Data preparation script NELLS module for anayses

Libraries

# get packages needed
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("readr", "tidyverse")
fpackage.check(packages)

NELLS combined import

Import the NELLS datafile with selected neigbhourhood variables.

load(file =  "data_analysis/data/data_processed/nells_data/2022-05-08_nells_nsum_data.rds")

Clean NSUM module data

First select the correct NSUM question. For the cleaning we use the variables which still have the original coding. Then we listwise delete missing values from these data. By doing so we go from 1595 responses to 1240.

#select nsum questions
raw_nsum_module <- nells_nsum %>% 
  arrange(id) %>%  #order on personal id code.
  select(!ends_with("boundary")) %>% 
  select(id, starts_with("knows")) %>% 
  na.omit()

Second task is to delete responses which have an sd of zero across name variables and catagory variables. These are respondents who filled in the same response for each X question. We lose 45 responses for names and 15 for categories. After deleting those responses we are left with 1187 responses.

#create filter
raw_nsum_module <- raw_nsum_module %>% 
  rowwise() %>% #create for every row the SD of all the naming questions. 
  mutate(sd_names = sd(c_across(2:12), na.rm = T),
         sd_categories = sd(c_across(3:24), na.rm = T)) %>% 
  ungroup()

#How many do you loose this way?
# raw_nsum_module %>% #N = 45 for names
#   filter(sd_names == 0) %>% 
#   count()

# raw_nsum_module %>% #N = 15 for categories
#   filter(sd_categories == 0) %>% 
#   count()

#filter
raw_nsum_module <- raw_nsum_module %>% 
  filter(sd_categories != 0) %>% 
  filter(sd_names != 0)

Third task of cleaning is to filter out responses that have a high frequency of 50/35/15. We chose to filter out responses when they indicate that they indicate to know 35 people for more than two names and now 50 people for more than one name. We remove 8 responses this way.

#functions to check prevalence of a value in variable
count_frequency_value_f <- function(object, value){
  y <- length(object[!is.na(object) & object == value])
}

#check for high frequency of 50.
raw_nsum_module <- raw_nsum_module %>%
  rowwise() %>%
  mutate(
    count_50_names = count_frequency_value_f(object = c_across(
      c(
        knows_daan,
        knows_kevin,
        knows_edwin,
        knows_albert,
        knows_emma,
        knows_linda,
        knows_ingrid,
        knows_willemina,
        knows_mohammed,
        knows_esra,
        knows_ibrahim,
        knows_fatima
      )
    ),
    value = 50),
    count_35_names = count_frequency_value_f(object = c_across(
      c(
        knows_daan,
        knows_kevin,
        knows_edwin,
        knows_albert,
        knows_emma,
        knows_linda,
        knows_ingrid,
        knows_willemina,
        knows_mohammed,
        knows_esra,
        knows_ibrahim,
        knows_fatima
      )
    ),
    value = 35),
    count_15_names = count_frequency_value_f(object = c_across(
      c(
        knows_daan,
        knows_kevin,
        knows_edwin,
        knows_albert,
        knows_emma,
        knows_linda,
        knows_ingrid,
        knows_willemina,
        knows_mohammed,
        knows_esra,
        knows_ibrahim,
        knows_fatima
      )
    ),
    value = 15)
  )

#for 35, remove those people who have a higher frequency than 2 for the names.
#for 50, remove those people who have a higher frequency than 7 for the names.
#we remove 8 names
selection <- raw_nsum_module %>% 
  filter(count_35_names < 3) %>% 
  filter(count_50_names < 2) %>% 
  pull(id)

#create selection from nells nsum file
nells_nsum <- nells_nsum %>% 
  filter(id %in% selection) %>% 
  arrange(id)

Ethnic names

nells_nsum <- nells_nsum %>% 
  mutate(knows_ethnic_boundary = ((knows_mohammed*(13448/20233)) + (knows_fatima*(2808/20233)) + (knows_esra*(1878/20233)) + (knows_ibrahim*(2099/20233)))/4) 

Create NSUM module

We do not use all of the questions from the NSUM module. We created a module with more names and and also more categories who are specified to people with a migration background then we actually need or use. If we use more names or categories that measure knowing so-called migratns we inflate the networks of these groups. So we come to a final selection of 16 populations for the main NSUM analysis.

#relevel migration background and create simple migration background 
nells_nsum <- nells_nsum %>%
  mutate(
    migration_background_fac = fct_relevel(
      migration_background_fac,
      "Dutch",
      "1st gen Turkish",
      "2nd gen Turkish",
      "1st gen Moroccan",
      "2nd gen Moroccan"
    ),
    migration_background_fac = factor(
      as.numeric(migration_background_fac),
      levels = 1:5,
      labels = c(
        "Dutch-Majority",
        "1st gen Turkish-Dutch",
        "2nd gen Turkish-Dutch",
        "1st gen Moroccan-Dutch",
        "2nd gen Moroccan-Dutch"
      )
    ),
    migration_background_simple_fac = case_when(
      migration_background_fac == "1st gen Turkish-Dutch" ~ 2,
      migration_background_fac == "2nd gen Turkish-Dutch" ~ 2,
      migration_background_fac == "1st gen Moroccan-Dutch" ~ 3,
      migration_background_fac == "2nd gen Moroccan-Dutch" ~ 3,
      migration_background_fac == "Dutch-Majority" ~ 1
    ),
    migration_background_simple_fac = factor(
      migration_background_simple_fac,
      levels = 1:3,
      labels = c("Dutch-Majority", "Turkish-Dutch", "Moroccan-Dutch")
    )
  )

Extract information for NSUM analysis.

#create matrix
#select observations from nells_nsum
nsum_model_selection <- nells_nsum %>% 
  arrange(id) %>% 
  select(knows_daan_boundary,
         knows_kevin_boundary, 
         knows_edwin_boundary,
         knows_albert_boundary,
         knows_emma_boundary,
         knows_linda_boundary,
         knows_ingrid_boundary,
         knows_willemina_boundary,
         knows_ibrahim_boundary,
         knows_prison_boundary,
         knows_mbo,
         knows_hbo,
         knows_university,
         knows_secundary,
         knows_secondhome,
         knows_unemployed)

#observations
mat <- nsum_model_selection %>% 
  as.matrix()

#known population information
#import frequencies
nsum_frequencies <- read_csv(file = "data_analysis/2022-08-26_namefrequencies.csv")

#vector with known population information
known_vector <- known_vector <- nsum_frequencies %>% 
  filter(name %in% c(
    "knows_daan",
    "knows_kevin", 
    "knows_edwin",
    "knows_albert",
    "knows_emma",
    "knows_linda",
    "knows_ingrid",
    "knows_willemina",
    "knows_ibrahim",
    "knows_prison",
    "knows_mbo",
    "knows_hbo",
    "knows_university",
    "knows_secundary",
    "knows_secondhome",
    "knows_unemployed"
  )) %>% 
  pull(number)
##########################

#export analysis matrix and known vector
analysis_files_selection <- list(mat, known_vector)

save(analysis_files_selection, file = "data_analysis/data/data_processed/nsum_input/2023-04-11_analysis_files_selection.rds")
#create matrix
#select observations from nells_nsum
nsum_model_selection_2 <- nells_nsum %>% 
  arrange(id) %>% 
  select(knows_daan_boundary,
         knows_kevin_boundary, 
         knows_edwin_boundary,
         knows_albert_boundary,
         knows_emma_boundary,
         knows_linda_boundary,
         knows_ingrid_boundary,
         knows_willemina_boundary,
         knows_ethnic_boundary,
         knows_prison_boundary,
         knows_mbo,
         knows_hbo,
         knows_university,
         knows_secundary,
         knows_secondhome,
         knows_unemployed)

#observations
mat_2 <- nsum_model_selection_2 %>% 
  as.matrix()

#vector with known population information
known_vector_2 <- nsum_frequencies %>% 
  mutate(number = ifelse(name == "knows_ibrahim", 20233, number)) %>% 
  filter(name %in% c(
    "knows_daan",
    "knows_kevin", 
    "knows_edwin",
    "knows_albert",
    "knows_emma",
    "knows_linda",
    "knows_ingrid",
    "knows_willemina",
    "knows_ibrahim",
    "knows_prison",
    "knows_mbo",
    "knows_hbo",
    "knows_university",
    "knows_secundary",
    "knows_secondhome",
    "knows_unemployed"
  )) %>% 
  pull(number)
##########################

#export analysis matrix and known vector
analysis_files_selection_2 <- list(mat_2, known_vector_2)

save(analysis_files_selection_2, file = "data_analysis/data/data_processed/nsum_input/2023-04-11_analysis_files_selection_2.rds")

Create model file for each subgroup

Full model

#create function to use in loop
nsum_full_model_prepare <- function(dataframe, known_df) { #dataframe = group_list[[1]]
  df <- dataframe %>%
    arrange(id) %>% #arrange on id so we can merge the results
    select( #only select information we need
      knows_daan_boundary,
      knows_kevin_boundary,
      knows_edwin_boundary,
      knows_albert_boundary,
      knows_emma_boundary,
      knows_linda_boundary,
      knows_ingrid_boundary,
      knows_willemina_boundary,
      knows_ibrahim_boundary,
      knows_prison_boundary,
      knows_mbo,
      knows_hbo,
      knows_university,
      knows_secundary,
      knows_secondhome,
      knows_unemployed
    )
  
  mat <- df %>% 
  as.matrix()
  
  known_vector <- known_df %>% 
  filter(name %in% c(
    "knows_daan",
    "knows_kevin", 
    "knows_edwin",
    "knows_albert",
    "knows_emma",
    "knows_linda",
    "knows_ingrid",
    "knows_willemina",
    "knows_ibrahim",
    "knows_prison",
    "knows_mbo",
    "knows_hbo",
    "knows_university",
    "knows_secundary",
    "knows_secondhome",
    "knows_unemployed"
  )) %>% 
  pull(number)
  
  nsum_model_selection <- list(mat, known_vector)
  
  return(nsum_model_selection)
}

#create list for loop
group_list <- nells_nsum %>% 
  group_split(migration_background_simple_fac)

#replace other with full sample
group_list[[4]] <- nells_nsum

#apply map and save result
full_model_groups <- group_list %>% 
  map(.x = .,
      .f = ~ nsum_full_model_prepare(dataframe = .x,
                                   known_df = nsum_frequencies))


#add names
names(full_model_groups) <- c("Dutch-Majority",
                              "Turkish-Dutch",
                              "Moroccan-Dutch", 
                              "Full sample")

Model with only categories

#create function to use in loop
nsum_category_model_prepare <- function(dataframe, known_df) { #dataframe = group_list[[1]]
  df <- dataframe %>%
    arrange(id) %>% #arrange on id so we can merge the results
    select( #only select information we need
      knows_prison_boundary,
      knows_mbo,
      knows_hbo,
      knows_university,
      knows_secundary,
      knows_secondhome,
      knows_unemployed
    )
  
  mat <- df %>% 
  as.matrix()
  
  known_vector <- known_df %>% 
  filter(name %in% c(
    "knows_prison",
    "knows_mbo",
    "knows_hbo",
    "knows_university",
    "knows_secundary",
    "knows_secondhome",
    "knows_unemployed"
  )) %>% 
  pull(number)
  
  nsum_model_selection <- list(mat, known_vector)
  
  return(nsum_model_selection)
}

#apply map and save result
cat_model_groups <- group_list %>% 
  map(.x = .,
      .f = ~ nsum_category_model_prepare(dataframe = .x,
                                   known_df = nsum_frequencies))


#add names
names(cat_model_groups) <- c("Dutch-Majority",
                              "Turkish-Dutch",
                              "Moroccan-Dutch", 
                              "Full sample")

Model with only ethnic categories

#create function to use in loop
nsum_ethnicnames_model_prepare <- function(dataframe, known_df) { #dataframe = group_list[[1]]
  df <- dataframe %>%
    arrange(id) %>% #arrange on id so we can merge the results
    select( #only select information we need
      knows_mohammed_boundary,
      knows_fatima_boundary,
      knows_esra_boundary,
      knows_ibrahim_boundary
    )
  
  mat <- df %>% 
  as.matrix()
  
  known_vector <- known_df %>% 
  filter(name %in% c(
    "knows_mohammed",
    "knows_fatima",
    "knows_esra",
    "knows_ibrahim"
  )) %>% 
  pull(number)
  
  nsum_model_selection <- list(mat, known_vector)
  
  return(nsum_model_selection)
}

#apply map and save result
ethnicnames_model_groups <- group_list %>% 
  map(.x = .,
      .f = ~ nsum_ethnicnames_model_prepare(dataframe = .x,
                                   known_df = nsum_frequencies))


#add names
names(ethnicnames_model_groups) <- c("Dutch-Majority",
                              "Turkish-Dutch",
                              "Moroccan-Dutch", 
                              "Full sample")

Model with only majority categories

#create function to use in loop
nsum_maj_model_prepare <- function(dataframe, known_df) { #dataframe = group_list[[1]]
  df <- dataframe %>%
    arrange(id) %>% #arrange on id so we can merge the results
    select( #only select information we need
      knows_daan_boundary,
      knows_kevin_boundary,
      knows_edwin_boundary,
      knows_albert_boundary,
      knows_emma_boundary,
      knows_linda_boundary,
      knows_ingrid_boundary,
      knows_willemina_boundary
    )
  
  mat <- df %>% 
  as.matrix()
  
  known_vector <- known_df %>% 
  filter(name %in% c(
    "knows_daan",
    "knows_kevin", 
    "knows_edwin",
    "knows_albert",
    "knows_emma",
    "knows_linda",
    "knows_ingrid",
    "knows_willemina"
  )) %>% 
  pull(number)
  
  nsum_model_selection <- list(mat, known_vector)
  
  return(nsum_model_selection)
}

#apply map and save result
maj_model_groups <- group_list %>% 
  map(.x = .,
      .f = ~ nsum_maj_model_prepare(dataframe = .x,
                                   known_df = nsum_frequencies))

#add names
names(maj_model_groups) <- c("Dutch-Majority",
                              "Turkish-Dutch",
                              "Moroccan-Dutch", 
                              "Full sample")

Model with all names

#create function to use in loop
nsum_names_model_prepare <- function(dataframe, known_df) { #dataframe = group_list[[1]]
  df <- dataframe %>%
    arrange(id) %>% #arrange on id so we can merge the results
    select( #only select information we need
      knows_daan_boundary,
      knows_kevin_boundary,
      knows_edwin_boundary,
      knows_albert_boundary,
      knows_emma_boundary,
      knows_linda_boundary,
      knows_ingrid_boundary,
      knows_willemina_boundary,
      knows_mohammed_boundary,
      knows_fatima_boundary,
      knows_esra_boundary,
      knows_ibrahim_boundary
    )
  
  mat <- df %>% 
  as.matrix()
  
  known_vector <- known_df %>% 
  filter(name %in% c(
    "knows_daan",
    "knows_kevin", 
    "knows_edwin",
    "knows_albert",
    "knows_emma",
    "knows_linda",
    "knows_ingrid",
    "knows_willemina",
    "knows_mohammed",
    "knows_fatima",
    "knows_esra",
    "knows_ibrahim"
  )) %>% 
  pull(number)
  
  nsum_model_selection <- list(mat, known_vector)
  
  return(nsum_model_selection)
}

#apply map and save result
names_model_groups <- group_list %>% 
  map(.x = .,
      .f = ~ nsum_names_model_prepare(dataframe = .x,
                                   known_df = nsum_frequencies))


#add names
names(names_model_groups) <- c("Dutch-Majority",
                              "Turkish-Dutch",
                              "Moroccan-Dutch", 
                              "Full sample")

Combine robustness data

robustness_dfs <- list(full_model_groups, 
     cat_model_groups,
     ethnicnames_model_groups,
     maj_model_groups,
     names_model_groups
     )

names(robustness_dfs) <- c("full_model_groups",
                           "cat_model_groups",
                           "ethnicnames_model_groups",
                           "maj_model_groups",
                           "names_model_groups") 
save(robustness_dfs, 
     file = "data_analysis/data/data_processed/nsum_input/2023-04-21_robustness-dfs.rda")

Export data

#export datafile
save(nells_nsum, file = "data_analysis/data/data_processed/nells_data/2023-05-08_nells-nsum-prepped-data.rds")
LS0tDQp0aXRsZTogIk5TVU0gcHJlcGFyYXRpb24iDQphdXRob3I6ICJUaGlqbWVuIEplcm9lbnNlIg0KZGF0ZTogIkxhc3QgY29tcGlsZWQgb24gYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiBUUlVFDQogICAgdG9jX2RlcHRoOiAzDQogICAgdG9jX2Zsb2F0OiBUUlVFDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQogICAgY29kZV9kb3dubG9hZDogVFJVRQ0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGNhY2hlID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIHJlc3VsdHMgPSAiYXNpcyIsDQogICAgICAgICAgICAgICAgICAgICAgZmlnLmFsaWduID0gImNlbnRlciIpDQpgYGANCg0KDQojIERhdGEgcHJlcGFyYXRpb24gc2NyaXB0IE5FTExTIG1vZHVsZSBmb3IgYW5heXNlcw0KDQojIyBMaWJyYXJpZXMNCg0KYGBge3IgbGlicmFyaWVzLCByZXN1bHRzPSdoaWRlJ30NCiMgZ2V0IHBhY2thZ2VzIG5lZWRlZA0KZnBhY2thZ2UuY2hlY2sgPC0gZnVuY3Rpb24ocGFja2FnZXMpIHsgIyAoYykgSm9jaGVtIFRvbHNtYQ0KICBsYXBwbHkocGFja2FnZXMsIEZVTiA9IGZ1bmN0aW9uKHgpIHsNCiAgICBpZiAoIXJlcXVpcmUoeCwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkgew0KICAgICAgaW5zdGFsbC5wYWNrYWdlcyh4LCBkZXBlbmRlbmNpZXMgPSBUUlVFKQ0KICAgICAgbGlicmFyeSh4LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpDQogICAgfQ0KICB9KQ0KfQ0KcGFja2FnZXMgPSBjKCJyZWFkciIsICJ0aWR5dmVyc2UiKQ0KZnBhY2thZ2UuY2hlY2socGFja2FnZXMpDQpgYGANCg0KIyMgTkVMTFMgY29tYmluZWQgaW1wb3J0DQoNCkltcG9ydCB0aGUgTkVMTFMgZGF0YWZpbGUgd2l0aCBzZWxlY3RlZCBuZWlnYmhvdXJob29kIHZhcmlhYmxlcy4gDQoNCmBgYHtyIGRhdGEgaW1wb3J0fQ0KbG9hZChmaWxlID0gICJkYXRhX2FuYWx5c2lzL2RhdGEvZGF0YV9wcm9jZXNzZWQvbmVsbHNfZGF0YS8yMDIyLTA1LTA4X25lbGxzX25zdW1fZGF0YS5yZHMiKQ0KYGBgDQoNCg0KIyBDbGVhbiBOU1VNIG1vZHVsZSBkYXRhDQoNCkZpcnN0IHNlbGVjdCB0aGUgY29ycmVjdCBOU1VNIHF1ZXN0aW9uLiBGb3IgdGhlIGNsZWFuaW5nIHdlIHVzZSB0aGUgdmFyaWFibGVzIHdoaWNoIHN0aWxsIGhhdmUgdGhlIG9yaWdpbmFsIGNvZGluZy4gVGhlbiB3ZSBsaXN0d2lzZSBkZWxldGUgbWlzc2luZyB2YWx1ZXMgZnJvbSB0aGVzZSBkYXRhLiBCeSBkb2luZyBzbyB3ZSBnbyBmcm9tIDE1OTUgcmVzcG9uc2VzIHRvIDEyNDAuIA0KDQpgYGB7ciBsaXN0d2lzZSBkZWxldGlvbn0NCiNzZWxlY3QgbnN1bSBxdWVzdGlvbnMNCnJhd19uc3VtX21vZHVsZSA8LSBuZWxsc19uc3VtICU+JSANCiAgYXJyYW5nZShpZCkgJT4lICAjb3JkZXIgb24gcGVyc29uYWwgaWQgY29kZS4NCiAgc2VsZWN0KCFlbmRzX3dpdGgoImJvdW5kYXJ5IikpICU+JSANCiAgc2VsZWN0KGlkLCBzdGFydHNfd2l0aCgia25vd3MiKSkgJT4lIA0KICBuYS5vbWl0KCkNCg0KYGBgDQoNCg0KU2Vjb25kIHRhc2sgaXMgdG8gZGVsZXRlIHJlc3BvbnNlcyB3aGljaCBoYXZlIGFuIHNkIG9mIHplcm8gYWNyb3NzIG5hbWUgdmFyaWFibGVzIGFuZCBjYXRhZ29yeSB2YXJpYWJsZXMuIFRoZXNlIGFyZSByZXNwb25kZW50cyB3aG8gZmlsbGVkIGluIHRoZSBzYW1lIHJlc3BvbnNlIGZvciBlYWNoIFggcXVlc3Rpb24uIFdlIGxvc2UgNDUgcmVzcG9uc2VzIGZvciBuYW1lcyBhbmQgMTUgZm9yIGNhdGVnb3JpZXMuIEFmdGVyIGRlbGV0aW5nIHRob3NlIHJlc3BvbnNlcyB3ZSBhcmUgbGVmdCB3aXRoIDExODcgcmVzcG9uc2VzLiANCg0KYGBge3IgZGVzZWxlY3Qgb24gc2R9DQojY3JlYXRlIGZpbHRlcg0KcmF3X25zdW1fbW9kdWxlIDwtIHJhd19uc3VtX21vZHVsZSAlPiUgDQogIHJvd3dpc2UoKSAlPiUgI2NyZWF0ZSBmb3IgZXZlcnkgcm93IHRoZSBTRCBvZiBhbGwgdGhlIG5hbWluZyBxdWVzdGlvbnMuIA0KICBtdXRhdGUoc2RfbmFtZXMgPSBzZChjX2Fjcm9zcygyOjEyKSwgbmEucm0gPSBUKSwNCiAgICAgICAgIHNkX2NhdGVnb3JpZXMgPSBzZChjX2Fjcm9zcygzOjI0KSwgbmEucm0gPSBUKSkgJT4lIA0KICB1bmdyb3VwKCkNCg0KI0hvdyBtYW55IGRvIHlvdSBsb29zZSB0aGlzIHdheT8NCiMgcmF3X25zdW1fbW9kdWxlICU+JSAjTiA9IDQ1IGZvciBuYW1lcw0KIyAgIGZpbHRlcihzZF9uYW1lcyA9PSAwKSAlPiUgDQojICAgY291bnQoKQ0KDQojIHJhd19uc3VtX21vZHVsZSAlPiUgI04gPSAxNSBmb3IgY2F0ZWdvcmllcw0KIyAgIGZpbHRlcihzZF9jYXRlZ29yaWVzID09IDApICU+JSANCiMgICBjb3VudCgpDQoNCiNmaWx0ZXINCnJhd19uc3VtX21vZHVsZSA8LSByYXdfbnN1bV9tb2R1bGUgJT4lIA0KICBmaWx0ZXIoc2RfY2F0ZWdvcmllcyAhPSAwKSAlPiUgDQogIGZpbHRlcihzZF9uYW1lcyAhPSAwKQ0KDQpgYGANCg0KVGhpcmQgdGFzayBvZiBjbGVhbmluZyBpcyB0byBmaWx0ZXIgb3V0IHJlc3BvbnNlcyB0aGF0IGhhdmUgYSBoaWdoIGZyZXF1ZW5jeSBvZiA1MC8zNS8xNS4gV2UgY2hvc2UgdG8gZmlsdGVyIG91dCByZXNwb25zZXMgd2hlbiB0aGV5IGluZGljYXRlIHRoYXQgdGhleSBpbmRpY2F0ZSB0byBrbm93IDM1IHBlb3BsZSBmb3IgbW9yZSB0aGFuIHR3byBuYW1lcyBhbmQgbm93IDUwIHBlb3BsZSBmb3IgbW9yZSB0aGFuIG9uZSBuYW1lLiBXZSByZW1vdmUgOCByZXNwb25zZXMgdGhpcyB3YXkuIA0KDQpgYGB7ciBjaGVjayBoaWdoIGZyZXF1ZW5jaWVzfQ0KDQojZnVuY3Rpb25zIHRvIGNoZWNrIHByZXZhbGVuY2Ugb2YgYSB2YWx1ZSBpbiB2YXJpYWJsZQ0KY291bnRfZnJlcXVlbmN5X3ZhbHVlX2YgPC0gZnVuY3Rpb24ob2JqZWN0LCB2YWx1ZSl7DQogIHkgPC0gbGVuZ3RoKG9iamVjdFshaXMubmEob2JqZWN0KSAmIG9iamVjdCA9PSB2YWx1ZV0pDQp9DQoNCiNjaGVjayBmb3IgaGlnaCBmcmVxdWVuY3kgb2YgNTAuDQpyYXdfbnN1bV9tb2R1bGUgPC0gcmF3X25zdW1fbW9kdWxlICU+JQ0KICByb3d3aXNlKCkgJT4lDQogIG11dGF0ZSgNCiAgICBjb3VudF81MF9uYW1lcyA9IGNvdW50X2ZyZXF1ZW5jeV92YWx1ZV9mKG9iamVjdCA9IGNfYWNyb3NzKA0KICAgICAgYygNCiAgICAgICAga25vd3NfZGFhbiwNCiAgICAgICAga25vd3Nfa2V2aW4sDQogICAgICAgIGtub3dzX2Vkd2luLA0KICAgICAgICBrbm93c19hbGJlcnQsDQogICAgICAgIGtub3dzX2VtbWEsDQogICAgICAgIGtub3dzX2xpbmRhLA0KICAgICAgICBrbm93c19pbmdyaWQsDQogICAgICAgIGtub3dzX3dpbGxlbWluYSwNCiAgICAgICAga25vd3NfbW9oYW1tZWQsDQogICAgICAgIGtub3dzX2VzcmEsDQogICAgICAgIGtub3dzX2licmFoaW0sDQogICAgICAgIGtub3dzX2ZhdGltYQ0KICAgICAgKQ0KICAgICksDQogICAgdmFsdWUgPSA1MCksDQogICAgY291bnRfMzVfbmFtZXMgPSBjb3VudF9mcmVxdWVuY3lfdmFsdWVfZihvYmplY3QgPSBjX2Fjcm9zcygNCiAgICAgIGMoDQogICAgICAgIGtub3dzX2RhYW4sDQogICAgICAgIGtub3dzX2tldmluLA0KICAgICAgICBrbm93c19lZHdpbiwNCiAgICAgICAga25vd3NfYWxiZXJ0LA0KICAgICAgICBrbm93c19lbW1hLA0KICAgICAgICBrbm93c19saW5kYSwNCiAgICAgICAga25vd3NfaW5ncmlkLA0KICAgICAgICBrbm93c193aWxsZW1pbmEsDQogICAgICAgIGtub3dzX21vaGFtbWVkLA0KICAgICAgICBrbm93c19lc3JhLA0KICAgICAgICBrbm93c19pYnJhaGltLA0KICAgICAgICBrbm93c19mYXRpbWENCiAgICAgICkNCiAgICApLA0KICAgIHZhbHVlID0gMzUpLA0KICAgIGNvdW50XzE1X25hbWVzID0gY291bnRfZnJlcXVlbmN5X3ZhbHVlX2Yob2JqZWN0ID0gY19hY3Jvc3MoDQogICAgICBjKA0KICAgICAgICBrbm93c19kYWFuLA0KICAgICAgICBrbm93c19rZXZpbiwNCiAgICAgICAga25vd3NfZWR3aW4sDQogICAgICAgIGtub3dzX2FsYmVydCwNCiAgICAgICAga25vd3NfZW1tYSwNCiAgICAgICAga25vd3NfbGluZGEsDQogICAgICAgIGtub3dzX2luZ3JpZCwNCiAgICAgICAga25vd3Nfd2lsbGVtaW5hLA0KICAgICAgICBrbm93c19tb2hhbW1lZCwNCiAgICAgICAga25vd3NfZXNyYSwNCiAgICAgICAga25vd3NfaWJyYWhpbSwNCiAgICAgICAga25vd3NfZmF0aW1hDQogICAgICApDQogICAgKSwNCiAgICB2YWx1ZSA9IDE1KQ0KICApDQoNCiNmb3IgMzUsIHJlbW92ZSB0aG9zZSBwZW9wbGUgd2hvIGhhdmUgYSBoaWdoZXIgZnJlcXVlbmN5IHRoYW4gMiBmb3IgdGhlIG5hbWVzLg0KI2ZvciA1MCwgcmVtb3ZlIHRob3NlIHBlb3BsZSB3aG8gaGF2ZSBhIGhpZ2hlciBmcmVxdWVuY3kgdGhhbiA3IGZvciB0aGUgbmFtZXMuDQojd2UgcmVtb3ZlIDggbmFtZXMNCnNlbGVjdGlvbiA8LSByYXdfbnN1bV9tb2R1bGUgJT4lIA0KICBmaWx0ZXIoY291bnRfMzVfbmFtZXMgPCAzKSAlPiUgDQogIGZpbHRlcihjb3VudF81MF9uYW1lcyA8IDIpICU+JSANCiAgcHVsbChpZCkNCg0KI2NyZWF0ZSBzZWxlY3Rpb24gZnJvbSBuZWxscyBuc3VtIGZpbGUNCm5lbGxzX25zdW0gPC0gbmVsbHNfbnN1bSAlPiUgDQogIGZpbHRlcihpZCAlaW4lIHNlbGVjdGlvbikgJT4lIA0KICBhcnJhbmdlKGlkKQ0KYGBgDQoNCiMgRXRobmljIG5hbWVzDQpgYGB7ciBldGhuaWNpdHkgd2VpZ2h0ZWR9DQpuZWxsc19uc3VtIDwtIG5lbGxzX25zdW0gJT4lIA0KICBtdXRhdGUoa25vd3NfZXRobmljX2JvdW5kYXJ5ID0gKChrbm93c19tb2hhbW1lZCooMTM0NDgvMjAyMzMpKSArIChrbm93c19mYXRpbWEqKDI4MDgvMjAyMzMpKSArIChrbm93c19lc3JhKigxODc4LzIwMjMzKSkgKyAoa25vd3NfaWJyYWhpbSooMjA5OS8yMDIzMykpKS80KSANCg0KYGBgDQoNCg0KIyBDcmVhdGUgTlNVTSBtb2R1bGUNCg0KV2UgZG8gbm90IHVzZSBhbGwgb2YgdGhlIHF1ZXN0aW9ucyBmcm9tIHRoZSBOU1VNIG1vZHVsZS4gV2UgY3JlYXRlZCBhIG1vZHVsZSB3aXRoIG1vcmUgbmFtZXMgYW5kIGFuZCBhbHNvIG1vcmUgY2F0ZWdvcmllcyB3aG8gYXJlIHNwZWNpZmllZCB0byBwZW9wbGUgd2l0aCBhIG1pZ3JhdGlvbiBiYWNrZ3JvdW5kIHRoZW4gd2UgYWN0dWFsbHkgbmVlZCBvciB1c2UuIElmIHdlIHVzZSBtb3JlIG5hbWVzIG9yIGNhdGVnb3JpZXMgdGhhdCBtZWFzdXJlIGtub3dpbmcgc28tY2FsbGVkIG1pZ3JhdG5zIHdlIGluZmxhdGUgdGhlIG5ldHdvcmtzIG9mIHRoZXNlIGdyb3Vwcy4gU28gd2UgY29tZSB0byBhIGZpbmFsIHNlbGVjdGlvbiBvZiAxNiBwb3B1bGF0aW9ucyBmb3IgdGhlIG1haW4gTlNVTSBhbmFseXNpcy4gDQoNCg0KYGBge3IgbWlncmF0aW9uIGRhdGFwcmVwfQ0KI3JlbGV2ZWwgbWlncmF0aW9uIGJhY2tncm91bmQgYW5kIGNyZWF0ZSBzaW1wbGUgbWlncmF0aW9uIGJhY2tncm91bmQgDQpuZWxsc19uc3VtIDwtIG5lbGxzX25zdW0gJT4lDQogIG11dGF0ZSgNCiAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPSBmY3RfcmVsZXZlbCgNCiAgICAgIG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYywNCiAgICAgICJEdXRjaCIsDQogICAgICAiMXN0IGdlbiBUdXJraXNoIiwNCiAgICAgICIybmQgZ2VuIFR1cmtpc2giLA0KICAgICAgIjFzdCBnZW4gTW9yb2NjYW4iLA0KICAgICAgIjJuZCBnZW4gTW9yb2NjYW4iDQogICAgKSwNCiAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPSBmYWN0b3IoDQogICAgICBhcy5udW1lcmljKG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyksDQogICAgICBsZXZlbHMgPSAxOjUsDQogICAgICBsYWJlbHMgPSBjKA0KICAgICAgICAiRHV0Y2gtTWFqb3JpdHkiLA0KICAgICAgICAiMXN0IGdlbiBUdXJraXNoLUR1dGNoIiwNCiAgICAgICAgIjJuZCBnZW4gVHVya2lzaC1EdXRjaCIsDQogICAgICAgICIxc3QgZ2VuIE1vcm9jY2FuLUR1dGNoIiwNCiAgICAgICAgIjJuZCBnZW4gTW9yb2NjYW4tRHV0Y2giDQogICAgICApDQogICAgKSwNCiAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9zaW1wbGVfZmFjID0gY2FzZV93aGVuKA0KICAgICAgbWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICIxc3QgZ2VuIFR1cmtpc2gtRHV0Y2giIH4gMiwNCiAgICAgIG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyA9PSAiMm5kIGdlbiBUdXJraXNoLUR1dGNoIiB+IDIsDQogICAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIjFzdCBnZW4gTW9yb2NjYW4tRHV0Y2giIH4gMywNCiAgICAgIG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyA9PSAiMm5kIGdlbiBNb3JvY2Nhbi1EdXRjaCIgfiAzLA0KICAgICAgbWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICJEdXRjaC1NYWpvcml0eSIgfiAxDQogICAgKSwNCiAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9zaW1wbGVfZmFjID0gZmFjdG9yKA0KICAgICAgbWlncmF0aW9uX2JhY2tncm91bmRfc2ltcGxlX2ZhYywNCiAgICAgIGxldmVscyA9IDE6MywNCiAgICAgIGxhYmVscyA9IGMoIkR1dGNoLU1ham9yaXR5IiwgIlR1cmtpc2gtRHV0Y2giLCAiTW9yb2NjYW4tRHV0Y2giKQ0KICAgICkNCiAgKQ0KYGBgDQoNCkV4dHJhY3QgaW5mb3JtYXRpb24gZm9yIE5TVU0gYW5hbHlzaXMuIA0KDQpgYGB7ciBuc3VtIGlucHV0IHByZXB9DQojY3JlYXRlIG1hdHJpeA0KI3NlbGVjdCBvYnNlcnZhdGlvbnMgZnJvbSBuZWxsc19uc3VtDQpuc3VtX21vZGVsX3NlbGVjdGlvbiA8LSBuZWxsc19uc3VtICU+JSANCiAgYXJyYW5nZShpZCkgJT4lIA0KICBzZWxlY3Qoa25vd3NfZGFhbl9ib3VuZGFyeSwNCiAgICAgICAgIGtub3dzX2tldmluX2JvdW5kYXJ5LCANCiAgICAgICAgIGtub3dzX2Vkd2luX2JvdW5kYXJ5LA0KICAgICAgICAga25vd3NfYWxiZXJ0X2JvdW5kYXJ5LA0KICAgICAgICAga25vd3NfZW1tYV9ib3VuZGFyeSwNCiAgICAgICAgIGtub3dzX2xpbmRhX2JvdW5kYXJ5LA0KICAgICAgICAga25vd3NfaW5ncmlkX2JvdW5kYXJ5LA0KICAgICAgICAga25vd3Nfd2lsbGVtaW5hX2JvdW5kYXJ5LA0KICAgICAgICAga25vd3NfaWJyYWhpbV9ib3VuZGFyeSwNCiAgICAgICAgIGtub3dzX3ByaXNvbl9ib3VuZGFyeSwNCiAgICAgICAgIGtub3dzX21ibywNCiAgICAgICAgIGtub3dzX2hibywNCiAgICAgICAgIGtub3dzX3VuaXZlcnNpdHksDQogICAgICAgICBrbm93c19zZWN1bmRhcnksDQogICAgICAgICBrbm93c19zZWNvbmRob21lLA0KICAgICAgICAga25vd3NfdW5lbXBsb3llZCkNCg0KI29ic2VydmF0aW9ucw0KbWF0IDwtIG5zdW1fbW9kZWxfc2VsZWN0aW9uICU+JSANCiAgYXMubWF0cml4KCkNCg0KI2tub3duIHBvcHVsYXRpb24gaW5mb3JtYXRpb24NCiNpbXBvcnQgZnJlcXVlbmNpZXMNCm5zdW1fZnJlcXVlbmNpZXMgPC0gcmVhZF9jc3YoZmlsZSA9ICJkYXRhX2FuYWx5c2lzLzIwMjItMDgtMjZfbmFtZWZyZXF1ZW5jaWVzLmNzdiIpDQoNCiN2ZWN0b3Igd2l0aCBrbm93biBwb3B1bGF0aW9uIGluZm9ybWF0aW9uDQprbm93bl92ZWN0b3IgPC0ga25vd25fdmVjdG9yIDwtIG5zdW1fZnJlcXVlbmNpZXMgJT4lIA0KICBmaWx0ZXIobmFtZSAlaW4lIGMoDQogICAgImtub3dzX2RhYW4iLA0KICAgICJrbm93c19rZXZpbiIsIA0KICAgICJrbm93c19lZHdpbiIsDQogICAgImtub3dzX2FsYmVydCIsDQogICAgImtub3dzX2VtbWEiLA0KICAgICJrbm93c19saW5kYSIsDQogICAgImtub3dzX2luZ3JpZCIsDQogICAgImtub3dzX3dpbGxlbWluYSIsDQogICAgImtub3dzX2licmFoaW0iLA0KICAgICJrbm93c19wcmlzb24iLA0KICAgICJrbm93c19tYm8iLA0KICAgICJrbm93c19oYm8iLA0KICAgICJrbm93c191bml2ZXJzaXR5IiwNCiAgICAia25vd3Nfc2VjdW5kYXJ5IiwNCiAgICAia25vd3Nfc2Vjb25kaG9tZSIsDQogICAgImtub3dzX3VuZW1wbG95ZWQiDQogICkpICU+JSANCiAgcHVsbChudW1iZXIpDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQojZXhwb3J0IGFuYWx5c2lzIG1hdHJpeCBhbmQga25vd24gdmVjdG9yDQphbmFseXNpc19maWxlc19zZWxlY3Rpb24gPC0gbGlzdChtYXQsIGtub3duX3ZlY3RvcikNCg0Kc2F2ZShhbmFseXNpc19maWxlc19zZWxlY3Rpb24sIGZpbGUgPSAiZGF0YV9hbmFseXNpcy9kYXRhL2RhdGFfcHJvY2Vzc2VkL25zdW1faW5wdXQvMjAyMy0wNC0xMV9hbmFseXNpc19maWxlc19zZWxlY3Rpb24ucmRzIikNCmBgYA0KDQoNCmBgYHtyIG5zdW0gaW5wdXQgcHJlcCAyfQ0KI2NyZWF0ZSBtYXRyaXgNCiNzZWxlY3Qgb2JzZXJ2YXRpb25zIGZyb20gbmVsbHNfbnN1bQ0KbnN1bV9tb2RlbF9zZWxlY3Rpb25fMiA8LSBuZWxsc19uc3VtICU+JSANCiAgYXJyYW5nZShpZCkgJT4lIA0KICBzZWxlY3Qoa25vd3NfZGFhbl9ib3VuZGFyeSwNCiAgICAgICAgIGtub3dzX2tldmluX2JvdW5kYXJ5LCANCiAgICAgICAgIGtub3dzX2Vkd2luX2JvdW5kYXJ5LA0KICAgICAgICAga25vd3NfYWxiZXJ0X2JvdW5kYXJ5LA0KICAgICAgICAga25vd3NfZW1tYV9ib3VuZGFyeSwNCiAgICAgICAgIGtub3dzX2xpbmRhX2JvdW5kYXJ5LA0KICAgICAgICAga25vd3NfaW5ncmlkX2JvdW5kYXJ5LA0KICAgICAgICAga25vd3Nfd2lsbGVtaW5hX2JvdW5kYXJ5LA0KICAgICAgICAga25vd3NfZXRobmljX2JvdW5kYXJ5LA0KICAgICAgICAga25vd3NfcHJpc29uX2JvdW5kYXJ5LA0KICAgICAgICAga25vd3NfbWJvLA0KICAgICAgICAga25vd3NfaGJvLA0KICAgICAgICAga25vd3NfdW5pdmVyc2l0eSwNCiAgICAgICAgIGtub3dzX3NlY3VuZGFyeSwNCiAgICAgICAgIGtub3dzX3NlY29uZGhvbWUsDQogICAgICAgICBrbm93c191bmVtcGxveWVkKQ0KDQojb2JzZXJ2YXRpb25zDQptYXRfMiA8LSBuc3VtX21vZGVsX3NlbGVjdGlvbl8yICU+JSANCiAgYXMubWF0cml4KCkNCg0KI3ZlY3RvciB3aXRoIGtub3duIHBvcHVsYXRpb24gaW5mb3JtYXRpb24NCmtub3duX3ZlY3Rvcl8yIDwtIG5zdW1fZnJlcXVlbmNpZXMgJT4lIA0KICBtdXRhdGUobnVtYmVyID0gaWZlbHNlKG5hbWUgPT0gImtub3dzX2licmFoaW0iLCAyMDIzMywgbnVtYmVyKSkgJT4lIA0KICBmaWx0ZXIobmFtZSAlaW4lIGMoDQogICAgImtub3dzX2RhYW4iLA0KICAgICJrbm93c19rZXZpbiIsIA0KICAgICJrbm93c19lZHdpbiIsDQogICAgImtub3dzX2FsYmVydCIsDQogICAgImtub3dzX2VtbWEiLA0KICAgICJrbm93c19saW5kYSIsDQogICAgImtub3dzX2luZ3JpZCIsDQogICAgImtub3dzX3dpbGxlbWluYSIsDQogICAgImtub3dzX2licmFoaW0iLA0KICAgICJrbm93c19wcmlzb24iLA0KICAgICJrbm93c19tYm8iLA0KICAgICJrbm93c19oYm8iLA0KICAgICJrbm93c191bml2ZXJzaXR5IiwNCiAgICAia25vd3Nfc2VjdW5kYXJ5IiwNCiAgICAia25vd3Nfc2Vjb25kaG9tZSIsDQogICAgImtub3dzX3VuZW1wbG95ZWQiDQogICkpICU+JSANCiAgcHVsbChudW1iZXIpDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQojZXhwb3J0IGFuYWx5c2lzIG1hdHJpeCBhbmQga25vd24gdmVjdG9yDQphbmFseXNpc19maWxlc19zZWxlY3Rpb25fMiA8LSBsaXN0KG1hdF8yLCBrbm93bl92ZWN0b3JfMikNCg0Kc2F2ZShhbmFseXNpc19maWxlc19zZWxlY3Rpb25fMiwgZmlsZSA9ICJkYXRhX2FuYWx5c2lzL2RhdGEvZGF0YV9wcm9jZXNzZWQvbnN1bV9pbnB1dC8yMDIzLTA0LTExX2FuYWx5c2lzX2ZpbGVzX3NlbGVjdGlvbl8yLnJkcyIpDQpgYGANCg0KDQojIENyZWF0ZSBtb2RlbCBmaWxlIGZvciBlYWNoIHN1Ymdyb3VwDQoNCiMjIEZ1bGwgbW9kZWwNCg0KYGBge3IgY3JlYXRlIGZpbGUgZm9yIGxvb3AgKGZ1bGwgbW9kZWwpfQ0KI2NyZWF0ZSBmdW5jdGlvbiB0byB1c2UgaW4gbG9vcA0KbnN1bV9mdWxsX21vZGVsX3ByZXBhcmUgPC0gZnVuY3Rpb24oZGF0YWZyYW1lLCBrbm93bl9kZikgeyAjZGF0YWZyYW1lID0gZ3JvdXBfbGlzdFtbMV1dDQogIGRmIDwtIGRhdGFmcmFtZSAlPiUNCiAgICBhcnJhbmdlKGlkKSAlPiUgI2FycmFuZ2Ugb24gaWQgc28gd2UgY2FuIG1lcmdlIHRoZSByZXN1bHRzDQogICAgc2VsZWN0KCAjb25seSBzZWxlY3QgaW5mb3JtYXRpb24gd2UgbmVlZA0KICAgICAga25vd3NfZGFhbl9ib3VuZGFyeSwNCiAgICAgIGtub3dzX2tldmluX2JvdW5kYXJ5LA0KICAgICAga25vd3NfZWR3aW5fYm91bmRhcnksDQogICAgICBrbm93c19hbGJlcnRfYm91bmRhcnksDQogICAgICBrbm93c19lbW1hX2JvdW5kYXJ5LA0KICAgICAga25vd3NfbGluZGFfYm91bmRhcnksDQogICAgICBrbm93c19pbmdyaWRfYm91bmRhcnksDQogICAgICBrbm93c193aWxsZW1pbmFfYm91bmRhcnksDQogICAgICBrbm93c19pYnJhaGltX2JvdW5kYXJ5LA0KICAgICAga25vd3NfcHJpc29uX2JvdW5kYXJ5LA0KICAgICAga25vd3NfbWJvLA0KICAgICAga25vd3NfaGJvLA0KICAgICAga25vd3NfdW5pdmVyc2l0eSwNCiAgICAgIGtub3dzX3NlY3VuZGFyeSwNCiAgICAgIGtub3dzX3NlY29uZGhvbWUsDQogICAgICBrbm93c191bmVtcGxveWVkDQogICAgKQ0KICANCiAgbWF0IDwtIGRmICU+JSANCiAgYXMubWF0cml4KCkNCiAgDQogIGtub3duX3ZlY3RvciA8LSBrbm93bl9kZiAlPiUgDQogIGZpbHRlcihuYW1lICVpbiUgYygNCiAgICAia25vd3NfZGFhbiIsDQogICAgImtub3dzX2tldmluIiwgDQogICAgImtub3dzX2Vkd2luIiwNCiAgICAia25vd3NfYWxiZXJ0IiwNCiAgICAia25vd3NfZW1tYSIsDQogICAgImtub3dzX2xpbmRhIiwNCiAgICAia25vd3NfaW5ncmlkIiwNCiAgICAia25vd3Nfd2lsbGVtaW5hIiwNCiAgICAia25vd3NfaWJyYWhpbSIsDQogICAgImtub3dzX3ByaXNvbiIsDQogICAgImtub3dzX21ibyIsDQogICAgImtub3dzX2hibyIsDQogICAgImtub3dzX3VuaXZlcnNpdHkiLA0KICAgICJrbm93c19zZWN1bmRhcnkiLA0KICAgICJrbm93c19zZWNvbmRob21lIiwNCiAgICAia25vd3NfdW5lbXBsb3llZCINCiAgKSkgJT4lIA0KICBwdWxsKG51bWJlcikNCiAgDQogIG5zdW1fbW9kZWxfc2VsZWN0aW9uIDwtIGxpc3QobWF0LCBrbm93bl92ZWN0b3IpDQogIA0KICByZXR1cm4obnN1bV9tb2RlbF9zZWxlY3Rpb24pDQp9DQoNCiNjcmVhdGUgbGlzdCBmb3IgbG9vcA0KZ3JvdXBfbGlzdCA8LSBuZWxsc19uc3VtICU+JSANCiAgZ3JvdXBfc3BsaXQobWlncmF0aW9uX2JhY2tncm91bmRfc2ltcGxlX2ZhYykNCg0KI3JlcGxhY2Ugb3RoZXIgd2l0aCBmdWxsIHNhbXBsZQ0KZ3JvdXBfbGlzdFtbNF1dIDwtIG5lbGxzX25zdW0NCg0KI2FwcGx5IG1hcCBhbmQgc2F2ZSByZXN1bHQNCmZ1bGxfbW9kZWxfZ3JvdXBzIDwtIGdyb3VwX2xpc3QgJT4lIA0KICBtYXAoLnggPSAuLA0KICAgICAgLmYgPSB+IG5zdW1fZnVsbF9tb2RlbF9wcmVwYXJlKGRhdGFmcmFtZSA9IC54LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrbm93bl9kZiA9IG5zdW1fZnJlcXVlbmNpZXMpKQ0KDQoNCiNhZGQgbmFtZXMNCm5hbWVzKGZ1bGxfbW9kZWxfZ3JvdXBzKSA8LSBjKCJEdXRjaC1NYWpvcml0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVHVya2lzaC1EdXRjaCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTW9yb2NjYW4tRHV0Y2giLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGdWxsIHNhbXBsZSIpDQpgYGANCg0KDQojIyAgTW9kZWwgd2l0aCBvbmx5IGNhdGVnb3JpZXMNCg0KYGBge3IgY3JlYXRlIGZpbGUgZm9yIGxvb3AgKGNhdGVnb3JpZXMpfQ0KI2NyZWF0ZSBmdW5jdGlvbiB0byB1c2UgaW4gbG9vcA0KbnN1bV9jYXRlZ29yeV9tb2RlbF9wcmVwYXJlIDwtIGZ1bmN0aW9uKGRhdGFmcmFtZSwga25vd25fZGYpIHsgI2RhdGFmcmFtZSA9IGdyb3VwX2xpc3RbWzFdXQ0KICBkZiA8LSBkYXRhZnJhbWUgJT4lDQogICAgYXJyYW5nZShpZCkgJT4lICNhcnJhbmdlIG9uIGlkIHNvIHdlIGNhbiBtZXJnZSB0aGUgcmVzdWx0cw0KICAgIHNlbGVjdCggI29ubHkgc2VsZWN0IGluZm9ybWF0aW9uIHdlIG5lZWQNCiAgICAgIGtub3dzX3ByaXNvbl9ib3VuZGFyeSwNCiAgICAgIGtub3dzX21ibywNCiAgICAgIGtub3dzX2hibywNCiAgICAgIGtub3dzX3VuaXZlcnNpdHksDQogICAgICBrbm93c19zZWN1bmRhcnksDQogICAgICBrbm93c19zZWNvbmRob21lLA0KICAgICAga25vd3NfdW5lbXBsb3llZA0KICAgICkNCiAgDQogIG1hdCA8LSBkZiAlPiUgDQogIGFzLm1hdHJpeCgpDQogIA0KICBrbm93bl92ZWN0b3IgPC0ga25vd25fZGYgJT4lIA0KICBmaWx0ZXIobmFtZSAlaW4lIGMoDQogICAgImtub3dzX3ByaXNvbiIsDQogICAgImtub3dzX21ibyIsDQogICAgImtub3dzX2hibyIsDQogICAgImtub3dzX3VuaXZlcnNpdHkiLA0KICAgICJrbm93c19zZWN1bmRhcnkiLA0KICAgICJrbm93c19zZWNvbmRob21lIiwNCiAgICAia25vd3NfdW5lbXBsb3llZCINCiAgKSkgJT4lIA0KICBwdWxsKG51bWJlcikNCiAgDQogIG5zdW1fbW9kZWxfc2VsZWN0aW9uIDwtIGxpc3QobWF0LCBrbm93bl92ZWN0b3IpDQogIA0KICByZXR1cm4obnN1bV9tb2RlbF9zZWxlY3Rpb24pDQp9DQoNCiNhcHBseSBtYXAgYW5kIHNhdmUgcmVzdWx0DQpjYXRfbW9kZWxfZ3JvdXBzIDwtIGdyb3VwX2xpc3QgJT4lIA0KICBtYXAoLnggPSAuLA0KICAgICAgLmYgPSB+IG5zdW1fY2F0ZWdvcnlfbW9kZWxfcHJlcGFyZShkYXRhZnJhbWUgPSAueCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga25vd25fZGYgPSBuc3VtX2ZyZXF1ZW5jaWVzKSkNCg0KDQojYWRkIG5hbWVzDQpuYW1lcyhjYXRfbW9kZWxfZ3JvdXBzKSA8LSBjKCJEdXRjaC1NYWpvcml0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVHVya2lzaC1EdXRjaCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTW9yb2NjYW4tRHV0Y2giLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGdWxsIHNhbXBsZSIpDQpgYGANCg0KDQojIyAgTW9kZWwgd2l0aCBvbmx5IGV0aG5pYyBjYXRlZ29yaWVzDQoNCmBgYHtyIGNyZWF0ZSBmaWxlIGZvciBsb29wIChtaWdyYW50KX0NCiNjcmVhdGUgZnVuY3Rpb24gdG8gdXNlIGluIGxvb3ANCm5zdW1fZXRobmljbmFtZXNfbW9kZWxfcHJlcGFyZSA8LSBmdW5jdGlvbihkYXRhZnJhbWUsIGtub3duX2RmKSB7ICNkYXRhZnJhbWUgPSBncm91cF9saXN0W1sxXV0NCiAgZGYgPC0gZGF0YWZyYW1lICU+JQ0KICAgIGFycmFuZ2UoaWQpICU+JSAjYXJyYW5nZSBvbiBpZCBzbyB3ZSBjYW4gbWVyZ2UgdGhlIHJlc3VsdHMNCiAgICBzZWxlY3QoICNvbmx5IHNlbGVjdCBpbmZvcm1hdGlvbiB3ZSBuZWVkDQogICAgICBrbm93c19tb2hhbW1lZF9ib3VuZGFyeSwNCiAgICAgIGtub3dzX2ZhdGltYV9ib3VuZGFyeSwNCiAgICAgIGtub3dzX2VzcmFfYm91bmRhcnksDQogICAgICBrbm93c19pYnJhaGltX2JvdW5kYXJ5DQogICAgKQ0KICANCiAgbWF0IDwtIGRmICU+JSANCiAgYXMubWF0cml4KCkNCiAgDQogIGtub3duX3ZlY3RvciA8LSBrbm93bl9kZiAlPiUgDQogIGZpbHRlcihuYW1lICVpbiUgYygNCiAgICAia25vd3NfbW9oYW1tZWQiLA0KICAgICJrbm93c19mYXRpbWEiLA0KICAgICJrbm93c19lc3JhIiwNCiAgICAia25vd3NfaWJyYWhpbSINCiAgKSkgJT4lIA0KICBwdWxsKG51bWJlcikNCiAgDQogIG5zdW1fbW9kZWxfc2VsZWN0aW9uIDwtIGxpc3QobWF0LCBrbm93bl92ZWN0b3IpDQogIA0KICByZXR1cm4obnN1bV9tb2RlbF9zZWxlY3Rpb24pDQp9DQoNCiNhcHBseSBtYXAgYW5kIHNhdmUgcmVzdWx0DQpldGhuaWNuYW1lc19tb2RlbF9ncm91cHMgPC0gZ3JvdXBfbGlzdCAlPiUgDQogIG1hcCgueCA9IC4sDQogICAgICAuZiA9IH4gbnN1bV9ldGhuaWNuYW1lc19tb2RlbF9wcmVwYXJlKGRhdGFmcmFtZSA9IC54LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrbm93bl9kZiA9IG5zdW1fZnJlcXVlbmNpZXMpKQ0KDQoNCiNhZGQgbmFtZXMNCm5hbWVzKGV0aG5pY25hbWVzX21vZGVsX2dyb3VwcykgPC0gYygiRHV0Y2gtTWFqb3JpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlR1cmtpc2gtRHV0Y2giLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1vcm9jY2FuLUR1dGNoIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRnVsbCBzYW1wbGUiKQ0KYGBgDQoNCg0KIyMgIE1vZGVsIHdpdGggb25seSBtYWpvcml0eSBjYXRlZ29yaWVzDQoNCmBgYHtyIGNyZWF0ZSBmaWxlIGZvciBsb29wIChtYWpvcml0eSl9DQojY3JlYXRlIGZ1bmN0aW9uIHRvIHVzZSBpbiBsb29wDQpuc3VtX21hal9tb2RlbF9wcmVwYXJlIDwtIGZ1bmN0aW9uKGRhdGFmcmFtZSwga25vd25fZGYpIHsgI2RhdGFmcmFtZSA9IGdyb3VwX2xpc3RbWzFdXQ0KICBkZiA8LSBkYXRhZnJhbWUgJT4lDQogICAgYXJyYW5nZShpZCkgJT4lICNhcnJhbmdlIG9uIGlkIHNvIHdlIGNhbiBtZXJnZSB0aGUgcmVzdWx0cw0KICAgIHNlbGVjdCggI29ubHkgc2VsZWN0IGluZm9ybWF0aW9uIHdlIG5lZWQNCiAgICAgIGtub3dzX2RhYW5fYm91bmRhcnksDQogICAgICBrbm93c19rZXZpbl9ib3VuZGFyeSwNCiAgICAgIGtub3dzX2Vkd2luX2JvdW5kYXJ5LA0KICAgICAga25vd3NfYWxiZXJ0X2JvdW5kYXJ5LA0KICAgICAga25vd3NfZW1tYV9ib3VuZGFyeSwNCiAgICAgIGtub3dzX2xpbmRhX2JvdW5kYXJ5LA0KICAgICAga25vd3NfaW5ncmlkX2JvdW5kYXJ5LA0KICAgICAga25vd3Nfd2lsbGVtaW5hX2JvdW5kYXJ5DQogICAgKQ0KICANCiAgbWF0IDwtIGRmICU+JSANCiAgYXMubWF0cml4KCkNCiAgDQogIGtub3duX3ZlY3RvciA8LSBrbm93bl9kZiAlPiUgDQogIGZpbHRlcihuYW1lICVpbiUgYygNCiAgICAia25vd3NfZGFhbiIsDQogICAgImtub3dzX2tldmluIiwgDQogICAgImtub3dzX2Vkd2luIiwNCiAgICAia25vd3NfYWxiZXJ0IiwNCiAgICAia25vd3NfZW1tYSIsDQogICAgImtub3dzX2xpbmRhIiwNCiAgICAia25vd3NfaW5ncmlkIiwNCiAgICAia25vd3Nfd2lsbGVtaW5hIg0KICApKSAlPiUgDQogIHB1bGwobnVtYmVyKQ0KICANCiAgbnN1bV9tb2RlbF9zZWxlY3Rpb24gPC0gbGlzdChtYXQsIGtub3duX3ZlY3RvcikNCiAgDQogIHJldHVybihuc3VtX21vZGVsX3NlbGVjdGlvbikNCn0NCg0KI2FwcGx5IG1hcCBhbmQgc2F2ZSByZXN1bHQNCm1hal9tb2RlbF9ncm91cHMgPC0gZ3JvdXBfbGlzdCAlPiUgDQogIG1hcCgueCA9IC4sDQogICAgICAuZiA9IH4gbnN1bV9tYWpfbW9kZWxfcHJlcGFyZShkYXRhZnJhbWUgPSAueCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga25vd25fZGYgPSBuc3VtX2ZyZXF1ZW5jaWVzKSkNCg0KI2FkZCBuYW1lcw0KbmFtZXMobWFqX21vZGVsX2dyb3VwcykgPC0gYygiRHV0Y2gtTWFqb3JpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlR1cmtpc2gtRHV0Y2giLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1vcm9jY2FuLUR1dGNoIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRnVsbCBzYW1wbGUiKQ0KYGBgDQoNCiMjIE1vZGVsIHdpdGggYWxsIG5hbWVzDQoNCmBgYHtyIGNyZWF0ZSBmaWxlIGZvciBsb29wIChhbGwgbmFtZXMpfQ0KI2NyZWF0ZSBmdW5jdGlvbiB0byB1c2UgaW4gbG9vcA0KbnN1bV9uYW1lc19tb2RlbF9wcmVwYXJlIDwtIGZ1bmN0aW9uKGRhdGFmcmFtZSwga25vd25fZGYpIHsgI2RhdGFmcmFtZSA9IGdyb3VwX2xpc3RbWzFdXQ0KICBkZiA8LSBkYXRhZnJhbWUgJT4lDQogICAgYXJyYW5nZShpZCkgJT4lICNhcnJhbmdlIG9uIGlkIHNvIHdlIGNhbiBtZXJnZSB0aGUgcmVzdWx0cw0KICAgIHNlbGVjdCggI29ubHkgc2VsZWN0IGluZm9ybWF0aW9uIHdlIG5lZWQNCiAgICAgIGtub3dzX2RhYW5fYm91bmRhcnksDQogICAgICBrbm93c19rZXZpbl9ib3VuZGFyeSwNCiAgICAgIGtub3dzX2Vkd2luX2JvdW5kYXJ5LA0KICAgICAga25vd3NfYWxiZXJ0X2JvdW5kYXJ5LA0KICAgICAga25vd3NfZW1tYV9ib3VuZGFyeSwNCiAgICAgIGtub3dzX2xpbmRhX2JvdW5kYXJ5LA0KICAgICAga25vd3NfaW5ncmlkX2JvdW5kYXJ5LA0KICAgICAga25vd3Nfd2lsbGVtaW5hX2JvdW5kYXJ5LA0KICAgICAga25vd3NfbW9oYW1tZWRfYm91bmRhcnksDQogICAgICBrbm93c19mYXRpbWFfYm91bmRhcnksDQogICAgICBrbm93c19lc3JhX2JvdW5kYXJ5LA0KICAgICAga25vd3NfaWJyYWhpbV9ib3VuZGFyeQ0KICAgICkNCiAgDQogIG1hdCA8LSBkZiAlPiUgDQogIGFzLm1hdHJpeCgpDQogIA0KICBrbm93bl92ZWN0b3IgPC0ga25vd25fZGYgJT4lIA0KICBmaWx0ZXIobmFtZSAlaW4lIGMoDQogICAgImtub3dzX2RhYW4iLA0KICAgICJrbm93c19rZXZpbiIsIA0KICAgICJrbm93c19lZHdpbiIsDQogICAgImtub3dzX2FsYmVydCIsDQogICAgImtub3dzX2VtbWEiLA0KICAgICJrbm93c19saW5kYSIsDQogICAgImtub3dzX2luZ3JpZCIsDQogICAgImtub3dzX3dpbGxlbWluYSIsDQogICAgImtub3dzX21vaGFtbWVkIiwNCiAgICAia25vd3NfZmF0aW1hIiwNCiAgICAia25vd3NfZXNyYSIsDQogICAgImtub3dzX2licmFoaW0iDQogICkpICU+JSANCiAgcHVsbChudW1iZXIpDQogIA0KICBuc3VtX21vZGVsX3NlbGVjdGlvbiA8LSBsaXN0KG1hdCwga25vd25fdmVjdG9yKQ0KICANCiAgcmV0dXJuKG5zdW1fbW9kZWxfc2VsZWN0aW9uKQ0KfQ0KDQojYXBwbHkgbWFwIGFuZCBzYXZlIHJlc3VsdA0KbmFtZXNfbW9kZWxfZ3JvdXBzIDwtIGdyb3VwX2xpc3QgJT4lIA0KICBtYXAoLnggPSAuLA0KICAgICAgLmYgPSB+IG5zdW1fbmFtZXNfbW9kZWxfcHJlcGFyZShkYXRhZnJhbWUgPSAueCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga25vd25fZGYgPSBuc3VtX2ZyZXF1ZW5jaWVzKSkNCg0KDQojYWRkIG5hbWVzDQpuYW1lcyhuYW1lc19tb2RlbF9ncm91cHMpIDwtIGMoIkR1dGNoLU1ham9yaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUdXJraXNoLUR1dGNoIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNb3JvY2Nhbi1EdXRjaCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkZ1bGwgc2FtcGxlIikNCmBgYA0KDQojIyBDb21iaW5lIHJvYnVzdG5lc3MgZGF0YSANCg0KYGBge3IgY29tYmluZSByb2J1c3RuZXNzIGRhdGFmaWxlc30NCnJvYnVzdG5lc3NfZGZzIDwtIGxpc3QoZnVsbF9tb2RlbF9ncm91cHMsIA0KICAgICBjYXRfbW9kZWxfZ3JvdXBzLA0KICAgICBldGhuaWNuYW1lc19tb2RlbF9ncm91cHMsDQogICAgIG1hal9tb2RlbF9ncm91cHMsDQogICAgIG5hbWVzX21vZGVsX2dyb3Vwcw0KICAgICApDQoNCm5hbWVzKHJvYnVzdG5lc3NfZGZzKSA8LSBjKCJmdWxsX21vZGVsX2dyb3VwcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAiY2F0X21vZGVsX2dyb3VwcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAiZXRobmljbmFtZXNfbW9kZWxfZ3JvdXBzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJtYWpfbW9kZWxfZ3JvdXBzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJuYW1lc19tb2RlbF9ncm91cHMiKSANCnNhdmUocm9idXN0bmVzc19kZnMsIA0KICAgICBmaWxlID0gImRhdGFfYW5hbHlzaXMvZGF0YS9kYXRhX3Byb2Nlc3NlZC9uc3VtX2lucHV0LzIwMjMtMDQtMjFfcm9idXN0bmVzcy1kZnMucmRhIikNCg0KYGBgDQoNCg0KIyBFeHBvcnQgZGF0YQ0KDQpgYGB7ciBleHBvcnQgZGF0YSB9DQojZXhwb3J0IGRhdGFmaWxlDQpzYXZlKG5lbGxzX25zdW0sIGZpbGUgPSAiZGF0YV9hbmFseXNpcy9kYXRhL2RhdGFfcHJvY2Vzc2VkL25lbGxzX2RhdGEvMjAyMy0wNS0wOF9uZWxscy1uc3VtLXByZXBwZWQtZGF0YS5yZHMiKQ0KDQpgYGANCg0KDQoNCg0KDQoNCg0K


Copyright © 2024 Jeroense Thijmen