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