Word selection information
Seed words:
1) Got all Kuperman words with 3 < AOA < 6
2) Filtered out Kuperman words that were on MCDI
3) Got hypernyms for Kuperman words
4) Selected lowest 25% as potential seed words (= most superordinate)
Control words:
1) For each seed word, got all hyponyms
2) Filtered based on CHILDES production frequencies:
a) Child log freq > 0
b) Adult log freq > 2
3) Removed control words that were also in the seed word list
4) Removed ‘beast’, ‘group’, ‘part’ due to disproportionately many hyponyms (>2SDs above mean)
5) For remaining words (~1000), got wordnet definition based on synset
a) important because hyponym synsets don’t map 1-1 with how kids would actually use the word
6) For each control word definition, decided if a child would/could use word in this sense
7) Narrowed down control words to words where child WOULD use word in that sense
8) Currently keeping multiple potential controls for some seed words, as ~500 words is reasonable to ask parents about
Read in relevant files
kuperman <- read.csv("../AoA_ratings_Kuperman_et_al_BRM/AoA_ratings_Kuperman_et_al_BRM.csv") %>%
select(Word, aoa=Rating.Mean)
mcdi <- read.csv("hypernym_analysis-master/wordbank/wordbank-aoa-data.csv") %>%
filter(language=="English (American)") %>%
select(uni_lemma, words, aoa) %>%
rename(aoa_months=aoa, Word=uni_lemma) %>%
select(Word)
hypernyms <- read.csv("seedWords_aoa_hypernyms_concreteness_CDI_z.csv") %>%
select(-Conc.M, conc_z_pos) %>%
rename(num_hypernyms=hypernyms)
concreteness <- read.csv("Concreteness_ratings_Brysbaert_et_al_BRM.txt", sep="") %>%
filter(Dom_Pos != 0) %>%
select(Word, Conc.M)
hyponyms <- read.csv("AOA/aoa_to_wordnet_with_hyponyms.csv") %>%
rename(Word=wordnet_lemma, pos=wordnet_PoS) %>%
select(Word, num_hyponyms, pos)
peers <- read.csv("AOA/aoa_to_wordnet_with_peers.csv") %>%
rename(Word=wordnet_lemma, pos=wordnet_PoS) %>%
select(Word, num_peers, pos)
subtlex <- read.csv("subtlex_full.txt", sep="")
all_childes_counts <- read.csv("hypernym_analysis-master/childes/childes_word_freq_adult_and_kid.txt") %>%
rename(Word=word)
individual_hyponyms_int <- read.csv("AOA/all_hyponyms_per_seed_word.csv")
individual_hyponyms_int$hyponym <- as.character(individual_hyponyms_int$hyponym)
individual_hyponyms <- individual_hyponyms_int %>%
select(-X) %>%
separate(hyponym, into=c("Word","pos","wordnet_sense"), sep='\\.') %>%
rename(SeedWord=wordnet_lemma, num_peers=hyponym_num_peers, num_hypernyms=hyponym_num_hypernyms)
Merge into big df for selecting control words
#use existing childes frequency csv, don't need to look them up
candidate_words <- left_join(hypernyms, concreteness, by="Word") %>%
filter(!(Word %in% mcdi)) %>%
left_join(hyponyms, by=c("Word", "pos")) %>%
left_join(peers, by=c("Word","pos")) %>%
group_by(pos) %>%
mutate(conc_z_pos = scale(Conc.M)) %>%
ungroup() %>%
left_join(all_childes_counts, by="Word") %>%
arrange(Word) %>%
mutate(type="seed", SeedWord=NA)
#get hyponym count for each seed word, from hyponym csv
control_word_count <- individual_hyponyms %>%
filter(SeedWord %in% candidate_words$Word) %>%
group_by(SeedWord) %>%
summarise(N_controls=n())
seedList <- candidate_words$Word
#narrow control word list to match words in candidate_words and remove group, beast, part, as they have disproportionately many hyponyms
control_words <- individual_hyponyms %>%
filter(SeedWord %in% candidate_words$Word) %>%
filter(!(SeedWord %in% c("group","beast","part"))) %>%
left_join(all_childes_counts, by="Word") %>%
select(SeedWord,Word,pos,kid_log_freq,adult_log_freq,
num_peers,num_hypernyms) %>%
filter(!is.na(adult_log_freq)) %>%
mutate(type="control") %>%
left_join(kuperman, by="Word")
candidate_words_smaller <- candidate_words %>%
select(names(control_words))
seed_and_controls <- bind_rows(candidate_words_smaller, control_words)
# choose_control_words <- candidate_words %>%
# select(SeedWord=Word, aoa_seed=aoa, num_hypernyms_seed=num_hypernyms, num_hyponyms_seed=num_hyponyms,
# num_peers_seed=num_peers, seed_kid_freq=kid_freq,seed_kid_log_freq=kid_log_freq,
# seed_adult_freq=adult_freq,seed_adult_log_freq=adult_log_freq,seed_pos=pos) %>%
# left_join(control_words, by="SeedWord") %>%
# select(SeedWord,seed_pos,Word,control_pos,seed_adult_log_freq,control_adult_log_freq,aoa_seed,
# num_hypernyms_seed,num_peers_seed,num_hypernyms_control=control_word_num_hypernyms,
# num_peers_control=control_word_num_peers) %>%
# distinct()
#choose control words based on childes adult log frequency
# choose_control_words_by_freq <- choose_control_words %>%
# filter((seed_adult_log_freq-1 < control_adult_log_freq) & (control_adult_log_freq<seed_adult_log_freq+1)) %>%
# filter(seed_pos==control_pos) %>%
# distinct()
Add subtlex frequency
subtlex_merge <- select(subtlex, Word, FREQcount)
seed_and_controls_subtlex <- left_join(seed_and_controls, subtlex_merge, by="Word") %>%
mutate(logFreq_subtlex=log(FREQcount+1))
#need to add hyponyms (seed words only)
seed_and_controls_full <- left_join(seed_and_controls_subtlex, hyponyms, by=c("Word", "pos")) %>%
distinct() %>%
filter(adult_log_freq>2 & kid_log_freq>0) %>%
filter((type=="control" & !(Word %in% seedList)) | type=="seed") %>%
mutate(log_hyponyms = log(num_hyponyms+1))
seeds_only <- filter(seed_and_controls_full, type=="seed")
controls_only <- filter(seed_and_controls_full, type=="control")
Add info about whether child would know the specific sense of the control word
seeds_with_controls <- filter(filtered_seeds_controls_full, !(SeedWord %in% seeds_with_no_controls_list$SeedWord))
Error: unexpected symbol in:
"
seeds_with_controls"
Make df for analyses
new_hyponyms_controls <- read.csv("controls_actual_hypernyms_hyponyms.csv") %>% select(-X, -wordnet_sense, -num_hypernyms, -num_hyponyms_set)
analysis_controls <- left_join(filter(seeds_with_controls, type=="control"), new_hyponyms_controls, by=c("Word","pos")) %>%
select(-num_hyponyms_old, -log_hyponyms_old)
Column `Word` joining character vector and factor, coercing into character vectorColumn `pos` joining character vector and factor, coercing into character vector
analysis_seeds <- filter(seeds_with_controls, type=="seed") %>%
rename(num_hyponyms=num_hyponyms_old) %>%
select(-log_hyponyms_old)
analysis_seeds_controls <- bind_rows(analysis_controls, analysis_seeds) %>%
mutate(log_hyponyms=log(num_hyponyms+1))
Compare seed and control words
Summary statistics
Filtered by adult_log_freq > 2, kid_log_freq > 0, and definition a child would know
sumTable <- analysis_seeds_controls %>%
group_by(type) %>%
summarise(number=n(),
mean_aoa=mean(aoa, na.rm=TRUE),
mean_kid_log_freq=mean(kid_log_freq, na.rm=TRUE),
mean_adult_log_freq=mean(adult_log_freq, na.rm=TRUE),
mean_hypernyms=mean(num_hypernyms),
mean_hyponyms=mean(num_hyponyms, na.rm=TRUE),
mean_peers=mean(num_peers))
as_tibble(sumTable)
Correlation matrices
Seed words
candidate_words_corrmatrix <- analysis_seeds_controls %>%
filter(type=="seed") %>%
select(-Word, -pos, -SeedWord, -type, -FREQcount, -control_def, -child_know, -num_hypernyms_first)
candidate_words_cor <- cor(candidate_words_corrmatrix, use="pairwise.complete.obs", method="pearson")
p.mat_item <- cor.mtest(candidate_words_cor)
pMatrix_item <- p.mat_item$p
corrplot(candidate_words_cor, method = 'color', type='lower', diag = TRUE, addCoef.col = "black",
tl.col = "black", number.font=2, number.cex=8/ncol(candidate_words_cor), p.mat=pMatrix_item, sig.level = 0.05, insig = "blank")

Control words
control_words_corrmatrix <- analysis_seeds_controls %>%
filter(type=="control") %>%
select(-Word, -pos, -SeedWord, -type, -FREQcount, -control_def, -child_know, -num_hypernyms_first)
control_words_cor <- cor(control_words_corrmatrix, use="pairwise.complete.obs", method="pearson")
p.mat_item <- cor.mtest(control_words_cor)
pMatrix_item <- p.mat_item$p
corrplot(control_words_cor, method = 'color', type='lower', diag = TRUE, addCoef.col = "black",
tl.col = "black", number.font=2, number.cex=8/ncol(control_words_cor), p.mat=pMatrix_item, sig.level = 0.05, insig = "blank")

All words (matrix corrects for multiple comparisons; num_hypernym-log_hyponym correlation p = .002)
all_words_corrmatrix <- analysis_seeds_controls %>%
select(-Word, -pos, -SeedWord, -type, -FREQcount, -control_def, -child_know, -num_hypernyms_first)
all_words_cor <- cor(all_words_corrmatrix, use="pairwise.complete.obs", method="pearson")
p.mat_item <- cor.mtest(all_words_cor)
pMatrix_item <- p.mat_item$p
corrplot(all_words_cor, method = 'color', type='lower', diag = TRUE, addCoef.col = "black",
tl.col = "black", number.font=2, number.cex=8/ncol(all_words_cor), p.mat=pMatrix_item, sig.level = 0.05, insig = "blank")

Look at relations between density & category hierarchy
Hyponyms & Hypernyms
ggplot(analysis_seeds_controls, aes(num_hypernyms,log_hyponyms, label=Word, color=type))+
geom_point()+
# geom_label()+
geom_smooth(method=lm)+
theme_classic()

Hyponyms & Peers
ggplot(analysis_seeds_controls, aes(log_hyponyms, num_peers, color=type, label=as.character(Word)))+
geom_point()+
geom_smooth(method="lm")+
# geom_label()+
#scale_x_continuous(breaks=seq(0,900,50))
theme_classic()

Hypernyms & Peers
ggplot(analysis_seeds_controls, aes(num_hypernyms, num_peers, label=as.character(Word), color=type))+
geom_point()+
geom_smooth(method="lm")+
#geom_label()
theme_classic()

#What are those low-hypernym, highly dense words? (they are all verbs - this makes sense)
# lowHyper_highPeer <- filter(seed_and_controls_full, (num_peers > 100) & (num_hypernyms < 3)) %>%
# select(Word, type, pos, aoa, num_peers, num_hyponyms, num_hypernyms, adult_log_freq)
# DT::datatable(lowHyper_highPeer)
#scale hyponyms and hypernyms by part of speech
seed_and_controls_pos <- analysis_seeds_controls %>%
group_by(pos) %>%
mutate(hyper_z_pos = scale(num_hypernyms), hypo_z_pos = scale(num_hyponyms)) %>%
ungroup() %>%
filter(pos %in% c('n','v'))
How are hyponyms-hypernyms correlation when controlling for pos?
Part of speech (points)
ggplot(seed_and_controls_pos, aes(hyper_z_pos, hypo_z_pos, color=pos, label=as.character(Word)))+
geom_point()+
geom_smooth(method=lm)+
theme_classic()

Part of speech (labels)
ggplot(seed_and_controls_pos, aes(hyper_z_pos, hypo_z_pos, color=pos, label=as.character(Word)))+
geom_point()+
geom_smooth(method=lm)+
geom_label()+
theme_classic()

Correlation looks good
cor.test(seed_and_controls_pos$hyper_z_pos, seed_and_controls_pos$hypo_z_pos)
Pearson's product-moment correlation
data: seed_and_controls_pos$hyper_z_pos and seed_and_controls_pos$hypo_z_pos
t = -6.1789, df = 483, p-value = 1.372e-09
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
-0.3512314 -0.1861055
sample estimates:
cor
-0.2706581
Compare childes adult and subtlex frequencies (r = .76)
Points
ggplot(analysis_seeds_controls, aes(adult_log_freq, logFreq_subtlex, color=type))+
geom_point()+
geom_smooth(method="lm")+
theme_classic()

Words
ggplot(analysis_seeds_controls, aes(adult_log_freq, logFreq_subtlex, color=type, label=as.character(Word)))+
geom_point()+
geom_label()+
theme_classic()

Compare child-produced and adult-produced frequences (childes)
Points
ggplot(analysis_seeds_controls, aes(adult_log_freq, kid_log_freq, color=type))+
geom_point()+
geom_smooth(method="lm")+
theme_classic()

Words
ggplot(analysis_seeds_controls, aes(adult_log_freq, kid_log_freq, color=type, label=as.character(Word)))+
geom_point()+
geom_label()+
theme_classic()

Difference in Adult-Child production
produceDiff <- analysis_seeds_controls %>%
mutate(adult_log_freq_z=scale(adult_log_freq), kid_log_freq_z=scale(kid_log_freq)) %>%
select(Word, type, pos, aoa, num_peers, num_hyponyms, num_hypernyms, adult_log_freq_z, kid_log_freq_z) %>%
mutate(productionDiff_z = adult_log_freq_z - kid_log_freq_z) %>%
distinct()
DT::datatable(produceDiff)
Childes frequency vs. AOA
Points
ggplot(analysis_seeds_controls, aes(adult_log_freq, aoa, color=type))+
geom_point()+
geom_smooth(method="lm")+
theme_classic()

Words
ggplot(analysis_seeds_controls, aes(adult_log_freq, aoa, color=type,label=as.character(Word)))+
geom_point()+
geom_label()+
theme_classic()

Childes frequency vs. hypernyms
Adults
ggplot(analysis_seeds_controls, aes(adult_log_freq, num_hypernyms, color=type))+
geom_point()+
geom_smooth(method="lm")+
theme_classic()

Kids
ggplot(analysis_seeds_controls, aes(kid_log_freq, num_hypernyms, color=type))+
geom_point()+
geom_smooth(method="lm")+
theme_classic()

What’s the relation between AOA and hypernyms, controlling for frequency?
Adult-produced frequency
summary(lm(aoa ~ num_hypernyms + adult_log_freq, data=analysis_seeds_controls))
Call:
lm(formula = aoa ~ num_hypernyms + adult_log_freq, data = analysis_seeds_controls)
Residuals:
Min 1Q Median 3Q Max
-2.6713 -0.9032 -0.1844 0.7587 6.9039
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 9.48806 0.25551 37.134 <2e-16 ***
num_hypernyms -0.03268 0.01997 -1.636 0.103
adult_log_freq -0.59737 0.03305 -18.074 <2e-16 ***
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
Residual standard error: 1.266 on 469 degrees of freedom
(19 observations deleted due to missingness)
Multiple R-squared: 0.4118, Adjusted R-squared: 0.4092
F-statistic: 164.1 on 2 and 469 DF, p-value: < 2.2e-16
Child-produced frequency
summary(lm(aoa ~ num_hypernyms + kid_log_freq, data=analysis_seeds_controls))
Call:
lm(formula = aoa ~ num_hypernyms + kid_log_freq, data = analysis_seeds_controls)
Residuals:
Min 1Q Median 3Q Max
-2.5617 -0.8955 -0.1123 0.8463 6.5283
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 7.3676121 0.1761510 41.826 <2e-16 ***
num_hypernyms -0.0001083 0.0205084 -0.005 0.996
kid_log_freq -0.4832487 0.0293781 -16.449 <2e-16 ***
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
Residual standard error: 1.314 on 469 degrees of freedom
(19 observations deleted due to missingness)
Multiple R-squared: 0.3671, Adjusted R-squared: 0.3644
F-statistic: 136 on 2 and 469 DF, p-value: < 2.2e-16
LS0tDQp0aXRsZTogIkNyZWF0ZSBkZiBvZiBjYW5kaWRhdGUgd29yZHMgJiBwb2tlIGF0IHRoZW0iDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGNoaWxkZXNyKQ0KbGlicmFyeShsbWU0KQ0KbGlicmFyeShjb3JycGxvdCkNCmxpYnJhcnkoZ2dyZXBlbCkNCmxpYnJhcnkocHN5Y2gpDQpgYGANCl9Xb3JkIHNlbGVjdGlvbiBpbmZvcm1hdGlvbl8gIA0KU2VlZCB3b3JkczogIA0KMSkgR290IGFsbCBLdXBlcm1hbiB3b3JkcyB3aXRoIDMgPCBBT0EgPCA2ICANCjIpIEZpbHRlcmVkIG91dCBLdXBlcm1hbiB3b3JkcyB0aGF0IHdlcmUgb24gTUNESSAgDQozKSBHb3QgaHlwZXJueW1zIGZvciBLdXBlcm1hbiB3b3JkcyAgDQo0KSBTZWxlY3RlZCBsb3dlc3QgMjUlIGFzIHBvdGVudGlhbCBzZWVkIHdvcmRzICg9IG1vc3Qgc3VwZXJvcmRpbmF0ZSkgIA0KICANCkNvbnRyb2wgd29yZHM6ICANCjEpIEZvciBlYWNoIHNlZWQgd29yZCwgZ290IGFsbCBoeXBvbnltcyAgDQoyKSBGaWx0ZXJlZCBiYXNlZCBvbiBDSElMREVTIHByb2R1Y3Rpb24gZnJlcXVlbmNpZXM6ICANCglhKSBDaGlsZCBsb2cgZnJlcSA+IDAgIA0KCWIpIEFkdWx0IGxvZyBmcmVxID4gMiAgDQozKSBSZW1vdmVkIGNvbnRyb2wgd29yZHMgdGhhdCB3ZXJlIGFsc28gaW4gdGhlIHNlZWQgd29yZCBsaXN0ICANCjQpIFJlbW92ZWQgJ2JlYXN0JywgJ2dyb3VwJywgJ3BhcnQnIGR1ZSB0byBkaXNwcm9wb3J0aW9uYXRlbHkgbWFueSBoeXBvbnltcyAoPjJTRHMgYWJvdmUgbWVhbikgIA0KNSkgRm9yIHJlbWFpbmluZyB3b3JkcyAofjEwMDApLCBnb3Qgd29yZG5ldCBkZWZpbml0aW9uIGJhc2VkIG9uIHN5bnNldCAgDQoJYSkgaW1wb3J0YW50IGJlY2F1c2UgaHlwb255bSBzeW5zZXRzIGRvbid0IG1hcCAxLTEgd2l0aCBob3cga2lkcyB3b3VsZCBhY3R1YWxseSB1c2UgdGhlIHdvcmQgIA0KNikgRm9yIGVhY2ggY29udHJvbCB3b3JkIGRlZmluaXRpb24sIGRlY2lkZWQgaWYgYSBjaGlsZCB3b3VsZC9jb3VsZCB1c2Ugd29yZCBpbiB0aGlzIHNlbnNlICANCjcpIE5hcnJvd2VkIGRvd24gY29udHJvbCB3b3JkcyB0byB3b3JkcyB3aGVyZSBjaGlsZCBXT1VMRCB1c2Ugd29yZCBpbiB0aGF0IHNlbnNlICANCjgpIEN1cnJlbnRseSBrZWVwaW5nIG11bHRpcGxlIHBvdGVudGlhbCBjb250cm9scyBmb3Igc29tZSBzZWVkIHdvcmRzLCBhcyB+NTAwIHdvcmRzIGlzIHJlYXNvbmFibGUgdG8gYXNrIHBhcmVudHMgYWJvdXQgIA0KICANCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgICANClJlYWQgaW4gcmVsZXZhbnQgZmlsZXMNCmBgYHtyfQ0Ka3VwZXJtYW4gPC0gcmVhZC5jc3YoIi4uL0FvQV9yYXRpbmdzX0t1cGVybWFuX2V0X2FsX0JSTS9Bb0FfcmF0aW5nc19LdXBlcm1hbl9ldF9hbF9CUk0uY3N2IikgJT4lIA0KICBzZWxlY3QoV29yZCwgYW9hPVJhdGluZy5NZWFuKQ0KbWNkaSA8LSByZWFkLmNzdigiaHlwZXJueW1fYW5hbHlzaXMtbWFzdGVyL3dvcmRiYW5rL3dvcmRiYW5rLWFvYS1kYXRhLmNzdiIpICU+JSANCiAgZmlsdGVyKGxhbmd1YWdlPT0iRW5nbGlzaCAoQW1lcmljYW4pIikgJT4lIA0KICBzZWxlY3QodW5pX2xlbW1hLCB3b3JkcywgYW9hKSAlPiUgDQogIHJlbmFtZShhb2FfbW9udGhzPWFvYSwgV29yZD11bmlfbGVtbWEpICU+JSANCiAgc2VsZWN0KFdvcmQpDQpoeXBlcm55bXMgPC0gcmVhZC5jc3YoInNlZWRXb3Jkc19hb2FfaHlwZXJueW1zX2NvbmNyZXRlbmVzc19DRElfei5jc3YiKSAlPiUgDQogIHNlbGVjdCgtQ29uYy5NLCBjb25jX3pfcG9zKSAlPiUgDQogIHJlbmFtZShudW1faHlwZXJueW1zPWh5cGVybnltcykNCmNvbmNyZXRlbmVzcyA8LSByZWFkLmNzdigiQ29uY3JldGVuZXNzX3JhdGluZ3NfQnJ5c2JhZXJ0X2V0X2FsX0JSTS50eHQiLCBzZXA9IiIpICU+JSANCiAgZmlsdGVyKERvbV9Qb3MgIT0gMCkgJT4lIA0KICBzZWxlY3QoV29yZCwgQ29uYy5NKQ0KaHlwb255bXMgPC0gcmVhZC5jc3YoIkFPQS9hb2FfdG9fd29yZG5ldF93aXRoX2h5cG9ueW1zLmNzdiIpICU+JSANCiAgcmVuYW1lKFdvcmQ9d29yZG5ldF9sZW1tYSwgcG9zPXdvcmRuZXRfUG9TKSAlPiUgDQogIHNlbGVjdChXb3JkLCBudW1faHlwb255bXMsIHBvcykNCnBlZXJzIDwtIHJlYWQuY3N2KCJBT0EvYW9hX3RvX3dvcmRuZXRfd2l0aF9wZWVycy5jc3YiKSAlPiUgDQogIHJlbmFtZShXb3JkPXdvcmRuZXRfbGVtbWEsIHBvcz13b3JkbmV0X1BvUykgJT4lIA0KICBzZWxlY3QoV29yZCwgbnVtX3BlZXJzLCBwb3MpDQpzdWJ0bGV4IDwtIHJlYWQuY3N2KCJzdWJ0bGV4X2Z1bGwudHh0Iiwgc2VwPSIiKQ0KYWxsX2NoaWxkZXNfY291bnRzIDwtIHJlYWQuY3N2KCJoeXBlcm55bV9hbmFseXNpcy1tYXN0ZXIvY2hpbGRlcy9jaGlsZGVzX3dvcmRfZnJlcV9hZHVsdF9hbmRfa2lkLnR4dCIpICU+JSANCiAgcmVuYW1lKFdvcmQ9d29yZCkNCmluZGl2aWR1YWxfaHlwb255bXNfaW50IDwtIHJlYWQuY3N2KCJBT0EvYWxsX2h5cG9ueW1zX3Blcl9zZWVkX3dvcmQuY3N2IikNCmluZGl2aWR1YWxfaHlwb255bXNfaW50JGh5cG9ueW0gPC0gYXMuY2hhcmFjdGVyKGluZGl2aWR1YWxfaHlwb255bXNfaW50JGh5cG9ueW0pDQppbmRpdmlkdWFsX2h5cG9ueW1zIDwtIGluZGl2aWR1YWxfaHlwb255bXNfaW50ICU+JQ0KICBzZWxlY3QoLVgpICU+JSANCiAgc2VwYXJhdGUoaHlwb255bSwgaW50bz1jKCJXb3JkIiwicG9zIiwid29yZG5ldF9zZW5zZSIpLCBzZXA9J1xcLicpICU+JSANCiAgcmVuYW1lKFNlZWRXb3JkPXdvcmRuZXRfbGVtbWEsIG51bV9wZWVycz1oeXBvbnltX251bV9wZWVycywgbnVtX2h5cGVybnltcz1oeXBvbnltX251bV9oeXBlcm55bXMpDQpgYGANCg0KTWVyZ2UgaW50byBiaWcgZGYgZm9yIHNlbGVjdGluZyBjb250cm9sIHdvcmRzDQpgYGB7cn0NCiN1c2UgZXhpc3RpbmcgY2hpbGRlcyBmcmVxdWVuY3kgY3N2LCBkb24ndCBuZWVkIHRvIGxvb2sgdGhlbSB1cA0KY2FuZGlkYXRlX3dvcmRzIDwtIGxlZnRfam9pbihoeXBlcm55bXMsIGNvbmNyZXRlbmVzcywgYnk9IldvcmQiKSAlPiUgDQogIGZpbHRlcighKFdvcmQgJWluJSBtY2RpKSkgJT4lIA0KICBsZWZ0X2pvaW4oaHlwb255bXMsIGJ5PWMoIldvcmQiLCAicG9zIikpICU+JSANCiAgbGVmdF9qb2luKHBlZXJzLCBieT1jKCJXb3JkIiwicG9zIikpICU+JQ0KICBncm91cF9ieShwb3MpICU+JSANCiAgbXV0YXRlKGNvbmNfel9wb3MgPSBzY2FsZShDb25jLk0pKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIGxlZnRfam9pbihhbGxfY2hpbGRlc19jb3VudHMsIGJ5PSJXb3JkIikgJT4lIA0KICBhcnJhbmdlKFdvcmQpICU+JSANCiAgbXV0YXRlKHR5cGU9InNlZWQiLCBTZWVkV29yZD1OQSkNCg0KI2dldCBoeXBvbnltIGNvdW50IGZvciBlYWNoIHNlZWQgd29yZCwgZnJvbSBoeXBvbnltIGNzdg0KY29udHJvbF93b3JkX2NvdW50IDwtIGluZGl2aWR1YWxfaHlwb255bXMgJT4lDQogIGZpbHRlcihTZWVkV29yZCAlaW4lIGNhbmRpZGF0ZV93b3JkcyRXb3JkKSAlPiUgDQogIGdyb3VwX2J5KFNlZWRXb3JkKSAlPiUgDQogIHN1bW1hcmlzZShOX2NvbnRyb2xzPW4oKSkNCg0Kc2VlZExpc3QgPC0gY2FuZGlkYXRlX3dvcmRzJFdvcmQNCg0KI25hcnJvdyBjb250cm9sIHdvcmQgbGlzdCB0byBtYXRjaCB3b3JkcyBpbiBjYW5kaWRhdGVfd29yZHMgYW5kIHJlbW92ZSBncm91cCwgYmVhc3QsIHBhcnQsIGFzIHRoZXkgaGF2ZSBkaXNwcm9wb3J0aW9uYXRlbHkgbWFueSBoeXBvbnltcw0KY29udHJvbF93b3JkcyA8LSBpbmRpdmlkdWFsX2h5cG9ueW1zICU+JQ0KICBmaWx0ZXIoU2VlZFdvcmQgJWluJSBjYW5kaWRhdGVfd29yZHMkV29yZCkgJT4lIA0KICBmaWx0ZXIoIShTZWVkV29yZCAlaW4lIGMoImdyb3VwIiwiYmVhc3QiLCJwYXJ0IikpKSAlPiUgDQogIGxlZnRfam9pbihhbGxfY2hpbGRlc19jb3VudHMsIGJ5PSJXb3JkIikgJT4lIA0KICBzZWxlY3QoU2VlZFdvcmQsV29yZCxwb3Msa2lkX2xvZ19mcmVxLGFkdWx0X2xvZ19mcmVxLA0KICAgICAgICAgbnVtX3BlZXJzLG51bV9oeXBlcm55bXMpICU+JSANCiAgZmlsdGVyKCFpcy5uYShhZHVsdF9sb2dfZnJlcSkpICU+JSANCiAgbXV0YXRlKHR5cGU9ImNvbnRyb2wiKSAlPiUgDQogIGxlZnRfam9pbihrdXBlcm1hbiwgYnk9IldvcmQiKQ0KDQpjYW5kaWRhdGVfd29yZHNfc21hbGxlciA8LSBjYW5kaWRhdGVfd29yZHMgJT4lDQogIHNlbGVjdChuYW1lcyhjb250cm9sX3dvcmRzKSkNCg0Kc2VlZF9hbmRfY29udHJvbHMgPC0gYmluZF9yb3dzKGNhbmRpZGF0ZV93b3Jkc19zbWFsbGVyLCBjb250cm9sX3dvcmRzKQ0KDQojIGNob29zZV9jb250cm9sX3dvcmRzIDwtIGNhbmRpZGF0ZV93b3JkcyAlPiUgDQojICAgc2VsZWN0KFNlZWRXb3JkPVdvcmQsIGFvYV9zZWVkPWFvYSwgbnVtX2h5cGVybnltc19zZWVkPW51bV9oeXBlcm55bXMsIG51bV9oeXBvbnltc19zZWVkPW51bV9oeXBvbnltcywNCiMgICAgICAgICAgbnVtX3BlZXJzX3NlZWQ9bnVtX3BlZXJzLCBzZWVkX2tpZF9mcmVxPWtpZF9mcmVxLHNlZWRfa2lkX2xvZ19mcmVxPWtpZF9sb2dfZnJlcSwNCiMgICAgICAgICAgc2VlZF9hZHVsdF9mcmVxPWFkdWx0X2ZyZXEsc2VlZF9hZHVsdF9sb2dfZnJlcT1hZHVsdF9sb2dfZnJlcSxzZWVkX3Bvcz1wb3MpICU+JSANCiMgICBsZWZ0X2pvaW4oY29udHJvbF93b3JkcywgYnk9IlNlZWRXb3JkIikgJT4lIA0KIyAgIHNlbGVjdChTZWVkV29yZCxzZWVkX3BvcyxXb3JkLGNvbnRyb2xfcG9zLHNlZWRfYWR1bHRfbG9nX2ZyZXEsY29udHJvbF9hZHVsdF9sb2dfZnJlcSxhb2Ffc2VlZCwNCiMgICAgICAgICAgbnVtX2h5cGVybnltc19zZWVkLG51bV9wZWVyc19zZWVkLG51bV9oeXBlcm55bXNfY29udHJvbD1jb250cm9sX3dvcmRfbnVtX2h5cGVybnltcywNCiMgICAgICAgICAgbnVtX3BlZXJzX2NvbnRyb2w9Y29udHJvbF93b3JkX251bV9wZWVycykgJT4lIA0KIyAgIGRpc3RpbmN0KCkNCg0KI2Nob29zZSBjb250cm9sIHdvcmRzIGJhc2VkIG9uIGNoaWxkZXMgYWR1bHQgbG9nIGZyZXF1ZW5jeSANCiMgY2hvb3NlX2NvbnRyb2xfd29yZHNfYnlfZnJlcSA8LSBjaG9vc2VfY29udHJvbF93b3JkcyAlPiUNCiMgICBmaWx0ZXIoKHNlZWRfYWR1bHRfbG9nX2ZyZXEtMSA8IGNvbnRyb2xfYWR1bHRfbG9nX2ZyZXEpICYgKGNvbnRyb2xfYWR1bHRfbG9nX2ZyZXE8c2VlZF9hZHVsdF9sb2dfZnJlcSsxKSkgJT4lIA0KIyAgIGZpbHRlcihzZWVkX3Bvcz09Y29udHJvbF9wb3MpICU+JSANCiMgICBkaXN0aW5jdCgpDQoNCmBgYA0KDQoNCkFkZCBzdWJ0bGV4IGZyZXF1ZW5jeQ0KYGBge3J9DQpzdWJ0bGV4X21lcmdlIDwtIHNlbGVjdChzdWJ0bGV4LCBXb3JkLCBGUkVRY291bnQpDQoNCnNlZWRfYW5kX2NvbnRyb2xzX3N1YnRsZXggPC0gbGVmdF9qb2luKHNlZWRfYW5kX2NvbnRyb2xzLCBzdWJ0bGV4X21lcmdlLCBieT0iV29yZCIpICU+JSANCiAgbXV0YXRlKGxvZ0ZyZXFfc3VidGxleD1sb2coRlJFUWNvdW50KzEpKQ0KDQojbmVlZCB0byBhZGQgaHlwb255bXMgKHNlZWQgd29yZHMgb25seSkNCnNlZWRfYW5kX2NvbnRyb2xzX2Z1bGwgPC0gbGVmdF9qb2luKHNlZWRfYW5kX2NvbnRyb2xzX3N1YnRsZXgsIGh5cG9ueW1zLCBieT1jKCJXb3JkIiwgInBvcyIpKSAlPiUgDQogIGRpc3RpbmN0KCkgJT4lDQogIGZpbHRlcihhZHVsdF9sb2dfZnJlcT4yICYga2lkX2xvZ19mcmVxPjApICU+JSANCiAgZmlsdGVyKCh0eXBlPT0iY29udHJvbCIgJiAhKFdvcmQgJWluJSBzZWVkTGlzdCkpIHwgdHlwZT09InNlZWQiKSAlPiUgDQogIG11dGF0ZShsb2dfaHlwb255bXMgPSBsb2cobnVtX2h5cG9ueW1zKzEpKQ0KDQpzZWVkc19vbmx5IDwtIGZpbHRlcihzZWVkX2FuZF9jb250cm9sc19mdWxsLCB0eXBlPT0ic2VlZCIpDQpjb250cm9sc19vbmx5IDwtIGZpbHRlcihzZWVkX2FuZF9jb250cm9sc19mdWxsLCB0eXBlPT0iY29udHJvbCIpDQpgYGANCg0KQWRkIGluZm8gYWJvdXQgd2hldGhlciBjaGlsZCB3b3VsZCBrbm93IHRoZSBzcGVjaWZpYyBzZW5zZSBvZiB0aGUgY29udHJvbCB3b3JkDQpgYGB7cn0NCmtpZF9rbm93bGVkZ2UgPC0gcmVhZC5jc3YoImNvbnRyb2xfc2Vuc2VzX3dpdGhfZGVmc19jaGlsZGtub3dsZWRnZS5jc3YiKSAlPiUNCiAgcmVuYW1lKGNvbnRyb2xfZGVmPWRlZmluaXRpb24pICU+JQ0KICBzZWxlY3QoLXdvcmRuZXRfc2Vuc2UpDQoNCmZpbHRlcmVkX3NlZWRzX2NvbnRyb2xzIDwtIGZ1bGxfam9pbihraWRfa25vd2xlZGdlLCBzZWVkX2FuZF9jb250cm9sc19mdWxsLCBieT1jKCJTZWVkV29yZCIsIldvcmQiLCJwb3MiKSkgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKHR5cGUpKSAlPiUgDQogIGZpbHRlcihjaGlsZF9rbm93PT0xIHwgdHlwZT09InNlZWQiKQ0KDQpmaWx0ZXJlZF9zZWVkcyA8LSBmaWx0ZXJlZF9zZWVkc19jb250cm9scyAlPiUNCiAgZmlsdGVyKHR5cGU9PSJzZWVkIikgJT4lDQogIG11dGF0ZShTZWVkV29yZD1Xb3JkKQ0KDQpmaWx0ZXJlZF9jb250cm9scyA8LSBmaWx0ZXJlZF9zZWVkc19jb250cm9scyAlPiUgZmlsdGVyKHR5cGU9PSJjb250cm9sIikNCmZpbHRlcmVkX3NlZWRzX2NvbnRyb2xzX2Z1bGwgPC0gYmluZF9yb3dzKGZpbHRlcmVkX2NvbnRyb2xzLCBmaWx0ZXJlZF9zZWVkcykNCnNlZWRzX3dpdGhfbm9fY29udHJvbHNfbGlzdCA8LSBmaWx0ZXJlZF9zZWVkc19jb250cm9sc19mdWxsICU+JSBncm91cF9ieShTZWVkV29yZCkgJT4lIHN1bW1hcmlzZShuX3dvcmRzPW4oKSkgJT4lIGZpbHRlciAobl93b3Jkcz09MSkgJT4lIHNlbGVjdChTZWVkV29yZCkNCnNlZWRzX3dpdGhfbm9fY29udHJvbHMgPC0gZmlsdGVyKGZpbHRlcmVkX3NlZWRzX2NvbnRyb2xzX2Z1bGwsIFdvcmQgJWluJSBzZWVkc193aXRoX25vX2NvbnRyb2xzX2xpc3QkU2VlZFdvcmQpDQpzZWVkc193aXRoX2NvbnRyb2xzIDwtIGZpbHRlcihmaWx0ZXJlZF9zZWVkc19jb250cm9sc19mdWxsLCAhKFNlZWRXb3JkICVpbiUgc2VlZHNfd2l0aF9ub19jb250cm9sc19saXN0JFNlZWRXb3JkKSkgJT4lDQogIGFycmFuZ2UoU2VlZFdvcmQpICU+JSANCiAgcmVuYW1lKG51bV9oeXBvbnltc19vbGQ9bnVtX2h5cG9ueW1zLCBsb2dfaHlwb255bXNfb2xkPWxvZ19oeXBvbnltcykNCg0KYGBgDQoNCk1ha2UgZGYgZm9yIGFuYWx5c2VzDQpgYGB7cn0NCm5ld19oeXBvbnltc19jb250cm9scyA8LSByZWFkLmNzdigiY29udHJvbHNfYWN0dWFsX2h5cGVybnltc19oeXBvbnltcy5jc3YiKSAlPiUgc2VsZWN0KC1YLCAtd29yZG5ldF9zZW5zZSwgLW51bV9oeXBlcm55bXMsIC1udW1faHlwb255bXNfc2V0KQ0KYW5hbHlzaXNfY29udHJvbHMgPC0gbGVmdF9qb2luKGZpbHRlcihzZWVkc193aXRoX2NvbnRyb2xzLCB0eXBlPT0iY29udHJvbCIpLCBuZXdfaHlwb255bXNfY29udHJvbHMsIGJ5PWMoIldvcmQiLCJwb3MiKSkgJT4lIA0KICBzZWxlY3QoLW51bV9oeXBvbnltc19vbGQsIC1sb2dfaHlwb255bXNfb2xkKQ0KDQphbmFseXNpc19zZWVkcyA8LSBmaWx0ZXIoc2VlZHNfd2l0aF9jb250cm9scywgdHlwZT09InNlZWQiKSAlPiUgDQogIHJlbmFtZShudW1faHlwb255bXM9bnVtX2h5cG9ueW1zX29sZCkgJT4lIA0KICBzZWxlY3QoLWxvZ19oeXBvbnltc19vbGQpDQphbmFseXNpc19zZWVkc19jb250cm9scyA8LSBiaW5kX3Jvd3MoYW5hbHlzaXNfY29udHJvbHMsIGFuYWx5c2lzX3NlZWRzKSAlPiUgDQogIG11dGF0ZShsb2dfaHlwb255bXM9bG9nKG51bV9oeXBvbnltcysxKSkNCmBgYA0KDQojIyBDb21wYXJlIHNlZWQgYW5kIGNvbnRyb2wgd29yZHMNCiMjIyBTdW1tYXJ5IHN0YXRpc3RpY3MNCkZpbHRlcmVkIGJ5IGBhZHVsdF9sb2dfZnJlcSA+IDJgLCBga2lkX2xvZ19mcmVxID4gMGAsIGFuZCBkZWZpbml0aW9uIGEgY2hpbGQgd291bGQga25vdw0KYGBge3J9DQoNCnN1bVRhYmxlIDwtIGFuYWx5c2lzX3NlZWRzX2NvbnRyb2xzICU+JSANCiAgZ3JvdXBfYnkodHlwZSkgJT4lIA0KICBzdW1tYXJpc2UobnVtYmVyPW4oKSwNCiAgICAgICAgICAgIG1lYW5fYW9hPW1lYW4oYW9hLCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgIG1lYW5fa2lkX2xvZ19mcmVxPW1lYW4oa2lkX2xvZ19mcmVxLCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgIG1lYW5fYWR1bHRfbG9nX2ZyZXE9bWVhbihhZHVsdF9sb2dfZnJlcSwgbmEucm09VFJVRSksDQogICAgICAgICAgICBtZWFuX2h5cGVybnltcz1tZWFuKG51bV9oeXBlcm55bXMpLA0KICAgICAgICAgICAgbWVhbl9oeXBvbnltcz1tZWFuKG51bV9oeXBvbnltcywgbmEucm09VFJVRSksDQogICAgICAgICAgICBtZWFuX3BlZXJzPW1lYW4obnVtX3BlZXJzKSkNCmFzX3RpYmJsZShzdW1UYWJsZSkNCmBgYA0KDQojIyMgQ29ycmVsYXRpb24gbWF0cmljZXMgey50YWJzZXR9DQojIyMjIFNlZWQgd29yZHMNCmBgYHtyfQ0KY2FuZGlkYXRlX3dvcmRzX2NvcnJtYXRyaXggPC0gYW5hbHlzaXNfc2VlZHNfY29udHJvbHMgJT4lIA0KICBmaWx0ZXIodHlwZT09InNlZWQiKSAlPiUgDQogIHNlbGVjdCgtV29yZCwgLXBvcywgLVNlZWRXb3JkLCAtdHlwZSwgLUZSRVFjb3VudCwgLWNvbnRyb2xfZGVmLCAtY2hpbGRfa25vdywgLW51bV9oeXBlcm55bXNfZmlyc3QpDQoNCmNhbmRpZGF0ZV93b3Jkc19jb3IgPC0gY29yKGNhbmRpZGF0ZV93b3Jkc19jb3JybWF0cml4LCB1c2U9InBhaXJ3aXNlLmNvbXBsZXRlLm9icyIsIG1ldGhvZD0icGVhcnNvbiIpDQoNCnAubWF0X2l0ZW0gPC0gY29yLm10ZXN0KGNhbmRpZGF0ZV93b3Jkc19jb3IpDQpwTWF0cml4X2l0ZW0gPC0gcC5tYXRfaXRlbSRwDQpjb3JycGxvdChjYW5kaWRhdGVfd29yZHNfY29yLCBtZXRob2QgPSAnY29sb3InLCB0eXBlPSdsb3dlcicsIGRpYWcgPSBUUlVFLCBhZGRDb2VmLmNvbCA9ICJibGFjayIsDQogICAgICAgICB0bC5jb2wgPSAiYmxhY2siLCBudW1iZXIuZm9udD0yLCBudW1iZXIuY2V4PTgvbmNvbChjYW5kaWRhdGVfd29yZHNfY29yKSwgcC5tYXQ9cE1hdHJpeF9pdGVtLCBzaWcubGV2ZWwgPSAwLjA1LCBpbnNpZyA9ICJibGFuayIpDQpgYGANCiMjIyMgQ29udHJvbCB3b3Jkcw0KYGBge3J9DQpjb250cm9sX3dvcmRzX2NvcnJtYXRyaXggPC0gYW5hbHlzaXNfc2VlZHNfY29udHJvbHMgJT4lIA0KICBmaWx0ZXIodHlwZT09ImNvbnRyb2wiKSAlPiUgDQogIHNlbGVjdCgtV29yZCwgLXBvcywgLVNlZWRXb3JkLCAtdHlwZSwgLUZSRVFjb3VudCwgLWNvbnRyb2xfZGVmLCAtY2hpbGRfa25vdywgLW51bV9oeXBlcm55bXNfZmlyc3QpDQoNCmNvbnRyb2xfd29yZHNfY29yIDwtIGNvcihjb250cm9sX3dvcmRzX2NvcnJtYXRyaXgsIHVzZT0icGFpcndpc2UuY29tcGxldGUub2JzIiwgbWV0aG9kPSJwZWFyc29uIikNCg0KcC5tYXRfaXRlbSA8LSBjb3IubXRlc3QoY29udHJvbF93b3Jkc19jb3IpDQpwTWF0cml4X2l0ZW0gPC0gcC5tYXRfaXRlbSRwDQpjb3JycGxvdChjb250cm9sX3dvcmRzX2NvciwgbWV0aG9kID0gJ2NvbG9yJywgdHlwZT0nbG93ZXInLCBkaWFnID0gVFJVRSwgYWRkQ29lZi5jb2wgPSAiYmxhY2siLA0KICAgICAgICAgdGwuY29sID0gImJsYWNrIiwgbnVtYmVyLmZvbnQ9MiwgbnVtYmVyLmNleD04L25jb2woY29udHJvbF93b3Jkc19jb3IpLCBwLm1hdD1wTWF0cml4X2l0ZW0sIHNpZy5sZXZlbCA9IDAuMDUsIGluc2lnID0gImJsYW5rIikNCmBgYA0KIyMjIyBBbGwgd29yZHMgKG1hdHJpeCBjb3JyZWN0cyBmb3IgbXVsdGlwbGUgY29tcGFyaXNvbnM7IG51bV9oeXBlcm55bS1sb2dfaHlwb255bSBjb3JyZWxhdGlvbiBwID0gLjAwMikNCmBgYHtyfQ0KYWxsX3dvcmRzX2NvcnJtYXRyaXggPC0gYW5hbHlzaXNfc2VlZHNfY29udHJvbHMgJT4lIA0KICBzZWxlY3QoLVdvcmQsIC1wb3MsIC1TZWVkV29yZCwgLXR5cGUsIC1GUkVRY291bnQsIC1jb250cm9sX2RlZiwgLWNoaWxkX2tub3csIC1udW1faHlwZXJueW1zX2ZpcnN0KQ0KDQphbGxfd29yZHNfY29yIDwtIGNvcihhbGxfd29yZHNfY29ycm1hdHJpeCwgdXNlPSJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiLCBtZXRob2Q9InBlYXJzb24iKQ0KDQpwLm1hdF9pdGVtIDwtIGNvci5tdGVzdChhbGxfd29yZHNfY29yKQ0KcE1hdHJpeF9pdGVtIDwtIHAubWF0X2l0ZW0kcA0KY29ycnBsb3QoYWxsX3dvcmRzX2NvciwgbWV0aG9kID0gJ2NvbG9yJywgdHlwZT0nbG93ZXInLCBkaWFnID0gVFJVRSwgYWRkQ29lZi5jb2wgPSAiYmxhY2siLA0KICAgICAgICAgdGwuY29sID0gImJsYWNrIiwgbnVtYmVyLmZvbnQ9MiwgbnVtYmVyLmNleD04L25jb2woYWxsX3dvcmRzX2NvciksIHAubWF0PXBNYXRyaXhfaXRlbSwgc2lnLmxldmVsID0gMC4wNSwgaW5zaWcgPSAiYmxhbmsiKQ0KYGBgDQoNCiMjIyBMb29rIGF0IHJlbGF0aW9ucyBiZXR3ZWVuIGRlbnNpdHkgJiBjYXRlZ29yeSBoaWVyYXJjaHkgey50YWJzZXR9DQojIyMjIEh5cG9ueW1zICYgSHlwZXJueW1zDQpgYGB7cn0NCmdncGxvdChhbmFseXNpc19zZWVkc19jb250cm9scywgYWVzKG51bV9oeXBlcm55bXMsbG9nX2h5cG9ueW1zLCBsYWJlbD1Xb3JkLCBjb2xvcj10eXBlKSkrDQogIGdlb21fcG9pbnQoKSsNCiAgIyBnZW9tX2xhYmVsKCkrDQogIGdlb21fc21vb3RoKG1ldGhvZD1sbSkrDQogIHRoZW1lX2NsYXNzaWMoKQ0KYGBgDQojIyMjIEh5cG9ueW1zICYgUGVlcnMNCmBgYHtyfQ0KZ2dwbG90KGFuYWx5c2lzX3NlZWRzX2NvbnRyb2xzLCBhZXMobG9nX2h5cG9ueW1zLCBudW1fcGVlcnMsIGNvbG9yPXR5cGUsIGxhYmVsPWFzLmNoYXJhY3RlcihXb3JkKSkpKw0KICBnZW9tX3BvaW50KCkrDQogIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iKSsNCiAgIyBnZW9tX2xhYmVsKCkrDQogICNzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDkwMCw1MCkpDQogIHRoZW1lX2NsYXNzaWMoKQ0KYGBgDQoNCiMjIyMgSHlwZXJueW1zICYgUGVlcnMNCmBgYHtyfQ0KZ2dwbG90KGFuYWx5c2lzX3NlZWRzX2NvbnRyb2xzLCBhZXMobnVtX2h5cGVybnltcywgbnVtX3BlZXJzLCBsYWJlbD1hcy5jaGFyYWN0ZXIoV29yZCksIGNvbG9yPXR5cGUpKSsNCiAgZ2VvbV9wb2ludCgpKw0KICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIikrDQogICNnZW9tX2xhYmVsKCkNCiAgdGhlbWVfY2xhc3NpYygpDQoNCiNXaGF0IGFyZSB0aG9zZSBsb3ctaHlwZXJueW0sIGhpZ2hseSBkZW5zZSB3b3Jkcz8gKHRoZXkgYXJlIGFsbCB2ZXJicyAtIHRoaXMgbWFrZXMgc2Vuc2UpDQojIGxvd0h5cGVyX2hpZ2hQZWVyIDwtIGZpbHRlcihzZWVkX2FuZF9jb250cm9sc19mdWxsLCAobnVtX3BlZXJzID4gMTAwKSAmIChudW1faHlwZXJueW1zIDwgMykpICU+JSANCiMgICBzZWxlY3QoV29yZCwgdHlwZSwgcG9zLCBhb2EsIG51bV9wZWVycywgbnVtX2h5cG9ueW1zLCBudW1faHlwZXJueW1zLCBhZHVsdF9sb2dfZnJlcSkNCiMgRFQ6OmRhdGF0YWJsZShsb3dIeXBlcl9oaWdoUGVlcikNCg0KYGBgDQoNCmBgYHtyfQ0KI3NjYWxlIGh5cG9ueW1zIGFuZCBoeXBlcm55bXMgYnkgcGFydCBvZiBzcGVlY2gNCnNlZWRfYW5kX2NvbnRyb2xzX3BvcyA8LSBhbmFseXNpc19zZWVkc19jb250cm9scyAlPiUNCiAgZ3JvdXBfYnkocG9zKSAlPiUgDQogIG11dGF0ZShoeXBlcl96X3BvcyA9IHNjYWxlKG51bV9oeXBlcm55bXMpLCBoeXBvX3pfcG9zID0gc2NhbGUobnVtX2h5cG9ueW1zKSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBmaWx0ZXIocG9zICVpbiUgYygnbicsJ3YnKSkNCmBgYA0KDQojIyMgSG93IGFyZSBoeXBvbnltcy1oeXBlcm55bXMgY29ycmVsYXRpb24gd2hlbiBjb250cm9sbGluZyBmb3IgcG9zPyB7LnRhYnNldH0NCiMjIyMgUGFydCBvZiBzcGVlY2ggKHBvaW50cykNCmBgYHtyfQ0KZ2dwbG90KHNlZWRfYW5kX2NvbnRyb2xzX3BvcywgYWVzKGh5cGVyX3pfcG9zLCAgaHlwb196X3BvcywgY29sb3I9cG9zLCBsYWJlbD1hcy5jaGFyYWN0ZXIoV29yZCkpKSsNCiAgZ2VvbV9wb2ludCgpKw0KICBnZW9tX3Ntb290aChtZXRob2Q9bG0pKw0KICB0aGVtZV9jbGFzc2ljKCkNCg0KYGBgDQojIyMjIFBhcnQgb2Ygc3BlZWNoIChsYWJlbHMpDQpgYGB7cn0NCmdncGxvdChzZWVkX2FuZF9jb250cm9sc19wb3MsIGFlcyhoeXBlcl96X3BvcywgIGh5cG9fel9wb3MsIGNvbG9yPXBvcywgbGFiZWw9YXMuY2hhcmFjdGVyKFdvcmQpKSkrDQogIGdlb21fcG9pbnQoKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtKSsNCiAgZ2VvbV9sYWJlbCgpKw0KICB0aGVtZV9jbGFzc2ljKCkNCg0KYGBgDQojIyMjIENvcnJlbGF0aW9uIGxvb2tzIGdvb2QNCmBgYHtyfQ0KY29yLnRlc3Qoc2VlZF9hbmRfY29udHJvbHNfcG9zJGh5cGVyX3pfcG9zLCBzZWVkX2FuZF9jb250cm9sc19wb3MkaHlwb196X3BvcykNCmBgYA0KDQojIyMjIElzIGl0IHJlbGF0ZWQgdG8gbmVpZ2hib3Job29kIGRlbnNpdHkNCmBgYHtyfQ0Kc3VtbWFyeShsbShudW1faHlwZXJueW1zIH4gbnVtX3BlZXJzICsgbG9nX2h5cG9ueW1zLCBhbmFseXNpc19zZWVkc19jb250cm9scykpDQoNCmBgYA0KIyMjIENvbXBhcmUgY2hpbGRlcyBhZHVsdCBhbmQgc3VidGxleCBmcmVxdWVuY2llcyAoKnIqID0gLjc2KSB7LnRhYnNldH0NCiMjIyMgUG9pbnRzDQpgYGB7cn0NCmdncGxvdChhbmFseXNpc19zZWVkc19jb250cm9scywgYWVzKGFkdWx0X2xvZ19mcmVxLCBsb2dGcmVxX3N1YnRsZXgsIGNvbG9yPXR5cGUpKSsNCiAgZ2VvbV9wb2ludCgpKw0KICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIikrDQogIHRoZW1lX2NsYXNzaWMoKQ0KYGBgDQojIyMjIFdvcmRzDQpgYGB7cn0NCmdncGxvdChhbmFseXNpc19zZWVkc19jb250cm9scywgYWVzKGFkdWx0X2xvZ19mcmVxLCBsb2dGcmVxX3N1YnRsZXgsIGNvbG9yPXR5cGUsIGxhYmVsPWFzLmNoYXJhY3RlcihXb3JkKSkpKw0KICBnZW9tX3BvaW50KCkrDQogIGdlb21fbGFiZWwoKSsNCiAgdGhlbWVfY2xhc3NpYygpDQpgYGANCg0KIyMjIENvbXBhcmUgY2hpbGQtcHJvZHVjZWQgYW5kIGFkdWx0LXByb2R1Y2VkIGZyZXF1ZW5jZXMgKGNoaWxkZXMpIHsudGFic2V0fQ0KIyMjIyBQb2ludHMNCmBgYHtyfQ0KZ2dwbG90KGFuYWx5c2lzX3NlZWRzX2NvbnRyb2xzLCBhZXMoYWR1bHRfbG9nX2ZyZXEsIGtpZF9sb2dfZnJlcSwgY29sb3I9dHlwZSkpKw0KICBnZW9tX3BvaW50KCkrDQogIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iKSsNCiAgdGhlbWVfY2xhc3NpYygpDQpgYGANCiMjIyMgV29yZHMNCmBgYHtyfQ0KZ2dwbG90KGFuYWx5c2lzX3NlZWRzX2NvbnRyb2xzLCBhZXMoYWR1bHRfbG9nX2ZyZXEsIGtpZF9sb2dfZnJlcSwgY29sb3I9dHlwZSwgbGFiZWw9YXMuY2hhcmFjdGVyKFdvcmQpKSkrDQogIGdlb21fcG9pbnQoKSsNCiAgZ2VvbV9sYWJlbCgpKw0KICB0aGVtZV9jbGFzc2ljKCkNCmBgYA0KPCEtLSAjIyMjIEFkdWx0cyBzYXksIGtpZHMgc2F5IGluZnJlcXVlbnRseSAtLT4NCjwhLS0gYGBge3J9IC0tPg0KPCEtLSBhZHVsdFNheSA8LSBmaWx0ZXIoc2VlZF9hbmRfY29udHJvbHNfZnVsbCwga2lkX2xvZ19mcmVxPDEpICU+JSAgLS0+DQo8IS0tICAgc2VsZWN0KFdvcmQsIHR5cGUsIHBvcywgYW9hLCBudW1fcGVlcnMsIG51bV9oeXBvbnltcywgbnVtX2h5cGVybnltcywgYWR1bHRfbG9nX2ZyZXEsIGtpZF9sb2dfZnJlcSkgLS0+DQo8IS0tIERUOjpkYXRhdGFibGUoYWR1bHRTYXkpIC0tPg0KDQo8IS0tIGBgYCAtLT4NCiMjIyMgRGlmZmVyZW5jZSBpbiBBZHVsdC1DaGlsZCBwcm9kdWN0aW9uDQpgYGB7cn0NCnByb2R1Y2VEaWZmIDwtIGFuYWx5c2lzX3NlZWRzX2NvbnRyb2xzICU+JSANCiAgbXV0YXRlKGFkdWx0X2xvZ19mcmVxX3o9c2NhbGUoYWR1bHRfbG9nX2ZyZXEpLCBraWRfbG9nX2ZyZXFfej1zY2FsZShraWRfbG9nX2ZyZXEpKSAlPiUgDQogIHNlbGVjdChXb3JkLCB0eXBlLCBwb3MsIGFvYSwgbnVtX3BlZXJzLCBudW1faHlwb255bXMsIG51bV9oeXBlcm55bXMsIGFkdWx0X2xvZ19mcmVxX3osIGtpZF9sb2dfZnJlcV96KSAlPiUgDQogIG11dGF0ZShwcm9kdWN0aW9uRGlmZl96ID0gYWR1bHRfbG9nX2ZyZXFfeiAtIGtpZF9sb2dfZnJlcV96KSAlPiUgDQogIGRpc3RpbmN0KCkNCkRUOjpkYXRhdGFibGUocHJvZHVjZURpZmYpDQoNCmBgYA0KDQojIyMgQ2hpbGRlcyBmcmVxdWVuY3kgdnMuIEFPQSB7LnRhYnNldH0NCiMjIyMgUG9pbnRzDQpgYGB7cn0NCmdncGxvdChhbmFseXNpc19zZWVkc19jb250cm9scywgYWVzKGFkdWx0X2xvZ19mcmVxLCBhb2EsIGNvbG9yPXR5cGUpKSsNCiAgZ2VvbV9wb2ludCgpKw0KICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIikrDQogIHRoZW1lX2NsYXNzaWMoKQ0KYGBgDQojIyMjIFdvcmRzDQpgYGB7cn0NCmdncGxvdChhbmFseXNpc19zZWVkc19jb250cm9scywgYWVzKGFkdWx0X2xvZ19mcmVxLCBhb2EsIGNvbG9yPXR5cGUsbGFiZWw9YXMuY2hhcmFjdGVyKFdvcmQpKSkrDQogIGdlb21fcG9pbnQoKSsNCiAgZ2VvbV9sYWJlbCgpKw0KICB0aGVtZV9jbGFzc2ljKCkNCmBgYA0KIyMjIENoaWxkZXMgZnJlcXVlbmN5IHZzLiBoeXBlcm55bXMgey50YWJzZXR9DQojIyMjIEFkdWx0cw0KYGBge3J9DQpnZ3Bsb3QoYW5hbHlzaXNfc2VlZHNfY29udHJvbHMsIGFlcyhhZHVsdF9sb2dfZnJlcSwgbnVtX2h5cGVybnltcywgY29sb3I9dHlwZSkpKw0KICBnZW9tX3BvaW50KCkrDQogIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iKSsNCiAgdGhlbWVfY2xhc3NpYygpDQpgYGANCiMjIyMgS2lkcw0KYGBge3J9DQpnZ3Bsb3QoYW5hbHlzaXNfc2VlZHNfY29udHJvbHMsIGFlcyhraWRfbG9nX2ZyZXEsIG51bV9oeXBlcm55bXMsIGNvbG9yPXR5cGUpKSsNCiAgZ2VvbV9wb2ludCgpKw0KICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIikrDQogIHRoZW1lX2NsYXNzaWMoKQ0KYGBgDQoNCiMjIyBXaGF0J3MgdGhlIHJlbGF0aW9uIGJldHdlZW4gQU9BIGFuZCBoeXBlcm55bXMsIGNvbnRyb2xsaW5nIGZvciBmcmVxdWVuY3k/IHsudGFic2V0fQ0KIyMjIyBBZHVsdC1wcm9kdWNlZCBmcmVxdWVuY3kNCmBgYHtyfQ0Kc3VtbWFyeShsbShhb2EgfiBudW1faHlwZXJueW1zICsgYWR1bHRfbG9nX2ZyZXEsIGRhdGE9YW5hbHlzaXNfc2VlZHNfY29udHJvbHMpKQ0KDQpgYGANCiMjIyMgQ2hpbGQtcHJvZHVjZWQgZnJlcXVlbmN5DQpgYGB7cn0NCnN1bW1hcnkobG0oYW9hIH4gbnVtX2h5cGVybnltcyArIGtpZF9sb2dfZnJlcSwgZGF0YT1hbmFseXNpc19zZWVkc19jb250cm9scykpDQoNCmBgYA0KDQoNCjwhLS0gIyMjIENoaWxkZXMgZnJlcXVlbmN5IHZzLiBjb25jcmV0ZW5lc3MgKCpyKiA9IC0uMiwgbnM7IHNlZWQgd29yZHMgb25seSkgey50YWJzZXR9IC0tPg0KPCEtLSAjIyMjIFBvaW50cyAtLT4NCjwhLS0gYGBge3J9IC0tPg0KPCEtLSBnZ3Bsb3QoY2FuZGlkYXRlX3dvcmRzX2FsbF9mcmVxcywgYWVzKGFkdWx0X2xvZ19mcmVxLCBDb25jLk0pKSsgLS0+DQo8IS0tICAgZ2VvbV9wb2ludCgpKyAtLT4NCjwhLS0gICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIikrIC0tPg0KPCEtLSAgIHRoZW1lX2NsYXNzaWMoKSAtLT4NCjwhLS0gYGBgIC0tPg0KPCEtLSAjIyMjIFdvcmRzIC0tPg0KPCEtLSBgYGB7cn0gLS0+DQo8IS0tIGdncGxvdChjYW5kaWRhdGVfd29yZHNfYWxsX2ZyZXFzLCBhZXMoYWR1bHRfbG9nX2ZyZXEsIENvbmMuTSwgbGFiZWw9YXMuY2hhcmFjdGVyKFdvcmQpKSkrIC0tPg0KPCEtLSAgIGdlb21fcG9pbnQoKSsgLS0+DQo8IS0tICAgZ2VvbV9sYWJlbCgpKyAtLT4NCjwhLS0gICB0aGVtZV9jbGFzc2ljKCkgLS0+DQo8IS0tIGBgYCAtLT4NCg0KPCEtLSAjIyMgQ2hpbGRlcyBmcmVxdWVuY3kgdnMuIEFPQSBmb3IgbG93ZXItdGhhbi1tZWFuIGNvbmNyZXRlbmVzcyB7LnRhYnNldH0gLS0+DQo8IS0tICMjIyMgUG9pbnRzIC0tPg0KPCEtLSBgYGB7cn0gLS0+DQo8IS0tIGdncGxvdChmaWx0ZXIoY2FuZGlkYXRlX3dvcmRzX2FsbF9mcmVxcywgQ29uYy5NPDMuOTApLCBhZXMoYWR1bHRfbG9nX2ZyZXEsIGFvYSkpKyAtLT4NCjwhLS0gICBnZW9tX3BvaW50KCkrIC0tPg0KPCEtLSAgIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iKSsgLS0+DQo8IS0tICAgdGhlbWVfY2xhc3NpYygpIC0tPg0KPCEtLSBgYGAgLS0+DQo8IS0tICMjIyMgV29yZHMgLS0+DQo8IS0tIGBgYHtyfSAtLT4NCjwhLS0gZ2dwbG90KGZpbHRlcihjYW5kaWRhdGVfd29yZHNfYWxsX2ZyZXFzLCBDb25jLk08My45MCksIGFlcyhhZHVsdF9sb2dfZnJlcSwgYW9hLCBsYWJlbD1hcy5jaGFyYWN0ZXIoV29yZCkpKSsgLS0+DQo8IS0tICAgZ2VvbV9wb2ludCgpKyAtLT4NCjwhLS0gICBnZW9tX2xhYmVsKCkrIC0tPg0KPCEtLSAgIHRoZW1lX2NsYXNzaWMoKSAtLT4NCg0KPCEtLSBgYGAgLS0+DQoNCjwhLS0gIyMjIFdoYXQgYXJlIHRoZSBsb3ctY29uY3JldGVuZXNzIChsb3dlciB0aGFuIG1lYW4pLCBoaWdoLWZyZXF1ZW5jeSAoaGlnaGVyIHRoYW4gbWVhbiksIGxhdGUtYW9hIChvbGRlciB0aGFuIDUpIHdvcmRzPyAtLT4NCjwhLS0gYGBge3J9IC0tPg0KPCEtLSBoRnJlcV9oQU9BX2xDb25jIDwtIGZpbHRlcihjYW5kaWRhdGVfd29yZHNfYWxsX2ZyZXFzLCAoQ29uYy5NIDwgMy45MCkgJiAoYW9hPjUpICYgKGFkdWx0X2xvZ19mcmVxID4gNS40MSkpICU+JSAgLS0+DQo8IS0tICAgc2VsZWN0KFdvcmQsIHBvcywgYW9hLCBudW1faHlwZXJueW1zLCBudW1faHlwb255bXMsIG51bV9wZWVycywgQ29uYy5NLCBhZHVsdF9sb2dfZnJlcSwgbG9nRnJlcV9zdWJ0bGV4KSAtLT4NCg0KPCEtLSBEVDo6ZGF0YXRhYmxlKGhGcmVxX2hBT0FfbENvbmMpIC0tPg0KPCEtLSBgYGAgLS0+DQoNCjwhLS0gIyMjIFJhbmdlIG9mIGNvbnRyb2wgd29yZCBmcmVxdWVuY3kgKHBlciBzZWVkIHdvcmQpIC0tPg0KPCEtLSBgYGB7cn0gLS0+DQoNCjwhLS0gc2VlZFdvcmRfaGlzdHMgPC0gZnVuY3Rpb24oZGYsIG5hLnJtPVRSVUUsIC4uLil7IC0tPg0KPCEtLSAgIHNlZWR3b3JkX2xpc3QgPC0gdW5pcXVlKGRmJFNlZWRXb3JkKSAtLT4NCjwhLS0gICBmb3IgKGkgaW4gc2VxX2Fsb25nKHNlZWR3b3JkX2xpc3QpKSB7IC0tPg0KPCEtLSAgICAgcGxvdCA8LSAtLT4NCjwhLS0gICAgICAgZ2dwbG90KHN1YnNldChkZiwgZGYkU2VlZFdvcmQ9PXNlZWR3b3JkX2xpc3RbaV0pLCAtLT4NCjwhLS0gICAgICAgICAgICAgIGFlcyhjb250cm9sX2FkdWx0X2xvZ19mcmVxKSkrIC0tPg0KPCEtLSAgICAgICBnZW9tX2Jhcih3aWR0aD0uMikrIC0tPg0KPCEtLSAgICAgICBnZ3RpdGxlKHBhc3RlKCJzZWVkIHdvcmQ6ICIsc2VlZHdvcmRfbGlzdFtpXSkpIC0tPg0KPCEtLSAgICAgcHJpbnQocGxvdCkgLS0+DQo8IS0tICAgfSAtLT4NCjwhLS0gfSAtLT4NCg0KPCEtLSBoaXN0X2RmIDwtIGZpbHRlcihjaG9vc2VfY29udHJvbF93b3Jkc19zdWJ0bGV4LCAoU2VlZFdvcmQgJWluJSB3b3Jkc193aXRoX21hbnlfY29udHJvbHMkU2VlZFdvcmQpICYgY29udHJvbF9hZHVsdF9sb2dfZnJlcT4wKSAtLT4NCg0KPCEtLSBzZWVkV29yZF9oaXN0cyhoaXN0X2RmKSAtLT4NCg0KPCEtLSBgYGAgLS0+DQo=