Required packages

# This is the R chunk for the required packages
library(dplyr)
library(tidyr)
library(readxl)
library(readr)
library(foreign)
library(knitr)
library(rvest)
library(deductive)
library(validate)
library(outliers)
library(MVN)
library(forecast)

Executive Summary

In this project I have merged three data sets (Country Information, Justification Among Adolescence and World Happiness) to form one cohesive data set providing data by country on attitudes towards violence against women, happiness ranking and socioeconomic status. This allows for future analysis between variables to be easily computed.

Data was downloaded from open source websites and imported using base r and readxl functions. Factor and numeric variables conversions were completed and column names set as necessary. Square bracket sub-setting was used to select only relevant variables. The Country Information and Justification Among Adolescence data sets were considered untidy and inappropriate values were removed from columns to ensure each column represented one variable.

Three new variables were created using the mutate function to give the average and difference of male and female respondents as well as the percentage difference.

To ensure data is suitable for future analysis, it is scanned for missing values, to ensure Male (%) or Female (%) and both Happiness Ranking and Income Group are present. Values that are missing in either gender are imputed with the respondent available for that country multiplied by percentage difference. A small number of rows still with missing values for income group or happiness ranking are then removed.

Outliers are scanned visually using boxplots and numerically using z.score normalisation. No outliers for univariate variables were identified. Bivariate outliers for Male (%) and Female (%) comparison are identified using Mahalabonis distance and remain for further investigation during analysis. In order to obtain a normal distribution , the Adolescent Average variable undergoes a square root transformation.

Finally, the resulting, tidy data frame is saved as a csv file to allow analysis to be readily completed.

Data

Three data sets containing information about the happiness levels of countries, attitudes towards violence towards women and socioeconomic and geographic details have been obtained. These data sets are preprocessed and merged to provide a complete data set for a range of analytical questions.

Happiness Levels Data Set

Data regarding the happiness levels of countries has been obtained from Kaggle. The data set was downloaded as a csv file from the following URL https://www.kaggle.com/unsdsn/world-happiness.

The data provided is obtained from responses to the Gallup World Poll.Countries are ranked compared to a fictional country ‘Dystopia’ which is given a score of zero for all variables. The original data set contains 9 variables. The following 5 variables have been identified as relevant.

Country Name: Name of the Country. Character Variable.

Overall Rank: Ranking of the country’s happiness indicator, with 1 being the country with the highest overall happiness score, based on a combination of the other variables. Numeric variable.

Score: Happiness score. Value between 0 and 10. 0 indicates the level of Dystopia, with no reported happiness. 10 indicates a perfectly happy respondent. Continuous numeric value.

GDP: GDP per capita. Refers to extent to which GDP refers to the happiness score. Value between 0 and 1.69.

Freedom: Freedom to make life choices. Refers to the extent of which freedom contributed to the happiness score.

Country Information Data Set

Information regarding the geographic region and socioeconomic status of the countries has been obtained from the World Bank data set “Women who believe a husband is justified in beating his wife (any of five reasons) (%)”. The data set was downloaded as a csv file from the following URL https://data.worldbank.org/indicator/SG.VAW.REAS.ZS?end=2018&name_desc=false&start=2018&view=bar This data set contains the supplementary information about the countries. Data, which were obtained in a separate but corresponding data set, here titles Adolescents Who Agree. The Country Information Data Set contains the following relevant variables.

Country Code A character variable identifying the Country

Region Identifies the geographical region of the country. A categorical, factor variable.

Country Name Identifies name of the country. A character variable.

Income Group Groups the countries into ordered factors based on average income. Factor levels are Low Income < Lower Middle Income < Middle Income < Upper Middle Income < High Income.

Adolescents Who Agree (AWA)

Information regarding ‘the proportion of adolescents who believe a husband is justified in beating his wife for any of the five given reasons’ has been obtained from the Unicef website at the following URL https://data.unicef.org/topic/gender/harmful-practices-and-intimate-partner-violence/.

The data is collected from a sample of 15 to 19 year old male and female adolescents between 2012-2019. The five reasons are given as arguing with their husband, burning the food, neglecting the children, refusing sexual relations and going out without telling him. The AWA data sets contains the following variables.

Country Name A character variable identifying the country.

Region Name A categorical variable identifying the geographic region of the country. An un-ordered factor.

Male Percentage of male respondents that believe wife beating is justified. A continuous numeric variable with a value between 0 and 100.

Female Percentage of female respondents that believe wife beating is justified. A continuous numeric variable with a value between 0 and 100.

The above data sets will undergo preliminary manipulation and tidying before being merged. In the following chunk data has been imported using baser and readxl functions. Data has been subsetted to include only relevant variable with the square bracket [] subsetting function. Column names are adjusted as necessary by reassigning with colnames().

# This is the R chunk for the Data Section

# Happiness Levels 
happy_2018<- read.csv("2018.csv")
colnames(happy_2018) = c("Overall Rank", "Country Name", "Score", "GDP", "Social Support", "Healthy LE", "Freedom", "Generosity", "Perceptions")
happy_2018<- happy_2018[ , c("Overall Rank", "Country Name", "Score", "GDP", "Freedom")]
head(happy_2018)

# Country Information
country_info<- read.csv("Justified_country_info.csv")
colnames(country_info)<- c("Country Code", "Region", "Income Group", "Notes", "Country.Region.To.Split")
country_info<- country_info[ , c("Country Code", "Region", "Income Group", "Country.Region.To.Split")] # Column containing notes on country that are not related to a variable has been omitted
head(country_info)

# Adolescents Who Agree
women_stats<- read_excel("Justification-of-wife-beating-among-adolescents-database_June-2020.xls", skip = 7, n_max = 203) #skip and n_max arguments are used to ensure only relevant rows with observations relating to countries are imported.
New names:
* `` -> ...3
* `` -> ...5
colnames(women_stats)<- c("Country Name", "Male", "3", "Female", "5", "Source")
women_stats<- women_stats[ , c("Country Name", "Male", "Female")] # Variable containing source information has been omitted. 
head(women_stats)

Understand

The World Happiness Data Set

The variable types in this data set are considered appropriate and do not need converting. Class type is data frame.

Overall Rank: Integer

Country Name: Character

Score: Numeric (Double)

GDP: Numeric (Double)

Freedom: Numeric (Double)

Country Information Data Set

The region and income group variables are converted from character variables into factored variables using the factor() function. The ordered = TRUE argument is applied to the Income Group variable to ensure the factors are in the appropriate order. Class type is data frame.

Country Code: Character

Region: Factor with 7 Levels: “Latin America & Caribbean”, “South Asia”, “Sub-Saharan Africa”, “Europe & Central Asia”, “Middle East & North Africa”, “East Asia & Pacific”
[7] “North America”

Income Group: Ordered Factor with 4 Levels: “Low income”, “Lower middle income”, “Upper middle income”, “High income”

Country.Region.To.Split: Character

Adolescents Who Agree Data Set

The Male and Female variables were automatically read as character due to presence of NA values. These are converted from character to numeric variables as they represent a percentage. This is completed using the as.numeric() function. Class type is data frame.

Male: Numeric (Double)

Female: Numeric (Double)

Country.Region.To.Split: Character

# This is the R chunk for the Understand Section

# Check variable type: Happiness Levels 
str(happy_2018)
'data.frame':   156 obs. of  5 variables:
 $ Overall Rank: int  1 2 3 4 5 6 7 8 9 10 ...
 $ Country Name: chr  "Finland" "Norway" "Denmark" "Iceland" ...
 $ Score       : num  7.63 7.59 7.55 7.5 7.49 ...
 $ GDP         : num  1.3 1.46 1.35 1.34 1.42 ...
 $ Freedom     : num  0.681 0.686 0.683 0.677 0.66 0.638 0.653 0.669 0.659 0.647 ...
typeof(happy_2018$Score)
[1] "double"
typeof(happy_2018$GDP)
[1] "double"
typeof(happy_2018$Freedom)
[1] "double"
# Check variable type: Country Info
str(country_info)
'data.frame':   263 obs. of  4 variables:
 $ Country Code           : chr  "ABW" "AFG" "AGO" "ALB" ...
 $ Region                 : chr  "Latin America & Caribbean" "South Asia" "Sub-Saharan Africa" "Europe & Central Asia" ...
 $ Income Group           : chr  "High income" "Low income" "Lower middle income" "Upper middle income" ...
 $ Country.Region.To.Split: chr  "Aruba" "Afghanistan" "Angola" "Albania" ...
# Convert to factor where necessary
country_info$Region<- factor(country_info$Region, levels = c("Latin America & Caribbean", "South Asia", "Sub-Saharan Africa", "Europe & Central Asia", "Middle East & North Africa", "East Asia & Pacific", "North America"), labels = c("Latin America & Caribbean", "South Asia", "Sub-Saharan Africa", "Europe & Central Asia", "Middle East & North Africa", "East Asia & Pacific", "North America"), ordered = FALSE)

country_info$`Income Group`<- factor(country_info$`Income Group`, levels = c("Low income", "Lower middle income", "Upper middle income", "High"), labels = c("Low income", "Lower middle income", "Upper middle income", "High income"), ordered = TRUE)

# Check levels and structure
str(country_info$`Income Group`)
 Ord.factor w/ 4 levels "Low income"<"Lower middle income"<..: NA 1 2 3 NA NA NA 3 3 3 ...
levels(country_info$`Income Group`)
[1] "Low income"          "Lower middle income" "Upper middle income" "High income"        
str(country_info$Region)
 Factor w/ 7 levels "Latin America & Caribbean",..: 1 2 3 4 4 NA 5 1 4 6 ...
levels(country_info$Region)
[1] "Latin America & Caribbean"  "South Asia"                 "Sub-Saharan Africa"        
[4] "Europe & Central Asia"      "Middle East & North Africa" "East Asia & Pacific"       
[7] "North America"             
# Check variable type: Adolescents Who Agree
str(women_stats)
tibble [203 × 3] (S3: tbl_df/tbl/data.frame)
 $ Country Name: chr [1:203] NA "Afghanistan" "Albania" "Algeria" ...
 $ Male        : chr [1:203] NA "70.599999999999994" "10.9" "−" ...
 $ Female      : chr [1:203] NA "78.299999999999997" "4.7000000000000002" "55" ...
# Convert percentage variables from character to numeric 
women_stats$Male<- as.numeric(women_stats$Male)
NAs introduced by coercion
women_stats$Female<- as.numeric(women_stats$Female)
NAs introduced by coercion
typeof(women_stats$Male)
[1] "double"
typeof(women_stats$Female)
[1] "double"

Tidy & Manipulate Data I

Of the above data sets, the World Happiness data set obtained from Kaggle is considered to be tidy. Each variable must has its own column, each observation must has its own row and each value has its own cell.

The Country Information data set is not considered to be tidy. This is because in the original data set Country and Region variables are found within the one column, titled ‘Table Name’. Additionally, there are rows which do not contain relevant observations.

Upon inspection of the Country Information data set, it can be seen that the rows that have missing values in the ‘Income Group’ column are consistent with the rows that have inappropriate values for the Country.Region.To.Split variable column. As we only need to keep data for country names from this column, we will omit those rows with missing values to tidy the data set. This is completed using the complete.cases() function which is appropriate for the sub-setted columns. This action will complete both of the steps required to tidy this data set. The column will be appropriately renamed to “Country Name” as it no longer contains unwanted information regarding the Region variable.

The Adolescents Who Agree dataset is not considered tidy. Two of the variables in columns 3 and 5 contains rows with multiple values in the one cell. However, the information in these columns is only given for a limited number of observations and pertains to the year or method of collection. It is not considered relevant to this data set, therefore these variables have been omitted (See Data section)

The data sets will be merged into one data frame.

# This is the R chunk for the Tidy & Manipulate Data I 

# Country Information Data Set - filter out names of Regions by sub-setting for only complete cases. 
country_info<- country_info[complete.cases(country_info), ] #This data frame should now contain no missing values when scanned
colnames(country_info)<- c("Country Code", "Region", "Income Group", "Country Name")
head(country_info)

# Merge Data sets
justified_full<- women_stats %>% full_join(country_info) %>% full_join(happy_2018)
Joining, by = "Country Name"
Joining, by = "Country Name"
head(justified_full)
# Subsetted to remove unnecessary variables
justified_full<- justified_full[ ,c(1:3,5:7)]

# Columns renamed for added clarity
colnames(justified_full)<- c("Country Name", "Male(%)", "Female(%)", "Region", "Income Group", "Happiness Ranking")

Tidy & Manipulate Data II

Three new variables are created using the mutate() function and simple maths functions. The variables are first converted back to type numeric as necessary.

The mean of the Percentage Difference variable will be used for imputing missing values.

# This is the R chunk for the Tidy & Manipulate Data II 

# The structure of variables is checked and converted to ensure they are in numeric form 
str(justified_full)
tibble [240 × 6] (S3: tbl_df/tbl/data.frame)
 $ Country Name     : chr [1:240] NA "Afghanistan" "Albania" "Algeria" ...
 $ Male(%)          : num [1:240] NA 70.6 10.9 NA NA 24 NA NA NA 24.7 ...
 $ Female(%)        : num [1:240] NA 78.3 4.7 55 NA 24.7 NA NA 2.3 8.7 ...
 $ Region           : Factor w/ 7 levels "Latin America & Caribbean",..: NA 2 4 5 NA 3 NA NA 1 4 ...
 $ Income Group     : Ord.factor w/ 4 levels "Low income"<"Lower middle income"<..: NA 1 3 2 NA 2 NA NA 3 3 ...
 $ Happiness Ranking: int [1:240] NA 145 112 84 NA 142 NA NA 29 129 ...
justified_full$`Male(%)`<- as.numeric(justified_full$`Male(%)`)
justified_full$`Female(%)`<- as.numeric(justified_full$`Female(%)`)

# Create new variables using mutate()
justified_full<- justified_full %>% mutate('Adolescent Average'  = (`Male(%)` + `Female(%)`)/2,
                                           'Male-Female Difference' = `Male(%)` - `Female(%)`)
justified_full<- justified_full %>% mutate('Percentage Difference' = `Male-Female Difference`/`Adolescent Average`)

# Mean of Percentge Difference found
mean(justified_full$`Percentage Difference`, na.rm = TRUE) %>% round(3)
[1] -0.027
head(justified_full)
NA

Scan I

In order for this information to be useful analytically, only rows for countries that have values for either Male or Female respondents, as well as both Income Group and Happiness Ranking will be included.

The initial AWA data set containing the Male (%) and Female (%) variables, is missing data for many rows. This is because data was only collected for a limited number of countries as compared to the Happiness Ranking and Country Information sets. Therefore, values that are missing for either but not both of these variable will be removed. This is completed by identifying which values are missing for both Female (%) and Male (%) using is.na() nested within the which() function, and saving this is a vector.

Missing values from either the Male or Female respondents columns will be replaced with the value of the opposing gender multiplied by the percentage mean of the Male-Female difference. For simplicity, the mean value has been included in the rules as the corresponding numeric value for 2.7% increase or decrease.

Following this the rows that have missing values in the Happiness Ranking or Income Group columns will be omitted.

# This is the R chunk for the Scan I
#The following code identifies rows which are missing values for both male and female respondents and therefore need to be omitted.
missing_vals<- which(is.na(justified_full$`Female(%)` | justified_full$`Male(%)`))

# Save data frame without missing values
justified_narm<- justified_full[-missing_vals, ] # Sub-setting to remove missing values
head(justified_narm)

# Set rules for imputation
Rules<- validator(`Male(%)` == `Female(%)`*0.973,
                  `Female(%)` == `Male(%)`*1.027)
# Imputation
justified_imputed<- impute_lr(justified_narm, Rules)
head(justified_imputed)

#Remove NAs from Happiness Ranking and Income Group

#Find values that are not NA in Happiness Ranking and Subset for these
happiness_narm<- which(!is.na(justified_imputed$`Happiness Ranking`))# Save vector excluding missing values
justified_HR_narm<- justified_imputed[happiness_narm,]

#Find values that are not NA in Income Group and Subset for these 
missing_income<- which(!is.na(justified_HR_narm$`Income Group`))
justified_all_narm<- justified_HR_narm[missing_income,]

# Print out
head(justified_all_narm)

Scan II

All numeric data will be scanned for outliers. Univariate analysis is conducted of Happiness, Male (%) and Female (%) variables. This is done visually using a box plot. Outliers are also analyzed by z-score normalization using the outliers() package. As Happiness is a ranking variable there is no outliers, as expected. Univariate analysis of the Male(%) and Female (%) variables there are no observations that are considered outliers.

Bivariate analysis is completed using the Mahalanobis distance through the MVN() package. In the bivariate analysis of Male (%) and Female (%) values there is 23 outliers identified, however many of these lie close to the quantile line. Due to expected cultural differences between females and males within a population, these outliers are considered valuable anomalies and would be further investigated in the analysis stage.

Adolescent Average and Male-Female Difference values do not need to be scanned for outliers as they are combinations of original values.

# This is the R chunk for the Scan II

# Happiness Variable Univariate Analysis
justified_all_narm$`Happiness Ranking` %>% boxplot(main = "Happiness Ranking Distribution", ylab = "Happiness Ranking", col = "pink") # Create Boxplot

z.scores.happiness<- justified_all_narm$`Happiness Ranking` %>% scores(type = "z") # z.score normalization
z.scores.happiness %>% summary()
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
-2.4626 -0.6441  0.1824  0.0000  0.8161  1.4773 
#z.scores that are greater than 3 or less than -3 are considered outliers
which( abs(z.scores.happiness) >3 )
integer(0)
# Male(%) Variable
justified_all_narm$`Male(%)` %>% boxplot(main = "Male (%) Distribution", ylab = "Percentage Who Agree", col = "red")

z.scores.male<- justified_all_narm$`Male(%)` %>% scores(type = "z")
z.scores.male %>% summary()
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
-1.3493 -0.7915 -0.2337  0.0000  0.7249  2.5721 
#z.scores that are greater than 3 or less than -3 are considered outliers
which( abs(z.scores.male) >3 )
integer(0)
# Female(%) Variable
justified_all_narm$`Female(%)` %>% boxplot(main = "Female (%) Distribution", ylab = "Percentage Who Agree", col = "Orange")

z.scores.female<- justified_all_narm$`Female(%)` %>% scores(type = "z")
z.scores.female %>% summary()
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
-1.3406 -0.9729 -0.1151  0.0000  0.8244  2.0176 
#z.scores that are greater than 3 or less than -3 are considered outliers
which( abs(z.scores.female) >3 )
integer(0)
# Male (%) and Female (%) Bivariate Analysis
# Multivariate outlier detection using Mahalanobis distance with QQ plots
results.mvn<- mvn(data = justified_all_narm[, 2:3], multivariateOutlierMethod = "quan", showOutliers = TRUE)

Transform

The AWA variable, is right-skewed, as observed in the below histogram. To make this more useful for analysis a normal distribution is obtained by applying a square root transformation. The resulting distribution is observed to be close to normal. Prior to this transformation the ‘Adolescent Average’ column was adjusted to include values that had been imputed in the Scan: Missing Values section above.

# This is the R chunk for the Transform Section

# Create new adolescent average column to reflect replaced missing values
justified_withavg<- justified_all_narm[, c(1:6, 8)] %>% mutate('Adolescent Average' = (`Male(%)`+`Female(%)`)/2)

# Visual analysis of histogram for Adolescent Average
hist(justified_withavg$`Adolescent Average`, main = "Histogram of AWA Mean Value", xlab = "Percentage Agreement", col = "light blue")


# Apply a square root transformation to obtain a normal distribution
sqrt_agree<- sqrt(justified_withavg$`Adolescent Average`)

# Visual analysis of histogram for Adolescent Average after transformation
hist(sqrt_agree, main = "Histogram of AWA (Sqrt)", xlab = "Normalised Percentage Agreement", col = "light blue", breaks = 8)

# This Chunk writes the data frame as a .csv file for future use
write.csv(sqrt_agree, "Country_attitudes_information_normalised.csv")

References

“World Happiness Report”, Sustainable Development Solutions Network, 2018, accessed from https://www.kaggle.com/unsdsn/world-happiness

“Women who believe a husband is justified in beating his wife (any of the five reasons) %”, The World Bank Group, 2016, accessed from https://data.worldbank.org/indicator/SG.VAW.REAS.ZS?end=2018&name_desc=false&start=2018&view=bar

“Percentage of girls and boys 15–19 years old who consider a husband to be justified in hitting or beating his wife for at least one of the specified reasons, i.e., if his wife burns the food, argues with him, goes out without telling him, neglects the children or refuses sexual relations”, UNICEF, 2020, accessed from https://data.unicef.org/topic/gender/harmful-practices-and-intimate-partner-violence/



LS0tCnRpdGxlOiAiTUFUSDIzNDkgRGF0YSBXcmFuZ2xpbmciCmF1dGhvcjogIkZlbGljaXR5IERyYXBlciBzMzc0MjU3MCIKc3VidGl0bGU6ICJBc3NpZ25tZW50IDogRGF0YSBQcmVwcm9jZXNzaW5nIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAotLS0KCgojIyBSZXF1aXJlZCBwYWNrYWdlcyAKCgpgYGB7cn0KIyBUaGlzIGlzIHRoZSBSIGNodW5rIGZvciB0aGUgcmVxdWlyZWQgcGFja2FnZXMKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZm9yZWlnbikKbGlicmFyeShrbml0cikKbGlicmFyeShydmVzdCkKbGlicmFyeShkZWR1Y3RpdmUpCmxpYnJhcnkodmFsaWRhdGUpCmxpYnJhcnkob3V0bGllcnMpCmxpYnJhcnkoTVZOKQpsaWJyYXJ5KGZvcmVjYXN0KQpgYGAKCgojIyBFeGVjdXRpdmUgU3VtbWFyeSAKCkluIHRoaXMgcHJvamVjdCBJIGhhdmUgbWVyZ2VkIHRocmVlIGRhdGEgc2V0cyAoQ291bnRyeSBJbmZvcm1hdGlvbiwgSnVzdGlmaWNhdGlvbiBBbW9uZyBBZG9sZXNjZW5jZSBhbmQgV29ybGQgSGFwcGluZXNzKSB0byBmb3JtIG9uZSBjb2hlc2l2ZSBkYXRhIHNldCBwcm92aWRpbmcgZGF0YSBieSBjb3VudHJ5IG9uIGF0dGl0dWRlcyB0b3dhcmRzIHZpb2xlbmNlIGFnYWluc3Qgd29tZW4sIGhhcHBpbmVzcyByYW5raW5nIGFuZCBzb2Npb2Vjb25vbWljIHN0YXR1cy4gVGhpcyBhbGxvd3MgZm9yIGZ1dHVyZSBhbmFseXNpcyBiZXR3ZWVuIHZhcmlhYmxlcyB0byBiZSBlYXNpbHkgY29tcHV0ZWQuCgpEYXRhIHdhcyBkb3dubG9hZGVkIGZyb20gb3BlbiBzb3VyY2Ugd2Vic2l0ZXMgYW5kIGltcG9ydGVkIHVzaW5nIGJhc2UgciBhbmQgcmVhZHhsIGZ1bmN0aW9ucy4gRmFjdG9yIGFuZCBudW1lcmljIHZhcmlhYmxlcyBjb252ZXJzaW9ucyB3ZXJlIGNvbXBsZXRlZCBhbmQgY29sdW1uIG5hbWVzIHNldCBhcyBuZWNlc3NhcnkuIFNxdWFyZSBicmFja2V0IHN1Yi1zZXR0aW5nIHdhcyB1c2VkIHRvIHNlbGVjdCBvbmx5IHJlbGV2YW50IHZhcmlhYmxlcy4gVGhlIENvdW50cnkgSW5mb3JtYXRpb24gYW5kIEp1c3RpZmljYXRpb24gQW1vbmcgQWRvbGVzY2VuY2UgZGF0YSBzZXRzIHdlcmUgY29uc2lkZXJlZCB1bnRpZHkgYW5kIGluYXBwcm9wcmlhdGUgdmFsdWVzIHdlcmUgcmVtb3ZlZCBmcm9tIGNvbHVtbnMgdG8gZW5zdXJlIGVhY2ggY29sdW1uIHJlcHJlc2VudGVkIG9uZSB2YXJpYWJsZS4gCgpUaHJlZSBuZXcgdmFyaWFibGVzIHdlcmUgY3JlYXRlZCB1c2luZyB0aGUgbXV0YXRlIGZ1bmN0aW9uIHRvIGdpdmUgdGhlIGF2ZXJhZ2UgYW5kIGRpZmZlcmVuY2Ugb2YgbWFsZSBhbmQgZmVtYWxlIHJlc3BvbmRlbnRzIGFzIHdlbGwgYXMgdGhlIHBlcmNlbnRhZ2UgZGlmZmVyZW5jZS4gCgpUbyBlbnN1cmUgZGF0YSBpcyBzdWl0YWJsZSBmb3IgZnV0dXJlIGFuYWx5c2lzLCBpdCBpcyBzY2FubmVkIGZvciBtaXNzaW5nIHZhbHVlcywgdG8gZW5zdXJlIE1hbGUgKCUpIG9yIEZlbWFsZSAoJSkgYW5kIGJvdGggSGFwcGluZXNzIFJhbmtpbmcgYW5kIEluY29tZSBHcm91cCBhcmUgcHJlc2VudC4gVmFsdWVzIHRoYXQgYXJlIG1pc3NpbmcgaW4gZWl0aGVyIGdlbmRlciBhcmUgaW1wdXRlZCB3aXRoIHRoZSByZXNwb25kZW50IGF2YWlsYWJsZSBmb3IgdGhhdCBjb3VudHJ5IG11bHRpcGxpZWQgYnkgcGVyY2VudGFnZSBkaWZmZXJlbmNlLiBBIHNtYWxsIG51bWJlciBvZiByb3dzIHN0aWxsIHdpdGggbWlzc2luZyB2YWx1ZXMgZm9yIGluY29tZSBncm91cCBvciBoYXBwaW5lc3MgcmFua2luZyBhcmUgdGhlbiByZW1vdmVkLiAKCk91dGxpZXJzIGFyZSBzY2FubmVkIHZpc3VhbGx5IHVzaW5nIGJveHBsb3RzIGFuZCBudW1lcmljYWxseSB1c2luZyB6LnNjb3JlIG5vcm1hbGlzYXRpb24uIE5vIG91dGxpZXJzIGZvciB1bml2YXJpYXRlIHZhcmlhYmxlcyB3ZXJlIGlkZW50aWZpZWQuIEJpdmFyaWF0ZSBvdXRsaWVycyBmb3IgTWFsZSAoJSkgYW5kIEZlbWFsZSAoJSkgY29tcGFyaXNvbiBhcmUgaWRlbnRpZmllZCB1c2luZyBNYWhhbGFib25pcyBkaXN0YW5jZSBhbmQgcmVtYWluIGZvciBmdXJ0aGVyIGludmVzdGlnYXRpb24gZHVyaW5nIGFuYWx5c2lzLiBJbiBvcmRlciB0byBvYnRhaW4gYSBub3JtYWwgZGlzdHJpYnV0aW9uICwgdGhlIEFkb2xlc2NlbnQgQXZlcmFnZSB2YXJpYWJsZSB1bmRlcmdvZXMgYSBzcXVhcmUgcm9vdCB0cmFuc2Zvcm1hdGlvbi4gCgpGaW5hbGx5LCB0aGUgcmVzdWx0aW5nLCB0aWR5IGRhdGEgZnJhbWUgaXMgc2F2ZWQgYXMgYSBjc3YgZmlsZSB0byBhbGxvdyBhbmFseXNpcyB0byBiZSByZWFkaWx5IGNvbXBsZXRlZC4gCgojIyBEYXRhIApUaHJlZSBkYXRhIHNldHMgY29udGFpbmluZyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgaGFwcGluZXNzIGxldmVscyBvZiBjb3VudHJpZXMsIGF0dGl0dWRlcyB0b3dhcmRzIHZpb2xlbmNlIHRvd2FyZHMgd29tZW4gYW5kIHNvY2lvZWNvbm9taWMgYW5kIGdlb2dyYXBoaWMgZGV0YWlscyBoYXZlIGJlZW4gb2J0YWluZWQuIFRoZXNlIGRhdGEgc2V0cyBhcmUgcHJlcHJvY2Vzc2VkIGFuZCBtZXJnZWQgdG8gcHJvdmlkZSBhIGNvbXBsZXRlIGRhdGEgc2V0IGZvciBhIHJhbmdlIG9mIGFuYWx5dGljYWwgcXVlc3Rpb25zLgoKIyMjIEhhcHBpbmVzcyBMZXZlbHMgRGF0YSBTZXQKRGF0YSByZWdhcmRpbmcgdGhlIGhhcHBpbmVzcyBsZXZlbHMgb2YgY291bnRyaWVzIGhhcyBiZWVuIG9idGFpbmVkIGZyb20gS2FnZ2xlLiAgVGhlIGRhdGEgc2V0IHdhcyBkb3dubG9hZGVkIGFzIGEgY3N2IGZpbGUgZnJvbSB0aGUgZm9sbG93aW5nIFVSTCBodHRwczovL3d3dy5rYWdnbGUuY29tL3Vuc2Rzbi93b3JsZC1oYXBwaW5lc3MuCgpUaGUgZGF0YSBwcm92aWRlZCBpcyBvYnRhaW5lZCBmcm9tIHJlc3BvbnNlcyB0byB0aGUgR2FsbHVwIFdvcmxkIFBvbGwuQ291bnRyaWVzIGFyZSByYW5rZWQgY29tcGFyZWQgdG8gYSBmaWN0aW9uYWwgY291bnRyeSAnRHlzdG9waWEnIHdoaWNoIGlzIGdpdmVuIGEgc2NvcmUgb2YgemVybyBmb3IgYWxsIHZhcmlhYmxlcy4gVGhlIG9yaWdpbmFsIGRhdGEgc2V0IGNvbnRhaW5zIDkgdmFyaWFibGVzLiBUaGUgZm9sbG93aW5nIDUgdmFyaWFibGVzIGhhdmUgYmVlbiBpZGVudGlmaWVkIGFzIHJlbGV2YW50LiAKCioqQ291bnRyeSBOYW1lKio6IE5hbWUgb2YgdGhlIENvdW50cnkuIENoYXJhY3RlciBWYXJpYWJsZS4KCioqT3ZlcmFsbCBSYW5rKio6IFJhbmtpbmcgb2YgdGhlIGNvdW50cnkncyBoYXBwaW5lc3MgaW5kaWNhdG9yLCB3aXRoIDEgYmVpbmcgdGhlIGNvdW50cnkgd2l0aCB0aGUgaGlnaGVzdCBvdmVyYWxsIGhhcHBpbmVzcyBzY29yZSwgYmFzZWQgb24gYSBjb21iaW5hdGlvbiBvZiB0aGUgb3RoZXIgdmFyaWFibGVzLiBOdW1lcmljIHZhcmlhYmxlLiAKCioqU2NvcmUqKjogSGFwcGluZXNzIHNjb3JlLiBWYWx1ZSBiZXR3ZWVuIDAgYW5kIDEwLiAwIGluZGljYXRlcyB0aGUgbGV2ZWwgb2YgRHlzdG9waWEsIHdpdGggbm8gcmVwb3J0ZWQgaGFwcGluZXNzLiAxMCBpbmRpY2F0ZXMgYSBwZXJmZWN0bHkgaGFwcHkgcmVzcG9uZGVudC4gQ29udGludW91cyBudW1lcmljIHZhbHVlLgoKKipHRFAqKjogR0RQIHBlciBjYXBpdGEuIFJlZmVycyB0byBleHRlbnQgdG8gd2hpY2ggR0RQIHJlZmVycyB0byB0aGUgaGFwcGluZXNzIHNjb3JlLiBWYWx1ZSBiZXR3ZWVuIDAgYW5kIDEuNjkuCgoqKkZyZWVkb20qKjogRnJlZWRvbSB0byBtYWtlIGxpZmUgY2hvaWNlcy4gUmVmZXJzIHRvIHRoZSBleHRlbnQgb2Ygd2hpY2ggZnJlZWRvbSBjb250cmlidXRlZCB0byB0aGUgaGFwcGluZXNzIHNjb3JlLiAKCiMjIyBDb3VudHJ5IEluZm9ybWF0aW9uIERhdGEgU2V0CkluZm9ybWF0aW9uIHJlZ2FyZGluZyB0aGUgZ2VvZ3JhcGhpYyByZWdpb24gYW5kIHNvY2lvZWNvbm9taWMgc3RhdHVzIG9mIHRoZSBjb3VudHJpZXMgaGFzIGJlZW4gb2J0YWluZWQgZnJvbSB0aGUgV29ybGQgQmFuayBkYXRhIHNldCAiV29tZW4gd2hvIGJlbGlldmUgYSBodXNiYW5kIGlzIGp1c3RpZmllZCBpbiBiZWF0aW5nIGhpcyB3aWZlIChhbnkgb2YgZml2ZSByZWFzb25zKSAoJSkiLiBUaGUgZGF0YSBzZXQgd2FzIGRvd25sb2FkZWQgYXMgYSBjc3YgZmlsZSBmcm9tIHRoZSBmb2xsb3dpbmcgVVJMIGh0dHBzOi8vZGF0YS53b3JsZGJhbmsub3JnL2luZGljYXRvci9TRy5WQVcuUkVBUy5aUz9lbmQ9MjAxOCZuYW1lX2Rlc2M9ZmFsc2Umc3RhcnQ9MjAxOCZ2aWV3PWJhciAKVGhpcyBkYXRhIHNldCBjb250YWlucyB0aGUgc3VwcGxlbWVudGFyeSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgY291bnRyaWVzLiBEYXRhLCB3aGljaCB3ZXJlIG9idGFpbmVkIGluIGEgc2VwYXJhdGUgYnV0IGNvcnJlc3BvbmRpbmcgZGF0YSBzZXQsIGhlcmUgdGl0bGVzIEFkb2xlc2NlbnRzIFdobyBBZ3JlZS4KVGhlIENvdW50cnkgSW5mb3JtYXRpb24gRGF0YSBTZXQgY29udGFpbnMgdGhlIGZvbGxvd2luZyByZWxldmFudCB2YXJpYWJsZXMuIAoKKipDb3VudHJ5IENvZGUqKiBBIGNoYXJhY3RlciB2YXJpYWJsZSBpZGVudGlmeWluZyB0aGUgQ291bnRyeQoKKipSZWdpb24qKiBJZGVudGlmaWVzIHRoZSBnZW9ncmFwaGljYWwgcmVnaW9uIG9mIHRoZSBjb3VudHJ5LiBBIGNhdGVnb3JpY2FsLCBmYWN0b3IgdmFyaWFibGUuCgoqKkNvdW50cnkgTmFtZSoqIElkZW50aWZpZXMgbmFtZSBvZiB0aGUgY291bnRyeS4gQSBjaGFyYWN0ZXIgdmFyaWFibGUuIAoKKipJbmNvbWUgR3JvdXAqKiBHcm91cHMgdGhlIGNvdW50cmllcyBpbnRvIG9yZGVyZWQgZmFjdG9ycyBiYXNlZCBvbiBhdmVyYWdlIGluY29tZS4gRmFjdG9yIGxldmVscyBhcmUgTG93IEluY29tZSA8IExvd2VyIE1pZGRsZSBJbmNvbWUgPCBNaWRkbGUgSW5jb21lIDwgVXBwZXIgTWlkZGxlIEluY29tZSA8IEhpZ2ggSW5jb21lLiAKCiMjIyBBZG9sZXNjZW50cyBXaG8gQWdyZWUgKEFXQSkKSW5mb3JtYXRpb24gcmVnYXJkaW5nICd0aGUgcHJvcG9ydGlvbiBvZiBhZG9sZXNjZW50cyB3aG8gYmVsaWV2ZSBhIGh1c2JhbmQgaXMganVzdGlmaWVkIGluIGJlYXRpbmcgaGlzIHdpZmUgZm9yIGFueSBvZiB0aGUgZml2ZSBnaXZlbiByZWFzb25zJyBoYXMgYmVlbiBvYnRhaW5lZCBmcm9tIHRoZSBVbmljZWYgd2Vic2l0ZSBhdCB0aGUgZm9sbG93aW5nIFVSTCBodHRwczovL2RhdGEudW5pY2VmLm9yZy90b3BpYy9nZW5kZXIvaGFybWZ1bC1wcmFjdGljZXMtYW5kLWludGltYXRlLXBhcnRuZXItdmlvbGVuY2UvLiAKClRoZSBkYXRhIGlzIGNvbGxlY3RlZCBmcm9tIGEgc2FtcGxlIG9mIDE1IHRvIDE5IHllYXIgb2xkIG1hbGUgYW5kIGZlbWFsZSBhZG9sZXNjZW50cyBiZXR3ZWVuIDIwMTItMjAxOS4gVGhlIGZpdmUgcmVhc29ucyBhcmUgZ2l2ZW4gYXMgYXJndWluZyB3aXRoIHRoZWlyIGh1c2JhbmQsIGJ1cm5pbmcgdGhlIGZvb2QsIG5lZ2xlY3RpbmcgdGhlIGNoaWxkcmVuLCByZWZ1c2luZyBzZXh1YWwgcmVsYXRpb25zIGFuZCBnb2luZyBvdXQgd2l0aG91dCB0ZWxsaW5nIGhpbS4gVGhlIEFXQSBkYXRhIHNldHMgY29udGFpbnMgdGhlIGZvbGxvd2luZyB2YXJpYWJsZXMuIAoKKipDb3VudHJ5IE5hbWUqKiBBIGNoYXJhY3RlciB2YXJpYWJsZSBpZGVudGlmeWluZyB0aGUgY291bnRyeS4KCioqUmVnaW9uIE5hbWUqKiBBIGNhdGVnb3JpY2FsIHZhcmlhYmxlIGlkZW50aWZ5aW5nIHRoZSBnZW9ncmFwaGljIHJlZ2lvbiBvZiB0aGUgY291bnRyeS4gQW4gdW4tb3JkZXJlZCBmYWN0b3IuIAoKKipNYWxlKiogUGVyY2VudGFnZSBvZiBtYWxlIHJlc3BvbmRlbnRzIHRoYXQgYmVsaWV2ZSB3aWZlIGJlYXRpbmcgaXMganVzdGlmaWVkLiBBIGNvbnRpbnVvdXMgbnVtZXJpYyB2YXJpYWJsZSB3aXRoIGEgdmFsdWUgYmV0d2VlbiAwIGFuZCAxMDAuIAoKKipGZW1hbGUqKiBQZXJjZW50YWdlIG9mIGZlbWFsZSByZXNwb25kZW50cyB0aGF0IGJlbGlldmUgd2lmZSBiZWF0aW5nIGlzIGp1c3RpZmllZC4gQSBjb250aW51b3VzIG51bWVyaWMgdmFyaWFibGUgd2l0aCBhIHZhbHVlIGJldHdlZW4gMCBhbmQgMTAwLgoKVGhlIGFib3ZlIGRhdGEgc2V0cyB3aWxsIHVuZGVyZ28gcHJlbGltaW5hcnkgbWFuaXB1bGF0aW9uIGFuZCB0aWR5aW5nIGJlZm9yZSBiZWluZyBtZXJnZWQuIEluIHRoZSBmb2xsb3dpbmcgY2h1bmsgZGF0YSBoYXMgYmVlbiBpbXBvcnRlZCB1c2luZyBiYXNlciBhbmQgcmVhZHhsIGZ1bmN0aW9ucy4gRGF0YSBoYXMgYmVlbiBzdWJzZXR0ZWQgdG8gaW5jbHVkZSBvbmx5IHJlbGV2YW50IHZhcmlhYmxlIHdpdGggdGhlIHNxdWFyZSBicmFja2V0IFtdIHN1YnNldHRpbmcgZnVuY3Rpb24uIENvbHVtbiBuYW1lcyBhcmUgYWRqdXN0ZWQgYXMgbmVjZXNzYXJ5IGJ5IHJlYXNzaWduaW5nIHdpdGggY29sbmFtZXMoKS4gCgoKYGBge3J9CiMgVGhpcyBpcyB0aGUgUiBjaHVuayBmb3IgdGhlIERhdGEgU2VjdGlvbgoKIyBIYXBwaW5lc3MgTGV2ZWxzIApoYXBweV8yMDE4PC0gcmVhZC5jc3YoIjIwMTguY3N2IikKY29sbmFtZXMoaGFwcHlfMjAxOCkgPSBjKCJPdmVyYWxsIFJhbmsiLCAiQ291bnRyeSBOYW1lIiwgIlNjb3JlIiwgIkdEUCIsICJTb2NpYWwgU3VwcG9ydCIsICJIZWFsdGh5IExFIiwgIkZyZWVkb20iLCAiR2VuZXJvc2l0eSIsICJQZXJjZXB0aW9ucyIpCmhhcHB5XzIwMTg8LSBoYXBweV8yMDE4WyAsIGMoIk92ZXJhbGwgUmFuayIsICJDb3VudHJ5IE5hbWUiLCAiU2NvcmUiLCAiR0RQIiwgIkZyZWVkb20iKV0KaGVhZChoYXBweV8yMDE4KQoKIyBDb3VudHJ5IEluZm9ybWF0aW9uCmNvdW50cnlfaW5mbzwtIHJlYWQuY3N2KCJKdXN0aWZpZWRfY291bnRyeV9pbmZvLmNzdiIpCmNvbG5hbWVzKGNvdW50cnlfaW5mbyk8LSBjKCJDb3VudHJ5IENvZGUiLCAiUmVnaW9uIiwgIkluY29tZSBHcm91cCIsICJOb3RlcyIsICJDb3VudHJ5LlJlZ2lvbi5Uby5TcGxpdCIpCmNvdW50cnlfaW5mbzwtIGNvdW50cnlfaW5mb1sgLCBjKCJDb3VudHJ5IENvZGUiLCAiUmVnaW9uIiwgIkluY29tZSBHcm91cCIsICJDb3VudHJ5LlJlZ2lvbi5Uby5TcGxpdCIpXSAjIENvbHVtbiBjb250YWluaW5nIG5vdGVzIG9uIGNvdW50cnkgdGhhdCBhcmUgbm90IHJlbGF0ZWQgdG8gYSB2YXJpYWJsZSBoYXMgYmVlbiBvbWl0dGVkCmhlYWQoY291bnRyeV9pbmZvKQoKIyBBZG9sZXNjZW50cyBXaG8gQWdyZWUKd29tZW5fc3RhdHM8LSByZWFkX2V4Y2VsKCJKdXN0aWZpY2F0aW9uLW9mLXdpZmUtYmVhdGluZy1hbW9uZy1hZG9sZXNjZW50cy1kYXRhYmFzZV9KdW5lLTIwMjAueGxzIiwgc2tpcCA9IDcsIG5fbWF4ID0gMjAzKSAjc2tpcCBhbmQgbl9tYXggYXJndW1lbnRzIGFyZSB1c2VkIHRvIGVuc3VyZSBvbmx5IHJlbGV2YW50IHJvd3Mgd2l0aCBvYnNlcnZhdGlvbnMgcmVsYXRpbmcgdG8gY291bnRyaWVzIGFyZSBpbXBvcnRlZC4KY29sbmFtZXMod29tZW5fc3RhdHMpPC0gYygiQ291bnRyeSBOYW1lIiwgIk1hbGUiLCAiMyIsICJGZW1hbGUiLCAiNSIsICJTb3VyY2UiKQp3b21lbl9zdGF0czwtIHdvbWVuX3N0YXRzWyAsIGMoIkNvdW50cnkgTmFtZSIsICJNYWxlIiwgIkZlbWFsZSIpXSAjIFZhcmlhYmxlIGNvbnRhaW5pbmcgc291cmNlIGluZm9ybWF0aW9uIGhhcyBiZWVuIG9taXR0ZWQuIApoZWFkKHdvbWVuX3N0YXRzKQpgYGAKCiMjIFVuZGVyc3RhbmQgCgoqKlRoZSBXb3JsZCBIYXBwaW5lc3MgRGF0YSBTZXQqKiAKClRoZSB2YXJpYWJsZSB0eXBlcyBpbiB0aGlzIGRhdGEgc2V0IGFyZSBjb25zaWRlcmVkIGFwcHJvcHJpYXRlIGFuZCBkbyBub3QgbmVlZCBjb252ZXJ0aW5nLiBDbGFzcyB0eXBlIGlzIGRhdGEgZnJhbWUuCgpPdmVyYWxsIFJhbms6IEludGVnZXIKCkNvdW50cnkgTmFtZTogQ2hhcmFjdGVyCgpTY29yZTogTnVtZXJpYyAoRG91YmxlKQoKR0RQOiBOdW1lcmljIChEb3VibGUpCgpGcmVlZG9tOiBOdW1lcmljIChEb3VibGUpCgoKCioqQ291bnRyeSBJbmZvcm1hdGlvbiBEYXRhIFNldCoqCgpUaGUgcmVnaW9uIGFuZCBpbmNvbWUgZ3JvdXAgdmFyaWFibGVzIGFyZSBjb252ZXJ0ZWQgZnJvbSBjaGFyYWN0ZXIgdmFyaWFibGVzIGludG8gZmFjdG9yZWQgdmFyaWFibGVzIHVzaW5nIHRoZSBmYWN0b3IoKSBmdW5jdGlvbi4gVGhlIG9yZGVyZWQgPSBUUlVFIGFyZ3VtZW50IGlzIGFwcGxpZWQgdG8gdGhlIEluY29tZSBHcm91cCB2YXJpYWJsZSB0byBlbnN1cmUgdGhlIGZhY3RvcnMgYXJlIGluIHRoZSBhcHByb3ByaWF0ZSBvcmRlci4gQ2xhc3MgdHlwZSBpcyBkYXRhIGZyYW1lLgoKQ291bnRyeSBDb2RlOiBDaGFyYWN0ZXIKClJlZ2lvbjogRmFjdG9yIHdpdGggNyBMZXZlbHM6ICJMYXRpbiBBbWVyaWNhICYgQ2FyaWJiZWFuIiwgIlNvdXRoIEFzaWEiLCAiU3ViLVNhaGFyYW4gQWZyaWNhIiwgIkV1cm9wZSAmIENlbnRyYWwgQXNpYSIsICJNaWRkbGUgRWFzdCAmIE5vcnRoIEFmcmljYSIsICJFYXN0IEFzaWEgJiBQYWNpZmljIiAgICAgICAKWzddICJOb3J0aCBBbWVyaWNhIgoKSW5jb21lIEdyb3VwOiBPcmRlcmVkIEZhY3RvciB3aXRoIDQgTGV2ZWxzOiAiTG93IGluY29tZSIsICJMb3dlciBtaWRkbGUgaW5jb21lIiwgIlVwcGVyIG1pZGRsZSBpbmNvbWUiLCAiSGlnaCBpbmNvbWUiICAKCkNvdW50cnkuUmVnaW9uLlRvLlNwbGl0OiBDaGFyYWN0ZXIKCioqQWRvbGVzY2VudHMgV2hvIEFncmVlIERhdGEgU2V0KioKClRoZSBNYWxlIGFuZCBGZW1hbGUgdmFyaWFibGVzIHdlcmUgYXV0b21hdGljYWxseSByZWFkIGFzIGNoYXJhY3RlciBkdWUgdG8gcHJlc2VuY2Ugb2YgTkEgdmFsdWVzLiBUaGVzZSBhcmUgY29udmVydGVkIGZyb20gY2hhcmFjdGVyIHRvIG51bWVyaWMgdmFyaWFibGVzIGFzIHRoZXkgcmVwcmVzZW50IGEgcGVyY2VudGFnZS4gVGhpcyBpcyBjb21wbGV0ZWQgdXNpbmcgdGhlIGFzLm51bWVyaWMoKSBmdW5jdGlvbi4gQ2xhc3MgdHlwZSBpcyBkYXRhIGZyYW1lLiAKCk1hbGU6IE51bWVyaWMgKERvdWJsZSkKCkZlbWFsZTogTnVtZXJpYyAoRG91YmxlKQoKQ291bnRyeS5SZWdpb24uVG8uU3BsaXQ6IENoYXJhY3RlcgoKCmBgYHtyfQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBVbmRlcnN0YW5kIFNlY3Rpb24KCiMgQ2hlY2sgdmFyaWFibGUgdHlwZTogSGFwcGluZXNzIExldmVscyAKc3RyKGhhcHB5XzIwMTgpCnR5cGVvZihoYXBweV8yMDE4JFNjb3JlKQp0eXBlb2YoaGFwcHlfMjAxOCRHRFApCnR5cGVvZihoYXBweV8yMDE4JEZyZWVkb20pCgojIENoZWNrIHZhcmlhYmxlIHR5cGU6IENvdW50cnkgSW5mbwpzdHIoY291bnRyeV9pbmZvKQoKIyBDb252ZXJ0IHRvIGZhY3RvciB3aGVyZSBuZWNlc3NhcnkKY291bnRyeV9pbmZvJFJlZ2lvbjwtIGZhY3Rvcihjb3VudHJ5X2luZm8kUmVnaW9uLCBsZXZlbHMgPSBjKCJMYXRpbiBBbWVyaWNhICYgQ2FyaWJiZWFuIiwgIlNvdXRoIEFzaWEiLCAiU3ViLVNhaGFyYW4gQWZyaWNhIiwgIkV1cm9wZSAmIENlbnRyYWwgQXNpYSIsICJNaWRkbGUgRWFzdCAmIE5vcnRoIEFmcmljYSIsICJFYXN0IEFzaWEgJiBQYWNpZmljIiwgIk5vcnRoIEFtZXJpY2EiKSwgbGFiZWxzID0gYygiTGF0aW4gQW1lcmljYSAmIENhcmliYmVhbiIsICJTb3V0aCBBc2lhIiwgIlN1Yi1TYWhhcmFuIEFmcmljYSIsICJFdXJvcGUgJiBDZW50cmFsIEFzaWEiLCAiTWlkZGxlIEVhc3QgJiBOb3J0aCBBZnJpY2EiLCAiRWFzdCBBc2lhICYgUGFjaWZpYyIsICJOb3J0aCBBbWVyaWNhIiksIG9yZGVyZWQgPSBGQUxTRSkKCmNvdW50cnlfaW5mbyRgSW5jb21lIEdyb3VwYDwtIGZhY3Rvcihjb3VudHJ5X2luZm8kYEluY29tZSBHcm91cGAsIGxldmVscyA9IGMoIkxvdyBpbmNvbWUiLCAiTG93ZXIgbWlkZGxlIGluY29tZSIsICJVcHBlciBtaWRkbGUgaW5jb21lIiwgIkhpZ2giKSwgbGFiZWxzID0gYygiTG93IGluY29tZSIsICJMb3dlciBtaWRkbGUgaW5jb21lIiwgIlVwcGVyIG1pZGRsZSBpbmNvbWUiLCAiSGlnaCBpbmNvbWUiKSwgb3JkZXJlZCA9IFRSVUUpCgojIENoZWNrIGxldmVscyBhbmQgc3RydWN0dXJlCnN0cihjb3VudHJ5X2luZm8kYEluY29tZSBHcm91cGApCmxldmVscyhjb3VudHJ5X2luZm8kYEluY29tZSBHcm91cGApCnN0cihjb3VudHJ5X2luZm8kUmVnaW9uKQpsZXZlbHMoY291bnRyeV9pbmZvJFJlZ2lvbikKCiMgQ2hlY2sgdmFyaWFibGUgdHlwZTogQWRvbGVzY2VudHMgV2hvIEFncmVlCnN0cih3b21lbl9zdGF0cykKCiMgQ29udmVydCBwZXJjZW50YWdlIHZhcmlhYmxlcyBmcm9tIGNoYXJhY3RlciB0byBudW1lcmljIAp3b21lbl9zdGF0cyRNYWxlPC0gYXMubnVtZXJpYyh3b21lbl9zdGF0cyRNYWxlKQp3b21lbl9zdGF0cyRGZW1hbGU8LSBhcy5udW1lcmljKHdvbWVuX3N0YXRzJEZlbWFsZSkKdHlwZW9mKHdvbWVuX3N0YXRzJE1hbGUpCnR5cGVvZih3b21lbl9zdGF0cyRGZW1hbGUpCmBgYAoKCiMjCVRpZHkgJiBNYW5pcHVsYXRlIERhdGEgSSAKT2YgdGhlIGFib3ZlIGRhdGEgc2V0cywgdGhlIFdvcmxkIEhhcHBpbmVzcyBkYXRhIHNldCBvYnRhaW5lZCBmcm9tIEthZ2dsZSBpcyBjb25zaWRlcmVkIHRvIGJlIHRpZHkuIEVhY2ggdmFyaWFibGUgbXVzdCBoYXMgaXRzIG93biBjb2x1bW4sIGVhY2ggb2JzZXJ2YXRpb24gbXVzdCBoYXMgaXRzIG93biByb3cgYW5kIGVhY2ggdmFsdWUgaGFzIGl0cyBvd24gY2VsbC4gCgpUaGUgQ291bnRyeSBJbmZvcm1hdGlvbiBkYXRhIHNldCBpcyBub3QgY29uc2lkZXJlZCB0byBiZSB0aWR5LiBUaGlzIGlzIGJlY2F1c2UgaW4gdGhlIG9yaWdpbmFsIGRhdGEgc2V0IENvdW50cnkgYW5kIFJlZ2lvbiB2YXJpYWJsZXMgYXJlIGZvdW5kIHdpdGhpbiB0aGUgb25lIGNvbHVtbiwgdGl0bGVkICdUYWJsZSBOYW1lJy4gQWRkaXRpb25hbGx5LCB0aGVyZSBhcmUgcm93cyB3aGljaCBkbyBub3QgY29udGFpbiByZWxldmFudCBvYnNlcnZhdGlvbnMuIAoKVXBvbiBpbnNwZWN0aW9uIG9mIHRoZSBDb3VudHJ5IEluZm9ybWF0aW9uIGRhdGEgc2V0LCBpdCBjYW4gYmUgc2VlbiB0aGF0IHRoZSByb3dzIHRoYXQgaGF2ZSBtaXNzaW5nIHZhbHVlcyBpbiB0aGUgJ0luY29tZSBHcm91cCcgY29sdW1uIGFyZSBjb25zaXN0ZW50IHdpdGggdGhlIHJvd3MgdGhhdCBoYXZlIGluYXBwcm9wcmlhdGUgdmFsdWVzIGZvciB0aGUgQ291bnRyeS5SZWdpb24uVG8uU3BsaXQgdmFyaWFibGUgY29sdW1uLiBBcyB3ZSBvbmx5IG5lZWQgdG8ga2VlcCBkYXRhIGZvciBjb3VudHJ5IG5hbWVzIGZyb20gdGhpcyBjb2x1bW4sIHdlIHdpbGwgb21pdCB0aG9zZSByb3dzIHdpdGggbWlzc2luZyB2YWx1ZXMgdG8gdGlkeSB0aGUgZGF0YSBzZXQuIFRoaXMgaXMgY29tcGxldGVkIHVzaW5nIHRoZSBjb21wbGV0ZS5jYXNlcygpIGZ1bmN0aW9uIHdoaWNoIGlzIGFwcHJvcHJpYXRlIGZvciB0aGUgc3ViLXNldHRlZCBjb2x1bW5zLiBUaGlzIGFjdGlvbiB3aWxsIGNvbXBsZXRlIGJvdGggb2YgdGhlIHN0ZXBzIHJlcXVpcmVkIHRvIHRpZHkgdGhpcyBkYXRhIHNldC4gVGhlIGNvbHVtbiB3aWxsIGJlIGFwcHJvcHJpYXRlbHkgcmVuYW1lZCB0byAiQ291bnRyeSBOYW1lIiBhcyBpdCBubyBsb25nZXIgY29udGFpbnMgdW53YW50ZWQgaW5mb3JtYXRpb24gcmVnYXJkaW5nIHRoZSBSZWdpb24gdmFyaWFibGUuCgpUaGUgQWRvbGVzY2VudHMgV2hvIEFncmVlIGRhdGFzZXQgaXMgbm90IGNvbnNpZGVyZWQgdGlkeS4gVHdvIG9mIHRoZSB2YXJpYWJsZXMgaW4gY29sdW1ucyAzIGFuZCA1IGNvbnRhaW5zIHJvd3Mgd2l0aCBtdWx0aXBsZSB2YWx1ZXMgaW4gdGhlIG9uZSBjZWxsLiBIb3dldmVyLCB0aGUgaW5mb3JtYXRpb24gaW4gdGhlc2UgY29sdW1ucyBpcyBvbmx5IGdpdmVuIGZvciBhIGxpbWl0ZWQgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBhbmQgcGVydGFpbnMgdG8gdGhlIHllYXIgb3IgbWV0aG9kIG9mIGNvbGxlY3Rpb24uIEl0IGlzIG5vdCBjb25zaWRlcmVkIHJlbGV2YW50IHRvIHRoaXMgZGF0YSBzZXQsIHRoZXJlZm9yZSB0aGVzZSB2YXJpYWJsZXMgaGF2ZSBiZWVuIG9taXR0ZWQgKFNlZSBEYXRhIHNlY3Rpb24pICAKClRoZSBkYXRhIHNldHMgd2lsbCBiZSBtZXJnZWQgaW50byBvbmUgZGF0YSBmcmFtZS4KCmBgYHtyfQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIEkgCgojIENvdW50cnkgSW5mb3JtYXRpb24gRGF0YSBTZXQgLSBmaWx0ZXIgb3V0IG5hbWVzIG9mIFJlZ2lvbnMgYnkgc3ViLXNldHRpbmcgZm9yIG9ubHkgY29tcGxldGUgY2FzZXMuIApjb3VudHJ5X2luZm88LSBjb3VudHJ5X2luZm9bY29tcGxldGUuY2FzZXMoY291bnRyeV9pbmZvKSwgXSAjVGhpcyBkYXRhIGZyYW1lIHNob3VsZCBub3cgY29udGFpbiBubyBtaXNzaW5nIHZhbHVlcyB3aGVuIHNjYW5uZWQKY29sbmFtZXMoY291bnRyeV9pbmZvKTwtIGMoIkNvdW50cnkgQ29kZSIsICJSZWdpb24iLCAiSW5jb21lIEdyb3VwIiwgIkNvdW50cnkgTmFtZSIpCmhlYWQoY291bnRyeV9pbmZvKQoKIyBNZXJnZSBEYXRhIHNldHMKanVzdGlmaWVkX2Z1bGw8LSB3b21lbl9zdGF0cyAlPiUgZnVsbF9qb2luKGNvdW50cnlfaW5mbykgJT4lIGZ1bGxfam9pbihoYXBweV8yMDE4KQpoZWFkKGp1c3RpZmllZF9mdWxsKQojIFN1YnNldHRlZCB0byByZW1vdmUgdW5uZWNlc3NhcnkgdmFyaWFibGVzCmp1c3RpZmllZF9mdWxsPC0ganVzdGlmaWVkX2Z1bGxbICxjKDE6Myw1OjcpXQoKIyBDb2x1bW5zIHJlbmFtZWQgZm9yIGFkZGVkIGNsYXJpdHkKY29sbmFtZXMoanVzdGlmaWVkX2Z1bGwpPC0gYygiQ291bnRyeSBOYW1lIiwgIk1hbGUoJSkiLCAiRmVtYWxlKCUpIiwgIlJlZ2lvbiIsICJJbmNvbWUgR3JvdXAiLCAiSGFwcGluZXNzIFJhbmtpbmciKQoKYGBgCgojIwlUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIElJIAoKVGhyZWUgbmV3IHZhcmlhYmxlcyBhcmUgY3JlYXRlZCB1c2luZyB0aGUgbXV0YXRlKCkgZnVuY3Rpb24gYW5kIHNpbXBsZSBtYXRocyBmdW5jdGlvbnMuICBUaGUgdmFyaWFibGVzIGFyZSBmaXJzdCBjb252ZXJ0ZWQgYmFjayB0byB0eXBlIG51bWVyaWMgYXMgbmVjZXNzYXJ5LgoKIC0gVGhlIGF2ZXJhZ2UgdmFsdWUgYnkgY291bnRyeSBvZiBNYWxlICglKSBhbmQgRmVtYWxlICglKSBpcyBjYWxsZWQgJ0Fkb2xlc2NlbnQgQXZlcmFnZScKIAogLSBUaGUgZGlmZmVyZW5jZSBpbiB2YWx1ZSBpbiBNYWxlICglKSBhbmQgRmVtYWxlICglKSByZXNwb25kZW50cyBieSBjb3VudHJ5IGlzIGNhbGxlZCAnTWFsZS1GZW1hbGUgRGlmZmVyZW5jZScKIAogLSBUaGVzZSB0d28gdmFyaWFibGVzIGFyZSB0aGVuIGNvbWJpbmVkIHRvIGNyZWF0ZSBhIFBlcmNlbnRhZ2UgRGlmZmVyZW5jZSB2YXJpYWJsZS4gCgpUaGUgbWVhbiBvZiB0aGUgUGVyY2VudGFnZSBEaWZmZXJlbmNlIHZhcmlhYmxlIHdpbGwgYmUgdXNlZCBmb3IgaW1wdXRpbmcgbWlzc2luZyB2YWx1ZXMuIAoKCmBgYHtyfQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIElJIAoKIyBUaGUgc3RydWN0dXJlIG9mIHZhcmlhYmxlcyBpcyBjaGVja2VkIGFuZCBjb252ZXJ0ZWQgdG8gZW5zdXJlIHRoZXkgYXJlIGluIG51bWVyaWMgZm9ybSAKc3RyKGp1c3RpZmllZF9mdWxsKQpqdXN0aWZpZWRfZnVsbCRgTWFsZSglKWA8LSBhcy5udW1lcmljKGp1c3RpZmllZF9mdWxsJGBNYWxlKCUpYCkKanVzdGlmaWVkX2Z1bGwkYEZlbWFsZSglKWA8LSBhcy5udW1lcmljKGp1c3RpZmllZF9mdWxsJGBGZW1hbGUoJSlgKQoKIyBDcmVhdGUgbmV3IHZhcmlhYmxlcyB1c2luZyBtdXRhdGUoKQpqdXN0aWZpZWRfZnVsbDwtIGp1c3RpZmllZF9mdWxsICU+JSBtdXRhdGUoJ0Fkb2xlc2NlbnQgQXZlcmFnZScgID0gKGBNYWxlKCUpYCArIGBGZW1hbGUoJSlgKS8yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ01hbGUtRmVtYWxlIERpZmZlcmVuY2UnID0gYE1hbGUoJSlgIC0gYEZlbWFsZSglKWApCmp1c3RpZmllZF9mdWxsPC0ganVzdGlmaWVkX2Z1bGwgJT4lIG11dGF0ZSgnUGVyY2VudGFnZSBEaWZmZXJlbmNlJyA9IGBNYWxlLUZlbWFsZSBEaWZmZXJlbmNlYC9gQWRvbGVzY2VudCBBdmVyYWdlYCkKCiMgTWVhbiBvZiBQZXJjZW50Z2UgRGlmZmVyZW5jZSBmb3VuZAptZWFuKGp1c3RpZmllZF9mdWxsJGBQZXJjZW50YWdlIERpZmZlcmVuY2VgLCBuYS5ybSA9IFRSVUUpICU+JSByb3VuZCgzKQoKaGVhZChqdXN0aWZpZWRfZnVsbCkKCmBgYAoKIyMJU2NhbiBJIAoKSW4gb3JkZXIgZm9yIHRoaXMgaW5mb3JtYXRpb24gdG8gYmUgdXNlZnVsIGFuYWx5dGljYWxseSwgb25seSByb3dzIGZvciBjb3VudHJpZXMgdGhhdCBoYXZlIHZhbHVlcyBmb3IgZWl0aGVyIE1hbGUgb3IgRmVtYWxlIHJlc3BvbmRlbnRzLCBhcyB3ZWxsIGFzIGJvdGggSW5jb21lIEdyb3VwIGFuZCBIYXBwaW5lc3MgUmFua2luZyB3aWxsIGJlIGluY2x1ZGVkLgoKVGhlIGluaXRpYWwgQVdBIGRhdGEgc2V0IGNvbnRhaW5pbmcgdGhlIE1hbGUgKCUpIGFuZCBGZW1hbGUgKCUpIHZhcmlhYmxlcywgaXMgbWlzc2luZyBkYXRhIGZvciBtYW55IHJvd3MuIFRoaXMgaXMgYmVjYXVzZSBkYXRhIHdhcyBvbmx5IGNvbGxlY3RlZCBmb3IgYSBsaW1pdGVkIG51bWJlciBvZiBjb3VudHJpZXMgYXMgY29tcGFyZWQgdG8gdGhlIEhhcHBpbmVzcyBSYW5raW5nIGFuZCBDb3VudHJ5IEluZm9ybWF0aW9uIHNldHMuIFRoZXJlZm9yZSwgdmFsdWVzIHRoYXQgYXJlIG1pc3NpbmcgZm9yIGVpdGhlciBidXQgbm90IGJvdGggb2YgdGhlc2UgdmFyaWFibGUgd2lsbCBiZSByZW1vdmVkLiBUaGlzIGlzIGNvbXBsZXRlZCBieSBpZGVudGlmeWluZyB3aGljaCB2YWx1ZXMgYXJlIG1pc3NpbmcgZm9yIGJvdGggRmVtYWxlICglKSBhbmQgTWFsZSAoJSkgdXNpbmcgaXMubmEoKSBuZXN0ZWQgd2l0aGluIHRoZSB3aGljaCgpIGZ1bmN0aW9uLCBhbmQgc2F2aW5nIHRoaXMgaXMgYSB2ZWN0b3IuIAoKTWlzc2luZyB2YWx1ZXMgZnJvbSBlaXRoZXIgdGhlIE1hbGUgb3IgRmVtYWxlIHJlc3BvbmRlbnRzIGNvbHVtbnMgd2lsbCBiZSByZXBsYWNlZCB3aXRoIHRoZSB2YWx1ZSBvZiB0aGUgb3Bwb3NpbmcgZ2VuZGVyIG11bHRpcGxpZWQgYnkgdGhlIHBlcmNlbnRhZ2UgbWVhbiBvZiB0aGUgTWFsZS1GZW1hbGUgZGlmZmVyZW5jZS4gRm9yIHNpbXBsaWNpdHksIHRoZSBtZWFuIHZhbHVlIGhhcyBiZWVuIGluY2x1ZGVkIGluIHRoZSBydWxlcyBhcyB0aGUgY29ycmVzcG9uZGluZyBudW1lcmljIHZhbHVlIGZvciAyLjclIGluY3JlYXNlIG9yIGRlY3JlYXNlLiAKCkZvbGxvd2luZyB0aGlzIHRoZSByb3dzIHRoYXQgaGF2ZSBtaXNzaW5nIHZhbHVlcyBpbiB0aGUgSGFwcGluZXNzIFJhbmtpbmcgb3IgSW5jb21lIEdyb3VwIGNvbHVtbnMgd2lsbCBiZSBvbWl0dGVkLgoKYGBge3J9CiMgVGhpcyBpcyB0aGUgUiBjaHVuayBmb3IgdGhlIFNjYW4gSQojVGhlIGZvbGxvd2luZyBjb2RlIGlkZW50aWZpZXMgcm93cyB3aGljaCBhcmUgbWlzc2luZyB2YWx1ZXMgZm9yIGJvdGggbWFsZSBhbmQgZmVtYWxlIHJlc3BvbmRlbnRzIGFuZCB0aGVyZWZvcmUgbmVlZCB0byBiZSBvbWl0dGVkLgptaXNzaW5nX3ZhbHM8LSB3aGljaChpcy5uYShqdXN0aWZpZWRfZnVsbCRgRmVtYWxlKCUpYCB8IGp1c3RpZmllZF9mdWxsJGBNYWxlKCUpYCkpCgojIFNhdmUgZGF0YSBmcmFtZSB3aXRob3V0IG1pc3NpbmcgdmFsdWVzCmp1c3RpZmllZF9uYXJtPC0ganVzdGlmaWVkX2Z1bGxbLW1pc3NpbmdfdmFscywgXSAjIFN1Yi1zZXR0aW5nIHRvIHJlbW92ZSBtaXNzaW5nIHZhbHVlcwpoZWFkKGp1c3RpZmllZF9uYXJtKQoKIyBTZXQgcnVsZXMgZm9yIGltcHV0YXRpb24KUnVsZXM8LSB2YWxpZGF0b3IoYE1hbGUoJSlgID09IGBGZW1hbGUoJSlgKjAuOTczLAogICAgICAgICAgICAgICAgICBgRmVtYWxlKCUpYCA9PSBgTWFsZSglKWAqMS4wMjcpCiMgSW1wdXRhdGlvbgpqdXN0aWZpZWRfaW1wdXRlZDwtIGltcHV0ZV9scihqdXN0aWZpZWRfbmFybSwgUnVsZXMpCmhlYWQoanVzdGlmaWVkX2ltcHV0ZWQpCgojUmVtb3ZlIE5BcyBmcm9tIEhhcHBpbmVzcyBSYW5raW5nIGFuZCBJbmNvbWUgR3JvdXAKCiNGaW5kIHZhbHVlcyB0aGF0IGFyZSBub3QgTkEgaW4gSGFwcGluZXNzIFJhbmtpbmcgYW5kIFN1YnNldCBmb3IgdGhlc2UKaGFwcGluZXNzX25hcm08LSB3aGljaCghaXMubmEoanVzdGlmaWVkX2ltcHV0ZWQkYEhhcHBpbmVzcyBSYW5raW5nYCkpIyBTYXZlIHZlY3RvciBleGNsdWRpbmcgbWlzc2luZyB2YWx1ZXMKanVzdGlmaWVkX0hSX25hcm08LSBqdXN0aWZpZWRfaW1wdXRlZFtoYXBwaW5lc3NfbmFybSxdCgojRmluZCB2YWx1ZXMgdGhhdCBhcmUgbm90IE5BIGluIEluY29tZSBHcm91cCBhbmQgU3Vic2V0IGZvciB0aGVzZSAKbWlzc2luZ19pbmNvbWU8LSB3aGljaCghaXMubmEoanVzdGlmaWVkX0hSX25hcm0kYEluY29tZSBHcm91cGApKQpqdXN0aWZpZWRfYWxsX25hcm08LSBqdXN0aWZpZWRfSFJfbmFybVttaXNzaW5nX2luY29tZSxdCgojIFByaW50IG91dApoZWFkKGp1c3RpZmllZF9hbGxfbmFybSkKYGBgCgoKIyMJU2NhbiBJSQoKQWxsIG51bWVyaWMgZGF0YSB3aWxsIGJlIHNjYW5uZWQgZm9yIG91dGxpZXJzLiBVbml2YXJpYXRlIGFuYWx5c2lzIGlzIGNvbmR1Y3RlZCBvZiBIYXBwaW5lc3MsIE1hbGUgKCUpIGFuZCBGZW1hbGUgKCUpIHZhcmlhYmxlcy4gVGhpcyBpcyBkb25lIHZpc3VhbGx5IHVzaW5nIGEgYm94IHBsb3QuIE91dGxpZXJzIGFyZSBhbHNvIGFuYWx5emVkIGJ5IHotc2NvcmUgbm9ybWFsaXphdGlvbiB1c2luZyB0aGUgb3V0bGllcnMoKSBwYWNrYWdlLiBBcyBIYXBwaW5lc3MgaXMgYSByYW5raW5nIHZhcmlhYmxlIHRoZXJlIGlzIG5vIG91dGxpZXJzLCBhcyBleHBlY3RlZC4gVW5pdmFyaWF0ZSBhbmFseXNpcyBvZiB0aGUgTWFsZSglKSBhbmQgRmVtYWxlICglKSB2YXJpYWJsZXMgdGhlcmUgYXJlIG5vIG9ic2VydmF0aW9ucyB0aGF0IGFyZSBjb25zaWRlcmVkIG91dGxpZXJzLiAKCkJpdmFyaWF0ZSBhbmFseXNpcyBpcyBjb21wbGV0ZWQgdXNpbmcgdGhlIE1haGFsYW5vYmlzIGRpc3RhbmNlIHRocm91Z2ggdGhlIE1WTigpIHBhY2thZ2UuIEluIHRoZSBiaXZhcmlhdGUgYW5hbHlzaXMgb2YgTWFsZSAoJSkgYW5kIEZlbWFsZSAoJSkgdmFsdWVzIHRoZXJlIGlzIDIzIG91dGxpZXJzIGlkZW50aWZpZWQsIGhvd2V2ZXIgbWFueSBvZiB0aGVzZSBsaWUgY2xvc2UgdG8gdGhlIHF1YW50aWxlIGxpbmUuIER1ZSB0byBleHBlY3RlZCBjdWx0dXJhbCBkaWZmZXJlbmNlcyBiZXR3ZWVuIGZlbWFsZXMgYW5kIG1hbGVzIHdpdGhpbiBhIHBvcHVsYXRpb24sIHRoZXNlIG91dGxpZXJzIGFyZSBjb25zaWRlcmVkIHZhbHVhYmxlIGFub21hbGllcyBhbmQgd291bGQgYmUgZnVydGhlciBpbnZlc3RpZ2F0ZWQgaW4gdGhlIGFuYWx5c2lzIHN0YWdlLiAKCkFkb2xlc2NlbnQgQXZlcmFnZSBhbmQgTWFsZS1GZW1hbGUgRGlmZmVyZW5jZSB2YWx1ZXMgZG8gbm90IG5lZWQgdG8gYmUgc2Nhbm5lZCBmb3Igb3V0bGllcnMgYXMgdGhleSBhcmUgY29tYmluYXRpb25zIG9mIG9yaWdpbmFsIHZhbHVlcy4gCgpgYGB7cn0KIyBUaGlzIGlzIHRoZSBSIGNodW5rIGZvciB0aGUgU2NhbiBJSQoKIyBIYXBwaW5lc3MgVmFyaWFibGUgVW5pdmFyaWF0ZSBBbmFseXNpcwpqdXN0aWZpZWRfYWxsX25hcm0kYEhhcHBpbmVzcyBSYW5raW5nYCAlPiUgYm94cGxvdChtYWluID0gIkhhcHBpbmVzcyBSYW5raW5nIERpc3RyaWJ1dGlvbiIsIHlsYWIgPSAiSGFwcGluZXNzIFJhbmtpbmciLCBjb2wgPSAicGluayIpICMgQ3JlYXRlIEJveHBsb3QKei5zY29yZXMuaGFwcGluZXNzPC0ganVzdGlmaWVkX2FsbF9uYXJtJGBIYXBwaW5lc3MgUmFua2luZ2AgJT4lIHNjb3Jlcyh0eXBlID0gInoiKSAjIHouc2NvcmUgbm9ybWFsaXphdGlvbgp6LnNjb3Jlcy5oYXBwaW5lc3MgJT4lIHN1bW1hcnkoKQojei5zY29yZXMgdGhhdCBhcmUgZ3JlYXRlciB0aGFuIDMgb3IgbGVzcyB0aGFuIC0zIGFyZSBjb25zaWRlcmVkIG91dGxpZXJzCndoaWNoKCBhYnMoei5zY29yZXMuaGFwcGluZXNzKSA+MyApCgojIE1hbGUoJSkgVmFyaWFibGUKanVzdGlmaWVkX2FsbF9uYXJtJGBNYWxlKCUpYCAlPiUgYm94cGxvdChtYWluID0gIk1hbGUgKCUpIERpc3RyaWJ1dGlvbiIsIHlsYWIgPSAiUGVyY2VudGFnZSBXaG8gQWdyZWUiLCBjb2wgPSAicmVkIikKei5zY29yZXMubWFsZTwtIGp1c3RpZmllZF9hbGxfbmFybSRgTWFsZSglKWAgJT4lIHNjb3Jlcyh0eXBlID0gInoiKQp6LnNjb3Jlcy5tYWxlICU+JSBzdW1tYXJ5KCkKCiN6LnNjb3JlcyB0aGF0IGFyZSBncmVhdGVyIHRoYW4gMyBvciBsZXNzIHRoYW4gLTMgYXJlIGNvbnNpZGVyZWQgb3V0bGllcnMKd2hpY2goIGFicyh6LnNjb3Jlcy5tYWxlKSA+MyApCgojIEZlbWFsZSglKSBWYXJpYWJsZQpqdXN0aWZpZWRfYWxsX25hcm0kYEZlbWFsZSglKWAgJT4lIGJveHBsb3QobWFpbiA9ICJGZW1hbGUgKCUpIERpc3RyaWJ1dGlvbiIsIHlsYWIgPSAiUGVyY2VudGFnZSBXaG8gQWdyZWUiLCBjb2wgPSAiT3JhbmdlIikKei5zY29yZXMuZmVtYWxlPC0ganVzdGlmaWVkX2FsbF9uYXJtJGBGZW1hbGUoJSlgICU+JSBzY29yZXModHlwZSA9ICJ6IikKei5zY29yZXMuZmVtYWxlICU+JSBzdW1tYXJ5KCkKCiN6LnNjb3JlcyB0aGF0IGFyZSBncmVhdGVyIHRoYW4gMyBvciBsZXNzIHRoYW4gLTMgYXJlIGNvbnNpZGVyZWQgb3V0bGllcnMKd2hpY2goIGFicyh6LnNjb3Jlcy5mZW1hbGUpID4zICkKCiMgTWFsZSAoJSkgYW5kIEZlbWFsZSAoJSkgQml2YXJpYXRlIEFuYWx5c2lzCiMgTXVsdGl2YXJpYXRlIG91dGxpZXIgZGV0ZWN0aW9uIHVzaW5nIE1haGFsYW5vYmlzIGRpc3RhbmNlIHdpdGggUVEgcGxvdHMKcmVzdWx0cy5tdm48LSBtdm4oZGF0YSA9IGp1c3RpZmllZF9hbGxfbmFybVssIDI6M10sIG11bHRpdmFyaWF0ZU91dGxpZXJNZXRob2QgPSAicXVhbiIsIHNob3dPdXRsaWVycyA9IFRSVUUpCmBgYAoKCiMjCVRyYW5zZm9ybSAKClRoZSBBV0EgdmFyaWFibGUsIGlzIHJpZ2h0LXNrZXdlZCwgYXMgb2JzZXJ2ZWQgaW4gdGhlIGJlbG93IGhpc3RvZ3JhbS4gVG8gbWFrZSB0aGlzIG1vcmUgdXNlZnVsIGZvciBhbmFseXNpcyBhIG5vcm1hbCBkaXN0cmlidXRpb24gaXMgb2J0YWluZWQgYnkgYXBwbHlpbmcgYSBzcXVhcmUgcm9vdCB0cmFuc2Zvcm1hdGlvbi4gVGhlIHJlc3VsdGluZyBkaXN0cmlidXRpb24gaXMgb2JzZXJ2ZWQgdG8gYmUgY2xvc2UgdG8gbm9ybWFsLiBQcmlvciB0byB0aGlzIHRyYW5zZm9ybWF0aW9uIHRoZSAnQWRvbGVzY2VudCBBdmVyYWdlJyBjb2x1bW4gd2FzIGFkanVzdGVkIHRvIGluY2x1ZGUgdmFsdWVzIHRoYXQgaGFkIGJlZW4gaW1wdXRlZCBpbiB0aGUgU2NhbjogTWlzc2luZyBWYWx1ZXMgc2VjdGlvbiBhYm92ZS4KCmBgYHtyfQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBUcmFuc2Zvcm0gU2VjdGlvbgoKIyBDcmVhdGUgbmV3IGFkb2xlc2NlbnQgYXZlcmFnZSBjb2x1bW4gdG8gcmVmbGVjdCByZXBsYWNlZCBtaXNzaW5nIHZhbHVlcwpqdXN0aWZpZWRfd2l0aGF2ZzwtIGp1c3RpZmllZF9hbGxfbmFybVssIGMoMTo2LCA4KV0gJT4lIG11dGF0ZSgnQWRvbGVzY2VudCBBdmVyYWdlJyA9IChgTWFsZSglKWArYEZlbWFsZSglKWApLzIpCgojIFZpc3VhbCBhbmFseXNpcyBvZiBoaXN0b2dyYW0gZm9yIEFkb2xlc2NlbnQgQXZlcmFnZQpoaXN0KGp1c3RpZmllZF93aXRoYXZnJGBBZG9sZXNjZW50IEF2ZXJhZ2VgLCBtYWluID0gIkhpc3RvZ3JhbSBvZiBBV0EgTWVhbiBWYWx1ZSIsIHhsYWIgPSAiUGVyY2VudGFnZSBBZ3JlZW1lbnQiLCBjb2wgPSAibGlnaHQgYmx1ZSIpCgojIEFwcGx5IGEgc3F1YXJlIHJvb3QgdHJhbnNmb3JtYXRpb24gdG8gb2J0YWluIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbgpzcXJ0X2FncmVlPC0gc3FydChqdXN0aWZpZWRfd2l0aGF2ZyRgQWRvbGVzY2VudCBBdmVyYWdlYCkKCiMgVmlzdWFsIGFuYWx5c2lzIG9mIGhpc3RvZ3JhbSBmb3IgQWRvbGVzY2VudCBBdmVyYWdlIGFmdGVyIHRyYW5zZm9ybWF0aW9uCmhpc3Qoc3FydF9hZ3JlZSwgbWFpbiA9ICJIaXN0b2dyYW0gb2YgQVdBIChTcXJ0KSIsIHhsYWIgPSAiTm9ybWFsaXNlZCBQZXJjZW50YWdlIEFncmVlbWVudCIsIGNvbCA9ICJsaWdodCBibHVlIiwgYnJlYWtzID0gOCkKYGBgCgoKYGBge3J9CiMgVGhpcyBDaHVuayB3cml0ZXMgdGhlIGRhdGEgZnJhbWUgYXMgYSAuY3N2IGZpbGUgZm9yIGZ1dHVyZSB1c2UKd3JpdGUuY3N2KHNxcnRfYWdyZWUsICJDb3VudHJ5X2F0dGl0dWRlc19pbmZvcm1hdGlvbl9ub3JtYWxpc2VkLmNzdiIpCmBgYAoKIyMgUmVmZXJlbmNlcwoKIldvcmxkIEhhcHBpbmVzcyBSZXBvcnQiLCBTdXN0YWluYWJsZSBEZXZlbG9wbWVudCBTb2x1dGlvbnMgTmV0d29yaywgMjAxOCwgYWNjZXNzZWQgZnJvbSBodHRwczovL3d3dy5rYWdnbGUuY29tL3Vuc2Rzbi93b3JsZC1oYXBwaW5lc3MKCiJXb21lbiB3aG8gYmVsaWV2ZSBhIGh1c2JhbmQgaXMganVzdGlmaWVkIGluIGJlYXRpbmcgaGlzIHdpZmUgKGFueSBvZiB0aGUgZml2ZSByZWFzb25zKSAlIiwgVGhlIFdvcmxkIEJhbmsgR3JvdXAsIDIwMTYsIGFjY2Vzc2VkIGZyb20gaHR0cHM6Ly9kYXRhLndvcmxkYmFuay5vcmcvaW5kaWNhdG9yL1NHLlZBVy5SRUFTLlpTP2VuZD0yMDE4Jm5hbWVfZGVzYz1mYWxzZSZzdGFydD0yMDE4JnZpZXc9YmFyIAoKIlBlcmNlbnRhZ2Ugb2YgZ2lybHMgYW5kIGJveXMgMTXigJMxOSB5ZWFycyBvbGQgd2hvIGNvbnNpZGVyIGEgaHVzYmFuZCB0byBiZSBqdXN0aWZpZWQgaW4gaGl0dGluZyBvciBiZWF0aW5nIGhpcyB3aWZlIGZvciBhdCBsZWFzdCBvbmUgb2YgdGhlIHNwZWNpZmllZCByZWFzb25zLCBpLmUuLCBpZiBoaXMgd2lmZSBidXJucyB0aGUgZm9vZCwgYXJndWVzIHdpdGggaGltLCBnb2VzIG91dCB3aXRob3V0IHRlbGxpbmcgaGltLCBuZWdsZWN0cyB0aGUgY2hpbGRyZW4gb3IgcmVmdXNlcyBzZXh1YWwgcmVsYXRpb25zIiwgVU5JQ0VGLCAyMDIwLCBhY2Nlc3NlZCBmcm9tICBodHRwczovL2RhdGEudW5pY2VmLm9yZy90b3BpYy9nZW5kZXIvaGFybWZ1bC1wcmFjdGljZXMtYW5kLWludGltYXRlLXBhcnRuZXItdmlvbGVuY2UvCgo8YnI+Cjxicj4K