Initial set up

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", 
             "viridis", "kableExtra","ggridges", "viridis", "ggdark", "ggplot2", "patchwork", "mice","qualvar",
             "oaxaca", "foreach"
)
fpackage.check(packages)

Goal

Create the descriptive statistics table and estimate the decomposition analysis.

Data preperation

NELLS and NSUM data import

Import the NSUM data and recreate the NSUM module.

#import NELLS file.
load(file = "data_analysis/data/data_processed/nells_data/2023-05-08_nells-nsum-prepped-data.rds")

Import the model estimates from the estimated NSUM models. We 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 and tauk 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")
}

Prepare data for analysis

Final data preperation for analysis

#extract results of NSUM 
nsum_estimates <- df_models_nsum_long %>% 
  filter(holdout == 10) 

#add nsum results to NELLS data
nells_df <- nsum_estimates %>% 
  left_join(nells_nsum)

#data prep
nells_df <- nells_df %>% 
  mutate(has_child = if_else(nr_children == "0", 0, 1),
         religious = if_else(religious_denom == "None", 0, 1),
         education_num = as.numeric(education_completed_highest),
         education_recoded_numeric = case_when(
           education_num == 1 ~ 1,
           education_num %in% c(2,13) ~ 2,
           education_num %in% c(3,4,14) ~ 3,
           education_num %in% c(5,6) ~ 4,
           education_num %in% c(7,8) ~ 5,
           education_num %in% c(9,15) ~ 6,
           education_num %in% c(10,11,12) ~ 7
         )
  )

#create inwoner coethnic
nells_df <- nells_df %>% 
  mutate(inwoner_coethnic_pc4 = case_when(
    str_detect(migration_background_fac, "kish") ~ per_TKY_mig_a_pc4,
    str_detect(migration_background_fac, "occan") ~ per_MOR_mig_a_pc4,
    migration_background_fac == "Dutch-Majority" ~ per_NL_mig_a_pc4,
    migration_background_fac == "Other" ~ per_MOR_mig_a_pc4 + per_TKY_mig_a_pc4
  ),
  inwoner_coethnic_pc4 = inwoner_coethnic_pc4*100,
  inwoner_coethnic_gem = case_when(
    str_detect(migration_background_fac, "kish") ~ per_TKY_mig_a_gem,
    str_detect(migration_background_fac, "occan") ~ per_MOR_mig_a_gem,
    migration_background_fac == "Dutch-Majority" ~ per_NL_mig_a_gem,
    migration_background_fac == "Other" ~ per_MOR_mig_a_gem + per_TKY_mig_a_gem
  ),
  inwoner_coethnic_gem = inwoner_coethnic_gem*100,
  per_NW_mig_a_gem = per_NW_mig_a_gem*100,
  per_NW_mig_a_pc4 = per_NW_mig_a_pc4*100
  )

#thermometer score outgroup
nells_df <- nells_df %>% 
   mutate(therm_outgroup_mean = case_when(
    str_detect(migration_background_fac, "kish") ~ (therm_dutch_maj + therm_mor)/2,
    str_detect(migration_background_fac, "occan") ~ (therm_dutch_maj + therm_tur)/2,
    migration_background_fac == "Dutch-Majority" ~ (therm_mor + therm_tur)/2,
    migration_background_fac == "Other" ~ (therm_dutch_maj + therm_tur + therm_mor)/3
  ),
  therm_outgroup_diff = case_when(
    str_detect(migration_background_fac, "kish") ~ ((therm_dutch_maj + therm_mor)/2) - therm_tur,
    str_detect(migration_background_fac, "occan") ~ ((therm_dutch_maj + therm_tur)/2) - therm_mor,
    migration_background_fac == "Dutch-Majority" ~ ((therm_mor + therm_tur)/2) - therm_dutch_maj,
    migration_background_fac == "Other" ~ (therm_dutch_maj + therm_tur + therm_mor)/3
  )) 

Prepare ethnic homogeneity measure.

nells_df <- nells_df %>%
  mutate(
    sum_dutch = knows_daan_boundary + knows_kevin_boundary + knows_emma_boundary + knows_linda_boundary + knows_albert_boundary + knows_edwin_boundary + knows_willemina_boundary + knows_ingrid_boundary,
    sum_turkish = knows_ibrahim_boundary + knows_esra_boundary,
    sum_moroccan = knows_mohammed_boundary + knows_fatima_boundary,
    sum_cat = knows_prison + knows_mbo + knows_secundary,
    +knows_hbo + knows_university + knows_unemployed + knows_secondhome,
    sum_total = sum_dutch + sum_turkish + sum_moroccan,
    per_dutch = (sum_dutch / sum_total) * 100,
    per_turkish = (sum_turkish / sum_total) * 100,
    per_moroccan = (sum_moroccan / sum_total) * 100
  )

#assign correct percentage co-ethnic to each group
nells_df <- nells_df %>% 
  mutate(per_ingroup = case_when(
    str_detect(migration_background_fac, "kish") ~ per_turkish,
    str_detect(migration_background_fac, "occan") ~ per_moroccan,
    migration_background_fac == "Dutch-Majority" ~ per_dutch,
    migration_background_fac == "Other" ~ per_dutch
  ))

#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 homogeneity measure based on naive NSUM method. First create the function.

#get the frequencies
frequencies <- read_csv("data_analysis/2022-08-26_namefrequencies.csv")

name_df <- nells_nsum %>% 
  select(id, contains("boundary")) %>% 
  select(-contains("prison"))

#nsum function
function_nsum <- function(dat, #data field of x with ID
                          popsize, #population size
                          freq) {#frequency vector
  #freq extract
  freq <- freq %>% 
    pull(number)
  
  #create df with ID
  dat_id <- dat %>%
    select(id)
  
  #create df without ID
  dat <- dat %>% select(-id)
  
  #extract names
  names_dat <- names(dat) %>%
    str_match(., "_(.*)_")
  
  #select correct list
  names_dat <- names_dat[, 2]
  
  
  #loop to apply naive function for all elements in the DF
  nsum_df <- foreach(a = 1:ncol(dat),
                     .combine = cbind) %do% {
                       dat %>%
                         select(.data[[names(dat)[a]]]) %>%
                         mutate(!!paste0(names_dat[a], "_predicted") := (.data[[names(dat)[a]]] /
                                                                           freq[a]) * popsize)
                     }
  #create NSUM predicted estimate (averaged over all individual scale ups)
  nsum_df <- nsum_df %>%
    bind_cols(dat_id) %>% #add ID
    rowwise() %>% #rowwise means
    mutate(ave_predicted = mean(x = c_across(cols = contains("predicted")),
                                na.rm = T)) %>%
    ungroup()
  
  return(nsum_df)
}

Apply function to NELLS data.

#Create naive scale up estimates with all names. 
name_all_df <- function_nsum(dat = name_df,
              popsize = 17407585,
              freq = frequencies) 

#rename all names and delete individual predictions
name_all_df <- name_all_df %>% 
  rename(all_pred = ave_predicted) %>% 
  rowwise() %>% 
  mutate(maj_pred = mean(x = c_across(cols = c(
    daan_predicted,
    kevin_predicted,
    edwin_predicted,
    albert_predicted,
    linda_predicted,
    emma_predicted,
    ingrid_predicted,
    willemina_predicted
  )),
  na.rm = T),
  min_pred = mean(x = c_across(cols = c(
    esra_predicted,
    mohammed_predicted,
    ibrahim_predicted,
    fatima_predicted,
  )),
  na.rm = T),
  ) %>% 
  ungroup()

#combine information
nells_df <- nells_df %>% 
  left_join(name_all_df, by = "id")

Delete outliers and filter out “Other” mig background

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(migration_background_fac != "Other")
#create standardized variables
nells_df <- nells_df %>% 
  mutate(sd_maj_pred = sd(maj_pred, na.rm = T),
         sd_min_pred = sd(min_pred, na.rm = T),
         z_maj_pred = (maj_pred - mean(maj_pred, na.rm = T))/sd_maj_pred,
         z_min_pred = (min_pred - mean(min_pred, na.rm = T))/sd_min_pred,
         z_value_ingroup = ifelse(migration_background_fac == "Dutch-Majority", z_maj_pred, z_min_pred),
         z_value_outgroup = ifelse(migration_background_fac == "Dutch-Majority", z_min_pred, z_maj_pred),
         z_distance_groups = z_value_outgroup - z_value_ingroup,
         z_distance_min_maj = z_min_pred - z_maj_pred) 

Missing data imputation

nells_df <- nells_df %>% 
  mutate(therm_diff_missing = ifelse(is.na(therm_outgroup_diff), 1, 0),
         therm_mean_missing = ifelse(is.na(therm_outgroup_mean), 1, 0),
         pc4_missing = ifelse(is.na(Inwoner_pc4), 1, 0))

imp <- nells_df %>% 
  select(migration_background_fac,
      age,
      gender,
      in_education,
      education_recoded_numeric,
      partner,
      partner_extended,
      has_child,
      paid_work,
      religious,
      religious_denom,
      rel_attendance,
      inwoner_coethnic_pc4,
      inwoner_coethnic_gem,
      therm_outgroup_mean,
      therm_outgroup_diff,
      therm_dutch_maj,
      therm_mor,
      therm_tur,
      starts_with("per"),
      woz_pc4,
      mean_woz_gem,
      Inwoner_gem,
      Inwoner_pc4,
      per_NW_mig_a_pc4) %>%  
  select(-per_ingroup, -per_ingroup_w) %>% 
  mice(method = "mean") %>% 
  complete()

imp <- nells_df %>%
  select(
    id,
    mean,
    per_ingroup,
    per_ingroup_w,
    therm_diff_missing,
    therm_mean_missing,
    pc4_missing,
    z_maj_pred,
    z_min_pred,
    z_value_ingroup,
    z_value_outgroup,
    z_distance_groups,
    z_distance_min_maj
  ) %>%
  bind_cols(imp)

Mean centering of continouos variables

imp <- imp %>% 
  mutate(education_recoded_numeric = education_recoded_numeric - mean(education_recoded_numeric, na.rm = T),
         age = age - mean(age, na.rm = T),
         woz_pc4 = woz_pc4 - mean(woz_pc4, na.rm = T),
         mean_woz_gem = mean_woz_gem - mean(mean_woz_gem, na.rm = T),
         Inwoner_gem = Inwoner_gem - mean(Inwoner_gem, na.rm = T),
         Inwoner_pc4 = Inwoner_pc4 - mean(Inwoner_pc4, na.rm = T),
         therm_outgroup_mean = therm_outgroup_mean - mean(therm_outgroup_mean, na.rm = T),
         therm_outgroup_diff = therm_outgroup_diff - mean(therm_outgroup_diff, na.rm = T),
         inwoner_coethnic_pc4 = inwoner_coethnic_pc4 - mean(inwoner_coethnic_pc4, na.rm = T),
         inwoner_coethnic_gem = inwoner_coethnic_gem - mean(inwoner_coethnic_gem, na.rm = T),
        per_NW_mig_a_pc4 = per_NW_mig_a_pc4 - mean(per_NW_mig_a_pc4, na.rm = T)
         )

Set correct labels of categorical variables.

#relabel the factor variables. 
imp <- imp %>%
  mutate(
    migration_background_fac = fct_relevel(migration_background_fac,
                                                "Dutch-Majority",
                                                "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")
    )
  )

#not all subgroups have complete cases for all the factor variables. Hence, the need to combine some categories. 
imp <- imp %>%
  mutate(
    rel_attendance_num = if_else(as.numeric(rel_attendance) > 3, 4, as.numeric(rel_attendance)),
    rel_fac_2 = factor(
      rel_attendance_num,
      levels = 1:4,
      labels = c("Never", "1-2 Year", "3-11 Year", "Monthly or more")
    ),
    partner = if_else(partner_extended == "Does not have a partner", 0, 1)
  )  

Descriptive statistics table

Desstats table function and table creation

prepare_desstats <- function(x, full.sample) {
  if (full.sample == T) {
    desstats <- x %>%
      mutate(
        ln_size = log(mean),
        Dutch = if_else(migration_background_fac == "Dutch Majority", 1, 0),
        `2nd_gen_Moroccan` = if_else(migration_background_fac == "2nd gen Moroccan-Dutch", 1, 0),
        `2nd_gen_Turkish` = if_else(migration_background_fac == "2nd gen Turkish-Dutch", 1, 0),
        `1st_gen_Turkish` = if_else(migration_background_fac == "1st gen Turkish-Dutch", 1, 0),
        `1st_gen_Moroccan` = if_else(migration_background_fac == "1st gen Moroccan-Dutch", 1, 0),
        age = as.numeric(age),
        female = if_else(gender == "Female", 1, 0),
        gender_other = if_else(gender == "Other", 1, 0),
        no_partner = if_else(partner_extended != "Does not have a partner", 1, 0),
        partner_seperate = if_else(partner_extended == "Has a partner, lives seperately", 1, 0),
        partner_together = if_else(partner_extended == "Lives together, unmarried", 1, 0),
        partner_married = if_else(partner_extended == "Married", 1, 0),
        rel_never = if_else(rel_attendance == "Never", 1, 0),
        rel_12_year = if_else(rel_attendance == "1-2 a year", 1, 0),
        rel_311_year = if_else(rel_attendance == "3-11 a year", 1, 0),
        rel_month = if_else(rel_attendance == "Once a month", 1, 0),
        rel_23_month = if_else(rel_attendance == "2-3 a month", 1, 0),
        rel_weekly = if_else(rel_attendance == "Every week", 1, 0),
        rel_mul_weekly = if_else(rel_attendance == "Multiple times a week", 1, 0),
        rel_month_more = if_else(rel_fac_2 == "Monthly or more", 1, 0)
      ) %>%
      rename(size = mean) %>%
      select(
        size,
        ln_size,
        per_ingroup_w,
        #per_ingroup,
        #ada_value,
        Dutch,
        `1st_gen_Turkish`,
        `2nd_gen_Turkish`,
        `1st_gen_Moroccan`,
        `2nd_gen_Moroccan`,
        age,
        female,
        education_recoded_numeric,
        no_partner,
        paid_work,
        in_education,
        rel_never,
        rel_12_year,
        rel_311_year,
        rel_month_more,
        therm_outgroup_diff,
        per_NW_mig_a_pc4,
        woz_pc4,
        Inwoner_pc4
      ) %>%
      psych::describe() %>% 
      round(., digits = 3)
  }
  else {
    desstats <- x %>%
      mutate(
        ln_size = log(mean),
        age = as.numeric(age),
        female = if_else(gender == "Female", 1, 0),
        gender_other = if_else(gender == "Other", 1, 0),
        no_partner = if_else(partner_extended != "Does not have a partner", 1, 0),
        partner_seperate = if_else(partner_extended == "Has a partner, lives seperately", 1, 0),
        partner_together = if_else(partner_extended == "Lives together, unmarried", 1, 0),
        partner_married = if_else(partner_extended == "Married", 1, 0),
        rel_never = if_else(rel_attendance == "Never", 1, 0),
        rel_12_year = if_else(rel_attendance == "1-2 a year", 1, 0),
        rel_311_year = if_else(rel_attendance == "3-11 a year", 1, 0),
        rel_month = if_else(rel_attendance == "Once a month", 1, 0),
        rel_23_month = if_else(rel_attendance == "2-3 a month", 1, 0),
        rel_weekly = if_else(rel_attendance == "Every week", 1, 0),
        rel_mul_weekly = if_else(rel_attendance == "Multiple times a week", 1, 0),
        rel_month_more = if_else(rel_fac_2 == "Monthly or more", 1, 0)
      ) %>%
      rename(size = mean) %>%
      select(
        size,
        ln_size,
        per_ingroup_w,
        #ada_value,
        age,
        female,
        education_recoded_numeric,
        no_partner,
        paid_work,
        in_education,
        rel_never,
        rel_12_year,
        rel_311_year,
        rel_month_more,
        therm_outgroup_diff,
        per_NW_mig_a_pc4,
        woz_pc4,
        Inwoner_pc4
      ) %>%
      psych::describe() %>% 
      round(., digits = 3)
  }
  
}

var_names_sample <- c(
  "Network size",
  "Network size (log)",
  "Ethnic homogeneity",
  "Age",
  "Gender [Female]",
  "Educational attainment",
  "Partner [Has a partner]",
  "Paid work",
  "Currently in education",
  "Religious attendance[Never]",
  "Religious attendance[1-2 year]",
  "Religious attendance[3-11 a year]",
  "Religious attendance[Once a month or more]",
  "Outgroup attitude",
  "Neighbourhood: % Non-western migrant",
  "Neighbourhood: mean property valuation",
  "Neighbourhood: # inhabitants"
)

var_names_full<- c(
  "Network size",
  "Network size (log)",
  "Ethnic homogeneity",
  "Group[Dutch majority]",
  "Group[1st gen Turkish-Dutch]",
  "Group[2nd gen Turkish-Dutch]",
  "Group[1st gen Moroccan-Dutch]",
  "Group[2nd gen Moroccan-Dutch]",
  "Age",
  "Gender [Female]",
  "Educational attainment",
  "Partner [Has a partner]",
  "Paid work",
  "Currently in education",
  "Religious attendance[Never]",
  "Religious attendance[1-2 year]",
  "Religious attendance[3-11 a year]",
  "Religious attendance[Once a month or more]",
  "Outgroup attitude",
  "Neighbourhood: % Non-western migrant",
  "Neighbourhood: mean property valuation",
  "Neighbourhood: # inhabitants"
)

desstats <- imp %>% 
  prepare_desstats(x = ., full.sample = T)

desstats_sample <- imp %>% 
  group_split(migration_background_fac) %>% 
  map(.x = ., .f = ~ prepare_desstats(x = .x, full.sample = F)) %>% 
  map(.x = ., .f = ~ dplyr::select(.data = .x, mean, sd))


#custom function to set rownames in pipe.
set_rownames <- function(df,names) {
row.names(df) <- names
return(df)
}

Descriptive statistics table full sample

desstats %>% 
  bind_cols(.name_repair = "minimal") %>% 
  select(mean, sd, median, min, max) %>% 
set_rownames(df = ., names = var_names_full) %>% 
    kbl(row.names = T) %>% 
  kable_classic()
mean sd median min max
Network size 943.463 639.821 778.346 48.220 3592.104
Network size (log) 6.633 0.674 6.657 3.876 8.186
Ethnic homogeneity 58.828 31.522 57.368 0.000 100.000
Group[Dutch majority] 0.599 0.490 1.000 0.000 1.000
Group[1st gen Turkish-Dutch] 0.128 0.335 0.000 0.000 1.000
Group[2nd gen Turkish-Dutch] 0.122 0.327 0.000 0.000 1.000
Group[1st gen Moroccan-Dutch] 0.066 0.249 0.000 0.000 1.000
Group[2nd gen Moroccan-Dutch] 0.084 0.277 0.000 0.000 1.000
Age 0.000 8.804 0.290 -15.710 23.290
Gender [Female] 0.540 0.499 1.000 0.000 1.000
Educational attainment 0.000 1.516 -0.189 -4.189 1.811
Partner [Has a partner] 0.655 0.476 1.000 0.000 1.000
Paid work 0.820 0.385 1.000 0.000 1.000
Currently in education 0.259 0.438 0.000 0.000 1.000
Religious attendance[Never] 0.602 0.490 1.000 0.000 1.000
Religious attendance[1-2 year] 0.170 0.376 0.000 0.000 1.000
Religious attendance[3-11 a year] 0.073 0.260 0.000 0.000 1.000
Religious attendance[Once a month or more] 0.155 0.362 0.000 0.000 1.000
Outgroup attitude 0.000 20.804 1.808 -88.192 92.808
Neighbourhood: % Non-western migrant 0.000 16.696 -5.692 -17.748 65.773
Neighbourhood: mean property valuation 0.000 97.381 -17.765 -157.765 910.235
Neighbourhood: # inhabitants 0.000 4788.646 -282.805 -9112.805 19347.195

Descriptive statistics by group

desstats_sample %>% 
  bind_cols(.name_repair = "minimal") %>%
  set_rownames(df = ., names = var_names_sample) %>% 
  kbl(row.names = T) %>% 
  kable_classic() %>%
  add_header_above(c(" " = 1,"Dutch" = 2, "1st gen Turkish" = 2, "2nd gen Turkish" = 2, "1st gen Moroccan" = 2, "2nd gen Moroccan" = 2)) %>% 
   footnote(general = "Size of the different groups ",
           number = c("Dutch: 658", "2nd gen Moroccan: 92",
                      "2nd gen Turkish: 134", "1st gen Turkish: 141",
                      "1st gen Moroccan: 73")) 
Dutch
1st gen Turkish
2nd gen Turkish
1st gen Moroccan
2nd gen Moroccan
mean sd mean sd mean sd mean sd mean sd
Network size 989.318 618.266 731.901 639.703 945.282 667.750 873.671 689.242 992.469 653.562
Network size (log) 6.711 0.623 6.282 0.795 6.639 0.651 6.491 0.767 6.716 0.603
Ethnic homogeneity 64.341 32.601 47.669 34.283 55.233 25.408 47.997 24.524 50.325 21.868
Age -0.572 8.742 4.907 6.931 -1.956 8.305 5.834 7.104 -5.210 8.238
Gender [Female] 0.538 0.499 0.489 0.502 0.619 0.487 0.466 0.502 0.576 0.497
Educational attainment 0.115 1.337 0.392 1.805 -0.234 1.440 -0.491 1.831 -0.689 1.732
Partner [Has a partner] 0.679 0.467 0.823 0.383 0.485 0.502 0.781 0.417 0.370 0.485
Paid work 0.877 0.329 0.709 0.456 0.716 0.452 0.726 0.449 0.804 0.399
Currently in education 0.257 0.437 0.149 0.357 0.313 0.466 0.123 0.331 0.467 0.502
Religious attendance[Never] 0.711 0.454 0.560 0.498 0.410 0.494 0.356 0.482 0.359 0.482
Religious attendance[1-2 year] 0.160 0.366 0.121 0.327 0.224 0.418 0.219 0.417 0.207 0.407
Religious attendance[3-11 a year] 0.038 0.191 0.113 0.318 0.119 0.325 0.096 0.296 0.174 0.381
Religious attendance[Once a month or more] 0.091 0.288 0.206 0.406 0.246 0.432 0.329 0.473 0.261 0.442
Outgroup attitude -1.590 22.075 4.993 22.287 -0.315 18.033 3.704 14.412 1.237 15.028
Neighbourhood: % Non-western migrant -6.437 10.871 8.574 17.408 9.419 19.864 10.843 21.265 10.577 18.839
Neighbourhood: mean property valuation 8.592 99.445 1.546 112.147 -22.556 82.258 -15.285 74.288 -18.841 86.491
Neighbourhood: # inhabitants -1022.266 4462.235 1484.925 4821.204 1563.426 4917.847 1619.798 4828.722 1473.173 4924.390
Note:
Size of the different groups
1 Dutch: 658
2 2nd gen Moroccan: 92
3 2nd gen Turkish: 134
4 1st gen Turkish: 141
5 1st gen Moroccan: 73

Inferential analysis

We now turn to testing group differences. Different methods are used. First we can check group differences with an OLS and dummies. Second, we can use an anova to check the differences. Third, we will use a decomposition analysis to explain group differences.

OLS model with dummy

size_group_model <- imp %>%  
  filter(gender != "Other") %>% 
  mutate(
  mean = as.integer(mean)
) %>%
  lm(
    log(mean) ~ migration_background_fac,
    data = .
  )
hom_group_model <- imp %>%
  filter(gender != "Other") %>%
  lm(
    per_ingroup_w ~ migration_background_fac,
    data = .
  )

#show table of OLS results
sjPlot::tab_model(size_group_model,
                  hom_group_model,
          pred.labels = c(
            "Constant",
            "Group[1st gen Turkish-Dutch]",
            "Group[2nd gen Turkish-Dutch]",
            "Group[1st gen Moroccan-Dutch]",
            "Group[2nd gen Moroccan-Dutch]"
            ),
          digits = 3,
          show.ci = F,
          show.stat = T,
          collapse.se  = F,
          col.order = c("est", "stat"),
          p.style = "scientific"
          #file = "reg.doc"
          )
  Dependent variable Dependent variable
Predictors Estimates Statistic Estimates Statistic
Constant 6.711 260.834 64.341 53.604
Group[1st gen Turkish-Dutch] -0.424 -6.908 -16.918 -5.904
Group[2nd gen Turkish-Dutch] -0.073 -1.162 -9.108 -3.121
Group[1st gen Moroccan-Dutch] -0.221 -2.713 -16.344 -4.303
Group[2nd gen Moroccan-Dutch] -0.000 -0.005 -13.951 -4.051
Observations 1096 1096
R2 / R2 adjusted 0.046 / 0.042 0.050 / 0.047

Anova

Size analysis. Complete groups.

# Compute the analysis of variance
res_aov_size <- aov(log(mean) ~ migration_background_simple_fac, data = imp)

# Summary of the analysis
results_size <- summary(res_aov_size)

#look at group differences
anova_diff_df_size  <- as_tibble(TukeyHSD(res_aov_size)$migration_background_simple_fac) %>% 
  mutate(Difference = row.names(TukeyHSD(res_aov_size)$migration_background_simple_fac)) %>% 
  select(5, 1:4) %>% 
  select(Difference,diff, `p adj`) %>% 
  rename(value = diff,
         p = `p adj`) %>% 
  mutate(variable = "ln(Size)")

# Compute the analysis of variance
res_aov_hom <- aov(per_ingroup_w ~ migration_background_simple_fac, data = imp)

# Summary of the analysis
results_hom <- summary(res_aov_hom)

#look at group differences
anova_diff_df_hom  <- as_tibble(TukeyHSD(res_aov_hom)$migration_background_simple_fac) %>% 
  mutate(Difference = row.names(TukeyHSD(res_aov_hom)$migration_background_simple_fac)) %>% 
  select(5, 1:4) %>% 
  select(Difference, diff, `p adj`) %>% 
  rename(value = diff,
         p = `p adj`) %>% 
  mutate(variable = "Homogeneity")

#add sig. indicator
anova_diff_df <- anova_diff_df_size %>% 
  bind_rows(anova_diff_df_hom) %>% 
  mutate(sig = ifelse(p < 0.05, 1, 0),
         sig_f = ifelse(sig == 1, "*", ""))


#create anova plot
anova_diff_simple_plot <- anova_diff_df %>% 
  mutate(diff_fac = fct_rev(factor(rep(1:3,2),
                           levels = 1:3,
                           labels = c("TKY - NED",
                                      "MOR - NED",
                                      "MOR - TKY")
                                      ))

         ) %>% 
  ggplot(aes(x = value, 
             y = diff_fac)) +
  geom_col(aes(fill = variable,
           colour = variable),
           alpha = 0.6) +
  geom_text(aes(label = sig_f),
            size = 6,
            hjust = 1) +
  facet_wrap(vars(variable),
             scales = "free_x") +
    theme_minimal() +
  scale_fill_viridis_d(option = "D") +
  scale_colour_viridis_d(option = "D") +
  theme(legend.position = "none",
        legend.title = element_blank(),
        axis.title.y = element_text(hjust = 1),
        axis.title.x = element_text(hjust = 1),
        text = element_text(colour = "black"),
        strip.text = element_text(colour = "black")) +
  labs(y = "",
       x = "",
       caption = "")

Migrant generations split.

# Compute the analysis of variance
res_aov_size <- aov(log(mean) ~ migration_background_fac, data = imp)

# Summary of the analysis
results_size <- summary(res_aov_size)

#look at group differences
anova_diff_df_size  <- as_tibble(TukeyHSD(res_aov_size)$migration_background_fac) %>% 
  mutate(Difference = row.names(TukeyHSD(res_aov_size)$migration_background_fac)) %>% 
  select(5, 1:4) %>% 
  select(Difference,diff, `p adj`) %>% 
  rename(value = diff,
         p = `p adj`) %>% 
  mutate(variable = "ln(Size)")

# Compute the analysis of variance
res_aov_hom <- aov(per_ingroup_w ~ migration_background_fac, data = imp)

# Summary of the analysis
results_hom <- summary(res_aov_hom)

#look at group differences
anova_diff_df_hom  <- as_tibble(TukeyHSD(res_aov_hom)$migration_background_fac) %>% 
  mutate(Difference = row.names(TukeyHSD(res_aov_hom)$migration_background_fac)) %>% 
  select(5, 1:4) %>% 
  select(Difference, diff, `p adj`) %>% 
  rename(value = diff,
         p = `p adj`) %>% 
  mutate(variable = "Homogeneity")

#add sig. indicator
anova_diff_df <- anova_diff_df_size %>% 
  bind_rows(anova_diff_df_hom) %>% 
  mutate(sig = ifelse(p < 0.05, 1, 0),
         sig_f = ifelse(sig == 1, "*", ""))

#create plot
anova_diff_extended_plot <- anova_diff_df %>% 
  mutate(diff_fac = factor(rep(1:10,2),
                           levels = 1:10,
                           labels = c("1st gen TKY - NED",
                                      "2nd gen TKY - NED",
                                      "1st gen MOR - NED",
                                      "2nd gen MOR - NED",
                                      "2nd gen TKY - 1st gen TKY",
                                      "1st gen MOR - 1st gen TKY",
                                      "2nd gen MOR - 1st gen TKY",
                                      "1st gen MOR - 2nd gen TKY",
                                      "2nd gen MOR - 2nd gen TKY",
                                      "2nd gen MOR - 1st gen MOR")

                                      ),
         diff_fac = fct_rev(fct_relevel(diff_fac,
                                "1st gen TKY - NED",
                                      "2nd gen TKY - NED",
                                      "1st gen MOR - NED",
                                      "2nd gen MOR - NED",
                                      "2nd gen TKY - 1st gen TKY",
                                      "2nd gen MOR - 1st gen MOR",
                                      "1st gen MOR - 1st gen TKY",
                                      "2nd gen MOR - 1st gen TKY",
                                      "1st gen MOR - 2nd gen TKY",
                                      "2nd gen MOR - 2nd gen TKY")

         )) %>% 
  filter(!diff_fac %in% c("1st gen MOR - 1st gen TKY",
                                      "2nd gen MOR - 1st gen TKY",
                                      "1st gen MOR - 2nd gen TKY",
                                      "2nd gen MOR - 2nd gen TKY")) %>% 
  ggplot(aes(x = value, 
             y = diff_fac)) +
  geom_col(aes(fill = variable,
           colour = variable),
           alpha = 0.6) +
  geom_text(aes(label = sig_f),
            size = 6,
            hjust = 1) +
  facet_wrap(vars(variable),
             scales = "free_x") +
    theme_minimal() +
  scale_fill_viridis_d(option = "D") +
  scale_colour_viridis_d(option = "D") +
  theme(legend.position = "none",
        legend.title = element_blank(),
        axis.title.y = element_text(hjust = 1),
        axis.title.x = element_text(hjust = 1),
        text = element_text(colour = "black"),
        strip.text = element_text(colour = "black")) +
  labs(y = "",
       x = "Coefficient")
#create combined plot
anova_plot <- anova_diff_simple_plot + 
anova_diff_extended_plot +
  plot_annotation(tag_levels ='a',
                  tag_prefix = '(',
                  tag_suffix = ')',
                  caption = "* p < 0.05") +
  plot_layout(ncol = 1,
              heights = c(1,3))

#show final plot
anova_plot

#save final anova plot
ggsave(anova_plot,
       file = "data_analysis/plots/results/anova_plot.jpg",
       width = 7,
       height = 5,
       dpi = 320)

Pooled regression model

Recreate the pooled regression model

#estimate size model
size_pooled_model <- imp %>%  
  filter(gender != "Other") %>% 
  mutate(
  mean = as.integer(mean)
) %>%
  lm(
    log(mean) ~ migration_background_fac +
        age +
        gender + 
        education_recoded_numeric +
        partner + 
        in_education +
        paid_work +
        rel_fac_2 +
        per_NW_mig_a_pc4 +
        woz_pc4 +
        Inwoner_pc4 +
        therm_outgroup_diff +
      therm_diff_missing,
    data = .
  )

#estiamte homogeneity model
hom_pooled_model <- imp %>%
  filter(gender != "Other") %>%
  lm(
    per_ingroup_w ~ migration_background_fac +
      age +
      gender +
      education_recoded_numeric +
      partner +
      in_education +
      paid_work +
      rel_fac_2 +
      per_NW_mig_a_pc4 +
      woz_pc4 +
      Inwoner_pc4 +
      therm_outgroup_diff +
      therm_diff_missing,
    data = .
  )

#create table
sjPlot::tab_model(size_pooled_model,
                  hom_pooled_model,
          pred.labels = c(
            "Constant",
            "Group[1st gen Turkish-Dutch]",
            "Group[2nd gen Turkish-Dutch]",
            "Group[1st gen Moroccan-Dutch]",
            "Group[2nd gen Moroccan-Dutch]",
            "Age",
            "Gender [Fenale]",
            "Educational attainment",
            "Partner[Has a partner]",
            "Paid work",
            "Currently in education",
            "Religious attendance[1-2 year]",
            "Religious attendance[3-11 a year]",
            "Religious attendance[Once a month or more]",
            "Neighborhood: % Non-western migrant",
            "Neighborhood: mean property valuation",
            "Neighborhood: # inhabitants",
            "Outgroup attitude",
            "Outgroup attitude missing"
            ),
          digits = 3,
          show.ci = F,
          show.stat = T,
          collapse.se  = F,
          col.order = c("est", "stat"),
          p.style = "stars"
          #file = "reg.doc"
          )
  Dependent variable Dependent variable
Predictors Estimates Statistic Estimates Statistic
Constant 6.514 *** 94.603 62.240 *** 19.189
Group[1st gen Turkish-Dutch] -0.375 *** -5.590 -15.014 *** -4.745
Group[2nd gen Turkish-Dutch] -0.091 -1.348 -8.994 ** -2.829
Group[1st gen Moroccan-Dutch] -0.225 * -2.561 -15.700 *** -3.799
Group[2nd gen Moroccan-Dutch] -0.075 -0.943 -13.496 *** -3.613
Age 0.000 0.100 0.034 0.231
Gender [Fenale] -0.048 -1.200 0.085 0.045
Educational attainment -0.018 -1.226 0.102 0.145
Partner[Has a partner] -0.010 -0.200 -1.170 -0.506
Paid work 0.168 ** 2.871 0.180 0.065
Currently in education 0.155 ** 2.879 0.661 0.260
Religious attendance[1-2 year] 0.152 ** 2.763 4.934 1.908
Religious attendance[3-11 a year] 0.129 1.623 0.191 0.051
Religious attendance[Once a month or more] 0.181 ** 3.027 5.670 * 2.012
Neighborhood: % Non-western migrant -0.000 -0.073 -0.085 -1.188
Neighborhood: mean property valuation -0.000 -0.513 0.000 0.025
Neighborhood: # inhabitants -0.000 -1.460 0.000 0.257
Outgroup attitude -0.001 -1.212 -0.188 *** -4.167
Outgroup attitude missing -0.015 -0.282 0.983 0.384
Observations 1096 1096
R2 / R2 adjusted 0.087 / 0.072 0.074 / 0.058
  • p<0.05   ** p<0.01   *** p<0.001

Decomposition analysis

Decomposition dataprep

Create separate df frames to use in the decomposition analyses.

#Dutch - TKY 1st gen
data_dutch_turkish_1st <- imp %>%
  filter(gender != "Other") %>% 
  filter(migration_background_fac %in% c("Dutch Majority", "1st gen Turkish-Dutch")) %>% 
  mutate(z = if_else(migration_background_fac == "Dutch Majority", 1, 0)
         ) 

#Dutch - TKY 2nd gen
data_dutch_turkish_2nd <- imp %>%
  filter(gender != "Other") %>% 
  filter(migration_background_fac %in% c("Dutch Majority", "2nd gen Turkish-Dutch")) %>% 
  mutate(z = if_else(migration_background_fac == "Dutch Majority", 1, 0)
         ) 

#Dutch - moroccan 2nd gen
data_dutch_moroccan_2nd <- imp %>%
  filter(gender != "Other") %>% 
  filter(migration_background_fac %in% c("Dutch Majority", "2nd gen Moroccan-Dutch")) %>% 
  mutate(z = if_else(migration_background_fac == "Dutch Majority", 1, 0)
         ) 

#Dutch - moroccan 1st gen
data_dutch_moroccan_1st <- imp %>%
  filter(gender != "Other") %>% 
  filter(migration_background_fac %in% c("Dutch Majority", "1st gen Moroccan-Dutch")) %>% 
  mutate(z = if_else(migration_background_fac == "Dutch Majority", 1, 0)
         ) 

#Turkish generation difference
data_turkish_diff <- imp %>%
  filter(gender != "Other") %>% 
  filter(migration_background_fac %in% c("1st gen Turkish-Dutch", "2nd gen Turkish-Dutch")) %>% 
  mutate(z = if_else(migration_background_fac == "2nd gen Turkish-Dutch", 1, 0)
         ) 

#Moroccan generation difference
data_moroccan_diff <- imp %>%
  filter(gender != "Other") %>% 
  filter(migration_background_fac %in% c("1st gen Moroccan-Dutch", "2nd gen Moroccan-Dutch")) %>% 
  mutate(z = if_else(migration_background_fac == "2nd gen Moroccan-Dutch", 1, 0)
         )

#Dutch turkish minority
data_dutch_turkish <- imp %>%
  filter(gender != "Other") %>% 
  filter(migration_background_fac %in% c("Dutch Majority", "1st gen Turkish-Dutch","2nd gen Turkish-Dutch")) %>% 
  mutate(z = if_else(migration_background_fac == "Dutch Majority", 1, 0)
         ) 

#Dutch moroccan minority
data_dutch_moroccan <- imp %>%
  filter(gender != "Other") %>% 
  filter(migration_background_fac %in% c("Dutch Majority", "1st gen Moroccan-Dutch","2nd gen Moroccan-Dutch")) %>% 
  mutate(z = if_else(migration_background_fac == "Dutch Majority", 1, 0)
         ) 

#combine elements in list
data_list <- list(data_dutch_turkish_1st,
                  data_dutch_turkish_2nd,
                  data_dutch_moroccan_2nd,
                  data_dutch_moroccan_1st,
                  data_turkish_diff,
                  data_moroccan_diff,
                  data_dutch_turkish,
                  data_dutch_moroccan)

Size ln

Decomposition estimation

#set seed
set.seed(2702)

#create the analysis function
oaxaca_spec_f <- function(x) {
  results <- x  %>%
  oaxaca(
    formula = log(mean) ~ age +
      gender +
      education_recoded_numeric +
      partner +
      in_education +
      paid_work +
      rel_fac_2 +
      per_NW_mig_a_pc4 +
      woz_pc4 +
      Inwoner_pc4 +
      therm_outgroup_diff | z,
  reg.fun = lm,
  data = .)
}

#create model list
oaxaca_model_list  <- map(.x = data_list, 
    .f = ~ oaxaca_spec_f(x = .x))


#create empty lists to store information in
predicted_list <- list()
two_fold_results_plot_list <- list()
two_fold_results_table_list <- list()
two_fold_variables_list <- list()


#select correct information from the model object and store in list
for(i in 1:length(oaxaca_model_list)) { #i = 8
  model_object <- oaxaca_model_list[[i]]
  
  #get the predicted network size of both groups
  predicted_list[[i]] <- tibble(y_a = model_object$y$y.A,
  y_b = model_object$y$y.B,
  y_diff = model_object$y$y.diff,
  model = i)
  
  #get the results of the twofold analysis for the plot
  two_fold_results_plot_list[[i]] <- model_object$twofold$overall %>% 
    as_tibble() %>% 
    filter(group.weight == 1) %>% 
    rename(coef_explained = `coef(explained)`,
           se_explained = `se(explained)`,
           coef_unexplained = `coef(unexplained)`,
           se_unexplained = `se(unexplained)`,
           coef_unexplained.a = `coef(unexplained A)`,
           se_unexplained.a = `se(unexplained A)`,
           coef_unexplained.b = `coef(unexplained B)`,
           se_unexplained.b = `se(unexplained B)`) %>% 
    select(-group.weight) %>% 
    select(1:8) %>% 
    pivot_longer(data = .,
                 cols = 1:8,
                 names_to = c("var", "name"),
                 values_to = "value",
                 names_sep = "_") %>% 
    mutate(model = i)
  
  #get the results of the twofold analysis for the table
  two_fold_results_table_list[[i]] <- model_object$twofold$overall %>% 
    as_tibble() %>% 
    filter(group.weight == -2) %>% 
    rename(coef_explained = `coef(explained)`,
           se_explained = `se(explained)`,
           coef_unexplained = `coef(unexplained)`,
           se_unexplained = `se(unexplained)`,
           coef_unexplained.a = `coef(unexplained A)`,
           se_unexplained.a = `se(unexplained A)`,
           coef_unexplained.b = `coef(unexplained B)`,
           se_unexplained.b = `se(unexplained B)`) %>% 
    select(-group.weight) %>% 
    select(1:8)
  
  #get the results of the twofold analysis for the variable plot
  two_fold_variables_list[[i]] <- model_object$twofold$variables[[6]] %>% 
    as_tibble() %>% 
    mutate(variables = row.names(model_object$twofold$variables[[6]])) %>% 
    filter(group.weight == -2) %>% 
    select(10,2:5) %>% 
    mutate(model = i)
}

Twofold decomposition results table

#extract twofold information
twofold_table <- two_fold_results_table_list %>% 
  bind_rows() %>% 
  filter(row_number()> 4) %>% 
  mutate(model = factor(1:4,
                        levels = 1:4,
                        labels = c(
                          "1st gen Turkish-Dutch -  2nd gen Turkish-Dutch",
                          "1st gen Moroccan-Dutch -  2nd gen Moroccan-Dutch",
                          "Turkish-Dutch -  Dutch-Majority",
                          "Moroccan-Dutch -  Dutch-Majority"
                        ))) %>% 
  select(9,1:4) %>% 
  mutate(z_explained = coef_explained/se_explained,
         z_unexplained = coef_unexplained/se_unexplained) %>% 
  select(model, coef_explained, z_explained, coef_unexplained, z_unexplained)

predicted_df <- predicted_list %>% 
  bind_rows() %>% 
  filter(model > 4) %>% 
  select(1:3)

#show results in table
twofold_table %>% 
  bind_cols(predicted_df) %>% 
  select(1,6:8, 2:5) %>% 
  kbl(digits = 3,
      align = 'l') %>% 
  kable_paper()
model y_a y_b y_diff coef_explained z_explained coef_unexplained z_unexplained
1st gen Turkish-Dutch - 2nd gen Turkish-Dutch 6.288 6.639 -0.351 -0.061 -1.045 -0.290 -3.240
1st gen Moroccan-Dutch - 2nd gen Moroccan-Dutch 6.491 6.711 -0.220 0.074 0.800 -0.294 -2.154
Turkish-Dutch - Dutch-Majority 6.459 6.711 -0.252 -0.025 -0.722 -0.227 -4.103
Moroccan-Dutch - Dutch-Majority 6.613 6.711 -0.098 0.007 0.167 -0.106 -1.760

Twofold panel plot

#create plot df
variables_plot_df <- two_fold_variables_list %>% 
  bind_rows() %>% 
  filter(model > 4) %>% 
  mutate(model = factor(model, 
                        levels = 5:8,
                        labels = c(
                          "Turkish-Dutch 1st gen - 2nd gen",
                          "Moroccan-Dutch 1st gen - 2nd gen",
                          "Turkish-Dutch -  Dutch-Majority",
                          "Moroccan-Dutch -  Dutch-Majority"
                        ))) %>% 
  rename(coef_explained = `coef(explained)`,
           se_explained = `se(explained)`,
           coef_unexplained = `coef(unexplained)`,
           se_unexplained = `se(unexplained)`) %>%
  pivot_longer(data = .,
                 cols = 2:5,
                 names_to = c("var", "name"),
                 values_to = "value",
                 names_sep = "_") %>% 
  pivot_wider(names_from = var,
              values_from = value) %>% 
  mutate(abs_z = abs(coef/se),
         sig = ifelse(abs_z > 1.95, 1, 0),
         sig_f = factor(sig,
                        levels = 0:1,
                        labels = c("", "*")))

#create vector to filter variables
indep_names <- c(
  "rel_fac_2Monthly or more",
  "rel_fac_23-11 Year",
  "rel_fac_21-2 Year",
  "paid_work",
  "in_education",
  "per_NW_mig_a_pc4",
  "Inwoner_pc4",
  "education_recoded_numeric",
  "therm_outgroup_diff",
  "age",
  "partner",
  "genderFemale",
  "woz_pc4")

#create plot
variables_decomp_size_plot <- variables_plot_df %>% #dataprep
  filter(variables %in% indep_names) %>%
  mutate(
    var_fac = case_when(
      variables == "paid_work" ~ 1,
      variables == "in_education" ~ 2,
      variables == "rel_fac_21-2 Year" ~ 3,
      variables == "rel_fac_23-11 Year" ~ 4,
      variables == "rel_fac_2Monthly or more" ~ 5,
      variables == "education_recoded_numeric" ~ 6,
      variables == "Inwoner_pc4" ~ 7,
      variables == "per_NW_mig_a_pc4" ~ 8,
      variables == "woz_pc4" ~ 9,
      variables == "therm_outgroup_diff" ~ 10,
      variables == "age" ~ 11,
      variables == "partner" ~ 12,
      variables == "genderFemale" ~ 13
    ),
    var_fac = factor(
      var_fac,
      levels = 1:13,
      labels = c(
        "Paid work",
        "Currently in education",
        "Religious attendance[1-2 year]",
        "Religious attendance[3-11 a year]",
        "Religious attendance[Once a month or more]",
        "Educational attainment",
        "Neighbourhood: # inhabitants",
        "Neighbourhood: mean property valuation",
        "Neighbourhood: % non-western migrant",
        "Outgroup attitudes",
        "Age",
        "Partner[no partner]",
        "Gender[Male]"
      )
    )
  ) %>% #plot
  ggplot(aes(x = coef, y = var_fac)) +
  geom_col(aes(colour = name,
             fill = name),
           alpha = 0.6) + 
  geom_errorbar(aes(xmin = coef - (se*1.96),
                    xmax = coef + (se*1.96))) +
  geom_vline(xintercept = 0) +
  geom_text(aes(label = sig_f),
            hjust = 2,
            size = 6) +
  facet_grid(cols = vars(model),
             rows = vars(name)) +
  theme_minimal() +
  scale_fill_viridis_d(option = "D") +
  scale_colour_viridis_d(option = "D") +
  theme(legend.position = "bottom",
        legend.title = element_blank(),
        axis.title.y = element_text(hjust = 1),
        axis.title.x = element_text(hjust = 1),
        text = element_text(colour = "black"),
        strip.text = element_text(colour = "black")) +
  labs(y = "Independent Variables",
       x = "Coefficient",
       caption = "* p < 0.05")

#save plot
ggsave(variables_decomp_size_plot,
        file = "data_analysis/plots/results/variables_decomp_size_plot.jpg",
       width = 12,
       height = 8,
       dpi = 320)

#show plot
variables_decomp_size_plot

Regression model results per group

All (sub)groups

#estimate model for different groups
size_pooled_model <- imp %>%
  filter(gender != "Other") %>%
   group_split(migration_background_fac) %>%
  map(
    .x = .,
    .f = ~ lm(
      log(mean) ~ age +
        gender + 
        education_recoded_numeric +
        partner + 
        in_education +
        paid_work +
        rel_fac_2 +
        per_NW_mig_a_pc4 +
        woz_pc4 +
        Inwoner_pc4 +
        therm_outgroup_diff,
      data = .x
    )
  )

#Show results in table
sjPlot::tab_model(size_pooled_model,
          pred.labels = c(
            "Constant",
           "Age",
            "Gender [Fenale]",
            "Educational attainment",
            "Partner[Has a partner]",
            "Paid work",
            "Currently in education",
            "Religious attendance[1-2 year]",
            "Religious attendance[3-11 a year]",
            "Religious attendance[Once a month or more]",
            "Outgroup attitude",
            "Neighborhood: % non-western migrant",
            "Neighborhood: mean property valuation",
            "Neighborhood: # inhabitants"
            ),
          dv.labels = c("Dutch", "1st gen Turkish", "2nd gen Turkish", "1st gen Moroccan","2nd gen Moroccan"),
          digits = 3,
          show.ci = F,
          show.stat = T,
          collapse.se  = F,
          col.order = c("est", "stat")
          #file = "reg.doc"
          )
  Dutch 1st gen Turkish 2nd gen Turkish 1st gen Moroccan 2nd gen Moroccan
Predictors Estimates Statistic Estimates Statistic Estimates Statistic Estimates Statistic Estimates Statistic
Constant 6.544 76.814 5.950 25.410 6.622 39.647 6.254 16.001 6.309 26.814
Age -0.002 -0.574 -0.010 -0.923 0.006 0.559 0.008 0.447 0.017 1.410
Gender [Fenale] -0.003 -0.070 -0.053 -0.397 -0.076 -0.607 -0.132 -0.628 -0.182 -1.275
Educational attainment -0.024 -1.147 0.024 0.530 -0.016 -0.344 -0.059 -0.927 -0.010 -0.203
Partner[Has a partner] 0.014 0.240 -0.076 -0.438 -0.177 -1.215 0.007 0.026 0.073 0.441
Paid work 0.205 2.850 0.114 0.506 0.031 0.197 0.130 0.330 0.314 1.835
Currently in education 0.033 0.436 0.256 1.691 0.206 1.560 0.246 0.923 0.419 2.398
Religious attendance[1-2 year] 0.233 3.513 0.399 1.764 -0.128 -0.776 -0.022 -0.080 0.057 0.322
Religious attendance[3-11 a year] 0.074 0.589 0.340 1.506 -0.153 -0.800 0.182 0.494 0.182 0.954
Religious attendance[Once a month or more] 0.047 0.556 0.515 2.541 0.221 1.391 0.094 0.344 0.131 0.743
Outgroup attitude -0.003 -1.432 0.002 0.535 -0.001 -0.225 0.003 0.435 -0.004 -0.896
Neighborhood: % non-western migrant 0.000 1.446 -0.001 -2.061 -0.000 -0.554 -0.001 -0.546 -0.001 -1.329
Neighborhood: mean property valuation -0.000 -0.965 0.000 0.974 -0.000 -0.465 -0.000 -1.488 0.000 0.693
Neighborhood: # inhabitants -0.003 -2.665 0.007 2.089 -0.002 -0.558 -0.000 -0.048 0.003 0.662
Observations 658 140 134 73 91
R2 / R2 adjusted 0.072 / 0.053 0.167 / 0.082 0.108 / 0.011 0.111 / -0.085 0.189 / 0.052

Only major groups.

results_list <- imp %>%
  filter(gender != "Other") %>% 
  group_split(migration_background_simple_fac) %>%
  map(
    .x = .,
    .f = ~ lm(
      log(mean) ~  age +
        gender + 
        education_recoded_numeric +
        therm_outgroup_diff +
        partner + 
        in_education +
        paid_work +
        rel_fac_2 +
        per_NW_mig_a_pc4 +
        woz_pc4 +
        Inwoner_pc4,
      data = .x
    )
  )

sjPlot::tab_model(results_list,
          pred.labels = c(
            "Constant",
            "Age",
            "Gender [Fenale]",
            "Educational attainment",
            "Partner[Has a partner]",
            "Paid work",
            "Currently in education",
            "Religious attendance[1-2 year]",
            "Religious attendance[3-11 a year]",
            "Religious attendance[Once a month or more]",
            "Outgroup attitude",
            "Neighborhood: % non-western migrant",
            "Neighborhood: mean property valuation",
            "Neighborhood: # inhabitants"
            ),
          dv.labels = c("Dutch","Turkish-Dutch", "Moroccan-Dutch"),
          digits = 3,
          show.ci = F,
          show.stat = T,
          collapse.se  = F,
          col.order = c("est", "stat")
          #file = "reg.doc"
          )
  Dutch Turkish-Dutch Moroccan-Dutch
Predictors Estimates Statistic Estimates Statistic Estimates Statistic
Constant 6.544 76.814 6.286 46.427 6.256 32.820
Age -0.002 -0.574 -0.007 -1.014 0.007 0.787
Gender [Fenale] -0.003 -0.070 -0.049 -0.547 -0.121 -1.037
Educational attainment -0.024 -1.147 -0.006 -0.183 -0.024 -0.682
Partner[Has a partner] -0.003 -2.665 0.002 0.895 0.001 0.268
Paid work 0.014 0.240 -0.128 -1.188 0.017 0.121
Currently in education 0.205 2.850 0.032 0.245 0.270 1.679
Religious attendance[1-2 year] 0.033 0.436 0.236 2.357 0.322 2.357
Religious attendance[3-11 a year] 0.233 3.513 0.084 0.623 0.018 0.119
Religious attendance[Once a month or more] 0.074 0.589 0.102 0.699 0.182 1.053
Outgroup attitude 0.047 0.556 0.325 2.593 0.093 0.633
Neighborhood: % non-western migrant -0.003 -1.432 0.000 0.093 0.000 0.002
Neighborhood: mean property valuation 0.000 1.446 -0.001 -2.335 -0.001 -1.559
Neighborhood: # inhabitants -0.000 -0.965 0.000 0.085 -0.000 -0.564
Observations 658 274 164
R2 / R2 adjusted 0.072 / 0.053 0.114 / 0.070 0.102 / 0.024

Ethnic homogeneity

Decomposition estimation

#set seed
set.seed(2702)

#create the analysis function
oaxaca_spec_f <- function(x) {
  results <- x  %>%
  oaxaca(
    formula = per_ingroup_w ~  age +
        gender + 
        education_recoded_numeric +
        therm_outgroup_diff +
        partner + 
        in_education +
        paid_work +
        rel_fac_2 +
        per_NW_mig_a_pc4 +
        woz_pc4 +
        Inwoner_pc4 | z ,
  reg.fun = lm,
  data = .)
}

#create model list
oaxaca_model_list_homogeneity  <- map(.x = data_list, 
    .f = ~ oaxaca_spec_f(x = .x))

predicted_list_hom <- list()
two_fold_results_plot_list_hom <- list()
two_fold_results_table_list_hom <- list()
two_fold_variables_list_hom <- list()

#select correct information from results
for(i in 1:length(oaxaca_model_list_homogeneity)) { #i = 8
  model_object <- oaxaca_model_list_homogeneity[[i]]
  
  predicted_list_hom[[i]] <- tibble(y_a = model_object$y$y.A,
  y_b = model_object$y$y.B,
  y_diff = model_object$y$y.diff,
  model = i)
  
  two_fold_results_plot_list_hom[[i]] <- model_object$twofold$overall %>% 
    as_tibble() %>% 
    filter(group.weight == -2) %>% 
    rename(coef_explained = `coef(explained)`,
           se_explained = `se(explained)`,
           coef_unexplained = `coef(unexplained)`,
           se_unexplained = `se(unexplained)`,
           coef_unexplained.a = `coef(unexplained A)`,
           se_unexplained.a = `se(unexplained A)`,
           coef_unexplained.b = `coef(unexplained B)`,
           se_unexplained.b = `se(unexplained B)`) %>% 
    select(-group.weight) %>% 
    select(1:8) %>% 
    pivot_longer(data = .,
                 cols = 1:8,
                 names_to = c("var", "name"),
                 values_to = "value",
                 names_sep = "_") %>% 
    mutate(model = i)
  
  two_fold_results_table_list_hom[[i]] <- model_object$twofold$overall %>% 
    as_tibble() %>% 
    filter(group.weight == -2) %>% 
    rename(coef_explained = `coef(explained)`,
           se_explained = `se(explained)`,
           coef_unexplained = `coef(unexplained)`,
           se_unexplained = `se(unexplained)`,
           coef_unexplained.a = `coef(unexplained A)`,
           se_unexplained.a = `se(unexplained A)`,
           coef_unexplained.b = `coef(unexplained B)`,
           se_unexplained.b = `se(unexplained B)`) %>% 
    select(-group.weight) %>% 
    select(1:8)
  
  
  two_fold_variables_list_hom[[i]] <- model_object$twofold$variables[[6]] %>% 
    as_tibble() %>% 
    mutate(variables = row.names(model_object$twofold$variables[[2]])) %>% 
    filter(group.weight == -2) %>% 
    select(10,2:5) %>% 
    mutate(model = i)
  
}

Decomposition results table

#extract twofold information
twofold_table_hom <- two_fold_results_table_list_hom %>% 
  bind_rows() %>% 
  filter(row_number()> 4) %>% 
  mutate(model = factor(1:4,
                        levels = 1:4,
                        labels = c(
                          "1st gen Turkish -  2nd gen Turkish",
                          "1st gen Moroccan -  2nd gen Moroccan",
                          "Turkish -  Dutch-Majority",
                          "Moroccan -  Dutch-Majority"
                        ))) %>% 
  select(9,1:4) %>% 
  mutate(z_explained = coef_explained/se_explained,
         z_unexplained = coef_unexplained/se_unexplained) %>% 
  select(model,coef_explained, z_explained, coef_unexplained, z_unexplained)


predicted_df_hom <- predicted_list_hom %>% 
  bind_rows() %>% 
  filter(model > 4) %>% 
  select(1:3)

#create resuls table
twofold_table_hom %>% 
  bind_cols(predicted_df_hom) %>% 
  select(1,6:8, 2:5) %>% 
    kbl(digits = 3,
      align = 'l') %>% 
  kable_paper()
model y_a y_b y_diff coef_explained z_explained coef_unexplained z_unexplained
1st gen Turkish - 2nd gen Turkish 47.423 55.233 -7.810 -2.507 -1.112 -5.304 -1.239
1st gen Moroccan - 2nd gen Moroccan 47.997 50.390 -2.393 1.993 0.654 -4.385 -0.973
Turkish - Dutch-Majority 51.243 64.341 -13.098 -2.570 -1.621 -10.528 -3.402
Moroccan - Dutch-Majority 49.325 64.341 -15.016 -4.782 -2.974 -10.234 -4.058

Decomposition results plot

#create plot df
variables_plot_df_hom <- two_fold_variables_list_hom %>% 
  bind_rows() %>% 
  filter(model > 4) %>% 
  mutate(model = factor(model, 
                        levels = 5:8,
                        labels = c(
                          "Turkish-Dutch 1st gen - 2nd gen",
                          "Moroccan-Dutch 1st gen - 2nd gen",
                          "Turkish-Dutch -  Dutch-Majority",
                          "Moroccan-Dutch -  Dutch-Majority"
                        ))) %>% 
  rename(coef_explained = `coef(explained)`,
           se_explained = `se(explained)`,
           coef_unexplained = `coef(unexplained)`,
           se_unexplained = `se(unexplained)`) %>%
  pivot_longer(data = .,
                 cols = 2:5,
                 names_to = c("var", "name"),
                 values_to = "value",
                 names_sep = "_") %>% 
  pivot_wider(names_from = var,
              values_from = value) %>% 
  mutate(abs_z = abs(coef/se),
         sig = ifelse(abs_z > 1.95, 1, 0),
         sig_f = factor(sig,
                        levels = 0:1,
                        labels = c("", "*")))

#create selection variable
indep_names <- c(
  "rel_fac_2Monthly or more",
  "rel_fac_23-11 Year",
  "rel_fac_21-2 Year",
  "paid_work",
  "in_education",
  "per_NW_mig_a_pc4",
  "Inwoner_pc4",
  "education_recoded_numeric",
  "therm_outgroup_diff",
  "age",
  "partner",
  "genderFemale",
  "woz_pc4")

#create decomposition homogeneity plot
variables_decomp_hom_plot <- variables_plot_df_hom %>%
  filter(variables %in% indep_names) %>%
  mutate(
    var_fac = case_when(
      variables == "paid_work" ~ 1,
      variables == "in_education" ~ 2,
      variables == "rel_fac_21-2 Year" ~ 3,
      variables == "rel_fac_23-11 Year" ~ 4,
      variables == "rel_fac_2Monthly or more" ~ 5,
      variables == "education_recoded_numeric" ~ 6,
      variables == "Inwoner_pc4" ~ 7,
      variables == "per_NW_mig_a_pc4" ~ 8,
      variables == "woz_pc4" ~ 9,
      variables == "therm_outgroup_diff" ~ 10,
      variables == "age" ~ 11,
      variables == "partner" ~ 12,
      variables == "genderFemale" ~ 13
    ),
    var_fac = factor(
      var_fac,
      levels = 1:13,
      labels = c(
        "Paid work",
        "Currently in education",
        "Religious attendance[1-2 year]",
        "Religious attendance[3-11 a year]",
        "Religious attendance[Once a month or more]",
        "Educational attainment",
        "Neighbourhood: # inhabitants",
        "Neighbourhood: % non-western migrant",
        "Neighbourhood: mean property valuation",
        "Outgroup attitudes",
        "Age",
        "Partner[no partner]",
        "Gender[Male]"
      )
    )
  ) %>% 
  ggplot(aes(x = coef, y = var_fac)) +
  geom_col(aes(colour = name,
             fill = name),
           alpha = 0.6) + 
  geom_errorbar(aes(xmin = coef - (se*1.96),
                    xmax = coef + (se*1.96))) +
  facet_grid(cols = vars(model),
             rows = vars(name)) +
  geom_vline(xintercept = 0) +
  geom_text(aes(label = sig_f),
            hjust = 2,
            size = 6) +
  theme_minimal() +
  scale_fill_viridis_d(option = "D") +
  scale_colour_viridis_d(option = "D") +
  theme(legend.position = "bottom",
        #plot.background = element_rect(fill = '#404040', colour = '#404040'),
        #panel.background = element_rect(fill = '#404040', colour = '#404040'),
        axis.title.y = element_text(hjust = 1),
        axis.title.x = element_text(hjust = 1),
        text = element_text(colour = "black"),
        strip.text = element_text(colour = "black"),
        legend.title = element_blank()) +
  labs(y = "Independent Variables",
       x = "Coefficient",
       caption = "* p < 0.05")

#save plot
  ggsave(variables_decomp_hom_plot,
        file = "data_analysis/plots/results/variables_decomp_hom_plot.jpg",
       width = 12,
       height = 8,
       dpi = 320)

  #show plot
variables_decomp_hom_plot

Regression model results per group

All (sub)groups

#create list with regression by migration group
results_list <- imp %>%
  filter(gender != "Other") %>% 
  group_split(migration_background_fac) %>%
  map(
    .x = .,
    .f = ~ lm(
      per_ingroup_w ~  age +
        gender + 
        education_recoded_numeric +
        partner + 
        in_education +
        paid_work +
        rel_fac_2 +
        therm_outgroup_diff +
        per_NW_mig_a_pc4 +
        woz_pc4 +
        Inwoner_pc4,
      data = .x
    )
  )

#show table with results
sjPlot::tab_model(results_list,
          pred.labels = c(
            "Constant",
            "Age",
            "Gender [Fenale]",
            "Educational attainment",
            "Partner[Has a partner]",
            "Paid work",
            "Currently in education",
            "Religious attendance[1-2 year]",
            "Religious attendance[3-11 a year]",
            "Religious attendance[Once a month or more]",
            "Outgroup attitude",
            "Neighborhood: % non-western migrant",
            "Neighborhood: mean property valuation",
            "Neighborhood: # inhabitants"
            ),
          dv.labels = c("Dutch","1st gen Turkish", "2nd gen Turkish", "1st gen Moroccan", "2nd gen Moroccan"),
          digits = 3,
          show.ci = F,
          show.stat = T,
          collapse.se  = F,
          col.order = c("est", "stat")
          #file = "reg.doc"
          )
  Dutch 1st gen Turkish 2nd gen Turkish 1st gen Moroccan 2nd gen Moroccan
Predictors Estimates Statistic Estimates Statistic Estimates Statistic Estimates Statistic Estimates Statistic
Constant 58.544 13.007 43.347 4.098 48.772 7.732 59.849 4.912 37.304 4.394
Age -0.251 -1.301 0.425 0.835 0.108 0.287 0.645 1.175 0.500 1.143
Gender [Fenale] -0.663 -0.258 -0.958 -0.159 1.840 0.387 -2.541 -0.388 14.452 2.799
Educational attainment 2.308 2.069 -0.368 -0.182 -3.198 -1.857 0.179 0.090 0.631 0.357
Partner[Has a partner] -1.168 -0.372 -0.608 -0.077 -3.592 -0.653 -14.754 -1.778 -3.992 -0.673
Paid work -0.198 -0.052 6.658 0.657 -3.138 -0.522 -8.770 -0.714 4.279 0.692
Currently in education 3.530 0.893 -3.897 -0.570 0.008 0.002 -6.621 -0.798 5.834 0.926
Religious attendance[1-2 year] 2.352 0.671 16.399 1.606 1.246 0.201 7.031 0.820 9.305 1.447
Religious attendance[3-11 a year] -5.375 -0.811 -2.216 -0.217 13.634 1.892 5.392 0.468 -1.516 -0.220
Religious attendance[Once a month or more] -0.646 -0.146 15.779 1.722 14.742 2.459 5.172 0.608 0.914 0.144
Outgroup attitude -0.192 -3.349 0.029 0.204 -0.215 -1.781 -0.387 -1.610 0.005 0.034
Neighborhood: % non-western migrant -0.472 -3.689 -0.074 -0.355 0.059 0.431 0.164 0.863 0.201 1.384
Neighborhood: mean property valuation 0.006 0.450 -0.032 -1.014 -0.007 -0.230 0.038 0.857 0.047 1.435
Neighborhood: # inhabitants 0.000 0.034 0.000 0.372 0.001 1.485 -0.000 -0.372 -0.001 -0.861
Observations 658 140 134 73 91
R2 / R2 adjusted 0.054 / 0.034 0.087 / -0.007 0.164 / 0.074 0.156 / -0.030 0.203 / 0.068

All major groups.

#list withr results of each group
results_list <- imp %>%
  filter(gender != "Other") %>% 
  group_split(migration_background_simple_fac) %>%
  map(
    .x = .,
    .f = ~ lm(
      per_ingroup_w ~  age +
        gender + 
        education_recoded_numeric +
        partner + 
        in_education +
        paid_work +
        rel_fac_2 +
        therm_outgroup_diff +
        per_NW_mig_a_pc4 +
        woz_pc4 +
        Inwoner_pc4,
      data = .x
    )
  )

#show results in a table
sjPlot::tab_model(results_list,
          pred.labels = c(
            "Constant",
            "Age",
            "Gender [Fenale]",
            "Educational attainment",
            "Partner[Has a partner]",
            "Paid work",
            "Currently in education",
            "Religious attendance[1-2 year]",
            "Religious attendance[3-11 a year]",
            "Religious attendance[Once a month or more]",
            "Outgroup attitude",
            "Neighborhood: % co-ethnic",
            "Neighborhood: mean property valuation",
            "Neighborhood: # inhabitants",
            "Therm missing"
            ),
          dv.labels = c("Dutch","Turkish-Dutch", "Moroccan-Dutch"),
          digits = 3,
          show.ci = F,
          show.stat = T,
          collapse.se  = F,
          col.order = c("est", "stat")
          #file = "reg.doc"
          )
  Dutch Turkish-Dutch Moroccan-Dutch
Predictors Estimates Statistic Estimates Statistic Estimates Statistic
(Intercept) 58.544 13.007 48.506 8.663 45.919 7.176
age -0.251 -1.301 0.073 0.252 0.453 1.608
genderFemale -0.663 -0.258 -0.103 -0.028 7.324 1.867
education_recoded_numeric 2.308 2.069 -0.913 -0.722 0.174 0.145
partner -1.168 -0.372 -2.559 -0.574 -7.029 -1.509
in_education -0.198 -0.052 1.017 0.186 2.206 0.409
paid_work 3.530 0.893 -2.846 -0.686 0.164 0.036
rel_fac_21-2 Year 2.352 0.671 9.702 1.747 6.540 1.312
rel_fac_23-11 Year -5.375 -0.811 6.451 1.065 -0.482 -0.083
rel_fac_2Monthly or more -0.646 -0.146 16.219 3.124 1.782 0.360
therm_outgroup_diff -0.192 -3.349 -0.080 -0.866 -0.210 -1.658
per_NW_mig_a_pc4 -0.472 -3.689 -0.078 -0.662 0.205 1.826
woz_pc4 0.006 0.450 -0.029 -1.398 0.034 1.374
Inwoner_pc4 0.000 0.034 0.001 1.131 -0.000 -0.267
Observations 658 274 164
R2 / R2 adjusted 0.054 / 0.034 0.088 / 0.042 0.103 / 0.026
LS0tDQp0aXRsZTogIkluZmVyZW50aWFsIGFuYWx5c2lzOiBCbGluZGVyLU9heGFjYSBkZWNvbXBvc2l0aW9uIg0KYXV0aG9yOiAiVGhpam1lbiBKZXJvZW5zZSINCmRhdGU6ICJMYXN0IGNvbXBpbGVkIG9uIGByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJUIsICVZJylgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogVFJVRQ0KICAgIHRvY19kZXB0aDogMw0KICAgIHRvY19mbG9hdDogVFJVRQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChjYWNoZSA9IFRSVUUsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCByZXN1bHRzID0gImFzaXMiLA0KICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiKQ0KYGBgDQoNCg0KIyBJbml0aWFsIHNldCB1cA0KDQpgYGB7ciBsaWJyYXJpZXMgYW5kIGZpbGVzLCByZXN1bHRzID0gJ2hpZGUnfQ0KZnBhY2thZ2UuY2hlY2sgPC0gZnVuY3Rpb24ocGFja2FnZXMpIHsgIyAoYykgSm9jaGVtIFRvbHNtYQ0KICBsYXBwbHkocGFja2FnZXMsIEZVTiA9IGZ1bmN0aW9uKHgpIHsNCiAgICBpZiAoIXJlcXVpcmUoeCwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkgew0KICAgICAgaW5zdGFsbC5wYWNrYWdlcyh4LCBkZXBlbmRlbmNpZXMgPSBUUlVFKQ0KICAgICAgbGlicmFyeSh4LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpDQogICAgfQ0KICB9KQ0KfQ0KcGFja2FnZXMgPSBjKCJ0aWR5dmVyc2UiLCANCiAgICAgICAgICAgICAidmlyaWRpcyIsICJrYWJsZUV4dHJhIiwiZ2dyaWRnZXMiLCAidmlyaWRpcyIsICJnZ2RhcmsiLCAiZ2dwbG90MiIsICJwYXRjaHdvcmsiLCAibWljZSIsInF1YWx2YXIiLA0KICAgICAgICAgICAgICJvYXhhY2EiLCAiZm9yZWFjaCINCikNCmZwYWNrYWdlLmNoZWNrKHBhY2thZ2VzKQ0KYGBgDQoNCg0KIyBHb2FsDQpDcmVhdGUgdGhlIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3MgdGFibGUgYW5kIGVzdGltYXRlIHRoZSBkZWNvbXBvc2l0aW9uIGFuYWx5c2lzLg0KDQojIERhdGEgcHJlcGVyYXRpb24NCg0KIyMgTkVMTFMgYW5kIE5TVU0gZGF0YSBpbXBvcnQNCg0KSW1wb3J0IHRoZSBOU1VNIGRhdGEgYW5kIHJlY3JlYXRlIHRoZSBOU1VNIG1vZHVsZS4gDQoNCmBgYHtyIGZpbGVzfQ0KI2ltcG9ydCBORUxMUyBmaWxlLg0KbG9hZChmaWxlID0gImRhdGFfYW5hbHlzaXMvZGF0YS9kYXRhX3Byb2Nlc3NlZC9uZWxsc19kYXRhLzIwMjMtMDUtMDhfbmVsbHMtbnN1bS1wcmVwcGVkLWRhdGEucmRzIikNCg0KYGBgDQoNCkltcG9ydCB0aGUgbW9kZWwgZXN0aW1hdGVzIGZyb20gdGhlIGVzdGltYXRlZCBOU1VNIG1vZGVscy4gV2UgaGF2ZSBjaG9zZW4gdGhlIG1vZGVsIHdoaWNoIHVzZXMgSWJyYWhpbSBmb3IgdGhlIGV0aG5pYyBuYW1lcy4gDQoNCmBgYHtyIGltcG9ydCByZXN1bHRzfQ0KDQppZiAoZmlsZS5leGlzdHMoDQogICJkYXRhX2FuYWx5c2lzL3Jlc3VsdHMvbnN1bV9vdXRwdXQvbWFpbi9jb21iaW5lZF9kYXRhL2RmX21vZGVsc19uc3VtX2xvbmcucmRzIg0KKSkgew0KICBsb2FkKGZpbGUgPSAiZGF0YV9hbmFseXNpcy9yZXN1bHRzL25zdW1fb3V0cHV0L21haW4vY29tYmluZWRfZGF0YS9kZl9tb2RlbHNfbnN1bV9sb25nLnJkcyIpDQp9IGVsc2Ugew0KICBsaXN0X2ZpbGVzIDwtDQogICAgYXMubGlzdCgNCiAgICAgIGRpcigNCiAgICAgICAgImRhdGFfYW5hbHlzaXMvcmVzdWx0cy9uc3VtX291dHB1dC9tYWluL21vZGVsLyIsDQogICAgICAgIGZ1bGwubmFtZXMgPSBUDQogICAgICApDQogICAgKQ0KICAjY3JlYXRlIGxvb3AgbGlzdHMNCiAga2RzIDwtIGxpc3QoKQ0KICBrZHNzZCA8LSBsaXN0KCkNCiAgZGF0YSA8LSBsaXN0KCkNCiAgbGlzdF9kZiA8LSBsaXN0KCkNCiAgDQogICNsb29wIHRvIGV4dHJhY3QgaW5mb3JtYXRpb24NCiAgZm9yIChpIGluIDE6bGVuZ3RoKGxpc3RfZmlsZXMpKSB7DQogICAgI2kgPSAxDQogICAgcHJpbnQocGFzdGUwKCJOdW1iZXIgIiwgaSwgIiBvZiAiLCBsZW5ndGgobGlzdF9maWxlcykpKQ0KICAgIGxvYWQobGlzdF9maWxlc1tbaV1dKQ0KICAgIGtkc1tbaV1dIDwtDQogICAgICByb3dNZWFucyhkZWdyZWUkZC52YWx1ZXMsIG5hLnJtID0gVFJVRSkgIyBjYWxjdWxhdGUgcm93bWVhbiBvZiBuZXRzaXplIGl0ZXJhdGlvbnM6IHNvIHRoZSByZXRhaW5lZCBjaGFpbnMNCiAgICBrZHNzZFtbaV1dIDwtDQogICAgICBtYXRyaXhTdGF0czo6cm93U2RzKGRlZ3JlZSRkLnZhbHVlcykgIyBjYWxjdWxhdGUgc2Qgb2YgNGsgZXN0aW1hdGVzIHBlciByb3c6IHNkIGZvciB0aG9zZSB2YWx1ZXMNCiAgICBkYXRhW1tpXV0gPC0gY2JpbmQoa2RzW1tpXV0sIGtkc3NkW1tpXV0pICMgY29tYmluZSB0aGVtDQogICAgbGlzdF9kZltbaV1dIDwtDQogICAgICBjYmluZChhc190aWJibGUoZGF0YVtbaV1dKSwgbmVsbHNfbnN1bSRpZCkgIyBhZGQgTkVMTFMgaWQgdmFyaWFibGUNCiAgICBzdHJpbmdzIDwtDQogICAgICBzdHJfc3BsaXQoc3RyX2V4dHJhY3QobGlzdF9maWxlc1tbaV1dWzFdLCBwYXR0ZXJuID0gImVzdGltYXRlcy4rIiksDQogICAgICAgICAgICAgICAgcGF0dGVybiA9ICJfIikgICMgYWRkIGhvbGRvdXQgYW5kIHRhdWsgbnVtYmVyDQogICAgbGlzdF9kZltbaV1dIDwtIGxpc3RfZGZbW2ldXSAlPiUNCiAgICAgIG11dGF0ZSgNCiAgICAgICAgaG9sZG91dCA9IGFzLm51bWVyaWMoc3RyX2V4dHJhY3Qoc3RyaW5nc1tbMV1dWzJdLCBwYXR0ZXJuID0gIltbOmRpZ2l0Ol1dezEsfSIpKSkNCiAgfQ0KICAgICNjb21iaW5lIHJlc3VsdHMgYW5kIHNhdmUNCiAgICBkZl9tb2RlbHNfbnN1bV9sb25nIDwtIGxpc3RfZGYgJT4lDQogICAgICBiaW5kX3Jvd3MoKSAlPiUNCiAgICAgIHJlbmFtZShtZWFuID0gVjEsDQogICAgICAgICAgICAgc2QgPSBWMiwNCiAgICAgICAgICAgICBpZCA9IDMpDQogICAgI3NhdmUgaW1hZ2UNCiAgICBzYXZlKGRmX21vZGVsc19uc3VtX2xvbmcsIGZpbGUgPSAiZGF0YV9hbmFseXNpcy9yZXN1bHRzL25zdW1fb3V0cHV0L21haW4vY29tYmluZWRfZGF0YS9kZl9tb2RlbHNfbnN1bV9sb25nLnJkcyIpDQp9DQpgYGANCg0KDQojIyBQcmVwYXJlIGRhdGEgZm9yIGFuYWx5c2lzDQoNCkZpbmFsIGRhdGEgcHJlcGVyYXRpb24gZm9yIGFuYWx5c2lzDQoNCmBgYHtyIGhvbGRvdXQgMTB9DQoNCiNleHRyYWN0IHJlc3VsdHMgb2YgTlNVTSANCm5zdW1fZXN0aW1hdGVzIDwtIGRmX21vZGVsc19uc3VtX2xvbmcgJT4lIA0KICBmaWx0ZXIoaG9sZG91dCA9PSAxMCkgDQoNCiNhZGQgbnN1bSByZXN1bHRzIHRvIE5FTExTIGRhdGENCm5lbGxzX2RmIDwtIG5zdW1fZXN0aW1hdGVzICU+JSANCiAgbGVmdF9qb2luKG5lbGxzX25zdW0pDQoNCiNkYXRhIHByZXANCm5lbGxzX2RmIDwtIG5lbGxzX2RmICU+JSANCiAgbXV0YXRlKGhhc19jaGlsZCA9IGlmX2Vsc2UobnJfY2hpbGRyZW4gPT0gIjAiLCAwLCAxKSwNCiAgICAgICAgIHJlbGlnaW91cyA9IGlmX2Vsc2UocmVsaWdpb3VzX2Rlbm9tID09ICJOb25lIiwgMCwgMSksDQogICAgICAgICBlZHVjYXRpb25fbnVtID0gYXMubnVtZXJpYyhlZHVjYXRpb25fY29tcGxldGVkX2hpZ2hlc3QpLA0KICAgICAgICAgZWR1Y2F0aW9uX3JlY29kZWRfbnVtZXJpYyA9IGNhc2Vfd2hlbigNCiAgICAgICAgICAgZWR1Y2F0aW9uX251bSA9PSAxIH4gMSwNCiAgICAgICAgICAgZWR1Y2F0aW9uX251bSAlaW4lIGMoMiwxMykgfiAyLA0KICAgICAgICAgICBlZHVjYXRpb25fbnVtICVpbiUgYygzLDQsMTQpIH4gMywNCiAgICAgICAgICAgZWR1Y2F0aW9uX251bSAlaW4lIGMoNSw2KSB+IDQsDQogICAgICAgICAgIGVkdWNhdGlvbl9udW0gJWluJSBjKDcsOCkgfiA1LA0KICAgICAgICAgICBlZHVjYXRpb25fbnVtICVpbiUgYyg5LDE1KSB+IDYsDQogICAgICAgICAgIGVkdWNhdGlvbl9udW0gJWluJSBjKDEwLDExLDEyKSB+IDcNCiAgICAgICAgICkNCiAgKQ0KDQojY3JlYXRlIGlud29uZXIgY29ldGhuaWMNCm5lbGxzX2RmIDwtIG5lbGxzX2RmICU+JSANCiAgbXV0YXRlKGlud29uZXJfY29ldGhuaWNfcGM0ID0gY2FzZV93aGVuKA0KICAgIHN0cl9kZXRlY3QobWlncmF0aW9uX2JhY2tncm91bmRfZmFjLCAia2lzaCIpIH4gcGVyX1RLWV9taWdfYV9wYzQsDQogICAgc3RyX2RldGVjdChtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMsICJvY2NhbiIpIH4gcGVyX01PUl9taWdfYV9wYzQsDQogICAgbWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICJEdXRjaC1NYWpvcml0eSIgfiBwZXJfTkxfbWlnX2FfcGM0LA0KICAgIG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyA9PSAiT3RoZXIiIH4gcGVyX01PUl9taWdfYV9wYzQgKyBwZXJfVEtZX21pZ19hX3BjNA0KICApLA0KICBpbndvbmVyX2NvZXRobmljX3BjNCA9IGlud29uZXJfY29ldGhuaWNfcGM0KjEwMCwNCiAgaW53b25lcl9jb2V0aG5pY19nZW0gPSBjYXNlX3doZW4oDQogICAgc3RyX2RldGVjdChtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMsICJraXNoIikgfiBwZXJfVEtZX21pZ19hX2dlbSwNCiAgICBzdHJfZGV0ZWN0KG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYywgIm9jY2FuIikgfiBwZXJfTU9SX21pZ19hX2dlbSwNCiAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIkR1dGNoLU1ham9yaXR5IiB+IHBlcl9OTF9taWdfYV9nZW0sDQogICAgbWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICJPdGhlciIgfiBwZXJfTU9SX21pZ19hX2dlbSArIHBlcl9US1lfbWlnX2FfZ2VtDQogICksDQogIGlud29uZXJfY29ldGhuaWNfZ2VtID0gaW53b25lcl9jb2V0aG5pY19nZW0qMTAwLA0KICBwZXJfTldfbWlnX2FfZ2VtID0gcGVyX05XX21pZ19hX2dlbSoxMDAsDQogIHBlcl9OV19taWdfYV9wYzQgPSBwZXJfTldfbWlnX2FfcGM0KjEwMA0KICApDQoNCiN0aGVybW9tZXRlciBzY29yZSBvdXRncm91cA0KbmVsbHNfZGYgPC0gbmVsbHNfZGYgJT4lIA0KICAgbXV0YXRlKHRoZXJtX291dGdyb3VwX21lYW4gPSBjYXNlX3doZW4oDQogICAgc3RyX2RldGVjdChtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMsICJraXNoIikgfiAodGhlcm1fZHV0Y2hfbWFqICsgdGhlcm1fbW9yKS8yLA0KICAgIHN0cl9kZXRlY3QobWlncmF0aW9uX2JhY2tncm91bmRfZmFjLCAib2NjYW4iKSB+ICh0aGVybV9kdXRjaF9tYWogKyB0aGVybV90dXIpLzIsDQogICAgbWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICJEdXRjaC1NYWpvcml0eSIgfiAodGhlcm1fbW9yICsgdGhlcm1fdHVyKS8yLA0KICAgIG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyA9PSAiT3RoZXIiIH4gKHRoZXJtX2R1dGNoX21haiArIHRoZXJtX3R1ciArIHRoZXJtX21vcikvMw0KICApLA0KICB0aGVybV9vdXRncm91cF9kaWZmID0gY2FzZV93aGVuKA0KICAgIHN0cl9kZXRlY3QobWlncmF0aW9uX2JhY2tncm91bmRfZmFjLCAia2lzaCIpIH4gKCh0aGVybV9kdXRjaF9tYWogKyB0aGVybV9tb3IpLzIpIC0gdGhlcm1fdHVyLA0KICAgIHN0cl9kZXRlY3QobWlncmF0aW9uX2JhY2tncm91bmRfZmFjLCAib2NjYW4iKSB+ICgodGhlcm1fZHV0Y2hfbWFqICsgdGhlcm1fdHVyKS8yKSAtIHRoZXJtX21vciwNCiAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIkR1dGNoLU1ham9yaXR5IiB+ICgodGhlcm1fbW9yICsgdGhlcm1fdHVyKS8yKSAtIHRoZXJtX2R1dGNoX21haiwNCiAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIk90aGVyIiB+ICh0aGVybV9kdXRjaF9tYWogKyB0aGVybV90dXIgKyB0aGVybV9tb3IpLzMNCiAgKSkgDQoNCmBgYA0KDQpQcmVwYXJlIGV0aG5pYyBob21vZ2VuZWl0eSBtZWFzdXJlLg0KDQpgYGB7ciBldGhuaWMgaG9tIG5hbWVzfQ0KbmVsbHNfZGYgPC0gbmVsbHNfZGYgJT4lDQogIG11dGF0ZSgNCiAgICBzdW1fZHV0Y2ggPSBrbm93c19kYWFuX2JvdW5kYXJ5ICsga25vd3Nfa2V2aW5fYm91bmRhcnkgKyBrbm93c19lbW1hX2JvdW5kYXJ5ICsga25vd3NfbGluZGFfYm91bmRhcnkgKyBrbm93c19hbGJlcnRfYm91bmRhcnkgKyBrbm93c19lZHdpbl9ib3VuZGFyeSArIGtub3dzX3dpbGxlbWluYV9ib3VuZGFyeSArIGtub3dzX2luZ3JpZF9ib3VuZGFyeSwNCiAgICBzdW1fdHVya2lzaCA9IGtub3dzX2licmFoaW1fYm91bmRhcnkgKyBrbm93c19lc3JhX2JvdW5kYXJ5LA0KICAgIHN1bV9tb3JvY2NhbiA9IGtub3dzX21vaGFtbWVkX2JvdW5kYXJ5ICsga25vd3NfZmF0aW1hX2JvdW5kYXJ5LA0KICAgIHN1bV9jYXQgPSBrbm93c19wcmlzb24gKyBrbm93c19tYm8gKyBrbm93c19zZWN1bmRhcnksDQogICAgK2tub3dzX2hibyArIGtub3dzX3VuaXZlcnNpdHkgKyBrbm93c191bmVtcGxveWVkICsga25vd3Nfc2Vjb25kaG9tZSwNCiAgICBzdW1fdG90YWwgPSBzdW1fZHV0Y2ggKyBzdW1fdHVya2lzaCArIHN1bV9tb3JvY2NhbiwNCiAgICBwZXJfZHV0Y2ggPSAoc3VtX2R1dGNoIC8gc3VtX3RvdGFsKSAqIDEwMCwNCiAgICBwZXJfdHVya2lzaCA9IChzdW1fdHVya2lzaCAvIHN1bV90b3RhbCkgKiAxMDAsDQogICAgcGVyX21vcm9jY2FuID0gKHN1bV9tb3JvY2NhbiAvIHN1bV90b3RhbCkgKiAxMDANCiAgKQ0KDQojYXNzaWduIGNvcnJlY3QgcGVyY2VudGFnZSBjby1ldGhuaWMgdG8gZWFjaCBncm91cA0KbmVsbHNfZGYgPC0gbmVsbHNfZGYgJT4lIA0KICBtdXRhdGUocGVyX2luZ3JvdXAgPSBjYXNlX3doZW4oDQogICAgc3RyX2RldGVjdChtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMsICJraXNoIikgfiBwZXJfdHVya2lzaCwNCiAgICBzdHJfZGV0ZWN0KG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYywgIm9jY2FuIikgfiBwZXJfbW9yb2NjYW4sDQogICAgbWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICJEdXRjaC1NYWpvcml0eSIgfiBwZXJfZHV0Y2gsDQogICAgbWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICJPdGhlciIgfiBwZXJfZHV0Y2gNCiAgKSkNCg0KI3dlaWdodGVkIGJ5IG5hbWUgZnJlcXVlbmN5Lg0KbmVsbHNfZGYgPC0gbmVsbHNfZGYgJT4lDQogIG11dGF0ZSgNCiAgICBzdW1fZHV0Y2hfdyA9IGtub3dzX2RhYW5fYm91bmRhcnkvMjI3MDQgKyANCiAgICAgIGtub3dzX2tldmluX2JvdW5kYXJ5LzIzMTY3ICsNCiAgICAgIGtub3dzX2VtbWFfYm91bmRhcnkvMTg3MzAgKyANCiAgICAgIGtub3dzX2xpbmRhX2JvdW5kYXJ5LzI5OTU1ICsgDQogICAgICBrbm93c19hbGJlcnRfYm91bmRhcnkvMzE3NjcgKyANCiAgICAgIGtub3dzX2Vkd2luX2JvdW5kYXJ5LzIxODY2ICsgDQogICAgICBrbm93c193aWxsZW1pbmFfYm91bmRhcnkvMTcxMzMgKyANCiAgICAgIGtub3dzX2luZ3JpZF9ib3VuZGFyeS8zMTMyMywNCiAgICBzdW1fdHVya2lzaF93ID0ga25vd3NfaWJyYWhpbV9ib3VuZGFyeS8yMDk5ICsgDQogICAgICBrbm93c19lc3JhX2JvdW5kYXJ5LzE4NzgsDQogICAgc3VtX21vcm9jY2FuX3cgPSBrbm93c19tb2hhbW1lZF9ib3VuZGFyeS8xMzQ0OCArIA0KICAgICAga25vd3NfZmF0aW1hX2JvdW5kYXJ5LzI4MDgsDQogICAgc3VtX3RvdGFsX3cgPSBzdW1fZHV0Y2hfdyArIHN1bV90dXJraXNoX3cgKyBzdW1fbW9yb2NjYW5fdywNCiAgICBwZXJfZHV0Y2hfdyA9IChzdW1fZHV0Y2hfdyAvIHN1bV90b3RhbF93KSAqIDEwMCwNCiAgICBwZXJfdHVya2lzaF93ID0gKHN1bV90dXJraXNoX3cgLyBzdW1fdG90YWxfdykgKiAxMDAsDQogICAgcGVyX21vcm9jY2FuX3cgPSAoc3VtX21vcm9jY2FuX3cgLyBzdW1fdG90YWxfdykgKiAxMDANCiAgKQ0KDQojYXNzaWduIGNvcnJlY3QgcGVyY2VudGFnZSBjby1ldGhuaWMgdG8gZWFjaCBncm91cA0KbmVsbHNfZGYgPC0gbmVsbHNfZGYgJT4lIA0KICBtdXRhdGUocGVyX2luZ3JvdXBfdyA9IGNhc2Vfd2hlbigNCiAgICBzdHJfZGV0ZWN0KG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYywgImtpc2giKSB+IHBlcl90dXJraXNoX3csDQogICAgc3RyX2RldGVjdChtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMsICJvY2NhbiIpIH4gcGVyX21vcm9jY2FuX3csDQogICAgbWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICJEdXRjaC1NYWpvcml0eSIgfiBwZXJfZHV0Y2hfdywNCiAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIk90aGVyIiB+IHBlcl9kdXRjaF93DQogICkpDQoNCmBgYA0KDQpDcmVhdGUgaG9tb2dlbmVpdHkgbWVhc3VyZSBiYXNlZCBvbiBuYWl2ZSBOU1VNIG1ldGhvZC4gRmlyc3QgY3JlYXRlIHRoZSBmdW5jdGlvbi4NCg0KYGBge3IgbnVzbSBuYWl2ZSBmcnEgZnVuY3Rpb259DQojZ2V0IHRoZSBmcmVxdWVuY2llcw0KZnJlcXVlbmNpZXMgPC0gcmVhZF9jc3YoImRhdGFfYW5hbHlzaXMvMjAyMi0wOC0yNl9uYW1lZnJlcXVlbmNpZXMuY3N2IikNCg0KbmFtZV9kZiA8LSBuZWxsc19uc3VtICU+JSANCiAgc2VsZWN0KGlkLCBjb250YWlucygiYm91bmRhcnkiKSkgJT4lIA0KICBzZWxlY3QoLWNvbnRhaW5zKCJwcmlzb24iKSkNCg0KI25zdW0gZnVuY3Rpb24NCmZ1bmN0aW9uX25zdW0gPC0gZnVuY3Rpb24oZGF0LCAjZGF0YSBmaWVsZCBvZiB4IHdpdGggSUQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgcG9wc2l6ZSwgI3BvcHVsYXRpb24gc2l6ZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICBmcmVxKSB7I2ZyZXF1ZW5jeSB2ZWN0b3INCiAgI2ZyZXEgZXh0cmFjdA0KICBmcmVxIDwtIGZyZXEgJT4lIA0KICAgIHB1bGwobnVtYmVyKQ0KICANCiAgI2NyZWF0ZSBkZiB3aXRoIElEDQogIGRhdF9pZCA8LSBkYXQgJT4lDQogICAgc2VsZWN0KGlkKQ0KICANCiAgI2NyZWF0ZSBkZiB3aXRob3V0IElEDQogIGRhdCA8LSBkYXQgJT4lIHNlbGVjdCgtaWQpDQogIA0KICAjZXh0cmFjdCBuYW1lcw0KICBuYW1lc19kYXQgPC0gbmFtZXMoZGF0KSAlPiUNCiAgICBzdHJfbWF0Y2goLiwgIl8oLiopXyIpDQogIA0KICAjc2VsZWN0IGNvcnJlY3QgbGlzdA0KICBuYW1lc19kYXQgPC0gbmFtZXNfZGF0WywgMl0NCiAgDQogIA0KICAjbG9vcCB0byBhcHBseSBuYWl2ZSBmdW5jdGlvbiBmb3IgYWxsIGVsZW1lbnRzIGluIHRoZSBERg0KICBuc3VtX2RmIDwtIGZvcmVhY2goYSA9IDE6bmNvbChkYXQpLA0KICAgICAgICAgICAgICAgICAgICAgLmNvbWJpbmUgPSBjYmluZCkgJWRvJSB7DQogICAgICAgICAgICAgICAgICAgICAgIGRhdCAlPiUNCiAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3QoLmRhdGFbW25hbWVzKGRhdClbYV1dXSkgJT4lDQogICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKCEhcGFzdGUwKG5hbWVzX2RhdFthXSwgIl9wcmVkaWN0ZWQiKSA6PSAoLmRhdGFbW25hbWVzKGRhdClbYV1dXSAvDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcmVxW2FdKSAqIHBvcHNpemUpDQogICAgICAgICAgICAgICAgICAgICB9DQogICNjcmVhdGUgTlNVTSBwcmVkaWN0ZWQgZXN0aW1hdGUgKGF2ZXJhZ2VkIG92ZXIgYWxsIGluZGl2aWR1YWwgc2NhbGUgdXBzKQ0KICBuc3VtX2RmIDwtIG5zdW1fZGYgJT4lDQogICAgYmluZF9jb2xzKGRhdF9pZCkgJT4lICNhZGQgSUQNCiAgICByb3d3aXNlKCkgJT4lICNyb3d3aXNlIG1lYW5zDQogICAgbXV0YXRlKGF2ZV9wcmVkaWN0ZWQgPSBtZWFuKHggPSBjX2Fjcm9zcyhjb2xzID0gY29udGFpbnMoInByZWRpY3RlZCIpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUKSkgJT4lDQogICAgdW5ncm91cCgpDQogIA0KICByZXR1cm4obnN1bV9kZikNCn0NCg0KYGBgDQoNCkFwcGx5IGZ1bmN0aW9uIHRvIE5FTExTIGRhdGEuDQoNCmBgYHtyIGV0aG5pYyBjb21wb3NpdGlvbiBwbG90fQ0KI0NyZWF0ZSBuYWl2ZSBzY2FsZSB1cCBlc3RpbWF0ZXMgd2l0aCBhbGwgbmFtZXMuIA0KbmFtZV9hbGxfZGYgPC0gZnVuY3Rpb25fbnN1bShkYXQgPSBuYW1lX2RmLA0KICAgICAgICAgICAgICBwb3BzaXplID0gMTc0MDc1ODUsDQogICAgICAgICAgICAgIGZyZXEgPSBmcmVxdWVuY2llcykgDQoNCiNyZW5hbWUgYWxsIG5hbWVzIGFuZCBkZWxldGUgaW5kaXZpZHVhbCBwcmVkaWN0aW9ucw0KbmFtZV9hbGxfZGYgPC0gbmFtZV9hbGxfZGYgJT4lIA0KICByZW5hbWUoYWxsX3ByZWQgPSBhdmVfcHJlZGljdGVkKSAlPiUgDQogIHJvd3dpc2UoKSAlPiUgDQogIG11dGF0ZShtYWpfcHJlZCA9IG1lYW4oeCA9IGNfYWNyb3NzKGNvbHMgPSBjKA0KICAgIGRhYW5fcHJlZGljdGVkLA0KICAgIGtldmluX3ByZWRpY3RlZCwNCiAgICBlZHdpbl9wcmVkaWN0ZWQsDQogICAgYWxiZXJ0X3ByZWRpY3RlZCwNCiAgICBsaW5kYV9wcmVkaWN0ZWQsDQogICAgZW1tYV9wcmVkaWN0ZWQsDQogICAgaW5ncmlkX3ByZWRpY3RlZCwNCiAgICB3aWxsZW1pbmFfcHJlZGljdGVkDQogICkpLA0KICBuYS5ybSA9IFQpLA0KICBtaW5fcHJlZCA9IG1lYW4oeCA9IGNfYWNyb3NzKGNvbHMgPSBjKA0KICAgIGVzcmFfcHJlZGljdGVkLA0KICAgIG1vaGFtbWVkX3ByZWRpY3RlZCwNCiAgICBpYnJhaGltX3ByZWRpY3RlZCwNCiAgICBmYXRpbWFfcHJlZGljdGVkLA0KICApKSwNCiAgbmEucm0gPSBUKSwNCiAgKSAlPiUgDQogIHVuZ3JvdXAoKQ0KDQojY29tYmluZSBpbmZvcm1hdGlvbg0KbmVsbHNfZGYgPC0gbmVsbHNfZGYgJT4lIA0KICBsZWZ0X2pvaW4obmFtZV9hbGxfZGYsIGJ5ID0gImlkIikNCg0KYGBgDQoNCg0KIyMgRGVsZXRlIG91dGxpZXJzIGFuZCBmaWx0ZXIgb3V0ICJPdGhlciIgbWlnIGJhY2tncm91bmQNCg0KYGBge3IgZGVsZXRlIG91dGxpZXJzfQ0KbmVsbHNfZGYgPC0gbmVsbHNfZGYgJT4lIA0KICAgIG11dGF0ZShtZWFuX3NpemUgPSBtZWFuKG1lYW4sIG5hLnJtID0gVCksDQogICAgICAgICBzZF9zaXplID0gc2QobWVhbiwgbmEucm0gPSBUKSwNCiAgICAgICAgIHogPSAobWVhbiAtIG1lYW5fc2l6ZSkvc2Rfc2l6ZSkgJT4lIA0KICBmaWx0ZXIoeiA8IDMpICU+JSANCiAgZmlsdGVyKG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyAhPSAiT3RoZXIiKQ0KYGBgDQoNCmBgYHtyIGNyZWF0ZSBzdGFuZGFyZGl6ZWQgdmFyaWFibGVzfQ0KI2NyZWF0ZSBzdGFuZGFyZGl6ZWQgdmFyaWFibGVzDQpuZWxsc19kZiA8LSBuZWxsc19kZiAlPiUgDQogIG11dGF0ZShzZF9tYWpfcHJlZCA9IHNkKG1hal9wcmVkLCBuYS5ybSA9IFQpLA0KICAgICAgICAgc2RfbWluX3ByZWQgPSBzZChtaW5fcHJlZCwgbmEucm0gPSBUKSwNCiAgICAgICAgIHpfbWFqX3ByZWQgPSAobWFqX3ByZWQgLSBtZWFuKG1hal9wcmVkLCBuYS5ybSA9IFQpKS9zZF9tYWpfcHJlZCwNCiAgICAgICAgIHpfbWluX3ByZWQgPSAobWluX3ByZWQgLSBtZWFuKG1pbl9wcmVkLCBuYS5ybSA9IFQpKS9zZF9taW5fcHJlZCwNCiAgICAgICAgIHpfdmFsdWVfaW5ncm91cCA9IGlmZWxzZShtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIkR1dGNoLU1ham9yaXR5Iiwgel9tYWpfcHJlZCwgel9taW5fcHJlZCksDQogICAgICAgICB6X3ZhbHVlX291dGdyb3VwID0gaWZlbHNlKG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyA9PSAiRHV0Y2gtTWFqb3JpdHkiLCB6X21pbl9wcmVkLCB6X21hal9wcmVkKSwNCiAgICAgICAgIHpfZGlzdGFuY2VfZ3JvdXBzID0gel92YWx1ZV9vdXRncm91cCAtIHpfdmFsdWVfaW5ncm91cCwNCiAgICAgICAgIHpfZGlzdGFuY2VfbWluX21haiA9IHpfbWluX3ByZWQgLSB6X21hal9wcmVkKSANCmBgYA0KDQoNCiMjIE1pc3NpbmcgZGF0YSBpbXB1dGF0aW9uDQoNCmBgYHtyIE1pc3NpbmcgaW1wdXRhdGlvbjogc2ltcGxlIG1lYW4sIHJlc3VsdHM9J2hpZGUnfQ0KbmVsbHNfZGYgPC0gbmVsbHNfZGYgJT4lIA0KICBtdXRhdGUodGhlcm1fZGlmZl9taXNzaW5nID0gaWZlbHNlKGlzLm5hKHRoZXJtX291dGdyb3VwX2RpZmYpLCAxLCAwKSwNCiAgICAgICAgIHRoZXJtX21lYW5fbWlzc2luZyA9IGlmZWxzZShpcy5uYSh0aGVybV9vdXRncm91cF9tZWFuKSwgMSwgMCksDQogICAgICAgICBwYzRfbWlzc2luZyA9IGlmZWxzZShpcy5uYShJbndvbmVyX3BjNCksIDEsIDApKQ0KDQppbXAgPC0gbmVsbHNfZGYgJT4lIA0KICBzZWxlY3QobWlncmF0aW9uX2JhY2tncm91bmRfZmFjLA0KICAgICAgYWdlLA0KICAgICAgZ2VuZGVyLA0KICAgICAgaW5fZWR1Y2F0aW9uLA0KICAgICAgZWR1Y2F0aW9uX3JlY29kZWRfbnVtZXJpYywNCiAgICAgIHBhcnRuZXIsDQogICAgICBwYXJ0bmVyX2V4dGVuZGVkLA0KICAgICAgaGFzX2NoaWxkLA0KICAgICAgcGFpZF93b3JrLA0KICAgICAgcmVsaWdpb3VzLA0KICAgICAgcmVsaWdpb3VzX2Rlbm9tLA0KICAgICAgcmVsX2F0dGVuZGFuY2UsDQogICAgICBpbndvbmVyX2NvZXRobmljX3BjNCwNCiAgICAgIGlud29uZXJfY29ldGhuaWNfZ2VtLA0KICAgICAgdGhlcm1fb3V0Z3JvdXBfbWVhbiwNCiAgICAgIHRoZXJtX291dGdyb3VwX2RpZmYsDQogICAgICB0aGVybV9kdXRjaF9tYWosDQogICAgICB0aGVybV9tb3IsDQogICAgICB0aGVybV90dXIsDQogICAgICBzdGFydHNfd2l0aCgicGVyIiksDQogICAgICB3b3pfcGM0LA0KICAgICAgbWVhbl93b3pfZ2VtLA0KICAgICAgSW53b25lcl9nZW0sDQogICAgICBJbndvbmVyX3BjNCwNCiAgICAgIHBlcl9OV19taWdfYV9wYzQpICU+JSAgDQogIHNlbGVjdCgtcGVyX2luZ3JvdXAsIC1wZXJfaW5ncm91cF93KSAlPiUgDQogIG1pY2UobWV0aG9kID0gIm1lYW4iKSAlPiUgDQogIGNvbXBsZXRlKCkNCg0KaW1wIDwtIG5lbGxzX2RmICU+JQ0KICBzZWxlY3QoDQogICAgaWQsDQogICAgbWVhbiwNCiAgICBwZXJfaW5ncm91cCwNCiAgICBwZXJfaW5ncm91cF93LA0KICAgIHRoZXJtX2RpZmZfbWlzc2luZywNCiAgICB0aGVybV9tZWFuX21pc3NpbmcsDQogICAgcGM0X21pc3NpbmcsDQogICAgel9tYWpfcHJlZCwNCiAgICB6X21pbl9wcmVkLA0KICAgIHpfdmFsdWVfaW5ncm91cCwNCiAgICB6X3ZhbHVlX291dGdyb3VwLA0KICAgIHpfZGlzdGFuY2VfZ3JvdXBzLA0KICAgIHpfZGlzdGFuY2VfbWluX21hag0KICApICU+JQ0KICBiaW5kX2NvbHMoaW1wKQ0KYGBgDQoNCiMjIE1lYW4gY2VudGVyaW5nIG9mIGNvbnRpbm91b3MgdmFyaWFibGVzDQoNCmBgYHtyIG1lYW4gc3VidHJhY3Rpb259DQppbXAgPC0gaW1wICU+JSANCiAgbXV0YXRlKGVkdWNhdGlvbl9yZWNvZGVkX251bWVyaWMgPSBlZHVjYXRpb25fcmVjb2RlZF9udW1lcmljIC0gbWVhbihlZHVjYXRpb25fcmVjb2RlZF9udW1lcmljLCBuYS5ybSA9IFQpLA0KICAgICAgICAgYWdlID0gYWdlIC0gbWVhbihhZ2UsIG5hLnJtID0gVCksDQogICAgICAgICB3b3pfcGM0ID0gd296X3BjNCAtIG1lYW4od296X3BjNCwgbmEucm0gPSBUKSwNCiAgICAgICAgIG1lYW5fd296X2dlbSA9IG1lYW5fd296X2dlbSAtIG1lYW4obWVhbl93b3pfZ2VtLCBuYS5ybSA9IFQpLA0KICAgICAgICAgSW53b25lcl9nZW0gPSBJbndvbmVyX2dlbSAtIG1lYW4oSW53b25lcl9nZW0sIG5hLnJtID0gVCksDQogICAgICAgICBJbndvbmVyX3BjNCA9IElud29uZXJfcGM0IC0gbWVhbihJbndvbmVyX3BjNCwgbmEucm0gPSBUKSwNCiAgICAgICAgIHRoZXJtX291dGdyb3VwX21lYW4gPSB0aGVybV9vdXRncm91cF9tZWFuIC0gbWVhbih0aGVybV9vdXRncm91cF9tZWFuLCBuYS5ybSA9IFQpLA0KICAgICAgICAgdGhlcm1fb3V0Z3JvdXBfZGlmZiA9IHRoZXJtX291dGdyb3VwX2RpZmYgLSBtZWFuKHRoZXJtX291dGdyb3VwX2RpZmYsIG5hLnJtID0gVCksDQogICAgICAgICBpbndvbmVyX2NvZXRobmljX3BjNCA9IGlud29uZXJfY29ldGhuaWNfcGM0IC0gbWVhbihpbndvbmVyX2NvZXRobmljX3BjNCwgbmEucm0gPSBUKSwNCiAgICAgICAgIGlud29uZXJfY29ldGhuaWNfZ2VtID0gaW53b25lcl9jb2V0aG5pY19nZW0gLSBtZWFuKGlud29uZXJfY29ldGhuaWNfZ2VtLCBuYS5ybSA9IFQpLA0KICAgICAgICBwZXJfTldfbWlnX2FfcGM0ID0gcGVyX05XX21pZ19hX3BjNCAtIG1lYW4ocGVyX05XX21pZ19hX3BjNCwgbmEucm0gPSBUKQ0KICAgICAgICAgKQ0KDQpgYGANCg0KIyMgU2V0IGNvcnJlY3QgbGFiZWxzIG9mIGNhdGVnb3JpY2FsIHZhcmlhYmxlcy4gDQoNCmBgYHtyIGRhdGEgcHJlcCBkZWNvbX0NCiNyZWxhYmVsIHRoZSBmYWN0b3IgdmFyaWFibGVzLiANCmltcCA8LSBpbXAgJT4lDQogIG11dGF0ZSgNCiAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPSBmY3RfcmVsZXZlbChtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRHV0Y2gtTWFqb3JpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjFzdCBnZW4gVHVya2lzaCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMm5kIGdlbiBUdXJraXNoIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIxc3QgZ2VuIE1vcm9jY2FuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIybmQgZ2VuIE1vcm9jY2FuIiksDQogICAgICAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPSBmYWN0b3IoYXMubnVtZXJpYyhtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMpLA0KICAgICAgICAgbGV2ZWxzID0gMTo1LA0KICAgICAgICAgbGFiZWxzID0gYygiRHV0Y2ggTWFqb3JpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjFzdCBnZW4gVHVya2lzaC1EdXRjaCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMm5kIGdlbiBUdXJraXNoLUR1dGNoIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIxc3QgZ2VuIE1vcm9jY2FuLUR1dGNoIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIybmQgZ2VuIE1vcm9jY2FuLUR1dGNoIikpLA0KICAgIG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX3NpbXBsZV9mYWMgPSBjYXNlX3doZW4oDQogICAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIjFzdCBnZW4gVHVya2lzaC1EdXRjaCIgfiAyLA0KICAgICAgbWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICIybmQgZ2VuIFR1cmtpc2gtRHV0Y2giIH4gMiwNCiAgICAgIG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyA9PSAiMXN0IGdlbiBNb3JvY2Nhbi1EdXRjaCIgfiAzLA0KICAgICAgbWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICIybmQgZ2VuIE1vcm9jY2FuLUR1dGNoIiB+IDMsDQogICAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIkR1dGNoIE1ham9yaXR5IiB+IDENCiAgICApLA0KICAgIG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX3NpbXBsZV9mYWMgPSBmYWN0b3IoDQogICAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9zaW1wbGVfZmFjLA0KICAgICAgbGV2ZWxzID0gMTozLA0KICAgICAgbGFiZWxzID0gYygiRHV0Y2ggTWFqb3JpdHkiLCAiVHVya2lzaC1EdXRjaCIsICJNb3JvY2Nhbi1EdXRjaCIpDQogICAgKQ0KICApDQoNCiNub3QgYWxsIHN1Ymdyb3VwcyBoYXZlIGNvbXBsZXRlIGNhc2VzIGZvciBhbGwgdGhlIGZhY3RvciB2YXJpYWJsZXMuIEhlbmNlLCB0aGUgbmVlZCB0byBjb21iaW5lIHNvbWUgY2F0ZWdvcmllcy4gDQppbXAgPC0gaW1wICU+JQ0KICBtdXRhdGUoDQogICAgcmVsX2F0dGVuZGFuY2VfbnVtID0gaWZfZWxzZShhcy5udW1lcmljKHJlbF9hdHRlbmRhbmNlKSA+IDMsIDQsIGFzLm51bWVyaWMocmVsX2F0dGVuZGFuY2UpKSwNCiAgICByZWxfZmFjXzIgPSBmYWN0b3IoDQogICAgICByZWxfYXR0ZW5kYW5jZV9udW0sDQogICAgICBsZXZlbHMgPSAxOjQsDQogICAgICBsYWJlbHMgPSBjKCJOZXZlciIsICIxLTIgWWVhciIsICIzLTExIFllYXIiLCAiTW9udGhseSBvciBtb3JlIikNCiAgICApLA0KICAgIHBhcnRuZXIgPSBpZl9lbHNlKHBhcnRuZXJfZXh0ZW5kZWQgPT0gIkRvZXMgbm90IGhhdmUgYSBwYXJ0bmVyIiwgMCwgMSkNCiAgKSAgDQoNCg0KDQpgYGANCg0KDQojIERlc2NyaXB0aXZlIHN0YXRpc3RpY3MgdGFibGUNCg0KIyMgRGVzc3RhdHMgdGFibGUgZnVuY3Rpb24gYW5kIHRhYmxlIGNyZWF0aW9uDQpgYGB7ciBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIHRhYmxlIGZ1bmN0aW9ufQ0KcHJlcGFyZV9kZXNzdGF0cyA8LSBmdW5jdGlvbih4LCBmdWxsLnNhbXBsZSkgew0KICBpZiAoZnVsbC5zYW1wbGUgPT0gVCkgew0KICAgIGRlc3N0YXRzIDwtIHggJT4lDQogICAgICBtdXRhdGUoDQogICAgICAgIGxuX3NpemUgPSBsb2cobWVhbiksDQogICAgICAgIER1dGNoID0gaWZfZWxzZShtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIkR1dGNoIE1ham9yaXR5IiwgMSwgMCksDQogICAgICAgIGAybmRfZ2VuX01vcm9jY2FuYCA9IGlmX2Vsc2UobWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICIybmQgZ2VuIE1vcm9jY2FuLUR1dGNoIiwgMSwgMCksDQogICAgICAgIGAybmRfZ2VuX1R1cmtpc2hgID0gaWZfZWxzZShtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIjJuZCBnZW4gVHVya2lzaC1EdXRjaCIsIDEsIDApLA0KICAgICAgICBgMXN0X2dlbl9UdXJraXNoYCA9IGlmX2Vsc2UobWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICIxc3QgZ2VuIFR1cmtpc2gtRHV0Y2giLCAxLCAwKSwNCiAgICAgICAgYDFzdF9nZW5fTW9yb2NjYW5gID0gaWZfZWxzZShtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIjFzdCBnZW4gTW9yb2NjYW4tRHV0Y2giLCAxLCAwKSwNCiAgICAgICAgYWdlID0gYXMubnVtZXJpYyhhZ2UpLA0KICAgICAgICBmZW1hbGUgPSBpZl9lbHNlKGdlbmRlciA9PSAiRmVtYWxlIiwgMSwgMCksDQogICAgICAgIGdlbmRlcl9vdGhlciA9IGlmX2Vsc2UoZ2VuZGVyID09ICJPdGhlciIsIDEsIDApLA0KICAgICAgICBub19wYXJ0bmVyID0gaWZfZWxzZShwYXJ0bmVyX2V4dGVuZGVkICE9ICJEb2VzIG5vdCBoYXZlIGEgcGFydG5lciIsIDEsIDApLA0KICAgICAgICBwYXJ0bmVyX3NlcGVyYXRlID0gaWZfZWxzZShwYXJ0bmVyX2V4dGVuZGVkID09ICJIYXMgYSBwYXJ0bmVyLCBsaXZlcyBzZXBlcmF0ZWx5IiwgMSwgMCksDQogICAgICAgIHBhcnRuZXJfdG9nZXRoZXIgPSBpZl9lbHNlKHBhcnRuZXJfZXh0ZW5kZWQgPT0gIkxpdmVzIHRvZ2V0aGVyLCB1bm1hcnJpZWQiLCAxLCAwKSwNCiAgICAgICAgcGFydG5lcl9tYXJyaWVkID0gaWZfZWxzZShwYXJ0bmVyX2V4dGVuZGVkID09ICJNYXJyaWVkIiwgMSwgMCksDQogICAgICAgIHJlbF9uZXZlciA9IGlmX2Vsc2UocmVsX2F0dGVuZGFuY2UgPT0gIk5ldmVyIiwgMSwgMCksDQogICAgICAgIHJlbF8xMl95ZWFyID0gaWZfZWxzZShyZWxfYXR0ZW5kYW5jZSA9PSAiMS0yIGEgeWVhciIsIDEsIDApLA0KICAgICAgICByZWxfMzExX3llYXIgPSBpZl9lbHNlKHJlbF9hdHRlbmRhbmNlID09ICIzLTExIGEgeWVhciIsIDEsIDApLA0KICAgICAgICByZWxfbW9udGggPSBpZl9lbHNlKHJlbF9hdHRlbmRhbmNlID09ICJPbmNlIGEgbW9udGgiLCAxLCAwKSwNCiAgICAgICAgcmVsXzIzX21vbnRoID0gaWZfZWxzZShyZWxfYXR0ZW5kYW5jZSA9PSAiMi0zIGEgbW9udGgiLCAxLCAwKSwNCiAgICAgICAgcmVsX3dlZWtseSA9IGlmX2Vsc2UocmVsX2F0dGVuZGFuY2UgPT0gIkV2ZXJ5IHdlZWsiLCAxLCAwKSwNCiAgICAgICAgcmVsX211bF93ZWVrbHkgPSBpZl9lbHNlKHJlbF9hdHRlbmRhbmNlID09ICJNdWx0aXBsZSB0aW1lcyBhIHdlZWsiLCAxLCAwKSwNCiAgICAgICAgcmVsX21vbnRoX21vcmUgPSBpZl9lbHNlKHJlbF9mYWNfMiA9PSAiTW9udGhseSBvciBtb3JlIiwgMSwgMCkNCiAgICAgICkgJT4lDQogICAgICByZW5hbWUoc2l6ZSA9IG1lYW4pICU+JQ0KICAgICAgc2VsZWN0KA0KICAgICAgICBzaXplLA0KICAgICAgICBsbl9zaXplLA0KICAgICAgICBwZXJfaW5ncm91cF93LA0KICAgICAgICAjcGVyX2luZ3JvdXAsDQogICAgICAgICNhZGFfdmFsdWUsDQogICAgICAgIER1dGNoLA0KICAgICAgICBgMXN0X2dlbl9UdXJraXNoYCwNCiAgICAgICAgYDJuZF9nZW5fVHVya2lzaGAsDQogICAgICAgIGAxc3RfZ2VuX01vcm9jY2FuYCwNCiAgICAgICAgYDJuZF9nZW5fTW9yb2NjYW5gLA0KICAgICAgICBhZ2UsDQogICAgICAgIGZlbWFsZSwNCiAgICAgICAgZWR1Y2F0aW9uX3JlY29kZWRfbnVtZXJpYywNCiAgICAgICAgbm9fcGFydG5lciwNCiAgICAgICAgcGFpZF93b3JrLA0KICAgICAgICBpbl9lZHVjYXRpb24sDQogICAgICAgIHJlbF9uZXZlciwNCiAgICAgICAgcmVsXzEyX3llYXIsDQogICAgICAgIHJlbF8zMTFfeWVhciwNCiAgICAgICAgcmVsX21vbnRoX21vcmUsDQogICAgICAgIHRoZXJtX291dGdyb3VwX2RpZmYsDQogICAgICAgIHBlcl9OV19taWdfYV9wYzQsDQogICAgICAgIHdvel9wYzQsDQogICAgICAgIElud29uZXJfcGM0DQogICAgICApICU+JQ0KICAgICAgcHN5Y2g6OmRlc2NyaWJlKCkgJT4lIA0KICAgICAgcm91bmQoLiwgZGlnaXRzID0gMykNCiAgfQ0KICBlbHNlIHsNCiAgICBkZXNzdGF0cyA8LSB4ICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBsbl9zaXplID0gbG9nKG1lYW4pLA0KICAgICAgICBhZ2UgPSBhcy5udW1lcmljKGFnZSksDQogICAgICAgIGZlbWFsZSA9IGlmX2Vsc2UoZ2VuZGVyID09ICJGZW1hbGUiLCAxLCAwKSwNCiAgICAgICAgZ2VuZGVyX290aGVyID0gaWZfZWxzZShnZW5kZXIgPT0gIk90aGVyIiwgMSwgMCksDQogICAgICAgIG5vX3BhcnRuZXIgPSBpZl9lbHNlKHBhcnRuZXJfZXh0ZW5kZWQgIT0gIkRvZXMgbm90IGhhdmUgYSBwYXJ0bmVyIiwgMSwgMCksDQogICAgICAgIHBhcnRuZXJfc2VwZXJhdGUgPSBpZl9lbHNlKHBhcnRuZXJfZXh0ZW5kZWQgPT0gIkhhcyBhIHBhcnRuZXIsIGxpdmVzIHNlcGVyYXRlbHkiLCAxLCAwKSwNCiAgICAgICAgcGFydG5lcl90b2dldGhlciA9IGlmX2Vsc2UocGFydG5lcl9leHRlbmRlZCA9PSAiTGl2ZXMgdG9nZXRoZXIsIHVubWFycmllZCIsIDEsIDApLA0KICAgICAgICBwYXJ0bmVyX21hcnJpZWQgPSBpZl9lbHNlKHBhcnRuZXJfZXh0ZW5kZWQgPT0gIk1hcnJpZWQiLCAxLCAwKSwNCiAgICAgICAgcmVsX25ldmVyID0gaWZfZWxzZShyZWxfYXR0ZW5kYW5jZSA9PSAiTmV2ZXIiLCAxLCAwKSwNCiAgICAgICAgcmVsXzEyX3llYXIgPSBpZl9lbHNlKHJlbF9hdHRlbmRhbmNlID09ICIxLTIgYSB5ZWFyIiwgMSwgMCksDQogICAgICAgIHJlbF8zMTFfeWVhciA9IGlmX2Vsc2UocmVsX2F0dGVuZGFuY2UgPT0gIjMtMTEgYSB5ZWFyIiwgMSwgMCksDQogICAgICAgIHJlbF9tb250aCA9IGlmX2Vsc2UocmVsX2F0dGVuZGFuY2UgPT0gIk9uY2UgYSBtb250aCIsIDEsIDApLA0KICAgICAgICByZWxfMjNfbW9udGggPSBpZl9lbHNlKHJlbF9hdHRlbmRhbmNlID09ICIyLTMgYSBtb250aCIsIDEsIDApLA0KICAgICAgICByZWxfd2Vla2x5ID0gaWZfZWxzZShyZWxfYXR0ZW5kYW5jZSA9PSAiRXZlcnkgd2VlayIsIDEsIDApLA0KICAgICAgICByZWxfbXVsX3dlZWtseSA9IGlmX2Vsc2UocmVsX2F0dGVuZGFuY2UgPT0gIk11bHRpcGxlIHRpbWVzIGEgd2VlayIsIDEsIDApLA0KICAgICAgICByZWxfbW9udGhfbW9yZSA9IGlmX2Vsc2UocmVsX2ZhY18yID09ICJNb250aGx5IG9yIG1vcmUiLCAxLCAwKQ0KICAgICAgKSAlPiUNCiAgICAgIHJlbmFtZShzaXplID0gbWVhbikgJT4lDQogICAgICBzZWxlY3QoDQogICAgICAgIHNpemUsDQogICAgICAgIGxuX3NpemUsDQogICAgICAgIHBlcl9pbmdyb3VwX3csDQogICAgICAgICNhZGFfdmFsdWUsDQogICAgICAgIGFnZSwNCiAgICAgICAgZmVtYWxlLA0KICAgICAgICBlZHVjYXRpb25fcmVjb2RlZF9udW1lcmljLA0KICAgICAgICBub19wYXJ0bmVyLA0KICAgICAgICBwYWlkX3dvcmssDQogICAgICAgIGluX2VkdWNhdGlvbiwNCiAgICAgICAgcmVsX25ldmVyLA0KICAgICAgICByZWxfMTJfeWVhciwNCiAgICAgICAgcmVsXzMxMV95ZWFyLA0KICAgICAgICByZWxfbW9udGhfbW9yZSwNCiAgICAgICAgdGhlcm1fb3V0Z3JvdXBfZGlmZiwNCiAgICAgICAgcGVyX05XX21pZ19hX3BjNCwNCiAgICAgICAgd296X3BjNCwNCiAgICAgICAgSW53b25lcl9wYzQNCiAgICAgICkgJT4lDQogICAgICBwc3ljaDo6ZGVzY3JpYmUoKSAlPiUgDQogICAgICByb3VuZCguLCBkaWdpdHMgPSAzKQ0KICB9DQogIA0KfQ0KDQp2YXJfbmFtZXNfc2FtcGxlIDwtIGMoDQogICJOZXR3b3JrIHNpemUiLA0KICAiTmV0d29yayBzaXplIChsb2cpIiwNCiAgIkV0aG5pYyBob21vZ2VuZWl0eSIsDQogICJBZ2UiLA0KICAiR2VuZGVyIFtGZW1hbGVdIiwNCiAgIkVkdWNhdGlvbmFsIGF0dGFpbm1lbnQiLA0KICAiUGFydG5lciBbSGFzIGEgcGFydG5lcl0iLA0KICAiUGFpZCB3b3JrIiwNCiAgIkN1cnJlbnRseSBpbiBlZHVjYXRpb24iLA0KICAiUmVsaWdpb3VzIGF0dGVuZGFuY2VbTmV2ZXJdIiwNCiAgIlJlbGlnaW91cyBhdHRlbmRhbmNlWzEtMiB5ZWFyXSIsDQogICJSZWxpZ2lvdXMgYXR0ZW5kYW5jZVszLTExIGEgeWVhcl0iLA0KICAiUmVsaWdpb3VzIGF0dGVuZGFuY2VbT25jZSBhIG1vbnRoIG9yIG1vcmVdIiwNCiAgIk91dGdyb3VwIGF0dGl0dWRlIiwNCiAgIk5laWdoYm91cmhvb2Q6ICUgTm9uLXdlc3Rlcm4gbWlncmFudCIsDQogICJOZWlnaGJvdXJob29kOiBtZWFuIHByb3BlcnR5IHZhbHVhdGlvbiIsDQogICJOZWlnaGJvdXJob29kOiAjIGluaGFiaXRhbnRzIg0KKQ0KDQp2YXJfbmFtZXNfZnVsbDwtIGMoDQogICJOZXR3b3JrIHNpemUiLA0KICAiTmV0d29yayBzaXplIChsb2cpIiwNCiAgIkV0aG5pYyBob21vZ2VuZWl0eSIsDQogICJHcm91cFtEdXRjaCBtYWpvcml0eV0iLA0KICAiR3JvdXBbMXN0IGdlbiBUdXJraXNoLUR1dGNoXSIsDQogICJHcm91cFsybmQgZ2VuIFR1cmtpc2gtRHV0Y2hdIiwNCiAgIkdyb3VwWzFzdCBnZW4gTW9yb2NjYW4tRHV0Y2hdIiwNCiAgIkdyb3VwWzJuZCBnZW4gTW9yb2NjYW4tRHV0Y2hdIiwNCiAgIkFnZSIsDQogICJHZW5kZXIgW0ZlbWFsZV0iLA0KICAiRWR1Y2F0aW9uYWwgYXR0YWlubWVudCIsDQogICJQYXJ0bmVyIFtIYXMgYSBwYXJ0bmVyXSIsDQogICJQYWlkIHdvcmsiLA0KICAiQ3VycmVudGx5IGluIGVkdWNhdGlvbiIsDQogICJSZWxpZ2lvdXMgYXR0ZW5kYW5jZVtOZXZlcl0iLA0KICAiUmVsaWdpb3VzIGF0dGVuZGFuY2VbMS0yIHllYXJdIiwNCiAgIlJlbGlnaW91cyBhdHRlbmRhbmNlWzMtMTEgYSB5ZWFyXSIsDQogICJSZWxpZ2lvdXMgYXR0ZW5kYW5jZVtPbmNlIGEgbW9udGggb3IgbW9yZV0iLA0KICAiT3V0Z3JvdXAgYXR0aXR1ZGUiLA0KICAiTmVpZ2hib3VyaG9vZDogJSBOb24td2VzdGVybiBtaWdyYW50IiwNCiAgIk5laWdoYm91cmhvb2Q6IG1lYW4gcHJvcGVydHkgdmFsdWF0aW9uIiwNCiAgIk5laWdoYm91cmhvb2Q6ICMgaW5oYWJpdGFudHMiDQopDQoNCmRlc3N0YXRzIDwtIGltcCAlPiUgDQogIHByZXBhcmVfZGVzc3RhdHMoeCA9IC4sIGZ1bGwuc2FtcGxlID0gVCkNCg0KZGVzc3RhdHNfc2FtcGxlIDwtIGltcCAlPiUgDQogIGdyb3VwX3NwbGl0KG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYykgJT4lIA0KICBtYXAoLnggPSAuLCAuZiA9IH4gcHJlcGFyZV9kZXNzdGF0cyh4ID0gLngsIGZ1bGwuc2FtcGxlID0gRikpICU+JSANCiAgbWFwKC54ID0gLiwgLmYgPSB+IGRwbHlyOjpzZWxlY3QoLmRhdGEgPSAueCwgbWVhbiwgc2QpKQ0KDQoNCiNjdXN0b20gZnVuY3Rpb24gdG8gc2V0IHJvd25hbWVzIGluIHBpcGUuDQpzZXRfcm93bmFtZXMgPC0gZnVuY3Rpb24oZGYsbmFtZXMpIHsNCnJvdy5uYW1lcyhkZikgPC0gbmFtZXMNCnJldHVybihkZikNCn0NCmBgYA0KDQojIyBEZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIHRhYmxlIGZ1bGwgc2FtcGxlDQoNCmBgYHtyIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3MgZnVsbCBzYW1wbGV9DQpkZXNzdGF0cyAlPiUgDQogIGJpbmRfY29scygubmFtZV9yZXBhaXIgPSAibWluaW1hbCIpICU+JSANCiAgc2VsZWN0KG1lYW4sIHNkLCBtZWRpYW4sIG1pbiwgbWF4KSAlPiUgDQpzZXRfcm93bmFtZXMoZGYgPSAuLCBuYW1lcyA9IHZhcl9uYW1lc19mdWxsKSAlPiUgDQogICAga2JsKHJvdy5uYW1lcyA9IFQpICU+JSANCiAga2FibGVfY2xhc3NpYygpDQogIA0KYGBgDQoNCiMjIERlc2NyaXB0aXZlIHN0YXRpc3RpY3MgYnkgZ3JvdXANCg0KYGBge3IgZGVzY3JpcHRpdmUgc3RhdGlzdGljcyBieSBncm91cH0NCmRlc3N0YXRzX3NhbXBsZSAlPiUgDQogIGJpbmRfY29scygubmFtZV9yZXBhaXIgPSAibWluaW1hbCIpICU+JQ0KICBzZXRfcm93bmFtZXMoZGYgPSAuLCBuYW1lcyA9IHZhcl9uYW1lc19zYW1wbGUpICU+JSANCiAga2JsKHJvdy5uYW1lcyA9IFQpICU+JSANCiAga2FibGVfY2xhc3NpYygpICU+JQ0KICBhZGRfaGVhZGVyX2Fib3ZlKGMoIiAiID0gMSwiRHV0Y2giID0gMiwgIjFzdCBnZW4gVHVya2lzaCIgPSAyLCAiMm5kIGdlbiBUdXJraXNoIiA9IDIsICIxc3QgZ2VuIE1vcm9jY2FuIiA9IDIsICIybmQgZ2VuIE1vcm9jY2FuIiA9IDIpKSAlPiUgDQogICBmb290bm90ZShnZW5lcmFsID0gIlNpemUgb2YgdGhlIGRpZmZlcmVudCBncm91cHMgIiwNCiAgICAgICAgICAgbnVtYmVyID0gYygiRHV0Y2g6IDY1OCIsICIybmQgZ2VuIE1vcm9jY2FuOiA5MiIsDQogICAgICAgICAgICAgICAgICAgICAgIjJuZCBnZW4gVHVya2lzaDogMTM0IiwgIjFzdCBnZW4gVHVya2lzaDogMTQxIiwNCiAgICAgICAgICAgICAgICAgICAgICAiMXN0IGdlbiBNb3JvY2NhbjogNzMiKSkgDQoNCg0KYGBgDQoNCg0KIyBJbmZlcmVudGlhbCBhbmFseXNpcw0KDQpXZSBub3cgdHVybiB0byB0ZXN0aW5nIGdyb3VwIGRpZmZlcmVuY2VzLiBEaWZmZXJlbnQgbWV0aG9kcyBhcmUgdXNlZC4gRmlyc3Qgd2UgY2FuIGNoZWNrIGdyb3VwIGRpZmZlcmVuY2VzIHdpdGggYW4gT0xTIGFuZCBkdW1taWVzLiBTZWNvbmQsIHdlIGNhbiB1c2UgYW4gYW5vdmEgdG8gY2hlY2sgdGhlIGRpZmZlcmVuY2VzLiBUaGlyZCwgd2Ugd2lsbCB1c2UgYSBkZWNvbXBvc2l0aW9uIGFuYWx5c2lzIHRvIGV4cGxhaW4gZ3JvdXAgZGlmZmVyZW5jZXMuIA0KDQojIyBPTFMgbW9kZWwgd2l0aCBkdW1teQ0KYGBge3IgZ3JvdXAgZGlmZmVyZWNjZXN9DQpzaXplX2dyb3VwX21vZGVsIDwtIGltcCAlPiUgIA0KICBmaWx0ZXIoZ2VuZGVyICE9ICJPdGhlciIpICU+JSANCiAgbXV0YXRlKA0KICBtZWFuID0gYXMuaW50ZWdlcihtZWFuKQ0KKSAlPiUNCiAgbG0oDQogICAgbG9nKG1lYW4pIH4gbWlncmF0aW9uX2JhY2tncm91bmRfZmFjLA0KICAgIGRhdGEgPSAuDQogICkNCmhvbV9ncm91cF9tb2RlbCA8LSBpbXAgJT4lDQogIGZpbHRlcihnZW5kZXIgIT0gIk90aGVyIikgJT4lDQogIGxtKA0KICAgIHBlcl9pbmdyb3VwX3cgfiBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMsDQogICAgZGF0YSA9IC4NCiAgKQ0KDQojc2hvdyB0YWJsZSBvZiBPTFMgcmVzdWx0cw0Kc2pQbG90Ojp0YWJfbW9kZWwoc2l6ZV9ncm91cF9tb2RlbCwNCiAgICAgICAgICAgICAgICAgIGhvbV9ncm91cF9tb2RlbCwNCiAgICAgICAgICBwcmVkLmxhYmVscyA9IGMoDQogICAgICAgICAgICAiQ29uc3RhbnQiLA0KICAgICAgICAgICAgIkdyb3VwWzFzdCBnZW4gVHVya2lzaC1EdXRjaF0iLA0KICAgICAgICAgICAgIkdyb3VwWzJuZCBnZW4gVHVya2lzaC1EdXRjaF0iLA0KICAgICAgICAgICAgIkdyb3VwWzFzdCBnZW4gTW9yb2NjYW4tRHV0Y2hdIiwNCiAgICAgICAgICAgICJHcm91cFsybmQgZ2VuIE1vcm9jY2FuLUR1dGNoXSINCiAgICAgICAgICAgICksDQogICAgICAgICAgZGlnaXRzID0gMywNCiAgICAgICAgICBzaG93LmNpID0gRiwNCiAgICAgICAgICBzaG93LnN0YXQgPSBULA0KICAgICAgICAgIGNvbGxhcHNlLnNlICA9IEYsDQogICAgICAgICAgY29sLm9yZGVyID0gYygiZXN0IiwgInN0YXQiKSwNCiAgICAgICAgICBwLnN0eWxlID0gInNjaWVudGlmaWMiDQogICAgICAgICAgI2ZpbGUgPSAicmVnLmRvYyINCiAgICAgICAgICApDQoNCg0KYGBgDQoNCiMjIEFub3ZhDQoNClNpemUgYW5hbHlzaXMuIA0KQ29tcGxldGUgZ3JvdXBzLg0KDQpgYGB7ciBzaW1wbGUgc2l6ZX0NCiMgQ29tcHV0ZSB0aGUgYW5hbHlzaXMgb2YgdmFyaWFuY2UNCnJlc19hb3Zfc2l6ZSA8LSBhb3YobG9nKG1lYW4pIH4gbWlncmF0aW9uX2JhY2tncm91bmRfc2ltcGxlX2ZhYywgZGF0YSA9IGltcCkNCg0KIyBTdW1tYXJ5IG9mIHRoZSBhbmFseXNpcw0KcmVzdWx0c19zaXplIDwtIHN1bW1hcnkocmVzX2Fvdl9zaXplKQ0KDQojbG9vayBhdCBncm91cCBkaWZmZXJlbmNlcw0KYW5vdmFfZGlmZl9kZl9zaXplICA8LSBhc190aWJibGUoVHVrZXlIU0QocmVzX2Fvdl9zaXplKSRtaWdyYXRpb25fYmFja2dyb3VuZF9zaW1wbGVfZmFjKSAlPiUgDQogIG11dGF0ZShEaWZmZXJlbmNlID0gcm93Lm5hbWVzKFR1a2V5SFNEKHJlc19hb3Zfc2l6ZSkkbWlncmF0aW9uX2JhY2tncm91bmRfc2ltcGxlX2ZhYykpICU+JSANCiAgc2VsZWN0KDUsIDE6NCkgJT4lIA0KICBzZWxlY3QoRGlmZmVyZW5jZSxkaWZmLCBgcCBhZGpgKSAlPiUgDQogIHJlbmFtZSh2YWx1ZSA9IGRpZmYsDQogICAgICAgICBwID0gYHAgYWRqYCkgJT4lIA0KICBtdXRhdGUodmFyaWFibGUgPSAibG4oU2l6ZSkiKQ0KDQojIENvbXB1dGUgdGhlIGFuYWx5c2lzIG9mIHZhcmlhbmNlDQpyZXNfYW92X2hvbSA8LSBhb3YocGVyX2luZ3JvdXBfdyB+IG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX3NpbXBsZV9mYWMsIGRhdGEgPSBpbXApDQoNCiMgU3VtbWFyeSBvZiB0aGUgYW5hbHlzaXMNCnJlc3VsdHNfaG9tIDwtIHN1bW1hcnkocmVzX2Fvdl9ob20pDQoNCiNsb29rIGF0IGdyb3VwIGRpZmZlcmVuY2VzDQphbm92YV9kaWZmX2RmX2hvbSAgPC0gYXNfdGliYmxlKFR1a2V5SFNEKHJlc19hb3ZfaG9tKSRtaWdyYXRpb25fYmFja2dyb3VuZF9zaW1wbGVfZmFjKSAlPiUgDQogIG11dGF0ZShEaWZmZXJlbmNlID0gcm93Lm5hbWVzKFR1a2V5SFNEKHJlc19hb3ZfaG9tKSRtaWdyYXRpb25fYmFja2dyb3VuZF9zaW1wbGVfZmFjKSkgJT4lIA0KICBzZWxlY3QoNSwgMTo0KSAlPiUgDQogIHNlbGVjdChEaWZmZXJlbmNlLCBkaWZmLCBgcCBhZGpgKSAlPiUgDQogIHJlbmFtZSh2YWx1ZSA9IGRpZmYsDQogICAgICAgICBwID0gYHAgYWRqYCkgJT4lIA0KICBtdXRhdGUodmFyaWFibGUgPSAiSG9tb2dlbmVpdHkiKQ0KDQojYWRkIHNpZy4gaW5kaWNhdG9yDQphbm92YV9kaWZmX2RmIDwtIGFub3ZhX2RpZmZfZGZfc2l6ZSAlPiUgDQogIGJpbmRfcm93cyhhbm92YV9kaWZmX2RmX2hvbSkgJT4lIA0KICBtdXRhdGUoc2lnID0gaWZlbHNlKHAgPCAwLjA1LCAxLCAwKSwNCiAgICAgICAgIHNpZ19mID0gaWZlbHNlKHNpZyA9PSAxLCAiKiIsICIiKSkNCg0KDQojY3JlYXRlIGFub3ZhIHBsb3QNCmFub3ZhX2RpZmZfc2ltcGxlX3Bsb3QgPC0gYW5vdmFfZGlmZl9kZiAlPiUgDQogIG11dGF0ZShkaWZmX2ZhYyA9IGZjdF9yZXYoZmFjdG9yKHJlcCgxOjMsMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSAxOjMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJUS1kgLSBORUQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTU9SIC0gTkVEIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1PUiAtIFRLWSIpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpDQoNCiAgICAgICAgICkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSB2YWx1ZSwgDQogICAgICAgICAgICAgeSA9IGRpZmZfZmFjKSkgKw0KICBnZW9tX2NvbChhZXMoZmlsbCA9IHZhcmlhYmxlLA0KICAgICAgICAgICBjb2xvdXIgPSB2YXJpYWJsZSksDQogICAgICAgICAgIGFscGhhID0gMC42KSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBzaWdfZiksDQogICAgICAgICAgICBzaXplID0gNiwNCiAgICAgICAgICAgIGhqdXN0ID0gMSkgKw0KICBmYWNldF93cmFwKHZhcnModmFyaWFibGUpLA0KICAgICAgICAgICAgIHNjYWxlcyA9ICJmcmVlX3giKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Qob3B0aW9uID0gIkQiKSArDQogIHNjYWxlX2NvbG91cl92aXJpZGlzX2Qob3B0aW9uID0gIkQiKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAxKSwNCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMSksDQogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gImJsYWNrIiksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gImJsYWNrIikpICsNCiAgbGFicyh5ID0gIiIsDQogICAgICAgeCA9ICIiLA0KICAgICAgIGNhcHRpb24gPSAiIikNCmBgYA0KDQpNaWdyYW50IGdlbmVyYXRpb25zIHNwbGl0Lg0KDQpgYGB7ciBhbm92YSBzaXplIGFuZCBob21vZ2VuZWl0eX0NCiMgQ29tcHV0ZSB0aGUgYW5hbHlzaXMgb2YgdmFyaWFuY2UNCnJlc19hb3Zfc2l6ZSA8LSBhb3YobG9nKG1lYW4pIH4gbWlncmF0aW9uX2JhY2tncm91bmRfZmFjLCBkYXRhID0gaW1wKQ0KDQojIFN1bW1hcnkgb2YgdGhlIGFuYWx5c2lzDQpyZXN1bHRzX3NpemUgPC0gc3VtbWFyeShyZXNfYW92X3NpemUpDQoNCiNsb29rIGF0IGdyb3VwIGRpZmZlcmVuY2VzDQphbm92YV9kaWZmX2RmX3NpemUgIDwtIGFzX3RpYmJsZShUdWtleUhTRChyZXNfYW92X3NpemUpJG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYykgJT4lIA0KICBtdXRhdGUoRGlmZmVyZW5jZSA9IHJvdy5uYW1lcyhUdWtleUhTRChyZXNfYW92X3NpemUpJG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYykpICU+JSANCiAgc2VsZWN0KDUsIDE6NCkgJT4lIA0KICBzZWxlY3QoRGlmZmVyZW5jZSxkaWZmLCBgcCBhZGpgKSAlPiUgDQogIHJlbmFtZSh2YWx1ZSA9IGRpZmYsDQogICAgICAgICBwID0gYHAgYWRqYCkgJT4lIA0KICBtdXRhdGUodmFyaWFibGUgPSAibG4oU2l6ZSkiKQ0KDQojIENvbXB1dGUgdGhlIGFuYWx5c2lzIG9mIHZhcmlhbmNlDQpyZXNfYW92X2hvbSA8LSBhb3YocGVyX2luZ3JvdXBfdyB+IG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYywgZGF0YSA9IGltcCkNCg0KIyBTdW1tYXJ5IG9mIHRoZSBhbmFseXNpcw0KcmVzdWx0c19ob20gPC0gc3VtbWFyeShyZXNfYW92X2hvbSkNCg0KI2xvb2sgYXQgZ3JvdXAgZGlmZmVyZW5jZXMNCmFub3ZhX2RpZmZfZGZfaG9tICA8LSBhc190aWJibGUoVHVrZXlIU0QocmVzX2Fvdl9ob20pJG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYykgJT4lIA0KICBtdXRhdGUoRGlmZmVyZW5jZSA9IHJvdy5uYW1lcyhUdWtleUhTRChyZXNfYW92X2hvbSkkbWlncmF0aW9uX2JhY2tncm91bmRfZmFjKSkgJT4lIA0KICBzZWxlY3QoNSwgMTo0KSAlPiUgDQogIHNlbGVjdChEaWZmZXJlbmNlLCBkaWZmLCBgcCBhZGpgKSAlPiUgDQogIHJlbmFtZSh2YWx1ZSA9IGRpZmYsDQogICAgICAgICBwID0gYHAgYWRqYCkgJT4lIA0KICBtdXRhdGUodmFyaWFibGUgPSAiSG9tb2dlbmVpdHkiKQ0KDQojYWRkIHNpZy4gaW5kaWNhdG9yDQphbm92YV9kaWZmX2RmIDwtIGFub3ZhX2RpZmZfZGZfc2l6ZSAlPiUgDQogIGJpbmRfcm93cyhhbm92YV9kaWZmX2RmX2hvbSkgJT4lIA0KICBtdXRhdGUoc2lnID0gaWZlbHNlKHAgPCAwLjA1LCAxLCAwKSwNCiAgICAgICAgIHNpZ19mID0gaWZlbHNlKHNpZyA9PSAxLCAiKiIsICIiKSkNCg0KI2NyZWF0ZSBwbG90DQphbm92YV9kaWZmX2V4dGVuZGVkX3Bsb3QgPC0gYW5vdmFfZGlmZl9kZiAlPiUgDQogIG11dGF0ZShkaWZmX2ZhYyA9IGZhY3RvcihyZXAoMToxMCwyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IDE6MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCIxc3QgZ2VuIFRLWSAtIE5FRCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIybmQgZ2VuIFRLWSAtIE5FRCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIxc3QgZ2VuIE1PUiAtIE5FRCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIybmQgZ2VuIE1PUiAtIE5FRCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIybmQgZ2VuIFRLWSAtIDFzdCBnZW4gVEtZIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjFzdCBnZW4gTU9SIC0gMXN0IGdlbiBUS1kiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMm5kIGdlbiBNT1IgLSAxc3QgZ2VuIFRLWSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIxc3QgZ2VuIE1PUiAtIDJuZCBnZW4gVEtZIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjJuZCBnZW4gTU9SIC0gMm5kIGdlbiBUS1kiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMm5kIGdlbiBNT1IgLSAxc3QgZ2VuIE1PUiIpDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwNCiAgICAgICAgIGRpZmZfZmFjID0gZmN0X3JldihmY3RfcmVsZXZlbChkaWZmX2ZhYywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjFzdCBnZW4gVEtZIC0gTkVEIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjJuZCBnZW4gVEtZIC0gTkVEIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjFzdCBnZW4gTU9SIC0gTkVEIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjJuZCBnZW4gTU9SIC0gTkVEIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjJuZCBnZW4gVEtZIC0gMXN0IGdlbiBUS1kiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMm5kIGdlbiBNT1IgLSAxc3QgZ2VuIE1PUiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIxc3QgZ2VuIE1PUiAtIDFzdCBnZW4gVEtZIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjJuZCBnZW4gTU9SIC0gMXN0IGdlbiBUS1kiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMXN0IGdlbiBNT1IgLSAybmQgZ2VuIFRLWSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIybmQgZ2VuIE1PUiAtIDJuZCBnZW4gVEtZIikNCg0KICAgICAgICAgKSkgJT4lIA0KICBmaWx0ZXIoIWRpZmZfZmFjICVpbiUgYygiMXN0IGdlbiBNT1IgLSAxc3QgZ2VuIFRLWSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIybmQgZ2VuIE1PUiAtIDFzdCBnZW4gVEtZIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjFzdCBnZW4gTU9SIC0gMm5kIGdlbiBUS1kiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMm5kIGdlbiBNT1IgLSAybmQgZ2VuIFRLWSIpKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IHZhbHVlLCANCiAgICAgICAgICAgICB5ID0gZGlmZl9mYWMpKSArDQogIGdlb21fY29sKGFlcyhmaWxsID0gdmFyaWFibGUsDQogICAgICAgICAgIGNvbG91ciA9IHZhcmlhYmxlKSwNCiAgICAgICAgICAgYWxwaGEgPSAwLjYpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHNpZ19mKSwNCiAgICAgICAgICAgIHNpemUgPSA2LA0KICAgICAgICAgICAgaGp1c3QgPSAxKSArDQogIGZhY2V0X3dyYXAodmFycyh2YXJpYWJsZSksDQogICAgICAgICAgICAgc2NhbGVzID0gImZyZWVfeCIpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICBzY2FsZV9maWxsX3ZpcmlkaXNfZChvcHRpb24gPSAiRCIpICsNCiAgc2NhbGVfY29sb3VyX3ZpcmlkaXNfZChvcHRpb24gPSAiRCIpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDEpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoaGp1c3QgPSAxKSwNCiAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiYmxhY2siKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiYmxhY2siKSkgKw0KICBsYWJzKHkgPSAiIiwNCiAgICAgICB4ID0gIkNvZWZmaWNpZW50IikNCiNjcmVhdGUgY29tYmluZWQgcGxvdA0KYW5vdmFfcGxvdCA8LSBhbm92YV9kaWZmX3NpbXBsZV9wbG90ICsgDQphbm92YV9kaWZmX2V4dGVuZGVkX3Bsb3QgKw0KICBwbG90X2Fubm90YXRpb24odGFnX2xldmVscyA9J2EnLA0KICAgICAgICAgICAgICAgICAgdGFnX3ByZWZpeCA9ICcoJywNCiAgICAgICAgICAgICAgICAgIHRhZ19zdWZmaXggPSAnKScsDQogICAgICAgICAgICAgICAgICBjYXB0aW9uID0gIiogcCA8IDAuMDUiKSArDQogIHBsb3RfbGF5b3V0KG5jb2wgPSAxLA0KICAgICAgICAgICAgICBoZWlnaHRzID0gYygxLDMpKQ0KDQojc2hvdyBmaW5hbCBwbG90DQphbm92YV9wbG90DQoNCiNzYXZlIGZpbmFsIGFub3ZhIHBsb3QNCmdnc2F2ZShhbm92YV9wbG90LA0KICAgICAgIGZpbGUgPSAiZGF0YV9hbmFseXNpcy9wbG90cy9yZXN1bHRzL2Fub3ZhX3Bsb3QuanBnIiwNCiAgICAgICB3aWR0aCA9IDcsDQogICAgICAgaGVpZ2h0ID0gNSwNCiAgICAgICBkcGkgPSAzMjApDQoNCiAgDQpgYGANCg0KIyMgUG9vbGVkIHJlZ3Jlc3Npb24gbW9kZWwgDQoNClJlY3JlYXRlIHRoZSBwb29sZWQgcmVncmVzc2lvbiBtb2RlbA0KDQpgYGB7ciBwb29sZWQgbW9kZWwgc2l6ZX0NCiNlc3RpbWF0ZSBzaXplIG1vZGVsDQpzaXplX3Bvb2xlZF9tb2RlbCA8LSBpbXAgJT4lICANCiAgZmlsdGVyKGdlbmRlciAhPSAiT3RoZXIiKSAlPiUgDQogIG11dGF0ZSgNCiAgbWVhbiA9IGFzLmludGVnZXIobWVhbikNCikgJT4lDQogIGxtKA0KICAgIGxvZyhtZWFuKSB+IG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyArDQogICAgICAgIGFnZSArDQogICAgICAgIGdlbmRlciArIA0KICAgICAgICBlZHVjYXRpb25fcmVjb2RlZF9udW1lcmljICsNCiAgICAgICAgcGFydG5lciArIA0KICAgICAgICBpbl9lZHVjYXRpb24gKw0KICAgICAgICBwYWlkX3dvcmsgKw0KICAgICAgICByZWxfZmFjXzIgKw0KICAgICAgICBwZXJfTldfbWlnX2FfcGM0ICsNCiAgICAgICAgd296X3BjNCArDQogICAgICAgIElud29uZXJfcGM0ICsNCiAgICAgICAgdGhlcm1fb3V0Z3JvdXBfZGlmZiArDQogICAgICB0aGVybV9kaWZmX21pc3NpbmcsDQogICAgZGF0YSA9IC4NCiAgKQ0KDQojZXN0aWFtdGUgaG9tb2dlbmVpdHkgbW9kZWwNCmhvbV9wb29sZWRfbW9kZWwgPC0gaW1wICU+JQ0KICBmaWx0ZXIoZ2VuZGVyICE9ICJPdGhlciIpICU+JQ0KICBsbSgNCiAgICBwZXJfaW5ncm91cF93IH4gbWlncmF0aW9uX2JhY2tncm91bmRfZmFjICsNCiAgICAgIGFnZSArDQogICAgICBnZW5kZXIgKw0KICAgICAgZWR1Y2F0aW9uX3JlY29kZWRfbnVtZXJpYyArDQogICAgICBwYXJ0bmVyICsNCiAgICAgIGluX2VkdWNhdGlvbiArDQogICAgICBwYWlkX3dvcmsgKw0KICAgICAgcmVsX2ZhY18yICsNCiAgICAgIHBlcl9OV19taWdfYV9wYzQgKw0KICAgICAgd296X3BjNCArDQogICAgICBJbndvbmVyX3BjNCArDQogICAgICB0aGVybV9vdXRncm91cF9kaWZmICsNCiAgICAgIHRoZXJtX2RpZmZfbWlzc2luZywNCiAgICBkYXRhID0gLg0KICApDQoNCiNjcmVhdGUgdGFibGUNCnNqUGxvdDo6dGFiX21vZGVsKHNpemVfcG9vbGVkX21vZGVsLA0KICAgICAgICAgICAgICAgICAgaG9tX3Bvb2xlZF9tb2RlbCwNCiAgICAgICAgICBwcmVkLmxhYmVscyA9IGMoDQogICAgICAgICAgICAiQ29uc3RhbnQiLA0KICAgICAgICAgICAgIkdyb3VwWzFzdCBnZW4gVHVya2lzaC1EdXRjaF0iLA0KICAgICAgICAgICAgIkdyb3VwWzJuZCBnZW4gVHVya2lzaC1EdXRjaF0iLA0KICAgICAgICAgICAgIkdyb3VwWzFzdCBnZW4gTW9yb2NjYW4tRHV0Y2hdIiwNCiAgICAgICAgICAgICJHcm91cFsybmQgZ2VuIE1vcm9jY2FuLUR1dGNoXSIsDQogICAgICAgICAgICAiQWdlIiwNCiAgICAgICAgICAgICJHZW5kZXIgW0ZlbmFsZV0iLA0KICAgICAgICAgICAgIkVkdWNhdGlvbmFsIGF0dGFpbm1lbnQiLA0KICAgICAgICAgICAgIlBhcnRuZXJbSGFzIGEgcGFydG5lcl0iLA0KICAgICAgICAgICAgIlBhaWQgd29yayIsDQogICAgICAgICAgICAiQ3VycmVudGx5IGluIGVkdWNhdGlvbiIsDQogICAgICAgICAgICAiUmVsaWdpb3VzIGF0dGVuZGFuY2VbMS0yIHllYXJdIiwNCiAgICAgICAgICAgICJSZWxpZ2lvdXMgYXR0ZW5kYW5jZVszLTExIGEgeWVhcl0iLA0KICAgICAgICAgICAgIlJlbGlnaW91cyBhdHRlbmRhbmNlW09uY2UgYSBtb250aCBvciBtb3JlXSIsDQogICAgICAgICAgICAiTmVpZ2hib3Job29kOiAlIE5vbi13ZXN0ZXJuIG1pZ3JhbnQiLA0KICAgICAgICAgICAgIk5laWdoYm9yaG9vZDogbWVhbiBwcm9wZXJ0eSB2YWx1YXRpb24iLA0KICAgICAgICAgICAgIk5laWdoYm9yaG9vZDogIyBpbmhhYml0YW50cyIsDQogICAgICAgICAgICAiT3V0Z3JvdXAgYXR0aXR1ZGUiLA0KICAgICAgICAgICAgIk91dGdyb3VwIGF0dGl0dWRlIG1pc3NpbmciDQogICAgICAgICAgICApLA0KICAgICAgICAgIGRpZ2l0cyA9IDMsDQogICAgICAgICAgc2hvdy5jaSA9IEYsDQogICAgICAgICAgc2hvdy5zdGF0ID0gVCwNCiAgICAgICAgICBjb2xsYXBzZS5zZSAgPSBGLA0KICAgICAgICAgIGNvbC5vcmRlciA9IGMoImVzdCIsICJzdGF0IiksDQogICAgICAgICAgcC5zdHlsZSA9ICJzdGFycyINCiAgICAgICAgICAjZmlsZSA9ICJyZWcuZG9jIg0KICAgICAgICAgICkNCmBgYA0KDQoNCiMgRGVjb21wb3NpdGlvbiBhbmFseXNpcw0KDQojIyBEZWNvbXBvc2l0aW9uIGRhdGFwcmVwDQoNCkNyZWF0ZSBzZXBhcmF0ZSBkZiBmcmFtZXMgdG8gdXNlIGluIHRoZSBkZWNvbXBvc2l0aW9uIGFuYWx5c2VzLg0KDQpgYGB7ciBvYXhhY2EgZGF0YSBwcmVwfQ0KI0R1dGNoIC0gVEtZIDFzdCBnZW4NCmRhdGFfZHV0Y2hfdHVya2lzaF8xc3QgPC0gaW1wICU+JQ0KICBmaWx0ZXIoZ2VuZGVyICE9ICJPdGhlciIpICU+JSANCiAgZmlsdGVyKG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyAlaW4lIGMoIkR1dGNoIE1ham9yaXR5IiwgIjFzdCBnZW4gVHVya2lzaC1EdXRjaCIpKSAlPiUgDQogIG11dGF0ZSh6ID0gaWZfZWxzZShtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIkR1dGNoIE1ham9yaXR5IiwgMSwgMCkNCiAgICAgICAgICkgDQoNCiNEdXRjaCAtIFRLWSAybmQgZ2VuDQpkYXRhX2R1dGNoX3R1cmtpc2hfMm5kIDwtIGltcCAlPiUNCiAgZmlsdGVyKGdlbmRlciAhPSAiT3RoZXIiKSAlPiUgDQogIGZpbHRlcihtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgJWluJSBjKCJEdXRjaCBNYWpvcml0eSIsICIybmQgZ2VuIFR1cmtpc2gtRHV0Y2giKSkgJT4lIA0KICBtdXRhdGUoeiA9IGlmX2Vsc2UobWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICJEdXRjaCBNYWpvcml0eSIsIDEsIDApDQogICAgICAgICApIA0KDQojRHV0Y2ggLSBtb3JvY2NhbiAybmQgZ2VuDQpkYXRhX2R1dGNoX21vcm9jY2FuXzJuZCA8LSBpbXAgJT4lDQogIGZpbHRlcihnZW5kZXIgIT0gIk90aGVyIikgJT4lIA0KICBmaWx0ZXIobWlncmF0aW9uX2JhY2tncm91bmRfZmFjICVpbiUgYygiRHV0Y2ggTWFqb3JpdHkiLCAiMm5kIGdlbiBNb3JvY2Nhbi1EdXRjaCIpKSAlPiUgDQogIG11dGF0ZSh6ID0gaWZfZWxzZShtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIkR1dGNoIE1ham9yaXR5IiwgMSwgMCkNCiAgICAgICAgICkgDQoNCiNEdXRjaCAtIG1vcm9jY2FuIDFzdCBnZW4NCmRhdGFfZHV0Y2hfbW9yb2NjYW5fMXN0IDwtIGltcCAlPiUNCiAgZmlsdGVyKGdlbmRlciAhPSAiT3RoZXIiKSAlPiUgDQogIGZpbHRlcihtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgJWluJSBjKCJEdXRjaCBNYWpvcml0eSIsICIxc3QgZ2VuIE1vcm9jY2FuLUR1dGNoIikpICU+JSANCiAgbXV0YXRlKHogPSBpZl9lbHNlKG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyA9PSAiRHV0Y2ggTWFqb3JpdHkiLCAxLCAwKQ0KICAgICAgICAgKSANCg0KI1R1cmtpc2ggZ2VuZXJhdGlvbiBkaWZmZXJlbmNlDQpkYXRhX3R1cmtpc2hfZGlmZiA8LSBpbXAgJT4lDQogIGZpbHRlcihnZW5kZXIgIT0gIk90aGVyIikgJT4lIA0KICBmaWx0ZXIobWlncmF0aW9uX2JhY2tncm91bmRfZmFjICVpbiUgYygiMXN0IGdlbiBUdXJraXNoLUR1dGNoIiwgIjJuZCBnZW4gVHVya2lzaC1EdXRjaCIpKSAlPiUgDQogIG11dGF0ZSh6ID0gaWZfZWxzZShtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIjJuZCBnZW4gVHVya2lzaC1EdXRjaCIsIDEsIDApDQogICAgICAgICApIA0KDQojTW9yb2NjYW4gZ2VuZXJhdGlvbiBkaWZmZXJlbmNlDQpkYXRhX21vcm9jY2FuX2RpZmYgPC0gaW1wICU+JQ0KICBmaWx0ZXIoZ2VuZGVyICE9ICJPdGhlciIpICU+JSANCiAgZmlsdGVyKG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyAlaW4lIGMoIjFzdCBnZW4gTW9yb2NjYW4tRHV0Y2giLCAiMm5kIGdlbiBNb3JvY2Nhbi1EdXRjaCIpKSAlPiUgDQogIG11dGF0ZSh6ID0gaWZfZWxzZShtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIjJuZCBnZW4gTW9yb2NjYW4tRHV0Y2giLCAxLCAwKQ0KICAgICAgICAgKQ0KDQojRHV0Y2ggdHVya2lzaCBtaW5vcml0eQ0KZGF0YV9kdXRjaF90dXJraXNoIDwtIGltcCAlPiUNCiAgZmlsdGVyKGdlbmRlciAhPSAiT3RoZXIiKSAlPiUgDQogIGZpbHRlcihtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgJWluJSBjKCJEdXRjaCBNYWpvcml0eSIsICIxc3QgZ2VuIFR1cmtpc2gtRHV0Y2giLCIybmQgZ2VuIFR1cmtpc2gtRHV0Y2giKSkgJT4lIA0KICBtdXRhdGUoeiA9IGlmX2Vsc2UobWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICJEdXRjaCBNYWpvcml0eSIsIDEsIDApDQogICAgICAgICApIA0KDQojRHV0Y2ggbW9yb2NjYW4gbWlub3JpdHkNCmRhdGFfZHV0Y2hfbW9yb2NjYW4gPC0gaW1wICU+JQ0KICBmaWx0ZXIoZ2VuZGVyICE9ICJPdGhlciIpICU+JSANCiAgZmlsdGVyKG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyAlaW4lIGMoIkR1dGNoIE1ham9yaXR5IiwgIjFzdCBnZW4gTW9yb2NjYW4tRHV0Y2giLCIybmQgZ2VuIE1vcm9jY2FuLUR1dGNoIikpICU+JSANCiAgbXV0YXRlKHogPSBpZl9lbHNlKG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyA9PSAiRHV0Y2ggTWFqb3JpdHkiLCAxLCAwKQ0KICAgICAgICAgKSANCg0KI2NvbWJpbmUgZWxlbWVudHMgaW4gbGlzdA0KZGF0YV9saXN0IDwtIGxpc3QoZGF0YV9kdXRjaF90dXJraXNoXzFzdCwNCiAgICAgICAgICAgICAgICAgIGRhdGFfZHV0Y2hfdHVya2lzaF8ybmQsDQogICAgICAgICAgICAgICAgICBkYXRhX2R1dGNoX21vcm9jY2FuXzJuZCwNCiAgICAgICAgICAgICAgICAgIGRhdGFfZHV0Y2hfbW9yb2NjYW5fMXN0LA0KICAgICAgICAgICAgICAgICAgZGF0YV90dXJraXNoX2RpZmYsDQogICAgICAgICAgICAgICAgICBkYXRhX21vcm9jY2FuX2RpZmYsDQogICAgICAgICAgICAgICAgICBkYXRhX2R1dGNoX3R1cmtpc2gsDQogICAgICAgICAgICAgICAgICBkYXRhX2R1dGNoX21vcm9jY2FuKQ0KDQpgYGANCg0KIyMgU2l6ZSBsbg0KIyMjIERlY29tcG9zaXRpb24gZXN0aW1hdGlvbg0KYGBge3Igb2F4YWNhIGZvcm11bGEgc2l6ZX0NCiNzZXQgc2VlZA0Kc2V0LnNlZWQoMjcwMikNCg0KI2NyZWF0ZSB0aGUgYW5hbHlzaXMgZnVuY3Rpb24NCm9heGFjYV9zcGVjX2YgPC0gZnVuY3Rpb24oeCkgew0KICByZXN1bHRzIDwtIHggICU+JQ0KICBvYXhhY2EoDQogICAgZm9ybXVsYSA9IGxvZyhtZWFuKSB+IGFnZSArDQogICAgICBnZW5kZXIgKw0KICAgICAgZWR1Y2F0aW9uX3JlY29kZWRfbnVtZXJpYyArDQogICAgICBwYXJ0bmVyICsNCiAgICAgIGluX2VkdWNhdGlvbiArDQogICAgICBwYWlkX3dvcmsgKw0KICAgICAgcmVsX2ZhY18yICsNCiAgICAgIHBlcl9OV19taWdfYV9wYzQgKw0KICAgICAgd296X3BjNCArDQogICAgICBJbndvbmVyX3BjNCArDQogICAgICB0aGVybV9vdXRncm91cF9kaWZmIHwgeiwNCiAgcmVnLmZ1biA9IGxtLA0KICBkYXRhID0gLikNCn0NCg0KI2NyZWF0ZSBtb2RlbCBsaXN0DQpvYXhhY2FfbW9kZWxfbGlzdCAgPC0gbWFwKC54ID0gZGF0YV9saXN0LCANCiAgICAuZiA9IH4gb2F4YWNhX3NwZWNfZih4ID0gLngpKQ0KDQoNCiNjcmVhdGUgZW1wdHkgbGlzdHMgdG8gc3RvcmUgaW5mb3JtYXRpb24gaW4NCnByZWRpY3RlZF9saXN0IDwtIGxpc3QoKQ0KdHdvX2ZvbGRfcmVzdWx0c19wbG90X2xpc3QgPC0gbGlzdCgpDQp0d29fZm9sZF9yZXN1bHRzX3RhYmxlX2xpc3QgPC0gbGlzdCgpDQp0d29fZm9sZF92YXJpYWJsZXNfbGlzdCA8LSBsaXN0KCkNCg0KDQojc2VsZWN0IGNvcnJlY3QgaW5mb3JtYXRpb24gZnJvbSB0aGUgbW9kZWwgb2JqZWN0IGFuZCBzdG9yZSBpbiBsaXN0DQpmb3IoaSBpbiAxOmxlbmd0aChvYXhhY2FfbW9kZWxfbGlzdCkpIHsgI2kgPSA4DQogIG1vZGVsX29iamVjdCA8LSBvYXhhY2FfbW9kZWxfbGlzdFtbaV1dDQogIA0KICAjZ2V0IHRoZSBwcmVkaWN0ZWQgbmV0d29yayBzaXplIG9mIGJvdGggZ3JvdXBzDQogIHByZWRpY3RlZF9saXN0W1tpXV0gPC0gdGliYmxlKHlfYSA9IG1vZGVsX29iamVjdCR5JHkuQSwNCiAgeV9iID0gbW9kZWxfb2JqZWN0JHkkeS5CLA0KICB5X2RpZmYgPSBtb2RlbF9vYmplY3QkeSR5LmRpZmYsDQogIG1vZGVsID0gaSkNCiAgDQogICNnZXQgdGhlIHJlc3VsdHMgb2YgdGhlIHR3b2ZvbGQgYW5hbHlzaXMgZm9yIHRoZSBwbG90DQogIHR3b19mb2xkX3Jlc3VsdHNfcGxvdF9saXN0W1tpXV0gPC0gbW9kZWxfb2JqZWN0JHR3b2ZvbGQkb3ZlcmFsbCAlPiUgDQogICAgYXNfdGliYmxlKCkgJT4lIA0KICAgIGZpbHRlcihncm91cC53ZWlnaHQgPT0gMSkgJT4lIA0KICAgIHJlbmFtZShjb2VmX2V4cGxhaW5lZCA9IGBjb2VmKGV4cGxhaW5lZClgLA0KICAgICAgICAgICBzZV9leHBsYWluZWQgPSBgc2UoZXhwbGFpbmVkKWAsDQogICAgICAgICAgIGNvZWZfdW5leHBsYWluZWQgPSBgY29lZih1bmV4cGxhaW5lZClgLA0KICAgICAgICAgICBzZV91bmV4cGxhaW5lZCA9IGBzZSh1bmV4cGxhaW5lZClgLA0KICAgICAgICAgICBjb2VmX3VuZXhwbGFpbmVkLmEgPSBgY29lZih1bmV4cGxhaW5lZCBBKWAsDQogICAgICAgICAgIHNlX3VuZXhwbGFpbmVkLmEgPSBgc2UodW5leHBsYWluZWQgQSlgLA0KICAgICAgICAgICBjb2VmX3VuZXhwbGFpbmVkLmIgPSBgY29lZih1bmV4cGxhaW5lZCBCKWAsDQogICAgICAgICAgIHNlX3VuZXhwbGFpbmVkLmIgPSBgc2UodW5leHBsYWluZWQgQilgKSAlPiUgDQogICAgc2VsZWN0KC1ncm91cC53ZWlnaHQpICU+JSANCiAgICBzZWxlY3QoMTo4KSAlPiUgDQogICAgcGl2b3RfbG9uZ2VyKGRhdGEgPSAuLA0KICAgICAgICAgICAgICAgICBjb2xzID0gMTo4LA0KICAgICAgICAgICAgICAgICBuYW1lc190byA9IGMoInZhciIsICJuYW1lIiksDQogICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ2YWx1ZSIsDQogICAgICAgICAgICAgICAgIG5hbWVzX3NlcCA9ICJfIikgJT4lIA0KICAgIG11dGF0ZShtb2RlbCA9IGkpDQogIA0KICAjZ2V0IHRoZSByZXN1bHRzIG9mIHRoZSB0d29mb2xkIGFuYWx5c2lzIGZvciB0aGUgdGFibGUNCiAgdHdvX2ZvbGRfcmVzdWx0c190YWJsZV9saXN0W1tpXV0gPC0gbW9kZWxfb2JqZWN0JHR3b2ZvbGQkb3ZlcmFsbCAlPiUgDQogICAgYXNfdGliYmxlKCkgJT4lIA0KICAgIGZpbHRlcihncm91cC53ZWlnaHQgPT0gLTIpICU+JSANCiAgICByZW5hbWUoY29lZl9leHBsYWluZWQgPSBgY29lZihleHBsYWluZWQpYCwNCiAgICAgICAgICAgc2VfZXhwbGFpbmVkID0gYHNlKGV4cGxhaW5lZClgLA0KICAgICAgICAgICBjb2VmX3VuZXhwbGFpbmVkID0gYGNvZWYodW5leHBsYWluZWQpYCwNCiAgICAgICAgICAgc2VfdW5leHBsYWluZWQgPSBgc2UodW5leHBsYWluZWQpYCwNCiAgICAgICAgICAgY29lZl91bmV4cGxhaW5lZC5hID0gYGNvZWYodW5leHBsYWluZWQgQSlgLA0KICAgICAgICAgICBzZV91bmV4cGxhaW5lZC5hID0gYHNlKHVuZXhwbGFpbmVkIEEpYCwNCiAgICAgICAgICAgY29lZl91bmV4cGxhaW5lZC5iID0gYGNvZWYodW5leHBsYWluZWQgQilgLA0KICAgICAgICAgICBzZV91bmV4cGxhaW5lZC5iID0gYHNlKHVuZXhwbGFpbmVkIEIpYCkgJT4lIA0KICAgIHNlbGVjdCgtZ3JvdXAud2VpZ2h0KSAlPiUgDQogICAgc2VsZWN0KDE6OCkNCiAgDQogICNnZXQgdGhlIHJlc3VsdHMgb2YgdGhlIHR3b2ZvbGQgYW5hbHlzaXMgZm9yIHRoZSB2YXJpYWJsZSBwbG90DQogIHR3b19mb2xkX3ZhcmlhYmxlc19saXN0W1tpXV0gPC0gbW9kZWxfb2JqZWN0JHR3b2ZvbGQkdmFyaWFibGVzW1s2XV0gJT4lIA0KICAgIGFzX3RpYmJsZSgpICU+JSANCiAgICBtdXRhdGUodmFyaWFibGVzID0gcm93Lm5hbWVzKG1vZGVsX29iamVjdCR0d29mb2xkJHZhcmlhYmxlc1tbNl1dKSkgJT4lIA0KICAgIGZpbHRlcihncm91cC53ZWlnaHQgPT0gLTIpICU+JSANCiAgICBzZWxlY3QoMTAsMjo1KSAlPiUgDQogICAgbXV0YXRlKG1vZGVsID0gaSkNCn0NCg0KDQpgYGANCg0KDQojIyMgVHdvZm9sZCBkZWNvbXBvc2l0aW9uIHJlc3VsdHMgdGFibGUNCg0KYGBge3IgcmVzdWx0cyB0YWJsZXMgc2l6ZX0NCiNleHRyYWN0IHR3b2ZvbGQgaW5mb3JtYXRpb24NCnR3b2ZvbGRfdGFibGUgPC0gdHdvX2ZvbGRfcmVzdWx0c190YWJsZV9saXN0ICU+JSANCiAgYmluZF9yb3dzKCkgJT4lIA0KICBmaWx0ZXIocm93X251bWJlcigpPiA0KSAlPiUgDQogIG11dGF0ZShtb2RlbCA9IGZhY3RvcigxOjQsDQogICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSAxOjQsDQogICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiMXN0IGdlbiBUdXJraXNoLUR1dGNoIC0gIDJuZCBnZW4gVHVya2lzaC1EdXRjaCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICIxc3QgZ2VuIE1vcm9jY2FuLUR1dGNoIC0gIDJuZCBnZW4gTW9yb2NjYW4tRHV0Y2giLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiVHVya2lzaC1EdXRjaCAtICBEdXRjaC1NYWpvcml0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJNb3JvY2Nhbi1EdXRjaCAtICBEdXRjaC1NYWpvcml0eSINCiAgICAgICAgICAgICAgICAgICAgICAgICkpKSAlPiUgDQogIHNlbGVjdCg5LDE6NCkgJT4lIA0KICBtdXRhdGUoel9leHBsYWluZWQgPSBjb2VmX2V4cGxhaW5lZC9zZV9leHBsYWluZWQsDQogICAgICAgICB6X3VuZXhwbGFpbmVkID0gY29lZl91bmV4cGxhaW5lZC9zZV91bmV4cGxhaW5lZCkgJT4lIA0KICBzZWxlY3QobW9kZWwsIGNvZWZfZXhwbGFpbmVkLCB6X2V4cGxhaW5lZCwgY29lZl91bmV4cGxhaW5lZCwgel91bmV4cGxhaW5lZCkNCg0KcHJlZGljdGVkX2RmIDwtIHByZWRpY3RlZF9saXN0ICU+JSANCiAgYmluZF9yb3dzKCkgJT4lIA0KICBmaWx0ZXIobW9kZWwgPiA0KSAlPiUgDQogIHNlbGVjdCgxOjMpDQoNCiNzaG93IHJlc3VsdHMgaW4gdGFibGUNCnR3b2ZvbGRfdGFibGUgJT4lIA0KICBiaW5kX2NvbHMocHJlZGljdGVkX2RmKSAlPiUgDQogIHNlbGVjdCgxLDY6OCwgMjo1KSAlPiUgDQogIGtibChkaWdpdHMgPSAzLA0KICAgICAgYWxpZ24gPSAnbCcpICU+JSANCiAga2FibGVfcGFwZXIoKQ0KDQoNCg0KYGBgDQoNCiMjIyBUd29mb2xkIHBhbmVsIHBsb3QNCg0KYGBge3IgcGFuZWwgcGxvdCBzaXplLCBmaWcud2lkdGg9MTIsZmlnLmhlaWdodCA9IDh9DQojY3JlYXRlIHBsb3QgZGYNCnZhcmlhYmxlc19wbG90X2RmIDwtIHR3b19mb2xkX3ZhcmlhYmxlc19saXN0ICU+JSANCiAgYmluZF9yb3dzKCkgJT4lIA0KICBmaWx0ZXIobW9kZWwgPiA0KSAlPiUgDQogIG11dGF0ZShtb2RlbCA9IGZhY3Rvcihtb2RlbCwgDQogICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSA1OjgsDQogICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiVHVya2lzaC1EdXRjaCAxc3QgZ2VuIC0gMm5kIGdlbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJNb3JvY2Nhbi1EdXRjaCAxc3QgZ2VuIC0gMm5kIGdlbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJUdXJraXNoLUR1dGNoIC0gIER1dGNoLU1ham9yaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIk1vcm9jY2FuLUR1dGNoIC0gIER1dGNoLU1ham9yaXR5Ig0KICAgICAgICAgICAgICAgICAgICAgICAgKSkpICU+JSANCiAgcmVuYW1lKGNvZWZfZXhwbGFpbmVkID0gYGNvZWYoZXhwbGFpbmVkKWAsDQogICAgICAgICAgIHNlX2V4cGxhaW5lZCA9IGBzZShleHBsYWluZWQpYCwNCiAgICAgICAgICAgY29lZl91bmV4cGxhaW5lZCA9IGBjb2VmKHVuZXhwbGFpbmVkKWAsDQogICAgICAgICAgIHNlX3VuZXhwbGFpbmVkID0gYHNlKHVuZXhwbGFpbmVkKWApICU+JQ0KICBwaXZvdF9sb25nZXIoZGF0YSA9IC4sDQogICAgICAgICAgICAgICAgIGNvbHMgPSAyOjUsDQogICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gYygidmFyIiwgIm5hbWUiKSwNCiAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInZhbHVlIiwNCiAgICAgICAgICAgICAgICAgbmFtZXNfc2VwID0gIl8iKSAlPiUgDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSB2YXIsDQogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gdmFsdWUpICU+JSANCiAgbXV0YXRlKGFic196ID0gYWJzKGNvZWYvc2UpLA0KICAgICAgICAgc2lnID0gaWZlbHNlKGFic196ID4gMS45NSwgMSwgMCksDQogICAgICAgICBzaWdfZiA9IGZhY3RvcihzaWcsDQogICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSAwOjEsDQogICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCIiLCAiKiIpKSkNCg0KI2NyZWF0ZSB2ZWN0b3IgdG8gZmlsdGVyIHZhcmlhYmxlcw0KaW5kZXBfbmFtZXMgPC0gYygNCiAgInJlbF9mYWNfMk1vbnRobHkgb3IgbW9yZSIsDQogICJyZWxfZmFjXzIzLTExIFllYXIiLA0KICAicmVsX2ZhY18yMS0yIFllYXIiLA0KICAicGFpZF93b3JrIiwNCiAgImluX2VkdWNhdGlvbiIsDQogICJwZXJfTldfbWlnX2FfcGM0IiwNCiAgIklud29uZXJfcGM0IiwNCiAgImVkdWNhdGlvbl9yZWNvZGVkX251bWVyaWMiLA0KICAidGhlcm1fb3V0Z3JvdXBfZGlmZiIsDQogICJhZ2UiLA0KICAicGFydG5lciIsDQogICJnZW5kZXJGZW1hbGUiLA0KICAid296X3BjNCIpDQoNCiNjcmVhdGUgcGxvdA0KdmFyaWFibGVzX2RlY29tcF9zaXplX3Bsb3QgPC0gdmFyaWFibGVzX3Bsb3RfZGYgJT4lICNkYXRhcHJlcA0KICBmaWx0ZXIodmFyaWFibGVzICVpbiUgaW5kZXBfbmFtZXMpICU+JQ0KICBtdXRhdGUoDQogICAgdmFyX2ZhYyA9IGNhc2Vfd2hlbigNCiAgICAgIHZhcmlhYmxlcyA9PSAicGFpZF93b3JrIiB+IDEsDQogICAgICB2YXJpYWJsZXMgPT0gImluX2VkdWNhdGlvbiIgfiAyLA0KICAgICAgdmFyaWFibGVzID09ICJyZWxfZmFjXzIxLTIgWWVhciIgfiAzLA0KICAgICAgdmFyaWFibGVzID09ICJyZWxfZmFjXzIzLTExIFllYXIiIH4gNCwNCiAgICAgIHZhcmlhYmxlcyA9PSAicmVsX2ZhY18yTW9udGhseSBvciBtb3JlIiB+IDUsDQogICAgICB2YXJpYWJsZXMgPT0gImVkdWNhdGlvbl9yZWNvZGVkX251bWVyaWMiIH4gNiwNCiAgICAgIHZhcmlhYmxlcyA9PSAiSW53b25lcl9wYzQiIH4gNywNCiAgICAgIHZhcmlhYmxlcyA9PSAicGVyX05XX21pZ19hX3BjNCIgfiA4LA0KICAgICAgdmFyaWFibGVzID09ICJ3b3pfcGM0IiB+IDksDQogICAgICB2YXJpYWJsZXMgPT0gInRoZXJtX291dGdyb3VwX2RpZmYiIH4gMTAsDQogICAgICB2YXJpYWJsZXMgPT0gImFnZSIgfiAxMSwNCiAgICAgIHZhcmlhYmxlcyA9PSAicGFydG5lciIgfiAxMiwNCiAgICAgIHZhcmlhYmxlcyA9PSAiZ2VuZGVyRmVtYWxlIiB+IDEzDQogICAgKSwNCiAgICB2YXJfZmFjID0gZmFjdG9yKA0KICAgICAgdmFyX2ZhYywNCiAgICAgIGxldmVscyA9IDE6MTMsDQogICAgICBsYWJlbHMgPSBjKA0KICAgICAgICAiUGFpZCB3b3JrIiwNCiAgICAgICAgIkN1cnJlbnRseSBpbiBlZHVjYXRpb24iLA0KICAgICAgICAiUmVsaWdpb3VzIGF0dGVuZGFuY2VbMS0yIHllYXJdIiwNCiAgICAgICAgIlJlbGlnaW91cyBhdHRlbmRhbmNlWzMtMTEgYSB5ZWFyXSIsDQogICAgICAgICJSZWxpZ2lvdXMgYXR0ZW5kYW5jZVtPbmNlIGEgbW9udGggb3IgbW9yZV0iLA0KICAgICAgICAiRWR1Y2F0aW9uYWwgYXR0YWlubWVudCIsDQogICAgICAgICJOZWlnaGJvdXJob29kOiAjIGluaGFiaXRhbnRzIiwNCiAgICAgICAgIk5laWdoYm91cmhvb2Q6IG1lYW4gcHJvcGVydHkgdmFsdWF0aW9uIiwNCiAgICAgICAgIk5laWdoYm91cmhvb2Q6ICUgbm9uLXdlc3Rlcm4gbWlncmFudCIsDQogICAgICAgICJPdXRncm91cCBhdHRpdHVkZXMiLA0KICAgICAgICAiQWdlIiwNCiAgICAgICAgIlBhcnRuZXJbbm8gcGFydG5lcl0iLA0KICAgICAgICAiR2VuZGVyW01hbGVdIg0KICAgICAgKQ0KICAgICkNCiAgKSAlPiUgI3Bsb3QNCiAgZ2dwbG90KGFlcyh4ID0gY29lZiwgeSA9IHZhcl9mYWMpKSArDQogIGdlb21fY29sKGFlcyhjb2xvdXIgPSBuYW1lLA0KICAgICAgICAgICAgIGZpbGwgPSBuYW1lKSwNCiAgICAgICAgICAgYWxwaGEgPSAwLjYpICsgDQogIGdlb21fZXJyb3JiYXIoYWVzKHhtaW4gPSBjb2VmIC0gKHNlKjEuOTYpLA0KICAgICAgICAgICAgICAgICAgICB4bWF4ID0gY29lZiArIChzZSoxLjk2KSkpICsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gc2lnX2YpLA0KICAgICAgICAgICAgaGp1c3QgPSAyLA0KICAgICAgICAgICAgc2l6ZSA9IDYpICsNCiAgZmFjZXRfZ3JpZChjb2xzID0gdmFycyhtb2RlbCksDQogICAgICAgICAgICAgcm93cyA9IHZhcnMobmFtZSkpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Qob3B0aW9uID0gIkQiKSArDQogIHNjYWxlX2NvbG91cl92aXJpZGlzX2Qob3B0aW9uID0gIkQiKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLA0KICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDEpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoaGp1c3QgPSAxKSwNCiAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiYmxhY2siKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiYmxhY2siKSkgKw0KICBsYWJzKHkgPSAiSW5kZXBlbmRlbnQgVmFyaWFibGVzIiwNCiAgICAgICB4ID0gIkNvZWZmaWNpZW50IiwNCiAgICAgICBjYXB0aW9uID0gIiogcCA8IDAuMDUiKQ0KDQojc2F2ZSBwbG90DQpnZ3NhdmUodmFyaWFibGVzX2RlY29tcF9zaXplX3Bsb3QsDQogICAgICAgIGZpbGUgPSAiZGF0YV9hbmFseXNpcy9wbG90cy9yZXN1bHRzL3ZhcmlhYmxlc19kZWNvbXBfc2l6ZV9wbG90LmpwZyIsDQogICAgICAgd2lkdGggPSAxMiwNCiAgICAgICBoZWlnaHQgPSA4LA0KICAgICAgIGRwaSA9IDMyMCkNCg0KI3Nob3cgcGxvdA0KdmFyaWFibGVzX2RlY29tcF9zaXplX3Bsb3QNCmBgYA0KDQoNCiMjIyBSZWdyZXNzaW9uIG1vZGVsIHJlc3VsdHMgcGVyIGdyb3VwDQoNCkFsbCAoc3ViKWdyb3Vwcw0KDQpgYGB7ciBkaWZmZXJlbnQgbW9kZWwgcmVzdWx0cyBzaXplfQ0KI2VzdGltYXRlIG1vZGVsIGZvciBkaWZmZXJlbnQgZ3JvdXBzDQpzaXplX3Bvb2xlZF9tb2RlbCA8LSBpbXAgJT4lDQogIGZpbHRlcihnZW5kZXIgIT0gIk90aGVyIikgJT4lDQogICBncm91cF9zcGxpdChtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMpICU+JQ0KICBtYXAoDQogICAgLnggPSAuLA0KICAgIC5mID0gfiBsbSgNCiAgICAgIGxvZyhtZWFuKSB+IGFnZSArDQogICAgICAgIGdlbmRlciArIA0KICAgICAgICBlZHVjYXRpb25fcmVjb2RlZF9udW1lcmljICsNCiAgICAgICAgcGFydG5lciArIA0KICAgICAgICBpbl9lZHVjYXRpb24gKw0KICAgICAgICBwYWlkX3dvcmsgKw0KICAgICAgICByZWxfZmFjXzIgKw0KICAgICAgICBwZXJfTldfbWlnX2FfcGM0ICsNCiAgICAgICAgd296X3BjNCArDQogICAgICAgIElud29uZXJfcGM0ICsNCiAgICAgICAgdGhlcm1fb3V0Z3JvdXBfZGlmZiwNCiAgICAgIGRhdGEgPSAueA0KICAgICkNCiAgKQ0KDQojU2hvdyByZXN1bHRzIGluIHRhYmxlDQpzalBsb3Q6OnRhYl9tb2RlbChzaXplX3Bvb2xlZF9tb2RlbCwNCiAgICAgICAgICBwcmVkLmxhYmVscyA9IGMoDQogICAgICAgICAgICAiQ29uc3RhbnQiLA0KICAgICAgICAgICAiQWdlIiwNCiAgICAgICAgICAgICJHZW5kZXIgW0ZlbmFsZV0iLA0KICAgICAgICAgICAgIkVkdWNhdGlvbmFsIGF0dGFpbm1lbnQiLA0KICAgICAgICAgICAgIlBhcnRuZXJbSGFzIGEgcGFydG5lcl0iLA0KICAgICAgICAgICAgIlBhaWQgd29yayIsDQogICAgICAgICAgICAiQ3VycmVudGx5IGluIGVkdWNhdGlvbiIsDQogICAgICAgICAgICAiUmVsaWdpb3VzIGF0dGVuZGFuY2VbMS0yIHllYXJdIiwNCiAgICAgICAgICAgICJSZWxpZ2lvdXMgYXR0ZW5kYW5jZVszLTExIGEgeWVhcl0iLA0KICAgICAgICAgICAgIlJlbGlnaW91cyBhdHRlbmRhbmNlW09uY2UgYSBtb250aCBvciBtb3JlXSIsDQogICAgICAgICAgICAiT3V0Z3JvdXAgYXR0aXR1ZGUiLA0KICAgICAgICAgICAgIk5laWdoYm9yaG9vZDogJSBub24td2VzdGVybiBtaWdyYW50IiwNCiAgICAgICAgICAgICJOZWlnaGJvcmhvb2Q6IG1lYW4gcHJvcGVydHkgdmFsdWF0aW9uIiwNCiAgICAgICAgICAgICJOZWlnaGJvcmhvb2Q6ICMgaW5oYWJpdGFudHMiDQogICAgICAgICAgICApLA0KICAgICAgICAgIGR2LmxhYmVscyA9IGMoIkR1dGNoIiwgIjFzdCBnZW4gVHVya2lzaCIsICIybmQgZ2VuIFR1cmtpc2giLCAiMXN0IGdlbiBNb3JvY2NhbiIsIjJuZCBnZW4gTW9yb2NjYW4iKSwNCiAgICAgICAgICBkaWdpdHMgPSAzLA0KICAgICAgICAgIHNob3cuY2kgPSBGLA0KICAgICAgICAgIHNob3cuc3RhdCA9IFQsDQogICAgICAgICAgY29sbGFwc2Uuc2UgID0gRiwNCiAgICAgICAgICBjb2wub3JkZXIgPSBjKCJlc3QiLCAic3RhdCIpDQogICAgICAgICAgI2ZpbGUgPSAicmVnLmRvYyINCiAgICAgICAgICApDQoNCmBgYA0KDQpPbmx5IG1ham9yIGdyb3Vwcy4NCg0KYGBge3IgZGlmZmVyZW50IG1vZGVsIHJlc3VsdHMgc2l6ZSBzaW1wbGV9DQpyZXN1bHRzX2xpc3QgPC0gaW1wICU+JQ0KICBmaWx0ZXIoZ2VuZGVyICE9ICJPdGhlciIpICU+JSANCiAgZ3JvdXBfc3BsaXQobWlncmF0aW9uX2JhY2tncm91bmRfc2ltcGxlX2ZhYykgJT4lDQogIG1hcCgNCiAgICAueCA9IC4sDQogICAgLmYgPSB+IGxtKA0KICAgICAgbG9nKG1lYW4pIH4gIGFnZSArDQogICAgICAgIGdlbmRlciArIA0KICAgICAgICBlZHVjYXRpb25fcmVjb2RlZF9udW1lcmljICsNCiAgICAgICAgdGhlcm1fb3V0Z3JvdXBfZGlmZiArDQogICAgICAgIHBhcnRuZXIgKyANCiAgICAgICAgaW5fZWR1Y2F0aW9uICsNCiAgICAgICAgcGFpZF93b3JrICsNCiAgICAgICAgcmVsX2ZhY18yICsNCiAgICAgICAgcGVyX05XX21pZ19hX3BjNCArDQogICAgICAgIHdvel9wYzQgKw0KICAgICAgICBJbndvbmVyX3BjNCwNCiAgICAgIGRhdGEgPSAueA0KICAgICkNCiAgKQ0KDQpzalBsb3Q6OnRhYl9tb2RlbChyZXN1bHRzX2xpc3QsDQogICAgICAgICAgcHJlZC5sYWJlbHMgPSBjKA0KICAgICAgICAgICAgIkNvbnN0YW50IiwNCiAgICAgICAgICAgICJBZ2UiLA0KICAgICAgICAgICAgIkdlbmRlciBbRmVuYWxlXSIsDQogICAgICAgICAgICAiRWR1Y2F0aW9uYWwgYXR0YWlubWVudCIsDQogICAgICAgICAgICAiUGFydG5lcltIYXMgYSBwYXJ0bmVyXSIsDQogICAgICAgICAgICAiUGFpZCB3b3JrIiwNCiAgICAgICAgICAgICJDdXJyZW50bHkgaW4gZWR1Y2F0aW9uIiwNCiAgICAgICAgICAgICJSZWxpZ2lvdXMgYXR0ZW5kYW5jZVsxLTIgeWVhcl0iLA0KICAgICAgICAgICAgIlJlbGlnaW91cyBhdHRlbmRhbmNlWzMtMTEgYSB5ZWFyXSIsDQogICAgICAgICAgICAiUmVsaWdpb3VzIGF0dGVuZGFuY2VbT25jZSBhIG1vbnRoIG9yIG1vcmVdIiwNCiAgICAgICAgICAgICJPdXRncm91cCBhdHRpdHVkZSIsDQogICAgICAgICAgICAiTmVpZ2hib3Job29kOiAlIG5vbi13ZXN0ZXJuIG1pZ3JhbnQiLA0KICAgICAgICAgICAgIk5laWdoYm9yaG9vZDogbWVhbiBwcm9wZXJ0eSB2YWx1YXRpb24iLA0KICAgICAgICAgICAgIk5laWdoYm9yaG9vZDogIyBpbmhhYml0YW50cyINCiAgICAgICAgICAgICksDQogICAgICAgICAgZHYubGFiZWxzID0gYygiRHV0Y2giLCJUdXJraXNoLUR1dGNoIiwgIk1vcm9jY2FuLUR1dGNoIiksDQogICAgICAgICAgZGlnaXRzID0gMywNCiAgICAgICAgICBzaG93LmNpID0gRiwNCiAgICAgICAgICBzaG93LnN0YXQgPSBULA0KICAgICAgICAgIGNvbGxhcHNlLnNlICA9IEYsDQogICAgICAgICAgY29sLm9yZGVyID0gYygiZXN0IiwgInN0YXQiKQ0KICAgICAgICAgICNmaWxlID0gInJlZy5kb2MiDQogICAgICAgICAgKQ0KDQpgYGANCg0KIyMgRXRobmljIGhvbW9nZW5laXR5DQoNCiMjIyBEZWNvbXBvc2l0aW9uIGVzdGltYXRpb24NCg0KYGBge3Igb2F4YWNhIGZvcm11bGEgaG9tb2dlbmVpdHkgfQ0KI3NldCBzZWVkDQpzZXQuc2VlZCgyNzAyKQ0KDQojY3JlYXRlIHRoZSBhbmFseXNpcyBmdW5jdGlvbg0Kb2F4YWNhX3NwZWNfZiA8LSBmdW5jdGlvbih4KSB7DQogIHJlc3VsdHMgPC0geCAgJT4lDQogIG9heGFjYSgNCiAgICBmb3JtdWxhID0gcGVyX2luZ3JvdXBfdyB+ICBhZ2UgKw0KICAgICAgICBnZW5kZXIgKyANCiAgICAgICAgZWR1Y2F0aW9uX3JlY29kZWRfbnVtZXJpYyArDQogICAgICAgIHRoZXJtX291dGdyb3VwX2RpZmYgKw0KICAgICAgICBwYXJ0bmVyICsgDQogICAgICAgIGluX2VkdWNhdGlvbiArDQogICAgICAgIHBhaWRfd29yayArDQogICAgICAgIHJlbF9mYWNfMiArDQogICAgICAgIHBlcl9OV19taWdfYV9wYzQgKw0KICAgICAgICB3b3pfcGM0ICsNCiAgICAgICAgSW53b25lcl9wYzQgfCB6ICwNCiAgcmVnLmZ1biA9IGxtLA0KICBkYXRhID0gLikNCn0NCg0KI2NyZWF0ZSBtb2RlbCBsaXN0DQpvYXhhY2FfbW9kZWxfbGlzdF9ob21vZ2VuZWl0eSAgPC0gbWFwKC54ID0gZGF0YV9saXN0LCANCiAgICAuZiA9IH4gb2F4YWNhX3NwZWNfZih4ID0gLngpKQ0KDQpwcmVkaWN0ZWRfbGlzdF9ob20gPC0gbGlzdCgpDQp0d29fZm9sZF9yZXN1bHRzX3Bsb3RfbGlzdF9ob20gPC0gbGlzdCgpDQp0d29fZm9sZF9yZXN1bHRzX3RhYmxlX2xpc3RfaG9tIDwtIGxpc3QoKQ0KdHdvX2ZvbGRfdmFyaWFibGVzX2xpc3RfaG9tIDwtIGxpc3QoKQ0KDQojc2VsZWN0IGNvcnJlY3QgaW5mb3JtYXRpb24gZnJvbSByZXN1bHRzDQpmb3IoaSBpbiAxOmxlbmd0aChvYXhhY2FfbW9kZWxfbGlzdF9ob21vZ2VuZWl0eSkpIHsgI2kgPSA4DQogIG1vZGVsX29iamVjdCA8LSBvYXhhY2FfbW9kZWxfbGlzdF9ob21vZ2VuZWl0eVtbaV1dDQogIA0KICBwcmVkaWN0ZWRfbGlzdF9ob21bW2ldXSA8LSB0aWJibGUoeV9hID0gbW9kZWxfb2JqZWN0JHkkeS5BLA0KICB5X2IgPSBtb2RlbF9vYmplY3QkeSR5LkIsDQogIHlfZGlmZiA9IG1vZGVsX29iamVjdCR5JHkuZGlmZiwNCiAgbW9kZWwgPSBpKQ0KICANCiAgdHdvX2ZvbGRfcmVzdWx0c19wbG90X2xpc3RfaG9tW1tpXV0gPC0gbW9kZWxfb2JqZWN0JHR3b2ZvbGQkb3ZlcmFsbCAlPiUgDQogICAgYXNfdGliYmxlKCkgJT4lIA0KICAgIGZpbHRlcihncm91cC53ZWlnaHQgPT0gLTIpICU+JSANCiAgICByZW5hbWUoY29lZl9leHBsYWluZWQgPSBgY29lZihleHBsYWluZWQpYCwNCiAgICAgICAgICAgc2VfZXhwbGFpbmVkID0gYHNlKGV4cGxhaW5lZClgLA0KICAgICAgICAgICBjb2VmX3VuZXhwbGFpbmVkID0gYGNvZWYodW5leHBsYWluZWQpYCwNCiAgICAgICAgICAgc2VfdW5leHBsYWluZWQgPSBgc2UodW5leHBsYWluZWQpYCwNCiAgICAgICAgICAgY29lZl91bmV4cGxhaW5lZC5hID0gYGNvZWYodW5leHBsYWluZWQgQSlgLA0KICAgICAgICAgICBzZV91bmV4cGxhaW5lZC5hID0gYHNlKHVuZXhwbGFpbmVkIEEpYCwNCiAgICAgICAgICAgY29lZl91bmV4cGxhaW5lZC5iID0gYGNvZWYodW5leHBsYWluZWQgQilgLA0KICAgICAgICAgICBzZV91bmV4cGxhaW5lZC5iID0gYHNlKHVuZXhwbGFpbmVkIEIpYCkgJT4lIA0KICAgIHNlbGVjdCgtZ3JvdXAud2VpZ2h0KSAlPiUgDQogICAgc2VsZWN0KDE6OCkgJT4lIA0KICAgIHBpdm90X2xvbmdlcihkYXRhID0gLiwNCiAgICAgICAgICAgICAgICAgY29scyA9IDE6OCwNCiAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSBjKCJ2YXIiLCAibmFtZSIpLA0KICAgICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidmFsdWUiLA0KICAgICAgICAgICAgICAgICBuYW1lc19zZXAgPSAiXyIpICU+JSANCiAgICBtdXRhdGUobW9kZWwgPSBpKQ0KICANCiAgdHdvX2ZvbGRfcmVzdWx0c190YWJsZV9saXN0X2hvbVtbaV1dIDwtIG1vZGVsX29iamVjdCR0d29mb2xkJG92ZXJhbGwgJT4lIA0KICAgIGFzX3RpYmJsZSgpICU+JSANCiAgICBmaWx0ZXIoZ3JvdXAud2VpZ2h0ID09IC0yKSAlPiUgDQogICAgcmVuYW1lKGNvZWZfZXhwbGFpbmVkID0gYGNvZWYoZXhwbGFpbmVkKWAsDQogICAgICAgICAgIHNlX2V4cGxhaW5lZCA9IGBzZShleHBsYWluZWQpYCwNCiAgICAgICAgICAgY29lZl91bmV4cGxhaW5lZCA9IGBjb2VmKHVuZXhwbGFpbmVkKWAsDQogICAgICAgICAgIHNlX3VuZXhwbGFpbmVkID0gYHNlKHVuZXhwbGFpbmVkKWAsDQogICAgICAgICAgIGNvZWZfdW5leHBsYWluZWQuYSA9IGBjb2VmKHVuZXhwbGFpbmVkIEEpYCwNCiAgICAgICAgICAgc2VfdW5leHBsYWluZWQuYSA9IGBzZSh1bmV4cGxhaW5lZCBBKWAsDQogICAgICAgICAgIGNvZWZfdW5leHBsYWluZWQuYiA9IGBjb2VmKHVuZXhwbGFpbmVkIEIpYCwNCiAgICAgICAgICAgc2VfdW5leHBsYWluZWQuYiA9IGBzZSh1bmV4cGxhaW5lZCBCKWApICU+JSANCiAgICBzZWxlY3QoLWdyb3VwLndlaWdodCkgJT4lIA0KICAgIHNlbGVjdCgxOjgpDQogIA0KICANCiAgdHdvX2ZvbGRfdmFyaWFibGVzX2xpc3RfaG9tW1tpXV0gPC0gbW9kZWxfb2JqZWN0JHR3b2ZvbGQkdmFyaWFibGVzW1s2XV0gJT4lIA0KICAgIGFzX3RpYmJsZSgpICU+JSANCiAgICBtdXRhdGUodmFyaWFibGVzID0gcm93Lm5hbWVzKG1vZGVsX29iamVjdCR0d29mb2xkJHZhcmlhYmxlc1tbMl1dKSkgJT4lIA0KICAgIGZpbHRlcihncm91cC53ZWlnaHQgPT0gLTIpICU+JSANCiAgICBzZWxlY3QoMTAsMjo1KSAlPiUgDQogICAgbXV0YXRlKG1vZGVsID0gaSkNCiAgDQp9DQoNCg0KYGBgDQoNCiMjIyBEZWNvbXBvc2l0aW9uIHJlc3VsdHMgdGFibGUNCg0KYGBge3IgcmVzdWx0cyB0YWJsZSBob21vZ2VuZWl0eX0NCiNleHRyYWN0IHR3b2ZvbGQgaW5mb3JtYXRpb24NCnR3b2ZvbGRfdGFibGVfaG9tIDwtIHR3b19mb2xkX3Jlc3VsdHNfdGFibGVfbGlzdF9ob20gJT4lIA0KICBiaW5kX3Jvd3MoKSAlPiUgDQogIGZpbHRlcihyb3dfbnVtYmVyKCk+IDQpICU+JSANCiAgbXV0YXRlKG1vZGVsID0gZmFjdG9yKDE6NCwNCiAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IDE6NCwNCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoDQogICAgICAgICAgICAgICAgICAgICAgICAgICIxc3QgZ2VuIFR1cmtpc2ggLSAgMm5kIGdlbiBUdXJraXNoIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIjFzdCBnZW4gTW9yb2NjYW4gLSAgMm5kIGdlbiBNb3JvY2NhbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJUdXJraXNoIC0gIER1dGNoLU1ham9yaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIk1vcm9jY2FuIC0gIER1dGNoLU1ham9yaXR5Ig0KICAgICAgICAgICAgICAgICAgICAgICAgKSkpICU+JSANCiAgc2VsZWN0KDksMTo0KSAlPiUgDQogIG11dGF0ZSh6X2V4cGxhaW5lZCA9IGNvZWZfZXhwbGFpbmVkL3NlX2V4cGxhaW5lZCwNCiAgICAgICAgIHpfdW5leHBsYWluZWQgPSBjb2VmX3VuZXhwbGFpbmVkL3NlX3VuZXhwbGFpbmVkKSAlPiUgDQogIHNlbGVjdChtb2RlbCxjb2VmX2V4cGxhaW5lZCwgel9leHBsYWluZWQsIGNvZWZfdW5leHBsYWluZWQsIHpfdW5leHBsYWluZWQpDQoNCg0KcHJlZGljdGVkX2RmX2hvbSA8LSBwcmVkaWN0ZWRfbGlzdF9ob20gJT4lIA0KICBiaW5kX3Jvd3MoKSAlPiUgDQogIGZpbHRlcihtb2RlbCA+IDQpICU+JSANCiAgc2VsZWN0KDE6MykNCg0KI2NyZWF0ZSByZXN1bHMgdGFibGUNCnR3b2ZvbGRfdGFibGVfaG9tICU+JSANCiAgYmluZF9jb2xzKHByZWRpY3RlZF9kZl9ob20pICU+JSANCiAgc2VsZWN0KDEsNjo4LCAyOjUpICU+JSANCiAgICBrYmwoZGlnaXRzID0gMywNCiAgICAgIGFsaWduID0gJ2wnKSAlPiUgDQogIGthYmxlX3BhcGVyKCkNCg0KYGBgDQoNCiMjIyBEZWNvbXBvc2l0aW9uIHJlc3VsdHMgcGxvdA0KDQpgYGB7ciBwYW5lbCBwbG90IGhvbSwgZmlnLndpZHRoPTEyLGZpZy5oZWlnaHQgPSA4fQ0KI2NyZWF0ZSBwbG90IGRmDQp2YXJpYWJsZXNfcGxvdF9kZl9ob20gPC0gdHdvX2ZvbGRfdmFyaWFibGVzX2xpc3RfaG9tICU+JSANCiAgYmluZF9yb3dzKCkgJT4lIA0KICBmaWx0ZXIobW9kZWwgPiA0KSAlPiUgDQogIG11dGF0ZShtb2RlbCA9IGZhY3Rvcihtb2RlbCwgDQogICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSA1OjgsDQogICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiVHVya2lzaC1EdXRjaCAxc3QgZ2VuIC0gMm5kIGdlbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJNb3JvY2Nhbi1EdXRjaCAxc3QgZ2VuIC0gMm5kIGdlbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJUdXJraXNoLUR1dGNoIC0gIER1dGNoLU1ham9yaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIk1vcm9jY2FuLUR1dGNoIC0gIER1dGNoLU1ham9yaXR5Ig0KICAgICAgICAgICAgICAgICAgICAgICAgKSkpICU+JSANCiAgcmVuYW1lKGNvZWZfZXhwbGFpbmVkID0gYGNvZWYoZXhwbGFpbmVkKWAsDQogICAgICAgICAgIHNlX2V4cGxhaW5lZCA9IGBzZShleHBsYWluZWQpYCwNCiAgICAgICAgICAgY29lZl91bmV4cGxhaW5lZCA9IGBjb2VmKHVuZXhwbGFpbmVkKWAsDQogICAgICAgICAgIHNlX3VuZXhwbGFpbmVkID0gYHNlKHVuZXhwbGFpbmVkKWApICU+JQ0KICBwaXZvdF9sb25nZXIoZGF0YSA9IC4sDQogICAgICAgICAgICAgICAgIGNvbHMgPSAyOjUsDQogICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gYygidmFyIiwgIm5hbWUiKSwNCiAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInZhbHVlIiwNCiAgICAgICAgICAgICAgICAgbmFtZXNfc2VwID0gIl8iKSAlPiUgDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSB2YXIsDQogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gdmFsdWUpICU+JSANCiAgbXV0YXRlKGFic196ID0gYWJzKGNvZWYvc2UpLA0KICAgICAgICAgc2lnID0gaWZlbHNlKGFic196ID4gMS45NSwgMSwgMCksDQogICAgICAgICBzaWdfZiA9IGZhY3RvcihzaWcsDQogICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSAwOjEsDQogICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCIiLCAiKiIpKSkNCg0KI2NyZWF0ZSBzZWxlY3Rpb24gdmFyaWFibGUNCmluZGVwX25hbWVzIDwtIGMoDQogICJyZWxfZmFjXzJNb250aGx5IG9yIG1vcmUiLA0KICAicmVsX2ZhY18yMy0xMSBZZWFyIiwNCiAgInJlbF9mYWNfMjEtMiBZZWFyIiwNCiAgInBhaWRfd29yayIsDQogICJpbl9lZHVjYXRpb24iLA0KICAicGVyX05XX21pZ19hX3BjNCIsDQogICJJbndvbmVyX3BjNCIsDQogICJlZHVjYXRpb25fcmVjb2RlZF9udW1lcmljIiwNCiAgInRoZXJtX291dGdyb3VwX2RpZmYiLA0KICAiYWdlIiwNCiAgInBhcnRuZXIiLA0KICAiZ2VuZGVyRmVtYWxlIiwNCiAgIndvel9wYzQiKQ0KDQojY3JlYXRlIGRlY29tcG9zaXRpb24gaG9tb2dlbmVpdHkgcGxvdA0KdmFyaWFibGVzX2RlY29tcF9ob21fcGxvdCA8LSB2YXJpYWJsZXNfcGxvdF9kZl9ob20gJT4lDQogIGZpbHRlcih2YXJpYWJsZXMgJWluJSBpbmRlcF9uYW1lcykgJT4lDQogIG11dGF0ZSgNCiAgICB2YXJfZmFjID0gY2FzZV93aGVuKA0KICAgICAgdmFyaWFibGVzID09ICJwYWlkX3dvcmsiIH4gMSwNCiAgICAgIHZhcmlhYmxlcyA9PSAiaW5fZWR1Y2F0aW9uIiB+IDIsDQogICAgICB2YXJpYWJsZXMgPT0gInJlbF9mYWNfMjEtMiBZZWFyIiB+IDMsDQogICAgICB2YXJpYWJsZXMgPT0gInJlbF9mYWNfMjMtMTEgWWVhciIgfiA0LA0KICAgICAgdmFyaWFibGVzID09ICJyZWxfZmFjXzJNb250aGx5IG9yIG1vcmUiIH4gNSwNCiAgICAgIHZhcmlhYmxlcyA9PSAiZWR1Y2F0aW9uX3JlY29kZWRfbnVtZXJpYyIgfiA2LA0KICAgICAgdmFyaWFibGVzID09ICJJbndvbmVyX3BjNCIgfiA3LA0KICAgICAgdmFyaWFibGVzID09ICJwZXJfTldfbWlnX2FfcGM0IiB+IDgsDQogICAgICB2YXJpYWJsZXMgPT0gIndvel9wYzQiIH4gOSwNCiAgICAgIHZhcmlhYmxlcyA9PSAidGhlcm1fb3V0Z3JvdXBfZGlmZiIgfiAxMCwNCiAgICAgIHZhcmlhYmxlcyA9PSAiYWdlIiB+IDExLA0KICAgICAgdmFyaWFibGVzID09ICJwYXJ0bmVyIiB+IDEyLA0KICAgICAgdmFyaWFibGVzID09ICJnZW5kZXJGZW1hbGUiIH4gMTMNCiAgICApLA0KICAgIHZhcl9mYWMgPSBmYWN0b3IoDQogICAgICB2YXJfZmFjLA0KICAgICAgbGV2ZWxzID0gMToxMywNCiAgICAgIGxhYmVscyA9IGMoDQogICAgICAgICJQYWlkIHdvcmsiLA0KICAgICAgICAiQ3VycmVudGx5IGluIGVkdWNhdGlvbiIsDQogICAgICAgICJSZWxpZ2lvdXMgYXR0ZW5kYW5jZVsxLTIgeWVhcl0iLA0KICAgICAgICAiUmVsaWdpb3VzIGF0dGVuZGFuY2VbMy0xMSBhIHllYXJdIiwNCiAgICAgICAgIlJlbGlnaW91cyBhdHRlbmRhbmNlW09uY2UgYSBtb250aCBvciBtb3JlXSIsDQogICAgICAgICJFZHVjYXRpb25hbCBhdHRhaW5tZW50IiwNCiAgICAgICAgIk5laWdoYm91cmhvb2Q6ICMgaW5oYWJpdGFudHMiLA0KICAgICAgICAiTmVpZ2hib3VyaG9vZDogJSBub24td2VzdGVybiBtaWdyYW50IiwNCiAgICAgICAgIk5laWdoYm91cmhvb2Q6IG1lYW4gcHJvcGVydHkgdmFsdWF0aW9uIiwNCiAgICAgICAgIk91dGdyb3VwIGF0dGl0dWRlcyIsDQogICAgICAgICJBZ2UiLA0KICAgICAgICAiUGFydG5lcltubyBwYXJ0bmVyXSIsDQogICAgICAgICJHZW5kZXJbTWFsZV0iDQogICAgICApDQogICAgKQ0KICApICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gY29lZiwgeSA9IHZhcl9mYWMpKSArDQogIGdlb21fY29sKGFlcyhjb2xvdXIgPSBuYW1lLA0KICAgICAgICAgICAgIGZpbGwgPSBuYW1lKSwNCiAgICAgICAgICAgYWxwaGEgPSAwLjYpICsgDQogIGdlb21fZXJyb3JiYXIoYWVzKHhtaW4gPSBjb2VmIC0gKHNlKjEuOTYpLA0KICAgICAgICAgICAgICAgICAgICB4bWF4ID0gY29lZiArIChzZSoxLjk2KSkpICsNCiAgZmFjZXRfZ3JpZChjb2xzID0gdmFycyhtb2RlbCksDQogICAgICAgICAgICAgcm93cyA9IHZhcnMobmFtZSkpICsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gc2lnX2YpLA0KICAgICAgICAgICAgaGp1c3QgPSAyLA0KICAgICAgICAgICAgc2l6ZSA9IDYpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Qob3B0aW9uID0gIkQiKSArDQogIHNjYWxlX2NvbG91cl92aXJpZGlzX2Qob3B0aW9uID0gIkQiKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLA0KICAgICAgICAjcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAnIzQwNDA0MCcsIGNvbG91ciA9ICcjNDA0MDQwJyksDQogICAgICAgICNwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAnIzQwNDA0MCcsIGNvbG91ciA9ICcjNDA0MDQwJyksDQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDEpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoaGp1c3QgPSAxKSwNCiAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiYmxhY2siKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiYmxhY2siKSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSArDQogIGxhYnMoeSA9ICJJbmRlcGVuZGVudCBWYXJpYWJsZXMiLA0KICAgICAgIHggPSAiQ29lZmZpY2llbnQiLA0KICAgICAgIGNhcHRpb24gPSAiKiBwIDwgMC4wNSIpDQoNCiNzYXZlIHBsb3QNCiAgZ2dzYXZlKHZhcmlhYmxlc19kZWNvbXBfaG9tX3Bsb3QsDQogICAgICAgIGZpbGUgPSAiZGF0YV9hbmFseXNpcy9wbG90cy9yZXN1bHRzL3ZhcmlhYmxlc19kZWNvbXBfaG9tX3Bsb3QuanBnIiwNCiAgICAgICB3aWR0aCA9IDEyLA0KICAgICAgIGhlaWdodCA9IDgsDQogICAgICAgZHBpID0gMzIwKQ0KDQogICNzaG93IHBsb3QNCnZhcmlhYmxlc19kZWNvbXBfaG9tX3Bsb3QNCg0KYGBgDQoNCiMjIyBSZWdyZXNzaW9uIG1vZGVsIHJlc3VsdHMgcGVyIGdyb3VwDQoNCkFsbCAoc3ViKWdyb3Vwcw0KDQpgYGB7ciBkaWZmZXJlbnQgbW9kZWwgcmVzdWx0cyBob21vZ2VuZWl0eSBnZW4gZGlmZn0NCiNjcmVhdGUgbGlzdCB3aXRoIHJlZ3Jlc3Npb24gYnkgbWlncmF0aW9uIGdyb3VwDQpyZXN1bHRzX2xpc3QgPC0gaW1wICU+JQ0KICBmaWx0ZXIoZ2VuZGVyICE9ICJPdGhlciIpICU+JSANCiAgZ3JvdXBfc3BsaXQobWlncmF0aW9uX2JhY2tncm91bmRfZmFjKSAlPiUNCiAgbWFwKA0KICAgIC54ID0gLiwNCiAgICAuZiA9IH4gbG0oDQogICAgICBwZXJfaW5ncm91cF93IH4gIGFnZSArDQogICAgICAgIGdlbmRlciArIA0KICAgICAgICBlZHVjYXRpb25fcmVjb2RlZF9udW1lcmljICsNCiAgICAgICAgcGFydG5lciArIA0KICAgICAgICBpbl9lZHVjYXRpb24gKw0KICAgICAgICBwYWlkX3dvcmsgKw0KICAgICAgICByZWxfZmFjXzIgKw0KICAgICAgICB0aGVybV9vdXRncm91cF9kaWZmICsNCiAgICAgICAgcGVyX05XX21pZ19hX3BjNCArDQogICAgICAgIHdvel9wYzQgKw0KICAgICAgICBJbndvbmVyX3BjNCwNCiAgICAgIGRhdGEgPSAueA0KICAgICkNCiAgKQ0KDQojc2hvdyB0YWJsZSB3aXRoIHJlc3VsdHMNCnNqUGxvdDo6dGFiX21vZGVsKHJlc3VsdHNfbGlzdCwNCiAgICAgICAgICBwcmVkLmxhYmVscyA9IGMoDQogICAgICAgICAgICAiQ29uc3RhbnQiLA0KICAgICAgICAgICAgIkFnZSIsDQogICAgICAgICAgICAiR2VuZGVyIFtGZW5hbGVdIiwNCiAgICAgICAgICAgICJFZHVjYXRpb25hbCBhdHRhaW5tZW50IiwNCiAgICAgICAgICAgICJQYXJ0bmVyW0hhcyBhIHBhcnRuZXJdIiwNCiAgICAgICAgICAgICJQYWlkIHdvcmsiLA0KICAgICAgICAgICAgIkN1cnJlbnRseSBpbiBlZHVjYXRpb24iLA0KICAgICAgICAgICAgIlJlbGlnaW91cyBhdHRlbmRhbmNlWzEtMiB5ZWFyXSIsDQogICAgICAgICAgICAiUmVsaWdpb3VzIGF0dGVuZGFuY2VbMy0xMSBhIHllYXJdIiwNCiAgICAgICAgICAgICJSZWxpZ2lvdXMgYXR0ZW5kYW5jZVtPbmNlIGEgbW9udGggb3IgbW9yZV0iLA0KICAgICAgICAgICAgIk91dGdyb3VwIGF0dGl0dWRlIiwNCiAgICAgICAgICAgICJOZWlnaGJvcmhvb2Q6ICUgbm9uLXdlc3Rlcm4gbWlncmFudCIsDQogICAgICAgICAgICAiTmVpZ2hib3Job29kOiBtZWFuIHByb3BlcnR5IHZhbHVhdGlvbiIsDQogICAgICAgICAgICAiTmVpZ2hib3Job29kOiAjIGluaGFiaXRhbnRzIg0KICAgICAgICAgICAgKSwNCiAgICAgICAgICBkdi5sYWJlbHMgPSBjKCJEdXRjaCIsIjFzdCBnZW4gVHVya2lzaCIsICIybmQgZ2VuIFR1cmtpc2giLCAiMXN0IGdlbiBNb3JvY2NhbiIsICIybmQgZ2VuIE1vcm9jY2FuIiksDQogICAgICAgICAgZGlnaXRzID0gMywNCiAgICAgICAgICBzaG93LmNpID0gRiwNCiAgICAgICAgICBzaG93LnN0YXQgPSBULA0KICAgICAgICAgIGNvbGxhcHNlLnNlICA9IEYsDQogICAgICAgICAgY29sLm9yZGVyID0gYygiZXN0IiwgInN0YXQiKQ0KICAgICAgICAgICNmaWxlID0gInJlZy5kb2MiDQogICAgICAgICAgKQ0KYGBgDQoNCkFsbCBtYWpvciBncm91cHMuDQoNCmBgYHtyIGRpZmZlcmVudCBtb2RlbCByZXN1bHRzIGhvbW9nZW5laXR5IHNpbXBsZX0NCiNsaXN0IHdpdGhyIHJlc3VsdHMgb2YgZWFjaCBncm91cA0KcmVzdWx0c19saXN0IDwtIGltcCAlPiUNCiAgZmlsdGVyKGdlbmRlciAhPSAiT3RoZXIiKSAlPiUgDQogIGdyb3VwX3NwbGl0KG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX3NpbXBsZV9mYWMpICU+JQ0KICBtYXAoDQogICAgLnggPSAuLA0KICAgIC5mID0gfiBsbSgNCiAgICAgIHBlcl9pbmdyb3VwX3cgfiAgYWdlICsNCiAgICAgICAgZ2VuZGVyICsgDQogICAgICAgIGVkdWNhdGlvbl9yZWNvZGVkX251bWVyaWMgKw0KICAgICAgICBwYXJ0bmVyICsgDQogICAgICAgIGluX2VkdWNhdGlvbiArDQogICAgICAgIHBhaWRfd29yayArDQogICAgICAgIHJlbF9mYWNfMiArDQogICAgICAgIHRoZXJtX291dGdyb3VwX2RpZmYgKw0KICAgICAgICBwZXJfTldfbWlnX2FfcGM0ICsNCiAgICAgICAgd296X3BjNCArDQogICAgICAgIElud29uZXJfcGM0LA0KICAgICAgZGF0YSA9IC54DQogICAgKQ0KICApDQoNCiNzaG93IHJlc3VsdHMgaW4gYSB0YWJsZQ0Kc2pQbG90Ojp0YWJfbW9kZWwocmVzdWx0c19saXN0LA0KICAgICAgICAgIHByZWQubGFiZWxzID0gYygNCiAgICAgICAgICAgICJDb25zdGFudCIsDQogICAgICAgICAgICAiQWdlIiwNCiAgICAgICAgICAgICJHZW5kZXIgW0ZlbmFsZV0iLA0KICAgICAgICAgICAgIkVkdWNhdGlvbmFsIGF0dGFpbm1lbnQiLA0KICAgICAgICAgICAgIlBhcnRuZXJbSGFzIGEgcGFydG5lcl0iLA0KICAgICAgICAgICAgIlBhaWQgd29yayIsDQogICAgICAgICAgICAiQ3VycmVudGx5IGluIGVkdWNhdGlvbiIsDQogICAgICAgICAgICAiUmVsaWdpb3VzIGF0dGVuZGFuY2VbMS0yIHllYXJdIiwNCiAgICAgICAgICAgICJSZWxpZ2lvdXMgYXR0ZW5kYW5jZVszLTExIGEgeWVhcl0iLA0KICAgICAgICAgICAgIlJlbGlnaW91cyBhdHRlbmRhbmNlW09uY2UgYSBtb250aCBvciBtb3JlXSIsDQogICAgICAgICAgICAiT3V0Z3JvdXAgYXR0aXR1ZGUiLA0KICAgICAgICAgICAgIk5laWdoYm9yaG9vZDogJSBjby1ldGhuaWMiLA0KICAgICAgICAgICAgIk5laWdoYm9yaG9vZDogbWVhbiBwcm9wZXJ0eSB2YWx1YXRpb24iLA0KICAgICAgICAgICAgIk5laWdoYm9yaG9vZDogIyBpbmhhYml0YW50cyIsDQogICAgICAgICAgICAiVGhlcm0gbWlzc2luZyINCiAgICAgICAgICAgICksDQogICAgICAgICAgZHYubGFiZWxzID0gYygiRHV0Y2giLCJUdXJraXNoLUR1dGNoIiwgIk1vcm9jY2FuLUR1dGNoIiksDQogICAgICAgICAgZGlnaXRzID0gMywNCiAgICAgICAgICBzaG93LmNpID0gRiwNCiAgICAgICAgICBzaG93LnN0YXQgPSBULA0KICAgICAgICAgIGNvbGxhcHNlLnNlICA9IEYsDQogICAgICAgICAgY29sLm9yZGVyID0gYygiZXN0IiwgInN0YXQiKQ0KICAgICAgICAgICNmaWxlID0gInJlZy5kb2MiDQogICAgICAgICAgKQ0KDQpgYGA=


Copyright © 2024 Jeroense Thijmen