Diane, Jane, and Kimberly.
Everything before 15 - analysis is a syntax to match all children.
I know errors happen all the time. Therefore, these codes were made available here if someone wants to review or check the consistency.
In the e-mail that you found this link, I attached an excel file in which you’ll be able to check this file.
Please notice that this report refers to birth to three only
If you don’t want to check any code, please click here
load package
pacman::p_load(tidyverse, janitor)
Data handling
get all ASQ4 data
read_excel_allsheets <- function(filename) {
sheets <- readxl::excel_sheets(filename) #get all sheet names
x <- lapply(sheets, function(X) readxl::read_excel(filename, sheet = X))
names(x) <- sheets #get names only
x #return
}
#get the excel file
excel_list <- read_excel_allsheets("C:/Users/luisf/Dropbox/ASQ4_AEPS Data for Luis 2.2021/Luis Feb 2021/Final ALL ASQ4 for AEPS 2019_2020.xlsx")
#transform into vectors
list2env(setNames(excel_list, #list
paste0("ds_",janitor::make_clean_names(names(excel_list)))), #fixing different names and other patterns
envir=.GlobalEnv) #where?
Create a backup
backup_asq4_demo <- ds_asq4_demo
backup_asq4_items <- ds_asq4_items
#remove all attributes
#ds_asq4_demo[] <- lapply(ds_asq4_demo, function(x) { attributes(x) <- NULL; x })
#backup_asq4_items[] <- lapply(backup_asq4_items, function(x) { attributes(x) <- NULL; x })
clean names
ds_asq4_demo <- clean_names(ds_asq4_demo)
ds_asq4_items <- clean_names(ds_asq4_items)
merge datasets
ds_asq <- left_join(ds_asq4_demo, ds_asq4_items, by = c("asq4_id"))
Compute totals
Change variable computational level
ds_asq <- ds_asq %>%
mutate_at(vars(c1:c6, gm1:gm6, fm1:fm6, ps1:ps6, p1:p6), ~as.numeric(.))
Compute totals for each ASQ-4 domain
ds_asq<-ds_asq %>%
mutate(com_sum = rowSums(select(.,c1:c6))) %>%
mutate(gm_sum = rowSums(select(.,gm1:gm6))) %>%
mutate(fm_sum = rowSums(select(.,fm1:fm6))) %>%
mutate(ps_sum = rowSums(select(.,ps1:ps6))) %>%
mutate(per_sum = rowSums(select(.,p1:p6)))
AEPS Demographics
aeps_1_demo <- readxl::read_excel("C:/Users/luisf/Dropbox/ASQ4_AEPS Data for Luis 2.2021/Luis Feb 2021/copy KM Cleaned AEPS 3.5.21/1.Cleaned AEPSBirthToThreeFormNoN 2 Grace 9.13.2019.xlsx", sheet = 2)
#fix names
aeps_1_demo <- clean_names(aeps_1_demo)
#remove empty columns and rows
aeps_1_demo <- remove_empty(aeps_1_demo, which = c("rows", "cols"), quiet = TRUE)
#remove useless rows
aeps_1_demo <- aeps_1_demo %>% filter(!is.na(childs_id))
#add new features to merge
aeps_1_demo <- aeps_1_demo %>%
mutate(aeps_file_number = 1) %>% #same as ds_asq
mutate(spread_sheet = spread_sheet_id_1) %>% #same as full dataset!
mutate(aeps_sprdsheet_id_number = spread_sheet_id_1) #same as ds_asq
1.AEPSBirthToThreeFormNoN 2 Grace 9.13.2019
First file 1 - Fine motor (1)
get data
aeps_1_fine <- readxl::read_excel("C:/Users/luisf/Dropbox/ASQ4_AEPS Data for Luis 2.2021/Luis Feb 2021/copy KM Cleaned AEPS 3.5.21/1.Cleaned AEPSBirthToThreeFormNoN 2 Grace 9.13.2019.xlsx", sheet = 3)
#clear excel attributes
aeps_1_fine[] <- lapply(aeps_1_fine, function(x) { attributes(x) <- NULL; x })
#fix names
aeps_1_fine <- clean_names(aeps_1_fine)
#remove empty columns and rows
aeps_1_fine <- remove_empty(aeps_1_fine, which = c("rows", "cols"), quiet = TRUE)
#create a skill
aeps_1_fine <- aeps_1_fine %>%
mutate(skill = .[[1]]) %>% #this is the first column )in this case -- fine motor (sub)domain
select(1,skill, everything())
#With this new variable (skill), just keep if is a letter
aeps_1_fine <- aeps_1_fine %>%
mutate(skill = if_else(str_detect(skill, "[a-z]"), .[[1]], NA_character_)) %>% #if skill is a letter, otherwise missing
fill(skill)
#remove first line (it's almost all na)
aeps_1_fine <- aeps_1_fine %>%
filter(!str_detect(.[[1]], "[a-z]"))
#transform to numeric
aeps_1_fine <- aeps_1_fine %>% mutate(!! names(.)[1] := as.numeric(!! rlang::sym(names(.)[1])))
#aeps_1_fine[[1]] <- as.numeric(aeps_1_fine[[1]])
Add domain
This chunk will get all domains and number skills. It will be useful to merge all ds in the future.
aeps_1_fine_long <- aeps_1_fine_long %>%
mutate(domain = names(.)[[1]]) %>%
rename(number_skill = names(.)[[1]]) %>%
select(domain, number_skill, everything())
First file 1 - Gross motor (2)
get data
aeps_1_gross <- readxl::read_excel("C:/Users/luisf/Dropbox/ASQ4_AEPS Data for Luis 2.2021/Luis Feb 2021/copy KM Cleaned AEPS 3.5.21/1.Cleaned AEPSBirthToThreeFormNoN 2 Grace 9.13.2019.xlsx", sheet = 4)
#clear excel attributes
aeps_1_gross[] <- lapply(aeps_1_gross, function(x) { attributes(x) <- NULL; x })
#fix names
aeps_1_gross <- clean_names(aeps_1_gross)
#remove empty columns and rows
aeps_1_gross <- remove_empty(aeps_1_gross, which = c("rows", "cols"), quiet = TRUE)
#create a skill
aeps_1_gross <- aeps_1_gross %>%
mutate(skill = .[[1]]) %>% #this is the first column )in this case -- fine motor (sub)domain
select(1,skill, everything())
#With this new variable (skill), just keep if is a letter
aeps_1_gross <- aeps_1_gross %>%
mutate(skill = if_else(str_detect(skill, "[a-z]"), .[[1]], NA_character_)) %>% #if skill is a letter, otherwise missing
fill(skill)
#remove first line (it's almost all na)
aeps_1_gross <- aeps_1_gross %>%
filter(!str_detect(.[[1]], "[a-z]"))
#transform to numeric
aeps_1_gross <- aeps_1_gross %>% mutate(!! names(.)[1] := as.numeric(!! rlang::sym(names(.)[1])))
#aeps_1_gross[[1]] <- as.numeric(aeps_1_gross[[1]])
Add domain
This chunk will get all domains and number skills. It will be useful to merge all ds in the future.
aeps_1_gross_long <- aeps_1_gross_long %>%
mutate(domain = names(.)[[1]]) %>%
rename(number_skill = names(.)[[1]]) %>%
select(domain, number_skill, everything())
First file 1 - Adaptive (3)
get data
aeps_1_adaptive <- readxl::read_excel("C:/Users/luisf/Dropbox/ASQ4_AEPS Data for Luis 2.2021/Luis Feb 2021/copy KM Cleaned AEPS 3.5.21/1.Cleaned AEPSBirthToThreeFormNoN 2 Grace 9.13.2019.xlsx", sheet = 5)
#clear excel attributes
aeps_1_adaptive[] <- lapply(aeps_1_adaptive, function(x) { attributes(x) <- NULL; x })
#fix names
aeps_1_adaptive <- clean_names(aeps_1_adaptive)
#remove empty columns and rows
aeps_1_adaptive <- remove_empty(aeps_1_adaptive, which = c("rows", "cols"), quiet = TRUE)
#create a skill
aeps_1_adaptive <- aeps_1_adaptive %>%
mutate(skill = .[[1]]) %>% #this is the first column )in this case -- fine motor (sub)domain
select(1,skill, everything())
#With this new variable (skill), just keep if is a letter
aeps_1_adaptive <- aeps_1_adaptive %>%
mutate(skill = if_else(str_detect(skill, "[a-z]"), .[[1]], NA_character_)) %>% #if skill is a letter, otherwise missing
fill(skill)
#remove first line (it's almost all na)
aeps_1_adaptive <- aeps_1_adaptive %>%
filter(!str_detect(.[[1]], "[a-z]"))
#transform to numeric
aeps_1_adaptive <- aeps_1_adaptive %>% mutate(!! names(.)[1] := as.numeric(!! rlang::sym(names(.)[1])))
#aeps_1_adaptive[[1]] <- as.numeric(aeps_1_adaptive[[1]])
Add domain
This chunk will get all domains and number skills. It will be useful to merge all ds in the future.
aeps_1_adaptive_long <- aeps_1_adaptive_long %>%
mutate(domain = names(.)[[1]]) %>%
rename(number_skill = names(.)[[1]]) %>%
select(domain, number_skill, everything())
Merge AEPS spreadsheets datasets
Just checking if we have 22 children in each dataset
aeps_1_fine_long %>% count(spread_sheet)
aeps_1_gross_long %>% count(spread_sheet)
aeps_1_adaptive_long %>% count(spread_sheet)
I’ll use bind_rows to put each dataset on top of the another. First, fine long with gross long
ds_aeps_birth_three <- bind_rows(
aeps_1_fine_long,
aeps_1_gross_long)
Now, this resultant ds with adaptive
ds_aeps_birth_three <- bind_rows(
ds_aeps_birth_three,
aeps_1_adaptive_long)
Merge AEPS with AEPS demographics
I’ll get aeps_1_demo to add to this partially full dataset the child’ ID
ds_aeps_birth_three <- left_join(ds_aeps_birth_three, aeps_1_demo)
First, i’ll add two key variables present in the ASQ-4 dataset to guarantee the merging will be correct
ds_aeps_birth_three <- ds_aeps_birth_three %>%
mutate(aeps_file_number = 1) %>%
mutate(aeps_sprdsheet_id_number = spread_sheet) %>%
rename(asq4_id = childs_id) %>%
mutate(asq4_id = as.numeric(asq4_id)) #in ASQ4 dataset, this variable is numeric
Create a full dataset with ASQ-4 and AEPS
ds_birth_three_aeps_asq <- left_join(
ds_aeps_birth_three,
ds_asq,
by = "asq4_id"
)
Manual check
ds_birth_three_aeps_asq %>%
filter(spread_sheet == "15") %>% View()
Save as excel
It seems everything worked! (Saturday, 13 March, 2021)
Ask Kimberly
Analyses - birth to three
Diane, Jane, and Kimberly. From this line on, I will:
(1) Present a plot and a table with the ASQ-4 summative results
(2) Present a plot and a table with the AEPS summative results (I read elsewhere and it seems that AEPS items need to be summed as well)
(3) Run all correlation analyses between the ASQ-4 summative scores and the AEPS summative scores
You’ll notice that the correlation results are too low. I’m wondering if something was under the radar in my code or if I’m missing some point.
I have sent an e-mail in which I present an excel file to make some points clearer.
ASQ-4 analysis
Plot
The graph below describes the distribution of all ASQ4 results.

Summary table
The table below reports the ASQ-4 results. I did not group the results by age interval.
| value |
|
|
|
|
|
|
0.328 |
| Mean (SD) |
51.250 (10.683) |
46.818 (12.492) |
52.045 (9.084) |
46.818 (9.580) |
48.636 (10.821) |
49.114 (10.631) |
|
| Range |
15.000 - 60.000 |
15.000 - 60.000 |
35.000 - 60.000 |
20.000 - 60.000 |
20.000 - 60.000 |
15.000 - 60.000 |
|
ds_birth_three_aeps_asq %>%
select(asq4_id, everything()) %>% #just for checking
distinct(asq4_id, .keep_all = T) %>% #use only one information (we have 22 children here)
select(ends_with("_sum")) %>%
janitor::remove_empty(c("cols")) %>% #remove empty columns
pivot_longer(everything(.)) %>%
arsenal::tableby(name ~ value, .) %>%
summary()
AEPS domains and skills
The following results will present the AEPS findings.
Descriptive table
The following table will present the descriptives of each participant and activitiy
How to interpret these results?
ASQ4id = 500 (it’s a child in the dataset) He or She has 18 results in domain adaptative and skill = Feeding.
If you access the excel file, it will be these same values.
Plot total scores
ds_birth_three_aeps_asq %>%
group_by(asq4_id,domain, skill) %>% #grop for having each score for each participant
summarise(raw_score = sum(score)) %>% #create the summative score
select(asq4_id,domain, skill, raw_score) %>% #select before pivoting
pivot_longer(-c(asq4_id, raw_score, skill),
values_to = "domain") %>%
select(-name) %>%
ggplot(., aes(x = domain, y = raw_score, fill = skill)) +
#geom_col(position = position_dodge2(preserve = "single")) +
geom_bar(stat = "summary", position = "dodge", width = 0.8) +
theme_bw()
`summarise()` has grouped output by 'asq4_id', 'domain'. You can override using the `.groups` argument.

Summary total scores
The following table presents the same information presented above. However, I imagine you’ll be able to check if everything is correct.
ds_birth_three_aeps_asq %>%
group_by(asq4_id,domain, skill) %>% #grop for having each score for each participant
summarise(raw_score = sum(score)) %>% #create the summative score
select(asq4_id,domain, skill, raw_score) %>% #select before pivoting
pivot_longer(-c(asq4_id, raw_score, skill),
values_to = "domain") %>%
select(-name) %>%
group_by(domain, skill) %>%
summarise(mean(raw_score), sd(raw_score), n()) %>%
mutate_if(is.numeric,round,2)
summarise() has grouped output by ‘asq4_id’, ‘domain’. You can override using the .groups argument. summarise() has grouped output by ‘domain’. You can override using the .groups argument. mutate_if() ignored the following grouping variables: Column domain
How to interpret these results?
Example:
when considering all children in domain (fine motor), and skill (A. Reach, Grab, Release), the mean result is 34.82
I double checked the excel file and this result is correct
Correlations AEPS ASQ-4
The following tables will present the correlation between each ASQ-4 domain and its AEPS parallel.
I’m using the summative score of the ASQ-4 and also the summative score of AEPS. Diane, please let me know if that’s the way to achieve the AEPS results.
Please don’t consider the three following chunks. They are programming syntaxes.
Create a summative score (Ask Diane)
cor_ds_1 <- ds_birth_three_aeps_asq %>%
group_by(asq4_id,domain, skill) %>% #grop for having each score for each participant
summarise(raw_score = sum(score))
`summarise()` has grouped output by 'asq4_id', 'domain'. You can override using the `.groups` argument.
Create a dataframe to gather all data
Merge these data and remove useless vectors
cor_ds <- left_join(cor_ds_1,cor_ds_2)
Joining, by = "asq4_id"
ASQ Fine motor vs AEPS Fine motor
library(corrr) #correlation
Correlation between ASQ Fine motor and AEPS Fine motor I’m using the same child!
How to interpret these results?
The correlation between the ASQ-4 fine motor and AEPS fine motor (skill: Reach and Grab) is -0.22 (makes no sense to me)
The correlation between the ASQ-4 fine motor and AEPS fine motor (skill: Functional use) is -0.05 (makes no sense to me)
I have attached an excel file in which I mannually ran these correlations and the results match
ASQ gross motor AEPS gross motor
Correlation between ASQ Gross motor and AEPS Gross motor I’m using the data from same children.
How to interpret these results?
The correlation between the ASQ-4 gross motor and AEPS gross motor (skill: A. Movement and Locomotion) is -0.17 (makes no sense to me)
The correlation between the ASQ-4 gross motor and AEPS gross motor (skill: B. Balance in Sitting) is -0.06 (makes no sense to me)
The correlation between the ASQ-4 gross motor and AEPS gross motor (skill: C. Balance & Mobility) is 0.03 (makes no sense to me)
The correlation between the ASQ-4 gross motor and AEPS gross motor (skill: D. Play Skills) is 0.04 (makes no sense to me)
ASQ Personal-Social AEPS adaptive
**Jane: Just to refresh my memory. In the dataset, PS means problem-solving and P means Personal and Social, right?
Correlation between ASQ Personal-Social and AEPS Adaptive I’m using the data from same children.
How to interpret these results?
The correlation between the ASQ-4 Personal and Social and AEPS Adaptive (skill: A. Feeding) is 0.34 (makes sense!!)
The correlation between the ASQ-4 Personal and Social and AEPS Adaptive (skill: B. Personal Hygiene) is 0.27 (makes sense!!)
The correlation between the ASQ-4 Personal and Social and AEPS Adaptive (skill: C. Undressing) is 0.30 (makes sense!!)
end of report
LS0tDQp0aXRsZTogIkRpYW5lIC0gQUVQUyAmIEFTUS00Ig0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRoZW1lOiB1bml0ZWQNCiAgICBoaWdobGlnaHQ6IHRleHRtYXRlDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KDQpgYGB7ciBnbG9iYWwgb3B0aW9ucywgaW5jbHVkZSA9IEZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBGQUxTRSwgDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCANCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlcyA9IEZBTFNFLCANCiAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzID0gImhpZGUiKQ0KYGBgDQoNCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXN1Y2Nlc3MiPg0KKipEaWFuZSwgSmFuZSwgYW5kIEtpbWJlcmx5LiAqKiAgIA0KRXZlcnl0aGluZyBiZWZvcmUgYDE1IC0gYW5hbHlzaXNgIGlzIGEgc3ludGF4IHRvIG1hdGNoIGFsbCBjaGlsZHJlbi4gICANCkkga25vdyBlcnJvcnMgaGFwcGVuIGFsbCB0aGUgdGltZS4gVGhlcmVmb3JlLCB0aGVzZSBjb2RlcyB3ZXJlIG1hZGUgYXZhaWxhYmxlIGhlcmUgaWYgc29tZW9uZSB3YW50cyB0byByZXZpZXcgb3IgY2hlY2sgdGhlIGNvbnNpc3RlbmN5LiAgIA0KSW4gdGhlIGUtbWFpbCB0aGF0IHlvdSBmb3VuZCB0aGlzIGxpbmssIEkgYXR0YWNoZWQgYW4gZXhjZWwgZmlsZSBpbiB3aGljaCB5b3UnbGwgYmUgYWJsZSB0byBjaGVjayB0aGlzIGZpbGUuICAgDQoNCioqUGxlYXNlIG5vdGljZSB0aGF0IHRoaXMgcmVwb3J0IHJlZmVycyB0byBiaXJ0aCB0byB0aHJlZSBvbmx5KiogICAgIA0KKipJZiB5b3UgZG9uJ3Qgd2FudCB0byBjaGVjayBhbnkgY29kZSwgcGxlYXNlIGNsaWNrIFtoZXJlXSgjYW5hbHlzZXMpKioNCjwvZGl2Pg0KDQoNCiMgbG9hZCBwYWNrYWdlDQpgYGB7cn0NCnBhY21hbjo6cF9sb2FkKHRpZHl2ZXJzZSwgamFuaXRvcikNCmBgYA0KDQojIERhdGEgaGFuZGxpbmcNCg0KIyBnZXQgYWxsIEFTUTQgZGF0YQ0KDQpgYGB7cn0NCnJlYWRfZXhjZWxfYWxsc2hlZXRzIDwtIGZ1bmN0aW9uKGZpbGVuYW1lKSB7DQogICAgc2hlZXRzIDwtIHJlYWR4bDo6ZXhjZWxfc2hlZXRzKGZpbGVuYW1lKSAjZ2V0IGFsbCBzaGVldCBuYW1lcw0KICAgIHggPC0gbGFwcGx5KHNoZWV0cywgZnVuY3Rpb24oWCkgcmVhZHhsOjpyZWFkX2V4Y2VsKGZpbGVuYW1lLCBzaGVldCA9IFgpKQ0KICAgIG5hbWVzKHgpIDwtIHNoZWV0cyAjZ2V0IG5hbWVzIG9ubHkNCiAgICB4ICNyZXR1cm4NCn0NCiNnZXQgdGhlIGV4Y2VsIGZpbGUNCmV4Y2VsX2xpc3QgPC0gcmVhZF9leGNlbF9hbGxzaGVldHMoIkM6L1VzZXJzL2x1aXNmL0Ryb3Bib3gvQVNRNF9BRVBTIERhdGEgZm9yIEx1aXMgMi4yMDIxL0x1aXMgRmViIDIwMjEvRmluYWwgQUxMIEFTUTQgZm9yIEFFUFMgMjAxOV8yMDIwLnhsc3giKQ0KI3RyYW5zZm9ybSBpbnRvIHZlY3RvcnMNCmxpc3QyZW52KHNldE5hbWVzKGV4Y2VsX2xpc3QsICNsaXN0DQogICAgICAgICAgICAgICAgICBwYXN0ZTAoImRzXyIsamFuaXRvcjo6bWFrZV9jbGVhbl9uYW1lcyhuYW1lcyhleGNlbF9saXN0KSkpKSwgICNmaXhpbmcgZGlmZmVyZW50IG5hbWVzIGFuZCBvdGhlciBwYXR0ZXJucw0KICAgICAgICAgZW52aXI9Lkdsb2JhbEVudikgI3doZXJlPw0KYGBgDQoNCiMgQ3JlYXRlIGEgYmFja3VwDQoNCmBgYHtyfQ0KYmFja3VwX2FzcTRfZGVtbyA8LSBkc19hc3E0X2RlbW8gDQpiYWNrdXBfYXNxNF9pdGVtcyA8LSBkc19hc3E0X2l0ZW1zDQpgYGANCg0KDQojcmVtb3ZlIGFsbCBhdHRyaWJ1dGVzIA0KDQpgYGB7cn0NCiNkc19hc3E0X2RlbW9bXSA8LSBsYXBwbHkoZHNfYXNxNF9kZW1vLCBmdW5jdGlvbih4KSB7IGF0dHJpYnV0ZXMoeCkgPC0gTlVMTDsgeCB9KQ0KI2JhY2t1cF9hc3E0X2l0ZW1zW10gPC0gbGFwcGx5KGJhY2t1cF9hc3E0X2l0ZW1zLCBmdW5jdGlvbih4KSB7IGF0dHJpYnV0ZXMoeCkgPC0gTlVMTDsgeCB9KQ0KYGBgDQoNCiMgY2xlYW4gbmFtZXMgDQoNCmBgYHtyfQ0KZHNfYXNxNF9kZW1vIDwtIGNsZWFuX25hbWVzKGRzX2FzcTRfZGVtbykNCmRzX2FzcTRfaXRlbXMgPC0gY2xlYW5fbmFtZXMoZHNfYXNxNF9pdGVtcykNCmBgYA0KDQojIG1lcmdlIGRhdGFzZXRzIA0KDQpgYGB7cn0NCmRzX2FzcSA8LSBsZWZ0X2pvaW4oZHNfYXNxNF9kZW1vLCBkc19hc3E0X2l0ZW1zLCBieSA9IGMoImFzcTRfaWQiKSkNCmBgYA0KDQojIENvbXB1dGUgdG90YWxzDQoNCiMjIENoYW5nZSB2YXJpYWJsZSBjb21wdXRhdGlvbmFsIGxldmVsIA0KDQpgYGB7cn0NCmRzX2FzcSA8LSBkc19hc3EgJT4lIA0KICBtdXRhdGVfYXQodmFycyhjMTpjNiwgZ20xOmdtNiwgZm0xOmZtNiwgcHMxOnBzNiwgcDE6cDYpLCB+YXMubnVtZXJpYyguKSkNCmBgYA0KDQojIyBDb21wdXRlIHRvdGFscyBmb3IgZWFjaCBBU1EtNCBkb21haW4NCmBgYHtyfQ0KZHNfYXNxPC1kc19hc3EgJT4lIA0KICBtdXRhdGUoY29tX3N1bSA9IHJvd1N1bXMoc2VsZWN0KC4sYzE6YzYpKSkgJT4lIA0KICBtdXRhdGUoZ21fc3VtID0gcm93U3VtcyhzZWxlY3QoLixnbTE6Z202KSkpICU+JSANCiAgbXV0YXRlKGZtX3N1bSA9IHJvd1N1bXMoc2VsZWN0KC4sZm0xOmZtNikpKSAlPiUgDQogIG11dGF0ZShwc19zdW0gPSByb3dTdW1zKHNlbGVjdCguLHBzMTpwczYpKSkgJT4lIA0KICBtdXRhdGUocGVyX3N1bSA9IHJvd1N1bXMoc2VsZWN0KC4scDE6cDYpKSkNCmBgYA0KDQoNCiMgQUVQUyBEZW1vZ3JhcGhpY3MNCg0KYGBge3J9DQphZXBzXzFfZGVtbyA8LSByZWFkeGw6OnJlYWRfZXhjZWwoIkM6L1VzZXJzL2x1aXNmL0Ryb3Bib3gvQVNRNF9BRVBTIERhdGEgZm9yIEx1aXMgMi4yMDIxL0x1aXMgRmViIDIwMjEvY29weSBLTSBDbGVhbmVkIEFFUFMgMy41LjIxLzEuQ2xlYW5lZCBBRVBTQmlydGhUb1RocmVlRm9ybU5vTiAyIEdyYWNlIDkuMTMuMjAxOS54bHN4Iiwgc2hlZXQgPSAyKQ0KYGBgDQoNCmBgYHtyfQ0KI2ZpeCBuYW1lcw0KYWVwc18xX2RlbW8gPC0gY2xlYW5fbmFtZXMoYWVwc18xX2RlbW8pDQojcmVtb3ZlIGVtcHR5IGNvbHVtbnMgYW5kIHJvd3MNCmFlcHNfMV9kZW1vIDwtIHJlbW92ZV9lbXB0eShhZXBzXzFfZGVtbywgd2hpY2ggPSBjKCJyb3dzIiwgImNvbHMiKSwgcXVpZXQgPSBUUlVFKQ0KI3JlbW92ZSB1c2VsZXNzIHJvd3MNCmFlcHNfMV9kZW1vIDwtIGFlcHNfMV9kZW1vICU+JSBmaWx0ZXIoIWlzLm5hKGNoaWxkc19pZCkpDQoNCiNhZGQgbmV3IGZlYXR1cmVzIHRvIG1lcmdlDQphZXBzXzFfZGVtbyA8LSBhZXBzXzFfZGVtbyAlPiUgDQogIG11dGF0ZShhZXBzX2ZpbGVfbnVtYmVyID0gMSkgJT4lICNzYW1lIGFzIGRzX2FzcQ0KICBtdXRhdGUoc3ByZWFkX3NoZWV0ID0gc3ByZWFkX3NoZWV0X2lkXzEpICU+JSAjc2FtZSBhcyBmdWxsIGRhdGFzZXQhDQogIG11dGF0ZShhZXBzX3NwcmRzaGVldF9pZF9udW1iZXIgPSBzcHJlYWRfc2hlZXRfaWRfMSkgI3NhbWUgYXMgZHNfYXNxDQpgYGANCg0KDQoNCiMgMS5BRVBTQmlydGhUb1RocmVlRm9ybU5vTiAyIEdyYWNlIDkuMTMuMjAxOQ0KDQojIEZpcnN0IGZpbGUgMSAtIEZpbmUgbW90b3IgKDEpDQoNCiMjIGdldCBkYXRhDQoNCmBgYHtyfQ0KYWVwc18xX2ZpbmUgPC0gcmVhZHhsOjpyZWFkX2V4Y2VsKCJDOi9Vc2Vycy9sdWlzZi9Ecm9wYm94L0FTUTRfQUVQUyBEYXRhIGZvciBMdWlzIDIuMjAyMS9MdWlzIEZlYiAyMDIxL2NvcHkgS00gQ2xlYW5lZCBBRVBTIDMuNS4yMS8xLkNsZWFuZWQgQUVQU0JpcnRoVG9UaHJlZUZvcm1Ob04gMiBHcmFjZSA5LjEzLjIwMTkueGxzeCIsIHNoZWV0ID0gMykNCmBgYA0KYGBge3J9DQojY2xlYXIgZXhjZWwgYXR0cmlidXRlcw0KYWVwc18xX2ZpbmVbXSA8LSBsYXBwbHkoYWVwc18xX2ZpbmUsIGZ1bmN0aW9uKHgpIHsgYXR0cmlidXRlcyh4KSA8LSBOVUxMOyB4IH0pDQojZml4IG5hbWVzDQphZXBzXzFfZmluZSA8LSBjbGVhbl9uYW1lcyhhZXBzXzFfZmluZSkNCiNyZW1vdmUgZW1wdHkgY29sdW1ucyBhbmQgcm93cw0KYWVwc18xX2ZpbmUgPC0gcmVtb3ZlX2VtcHR5KGFlcHNfMV9maW5lLCB3aGljaCA9IGMoInJvd3MiLCAiY29scyIpLCBxdWlldCA9IFRSVUUpDQojY3JlYXRlIGEgc2tpbGwNCmFlcHNfMV9maW5lIDwtIGFlcHNfMV9maW5lICU+JSANCiAgbXV0YXRlKHNraWxsID0gLltbMV1dKSAlPiUgI3RoaXMgaXMgdGhlIGZpcnN0IGNvbHVtbiApaW4gdGhpcyBjYXNlIC0tIGZpbmUgbW90b3IgKHN1Yilkb21haW4NCiAgc2VsZWN0KDEsc2tpbGwsIGV2ZXJ5dGhpbmcoKSkNCiNXaXRoIHRoaXMgbmV3IHZhcmlhYmxlIChza2lsbCksIGp1c3Qga2VlcCBpZiBpcyBhIGxldHRlcg0KYWVwc18xX2ZpbmUgPC0gYWVwc18xX2ZpbmUgJT4lIA0KICBtdXRhdGUoc2tpbGwgPSBpZl9lbHNlKHN0cl9kZXRlY3Qoc2tpbGwsICJbYS16XSIpLCAuW1sxXV0sICBOQV9jaGFyYWN0ZXJfKSkgJT4lICNpZiBza2lsbCBpcyBhIGxldHRlciwgb3RoZXJ3aXNlIG1pc3NpbmcNCiAgZmlsbChza2lsbCkNCiNyZW1vdmUgZmlyc3QgbGluZSAoaXQncyBhbG1vc3QgYWxsIG5hKQ0KYWVwc18xX2ZpbmUgPC0gYWVwc18xX2ZpbmUgJT4lIA0KICBmaWx0ZXIoIXN0cl9kZXRlY3QoLltbMV1dLCAiW2Etel0iKSkNCiN0cmFuc2Zvcm0gdG8gbnVtZXJpYw0KYWVwc18xX2ZpbmUgPC0gYWVwc18xX2ZpbmUgJT4lIG11dGF0ZSghISBuYW1lcyguKVsxXSA6PSBhcy5udW1lcmljKCEhIHJsYW5nOjpzeW0obmFtZXMoLilbMV0pKSkgDQojYWVwc18xX2ZpbmVbWzFdXSA8LSBhcy5udW1lcmljKGFlcHNfMV9maW5lW1sxXV0pDQpgYGANCg0KDQojIyBUcmFuZm9ybSBpdCB0byBsb25nIGZvcm1hdA0KDQpgYGB7cn0NCnNwZWMgPC0gdGliYmxlKGAubmFtZWAgPSBuYW1lcyhhZXBzXzFfZmluZSkpICU+JQ0KICBzbGljZSgtYygxOjIpKSAlPiUNCiAgbXV0YXRlKGAudmFsdWVgID0gY2FzZV93aGVuKA0KICAgICAgICAgICBgLm5hbWVgICU+JSBzdHJfZGV0ZWN0KCJzcHJlYWQiKSB+ICJzcHJlYWRfc2hlZXQiLA0KICAgICAgICAgICBgLm5hbWVgICU+JSBzdHJfZGV0ZWN0KCJzY29yZSIpICB+ICJzY29yZSIsDQogICAgICAgICAgIGAubmFtZWAgJT4lIHN0cl9kZXRlY3QoImNvbmZpcm0iKSB+ICJjb25maXJtIikNCiAgKQ0KIyBhcHBseSB0aGUgc3BlYw0KYWVwc18xX2ZpbmVfbG9uZyA8LSBhZXBzXzFfZmluZSAlPiUNCiAgcGl2b3RfbG9uZ2VyX3NwZWMoc3BlYykNCmBgYA0KDQojIyBBZGQgZG9tYWluDQoNClRoaXMgY2h1bmsgd2lsbCBnZXQgYWxsIGRvbWFpbnMgYW5kIG51bWJlciBza2lsbHMuIEl0IHdpbGwgYmUgdXNlZnVsIHRvIG1lcmdlIGFsbCBkcyBpbiB0aGUgZnV0dXJlLiAgDQoNCmBgYHtyfQ0KYWVwc18xX2ZpbmVfbG9uZyA8LSBhZXBzXzFfZmluZV9sb25nICU+JSANCiAgbXV0YXRlKGRvbWFpbiA9IG5hbWVzKC4pW1sxXV0pICU+JSANCiAgcmVuYW1lKG51bWJlcl9za2lsbCA9IG5hbWVzKC4pW1sxXV0pICU+JSANCiAgc2VsZWN0KGRvbWFpbiwgbnVtYmVyX3NraWxsLCBldmVyeXRoaW5nKCkpDQpgYGANCg0KDQojIEZpcnN0IGZpbGUgMSAtIEdyb3NzIG1vdG9yICgyKQ0KDQojIyBnZXQgZGF0YQ0KDQpgYGB7cn0NCmFlcHNfMV9ncm9zcyA8LSByZWFkeGw6OnJlYWRfZXhjZWwoIkM6L1VzZXJzL2x1aXNmL0Ryb3Bib3gvQVNRNF9BRVBTIERhdGEgZm9yIEx1aXMgMi4yMDIxL0x1aXMgRmViIDIwMjEvY29weSBLTSBDbGVhbmVkIEFFUFMgMy41LjIxLzEuQ2xlYW5lZCBBRVBTQmlydGhUb1RocmVlRm9ybU5vTiAyIEdyYWNlIDkuMTMuMjAxOS54bHN4Iiwgc2hlZXQgPSA0KQ0KYGBgDQpgYGB7cn0NCiNjbGVhciBleGNlbCBhdHRyaWJ1dGVzDQphZXBzXzFfZ3Jvc3NbXSA8LSBsYXBwbHkoYWVwc18xX2dyb3NzLCBmdW5jdGlvbih4KSB7IGF0dHJpYnV0ZXMoeCkgPC0gTlVMTDsgeCB9KQ0KI2ZpeCBuYW1lcw0KYWVwc18xX2dyb3NzIDwtIGNsZWFuX25hbWVzKGFlcHNfMV9ncm9zcykNCiNyZW1vdmUgZW1wdHkgY29sdW1ucyBhbmQgcm93cw0KYWVwc18xX2dyb3NzIDwtIHJlbW92ZV9lbXB0eShhZXBzXzFfZ3Jvc3MsIHdoaWNoID0gYygicm93cyIsICJjb2xzIiksIHF1aWV0ID0gVFJVRSkNCiNjcmVhdGUgYSBza2lsbA0KYWVwc18xX2dyb3NzIDwtIGFlcHNfMV9ncm9zcyAlPiUgDQogIG11dGF0ZShza2lsbCA9IC5bWzFdXSkgJT4lICN0aGlzIGlzIHRoZSBmaXJzdCBjb2x1bW4gKWluIHRoaXMgY2FzZSAtLSBmaW5lIG1vdG9yIChzdWIpZG9tYWluDQogIHNlbGVjdCgxLHNraWxsLCBldmVyeXRoaW5nKCkpDQojV2l0aCB0aGlzIG5ldyB2YXJpYWJsZSAoc2tpbGwpLCBqdXN0IGtlZXAgaWYgaXMgYSBsZXR0ZXINCmFlcHNfMV9ncm9zcyA8LSBhZXBzXzFfZ3Jvc3MgJT4lIA0KICBtdXRhdGUoc2tpbGwgPSBpZl9lbHNlKHN0cl9kZXRlY3Qoc2tpbGwsICJbYS16XSIpLCAuW1sxXV0sICBOQV9jaGFyYWN0ZXJfKSkgJT4lICNpZiBza2lsbCBpcyBhIGxldHRlciwgb3RoZXJ3aXNlIG1pc3NpbmcNCiAgZmlsbChza2lsbCkNCiNyZW1vdmUgZmlyc3QgbGluZSAoaXQncyBhbG1vc3QgYWxsIG5hKQ0KYWVwc18xX2dyb3NzIDwtIGFlcHNfMV9ncm9zcyAlPiUgDQogIGZpbHRlcighc3RyX2RldGVjdCguW1sxXV0sICJbYS16XSIpKQ0KI3RyYW5zZm9ybSB0byBudW1lcmljDQphZXBzXzFfZ3Jvc3MgPC0gYWVwc18xX2dyb3NzICU+JSBtdXRhdGUoISEgbmFtZXMoLilbMV0gOj0gYXMubnVtZXJpYyghISBybGFuZzo6c3ltKG5hbWVzKC4pWzFdKSkpIA0KI2FlcHNfMV9ncm9zc1tbMV1dIDwtIGFzLm51bWVyaWMoYWVwc18xX2dyb3NzW1sxXV0pDQpgYGANCg0KDQojIyBUcmFuZm9ybSBpdCB0byBsb25nIGZvcm1hdA0KDQpgYGB7cn0NCnNwZWMgPC0gdGliYmxlKGAubmFtZWAgPSBuYW1lcyhhZXBzXzFfZ3Jvc3MpKSAlPiUNCiAgc2xpY2UoLWMoMToyKSkgJT4lDQogIG11dGF0ZShgLnZhbHVlYCA9IGNhc2Vfd2hlbigNCiAgICBgLm5hbWVgICU+JSBzdHJfZGV0ZWN0KCJzcHJlYWQiKSB+ICJzcHJlYWRfc2hlZXQiLA0KICAgIGAubmFtZWAgJT4lIHN0cl9kZXRlY3QoInNjb3JlIikgIH4gInNjb3JlIiwNCiAgICBgLm5hbWVgICU+JSBzdHJfZGV0ZWN0KCJjb25maXJtIikgfiAiY29uZmlybSIpDQogICkNCiMgYXBwbHkgdGhlIHNwZWMNCmFlcHNfMV9ncm9zc19sb25nIDwtIGFlcHNfMV9ncm9zcyAlPiUNCiAgcGl2b3RfbG9uZ2VyX3NwZWMoc3BlYykNCmBgYA0KDQojIyBBZGQgZG9tYWluDQoNClRoaXMgY2h1bmsgd2lsbCBnZXQgYWxsIGRvbWFpbnMgYW5kIG51bWJlciBza2lsbHMuIEl0IHdpbGwgYmUgdXNlZnVsIHRvIG1lcmdlIGFsbCBkcyBpbiB0aGUgZnV0dXJlLiAgDQoNCmBgYHtyfQ0KYWVwc18xX2dyb3NzX2xvbmcgPC0gYWVwc18xX2dyb3NzX2xvbmcgJT4lIA0KICBtdXRhdGUoZG9tYWluID0gbmFtZXMoLilbWzFdXSkgJT4lIA0KICByZW5hbWUobnVtYmVyX3NraWxsID0gbmFtZXMoLilbWzFdXSkgJT4lIA0KICBzZWxlY3QoZG9tYWluLCBudW1iZXJfc2tpbGwsIGV2ZXJ5dGhpbmcoKSkNCmBgYA0KDQoNCg0KIyBGaXJzdCBmaWxlIDEgLSBBZGFwdGl2ZSAoMykNCg0KIyMgZ2V0IGRhdGENCg0KYGBge3J9DQphZXBzXzFfYWRhcHRpdmUgPC0gcmVhZHhsOjpyZWFkX2V4Y2VsKCJDOi9Vc2Vycy9sdWlzZi9Ecm9wYm94L0FTUTRfQUVQUyBEYXRhIGZvciBMdWlzIDIuMjAyMS9MdWlzIEZlYiAyMDIxL2NvcHkgS00gQ2xlYW5lZCBBRVBTIDMuNS4yMS8xLkNsZWFuZWQgQUVQU0JpcnRoVG9UaHJlZUZvcm1Ob04gMiBHcmFjZSA5LjEzLjIwMTkueGxzeCIsIHNoZWV0ID0gNSkNCmBgYA0KDQpgYGB7cn0NCiNjbGVhciBleGNlbCBhdHRyaWJ1dGVzDQphZXBzXzFfYWRhcHRpdmVbXSA8LSBsYXBwbHkoYWVwc18xX2FkYXB0aXZlLCBmdW5jdGlvbih4KSB7IGF0dHJpYnV0ZXMoeCkgPC0gTlVMTDsgeCB9KQ0KI2ZpeCBuYW1lcw0KYWVwc18xX2FkYXB0aXZlIDwtIGNsZWFuX25hbWVzKGFlcHNfMV9hZGFwdGl2ZSkNCiNyZW1vdmUgZW1wdHkgY29sdW1ucyBhbmQgcm93cw0KYWVwc18xX2FkYXB0aXZlIDwtIHJlbW92ZV9lbXB0eShhZXBzXzFfYWRhcHRpdmUsIHdoaWNoID0gYygicm93cyIsICJjb2xzIiksIHF1aWV0ID0gVFJVRSkNCiNjcmVhdGUgYSBza2lsbA0KYWVwc18xX2FkYXB0aXZlIDwtIGFlcHNfMV9hZGFwdGl2ZSAlPiUgDQogIG11dGF0ZShza2lsbCA9IC5bWzFdXSkgJT4lICN0aGlzIGlzIHRoZSBmaXJzdCBjb2x1bW4gKWluIHRoaXMgY2FzZSAtLSBmaW5lIG1vdG9yIChzdWIpZG9tYWluDQogIHNlbGVjdCgxLHNraWxsLCBldmVyeXRoaW5nKCkpDQojV2l0aCB0aGlzIG5ldyB2YXJpYWJsZSAoc2tpbGwpLCBqdXN0IGtlZXAgaWYgaXMgYSBsZXR0ZXINCmFlcHNfMV9hZGFwdGl2ZSA8LSBhZXBzXzFfYWRhcHRpdmUgJT4lIA0KICBtdXRhdGUoc2tpbGwgPSBpZl9lbHNlKHN0cl9kZXRlY3Qoc2tpbGwsICJbYS16XSIpLCAuW1sxXV0sICBOQV9jaGFyYWN0ZXJfKSkgJT4lICNpZiBza2lsbCBpcyBhIGxldHRlciwgb3RoZXJ3aXNlIG1pc3NpbmcNCiAgZmlsbChza2lsbCkNCiNyZW1vdmUgZmlyc3QgbGluZSAoaXQncyBhbG1vc3QgYWxsIG5hKQ0KYWVwc18xX2FkYXB0aXZlIDwtIGFlcHNfMV9hZGFwdGl2ZSAlPiUgDQogIGZpbHRlcighc3RyX2RldGVjdCguW1sxXV0sICJbYS16XSIpKQ0KI3RyYW5zZm9ybSB0byBudW1lcmljDQphZXBzXzFfYWRhcHRpdmUgPC0gYWVwc18xX2FkYXB0aXZlICU+JSBtdXRhdGUoISEgbmFtZXMoLilbMV0gOj0gYXMubnVtZXJpYyghISBybGFuZzo6c3ltKG5hbWVzKC4pWzFdKSkpIA0KI2FlcHNfMV9hZGFwdGl2ZVtbMV1dIDwtIGFzLm51bWVyaWMoYWVwc18xX2FkYXB0aXZlW1sxXV0pDQpgYGANCg0KDQojIyBUcmFuZm9ybSBpdCB0byBsb25nIGZvcm1hdA0KDQpgYGB7cn0NCnNwZWMgPC0gdGliYmxlKGAubmFtZWAgPSBuYW1lcyhhZXBzXzFfYWRhcHRpdmUpKSAlPiUNCiAgc2xpY2UoLWMoMToyKSkgJT4lDQogIG11dGF0ZShgLnZhbHVlYCA9IGNhc2Vfd2hlbigNCiAgICBgLm5hbWVgICU+JSBzdHJfZGV0ZWN0KCJzcHJlYWQiKSB+ICJzcHJlYWRfc2hlZXQiLA0KICAgIGAubmFtZWAgJT4lIHN0cl9kZXRlY3QoInNjb3JlIikgIH4gInNjb3JlIiwNCiAgICBgLm5hbWVgICU+JSBzdHJfZGV0ZWN0KCJjb25maXJtIikgfiAiY29uZmlybSIpDQogICkNCiMgYXBwbHkgdGhlIHNwZWMNCmFlcHNfMV9hZGFwdGl2ZV9sb25nIDwtIGFlcHNfMV9hZGFwdGl2ZSAlPiUNCiAgcGl2b3RfbG9uZ2VyX3NwZWMoc3BlYykNCmBgYA0KDQojIyBBZGQgZG9tYWluDQoNClRoaXMgY2h1bmsgd2lsbCBnZXQgYWxsIGRvbWFpbnMgYW5kIG51bWJlciBza2lsbHMuIEl0IHdpbGwgYmUgdXNlZnVsIHRvIG1lcmdlIGFsbCBkcyBpbiB0aGUgZnV0dXJlLiAgDQoNCmBgYHtyfQ0KYWVwc18xX2FkYXB0aXZlX2xvbmcgPC0gYWVwc18xX2FkYXB0aXZlX2xvbmcgJT4lIA0KICBtdXRhdGUoZG9tYWluID0gbmFtZXMoLilbWzFdXSkgJT4lIA0KICByZW5hbWUobnVtYmVyX3NraWxsID0gbmFtZXMoLilbWzFdXSkgJT4lIA0KICBzZWxlY3QoZG9tYWluLCBudW1iZXJfc2tpbGwsIGV2ZXJ5dGhpbmcoKSkNCmBgYA0KDQoNCiMgTWVyZ2UgQUVQUyBzcHJlYWRzaGVldHMgZGF0YXNldHMNCg0KSnVzdCBjaGVja2luZyBpZiB3ZSBoYXZlIDIyIGNoaWxkcmVuIGluIGVhY2ggZGF0YXNldCAgDQpgYGB7cn0NCmFlcHNfMV9maW5lX2xvbmcgJT4lIGNvdW50KHNwcmVhZF9zaGVldCkNCmFlcHNfMV9ncm9zc19sb25nICU+JSBjb3VudChzcHJlYWRfc2hlZXQpDQphZXBzXzFfYWRhcHRpdmVfbG9uZyAlPiUgY291bnQoc3ByZWFkX3NoZWV0KQ0KYGBgDQoNCkknbGwgdXNlIGBiaW5kX3Jvd3NgIHRvIHB1dCBlYWNoIGRhdGFzZXQgb24gdG9wIG9mIHRoZSBhbm90aGVyLiANCkZpcnN0LCBmaW5lIGxvbmcgd2l0aCBncm9zcyBsb25nDQoNCg0KYGBge3J9DQpkc19hZXBzX2JpcnRoX3RocmVlIDwtIGJpbmRfcm93cygNCiAgYWVwc18xX2ZpbmVfbG9uZywNCiAgYWVwc18xX2dyb3NzX2xvbmcpDQpgYGANCg0KTm93LCB0aGlzIHJlc3VsdGFudCBkcyB3aXRoIGFkYXB0aXZlDQoNCmBgYHtyfQ0KZHNfYWVwc19iaXJ0aF90aHJlZSA8LSBiaW5kX3Jvd3MoDQogIGRzX2FlcHNfYmlydGhfdGhyZWUsDQogIGFlcHNfMV9hZGFwdGl2ZV9sb25nKQ0KYGBgDQoNCg0KIyBNZXJnZSBBRVBTIHdpdGggQUVQUyBkZW1vZ3JhcGhpY3MNCg0KSSdsbCBnZXQgYGFlcHNfMV9kZW1vYCB0byBhZGQgdG8gdGhpcyBwYXJ0aWFsbHkgZnVsbCBkYXRhc2V0IHRoZSBjaGlsZCcgSUQNCg0KYGBge3J9DQpkc19hZXBzX2JpcnRoX3RocmVlIDwtIGxlZnRfam9pbihkc19hZXBzX2JpcnRoX3RocmVlLCBhZXBzXzFfZGVtbykNCmBgYA0KDQpGaXJzdCwgaSdsbCBhZGQgdHdvIGtleSB2YXJpYWJsZXMgcHJlc2VudCBpbiB0aGUgQVNRLTQgZGF0YXNldCB0byBndWFyYW50ZWUgdGhlIG1lcmdpbmcgd2lsbCBiZSBjb3JyZWN0DQoNCmBgYHtyfQ0KZHNfYWVwc19iaXJ0aF90aHJlZSA8LSBkc19hZXBzX2JpcnRoX3RocmVlICU+JSANCiAgbXV0YXRlKGFlcHNfZmlsZV9udW1iZXIgPSAxKSAlPiUgDQogIG11dGF0ZShhZXBzX3NwcmRzaGVldF9pZF9udW1iZXIgPSBzcHJlYWRfc2hlZXQpICU+JSANCiAgcmVuYW1lKGFzcTRfaWQgPSBjaGlsZHNfaWQpICU+JSANCiAgbXV0YXRlKGFzcTRfaWQgPSBhcy5udW1lcmljKGFzcTRfaWQpKSAjaW4gQVNRNCBkYXRhc2V0LCB0aGlzIHZhcmlhYmxlIGlzIG51bWVyaWMNCmBgYA0KDQoNCkNyZWF0ZSBhIGZ1bGwgZGF0YXNldCB3aXRoIEFTUS00IGFuZCBBRVBTDQoNCmBgYHtyfQ0KZHNfYmlydGhfdGhyZWVfYWVwc19hc3EgPC0gbGVmdF9qb2luKA0KICBkc19hZXBzX2JpcnRoX3RocmVlLA0KICBkc19hc3EsDQogIGJ5ID0gImFzcTRfaWQiDQopDQpgYGANCg0KDQojIyBNYW51YWwgY2hlY2sNCg0KYGBge3J9DQpkc19iaXJ0aF90aHJlZV9hZXBzX2FzcSAlPiUgDQogIGZpbHRlcihzcHJlYWRfc2hlZXQgPT0gIjE1IikgJT4lIFZpZXcoKQ0KYGBgDQoNCg0KIyMgU2F2ZSBhcyBleGNlbA0KDQpgYGB7cn0NCndyaXRlLmNzdihkc19iaXJ0aF90aHJlZV9hZXBzX2FzcSwgZmlsZSA9ICJkc19iaXJ0aF90aHJlZV9hZXBzX2FzcS5jc3YiLCByb3cubmFtZXMgPSBGKQ0KYGBgDQoNCg0KPiBJdCBzZWVtcyBldmVyeXRoaW5nIHdvcmtlZCEgKFNhdHVyZGF5LCAxMyBNYXJjaCwgMjAyMSkgIA0KQXNrIEtpbWJlcmx5DQoNCiMgQW5hbHlzZXMgLSBiaXJ0aCB0byB0aHJlZSB7I2FuYWx5c2VzfQ0KDQoNCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXN1Y2Nlc3MiPg0KRGlhbmUsIEphbmUsIGFuZCBLaW1iZXJseS4gDQpGcm9tIHRoaXMgbGluZSBvbiwgSSB3aWxsOiAgICANCioqKDEpKiogUHJlc2VudCBhIHBsb3QgYW5kIGEgdGFibGUgd2l0aCB0aGUgQVNRLTQgc3VtbWF0aXZlIHJlc3VsdHMgICANCioqKDIpKiogUHJlc2VudCBhIHBsb3QgYW5kIGEgdGFibGUgd2l0aCB0aGUgIEFFUFMgc3VtbWF0aXZlIHJlc3VsdHMgKEkgcmVhZCBlbHNld2hlcmUgYW5kIGl0IHNlZW1zIHRoYXQgQUVQUyBpdGVtcyBuZWVkIHRvIGJlIHN1bW1lZCBhcyB3ZWxsKSAgIA0KKiooMykqKiBSdW4gYWxsIGNvcnJlbGF0aW9uIGFuYWx5c2VzIGJldHdlZW4gdGhlIEFTUS00IHN1bW1hdGl2ZSBzY29yZXMgYW5kIHRoZSBBRVBTIHN1bW1hdGl2ZSBzY29yZXMgICANCg0KWW91J2xsIG5vdGljZSB0aGF0IHRoZSBjb3JyZWxhdGlvbiByZXN1bHRzIGFyZSB0b28gbG93LiBJJ20gd29uZGVyaW5nIGlmIHNvbWV0aGluZyB3YXMgdW5kZXIgdGhlIHJhZGFyIGluIG15IGNvZGUgb3IgaWYgSSdtIG1pc3Npbmcgc29tZSBwb2ludC4gIA0KSSBoYXZlIHNlbnQgYW4gZS1tYWlsIGluIHdoaWNoIEkgcHJlc2VudCBhbiBleGNlbCBmaWxlIHRvIG1ha2Ugc29tZSBwb2ludHMgY2xlYXJlci4NCjwvZGl2Pg0KDQoNCiMjIEFTUS00IGFuYWx5c2lzDQoNCiMjIyBQbG90IA0KDQo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1pbmZvIj4NClRoZSBncmFwaCBiZWxvdyBkZXNjcmliZXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiBhbGwgQVNRNCByZXN1bHRzLg0KPC9kaXY+DQoNCmBgYHtyfQ0KZHNfYmlydGhfdGhyZWVfYWVwc19hc3EgJT4lDQogIHNlbGVjdChhc3E0X2lkLCBldmVyeXRoaW5nKCkpICU+JSAjanVzdCBmb3IgY2hlY2tpbmcNCiAgZGlzdGluY3QoYXNxNF9pZCwgLmtlZXBfYWxsID0gVCkgJT4lICN1c2Ugb25seSBvbmUgaW5mb3JtYXRpb24gKHdlIGhhdmUgMjIgY2hpbGRyZW4gaGVyZSkNCiAgc2VsZWN0KGVuZHNfd2l0aCgiX3N1bSIpKSAlPiUgDQogIGphbml0b3I6OnJlbW92ZV9lbXB0eSgiY29scyIpICU+JSAjcmVtb3ZlIGVtcHR5IGNvbHVtbnMNCiAgcGl2b3RfbG9uZ2VyKGV2ZXJ5dGhpbmcoLikpICU+JSANCiAgZ2dwbG90KC4sIGFlcyhuYW1lLCB2YWx1ZSkpICsNCiAgZ2VvbV9ib3hwbG90KCkgKw0KICB0aGVtZV9idygpDQpgYGANCiMjIyBTdW1tYXJ5IHRhYmxlICANCg0KPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtaW5mbyI+DQpUaGUgdGFibGUgYmVsb3cgcmVwb3J0cyB0aGUgQVNRLTQgcmVzdWx0cy4gSSBkaWQgbm90IGdyb3VwIHRoZSByZXN1bHRzIGJ5IGFnZSBpbnRlcnZhbC4gICAgICANCjwvZGl2Pg0KDQpgYGB7ciwgcmVzdWx0cyA9ICJhc2lzIn0NCmRzX2JpcnRoX3RocmVlX2FlcHNfYXNxICU+JQ0KICBzZWxlY3QoYXNxNF9pZCwgZXZlcnl0aGluZygpKSAlPiUgI2p1c3QgZm9yIGNoZWNraW5nDQogIGRpc3RpbmN0KGFzcTRfaWQsIC5rZWVwX2FsbCA9IFQpICU+JSAjdXNlIG9ubHkgb25lIGluZm9ybWF0aW9uICh3ZSBoYXZlIDIyIGNoaWxkcmVuIGhlcmUpDQogIHNlbGVjdChlbmRzX3dpdGgoIl9zdW0iKSkgJT4lIA0KICBqYW5pdG9yOjpyZW1vdmVfZW1wdHkoYygiY29scyIpKSAlPiUgI3JlbW92ZSBlbXB0eSBjb2x1bW5zDQogIHBpdm90X2xvbmdlcihldmVyeXRoaW5nKC4pKSAlPiUgDQogIGFyc2VuYWw6OnRhYmxlYnkobmFtZSB+IHZhbHVlLCAuKSAlPiUgDQogIHN1bW1hcnkoKQ0KYGBgDQoNCg0KDQojIyBBRVBTIGRvbWFpbnMgYW5kIHNraWxscw0KDQo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1pbmZvIj4NClRoZSBmb2xsb3dpbmcgcmVzdWx0cyB3aWxsIHByZXNlbnQgdGhlIEFFUFMgZmluZGluZ3MuICAgDQo8L2Rpdj4NCg0KIyMjIERlc2NyaXB0aXZlIHRhYmxlICANCg0KDQo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1pbmZvIj4NClRoZSBmb2xsb3dpbmcgdGFibGUgd2lsbCBwcmVzZW50IHRoZSBkZXNjcmlwdGl2ZXMgb2YgZWFjaCBwYXJ0aWNpcGFudCBhbmQgYWN0aXZpdGl5IA0KPC9kaXY+DQoNCg0KYGBge3J9DQpkc19iaXJ0aF90aHJlZV9hZXBzX2FzcSAlPiUgDQogIHNlbGVjdChhc3E0X2lkLCBldmVyeXRoaW5nKCkpICU+JSANCiAgZ3JvdXBfYnkoYXNxNF9pZCkgJT4lIA0KICBhcnJhbmdlKGFzcTRfaWQpICU+JSANCiAgY291bnQoZG9tYWluLCBza2lsbCkNCmBgYA0KPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtZGFuZ2VyIj4NCkhvdyB0byBpbnRlcnByZXQgdGhlc2UgcmVzdWx0cz8gICAgICANCkFTUTRpZCA9IDUwMCAoaXQncyBhIGNoaWxkIGluIHRoZSBkYXRhc2V0KQ0KSGUgb3IgU2hlIGhhcyAxOCByZXN1bHRzIGluIGRvbWFpbiBgYWRhcHRhdGl2ZWAgYW5kIHNraWxsID0gYEZlZWRpbmdgLiAgIA0KSWYgeW91IGFjY2VzcyB0aGUgZXhjZWwgZmlsZSwgaXQgd2lsbCBiZSB0aGVzZSBzYW1lIHZhbHVlcy4gIA0KPC9kaXY+DQoNCg0KDQojIyMgUGxvdCB0b3RhbCBzY29yZXMgIA0KDQo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1pbmZvIj4NCklmIEkgdW5kZXJzdG9vZCBldmVyeXRoaW5nIHJpZ2h0IChJJ3ZlIGNvbnN1bHRlZCBodHRwczovL3B0LnNsaWRlc2hhcmUubmV0L0Jyb29rZXNQdWJDby9hZXBzLWludHJvLXdlYmluYXItc2xpZGVzaGFyZSksICAgIA0KZWFjaCBwYXJ0aWNpcGFudCBuZWVkcyB0byBoYXZlIGEgc2NvcmUgcmVmbGVjdGluZyBoaXMvaGVyIGFiaWxpdHkuICAgIA0KVGhlcmVmb3JlLCBJIHN1bW1lZCB1cCB0aGUgc2NvcmVzIG9idGFpbmVkIGluIGVhY2ggc2tpbGwgb2YgZWFjaCBkb21haW4gKGUuZy46IFJlYWNoLCBHcmFiLCBhbmQgUmVsZWFzZSBmcm9tIEZpbmUgbW90b3IpLiANCjwvZGl2Pg0KDQoNCmBgYHtyfQ0KZHNfYmlydGhfdGhyZWVfYWVwc19hc3EgJT4lIA0KICBncm91cF9ieShhc3E0X2lkLGRvbWFpbiwgc2tpbGwpICU+JSAgI2dyb3AgZm9yIGhhdmluZyBlYWNoIHNjb3JlIGZvciBlYWNoIHBhcnRpY2lwYW50DQogIHN1bW1hcmlzZShyYXdfc2NvcmUgPSBzdW0oc2NvcmUpKSAlPiUgI2NyZWF0ZSB0aGUgc3VtbWF0aXZlIHNjb3JlDQogIHNlbGVjdChhc3E0X2lkLGRvbWFpbiwgc2tpbGwsIHJhd19zY29yZSkgJT4lICNzZWxlY3QgYmVmb3JlIHBpdm90aW5nDQogICAgICBwaXZvdF9sb25nZXIoLWMoYXNxNF9pZCwgcmF3X3Njb3JlLCBza2lsbCksDQogICAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gImRvbWFpbiIpICU+JSANCiAgc2VsZWN0KC1uYW1lKSAlPiUgDQogIGdncGxvdCguLCBhZXMoeCA9IGRvbWFpbiwgeSA9IHJhd19zY29yZSwgZmlsbCA9IHNraWxsKSkgKw0KICAjZ2VvbV9jb2wocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZTIocHJlc2VydmUgPSAic2luZ2xlIikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgcG9zaXRpb24gPSAiZG9kZ2UiLCB3aWR0aCA9IDAuOCkgKw0KICB0aGVtZV9idygpDQogIA0KYGBgDQoNCiMjIyBTdW1tYXJ5IHRvdGFsIHNjb3JlcyANCg0KPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtaW5mbyI+DQpUaGUgZm9sbG93aW5nIHRhYmxlIHByZXNlbnRzIHRoZSBzYW1lIGluZm9ybWF0aW9uIHByZXNlbnRlZCBhYm92ZS4gSG93ZXZlciwgSSBpbWFnaW5lIHlvdSdsbCBiZSBhYmxlIHRvIGNoZWNrIGlmIGV2ZXJ5dGhpbmcgaXMgY29ycmVjdC4gICANCjwvZGl2Pg0KDQpgYGB7ciwgcmVzdWx0cyA9ICJhc2lzIn0NCmRzX2JpcnRoX3RocmVlX2FlcHNfYXNxICU+JSANCiAgZ3JvdXBfYnkoYXNxNF9pZCxkb21haW4sIHNraWxsKSAlPiUgICNncm9wIGZvciBoYXZpbmcgZWFjaCBzY29yZSBmb3IgZWFjaCBwYXJ0aWNpcGFudA0KICBzdW1tYXJpc2UocmF3X3Njb3JlID0gc3VtKHNjb3JlKSkgJT4lICNjcmVhdGUgdGhlIHN1bW1hdGl2ZSBzY29yZQ0KICBzZWxlY3QoYXNxNF9pZCxkb21haW4sIHNraWxsLCByYXdfc2NvcmUpICU+JSAjc2VsZWN0IGJlZm9yZSBwaXZvdGluZw0KICAgICAgcGl2b3RfbG9uZ2VyKC1jKGFzcTRfaWQsIHJhd19zY29yZSwgc2tpbGwpLA0KICAgICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJkb21haW4iKSAlPiUgDQogIHNlbGVjdCgtbmFtZSkgJT4lIA0KICBncm91cF9ieShkb21haW4sIHNraWxsKSAlPiUgDQogIHN1bW1hcmlzZShtZWFuKHJhd19zY29yZSksIHNkKHJhd19zY29yZSksIG4oKSkgJT4lIA0KICBtdXRhdGVfaWYoaXMubnVtZXJpYyxyb3VuZCwyKQ0KYGBgDQoNCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LWRhbmdlciI+DQpIb3cgdG8gaW50ZXJwcmV0IHRoZXNlIHJlc3VsdHM/ICAgICAgDQpFeGFtcGxlOiAgIA0Kd2hlbiBjb25zaWRlcmluZyAqKmFsbCBjaGlsZHJlbioqIGluIGRvbWFpbiAoZmluZSBtb3RvciksIGFuZCBza2lsbCAoQS4gUmVhY2gsIEdyYWIsIFJlbGVhc2UpLCB0aGUgbWVhbiByZXN1bHQgaXMgMzQuODIgICANCkkgZG91YmxlIGNoZWNrZWQgdGhlIGV4Y2VsIGZpbGUgYW5kIHRoaXMgcmVzdWx0IGlzIGNvcnJlY3QgICANCjwvZGl2Pg0KDQoNCg0KIyMgQ29ycmVsYXRpb25zIEFFUFMgQVNRLTQgDQoNCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LWluZm8iPg0KVGhlIGZvbGxvd2luZyB0YWJsZXMgd2lsbCBwcmVzZW50IHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIGVhY2ggQVNRLTQgZG9tYWluIGFuZCBpdHMgQUVQUyBwYXJhbGxlbC4gICANCkknbSB1c2luZyB0aGUgc3VtbWF0aXZlIHNjb3JlIG9mIHRoZSBBU1EtNCBhbmQgYWxzbyB0aGUgc3VtbWF0aXZlIHNjb3JlIG9mIEFFUFMuICBEaWFuZSwgcGxlYXNlIGxldCBtZSBrbm93IGlmIHRoYXQncyB0aGUgd2F5IHRvIGFjaGlldmUgdGhlIEFFUFMgcmVzdWx0cy4gICANCjwvZGl2Pg0KDQo+IFBsZWFzZSBkb24ndCBjb25zaWRlciB0aGUgdGhyZWUgZm9sbG93aW5nIGNodW5rcy4gVGhleSBhcmUgcHJvZ3JhbW1pbmcgc3ludGF4ZXMuICANCg0KIyMjIENyZWF0ZSBhIHN1bW1hdGl2ZSBzY29yZSAoQXNrIERpYW5lKQ0KDQpgYGB7cn0NCmNvcl9kc18xIDwtIGRzX2JpcnRoX3RocmVlX2FlcHNfYXNxICU+JSANCiAgZ3JvdXBfYnkoYXNxNF9pZCxkb21haW4sIHNraWxsKSAlPiUgICNncm9wIGZvciBoYXZpbmcgZWFjaCBzY29yZSBmb3IgZWFjaCBwYXJ0aWNpcGFudA0KICBzdW1tYXJpc2UocmF3X3Njb3JlID0gc3VtKHNjb3JlKSkNCmBgYA0KDQojIyMgQ3JlYXRlIGEgZGF0YWZyYW1lIHRvIGdhdGhlciBhbGwgZGF0YSANCg0KYGBge3J9DQpjb3JfZHNfMiA8LSBkc19iaXJ0aF90aHJlZV9hZXBzX2FzcSAlPiUNCiAgc2VsZWN0KGFzcTRfaWQsIGV2ZXJ5dGhpbmcoKSkgJT4lICNqdXN0IGZvciBjaGVja2luZw0KICBkaXN0aW5jdChhc3E0X2lkLCAua2VlcF9hbGwgPSBUKSAlPiUgI3VzZSBvbmx5IG9uZSBpbmZvcm1hdGlvbiAod2UgaGF2ZSAyMiBjaGlsZHJlbiBoZXJlKQ0KICBzZWxlY3QoYXNxNF9pZCxlbmRzX3dpdGgoIl9zdW0iKSkgJT4lIA0KICBqYW5pdG9yOjpyZW1vdmVfZW1wdHkoImNvbHMiKSAlPiUgI3JlbW92ZSBlbXB0eSBjb2x1bW5zDQogIHBpdm90X2xvbmdlcigtYXNxNF9pZCwgbmFtZXNfdG8gPSAiYXNxNCIpIA0KYGBgDQoNCg0KIyMjIE1lcmdlIHRoZXNlIGRhdGEgYW5kIHJlbW92ZSB1c2VsZXNzIHZlY3RvcnMgIA0KYGBge3J9DQpjb3JfZHMgPC0gbGVmdF9qb2luKGNvcl9kc18xLGNvcl9kc18yKQ0Kcm0oY29yX2RzXzEsIGNvcl9kc18yKQ0KYGBgDQoNCg0KIyMgQVNRIEZpbmUgbW90b3IgdnMgQUVQUyBGaW5lIG1vdG9yDQoNCmBgYHtyfQ0KbGlicmFyeShjb3JycikgI2NvcnJlbGF0aW9uIA0KYGBgDQoNCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LWluZm8iPg0KQ29ycmVsYXRpb24gYmV0d2VlbiAqQVNRIEZpbmUgbW90b3IqIGFuZCAqQUVQUyBGaW5lIG1vdG9yKg0KSSdtIHVzaW5nIHRoZSBzYW1lIGNoaWxkISANCjwvZGl2Pg0KDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlID0gRkFMU0UgIH0NCmNvcl9kcyAlPiUgDQogIGZpbHRlcihhc3E0ID09ICJmbV9zdW0iLCBkb21haW4gPT0gImZpbmVfbW90b3IiKSU+JQ0KICBncm91cF9ieShza2lsbCkgJT4lIA0KICBzZWxlY3QocmF3X3Njb3JlLCB2YWx1ZSkgJT4lIA0KICBuZXN0KCkgJT4lIA0KICBtdXRhdGUoZGF0YSA9IG1hcChkYXRhLCBwdXJycjo6Y29tcG9zZShzdHJldGNoLCBjb3JyZWxhdGUpKSkgJT4lIA0KICB1bm5lc3QoY29scyA9IC1za2lsbCkgJT4lIA0KICBuYS5vbWl0ICAlPiUgDQogIGRpc3RpbmN0KHNraWxsLCAua2VlcF9hbGwgPSBUKQ0KYGBgDQoNCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LWRhbmdlciI+DQpIb3cgdG8gaW50ZXJwcmV0IHRoZXNlIHJlc3VsdHM/ICAgICAgDQpUaGUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgQVNRLTQgZmluZSBtb3RvciBhbmQgQUVQUyBmaW5lIG1vdG9yIChza2lsbDogUmVhY2ggYW5kIEdyYWIpIGlzIC0wLjIyIChtYWtlcyBubyBzZW5zZSB0byBtZSkgICANClRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBBU1EtNCBmaW5lIG1vdG9yIGFuZCBBRVBTIGZpbmUgbW90b3IgKHNraWxsOiBGdW5jdGlvbmFsIHVzZSkgaXMgLTAuMDUgKG1ha2VzIG5vIHNlbnNlIHRvIG1lKSAgIA0KDQoqKkkgaGF2ZSBhdHRhY2hlZCBhbiBleGNlbCBmaWxlIGluIHdoaWNoIEkgbWFubnVhbGx5IHJhbiB0aGVzZSBjb3JyZWxhdGlvbnMgYW5kIHRoZSByZXN1bHRzIG1hdGNoKioNCjwvZGl2Pg0KDQojIyBBU1EgZ3Jvc3MgbW90b3IgQUVQUyBncm9zcyBtb3Rvcg0KDQoNCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LWluZm8iPg0KQ29ycmVsYXRpb24gYmV0d2VlbiAqQVNRIEdyb3NzIG1vdG9yKiBhbmQgKkFFUFMgR3Jvc3MgbW90b3IqDQpJJ20gdXNpbmcgdGhlIGRhdGEgZnJvbSBzYW1lIGNoaWxkcmVuLiAgICANCjwvZGl2Pg0KDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlID0gRkFMU0UgIH0NCmNvcl9kcyAlPiUgDQogIGZpbHRlcihhc3E0ID09ICJnbV9zdW0iLCBkb21haW4gPT0gImdyb3NzX21vdG9yIikgJT4lDQogIGdyb3VwX2J5KHNraWxsKSAlPiUgDQogIHNlbGVjdChyYXdfc2NvcmUsIHZhbHVlKSAlPiUgDQogIG5lc3QoKSAlPiUgDQogIG11dGF0ZShkYXRhID0gbWFwKGRhdGEsIHB1cnJyOjpjb21wb3NlKHN0cmV0Y2gsIGNvcnJlbGF0ZSkpKSAlPiUgDQogIHVubmVzdChjb2xzID0gLXNraWxsKSAlPiUgDQogIG5hLm9taXQgICU+JSANCiAgZGlzdGluY3Qoc2tpbGwsIC5rZWVwX2FsbCA9IFQpDQpgYGANCg0KPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtZGFuZ2VyIj4NCkhvdyB0byBpbnRlcnByZXQgdGhlc2UgcmVzdWx0cz8gICAgICANClRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBBU1EtNCBncm9zcyBtb3RvciBhbmQgQUVQUyBncm9zcyBtb3RvciAoc2tpbGw6IEEuIE1vdmVtZW50IGFuZCBMb2NvbW90aW9uKSBpcyAtMC4xNyAobWFrZXMgbm8gc2Vuc2UgdG8gbWUpICAgICANClRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBBU1EtNCBncm9zcyBtb3RvciBhbmQgQUVQUyBncm9zcyBtb3RvciAoc2tpbGw6IEIuIEJhbGFuY2UgaW4gU2l0dGluZykgaXMgLTAuMDYgKG1ha2VzIG5vIHNlbnNlIHRvIG1lKSAgICAgDQpUaGUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgQVNRLTQgZ3Jvc3MgbW90b3IgYW5kIEFFUFMgZ3Jvc3MgbW90b3IgKHNraWxsOiBDLiBCYWxhbmNlICYgTW9iaWxpdHkpIGlzIDAuMDMgKG1ha2VzIG5vIHNlbnNlIHRvIG1lKSAgICAgIA0KVGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIEFTUS00IGdyb3NzIG1vdG9yIGFuZCBBRVBTIGdyb3NzIG1vdG9yIChza2lsbDogRC4gUGxheSBTa2lsbHMpIGlzIDAuMDQgKG1ha2VzIG5vIHNlbnNlIHRvIG1lKSANCjwvZGl2Pg0KDQojIyBBU1EgUGVyc29uYWwtU29jaWFsIEFFUFMgYWRhcHRpdmUNCg0KPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtaW5mbyI+DQoqKkphbmU6IEp1c3QgdG8gcmVmcmVzaCBteSBtZW1vcnkuIEluIHRoZSBkYXRhc2V0LCBQUyBtZWFucyBwcm9ibGVtLXNvbHZpbmcgYW5kIFAgbWVhbnMgUGVyc29uYWwgYW5kIFNvY2lhbCwgcmlnaHQ/ICAgDQpDb3JyZWxhdGlvbiBiZXR3ZWVuICpBU1EgUGVyc29uYWwtU29jaWFsKiBhbmQgKkFFUFMgQWRhcHRpdmUqDQpJJ20gdXNpbmcgdGhlIGRhdGEgZnJvbSBzYW1lIGNoaWxkcmVuLiAgICANCjwvZGl2Pg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZSA9IEZBTFNFICB9DQpjb3JfZHMgJT4lIA0KICBmaWx0ZXIoYXNxNCA9PSAicGVyX3N1bSIsIGRvbWFpbiA9PSAiYWRhcHRpdmVfYXJlYSIpICU+JQ0KICBncm91cF9ieShza2lsbCkgJT4lIA0KICBzZWxlY3QocmF3X3Njb3JlLCB2YWx1ZSkgJT4lIA0KICBuZXN0KCkgJT4lIA0KICBtdXRhdGUoZGF0YSA9IG1hcChkYXRhLCBwdXJycjo6Y29tcG9zZShzdHJldGNoLCBjb3JyZWxhdGUpKSkgJT4lIA0KICB1bm5lc3QoY29scyA9IC1za2lsbCkgJT4lIA0KICBuYS5vbWl0ICAlPiUgDQogIGRpc3RpbmN0KHNraWxsLCAua2VlcF9hbGwgPSBUKQ0KYGBgDQoNCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LWRhbmdlciI+DQpIb3cgdG8gaW50ZXJwcmV0IHRoZXNlIHJlc3VsdHM/ICAgICAgDQpUaGUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgQVNRLTQgUGVyc29uYWwgYW5kIFNvY2lhbCBhbmQgQUVQUyBBZGFwdGl2ZSAoc2tpbGw6IEEuIEZlZWRpbmcpIGlzIDAuMzQgKG1ha2VzIHNlbnNlISEpICAgICANClRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBBU1EtNCBQZXJzb25hbCBhbmQgU29jaWFsIGFuZCBBRVBTIEFkYXB0aXZlIChza2lsbDogQi4gUGVyc29uYWwgSHlnaWVuZSkgaXMgMC4yNyAobWFrZXMgc2Vuc2UhISkgICAgIA0KVGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIEFTUS00IFBlcnNvbmFsIGFuZCBTb2NpYWwgYW5kIEFFUFMgQWRhcHRpdmUgKHNraWxsOiBDLiBVbmRyZXNzaW5nKSBpcyAwLjMwIChtYWtlcyBzZW5zZSEhKSAgICAgDQo8L2Rpdj4gICANCg0KZW5kIG9mIHJlcG9ydA==