Required packages

# Load required packages

library(readr)
library(tidyr)
library(dplyr)
library(stringr)
library(outliers)
library(ggplot2)
library(forecast)

Custom functions


is.special <- function(x){
if (is.numeric(x)) (is.infinite(x) | is.nan(x))
}

is.specialorNA <- function(x){
if (is.numeric(x)) (is.infinite(x) | is.nan(x) | is.na(x))
}

Executive Summary

Data for analysis of Carbon emissions from nations across the years 1995 to 2016, along with nations vulnerability to climate change, was prepared.

Data

Source descriptions

Carbon emissions data (nation.1751_2016.csv) from Carbon Dioxide Information Analysis Center

Dataset of different carbon emissions by countries across the years with the following variables.

Nation - name of country to which emissions pertain to.

Year - year in which emissions occurred.

tot_co2_emi - Total CO2 emissions from fossil-fuels (solid, liquid, gas,flaring) and cement production. In thousand metric tons of C.

solid_cons - Emissions from solid fuel consumption.

liquid_cons - Emissions from liquid fuel consumption.

gas_cons - Emissions from gas fuel consumption.

cement_prod - Emissions from cement production.

gas_flare - Emissions from gas flaring.

cap_co2_emi - Per capita CO2 emissions (metric tons of carbon).

bunker_cons - Emissions from bunker fuels (not included in the totals). Emissions from fuel used for international aviation and maritime transport. Convention and protocol dictate these emissions are not included in national totals (tot_co2_emi).


NDGain Index data (gain.csv) from the Notre Dame Global Adaptation Initiative

Data set of NDGain index (vulnerability to climate change) for each country across the years, with the following variables.

This index is based on numerous (quantitative) indicators eg economic and governance readiness to adapt to change , and exposure to negative impacts.

The smaller the index, the more vulnerable to climate change is the nation.

ISO3 - 3 character ISO 3166 coding of country.

Name - Name of country to which the NDGain Index pertains to.

1995 - NDGain index for year 1995.

Indices for subsequent years, through to 2018, are provided as seperate variables.


Population data (input.csv) from the Notre Dame Global Adaptation Initiative

Data set of human population for each country across the years, with the following variables.

ISO3 - 3 character ISO 3166 coding of country.

Name - Name of country to which the population pertains to.

1995 - population for year 1995.

Population for subsequent years, through to 2018, are provided as seperate variables.


Extract Steps

The three data sets are read in via readr::read_csv function.

The variables for carbon emissions are named appropriately. They are each too long for analysis.

#Source data

# Carbon Dioxide Information Analysis Center at Appalachian State University, Boone North Carolina, https://energy.appstate/CDIAC.
c_emissions <- read_csv("nation.1751_2016.csv", skip = 4)
Parsed with column specification:
cols(
  Nation = col_character(),
  Year = col_double(),
  `Total CO2 emissions from fossil-fuels and cement production (thousand metric tons of C)` = col_double(),
  `Emissions from solid fuel consumption` = col_double(),
  `Emissions from liquid fuel consumption` = col_double(),
  `Emissions from gas fuel consumption` = col_double(),
  `Emissions from cement production` = col_double(),
  `Emissions from gas flaring` = col_character(),
  `Per capita CO2 emissions (metric tons of carbon)` = col_character(),
  `Emissions from bunker fuels (not included in the totals)` = col_double()
)
612 parsing failures.
 row                                    col expected actual                   file
3562 Emissions from solid fuel consumption  a double      . 'nation.1751_2016.csv'
3562 Emissions from liquid fuel consumption a double      . 'nation.1751_2016.csv'
3562 Emissions from gas fuel consumption    a double      . 'nation.1751_2016.csv'
3563 Emissions from solid fuel consumption  a double      . 'nation.1751_2016.csv'
3563 Emissions from liquid fuel consumption a double      . 'nation.1751_2016.csv'
.... ...................................... ........ ...... ......................
See problems(...) for more details.
# Notre Dame Global Adaptation Initiative, University of Notre Dame,  https://gain.nd.edu/our-work/country-index/rankings/
gain <- read_csv("resources_2020_04_05_19h09/resources/gain/gain.csv")
Parsed with column specification:
cols(
  .default = col_double(),
  ISO3 = col_character(),
  Name = col_character()
)
See spec(...) for full column specifications.
# Notre Dame Global Adaptation Initiative, University of Notre Dame,  https://gain.nd.edu/our-work/country-index/rankings/
# Get population data for inputing missing CO2 emission per capita 
pop <- read_csv("resources_2020_04_05_19h09/resources/indicators/pop/input.csv") %>% select(-(2))
Parsed with column specification:
cols(
  .default = col_double(),
  ISO3 = col_character(),
  Name = col_character()
)
See spec(...) for full column specifications.
#Renaming emission variables appropriately
names(c_emissions)[names(c_emissions)== "Total CO2 emissions from fossil-fuels and cement production (thousand metric tons of C)"] <- "tot_co2_emi"
names(c_emissions)[names(c_emissions)== "Emissions from solid fuel consumption"] <- "solid_cons"
names(c_emissions)[names(c_emissions)== "Emissions from liquid fuel consumption"] <- "liquid_cons"
names(c_emissions)[names(c_emissions)== "Emissions from gas fuel consumption"] <- "gas_cons"
names(c_emissions)[names(c_emissions)== "Emissions from cement production"] <- "cement_prod"
names(c_emissions)[names(c_emissions)== "Emissions from gas flaring"] <- "gas_flare"
names(c_emissions)[names(c_emissions)== "Per capita CO2 emissions (metric tons of carbon)"] <- "cap_co2_emi"
names(c_emissions)[names(c_emissions)== "Emissions from bunker fuels (not included in the totals)"] <- "bunker_cons"

#Sample emissions data
c_emissions %>% head()

#Sample NDGain data
gain %>% head()

#Sample population data
pop %>% head()
NA

Extract Steps (continued)

Clean up and standardise join column Nation/Name in both source data sets c_emissions and gain

  • Capitalise
  • Standardise eg. ‘AND’ to ‘&’, shortening of name etc.
# Clean up / standardise join column Nation
c_emi_nation <- c_emissions %>% 
  mutate(
    Nation = str_replace_all(Nation,  c(" AND " = " & ", " \\(.*\\)" = "", "UNITED STATES OF AMERICA" = "UNITED STATES", "DEMOCRATIC REPUBLIC OF THE CONGO" = "ZAIRE","COTE D IVOIRE" = "COTE D'IVOIRE", "BRUNEI DARUSSALAM"= "BRUNEI", "REPUBLIC OF " = "", "ISLAMIC IRAN" = "IRAN", "UNITED TANZANIA" = "TANZANIA", "LAO PEOPLE S DEMOCRATIC REPUBLIC" = "LAO PEOPLE'S DEMOCRATIC REPUBLIC", "PLURINATIONAL STATE OF BOLIVIA" = "BOLIVIA", "GUINEA BISSAU" = "GUINEA-BISSAU", "RUSSIAN FEDERATION" = "RUSSIA"))
  )

# clean join column
gain_nation <- gain %>%
              mutate(
                Name = toupper(Name) %>% str_replace_all(c(" AND " = " & ",", REPUBLIC OF" = "", ", BOLIVARIAN REPUBLIC O" = "", "BRUNEI DARUSSALAM"= "BRUNEI", ", UNITED REPUBLIC OF" = "", ", ISLAMIC REPUBLIC OF" = "", "CONGO, THE DEMOCRATIC REPUBLIC O" = "ZAIRE", ", PLURINATIONAL STATE OF" = "", "RUSSIAN FEDERATION" = "RUSSIA"))
                            
              )

Subsetting

  • Only those records from gain(gain_nation) that have no missing values (complete cases) will be considered. All incomplete cases have no NDGain index for any year.
  • Subset NDGains 1995 - 2016. Emissions dataset go as far as 2016.
# Scan for incomplete cases
gain_notcomplete <- gain_nation[!complete.cases(gain_nation),]

# All incomplete cases have no index for any year
gain_notcomplete %>% head()

# Subset gain data to 1995 - 2016
gain_nation <- gain_nation[complete.cases(gain_nation),] %>% select(1:24)

Tidy & Manipulate Data I

The NDGain dataset (gain) is not tidy as it has values for variable year as column names (1995, 1996 …). And the observations for each year are on one row. The year needs to be along a column , and each observation on a seperate row.

The same applies to the population dataset (pop): values for variable year as column names (1995, 1996 …). And the observations for each year are on one row. The year needs to be along a column , and each observation on a seperate row.

To make the datasets tidy the following steps are conducted.

#Make gain dataset tidy
gain_tidy <- gain_nation %>% pivot_longer(cols = -(1:2), names_to = "Year",  values_to = "NDGain")
#Convert Year to integer
gain_tidy$Year <- as.integer(gain_tidy$Year)

#Make population dataset tidy
pop_tidy <- pop %>% pivot_longer(cols = -(1), names_to = "Year",  values_to = "Population")
#Convert Year to integer
pop_tidy$Year <- as.integer(pop_tidy$Year)

# Show tidy gain dataset
head(gain_tidy)

# Show tidy population dataset
head(pop_tidy)

Merge data sets

The gain and population data sets are then merged together (gain_tidy) by ISO3 and Year.

The final dataset (emigain) is the result of the merge of the tidy gain dataset(gain_tidy) and emissions dataset(c_emi_nation) by Nation/Name and Year.

#left join gain and population sets together on ISO3 and Year
gain_tidy <- gain_tidy %>% left_join(pop_tidy, by = c("ISO3" = "ISO3", "Year" = "Year"))

#merge gain and emissions datasets together
emigain <- gain_tidy %>% inner_join(c_emi_nation , by = c("Name" = "Nation", "Year" = "Year") )

Understand

The emigain dataset is a dataframe of dimension 3887 x 13 (13 variables, 3887 observations).

Variables, their data type and any type conversions are as follows.

# Understand the data and structure
emigain %>% str()
tibble [3,887 x 13] (S3: tbl_df/tbl/data.frame)
 $ ISO3       : chr [1:3887] "AFG" "AFG" "AFG" "AFG" ...
 $ Name       : chr [1:3887] "AFGHANISTAN" "AFGHANISTAN" "AFGHANISTAN" "AFGHANISTAN" ...
 $ Year       : num [1:3887] 1995 1996 1997 1998 1999 ...
 $ NDGain     : num [1:3887] 34.3 34.3 34.3 34.5 34.5 ...
 $ Population : num [1:3887] 18110657 18853437 19357126 19737765 20170844 ...
 $ tot_co2_emi: num [1:3887] 339 321 299 284 224 211 223 292 331 250 ...
 $ solid_cons : num [1:3887] 4 2 1 1 1 1 19 15 25 25 ...
 $ liquid_cons: num [1:3887] 225 213 198 188 135 136 134 120 169 153 ...
 $ gas_cons   : num [1:3887] 88 84 77 72 66 61 57 149 127 62 ...
 $ cement_prod: num [1:3887] 16 16 16 16 16 7 7 8 10 10 ...
 $ gas_flare  : chr [1:3887] "6" "6" "6" "6" ...
 $ cap_co2_emi: chr [1:3887] "0.02" "0.02" "0.02" "0.01" ...
 $ bunker_cons: num [1:3887] 4 4 4 4 4 4 4 4 7 9 ...


The conversion to factor is done via the factor() function. No labelling is required this time.

For the ordered factor (Year), the factor() function is used along with parameters levels = [vector of ordered years] and ordered=TRUE.

The conversion of the two emissions (gas_flare, cap_co2_emi) from character to numeric double is completed using the conversion function as.double().

#ISO3 as factor
emigain$ISO3 <- emigain$ISO3 %>% factor()

#Name as factor
emigain$Name <- emigain$Name %>% factor()

#Name as factor
emigain$Name <- emigain$Name %>% factor()

#Year as order factor
#emigain$Year %>% unique() 

emigain$Year <- emigain$Year %>% factor(levels = c(1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016), ordered = TRUE)

#gas_flare & cap_co2_emi
emigain$gas_flare <- emigain$gas_flare %>% as.double()
emigain$cap_co2_emi <- emigain$cap_co2_emi %>% as.double()
NAs introduced by coercion


After the necessary conversions, inspecting the resulting data types below show the 3 factors, one ordered, and all emission variables are numeric.

emigain %>% str()
tibble [3,887 x 13] (S3: tbl_df/tbl/data.frame)
 $ ISO3       : Factor w/ 178 levels "AFG","AGO","ALB",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Name       : Factor w/ 178 levels "AFGHANISTAN",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Year       : Ord.factor w/ 22 levels "1995"<"1996"<..: 1 2 3 4 5 6 7 8 9 10 ...
 $ NDGain     : num [1:3887] 34.3 34.3 34.3 34.5 34.5 ...
 $ Population : num [1:3887] 18110657 18853437 19357126 19737765 20170844 ...
 $ tot_co2_emi: num [1:3887] 339 321 299 284 224 211 223 292 331 250 ...
 $ solid_cons : num [1:3887] 4 2 1 1 1 1 19 15 25 25 ...
 $ liquid_cons: num [1:3887] 225 213 198 188 135 136 134 120 169 153 ...
 $ gas_cons   : num [1:3887] 88 84 77 72 66 61 57 149 127 62 ...
 $ cement_prod: num [1:3887] 16 16 16 16 16 7 7 8 10 10 ...
 $ gas_flare  : num [1:3887] 6 6 6 6 6 6 6 0 0 0 ...
 $ cap_co2_emi: num [1:3887] 0.02 0.02 0.02 0.01 0.01 0.01 0.01 0.01 0.01 0.01 ...
 $ bunker_cons: num [1:3887] 4 4 4 4 4 4 4 4 7 9 ...

Tidy & Manipulate Data II

Addition of variable all_co2_emi

The variable is inclued in the emigain dataset via the mutate function, where it is derived using the indicated formula.

#Add all_co2_emi variable - total co2 emissions + bunker emissions.

emigain <- emigain %>% mutate(
                              all_co2_emi = tot_co2_emi + bunker_cons  
                      )

#Inspect variable structure
emigain$all_co2_emi %>% str()
 num [1:3887] 343 325 303 288 228 215 227 296 338 259 ...

Scan I

Scanning and dealing with missing values, special values, errors

  • Missing values either through merging of datasets (Population) or as literals ‘.’ , ‘..’ were standardised to R’s NA.

  • gas_flare/cap_co2_emi conversion to numeric coerced the ‘.’/‘..’ to NA.

  • Complete cases in emigain, across numeric variables (4:14), were examined. ISO3/Name/Year (1:3) were ignored as they are join columns.

  • Column counts of missing values reveal that missing values are confined to Population and cap_co2_emi.

  • Verifying the records where there are missing values for either Population or cap_co2_emi, show that they can easily be imputed.

  • Impute using formula ‘carbon emission per capita’ = ‘total carbon emission’ x 1000 / population

cap_co2_emi = tot_co2_emi x 1000 / Population


Scan for missing values

Summary of missing values show

  • 22 missing in Population

  • 17 missing in cap_co2_emi

#Get incomplete cases to check against post impute
emigain_notc2 <- emigain[!complete.cases(emigain[, 4:14]),]

#Scan for NAs in data set
colSums(is.na(emigain))
       ISO3        Name        Year      NDGain  Population tot_co2_emi  solid_cons liquid_cons    gas_cons cement_prod   gas_flare cap_co2_emi bunker_cons 
          0           0           0           0          22           0           0           0           0           0           0          17           0 
all_co2_emi 
          0 

Show samples of records with missing values

#Check Population NAs
emigain[is.na(emigain$Population),]  %>% head(5)

#Check cap_co2_emi NAs
emigain[is.na(emigain$cap_co2_emi),] %>% head(5)
NA

Impute missing values

  • Impute missing population and per capita emission based on formula above.

  • Checking imputation by looking up results against incomplete case dataset (emigain_notc2) show that the imputations are correct.

#Impute missing population
emigain$Population[is.na(emigain$Population)] <- emigain$tot_co2_emi[is.na(emigain$Population)] * 1000 /  emigain$cap_co2_emi[is.na(emigain$Population)]

#Impute missing per capita emission
emigain$cap_co2_emi[is.na(emigain$cap_co2_emi)] <- round(emigain$tot_co2_emi[is.na(emigain$cap_co2_emi)] * 1000/  emigain$Population[is.na(emigain$cap_co2_emi)], 2)

#Check imputations
emigain_notc2 %>% inner_join(select(emigain, Year, Name, Population, cap_co2_emi), by = c("Year", "Name"))
NA

Scan for special values and errors

  • Special values (NaN , Inf) in emigain are scanned for, revealing none. Via applying the is.special() function across the columns.

  • Errors (negative emissions, non positive NDGain/Population) are scanned for, revealing none. Via applying comparison operators against relevant subsets.

#Check for special values
sapply(emigain, function(x) sum(is.special(x)))
       ISO3        Name        Year      NDGain  Population tot_co2_emi  solid_cons liquid_cons    gas_cons cement_prod   gas_flare cap_co2_emi bunker_cons 
          0           0           0           0           0           0           0           0           0           0           0           0           0 
all_co2_emi 
          0 
#Check for negative emissions
colSums(emigain[, -(1:5)] < 0, na.rm = TRUE)
tot_co2_emi  solid_cons liquid_cons    gas_cons cement_prod   gas_flare cap_co2_emi bunker_cons all_co2_emi 
          0           0           0           0           0           0           0           0           0 
#Check for non positive NDGain or Population
colSums(emigain[, (4:5)] < 0, na.rm = TRUE)
    NDGain Population 
         0          0 

Scan II

Approach & Summary

  • Univariate outlier detection is used on each NDGain , Population and the 9 emission variables.

  • This was decided as the emissions don’t share special relationships with each other and all the variables can be treated individually.

  • z-scores are applied across each variable. Outliers are flagged as those values with |z-score| > 3.

  • NDGain has no outliers flagged. The other variables eg. Population (44 flaged) , tot_co2_emi (47) do have outliers flagged.

  • Further inspection shows that the population for China and India are indeed valid values.

  • Likewise, total emission and other emissions from China, India and USA are legitimate values.

  • The distribution for these variables above are extremely positively skewed. These “outliers” are so far from the next set of observations in the same quartile.

  • Therefore the suggested outliers will be left alone - no transformation nor imputation.

Outlier summary

The z-scores across each of the numeric variables (column 4 to 14) will be established via applying the scores(type = “z”) function using function lapply().

Summary of outliers using the scores (|z-score| > 3)

00 NDGain

44 Population

47 tot_co2_emi

49 solid_cons

48 liquid_cons

45 gas_cons

22 cement_prod

88 gas_flare

78 cap_co2_emi

69 bunker_cons

46 all_co2_emi

# Get z-score for each numeric variable.  Score() function with type= "z"
z_scores <- emigain[, (4:14)] %>% lapply(FUN = function(x) scores(x, type= "z")) %>% as.data.frame()

# Outlier summary
colSums(abs(z_scores) > 3) 
     NDGain  Population tot_co2_emi  solid_cons liquid_cons    gas_cons cement_prod   gas_flare cap_co2_emi bunker_cons all_co2_emi 
          0          44          47          49          48          45          22          88          78          69          46 

Outlier inspection

Closer inspection of the Population outliers show that the populations are those for China and India. These are all valid. Confirmed these via the internet.

emigain[abs(z_scores$Population) > 3, ] %>% group_by(ISO3, Name) %>% slice_head(n=2)
NA

Closer inspection of the tot_co2_emi outliers show that the total emissions are those for China, India and USA. These are all valid. Confirmed these via the internet.

emigain[abs(z_scores$tot_co2_emi) > 3, ] %>% group_by(ISO3, Name) %>% slice_head(n=2)
NA

Closer inspection of the solid_cons outliers show that these emissions are those for China, India and USA. These are all valid. Confirmed these via the internet.

emigain[abs(z_scores$solid_cons) > 3, ] %>% group_by(ISO3, Name) %>% slice_head(n=2)
NA

Closer inspection of the liquid_cons outliers show that these emissions are those for China, India, Japan and USA. These are all valid. Confirmed these via the internet.

emigain[abs(z_scores$liquid_cons) > 3, ] %>% group_by(ISO3, Name) %>% slice_head(n=2)
NA

Closer inspection of the gas_cons outliers show that these emissions are those for China, Russia and USA. These are all valid. Confirmed these via the internet.

emigain[abs(z_scores$gas_cons) > 3, ] %>% group_by(ISO3, Name) %>% slice_head(n=2)
NA

Closer inspection of the cement_prod outliers show that these emissions are those for China. These are all valid. Confirmed these via the internet.

emigain[abs(z_scores$cement_prod) > 3, ] %>% group_by(ISO3, Name) %>% slice_head(n=2)
NA

Closer inspection of the gas_flare outliers show that these emissions all valid. Confirmed these via the internet.

emigain[abs(z_scores$gas_flare) > 3, ] %>% group_by(ISO3, Name) %>% slice_head(n=2)
NA

Closer inspection of the cap_co2_emi outliers show that these per capita emissions are valid. Confirmed these via the internet.

emigain[abs(z_scores$cap_co2_emi) > 3, ] %>% group_by(ISO3, Name) %>% slice_head(n=2)
NA

Closer inspection of the bunker_cons outliers show that these emissions are all valid. Confirmed these via the internet.

emigain[abs(z_scores$bunker_cons) > 3, ] %>% group_by(ISO3, Name) %>% slice_head(n=2)
NA
NA

Closer inspection of the all_co2_emi outliers show that these emissions are those for China, India and USA. These are all valid. They would follow the total emissions above.

emigain[abs(z_scores$all_co2_emi) > 3, ] %>% group_by(ISO3, Name) %>% slice_head(n=2)
NA

Transform

Approach & Summary

The total carbon emissions (tot_co2_emi) and population (Population) distributions are both heavily right skewed.

Transformations are applied to move them to normal distributions. tot_co2_emi.t and Population.t respectively.

Given that they are right skewed, mathematical functions log(), log10(), sqrt() are applied.

The resulting distributions are verified using histogram plots. At least one of the functions is considered suitable for the transformation, ie. closest to normal. So there is no need to explore elsewhere for other methods.

The Box Cox transformaton is used, using forecast::BoxCox.lambda to work out the best lambda, and then BoxCox() to perform the transformation. This is to discover alternative methods.

Total CO2 emissions transformation

  • Best transformation function is log10()

  • BoxCox lambda is 0

#total emissions distribution is heavily right skewed
emigain$tot_co2_emi %>% hist(main = "tot_co2_emi", breaks= 100)


#try transformations
emigain$tot_co2_emi %>% log() %>% hist(main = "log(tot_co2_emi)")

emigain$tot_co2_emi %>% log10() %>% hist(main = "log10(tot_co2_emi)") #best

emigain$tot_co2_emi %>% sqrt() %>% hist(main = "sqrt(tot_co2_emi)")


#get best lambda , then apply to transformation
emigain$tot_co2_emi %>% BoxCox.lambda(method = "loglik", lower = -3, upper = 3)
[1] 0
emigain$tot_co2_emi %>% BoxCox(lambda = 0) %>% hist(main = "BoxCox(tot_co2_emi)")


#apply best transformation
emigain$tot_co2_emi.t <- emigain$tot_co2_emi %>% log10()

Population transformation

  • Best transformation function is log()

  • BoxCox lambda is 0.05

#population distribution is heavily right skewed
emigain$Population %>% hist(main = "Population")


#try transformations
emigain$Population %>% log() %>% hist(main = "log(Population)") #best

emigain$Population %>% log10() %>% hist(main = "log10(Population)")

emigain$Population %>% sqrt() %>% hist(main = "sqrt(Population)")


#get best lambda , then apply to transformation
emigain$Population %>% BoxCox.lambda(method = "loglik", lower = -3, upper = 3)
[1] 0.05
emigain$Population %>% BoxCox(lambda = 0.05) %>% hist(main = "BoxCox(Population)")


#apply best transformation
emigain$Population.t <- emigain$Population %>% log()

View transformations tot_co2_emi.t and Population.t

emigain %>% head()
NA

Data Reference



LS0tDQp0aXRsZTogIkRhdGEgd3JhbmdsaW5nIG9mIENhcmJvbiBlbWlzc2lvbnMgZGF0YSINCmF1dGhvcjogIktldmluIEt1ZWsgKHMzODM1MTUyKSINCnN1YnRpdGxlOiBNQVRIMjM0OSBEYXRhIFdyYW5nbGluZyBBc3NpZ25tZW50IDINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KDQoNCiMjIFJlcXVpcmVkIHBhY2thZ2VzIA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFfQ0KIyBMb2FkIHJlcXVpcmVkIHBhY2thZ2VzDQoNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoc3RyaW5ncikNCmxpYnJhcnkob3V0bGllcnMpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGZvcmVjYXN0KQ0KDQpgYGANCg0KKipDdXN0b20gZnVuY3Rpb25zKioNCg0KKiBpcy5zcGVjaWFsIHJldHVybnMgVFJVRSBpZiB4IGlzIGVpdGhlciBhbiBpbmZpbml0ZSB2YWx1ZSBvciBub3QgYSBudW1iZXIsIEZBTFNFIG90aGVyd2lzZS4NCiogaXMuc3BlY2lhbG9yTkEgcmV0dXJucyBUUlVFIGlmIHggaXMgZWl0aGVyIGFuIGluZmluaXRlIHZhbHVlLCBub3QgYSBudW1iZXIgb3IgYSBtaXNzaW5nIHZhbHVlLCBGQUxTRSBvdGhlcndpc2UuDQoNCmBgYHtyfQ0KDQppcy5zcGVjaWFsIDwtIGZ1bmN0aW9uKHgpew0KaWYgKGlzLm51bWVyaWMoeCkpIChpcy5pbmZpbml0ZSh4KSB8IGlzLm5hbih4KSkNCn0NCg0KaXMuc3BlY2lhbG9yTkEgPC0gZnVuY3Rpb24oeCl7DQppZiAoaXMubnVtZXJpYyh4KSkgKGlzLmluZmluaXRlKHgpIHwgaXMubmFuKHgpIHwgaXMubmEoeCkpDQp9DQoNCmBgYA0KDQoNCiMjIEV4ZWN1dGl2ZSBTdW1tYXJ5IA0KDQpEYXRhIGZvciBhbmFseXNpcyBvZiBDYXJib24gZW1pc3Npb25zIGZyb20gbmF0aW9ucyBhY3Jvc3MgdGhlIHllYXJzIDE5OTUgdG8gMjAxNiwgYWxvbmcgd2l0aCBuYXRpb25zIHZ1bG5lcmFiaWxpdHkgdG8gY2xpbWF0ZSBjaGFuZ2UsIHdhcyBwcmVwYXJlZC4NCg0KKiAzIGRhdGFzZXRzIGZyb20gdHdvIHNvdXJjZXMgd2VyZSBvYnRhaW5lZCBhbmQgaW1wb3J0ZWQgZm9yIHByZXBhcmF0aW9uOiBFbWlzc2lvbnMgZnJvbSBDRElBQzsgTkRHYWluIChWdWxuZXJhYmlsaXR5KSBhbmQgUG9wdWxhdGlvbiBmcm9tIE5ER0FJLg0KDQoqIFRoZSBjb3VudHJ5IG5hbWVzIGZyb20gdGhlIGRhdGFzZXRzIHdlcmUgY2xlYW5lZCB1cCAvIHN0YW5kYXJkaXNlZCBpbiBwcmVwYXJhdGlvbiBmb3IgdGhlIG1lcmdlIG9mIHNldHMuICBDb3VudHJ5IG5hbWUgaXMgYSBqb2luIGNvbHVtbi4NCg0KKiBTdWJzZXR0aW5nIG9mIGRhdGEgd2FzIGNvbmR1Y3RlZDogT255IHRob3NlIGNvdW50cmllcyB3aXRoIGNvbXBsZXRlIHNldCBvZiBOREdhaW4gaW5kaWNlcyB3ZXJlIGNvbnNpZGVyZWQuICBBbmQgRGF0YSBmb3IgeWVhcnMgMTk5NSB0byAyMDE2IHdlcmUgY29uc2lkZXJlZC4NCg0KKiBEYXRhc2V0cyBmb3IgTkRHYWluIGFuZCBwb3B1bGF0aW9uIHdlcmUgbWFkZSBpbnRvIHRpZHkgZGF0YXNldHMuDQoNCiogQWxsIDMgZGF0YXNldHMgd2VyZSBtZXJnZWQuDQoNCiogVGhlIHJlc3VsdGluZyBkYXRhc2V0IHdhcyBpbnNwZWN0ZWQgdG8gdW5kZXJzdGFuZCB0aGUgc3RydWN0dXJlICwgZGF0YXR5cGVzLCBhbmQgdGhlIG5lY2Vzc2FyeSBjb252ZXJzaW9ucyB0byBmYWN0b3JzLCBudW1lcmljIGRhdGF0eXBlcyB3ZXJlIGNvbmR1Y3RlZC4NCg0KKiBOZXcgdmFyaWFibGUgaW5jbHVkZWQ6IEFsbCBlbWlzc2lvbnMgdG90YWwsIHVzaW5nIHRvdGFsIGNhcmJvbiBlbWlzc2lvbnMgYW5kIGJ1bmtlciBmdWVsIGVtaXNzaW9ucy4NCg0KKiBTY2FubmluZyBhbmQgZGVhbGluZyB3aXRoIG1pc3NpbmcgdmFsdWVzLCBzcGVjaWFsIHZhbHVlcywgZXJyb3JzLg0KDQoqIFNjYW5uaW5nIGFuZCBkZWFsaW5nIHdpdGggb3V0bGllcnMuDQoNCiogVHJhbnNmb3JtYXRpb24gb2YgdG90YWwgY2FyYm9uIGVtaXNzaW9ucyAodG90X2NvMl9lbWkpIGFuZCBwb3B1bGF0aW9uIChQb3B1bGF0aW9uKSBkaXN0cmlidXRpb25zIHRvIG5vcm1hbCBkaXN0cmlidXRpb25zLg0KDQoNCiMjIERhdGEgDQoNCiMjIyBTb3VyY2UgZGVzY3JpcHRpb25zDQoNCioqQ2FyYm9uIGVtaXNzaW9ucyBkYXRhIChuYXRpb24uMTc1MV8yMDE2LmNzdikgZnJvbSBDYXJib24gRGlveGlkZSBJbmZvcm1hdGlvbiBBbmFseXNpcyBDZW50ZXIqKg0KDQpEYXRhc2V0IG9mIGRpZmZlcmVudCBjYXJib24gZW1pc3Npb25zIGJ5IGNvdW50cmllcyBhY3Jvc3MgdGhlIHllYXJzIHdpdGggdGhlIGZvbGxvd2luZyB2YXJpYWJsZXMuDQoNCioqKk5hdGlvbioqKiAtIG5hbWUgb2YgY291bnRyeSB0byB3aGljaCBlbWlzc2lvbnMgcGVydGFpbiB0by4NCg0KKioqWWVhcioqKiAtIHllYXIgaW4gd2hpY2ggZW1pc3Npb25zIG9jY3VycmVkLg0KDQoqKip0b3RfY28yX2VtaSoqKiAtIFRvdGFsIENPMiBlbWlzc2lvbnMgZnJvbSBmb3NzaWwtZnVlbHMgKHNvbGlkLCBsaXF1aWQsIGdhcyxmbGFyaW5nKSBhbmQgY2VtZW50IHByb2R1Y3Rpb24uIEluIHRob3VzYW5kIG1ldHJpYyB0b25zIG9mIEMuDQoNCioqKnNvbGlkX2NvbnMqKiogLSBFbWlzc2lvbnMgZnJvbSBzb2xpZCBmdWVsIGNvbnN1bXB0aW9uLg0KDQoqKipsaXF1aWRfY29ucyoqKiAtIEVtaXNzaW9ucyBmcm9tIGxpcXVpZCBmdWVsIGNvbnN1bXB0aW9uLg0KDQoqKipnYXNfY29ucyoqKiAtIEVtaXNzaW9ucyBmcm9tIGdhcyBmdWVsIGNvbnN1bXB0aW9uLg0KDQoqKipjZW1lbnRfcHJvZCoqKiAtIEVtaXNzaW9ucyBmcm9tIGNlbWVudCBwcm9kdWN0aW9uLg0KDQoqKipnYXNfZmxhcmUqKiogLSBFbWlzc2lvbnMgZnJvbSBnYXMgZmxhcmluZy4NCg0KKioqY2FwX2NvMl9lbWkqKiogLSBQZXIgY2FwaXRhIENPMiBlbWlzc2lvbnMgKG1ldHJpYyB0b25zIG9mIGNhcmJvbikuDQoNCioqKmJ1bmtlcl9jb25zKioqIC0gRW1pc3Npb25zIGZyb20gYnVua2VyIGZ1ZWxzIChub3QgaW5jbHVkZWQgaW4gdGhlIHRvdGFscykuIEVtaXNzaW9ucyBmcm9tIGZ1ZWwgdXNlZCBmb3IgaW50ZXJuYXRpb25hbCBhdmlhdGlvbiBhbmQgbWFyaXRpbWUgdHJhbnNwb3J0LiAgQ29udmVudGlvbiBhbmQgcHJvdG9jb2wgZGljdGF0ZSB0aGVzZSBlbWlzc2lvbnMgYXJlIG5vdCBpbmNsdWRlZCBpbiBuYXRpb25hbCB0b3RhbHMgKHRvdF9jbzJfZW1pKS4NCg0KDQo8YnI+DQoqKk5ER2FpbiBJbmRleCBkYXRhIChnYWluLmNzdikgZnJvbSB0aGUgTm90cmUgRGFtZSBHbG9iYWwgQWRhcHRhdGlvbiBJbml0aWF0aXZlKioNCg0KRGF0YSBzZXQgb2YgTkRHYWluIGluZGV4ICh2dWxuZXJhYmlsaXR5IHRvIGNsaW1hdGUgY2hhbmdlKSBmb3IgZWFjaCBjb3VudHJ5IGFjcm9zcyB0aGUgeWVhcnMsIHdpdGggdGhlIGZvbGxvd2luZyB2YXJpYWJsZXMuDQoNClRoaXMgaW5kZXggaXMgYmFzZWQgb24gbnVtZXJvdXMgKHF1YW50aXRhdGl2ZSkgaW5kaWNhdG9ycyBlZyBlY29ub21pYyBhbmQgZ292ZXJuYW5jZSByZWFkaW5lc3MgdG8gYWRhcHQgdG8gY2hhbmdlICwgYW5kIGV4cG9zdXJlIHRvIG5lZ2F0aXZlIGltcGFjdHMuDQoNClRoZSBzbWFsbGVyIHRoZSBpbmRleCwgdGhlIG1vcmUgdnVsbmVyYWJsZSB0byBjbGltYXRlIGNoYW5nZSBpcyB0aGUgbmF0aW9uLg0KDQoqKipJU08zKioqIC0gMyBjaGFyYWN0ZXIgSVNPIDMxNjYgY29kaW5nIG9mIGNvdW50cnkuDQoNCioqKk5hbWUqKiogLSBOYW1lIG9mIGNvdW50cnkgdG8gd2hpY2ggdGhlIE5ER2FpbiBJbmRleCBwZXJ0YWlucyB0by4NCg0KKioqMTk5NSoqKiAtIE5ER2FpbiBpbmRleCBmb3IgeWVhciAxOTk1Lg0KDQpJbmRpY2VzIGZvciBzdWJzZXF1ZW50IHllYXJzLCB0aHJvdWdoIHRvIDIwMTgsIGFyZSBwcm92aWRlZCBhcyBzZXBlcmF0ZSB2YXJpYWJsZXMuDQoNCg0KPGJyPg0KKipQb3B1bGF0aW9uIGRhdGEgKGlucHV0LmNzdikgZnJvbSB0aGUgTm90cmUgRGFtZSBHbG9iYWwgQWRhcHRhdGlvbiBJbml0aWF0aXZlKioNCg0KRGF0YSBzZXQgb2YgaHVtYW4gcG9wdWxhdGlvbiBmb3IgZWFjaCBjb3VudHJ5IGFjcm9zcyB0aGUgeWVhcnMsIHdpdGggdGhlIGZvbGxvd2luZyB2YXJpYWJsZXMuDQoNCioqKklTTzMqKiogLSAzIGNoYXJhY3RlciBJU08gMzE2NiBjb2Rpbmcgb2YgY291bnRyeS4NCg0KKioqTmFtZSoqKiAtIE5hbWUgb2YgY291bnRyeSB0byB3aGljaCB0aGUgcG9wdWxhdGlvbiBwZXJ0YWlucyB0by4NCg0KKioqMTk5NSoqKiAtIHBvcHVsYXRpb24gZm9yIHllYXIgMTk5NS4NCg0KUG9wdWxhdGlvbiBmb3Igc3Vic2VxdWVudCB5ZWFycywgdGhyb3VnaCB0byAyMDE4LCBhcmUgcHJvdmlkZWQgYXMgc2VwZXJhdGUgdmFyaWFibGVzLg0KDQo8YnI+DQoNCiMjIyBFeHRyYWN0IFN0ZXBzDQpUaGUgdGhyZWUgZGF0YSBzZXRzIGFyZSByZWFkIGluIHZpYSByZWFkcjo6cmVhZF9jc3YgZnVuY3Rpb24uDQoNClRoZSB2YXJpYWJsZXMgZm9yIGNhcmJvbiBlbWlzc2lvbnMgYXJlIG5hbWVkIGFwcHJvcHJpYXRlbHkuICBUaGV5IGFyZSBlYWNoIHRvbyBsb25nIGZvciBhbmFseXNpcy4NCg0KYGBge3J9DQojU291cmNlIGRhdGENCg0KIyBDYXJib24gRGlveGlkZSBJbmZvcm1hdGlvbiBBbmFseXNpcyBDZW50ZXIgYXQgQXBwYWxhY2hpYW4gU3RhdGUgVW5pdmVyc2l0eSwgQm9vbmUgTm9ydGggQ2Fyb2xpbmEsIGh0dHBzOi8vZW5lcmd5LmFwcHN0YXRlL0NESUFDLg0KY19lbWlzc2lvbnMgPC0gcmVhZF9jc3YoIm5hdGlvbi4xNzUxXzIwMTYuY3N2Iiwgc2tpcCA9IDQpDQoNCiMgTm90cmUgRGFtZSBHbG9iYWwgQWRhcHRhdGlvbiBJbml0aWF0aXZlLCBVbml2ZXJzaXR5IG9mIE5vdHJlIERhbWUsICBodHRwczovL2dhaW4ubmQuZWR1L291ci13b3JrL2NvdW50cnktaW5kZXgvcmFua2luZ3MvDQpnYWluIDwtIHJlYWRfY3N2KCJyZXNvdXJjZXNfMjAyMF8wNF8wNV8xOWgwOS9yZXNvdXJjZXMvZ2Fpbi9nYWluLmNzdiIpDQoNCiMgTm90cmUgRGFtZSBHbG9iYWwgQWRhcHRhdGlvbiBJbml0aWF0aXZlLCBVbml2ZXJzaXR5IG9mIE5vdHJlIERhbWUsICBodHRwczovL2dhaW4ubmQuZWR1L291ci13b3JrL2NvdW50cnktaW5kZXgvcmFua2luZ3MvDQojIEdldCBwb3B1bGF0aW9uIGRhdGEgZm9yIGlucHV0aW5nIG1pc3NpbmcgQ08yIGVtaXNzaW9uIHBlciBjYXBpdGEgDQpwb3AgPC0gcmVhZF9jc3YoInJlc291cmNlc18yMDIwXzA0XzA1XzE5aDA5L3Jlc291cmNlcy9pbmRpY2F0b3JzL3BvcC9pbnB1dC5jc3YiKSAlPiUgc2VsZWN0KC0oMikpDQoNCg0KI1JlbmFtaW5nIGVtaXNzaW9uIHZhcmlhYmxlcyBhcHByb3ByaWF0ZWx5DQpuYW1lcyhjX2VtaXNzaW9ucylbbmFtZXMoY19lbWlzc2lvbnMpPT0gIlRvdGFsIENPMiBlbWlzc2lvbnMgZnJvbSBmb3NzaWwtZnVlbHMgYW5kIGNlbWVudCBwcm9kdWN0aW9uICh0aG91c2FuZCBtZXRyaWMgdG9ucyBvZiBDKSJdIDwtICJ0b3RfY28yX2VtaSINCm5hbWVzKGNfZW1pc3Npb25zKVtuYW1lcyhjX2VtaXNzaW9ucyk9PSAiRW1pc3Npb25zIGZyb20gc29saWQgZnVlbCBjb25zdW1wdGlvbiJdIDwtICJzb2xpZF9jb25zIg0KbmFtZXMoY19lbWlzc2lvbnMpW25hbWVzKGNfZW1pc3Npb25zKT09ICJFbWlzc2lvbnMgZnJvbSBsaXF1aWQgZnVlbCBjb25zdW1wdGlvbiJdIDwtICJsaXF1aWRfY29ucyINCm5hbWVzKGNfZW1pc3Npb25zKVtuYW1lcyhjX2VtaXNzaW9ucyk9PSAiRW1pc3Npb25zIGZyb20gZ2FzIGZ1ZWwgY29uc3VtcHRpb24iXSA8LSAiZ2FzX2NvbnMiDQpuYW1lcyhjX2VtaXNzaW9ucylbbmFtZXMoY19lbWlzc2lvbnMpPT0gIkVtaXNzaW9ucyBmcm9tIGNlbWVudCBwcm9kdWN0aW9uIl0gPC0gImNlbWVudF9wcm9kIg0KbmFtZXMoY19lbWlzc2lvbnMpW25hbWVzKGNfZW1pc3Npb25zKT09ICJFbWlzc2lvbnMgZnJvbSBnYXMgZmxhcmluZyJdIDwtICJnYXNfZmxhcmUiDQpuYW1lcyhjX2VtaXNzaW9ucylbbmFtZXMoY19lbWlzc2lvbnMpPT0gIlBlciBjYXBpdGEgQ08yIGVtaXNzaW9ucyAobWV0cmljIHRvbnMgb2YgY2FyYm9uKSJdIDwtICJjYXBfY28yX2VtaSINCm5hbWVzKGNfZW1pc3Npb25zKVtuYW1lcyhjX2VtaXNzaW9ucyk9PSAiRW1pc3Npb25zIGZyb20gYnVua2VyIGZ1ZWxzIChub3QgaW5jbHVkZWQgaW4gdGhlIHRvdGFscykiXSA8LSAiYnVua2VyX2NvbnMiDQoNCiNTYW1wbGUgZW1pc3Npb25zIGRhdGENCmNfZW1pc3Npb25zICU+JSBoZWFkKCkNCg0KI1NhbXBsZSBOREdhaW4gZGF0YQ0KZ2FpbiAlPiUgaGVhZCgpDQoNCiNTYW1wbGUgcG9wdWxhdGlvbiBkYXRhDQpwb3AgJT4lIGhlYWQoKQ0KDQpgYGANCg0KIyMjIEV4dHJhY3QgU3RlcHMgKGNvbnRpbnVlZCkNCg0KQ2xlYW4gdXAgYW5kIHN0YW5kYXJkaXNlIGpvaW4gY29sdW1uIE5hdGlvbi9OYW1lIGluIGJvdGggc291cmNlIGRhdGEgc2V0cyBjX2VtaXNzaW9ucyBhbmQgZ2Fpbg0KDQoqIENhcGl0YWxpc2UNCiogU3RhbmRhcmRpc2UgZWcuICdBTkQnIHRvICcmJywgc2hvcnRlbmluZyBvZiBuYW1lIGV0Yy4NCg0KYGBge3J9DQojIENsZWFuIHVwIC8gc3RhbmRhcmRpc2Ugam9pbiBjb2x1bW4gTmF0aW9uDQpjX2VtaV9uYXRpb24gPC0gY19lbWlzc2lvbnMgJT4lIA0KICBtdXRhdGUoDQogICAgTmF0aW9uID0gc3RyX3JlcGxhY2VfYWxsKE5hdGlvbiwgIGMoIiBBTkQgIiA9ICIgJiAiLCAiIFxcKC4qXFwpIiA9ICIiLCAiVU5JVEVEIFNUQVRFUyBPRiBBTUVSSUNBIiA9ICJVTklURUQgU1RBVEVTIiwgIkRFTU9DUkFUSUMgUkVQVUJMSUMgT0YgVEhFIENPTkdPIiA9ICJaQUlSRSIsIkNPVEUgRCBJVk9JUkUiID0gIkNPVEUgRCdJVk9JUkUiLCAiQlJVTkVJIERBUlVTU0FMQU0iPSAiQlJVTkVJIiwgIlJFUFVCTElDIE9GICIgPSAiIiwgIklTTEFNSUMgSVJBTiIgPSAiSVJBTiIsICJVTklURUQgVEFOWkFOSUEiID0gIlRBTlpBTklBIiwgIkxBTyBQRU9QTEUgUyBERU1PQ1JBVElDIFJFUFVCTElDIiA9ICJMQU8gUEVPUExFJ1MgREVNT0NSQVRJQyBSRVBVQkxJQyIsICJQTFVSSU5BVElPTkFMIFNUQVRFIE9GIEJPTElWSUEiID0gIkJPTElWSUEiLCAiR1VJTkVBIEJJU1NBVSIgPSAiR1VJTkVBLUJJU1NBVSIsICJSVVNTSUFOIEZFREVSQVRJT04iID0gIlJVU1NJQSIpKQ0KICApDQoNCiMgY2xlYW4gam9pbiBjb2x1bW4NCmdhaW5fbmF0aW9uIDwtIGdhaW4gJT4lDQogICAgICAgICAgICAgIG11dGF0ZSgNCiAgICAgICAgICAgICAgICBOYW1lID0gdG91cHBlcihOYW1lKSAlPiUgc3RyX3JlcGxhY2VfYWxsKGMoIiBBTkQgIiA9ICIgJiAiLCIsIFJFUFVCTElDIE9GIiA9ICIiLCAiLCBCT0xJVkFSSUFOIFJFUFVCTElDIE8iID0gIiIsICJCUlVORUkgREFSVVNTQUxBTSI9ICJCUlVORUkiLCAiLCBVTklURUQgUkVQVUJMSUMgT0YiID0gIiIsICIsIElTTEFNSUMgUkVQVUJMSUMgT0YiID0gIiIsICJDT05HTywgVEhFIERFTU9DUkFUSUMgUkVQVUJMSUMgTyIgPSAiWkFJUkUiLCAiLCBQTFVSSU5BVElPTkFMIFNUQVRFIE9GIiA9ICIiLCAiUlVTU0lBTiBGRURFUkFUSU9OIiA9ICJSVVNTSUEiKSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgKQ0KDQpgYGANCg0KKipTdWJzZXR0aW5nKioNCg0KKiBPbmx5IHRob3NlIHJlY29yZHMgZnJvbSBnYWluKGdhaW5fbmF0aW9uKSB0aGF0IGhhdmUgbm8gbWlzc2luZyB2YWx1ZXMgKGNvbXBsZXRlIGNhc2VzKSB3aWxsIGJlIGNvbnNpZGVyZWQuICBBbGwgaW5jb21wbGV0ZSBjYXNlcyBoYXZlIG5vIE5ER2FpbiBpbmRleCBmb3IgYW55IHllYXIuDQoqIFN1YnNldCBOREdhaW5zIDE5OTUgLSAyMDE2LiAgRW1pc3Npb25zIGRhdGFzZXQgZ28gYXMgZmFyIGFzIDIwMTYuDQoNCmBgYHtyfQ0KIyBTY2FuIGZvciBpbmNvbXBsZXRlIGNhc2VzDQpnYWluX25vdGNvbXBsZXRlIDwtIGdhaW5fbmF0aW9uWyFjb21wbGV0ZS5jYXNlcyhnYWluX25hdGlvbiksXQ0KDQojIEFsbCBpbmNvbXBsZXRlIGNhc2VzIGhhdmUgbm8gaW5kZXggZm9yIGFueSB5ZWFyDQpnYWluX25vdGNvbXBsZXRlICU+JSBoZWFkKCkNCg0KIyBTdWJzZXQgZ2FpbiBkYXRhIHRvIDE5OTUgLSAyMDE2DQpnYWluX25hdGlvbiA8LSBnYWluX25hdGlvbltjb21wbGV0ZS5jYXNlcyhnYWluX25hdGlvbiksXSAlPiUgc2VsZWN0KDE6MjQpDQoNCmBgYA0KDQojIwlUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIEkgDQoNClRoZSBOREdhaW4gZGF0YXNldCAoZ2FpbikgaXMgbm90IHRpZHkgYXMgaXQgaGFzIHZhbHVlcyBmb3IgdmFyaWFibGUgeWVhciBhcyBjb2x1bW4gbmFtZXMgKDE5OTUsIDE5OTYgLi4uKS4gQW5kIHRoZSBvYnNlcnZhdGlvbnMgZm9yIGVhY2ggeWVhciBhcmUgb24gb25lIHJvdy4gIFRoZSB5ZWFyIG5lZWRzIHRvIGJlIGFsb25nIGEgY29sdW1uICwgYW5kIGVhY2ggb2JzZXJ2YXRpb24gb24gYSBzZXBlcmF0ZSByb3cuDQoNClRoZSBzYW1lIGFwcGxpZXMgdG8gdGhlIHBvcHVsYXRpb24gZGF0YXNldCAocG9wKTogdmFsdWVzIGZvciB2YXJpYWJsZSB5ZWFyIGFzIGNvbHVtbiBuYW1lcyAoMTk5NSwgMTk5NiAuLi4pLiBBbmQgdGhlIG9ic2VydmF0aW9ucyBmb3IgZWFjaCB5ZWFyIGFyZSBvbiBvbmUgcm93LiAgVGhlIHllYXIgbmVlZHMgdG8gYmUgYWxvbmcgYSBjb2x1bW4gLCBhbmQgZWFjaCBvYnNlcnZhdGlvbiBvbiBhIHNlcGVyYXRlIHJvdy4NCg0KVG8gbWFrZSB0aGUgZGF0YXNldHMgdGlkeSB0aGUgZm9sbG93aW5nIHN0ZXBzIGFyZSBjb25kdWN0ZWQuDQoNCiogTWFrZSB0aGUgZGF0YSBzZXQgbG9uZ2VyIHVzaW5nIHBpdm90X2xvbmdlcigpIHdoZXJlIHRoZSB5ZWFycyAxOTk1LCAxOTk2IGV0YyBhcmUgbW92ZWQgdG8gY29sdW1uICJZZWFyIiwgYW5kIHRoZSB2YWx1ZXMgdG8gY29sdW1uICJOREdhaW4iIGZvciBnYWluICwgIlBvcHVsYXRpb24iIGZvciBwb3B1bGF0aW9uLg0KDQpgYGB7cn0NCiNNYWtlIGdhaW4gZGF0YXNldCB0aWR5DQpnYWluX3RpZHkgPC0gZ2Fpbl9uYXRpb24gJT4lIHBpdm90X2xvbmdlcihjb2xzID0gLSgxOjIpLCBuYW1lc190byA9ICJZZWFyIiwgIHZhbHVlc190byA9ICJOREdhaW4iKQ0KI0NvbnZlcnQgWWVhciB0byBpbnRlZ2VyDQpnYWluX3RpZHkkWWVhciA8LSBhcy5pbnRlZ2VyKGdhaW5fdGlkeSRZZWFyKQ0KDQojTWFrZSBwb3B1bGF0aW9uIGRhdGFzZXQgdGlkeQ0KcG9wX3RpZHkgPC0gcG9wICU+JSBwaXZvdF9sb25nZXIoY29scyA9IC0oMSksIG5hbWVzX3RvID0gIlllYXIiLCAgdmFsdWVzX3RvID0gIlBvcHVsYXRpb24iKQ0KI0NvbnZlcnQgWWVhciB0byBpbnRlZ2VyDQpwb3BfdGlkeSRZZWFyIDwtIGFzLmludGVnZXIocG9wX3RpZHkkWWVhcikNCg0KIyBTaG93IHRpZHkgZ2FpbiBkYXRhc2V0DQpoZWFkKGdhaW5fdGlkeSkNCg0KIyBTaG93IHRpZHkgcG9wdWxhdGlvbiBkYXRhc2V0DQpoZWFkKHBvcF90aWR5KQ0KYGBgDQoNCiMjIyBNZXJnZSBkYXRhIHNldHMNClRoZSBnYWluIGFuZCBwb3B1bGF0aW9uIGRhdGEgc2V0cyBhcmUgdGhlbiBtZXJnZWQgdG9nZXRoZXIgKGdhaW5fdGlkeSkgYnkgSVNPMyBhbmQgWWVhci4NCg0KVGhlIGZpbmFsIGRhdGFzZXQgKGVtaWdhaW4pIGlzIHRoZSByZXN1bHQgb2YgdGhlIG1lcmdlIG9mIHRoZSB0aWR5IGdhaW4gZGF0YXNldChnYWluX3RpZHkpIGFuZCBlbWlzc2lvbnMgZGF0YXNldChjX2VtaV9uYXRpb24pIGJ5IE5hdGlvbi9OYW1lIGFuZCBZZWFyLg0KYGBge3J9DQojbGVmdCBqb2luIGdhaW4gYW5kIHBvcHVsYXRpb24gc2V0cyB0b2dldGhlciBvbiBJU08zIGFuZCBZZWFyDQpnYWluX3RpZHkgPC0gZ2Fpbl90aWR5ICU+JSBsZWZ0X2pvaW4ocG9wX3RpZHksIGJ5ID0gYygiSVNPMyIgPSAiSVNPMyIsICJZZWFyIiA9ICJZZWFyIikpDQoNCiNtZXJnZSBnYWluIGFuZCBlbWlzc2lvbnMgZGF0YXNldHMgdG9nZXRoZXINCmVtaWdhaW4gPC0gZ2Fpbl90aWR5ICU+JSBpbm5lcl9qb2luKGNfZW1pX25hdGlvbiAsIGJ5ID0gYygiTmFtZSIgPSAiTmF0aW9uIiwgIlllYXIiID0gIlllYXIiKSApDQoNCmBgYA0KDQoNCiMjIFVuZGVyc3RhbmQgDQoNClRoZSAqKiplbWlnYWluKioqIGRhdGFzZXQgaXMgYSBkYXRhZnJhbWUgb2YgZGltZW5zaW9uIDM4ODcgeCAxMyAoMTMgdmFyaWFibGVzLCAzODg3IG9ic2VydmF0aW9ucykuDQoNClZhcmlhYmxlcywgdGhlaXIgZGF0YSB0eXBlIGFuZCBhbnkgdHlwZSBjb252ZXJzaW9ucyBhcmUgYXMgZm9sbG93cy4NCg0KKiAqSVNPMyo6IGNoYXJhY3RlciBkYXRhdHlwZS4gV2lsbCBiZSBjb252ZXJ0ZWQgdG8gZmFjdG9yLiAgQ291bnRyeSBpcyBjYXRlZ29yaWNhbC4NCiogKk5hbWUqOiBjaGFyYWN0ZXIgZGF0YXR5cGUuIFdpbGwgYmUgY29udmVydGVkIHRvIGZhY3Rvci4gIENvdW50cnkgaXMgY2F0ZWdvcmljYWwuDQoqICpZZWFyKjogbnVtZXJpYyBkYXRhdHlwZS4gV2lsbCBiZSBjb252ZXJ0ZWQgdG8gb3JkZXJlZCBmYWN0b3IuICBZZWFyIGlzIG9yZGluYWwuDQoqICpOREdhaW4qOiBudW1lcmljIGRhdGF0eXBlLiBObyBjb252ZXJzaW9uLg0KKiAqUG9wdWxhdGlvbio6IG51bWVyaWMgZGF0YXR5cGUuIE5vIGNvbnZlcnNpb24uDQoqICp0b3RfY28yX2VtaSo6IG51bWVyaWMgZGF0YXR5cGUuIE5vIGNvbnZlcnNpb24uDQoqICpzb2xpZF9jb25zKjogbnVtZXJpYyBkYXRhdHlwZS4gTm8gY29udmVyc2lvbi4NCiogKmxpcXVpZF9jb25zKjogbnVtZXJpYyBkYXRhdHlwZS4gTm8gY29udmVyc2lvbi4NCiogKmdhc19jb25zKjogbnVtZXJpYyBkYXRhdHlwZS4gTm8gY29udmVyc2lvbi4NCiogKmNlbWVudF9wcm9kKjogbnVtZXJpYyBkYXRhdHlwZS4gTm8gY29udmVyc2lvbi4NCiogKmdhc19mbGFyZSo6IGNoYXJhY3RlciBkYXRhdHlwZS4gV2lsbCBiZSBjb252ZXJ0ZWQgdG8gbnVtZXJpYyhkb3VibGUpIGRhdGF0eXBlLiAgVGhpcyBpcyBhbiBlbWlzc2lvbnMgdmFyaWFibGUgc28gY29udGludW91cy9yYXRpb25hbC4NCiogKmNhcF9jbzJfZW1pKjogY2hhcmFjdGVyIGRhdGF0eXBlLiBXaWxsIGJlIGNvbnZlcnRlZCB0byBudW1lcmljKGRvdWJsZSkgZGF0YXR5cGUuICBUaGlzIGlzIGFuIGVtaXNzaW9ucyB2YXJpYWJsZSBzbyBjb250aW51b3VzL3JhdGlvbmFsLg0KKiAqYnVua2VyX2NvbnMqOiBudW1lcmljIGRhdGF0eXBlLiBObyBjb252ZXJzaW9uLg0KDQpgYGB7cn0NCiMgVW5kZXJzdGFuZCB0aGUgZGF0YSBhbmQgc3RydWN0dXJlDQplbWlnYWluICU+JSBzdHIoKQ0KDQpgYGANCg0KPGJyPg0KDQpUaGUgY29udmVyc2lvbiB0byBmYWN0b3IgaXMgZG9uZSB2aWEgdGhlIGZhY3RvcigpIGZ1bmN0aW9uLiAgTm8gbGFiZWxsaW5nIGlzIHJlcXVpcmVkIHRoaXMgdGltZS4NCg0KRm9yIHRoZSBvcmRlcmVkIGZhY3RvciAoWWVhciksIHRoZSBmYWN0b3IoKSBmdW5jdGlvbiBpcyB1c2VkIGFsb25nIHdpdGggcGFyYW1ldGVycyAqbGV2ZWxzID0gW3ZlY3RvciBvZiBvcmRlcmVkIHllYXJzXSAqIGFuZCAqb3JkZXJlZD1UUlVFKi4NCg0KVGhlIGNvbnZlcnNpb24gb2YgdGhlIHR3byBlbWlzc2lvbnMgKCpnYXNfZmxhcmUqLCAqY2FwX2NvMl9lbWkqKSBmcm9tIGNoYXJhY3RlciB0byBudW1lcmljIGRvdWJsZSBpcyBjb21wbGV0ZWQgdXNpbmcgdGhlIGNvbnZlcnNpb24gZnVuY3Rpb24gYXMuZG91YmxlKCkuDQoNCmBgYHtyfQ0KI0lTTzMgYXMgZmFjdG9yDQplbWlnYWluJElTTzMgPC0gZW1pZ2FpbiRJU08zICU+JSBmYWN0b3IoKQ0KDQojTmFtZSBhcyBmYWN0b3INCmVtaWdhaW4kTmFtZSA8LSBlbWlnYWluJE5hbWUgJT4lIGZhY3RvcigpDQoNCiNOYW1lIGFzIGZhY3Rvcg0KZW1pZ2FpbiROYW1lIDwtIGVtaWdhaW4kTmFtZSAlPiUgZmFjdG9yKCkNCg0KI1llYXIgYXMgb3JkZXIgZmFjdG9yDQojZW1pZ2FpbiRZZWFyICU+JSB1bmlxdWUoKSANCg0KZW1pZ2FpbiRZZWFyIDwtIGVtaWdhaW4kWWVhciAlPiUgZmFjdG9yKGxldmVscyA9IGMoMTk5NSwgMTk5NiwgMTk5NywgMTk5OCwgMTk5OSwgMjAwMCwgMjAwMSwgMjAwMiwgMjAwMywgMjAwNCwgMjAwNSwgMjAwNiwgMjAwNywgMjAwOCwgMjAwOSwgMjAxMCwgMjAxMSwgMjAxMiwgMjAxMywgMjAxNCwgMjAxNSwgMjAxNiksIG9yZGVyZWQgPSBUUlVFKQ0KDQojZ2FzX2ZsYXJlICYgY2FwX2NvMl9lbWkNCmVtaWdhaW4kZ2FzX2ZsYXJlIDwtIGVtaWdhaW4kZ2FzX2ZsYXJlICU+JSBhcy5kb3VibGUoKQ0KZW1pZ2FpbiRjYXBfY28yX2VtaSA8LSBlbWlnYWluJGNhcF9jbzJfZW1pICU+JSBhcy5kb3VibGUoKQ0KDQpgYGANCg0KPGJyPg0KQWZ0ZXIgdGhlIG5lY2Vzc2FyeSBjb252ZXJzaW9ucywgaW5zcGVjdGluZyB0aGUgcmVzdWx0aW5nIGRhdGEgdHlwZXMgYmVsb3cgc2hvdyB0aGUgMyBmYWN0b3JzLCBvbmUgb3JkZXJlZCwgYW5kIGFsbCBlbWlzc2lvbiB2YXJpYWJsZXMgYXJlIG51bWVyaWMuDQpgYGB7cn0NCmVtaWdhaW4gJT4lIHN0cigpDQoNCmBgYA0KDQoNCiMjCVRpZHkgJiBNYW5pcHVsYXRlIERhdGEgSUkgDQoNCkFkZGl0aW9uIG9mIHZhcmlhYmxlICoqKmFsbF9jbzJfZW1pKioqDQoNCiogVGhpcyB2YXJpYWJsZSBpcyB0aGUgdG90YWwgb2YgQUxMIGVtaXNzaW9ucywgaW5jbHVkaW5nIHRob3NlIGZyb20gYnVua2VyKGludGVybmF0aW9uYWwgYXZpYXRpb24gYW5kIG1hcml0aW1lKSBmdWVsLiAgDQoNCiogTG9uZyBzdGFuZGluZyBjb252ZW50aW9uL3Byb3RvY29sIHN0YXRlcyB0aGF0IGJ1bmtlciBlbWlzc2lvbnMgYXJlIGV4Y2x1ZGVkIGZyb20gbmF0aW9uIHJlcG9ydGluZy4gSGlzdG9yaWNhbGx5IGhhcmQgdG8gYXR0cmlidXRlIHRvIGNvdW50cnkuICBTb3VyY2UgY291bnRyeT8gRGVzaW50YXRpb24/IGV0Yy4NCg0KKiBJdCdzIGhhbmR5IHRvIGhhdmUgdGhpcyB2YXJpYWJsZSBhcyBpdCBnaXZlcyBhIGJldHRlciBwaWN0dXJlIG9mIGVtaXNzaW9ucy4gV2h5IGV4Y2x1ZGUgYW5vdGhlciBzb3VyY2Ugb2YgY2FyYm9uIGVtaXNzaW9ucz8NCg0KKiBBcyB0b3RhbCBlbWlzc2lvbnMgKHRvdF9jbzJfZW1pKSBpcyBwcm92aWRlZCwgYWRkIGJ1bmtlciBlbWlzc2lvbnMgdG8gdGhpcy4NCg0KKiBhbGxfY28yX2VtaSA9IHRvdF9jbzJfZW1pICsgYnVua2VyX2NvbnMNCg0KVGhlIHZhcmlhYmxlIGlzIGluY2x1ZWQgaW4gdGhlIGVtaWdhaW4gZGF0YXNldCB2aWEgdGhlIG11dGF0ZSBmdW5jdGlvbiwgd2hlcmUgaXQgaXMgZGVyaXZlZCB1c2luZyB0aGUgaW5kaWNhdGVkIGZvcm11bGEuDQoNCmBgYHtyfQ0KI0FkZCBhbGxfY28yX2VtaSB2YXJpYWJsZSAtIHRvdGFsIGNvMiBlbWlzc2lvbnMgKyBidW5rZXIgZW1pc3Npb25zLg0KDQplbWlnYWluIDwtIGVtaWdhaW4gJT4lIG11dGF0ZSgNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbF9jbzJfZW1pID0gdG90X2NvMl9lbWkgKyBidW5rZXJfY29ucyAgDQogICAgICAgICAgICAgICAgICAgICAgKQ0KDQojSW5zcGVjdCB2YXJpYWJsZSBzdHJ1Y3R1cmUNCmVtaWdhaW4kYWxsX2NvMl9lbWkgJT4lIHN0cigpDQpgYGANCg0KIyMJU2NhbiBJIA0KDQojIyMgU2Nhbm5pbmcgYW5kIGRlYWxpbmcgd2l0aCBtaXNzaW5nIHZhbHVlcywgc3BlY2lhbCB2YWx1ZXMsIGVycm9ycw0KDQoqIE1pc3NpbmcgdmFsdWVzIGVpdGhlciB0aHJvdWdoIG1lcmdpbmcgb2YgZGF0YXNldHMgKFBvcHVsYXRpb24pIG9yIGFzIGxpdGVyYWxzICcuJyAsICcuLicgd2VyZSBzdGFuZGFyZGlzZWQgdG8gUidzIE5BLiAgDQoNCiogKmdhc19mbGFyZSovKmNhcF9jbzJfZW1pKiBjb252ZXJzaW9uIHRvIG51bWVyaWMgY29lcmNlZCB0aGUgJy4nLycuLicgdG8gTkEuDQoNCiogQ29tcGxldGUgY2FzZXMgaW4gZW1pZ2FpbiwgYWNyb3NzIG51bWVyaWMgdmFyaWFibGVzICg0OjE0KSwgd2VyZSBleGFtaW5lZC4gSVNPMy9OYW1lL1llYXIgKDE6Mykgd2VyZSBpZ25vcmVkIGFzIHRoZXkgYXJlIGpvaW4gY29sdW1ucy4NCg0KKiBDb2x1bW4gY291bnRzIG9mIG1pc3NpbmcgdmFsdWVzIHJldmVhbCB0aGF0IG1pc3NpbmcgdmFsdWVzIGFyZSBjb25maW5lZCB0byAqUG9wdWxhdGlvbiogYW5kICpjYXBfY28yX2VtaSouDQoNCiogVmVyaWZ5aW5nIHRoZSByZWNvcmRzIHdoZXJlIHRoZXJlIGFyZSBtaXNzaW5nIHZhbHVlcyBmb3IgZWl0aGVyICpQb3B1bGF0aW9uKiBvciAqY2FwX2NvMl9lbWkqLCBzaG93IHRoYXQgdGhleSBjYW4gZWFzaWx5IGJlIGltcHV0ZWQuDQoNCiogSW1wdXRlIHVzaW5nIGZvcm11bGEgJ2NhcmJvbiBlbWlzc2lvbiBwZXIgY2FwaXRhJyA9ICd0b3RhbCBjYXJib24gZW1pc3Npb24nIHggMTAwMCAvIHBvcHVsYXRpb24NCg0KPiAqY2FwX2NvMl9lbWkqID0gKnRvdF9jbzJfZW1pKiB4IDEwMDAgLyAqUG9wdWxhdGlvbioNCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KdCA8LSBlbWlnYWluDQoNCmBgYA0KDQo8YnI+DQoNCiMjIyBTY2FuIGZvciBtaXNzaW5nIHZhbHVlcw0KDQpTdW1tYXJ5IG9mIG1pc3NpbmcgdmFsdWVzIHNob3cNCg0KKiAyMiBtaXNzaW5nIGluIFBvcHVsYXRpb24NCg0KKiAxNyBtaXNzaW5nIGluIGNhcF9jbzJfZW1pIA0KYGBge3J9DQojR2V0IGluY29tcGxldGUgY2FzZXMgdG8gY2hlY2sgYWdhaW5zdCBwb3N0IGltcHV0ZQ0KZW1pZ2Fpbl9ub3RjMiA8LSBlbWlnYWluWyFjb21wbGV0ZS5jYXNlcyhlbWlnYWluWywgNDoxNF0pLF0NCg0KI1NjYW4gZm9yIE5BcyBpbiBkYXRhIHNldA0KY29sU3Vtcyhpcy5uYShlbWlnYWluKSkNCg0KYGBgDQoNClNob3cgc2FtcGxlcyBvZiByZWNvcmRzIHdpdGggbWlzc2luZyB2YWx1ZXMNCmBgYHtyfQ0KI0NoZWNrIFBvcHVsYXRpb24gTkFzDQplbWlnYWluW2lzLm5hKGVtaWdhaW4kUG9wdWxhdGlvbiksXSAgJT4lIGhlYWQoNSkNCg0KI0NoZWNrIGNhcF9jbzJfZW1pIE5Bcw0KZW1pZ2Fpbltpcy5uYShlbWlnYWluJGNhcF9jbzJfZW1pKSxdICU+JSBoZWFkKDUpDQoNCmBgYA0KDQojIyMgSW1wdXRlIG1pc3NpbmcgdmFsdWVzDQoNCiogSW1wdXRlIG1pc3NpbmcgcG9wdWxhdGlvbiBhbmQgcGVyIGNhcGl0YSBlbWlzc2lvbiBiYXNlZCBvbiBmb3JtdWxhIGFib3ZlLg0KDQoqIENoZWNraW5nIGltcHV0YXRpb24gYnkgbG9va2luZyB1cCByZXN1bHRzIGFnYWluc3QgaW5jb21wbGV0ZSBjYXNlIGRhdGFzZXQgKGVtaWdhaW5fbm90YzIpIHNob3cgdGhhdCB0aGUgaW1wdXRhdGlvbnMgYXJlIGNvcnJlY3QuDQoNCmBgYHtyfQ0KI0ltcHV0ZSBtaXNzaW5nIHBvcHVsYXRpb24NCmVtaWdhaW4kUG9wdWxhdGlvbltpcy5uYShlbWlnYWluJFBvcHVsYXRpb24pXSA8LSBlbWlnYWluJHRvdF9jbzJfZW1pW2lzLm5hKGVtaWdhaW4kUG9wdWxhdGlvbildICogMTAwMCAvICBlbWlnYWluJGNhcF9jbzJfZW1pW2lzLm5hKGVtaWdhaW4kUG9wdWxhdGlvbildDQoNCiNJbXB1dGUgbWlzc2luZyBwZXIgY2FwaXRhIGVtaXNzaW9uDQplbWlnYWluJGNhcF9jbzJfZW1pW2lzLm5hKGVtaWdhaW4kY2FwX2NvMl9lbWkpXSA8LSByb3VuZChlbWlnYWluJHRvdF9jbzJfZW1pW2lzLm5hKGVtaWdhaW4kY2FwX2NvMl9lbWkpXSAqIDEwMDAvICBlbWlnYWluJFBvcHVsYXRpb25baXMubmEoZW1pZ2FpbiRjYXBfY28yX2VtaSldLCAyKQ0KDQojQ2hlY2sgaW1wdXRhdGlvbnMNCmVtaWdhaW5fbm90YzIgJT4lIGlubmVyX2pvaW4oc2VsZWN0KGVtaWdhaW4sIFllYXIsIE5hbWUsIFBvcHVsYXRpb24sIGNhcF9jbzJfZW1pKSwgYnkgPSBjKCJZZWFyIiwgIk5hbWUiKSkNCg0KYGBgDQoNCiMjIyBTY2FuIGZvciBzcGVjaWFsIHZhbHVlcyBhbmQgZXJyb3JzDQoNCiogU3BlY2lhbCB2YWx1ZXMgKE5hTiAsIEluZikgaW4gZW1pZ2FpbiBhcmUgc2Nhbm5lZCBmb3IsIHJldmVhbGluZyBub25lLiAgVmlhIGFwcGx5aW5nIHRoZSBpcy5zcGVjaWFsKCkgZnVuY3Rpb24gYWNyb3NzIHRoZSBjb2x1bW5zLg0KDQoqIEVycm9ycyAobmVnYXRpdmUgZW1pc3Npb25zLCBub24gcG9zaXRpdmUgTkRHYWluL1BvcHVsYXRpb24pIGFyZSBzY2FubmVkIGZvciwgcmV2ZWFsaW5nIG5vbmUuICBWaWEgYXBwbHlpbmcgY29tcGFyaXNvbiBvcGVyYXRvcnMgYWdhaW5zdCByZWxldmFudCBzdWJzZXRzLg0KYGBge3J9DQojQ2hlY2sgZm9yIHNwZWNpYWwgdmFsdWVzDQpzYXBwbHkoZW1pZ2FpbiwgZnVuY3Rpb24oeCkgc3VtKGlzLnNwZWNpYWwoeCkpKQ0KDQojQ2hlY2sgZm9yIG5lZ2F0aXZlIGVtaXNzaW9ucw0KY29sU3VtcyhlbWlnYWluWywgLSgxOjUpXSA8IDAsIG5hLnJtID0gVFJVRSkNCg0KI0NoZWNrIGZvciBub24gcG9zaXRpdmUgTkRHYWluIG9yIFBvcHVsYXRpb24NCmNvbFN1bXMoZW1pZ2FpblssICg0OjUpXSA8IDAsIG5hLnJtID0gVFJVRSkNCmBgYA0KDQpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KZW1pZ2FpbltlbWlnYWluJElTTzMgJWluJSBjKCdTRE4nLCAnTUtEJyksIF0NCnNldGRpZmYodCwgZW1pZ2FpbikNCg0KI2xpYnJhcnkoZGVkdWN0aXZlKQ0KI2xpYnJhcnkodmFsaWRhdGUpDQojIHRlc3RpbmcgYW5vdGhlciBpbXB1dGUgbWV0aG9kIHRoYXQgZG9lc250IHdvcmsNCnJ1bGVzIDwtIHZhbGlkYXRvcihjYXAgPSB0b3RfY28yX2VtaSAqIDEwMDAvIHBvcHVsYXRpb24gID09IGNhcF9jbzJfZW1pICkNCnJ1bGVzDQojIFVzZSBpbXB1dGVfbHIgZnVuY3Rpb24NCg0KaW1wdXRlZF9kZiA8LSBpbXB1dGVfbHIoZW1pZ2FpbixydWxlcykNCg0KaW1wdXRlZF9kZltpbXB1dGVkX2RmJElTTzMgJWluJSBjKCdNS0QnLCAnU0ROJyksXQ0KDQoNCmBgYA0KDQojIwlTY2FuIElJDQoNCiMjIyBBcHByb2FjaCAmIFN1bW1hcnkNCg0KKiBVbml2YXJpYXRlIG91dGxpZXIgZGV0ZWN0aW9uIGlzIHVzZWQgb24gZWFjaCBOREdhaW4gLCBQb3B1bGF0aW9uIGFuZCB0aGUgOSBlbWlzc2lvbiB2YXJpYWJsZXMuDQoNCiogVGhpcyB3YXMgZGVjaWRlZCBhcyB0aGUgZW1pc3Npb25zIGRvbid0IHNoYXJlIHNwZWNpYWwgcmVsYXRpb25zaGlwcyB3aXRoIGVhY2ggb3RoZXIgYW5kIGFsbCB0aGUgdmFyaWFibGVzIGNhbiBiZSB0cmVhdGVkIGluZGl2aWR1YWxseS4NCg0KKiB6LXNjb3JlcyBhcmUgYXBwbGllZCBhY3Jvc3MgZWFjaCB2YXJpYWJsZS4gIE91dGxpZXJzIGFyZSBmbGFnZ2VkIGFzIHRob3NlIHZhbHVlcyB3aXRoIHx6LXNjb3JlfCA+IDMuDQoNCiogKk5ER2FpbiogaGFzIG5vIG91dGxpZXJzIGZsYWdnZWQuICBUaGUgb3RoZXIgdmFyaWFibGVzIGVnLiAqUG9wdWxhdGlvbiogKDQ0IGZsYWdlZCkgLCAqdG90X2NvMl9lbWkqICg0NykgZG8gaGF2ZSBvdXRsaWVycyBmbGFnZ2VkLg0KDQoqIEZ1cnRoZXIgaW5zcGVjdGlvbiBzaG93cyB0aGF0IHRoZSBwb3B1bGF0aW9uIGZvciBDaGluYSBhbmQgSW5kaWEgYXJlIGluZGVlZCB2YWxpZCB2YWx1ZXMuDQoNCiogTGlrZXdpc2UsIHRvdGFsIGVtaXNzaW9uIGFuZCBvdGhlciBlbWlzc2lvbnMgZnJvbSBDaGluYSwgSW5kaWEgYW5kIFVTQSBhcmUgbGVnaXRpbWF0ZSB2YWx1ZXMuDQoNCiogVGhlIGRpc3RyaWJ1dGlvbiBmb3IgdGhlc2UgdmFyaWFibGVzIGFib3ZlIGFyZSBleHRyZW1lbHkgcG9zaXRpdmVseSBza2V3ZWQuICBUaGVzZSAib3V0bGllcnMiIGFyZSBzbyBmYXIgZnJvbSB0aGUgbmV4dCBzZXQgb2Ygb2JzZXJ2YXRpb25zIGluIHRoZSBzYW1lIHF1YXJ0aWxlLg0KDQoqIFRoZXJlZm9yZSB0aGUgc3VnZ2VzdGVkIG91dGxpZXJzIHdpbGwgYmUgbGVmdCBhbG9uZSAtIG5vIHRyYW5zZm9ybWF0aW9uIG5vciBpbXB1dGF0aW9uLg0KDQpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShNVk4pDQoNCmVtaWdhaW5fc3ViIDwtIGVtaWdhaW5bLCAtKDE6NSldDQoNCnJlc3VsdHMgPC0gbXZuKGRhdGEgPSBlbWlnYWluX3N1YiwgbXVsdGl2YXJpYXRlT3V0bGllck1ldGhvZCA9ICJxdWFuIiwgc2hvd091dGxpZXJzID0gVFJVRSwgc2hvd05ld0RhdGEgPSBUUlVFKQ0KDQpyZXN1bHRzJG11bHRpdmFyaWF0ZU91dGxpZXJzDQpyZXN1bHRzJG5ld0RhdGENCg0KYGBgDQoNCiMjIyBPdXRsaWVyIHN1bW1hcnkNCg0KVGhlIHotc2NvcmVzIGFjcm9zcyBlYWNoIG9mIHRoZSBudW1lcmljIHZhcmlhYmxlcyAoY29sdW1uIDQgdG8gMTQpIHdpbGwgYmUgZXN0YWJsaXNoZWQgdmlhIGFwcGx5aW5nIHRoZSBzY29yZXModHlwZSA9ICJ6IikgZnVuY3Rpb24gdXNpbmcgZnVuY3Rpb24gbGFwcGx5KCkuDQoNCioqU3VtbWFyeSBvZiBvdXRsaWVycyB1c2luZyB0aGUgc2NvcmVzICh8ei1zY29yZXwgPiAzKSoqDQoNCjAwIE5ER2FpbiAgDQoNCjQ0IFBvcHVsYXRpb24gDQoNCjQ3IHRvdF9jbzJfZW1pICANCg0KNDkgc29saWRfY29ucyANCg0KNDggbGlxdWlkX2NvbnMgICAgDQoNCjQ1IGdhc19jb25zIA0KDQoyMiBjZW1lbnRfcHJvZA0KDQo4OCBnYXNfZmxhcmUgDQoNCjc4IGNhcF9jbzJfZW1pIA0KDQo2OSBidW5rZXJfY29ucyANCg0KNDYgYWxsX2NvMl9lbWkgDQoNCmBgYHtyfQ0KIyBHZXQgei1zY29yZSBmb3IgZWFjaCBudW1lcmljIHZhcmlhYmxlLiAgU2NvcmUoKSBmdW5jdGlvbiB3aXRoIHR5cGU9ICJ6Ig0Kel9zY29yZXMgPC0gZW1pZ2FpblssICg0OjE0KV0gJT4lIGxhcHBseShGVU4gPSBmdW5jdGlvbih4KSBzY29yZXMoeCwgdHlwZT0gInoiKSkgJT4lIGFzLmRhdGEuZnJhbWUoKQ0KDQojIE91dGxpZXIgc3VtbWFyeQ0KY29sU3VtcyhhYnMoel9zY29yZXMpID4gMykgDQoNCmBgYA0KDQojIyMgT3V0bGllciBpbnNwZWN0aW9uDQoNCkNsb3NlciBpbnNwZWN0aW9uIG9mIHRoZSBQb3B1bGF0aW9uIG91dGxpZXJzIHNob3cgdGhhdCB0aGUgcG9wdWxhdGlvbnMgYXJlIHRob3NlIGZvciBDaGluYSBhbmQgSW5kaWEuICBUaGVzZSBhcmUgYWxsIHZhbGlkLiAgQ29uZmlybWVkIHRoZXNlIHZpYSB0aGUgaW50ZXJuZXQuDQoNCmBgYHtyfQ0KZW1pZ2FpblthYnMoel9zY29yZXMkUG9wdWxhdGlvbikgPiAzLCBdICU+JSBncm91cF9ieShJU08zLCBOYW1lKSAlPiUgc2xpY2VfaGVhZChuPTIpDQoNCmBgYA0KDQpDbG9zZXIgaW5zcGVjdGlvbiBvZiB0aGUgdG90X2NvMl9lbWkgb3V0bGllcnMgc2hvdyB0aGF0IHRoZSB0b3RhbCBlbWlzc2lvbnMgYXJlIHRob3NlIGZvciBDaGluYSwgSW5kaWEgYW5kIFVTQS4gIFRoZXNlIGFyZSBhbGwgdmFsaWQuICBDb25maXJtZWQgdGhlc2UgdmlhIHRoZSBpbnRlcm5ldC4NCg0KYGBge3J9DQplbWlnYWluW2Ficyh6X3Njb3JlcyR0b3RfY28yX2VtaSkgPiAzLCBdICU+JSBncm91cF9ieShJU08zLCBOYW1lKSAlPiUgc2xpY2VfaGVhZChuPTIpDQoNCmBgYA0KDQpDbG9zZXIgaW5zcGVjdGlvbiBvZiB0aGUgc29saWRfY29ucyBvdXRsaWVycyBzaG93IHRoYXQgdGhlc2UgZW1pc3Npb25zIGFyZSB0aG9zZSBmb3IgQ2hpbmEsIEluZGlhIGFuZCBVU0EuICBUaGVzZSBhcmUgYWxsIHZhbGlkLiAgQ29uZmlybWVkIHRoZXNlIHZpYSB0aGUgaW50ZXJuZXQuDQoNCmBgYHtyfQ0KZW1pZ2FpblthYnMoel9zY29yZXMkc29saWRfY29ucykgPiAzLCBdICU+JSBncm91cF9ieShJU08zLCBOYW1lKSAlPiUgc2xpY2VfaGVhZChuPTIpDQoNCmBgYA0KDQpDbG9zZXIgaW5zcGVjdGlvbiBvZiB0aGUgbGlxdWlkX2NvbnMgb3V0bGllcnMgc2hvdyB0aGF0IHRoZXNlIGVtaXNzaW9ucyBhcmUgdGhvc2UgZm9yIENoaW5hLCBJbmRpYSwgSmFwYW4gYW5kIFVTQS4gIFRoZXNlIGFyZSBhbGwgdmFsaWQuICBDb25maXJtZWQgdGhlc2UgdmlhIHRoZSBpbnRlcm5ldC4NCg0KYGBge3J9DQplbWlnYWluW2Ficyh6X3Njb3JlcyRsaXF1aWRfY29ucykgPiAzLCBdICU+JSBncm91cF9ieShJU08zLCBOYW1lKSAlPiUgc2xpY2VfaGVhZChuPTIpDQoNCmBgYA0KDQpDbG9zZXIgaW5zcGVjdGlvbiBvZiB0aGUgZ2FzX2NvbnMgb3V0bGllcnMgc2hvdyB0aGF0IHRoZXNlIGVtaXNzaW9ucyBhcmUgdGhvc2UgZm9yIENoaW5hLCBSdXNzaWEgYW5kIFVTQS4gIFRoZXNlIGFyZSBhbGwgdmFsaWQuICBDb25maXJtZWQgdGhlc2UgdmlhIHRoZSBpbnRlcm5ldC4NCg0KYGBge3J9DQplbWlnYWluW2Ficyh6X3Njb3JlcyRnYXNfY29ucykgPiAzLCBdICU+JSBncm91cF9ieShJU08zLCBOYW1lKSAlPiUgc2xpY2VfaGVhZChuPTIpDQoNCmBgYA0KDQpDbG9zZXIgaW5zcGVjdGlvbiBvZiB0aGUgY2VtZW50X3Byb2Qgb3V0bGllcnMgc2hvdyB0aGF0IHRoZXNlIGVtaXNzaW9ucyBhcmUgdGhvc2UgZm9yIENoaW5hLiAgVGhlc2UgYXJlIGFsbCB2YWxpZC4gIENvbmZpcm1lZCB0aGVzZSB2aWEgdGhlIGludGVybmV0Lg0KDQpgYGB7cn0NCmVtaWdhaW5bYWJzKHpfc2NvcmVzJGNlbWVudF9wcm9kKSA+IDMsIF0gJT4lIGdyb3VwX2J5KElTTzMsIE5hbWUpICU+JSBzbGljZV9oZWFkKG49MikNCg0KYGBgDQoNCkNsb3NlciBpbnNwZWN0aW9uIG9mIHRoZSBnYXNfZmxhcmUgb3V0bGllcnMgc2hvdyB0aGF0IHRoZXNlIGVtaXNzaW9ucyBhbGwgdmFsaWQuICBDb25maXJtZWQgdGhlc2UgdmlhIHRoZSBpbnRlcm5ldC4NCg0KYGBge3J9DQplbWlnYWluW2Ficyh6X3Njb3JlcyRnYXNfZmxhcmUpID4gMywgXSAlPiUgZ3JvdXBfYnkoSVNPMywgTmFtZSkgJT4lIHNsaWNlX2hlYWQobj0yKQ0KDQpgYGANCg0KQ2xvc2VyIGluc3BlY3Rpb24gb2YgdGhlIGNhcF9jbzJfZW1pIG91dGxpZXJzIHNob3cgdGhhdCB0aGVzZSBwZXIgY2FwaXRhIGVtaXNzaW9ucyBhcmUgdmFsaWQuICBDb25maXJtZWQgdGhlc2UgdmlhIHRoZSBpbnRlcm5ldC4NCg0KYGBge3J9DQplbWlnYWluW2Ficyh6X3Njb3JlcyRjYXBfY28yX2VtaSkgPiAzLCBdICU+JSBncm91cF9ieShJU08zLCBOYW1lKSAlPiUgc2xpY2VfaGVhZChuPTIpDQoNCmBgYA0KDQpDbG9zZXIgaW5zcGVjdGlvbiBvZiB0aGUgYnVua2VyX2NvbnMgb3V0bGllcnMgc2hvdyB0aGF0IHRoZXNlIGVtaXNzaW9ucyBhcmUgYWxsIHZhbGlkLiAgQ29uZmlybWVkIHRoZXNlIHZpYSB0aGUgaW50ZXJuZXQuDQoNCmBgYHtyfQ0KZW1pZ2FpblthYnMoel9zY29yZXMkYnVua2VyX2NvbnMpID4gMywgXSAlPiUgZ3JvdXBfYnkoSVNPMywgTmFtZSkgJT4lIHNsaWNlX2hlYWQobj0yKQ0KDQoNCmBgYA0KDQpDbG9zZXIgaW5zcGVjdGlvbiBvZiB0aGUgYWxsX2NvMl9lbWkgb3V0bGllcnMgc2hvdyB0aGF0IHRoZXNlIGVtaXNzaW9ucyBhcmUgdGhvc2UgZm9yIENoaW5hLCBJbmRpYSBhbmQgVVNBLiAgVGhlc2UgYXJlIGFsbCB2YWxpZC4gVGhleSB3b3VsZCBmb2xsb3cgdGhlIHRvdGFsIGVtaXNzaW9ucyBhYm92ZS4NCg0KYGBge3J9DQplbWlnYWluW2Ficyh6X3Njb3JlcyRhbGxfY28yX2VtaSkgPiAzLCBdICU+JSBncm91cF9ieShJU08zLCBOYW1lKSAlPiUgc2xpY2VfaGVhZChuPTIpDQoNCmBgYA0KDQoNCiMjCVRyYW5zZm9ybSANCg0KIyMjIEFwcHJvYWNoICYgU3VtbWFyeQ0KDQpUaGUgdG90YWwgY2FyYm9uIGVtaXNzaW9ucyAodG90X2NvMl9lbWkpIGFuZCBwb3B1bGF0aW9uIChQb3B1bGF0aW9uKSBkaXN0cmlidXRpb25zIGFyZSBib3RoIGhlYXZpbHkgcmlnaHQgc2tld2VkLg0KDQpUcmFuc2Zvcm1hdGlvbnMgYXJlIGFwcGxpZWQgdG8gbW92ZSB0aGVtIHRvIG5vcm1hbCBkaXN0cmlidXRpb25zLiAgdG90X2NvMl9lbWkudCBhbmQgUG9wdWxhdGlvbi50IHJlc3BlY3RpdmVseS4NCg0KR2l2ZW4gdGhhdCB0aGV5IGFyZSByaWdodCBza2V3ZWQsIG1hdGhlbWF0aWNhbCBmdW5jdGlvbnMgbG9nKCksIGxvZzEwKCksIHNxcnQoKSBhcmUgYXBwbGllZC4gDQoNClRoZSByZXN1bHRpbmcgZGlzdHJpYnV0aW9ucyBhcmUgdmVyaWZpZWQgdXNpbmcgaGlzdG9ncmFtIHBsb3RzLiBBdCBsZWFzdCBvbmUgb2YgdGhlIGZ1bmN0aW9ucyBpcyBjb25zaWRlcmVkIHN1aXRhYmxlIGZvciB0aGUgdHJhbnNmb3JtYXRpb24sIGllLiBjbG9zZXN0IHRvIG5vcm1hbC4gIFNvIHRoZXJlIGlzIG5vIG5lZWQgdG8gZXhwbG9yZSBlbHNld2hlcmUgZm9yIG90aGVyIG1ldGhvZHMuDQoNClRoZSBCb3ggQ294IHRyYW5zZm9ybWF0b24gaXMgdXNlZCwgdXNpbmcgZm9yZWNhc3Q6OkJveENveC5sYW1iZGEgdG8gd29yayBvdXQgdGhlIGJlc3QgbGFtYmRhLCBhbmQgdGhlbiBCb3hDb3goKSB0byBwZXJmb3JtIHRoZSB0cmFuc2Zvcm1hdGlvbi4gICBUaGlzIGlzIHRvIGRpc2NvdmVyIGFsdGVybmF0aXZlIG1ldGhvZHMuDQoNCg0KIyMjIFRvdGFsIENPMiBlbWlzc2lvbnMgdHJhbnNmb3JtYXRpb24NCg0KKiBCZXN0IHRyYW5zZm9ybWF0aW9uIGZ1bmN0aW9uIGlzIGxvZzEwKCkNCg0KKiBCb3hDb3ggbGFtYmRhIGlzIDANCg0KYGBge3J9DQojdG90YWwgZW1pc3Npb25zIGRpc3RyaWJ1dGlvbiBpcyBoZWF2aWx5IHJpZ2h0IHNrZXdlZA0KZW1pZ2FpbiR0b3RfY28yX2VtaSAlPiUgaGlzdChtYWluID0gInRvdF9jbzJfZW1pIiwgYnJlYWtzPSAxMDApDQoNCiN0cnkgdHJhbnNmb3JtYXRpb25zDQplbWlnYWluJHRvdF9jbzJfZW1pICU+JSBsb2coKSAlPiUgaGlzdChtYWluID0gImxvZyh0b3RfY28yX2VtaSkiKQ0KZW1pZ2FpbiR0b3RfY28yX2VtaSAlPiUgbG9nMTAoKSAlPiUgaGlzdChtYWluID0gImxvZzEwKHRvdF9jbzJfZW1pKSIpICNiZXN0DQplbWlnYWluJHRvdF9jbzJfZW1pICU+JSBzcXJ0KCkgJT4lIGhpc3QobWFpbiA9ICJzcXJ0KHRvdF9jbzJfZW1pKSIpDQoNCiNnZXQgYmVzdCBsYW1iZGEgLCB0aGVuIGFwcGx5IHRvIHRyYW5zZm9ybWF0aW9uDQplbWlnYWluJHRvdF9jbzJfZW1pICU+JSBCb3hDb3gubGFtYmRhKG1ldGhvZCA9ICJsb2dsaWsiLCBsb3dlciA9IC0zLCB1cHBlciA9IDMpDQplbWlnYWluJHRvdF9jbzJfZW1pICU+JSBCb3hDb3gobGFtYmRhID0gMCkgJT4lIGhpc3QobWFpbiA9ICJCb3hDb3godG90X2NvMl9lbWkpIikNCg0KI2FwcGx5IGJlc3QgdHJhbnNmb3JtYXRpb24NCmVtaWdhaW4kdG90X2NvMl9lbWkudCA8LSBlbWlnYWluJHRvdF9jbzJfZW1pICU+JSBsb2cxMCgpDQpgYGANCg0KIyMjIFBvcHVsYXRpb24gdHJhbnNmb3JtYXRpb24NCg0KKiBCZXN0IHRyYW5zZm9ybWF0aW9uIGZ1bmN0aW9uIGlzIGxvZygpDQoNCiogQm94Q294IGxhbWJkYSBpcyAwLjA1DQpgYGB7cn0NCiNwb3B1bGF0aW9uIGRpc3RyaWJ1dGlvbiBpcyBoZWF2aWx5IHJpZ2h0IHNrZXdlZA0KZW1pZ2FpbiRQb3B1bGF0aW9uICU+JSBoaXN0KG1haW4gPSAiUG9wdWxhdGlvbiIpDQoNCiN0cnkgdHJhbnNmb3JtYXRpb25zDQplbWlnYWluJFBvcHVsYXRpb24gJT4lIGxvZygpICU+JSBoaXN0KG1haW4gPSAibG9nKFBvcHVsYXRpb24pIikgI2Jlc3QNCmVtaWdhaW4kUG9wdWxhdGlvbiAlPiUgbG9nMTAoKSAlPiUgaGlzdChtYWluID0gImxvZzEwKFBvcHVsYXRpb24pIikNCmVtaWdhaW4kUG9wdWxhdGlvbiAlPiUgc3FydCgpICU+JSBoaXN0KG1haW4gPSAic3FydChQb3B1bGF0aW9uKSIpDQoNCiNnZXQgYmVzdCBsYW1iZGEgLCB0aGVuIGFwcGx5IHRvIHRyYW5zZm9ybWF0aW9uDQplbWlnYWluJFBvcHVsYXRpb24gJT4lIEJveENveC5sYW1iZGEobWV0aG9kID0gImxvZ2xpayIsIGxvd2VyID0gLTMsIHVwcGVyID0gMykNCmVtaWdhaW4kUG9wdWxhdGlvbiAlPiUgQm94Q294KGxhbWJkYSA9IDAuMDUpICU+JSBoaXN0KG1haW4gPSAiQm94Q294KFBvcHVsYXRpb24pIikNCg0KI2FwcGx5IGJlc3QgdHJhbnNmb3JtYXRpb24NCmVtaWdhaW4kUG9wdWxhdGlvbi50IDwtIGVtaWdhaW4kUG9wdWxhdGlvbiAlPiUgbG9nKCkNCg0KYGBgDQoNClZpZXcgdHJhbnNmb3JtYXRpb25zICp0b3RfY28yX2VtaS50KiBhbmQgKlBvcHVsYXRpb24udCoNCg0KYGBge3J9DQplbWlnYWluICU+JSBoZWFkKCkNCg0KYGBgDQoNCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9DQojTkRHYWluIGRpc3RyaWJ1dGlvbiBpcyBtaWxkbHkgcmlnaHQgc2tld2VkDQplbWlnYWluJE5ER2FpbiAlPiUgaGlzdCgpDQoNCiN0cnkgdHJhbnNmb3JtYXRpb25zDQplbWlnYWluJE5ER2FpbiAlPiUgbG9nKCkgJT4lIGhpc3QoKQ0KZW1pZ2FpbiROREdhaW4gJT4lIGxvZzEwKCkgJT4lIGhpc3QoKSAjYmVzdA0KZW1pZ2FpbiROREdhaW4gJT4lIHNxcnQoKSAlPiUgaGlzdCgpDQoNCmVtaWdhaW4kTkRHYWluICU+JSBCb3hDb3gubGFtYmRhKG1ldGhvZCA9ICJndWVycmVybyIsIGxvd2VyID0gLTMsIHVwcGVyID0gMykNCmVtaWdhaW4kTkRHYWluICU+JSBCb3hDb3gubGFtYmRhKG1ldGhvZCA9ICJsb2dsaWsiLCBsb3dlciA9IC0zLCB1cHBlciA9IDMpDQplbWlnYWluJE5ER2FpbiAlPiUgQm94Q294KGxhbWJkYSA9IC0wLjI1KSAlPiUgaGlzdCgpDQoNCnFwbG90KHg9TkRHYWluLCB5PXRvdF9jbzJfZW1pLCBkYXRhPWVtaWdhaW4sIGdlb20gPSAicG9pbnQiKQ0KDQpxcGxvdCh4PWxvZzEwKE5ER2FpbiksIHk9bG9nMTAodG90X2NvMl9lbWkpLCBkYXRhPWVtaWdhaW4sIGdlb20gPSAicG9pbnQiKQ0KDQpxcGxvdCh4PVBvcHVsYXRpb24sIHk9dG90X2NvMl9lbWksIGRhdGE9ZW1pZ2FpbiwgZ2VvbSA9ICJwb2ludCIpDQoNCnFwbG90KHg9bG9nKFBvcHVsYXRpb24pLCB5PWxvZzEwKHRvdF9jbzJfZW1pKSwgZGF0YT1lbWlnYWluLCBnZW9tID0gInBvaW50IikNCmBgYA0KDQoNCiMjIyBEYXRhIFJlZmVyZW5jZQ0KDQoqIEQuIEdpbGZpbGxhbiwgRy4gTWFybGFuZCwgVC4gQm9kZW4sIGFuZCBSLiAgQW5kcmVzLiAoMjAxOSkuICpHbG9iYWwsIFJlZ2lvbmFsLCBhbmQgTmF0aW9uYWwgRm9zc2lsLUZ1ZWwgQ08yIEVtaXNzaW9uczogMTc1MS0yMDE2KiBbY3N2IGZpbGUgbmF0aW9uLjE3NTFfMjAxNi5jc3ZdLiBodHRwczovL2VuZXJneS5hcHBzdGF0ZS5lZHUvcmVzZWFyY2gvd29yay1hcmVhcy9jZGlhYy1hcHBzdGF0ZQ0KKiBVbml2ZXJzaXR5IG9mIE5vdHJlIERhbWUsIE5vdHJlIERhbWUgR2xvYmFsIEFkYXB0YXRpb24gSW5pdGlhdGl2ZS4oMjAyMCkuICpORC1HQUlOIENvdW50cnkgSW5kZXgqLiBodHRwczovL2dhaW4ubmQuZWR1L291ci13b3JrL2NvdW50cnktaW5kZXgvcmFua2luZ3MvDQoNCg0KPGJyPg0KPGJyPg0K