L1 Intro
L1.1 Use stock exchange quotations to record the stock price and
dividend of one stock from each stock exchange in which you would like
to invest.
Starting quantmod
library(quantmod)
Function to get the symbols on the time period required
get_stock_info_by_date <- function(symbol, BoT_date, EoT_date){
stock_data <- getSymbols(symbol, from = BoT_date, to = EoT_date, auto.assign = FALSE)
start_price <- as.numeric(Cl(stock_data[BoT_date]))
end_price <- as.numeric(Cl(stock_data[EoT_date]))
if (is.null(end_price) || length(end_price) == 0 || is.na(as.numeric(end_price))) {
end_price <- as.numeric(Cl(last(stock_data[paste0("/", EoT_date)])))} else {
end_price <- as.numeric(end_price)}
dividends <- getDividends(symbol, from = BoT_date, to = EoT_date, auto.assign = FALSE)
start_dividend <- if (BoT_date %in% index(dividends)) {as.numeric(dividends[BoT_date])} else NA
if (is.null(start_dividend) || length(start_dividend) == 0 || is.na(as.numeric(start_dividend))) {
start_dividend <- as.numeric(last(dividends[paste0("/", EoT_date)]))} else {
start_dividend <- as.numeric(start_dividend)}
end_dividend <- if(EoT_date %in% index(dividends)) as.numeric(dividends[EoT_date])
if (is.null(end_dividend) || length(end_dividend) == 0 || is.na(as.numeric(end_dividend))) {
end_dividend <- as.numeric(last(dividends[paste0("/", EoT_date)]))} else {
end_dividend <- as.numeric(end_dividend)}
list(
Start_Price= start_price,
End_Price= end_price,
Start_Dividend= start_dividend,
End_Dividend= end_dividend
)
}
Determining the dates of beginning and end
BoT_date <- "2024-05-01"
EoT_date <- "2024-09-30"
Determining the stock symbols
nyse_stock <- "IBM"
nasdaq_stock <- "SBUX"
Retrieve information from each stock
nyse_info <- get_stock_info_by_date(nyse_stock, BoT_date, EoT_date)
nasdaq_info <- get_stock_info_by_date(nasdaq_stock, BoT_date, EoT_date)
Create a data frame to display the results
stock_data <- data.frame(
Exchange = c("New York Stock Exchange", "Nasdaq Market"),
Firm = c(nyse_stock, nasdaq_stock),
BoT_Price = c(nyse_info$Start_Price, nasdaq_info$Start_Price),
EoT_Price = c(nyse_info$End_Price, nasdaq_info$End_Price),
BoT_Dividend = c(nyse_info$Start_Dividend, nasdaq_info$Start_Dividend),
EoT_Dividend = c(nyse_info$End_Dividend, nasdaq_info$End_Dividend))
print(stock_data)
Analysis of results.
In this exercise we have obtained the stock prices and dividend of an
stock from the New York Stock Exchange and another from the Nasdaq
Market, both at the beginning of the school term date (BoT date) and the
end of the school term date (EoT date) For the development of this
exercise, we have designed a function which allows us to extract the
stock price as well as the dividend, giving a solution to manage the
lack of data at the EoT date, which is a non-trading day. In this
solution, which we will have to further implement in the rest of
exercises that involve obtaining data at EoT date, we have given an
order to use the last available data when the date selected has no
available data. Additionally, although it will probably not be needed,
we have implemented an equivalent system for obtaining the data on BoT
date, so that if we encounter a missing value, we will use the next
available data. Regarding the results of the exercise, we can observe an
increase in the price of the of both stocks during the school term. The
increasing prices usually revolve around positive future expectancy of
the companies as well as a favorable presentation of results at the end
of each quarter. The dividends have not seen neither an increase nor a
decrease, which indicates stability in their internal financial
organization and gives a further sense of safeness to their
stockholders.
L1.2 Use futures prices quotations to record the recent (“settle”)
price of the following futures (select futures with first settlement
date beyond the end of the school term)
Creating function to extract the values
get__futures_data_by_date <- function(symbol, from = BoT_date, to = EoT_date) {
futures_data <- getSymbols(symbol, from = BoT_date, to = EoT_date, auto.assign = FALSE)
if (is.null(futures_data) || nrow(futures_data) == 0) {
warning(paste("No data found for symbol:", symbol))
return(NA)
}
BoT_price <- as.numeric(Cl(futures_data[BoT_date]))
EoT_data <- futures_data[paste0("/", EoT_date)]
if(nrow(EoT_data) == 0) {
warning(paste("No data available on or before EoT_date for symbol:", symbol))
EoT_price <- NA
} else {
EoT_price <- as.numeric(last(Cl(EoT_data)))
}
return(list(
Symbol = symbol,
BoT_Price = BoT_price,
EoT_Price = EoT_price
))
}
use the function for each futures contract
treasury_bond <- get__futures_data_by_date("ZB=F", BoT_date, EoT_date)
sp500_futures <- get__futures_data_by_date("ES=F", BoT_date, EoT_date)
nasdaq <- get__futures_data_by_date("^IXIC", BoT_date, EoT_date)
british_pound <- get__futures_data_by_date("6B=F", BoT_date, EoT_date)
build the data frame
future_prices <- data.frame(
Asset = c(
"Treasury Bond Futures Dec 2024",
"S&P 500 Futures Dec 2024",
"Nasdaq Composite Index",
"British Pound Futures Dec 2024"
),
Symbol = c(
treasury_bond$Symbol,
sp500_futures$Symbol,
nasdaq$Symbol,
british_pound$Symbol
),
BoT_Price = c(
treasury_bond$BoT_Price,
sp500_futures$BoT_Price,
nasdaq$BoT_Price,
british_pound$BoT_Price
),
EoT_Price = c(
treasury_bond$EoT_Price,
sp500_futures$EoT_Price,
nasdaq$EoT_Price,
british_pound$EoT_Price
)
)
Print the data frame
print(future_prices)
Analysis of the results
In this case, we have created a function in order to retrieve the
settle price of the different types of futures, with the first
settlement date beyond the end of the school term. As done before, we
have adjusted the function to manage non-trading days. In the data
obtained we can observe an individual appreciation of each of their
prices, which may indicate an overall growth in economy. However, some
other factors that usually affect futures prices, such as interest
rates, macroeconomic decisions, the market preferences and supply and
demand can have a significant impact in the pricing of these assets.
L1.3 Use an options quotations table to select a call option on a
firm whose stock price you expect to increase (select the option with
the first expiration month beyond the end of the school term)
Install and load packages
# Load packages
library(quantmod)
library(tidyverse)
library(lubridate)
library(timeDate)
library(RQuantLib)
Define BoT and EoT dates
BoT_date <- as.Date("2024-05-01")
EoT_date <- as.Date("2024-09-30")
Create function to adjust to non-trading dates and obtain stock
information
#getting the symbols
get_stock_price <- function(symbol, date, use_next = FALSE) {
data <- getSymbols(
Symbols = symbol,
from = date - days(10),
to = date + days(10),
auto.assign = FALSE
)
#solving issues with non-trading days
index(data) <- as.Date(index(data))
if (use_next) {
available_dates <- index(data)[index(data) >= date]
if(length(available_dates) == 0) {
warning(paste("No data available after", date, "for symbol:", symbol))
return(NA)
}
date_used <- min(available_dates)
} else {
available_dates <- index(data)[index(data) <= date]
if (length(available_dates) == 0) {
warning(paste("No data available before", date, "for symbol:", symbol))
return(NA)
}
date_used <- max(available_dates)
}
#obtaining price
price <- as.numeric(Cl(data[date_used]))
return(list(
Price = price, Date = as.Date(date_used)
))
}
Getting the data for our selected stock
BoT_stock <- get_stock_price("BABA", BoT_date, use_next = TRUE)
EoT_stock <- get_stock_price("BABA", EoT_date, use_next = FALSE)
Calculate Option Premiums on BoT and EoT. Option Type: Call Option
Strike Price: Closest to the stock price at BoT_date Expiration Date:
First Option expiration date beyond EoT_Date
# Load necessary packages
library(lubridate)
library(timeDate)
# Initialize expiration_dates as an empty vector of class Date
expiration_dates <- as.Date(character())
# Get the current date
current_date <- as.Date(Sys.Date())
# Define your EoT_date
EoT_date <- as.Date("2024-09-30")
# Define the corrected third_friday function
third_friday <- function(year, month) {
# Get all days in the month
dates <- seq(
from = as.Date(paste0(year, "-", month, "-01")),
to = as.Date(paste0(year, "-", month, "-", days_in_month(as.Date(paste0(year, "-", month, "-01"))))),
by = "day"
)
# Get all Fridays using wday()
fridays <- dates[wday(dates) == 6] # 6 corresponds to Friday
# Return the third Friday
if (length(fridays) >= 3) {
return(fridays[3])
} else {
return(NA)
}
}
# Loop over the next 18 months
for (i in 0:17) {
# Add i months to the current date
date <- current_date %m+% months(i)
# Extract the year and month
yr <- year(date)
mnth <- month(date)
# Calculate the third Friday of the month
exp_date <- third_friday(yr, mnth)
if (!is.na(exp_date)) {
expiration_dates <- c(expiration_dates, exp_date)
}
}
# Filter expiration dates beyond EoT_date
expiration_dates <- expiration_dates[expiration_dates > EoT_date]
# Print the expiration dates
print(expiration_dates)
[1] "2025-01-17" "2025-02-21" "2025-03-21"
[4] "2025-04-18" "2025-05-16" "2025-06-20"
[7] "2025-07-18" "2025-08-15" "2025-09-19"
[10] "2025-10-17" "2025-11-21" "2025-12-19"
[13] "2026-01-16" "2026-02-20" "2026-03-20"
[16] "2026-04-17" "2026-05-15" "2026-06-19"
Get strike price
strike_price <- round(BoT_stock$Price, digits = -1) # Round to nearest 10
Estimate volatility
# Get historical stock prices for the past year before BoT_date
ticker <- "BABA"
vol_data <- getSymbols(
Symbols = ticker,
src = "yahoo",
from = BoT_stock$Date - years(1),
to = BoT_stock$Date,
auto.assign = FALSE
)
# Calculate daily returns
returns <- dailyReturn(Cl(vol_data))
# Calculate annualized volatility
volatility <- sd(returns, na.rm = TRUE) * sqrt(252) # 252 trading days in a year
Set risk-free Interest Rate and Dividend Yield
#Risk-free interest rate (e.g., 2% annualized)
risk_free_rate <- 0.02
#Dividend yield (from Yahoo Finance or set to 0.005 for 0.5%)
dividend_yield <- 0.05
Calculate Time to Expiration
# Assuming 'expiration_dates' is a vector of Date objects
expiration_dates <- expiration_dates[expiration_dates > EoT_date]
# Select the earliest expiration date beyond EoT_date
expiration_date <- expiration_dates[1]
# Time to expiration from BoT_date
time_to_expiration_BoT <- as.numeric(expiration_date - BoT_stock$Date) / 365
# Time to expiration from EoT_date
time_to_expiration_EoT <- as.numeric(expiration_date - EoT_stock$Date) / 365
Use Black-Scholes Model to calculate Option Premiums
#Function to calculate Option Premium
calculate_option_premium <- function(S, K, r, time_to_expiration, sigma, dividend_yield) {
option <- EuropeanOption(
type = "call",
underlying = S,
strike = K,
dividendYield = dividend_yield,
riskFreeRate = r,
maturity = time_to_expiration,
volatility = sigma
)
return(option$value)
}
Calculate Option Premiums
# Option premium on BoT_date
BoT_premium <- calculate_option_premium(
S = BoT_stock$Price,
K = strike_price,
r = risk_free_rate,
time_to_expiration = time_to_expiration_BoT,
sigma = volatility,
dividend_yield = dividend_yield
)
# Option premium on EoT_date
EoT_premium <- calculate_option_premium(
S = EoT_stock$Price,
K = strike_price,
r = risk_free_rate,
time_to_expiration = time_to_expiration_EoT,
sigma = volatility,
dividend_yield = dividend_yield
)
Create table for results
results <- data.frame(
Stock = "BABA",
BoT_Date = BoT_stock$Date,
BoT_Price = BoT_stock$Price,
BoT_Option_Premium = BoT_premium,
EoT_Date = EoT_stock$Date,
EoT_Price = EoT_stock$Price,
EoT_Option_Premium = EoT_premium
)
print(results)
Analysis of results
In this exercise we must retrieve data of a call data from a stock we
expect to increase. In these case, we have considered to take into
account Alibaba (“BABA”), as we consider that is a company which is
currently undervalued and has a huge potential of growth in terms of
stock price. For the development of this exercise we have developed a
new function to get our sstock data, but in this case we have lengthened
our time bracket to obtain data both from before BoT date and after EoT
date. We have also defined the expiration dates to the month’s third
Friday, and we have set the expiration dates available to those after
EoT date. Afterwards we have stablished the strike price and, with the
use of a new function, we have calculated the volatility. As our last
steps before applying the Black-Scholes model, we have calculated our
time to expiration and we have established the risk-free rate and the
dividend yield. Finally, we have defined our function for applying the
Black-Scholes model and we have retrieved the option premiums at BoT
date and EoT date.
The results obtained thanks to this code has led us to perceive a
significant appreciation in the option premium, which we can attribute
to an improvement of the underlying asset (“BABA”). Also, when we
observe the change in price, it matches with the observation in the
premiums, overall determining the great performance of the selected
asset during the school term.
L1.4
Getting data for our selected stock
# Get stock prices on BoT and EoT dates
BoT_stock <- get_stock_price("ING", BoT_date, use_next = TRUE)
EoT_stock <- get_stock_price("ING", EoT_date, use_next = FALSE)
Calculate Option Premiums on BoT and EoT +Option type: put option
+Strike Price: Closes to the Stock price at BoT_Date +Expiration Date:
First option expiration date beyond EoT_date
Get Strike Price
#Round to the nearest 10
strike_price <- round(BoT_stock$Price, digits = -1)
Estimate Volatility
# Get historical stock prices for the past year before BoT_date
ticker <- "ING"
vol_data <- getSymbols(
Symbols = ticker,
src = "yahoo",
from = BoT_stock$Date - years(1),
to = BoT_stock$Date,
auto.assign = FALSE
)
# Calculate daily returns
returns <- dailyReturn(Cl(vol_data))
# Calculate annualized volatility
volatility <- sd(returns, na.rm = TRUE) * sqrt(252) # 252 trading days in a year
Set Risk-Free Interest Rate and Dividend Yield
#Risk-free interest rate (2% annualized for example)
risk_free_rate <- 0.02
#Dividend Yield (most recent)
dividend_yield <- 0.0749
Calculate time to expiration
# Time to expiration from BoT_date
time_to_expiration_BoT <- as.numeric(expiration_date - BoT_stock$Date) / 365
# Time to expiration from EoT_date
time_to_expiration_EoT <- as.numeric(expiration_date - EoT_stock$Date) / 365
Calculate Option Premiums
# Option premium on BoT_date
BoT_premium <- calculate_option_premium(
S = BoT_stock$Price,
K = strike_price,
r = risk_free_rate,
time_to_expiration = time_to_expiration_BoT,
sigma = volatility,
dividend_yield = dividend_yield
)
# Option premium on EoT_date
EoT_premium <- calculate_option_premium(
S = EoT_stock$Price,
K = strike_price,
r = risk_free_rate,
time_to_expiration = time_to_expiration_EoT,
sigma = volatility,
dividend_yield = dividend_yield
)
Create table for Results
# Create a data frame with the obtained data
results <- data.frame(
Stock = "ING",
BoT_Date = BoT_stock$Date,
BoT_Price = BoT_stock$Price,
BoT_Option_Premium = BoT_premium,
EoT_Date = EoT_stock$Date,
EoT_Price = EoT_stock$Price,
EoT_Option_Premium = EoT_premium
)
# Display the results
print(results)
NA
Analysis of results.
In this case, we have only had to apply the functions and process we
had just applied for the call option. The Asset we have selected is Bank
ING which we had expected to fall. However, in the results obtained we
have noticed an appreciation in the stock value as well as the premiums.
This means that the stock has out performed our expectations and has not
fallen during the school term. Had we bought the put option in the
beginning of term date, we would have had a negative action of our
operation. However, we would like to note that in the recent times, ING
has been hit with negative news and information regarding massive
withdrawals. However, this information appears to have been debunked,
although there has been observed recent negative stock movements.
L1.5
Define BoT and EoT dates
BoT_date <- as.Date("2024-05-01")
EoT_date <- as.Date("2024-09-30")
Create a Function to Retrieve Exchange Rates with Non-Trading day
Adjustment
get_exchange_rate <- function(symbol, date, use_next = FALSE, invert = FALSE) {
# Retrieve exchange rate data from FRED
data <- getSymbols(Symbols = symbol, src = "FRED", auto.assign = FALSE)
# Convert index to Date format
index(data) <- as.Date(index(data))
# Adjust for non-trading days
if (use_next) {
# For BoT_date, get the next available date after the date
available_dates <- index(data)[index(data) >= date & !is.na(data[index(data)])]
if(length(available_dates) == 0) {
warning(paste("No data available after", date, "for symbol:", symbol))
return(list(Rate = NA, Date = NA))
}
date_used <- min(available_dates)
} else {
# For EoT_date, get the last available date before the date
available_dates <- index(data)[index(data) <= date & !is.na(data[index(data)])]
if (length(available_dates) == 0) {
warning(paste("No data available before", date, "for symbol:", symbol))
return(list(Rate = NA, Date = NA))
}
date_used <- max(available_dates)
}
# Get the exchange rate
rate <- as.numeric(data[date_used])
# Invert the rate if needed (for currencies quoted as foreign currency per USD)
if (invert) {
rate <- 1 / rate
}
return(list(
Rate = rate,
Date = as.Date(date_used)
))
}
Retrieve Exchange Rates on BoT and EoT Dates Symbols in FRED:
GPB/USD: DEXUSUK JPY/USD: DEXJPUS MXN/USD: DEXMXUS (FRED provides
exchange rates in foreign currency units per U.S. dollar for JPY and
MXN, so we’ll invert these rates to get USD per foreign currency
unit)
# Retrieve exchange rates on BoT_date
GBP_BoT <- get_exchange_rate("DEXUSUK", BoT_date, use_next = TRUE)
JPY_BoT <- get_exchange_rate("DEXJPUS", BoT_date, use_next = TRUE, invert = TRUE)
MXN_BoT <- get_exchange_rate("DEXMXUS", BoT_date, use_next = TRUE, invert = TRUE)
# Retrieve exchange rates on EoT_date
GBP_EoT <- get_exchange_rate("DEXUSUK", EoT_date, use_next = FALSE)
JPY_EoT <- get_exchange_rate("DEXJPUS", EoT_date, use_next = FALSE, invert = TRUE)
MXN_EoT <- get_exchange_rate("DEXMXUS", EoT_date, use_next = FALSE, invert = TRUE)
Create a Data Frame to Display the Results
# Create data frame with the results
results <- data.frame(
Currency = c("GBP/USD", "JPY/USD", "MXN/USD"),
BoT_Date = c(GBP_BoT$Date, JPY_BoT$Date, MXN_BoT$Date),
BoT_Rate = c(GBP_BoT$Rate, JPY_BoT$Rate, MXN_BoT$Rate),
EoT_Date = c(GBP_EoT$Date, JPY_EoT$Date, MXN_EoT$Date),
EoT_Rate = c(GBP_EoT$Rate, JPY_EoT$Rate, MXN_EoT$Rate)
)
# Display the results
print(results)
Analysis of results
In this exercise we have designed a new function to retrieve exchange
rates, as always adjusting it to the non-trading days. We have retrieve
the data of three different exchange rates both on BoT date and EoT date
and we have portrayed the result in a data frame.
L1.6 Use currency options data (if available) to select a call
option on a foreign currency that you expect will strengthen against the
dollar (select the option with the first expiration month beyond the end
of the school term)
Load packages
# Load packages
library(quantmod)
library(lubridate)
library(timeDate)
library(tidyverse)
Define BoT and EoT Dates
BoT_date <- as.Date("2024-05-01")
EoT_date <- as.Date("2024-09-30")
Create a function to Adjust for Non-Trading Days and Obtain Exchange
Rate Data
get_exchange_rate <- function(symbol, date, use_next = FALSE) {
# Download data around the date
data <- getSymbols(
Symbols = symbol,
src = "yahoo",
from = date - days(10),
to = date + days(10),
auto.assign = FALSE
)
# Convert index to Date format
index(data) <- as.Date(index(data))
# Handle non-trading days
if (use_next) {
# For BoT_date, get the next available date after the date
available_dates <- index(data)[index(data) >= date]
if(length(available_dates) == 0) {
warning(paste("No data available after", date, "for symbol:", symbol))
return(list(Rate = NA, Date = NA))
}
date_used <- min(available_dates)
} else {
# For EoT_date, get the last available date before the date
available_dates <- index(data)[index(data) <= date]
if (length(available_dates) == 0) {
warning(paste("No data available before", date, "for symbol:", symbol))
return(list(Rate = NA, Date = NA))
}
date_used <- max(available_dates)
}
# Get the exchange rate
rate <- as.numeric(Cl(data[date_used]))
return(list(
Rate = rate,
Date = as.Date(date_used)
))
}
Retrieve Exchabge Rates on BoT and EoT dates
# Get exchange rates for CNY/USD
# Note: On Yahoo Finance, the symbol for CNY/USD is "CNY=X"
CNY_BoT <- get_exchange_rate("CNY=X", BoT_date, use_next = TRUE)
CNY_EoT <- get_exchange_rate("CNY=X", EoT_date, use_next = FALSE)
Determine Option Details +Option type: Call option +Strike Price: Use
the spot exchange rate at BoT_Date (At-The-Money) +Expiration Date:
First option expiration date beyond EoT_Date
Generate Option Expiration Dates
# Function to get the third Friday of a month
third_friday <- function(year, month) {
dates <- seq(
from = as.Date(paste0(year, "-", month, "-01")),
to = as.Date(paste0(year, "-", month, "-", days_in_month(as.Date(paste0(year, "-", month, "-01"))))),
by = "day"
)
fridays <- dates[wday(dates) == 6] # 6 corresponds to Friday
if (length(fridays) >= 3) {
return(fridays[3])
} else {
return(NA)
}
}
# Generate expiration dates for the next 18 months
expiration_dates <- as.Date(character())
current_date <- as.Date(Sys.Date())
for (i in 0:17) {
date <- current_date %m+% months(i)
yr <- year(date)
mnth <- month(date)
exp_date <- third_friday(yr, mnth)
if (!is.na(exp_date)) {
expiration_dates <- c(expiration_dates, exp_date)
}
}
# Filter expiration dates beyond EoT_date
expiration_dates <- expiration_dates[expiration_dates > EoT_date]
# Select the first expiration date beyond EoT_date
if (length(expiration_dates) == 0) {
stop("No expiration dates found beyond EoT_date.")
}
expiration_date <- expiration_dates[1]
print(paste("Selected Option Expiration Date:", expiration_date))
[1] "Selected Option Expiration Date: 2025-01-17"
Calculate Time to expiration
# Time to expiration from BoT_date
time_to_expiration_BoT <- as.numeric(expiration_date - CNY_BoT$Date) / 365
# Time to expiration from EoT_date
time_to_expiration_EoT <- as.numeric(expiration_date - CNY_EoT$Date) / 365
Set the Strike Price
strike_price <- CNY_BoT$Rate # At-The-Money option
Estimate Volatility
# Get historical exchange rate data for the past year before BoT_date
vol_data <- getSymbols(
Symbols = "CNY=X",
src = "yahoo",
from = CNY_BoT$Date - years(1),
to = CNY_BoT$Date,
auto.assign = FALSE
)
# Calculate daily returns
returns <- dailyReturn(Cl(vol_data))
# Calculate annualized volatility
volatility <- sd(returns, na.rm = TRUE) * sqrt(252) # 252 trading days in a year
Set Domestic and Foreign Risk-Free Interest Rates Domestic Risk-Free
Rate (r_domestic): US risk-free rate Foreign Risk-Free Rate (r_foreign):
Chinese risk-free rate
r_domestic <- 0.043
r_foreign <- 0.0209
Define the Garman-Kohlhagen Model Function
calculate_currency_option_premium <- function(S, K, r_domestic, r_foreign, time_to_expiration, sigma, option_type = "call") {
d1 <- (log(S / K) + (r_domestic - r_foreign + 0.5 * sigma^2) * time_to_expiration) / (sigma * sqrt(time_to_expiration))
d2 <- d1 - sigma * sqrt(time_to_expiration)
if (option_type == "call") {
premium <- S * exp(-r_foreign * time_to_expiration) * pnorm(d1) - K * exp(-r_domestic * time_to_expiration) * pnorm(d2)
} else if (option_type == "put") {
premium <- K * exp(-r_domestic * time_to_expiration) * pnorm(-d2) - S * exp(-r_foreign * time_to_expiration) * pnorm(-d1)
} else {
stop("Invalid option type. Use 'call' or 'put'.")
}
return(premium)
}
Calculate Option Premiums
# Option premium on BoT_date
BoT_premium <- calculate_currency_option_premium(
S = CNY_BoT$Rate,
K = strike_price,
r_domestic = r_domestic,
r_foreign = r_foreign,
time_to_expiration = time_to_expiration_BoT,
sigma = volatility,
option_type = "call"
)
# Option premium on EoT_date
EoT_premium <- calculate_currency_option_premium(
S = CNY_EoT$Rate,
K = strike_price,
r_domestic = r_domestic,
r_foreign = r_foreign,
time_to_expiration = time_to_expiration_EoT,
sigma = volatility,
option_type = "call"
)
Create Data Frame to Display Results
# Create data frame with the results
results <- data.frame(
Currency = "CNY/USD",
BoT_Date = CNY_BoT$Date,
BoT_Rate = CNY_BoT$Rate,
BoT_Option_Premium = BoT_premium,
EoT_Date = CNY_EoT$Date,
EoT_Rate = CNY_EoT$Rate,
EoT_Option_Premium = EoT_premium
)
# Display the results
print(results)
Analysis of results
In this exercise we have performed a rather similar process than that
of L1.4 and L1.5. However, in this case we are studying a call option on
a currency that we think might appreciate in value during the school
term. The currency we have selected has been the Chinese Yuan. The
weakening of the US Treasury Interest is one of the main drivers of the
weakening of the US Dollar and probably the main reason for the
appreciation of the Chinese Yuan against it.
In this case, we have not used the Black-Scholes Model, but rather the
Garman-Kohlhagen Model Function, which is often use to price currency
options.
Regarding the results, in this case we have not been able to secure a
favorable result in the call option, as the rate has depreciated, as
well as the premium, at EoT. This results can be explained due to a
great range of factors that include monetary policy of both countries,
market movements, supply and demand, macroeconomic data, microeconomic
details or even speculation from investors. Either way, the results
depict an strengthen US Dollar against the Chinese Yuan and the exercise
helps us to exemplify how a call option on a currency may be priced.
L1.7 Use currency options data (if available) to select a put option
on a foreign currency that you expect will weaken against the dollar
(select the option with the first expiration month beyond the end of the
school term).
Retrieve Exchange Rates on BoT and EoT dates
# Get exchange rates for EUR/USD
# Note: On Yahoo Finance, the symbol for CNY/USD is "EURUSD=X"
EUR_BoT <- get_exchange_rate("EURUSD=X", BoT_date, use_next = TRUE)
EUR_EoT <- get_exchange_rate("EURUSD=X", EoT_date, use_next = FALSE)
Determine Option Details +Option type: Call option +Strike Price: Use
the spot exchange rate at BoT_Date (At-The-Money) +Expiration Date:
First option expiration date beyond EoT_Date
Calculate Time to expiration
# Time to expiration from BoT_date
time_to_expiration_BoT <- as.numeric(expiration_date - EUR_BoT$Date) / 365
# Time to expiration from EoT_date
time_to_expiration_EoT <- as.numeric(expiration_date - EUR_EoT$Date) / 365
Set the Strike Price
strike_price <- EUR_BoT$Rate # At-The-Money option
Estimate Volatility
# Get historical exchange rate data for the past year before BoT_date
vol_data <- getSymbols(
Symbols = "EURUSD=X",
src = "yahoo",
from = EUR_BoT$Date - years(1),
to = EUR_BoT$Date,
auto.assign = FALSE
)
# Calculate daily returns
returns <- dailyReturn(Cl(vol_data))
# Calculate annualized volatility
volatility <- sd(returns, na.rm = TRUE) * sqrt(252) # 252 trading days in a year
Set Domestic and Foreign Risk-Free Interest Rates Domestic Risk-Free
Rate (r_domestic): US risk-free rate Foreign Risk-Free Rate (r_foreign):
European risk-free rate
r_domestic <- 0.043
r_foreign <- 0.0247
Calculate Option Premiums
# Option premium on BoT_date
BoT_premium <- calculate_currency_option_premium(
S = EUR_BoT$Rate,
K = strike_price,
r_domestic = r_domestic,
r_foreign = r_foreign,
time_to_expiration = time_to_expiration_BoT,
sigma = volatility,
option_type = "put"
)
# Option premium on EoT_date
EoT_premium <- calculate_currency_option_premium(
S = EUR_EoT$Rate,
K = strike_price,
r_domestic = r_domestic,
r_foreign = r_foreign,
time_to_expiration = time_to_expiration_EoT,
sigma = volatility,
option_type = "put"
)
Create Data Frame to Display Results
# Create data frame with the results
results <- data.frame(
Currency = "EUR/USD",
BoT_Date = EUR_BoT$Date,
BoT_Rate = EUR_BoT$Rate,
BoT_Option_Premium = BoT_premium,
EoT_Date = EUR_EoT$Date,
EoT_Rate = EUR_EoT$Rate,
EoT_Option_Premium = EoT_premium
)
# Display the results
print(results)
Analysis of results
In this last exercise of the section we have retrieved the
information of the Rate of Exchange EUR/USD and we had an initial
expectation of a decrease in the value of the EUR over the school term.
However, our initial thoughts have been proven wrong as we have obtained
a higher rate at the EoT date and the Option Premium has fallen. In the
case of having buyed this put option, the outcome would have resulted in
a negative operation. This results depict an strengthened Euro against
the Dollar. Even though our initial hypothesis of the movement of the
Euro against the Dollar were wrong, we have developed an answer that
explains how a put option on an currency exchange rate may be priced and
how its premium can be calculated, using the Garman-Kohlhagen Model
Function.
L2 Financial markets microstructure
Nasdaq and London Stock Exchange are two major global stock exchanges
with significant influence no global financial markets. Historical Stock
data for representative indices of both exchanges can be retrieved and
analyzed using R. Qualitative information about ach exchange is
available from reputable sources.
Hypotheses
There is a significant correlation between the performance of Nasdaq
and the LSE indices over the specified period. Differences in market
capitalization, liquidity, and types of instruments traded influence the
statistical measures observed The time zone difference affects the
trading patterns and liquidity of the two exchanges.
Data Retrieval and Preparation
Load required packages
# Install and load required packages
if (!require("quantmod")) {
install.packages("quantmod")
}
if (!require("PerformanceAnalytics")) {
install.packages("PerformanceAnalytics")
}
library(quantmod)
library(PerformanceAnalytics)
Retrieve Historical Data
# Define the date range
start_date <- as.Date("2008-01-03")
end_date <- as.Date("2023-01-05")
# Get historical data for Nasdaq Composite Index
getSymbols("^IXIC", src = "yahoo", from = start_date, to = end_date)
[1] "IXIC"
# Get historical data for FTSE 100 Index
getSymbols("^FTSE", src = "yahoo", from = start_date, to = end_date)
Aviso: ^FTSE contains missing values. Some functions will not work if objects contain missing values in the middle of the series. Consider using na.omit(), na.approx(), na.fill(), etc to remove or replace them.
[1] "FTSE"
Data Cleaning and Alignment
# Assign data to variables
nasdaq_data <- `IXIC`
ftse_data <- `FTSE`
# Check for missing values
sum(is.na(ftse_data))
[1] 12
# Handle missing values using linear interpolation
ftse_data <- na.approx(ftse_data)
# Merge the closing prices based on date
combined_data <- merge(Cl(nasdaq_data), Cl(ftse_data), all = FALSE)
# Rename columns for clarity
colnames(combined_data) <- c("Nasdaq_Close", "FTSE_Close")
Statistical Analysis
Calculate Basic Statistics
For Nasdaq
# Calculate basic statistics for Nasdaq
nasdaq_stats <- data.frame(
Mean = mean(combined_data$Nasdaq_Close, na.rm = TRUE),
Median = median(combined_data$Nasdaq_Close, na.rm = TRUE),
StDev = sd(combined_data$Nasdaq_Close, na.rm = TRUE)
)
print(nasdaq_stats)
For FTSE
# Calculate basic statistics for FTSE
ftse_stats <- data.frame(
Mean = mean(combined_data$FTSE_Close, na.rm = TRUE),
Median = median(combined_data$FTSE_Close, na.rm = TRUE),
StDev = sd(combined_data$FTSE_Close, na.rm = TRUE)
)
print(ftse_stats)
Calculate Correlation
# Calculate correlation between Nasdaq and FTSE closing prices
correlation <- cor(combined_data$Nasdaq_Close, combined_data$FTSE_Close, use = "complete.obs")
# Print the correlation coefficient
cat("Correlation between Nasdaq and FTSE:", round(correlation, 2), "\n")
Correlation between Nasdaq and FTSE: 0.65
Display Results
# Combine statistics for comparison
stats_comparison <- rbind(Nasdaq = nasdaq_stats, FTSE = ftse_stats)
# Set column names
colnames(stats_comparison) <- c("Mean", "Median", "Standard Deviation")
# Print the statistics
print("Basic Statistics Comparison:")
[1] "Basic Statistics Comparison:"
print(round(stats_comparison, 2))
# Print the correlation coefficient
cat("Correlation between Nasdaq and FTSE:", round(correlation, 2), "\n")
Correlation between Nasdaq and FTSE: 0.65
Analysis of the correlation
The correlation coefficient measures the strength and direction of
the relation between two sets of data, or in this case, of two assets.
The correlation coefficient can vary from -1 to 1, and with each value
we obtain a representation of how interconnected are two assets. In the
case of this exercise, we have obtained a correlation coefficient of
0.65, which constitutes a positive and strong correlation between the
two indexes in study. In broader terms, this means that the tendencies
of both indexes will be somewhat similar and will trend in the same
direction.
Market Capitalization
Market capitalization represents the total value of all listed
companies on an exchange. It’s a key indicator of the size and economic
weight of a stock exchange. Although we do not have access to direct
data, we will try to make the comparison using the top 5 companies from
each exchange.
Hypothesis:
The Nasdaq has a larger market capitalization compared to LSE due to
its concentration of large technology companies
Implementation:
Load packages
# Install and load required packages
if (!require("quantmod")) {
install.packages("quantmod")
}
library(quantmod)
library(dplyr)
Define Top Companies. We will extract this companies from the indexes
websites. LSE top 5 companies: Atrazeneca PLC, Shell PLC, HSBC HLDGS
PLC, Unilever PLC, RELX PLC.
NASDAQ top 5 companies: Apple Inc, NVIDIA corp, Microsoft Corp,
Amazon.com Inc, Broadcom Inc.
nasdaq_symbols <- c("AAPL", "NVDA", "MSFT", "AMZN", "AVGO")
lse_symbols <- c("AZN.L", "SHEL.L", "HSBA.L", "ULVR.L", "REL.L")
Retrieve Market Capitalization Data
# Install and load tidyquant
if (!require("tidyquant")) {
install.packages("tidyquant")
}
library(tidyquant)
library(dplyr)
Get Market Cap Data
# Function to get market cap data
get_market_cap <- function(symbols) {
# Retrieve market capitalization data
data <- getQuote(symbols, what = yahooQF("Market Capitalization"))
# Convert rownames to a column
data <- data %>%
rownames_to_column(var = "symbol") %>%
rename(market_cap = `Market Capitalization`) %>%
select(symbol, market_cap)
return(data)
}
# Get market cap data for Nasdaq companies
nasdaq_market_cap <- get_market_cap(nasdaq_symbols)
Error en getQuote.yahoo(Symbols = c("AAPL", "NVDA", "MSFT", "AMZN", "AVGO":
Unable to obtain yahoo crumb. If this is being called from a GDPR country, Yahoo requires GDPR consent, which cannot be scripted
Sum Market Caps
# Sum the market caps
nasdaq_total_market_cap <- sum(as.numeric(nasdaq_market_cap$market_cap), na.rm = TRUE)
Error: objeto 'nasdaq_market_cap' no encontrado
Handle Exchange Rates
# Get current GBP to USD exchange rate
getSymbols("GBPUSD=X", src = "yahoo", from = Sys.Date() - 1, to = Sys.Date())
[1] "GBPUSD=X"
exchange_rate <- as.numeric(Cl(`GBPUSD=X`)[1])
# Convert LSE market caps to USD
lse_market_cap$market_cap_usd <- as.numeric(lse_market_cap$market_cap) * exchange_rate
Error: objeto 'lse_market_cap' no encontrado
When trying to perform out analysis of the market capitalization we
have encounter a problem two retrieve data from R, so we cannot perform
the numerical demonstration. However, we will state that as far as the
information we have been able to gather, the LSEG has a higher market
capitalization than Nasdaq, Inc. This means that the LSE has a higher
corporate market capitalization. However, if we take into account the
aggregate market capitalization, the total market value of the assets
traded in Nasdaq greatly surpass the value of those traded in the
LSE.
A higher market capitalization may indicate higher economic
influence, liquidity and overall international attractiveness. However,
in this case Nasdaq’s thorough focus on technological companies narrows
its representation of the economy while the LSE has a broader range of
assets.
Liquidity.
It reflects how easily can assets be bought and sold in the market.
Higher trading volumes indicate higher liquidity.
Hypothesis.
The Nasdaq has a higher average trading volumes compared to LSE due
to its larger size and global investor base
We will retrieve the daily trading volume data from the indices and
calculate the average daily volume over an specified period.
For the Volume Data we will be using their top companies as a
proxy.
nasdaq_volumes <- list()
for (symbol in nasdaq_symbols) {
data <- getSymbols(symbol, src = "yahoo", from = start_date, to = end_date, auto.assign = FALSE)
nasdaq_volumes[[symbol]] <- Cl(data)
}
# Get volume data for top LSE companies
lse_volumes <- list()
for (symbol in lse_symbols) {
data <- getSymbols(symbol, src = "yahoo", from = start_date, to = end_date, auto.assign = FALSE)
volume_data <- Vo(data)
# Handle missing values
if (any(is.na(volume_data))) {
cat("Handling missing values for", symbol, "\n")
volume_data <- na.approx(volume_data)
}
# Store cleaned volume data
lse_volumes[[symbol]] <- volume_data
}
# Merge and align LSE volumes
lse_volume_data <- do.call(merge, lse_volumes)
# Remove any remaining missing values
lse_volume_data <- na.omit(lse_volume_data)
We calculate Average Volume
# Calculate average volume for Nasdaq companies
nasdaq_avg_volumes <- sapply(nasdaq_symbols, function(symbol) {
data <- getSymbols(symbol, src = "yahoo", from = start_date, to = end_date, auto.assign = FALSE)
mean(Vo(data), na.rm = TRUE)
})
# Calculate average volume for LSE companies
lse_avg_volumes <- sapply(lse_volumes, function(volume_data) {
mean(volume_data, na.rm = TRUE)
})
# Calculate the overall average volume
lse_avg_volume <- mean(lse_avg_volumes, na.rm = TRUE)
# Average volume across top companies
nasdaq_avg_volume <- mean(nasdaq_avg_volumes, na.rm = TRUE)
lse_avg_volume <- mean(lse_avg_volumes, na.rm = TRUE)
# Print results
cat("Average Daily Trading Volume for Nasdaq Top Companies:", formatC(nasdaq_avg_volume, format = "f", big.mark = ",", digits = 0), "\n")
Average Daily Trading Volume for Nasdaq Top Companies: 209,954,412
cat("Average Daily Trading Volume for LSE Top Companies:", formatC(lse_avg_volume, format = "f", big.mark = ",", digits = 0), "shares\n")
Average Daily Trading Volume for LSE Top Companies: 9,923,258 shares
Analysis of results
We encounter some limitation regarding this comparison, as the volume
units may differ between exchanges and the volume data for indices may
not be directly comparable. However, it becomes noticeable that the
average trading volume for Nasdaq’s Top companies is significantly
higher than that of LSE. This indicates a more active market and is
understandably explained by the constantly changing environment of the
technological companies traded in the Nasdaq.
Number of IPOs
The number of Initial Public Offerings reflects the attractiveness of
an exchange for companies looking to raise capital. Due to lack of
possibility to retrieve such data, we will just mention that recent data
signals a greater number of IPOs in Nasdaq compared to those of LSE,
which indicates a much more attractive stock exchange both for investors
and for companies who seek to raise capital, and gives a great example
of how remarkable are sector trends in the manifestation of IPOs.
M&A Frequency
The frequency in mergers and acquisitions may indicate the dynamism
of the market.
This data is yet again not available directly from R, but we may find
it from other sources.
Nasdaq: active M&A environment in technology and biotech
sectors.
LSE: regular M&A activity across sectors like finance, energy and
mining.
Trading Costs
Nasdaq: Trading costs include brokerage fees, SEC fees, and potential
exchange fees. Generally low due to high competition among brokers.
LSE: Trading costs may include brokerage fees, stamp duty (0.5% on
purchases), and other transaction costs.
Trading Hours (time zone difference)
We may quantify the trading hours and calculate the overlap
# Nasdaq trading hours: 9:30 AM to 4:00 PM EST
# LSE trading hours: 8:00 AM to 4:30 PM GMT
# Convert trading hours to UTC
nasdaq_open_utc <- as.POSIXct("14:30", format = "%H:%M", tz = "UTC") # 9:30 AM EST is 14:30 UTC
nasdaq_close_utc <- as.POSIXct("21:00", format = "%H:%M", tz = "UTC") # 4:00 PM EST is 21:00 UTC
lse_open_utc <- as.POSIXct("08:00", format = "%H:%M", tz = "UTC")
lse_close_utc <- as.POSIXct("16:30", format = "%H:%M", tz = "UTC")
# Calculate overlap
overlap_start <- max(nasdaq_open_utc, lse_open_utc)
overlap_end <- min(nasdaq_close_utc, lse_close_utc)
if (overlap_start < overlap_end) {
overlap_hours <- as.numeric(difftime(overlap_end, overlap_start, units = "hours"))
} else {
overlap_hours <- 0
}
# Print results
cat("Overlap in Trading Hours: ", overlap_hours, " hours\n")
Overlap in Trading Hours: 2 hours
Here we have calculated the overlaping in trading hours. The low
overlaping trading hours can have huge impacts on the trading
strategies, as the information from one market will already be
incorporated at the opening of the other. This causes shifts in
volatility and investor’s behaviour, but can also be used as an
strategic advantage for diversifying their investments.
L4 Efficiency of market and information
Check if on 26 October 2017 coca cola shares were hit by the advarse
information realize on the market. (assume 26 is the information realese
date)
Load packages
library(quantmod)
Define dates
event_date <- as.Date("2017-10-26")
start_date <- event_date - 7
end_date <- event_date + 7
Retrieve Coca-Cola Data
ticker <- "KO"
getSymbols(Symbols = ticker, scr = "yahoo", from = start_date, to = end_date)
[1] "KO"
head(KO)
KO.Open KO.High KO.Low KO.Close
2017-10-19 46.37 46.79 46.32 46.59
2017-10-20 46.58 46.59 46.28 46.38
2017-10-23 46.38 46.65 46.23 46.32
2017-10-24 46.26 46.29 45.95 46.18
2017-10-25 46.37 46.76 45.93 46.05
2017-10-26 46.32 46.75 46.22 46.23
KO.Volume KO.Adjusted
2017-10-19 7515500 37.07839
2017-10-20 9646800 36.91126
2017-10-23 7153600 36.86351
2017-10-24 9539500 36.75209
2017-10-25 11994200 36.64863
2017-10-26 10569100 36.79188
Plot Closing prices
dev.new()
chartSeries(KO, name = "Coca-Cola (KO) Stock Price")

Plot with Trading Volume
# Plot closing prices with volume
chartSeries(KO, name = "Coca-Cola (KO) Stock Price with Volume", theme = chartTheme("white"), TA = "addVo()")

Calculate Daily Returns
# Calculate daily returns
KO_returns <- dailyReturn(Cl(KO))
# View the returns
KO_returns
daily.returns
2017-10-19 0.000000000
2017-10-20 -0.004507385
2017-10-23 -0.001293691
2017-10-24 -0.003022439
2017-10-25 -0.002815095
2017-10-26 0.003908801
2017-10-27 -0.003460953
2017-10-30 -0.004558261
2017-10-31 0.002616636
2017-11-01 -0.003914752
Analyze the Return on 26 October 2017
# Get the return on the event date
event_return <- KO_returns[event_date]
# Print the return
print(event_return)
daily.returns
2017-10-26 0.003908801
Compare with Market Index (S&P 500)
Retrieve S&P 500
# Retrieve S&P 500 data
getSymbols("^GSPC", src = "yahoo", from = start_date, to = end_date)
[1] "GSPC"
# Calculate daily returns for S&P 500
SP500_returns <- dailyReturn(Cl(GSPC))
Merge and Compare Returns
# Merge the returns
combined_returns <- merge(KO_returns, SP500_returns, join = "inner")
colnames(combined_returns) <- c("KO_Return", "SP500_Return")
# View combined returns
print(combined_returns)
KO_Return SP500_Return
2017-10-19 0.000000000 0.0000000000
2017-10-20 -0.004507385 0.0051168427
2017-10-23 -0.001293691 -0.0039724840
2017-10-24 -0.003022439 0.0016179083
2017-10-25 -0.002815095 -0.0046630498
2017-10-26 0.003908801 0.0012709462
2017-10-27 -0.003460953 0.0080730225
2017-10-30 -0.004558261 -0.0031924706
2017-10-31 0.002616636 0.0009444587
2017-11-01 -0.003914752 0.0015921102
Plot the Returns
# Load ggplot2 for plotting
if (!require("ggplot2")) {
install.packages("ggplot2")
}
library(ggplot2)
# Prepare data for plotting
returns_df <- data.frame(Date = index(combined_returns), coredata(combined_returns))
# Melt the data frame for ggplot2
if (!require("reshape2")) {
install.packages("reshape2")
}
library(reshape2)
returns_melted <- melt(returns_df, id.vars = "Date")
# Plot the returns
ggplot(returns_melted, aes(x = Date, y = value, color = variable)) +
geom_line(size = 1) +
labs(title = "Daily Returns: Coca-Cola vs. S&P 500",
x = "Date",
y = "Daily Return",
color = "Legend") +
geom_vline(xintercept = as.numeric(event_date), linetype = "dashed", color = "red") +
theme_minimal()

Statistical Analysis
Calculate Z-score for Event Date Return
# Calculate mean and standard deviation excluding event date
mean_return <- mean(KO_returns[-which(index(KO_returns) == event_date)])
sd_return <- sd(KO_returns[-which(index(KO_returns) == event_date)])
# Calculate z-score
z_score <- (as.numeric(event_return) - mean_return) / sd_return
# Print z-score
print(paste("Z-score on", event_date, ":", round(z_score, 2)))
[1] "Z-score on 2017-10-26 : 2.62"
Analysis of results.
In this exercise we have performed an study on the Coca Cola shares
movements on an specified event. In order to unveil the abnormal
returns, we have first obtained the Coca cola (KO) data and we have
specifically obtained the return on the event date. Afterwards, we have
obtained the equivalent data from the S&P500 in order to compare the
returns obtained by the market in the event date so as to determine
whether the returns are determined by the adverse information regarding
Coca Cola or if it was rather a generalized movement of the market as a
whole.
When observing the graphic comparison between the S&P500 and the
Coca Cola shares, we observe that their tendency matches quite fairly,
so our first intuition will be that the information had no relevant
effect on the Coca Cola. We can also observe that the Coca Cola Shares
have a clear peak in the event date that is followed by a drastic fall
in the daily returns.
However, in order to better assess the event and its effects, we have
performed an statistical analysis with the Z-Score. To analyze the
results of this statistical study we must know that if our Z-score is
greater than 2 (|Z-Score| > 2) we will be able to affirm that the
return is significantly different with a significance level of 5%.
Furthermore if the Z-Score is greater than 3, we will be able to affirm
that the return is significantly different with a significance level of
1%. In the present case, the Z-Score we obtained has a value of 2.62,
which lead us to conclude that with a significance level of 5% (or with
a confidence level of 95%), the daily returns have been significantly
different.
This ultimately leads us to affirm within our confidence level that
the adverse information that hit the Coca-Cola Shares has had an impact
in its price, which can be backed up with the observance of the graphic
in the event date as well as the trend that follows inmidiately
afterwards.
L7.3 - L7.6 Assessing the forecasting ability of the yield
curve
L7.3 - L7.5
Load packages
library(quantmod)
library(lubridate)
library(ggplot2)
Define BoT_date
# Define Beginning of Term (BoT) date
BoT_date <- as.Date("2024-05-01")
Date Range
# Define the date range
start_date <- BoT_date - 7 # One week before
end_date <- BoT_date + 7 # One week after
Retrieve 13week and 26 week T-bill Yield Data 13-week tbill symbol:
“DGS3MO” 26-week tbill symbol: “DGS6MO” We are using the daily yield
data for the constant maturity rate, as no data was to be found and used
otherwise
# Retrieve 13-week T-bill yield data
getSymbols("DGS3MO", src = "FRED", from = start_date, to = end_date)
[1] "DGS3MO"
# Retrieve 26-week T-bill yield data
getSymbols("DGS6MO", src = "FRED", from = start_date, to = end_date)
[1] "DGS6MO"
Merge Yields into one data frame and converting it to plot
# Merge the yields into one data frame
yields_data <- merge(DGS3MO, DGS6MO, join = "inner")
colnames(yields_data) <- c("Yield_13wk", "Yield_26wk")
# Convert to data frame for plotting
yields_df <- data.frame(Date = index(yields_data), coredata(yields_data))
# Remove rows with NA values
yields_df <- na.omit(yields_df)
#Plot Yields over time
# Plot the yields over time
ggplot(yields_df, aes(x = Date)) +
geom_line(aes(y = Yield_13wk, color = "13-week T-bill")) +
geom_line(aes(y = Yield_26wk, color = "26-week T-bill")) +
geom_vline(xintercept = as.numeric(as.Date(BoT_date)), linetype = "dashed", color = "red") +
labs(
title = "13-week and 26-week T-bill Yields Around BoT_date",
x = "Date",
y = "Yield (%)",
color = "T-bill Maturity"
) +
theme_minimal()

Adjust to Non-Trading Days
get_yield_on_date <- function(data, date) {
# Convert index to Date format
index(data) <- as.Date(index(data))
# Get available dates on or before the specified date
available_dates <- index(data)[index(data) <= date & !is.na(data[index(data)])]
if (length(available_dates) == 0) {
warning(paste("No data available on or before", date))
return(list(Yield = NA, Date = NA))
}
date_used <- max(available_dates)
# Get the yield
yield <- as.numeric(data[date_used])
return(list(
Yield = yield,
Date = as.Date(date_used)
))
}
Retrieve Yields on BoT_date
# Get 13-week T-bill yield on BoT_date
yield_13wk <- get_yield_on_date(DGS3MO, BoT_date)
# Get 26-week T-bill yield on BoT_date
yield_26wk <- get_yield_on_date(DGS6MO, BoT_date)
Calculate the Difference
# Calculate the yield difference
yield_difference = yield_26wk$Yield - yield_13wk$Yield
# Create a data frame to display the results
results_L73 <- data.frame(
Date = yield_13wk$Date,
Yield_13wk = yield_13wk$Yield,
Yield_26wk = yield_26wk$Yield,
Yield_Difference = yield_difference
)
print(results_L73)
NA
Additionally, we can plot our results in order to have a visual
representation
# Create a data frame for plotting the yield curve
yield_curve_df <- data.frame(
Maturity = c(13/52, 26/52), # Convert weeks to years
Yield = c(yield_13wk$Yield, yield_26wk$Yield)
)
# Plot the yield curve between 13-week and 26-week T-bills
ggplot(yield_curve_df, aes(x = Maturity, y = Yield)) +
geom_line(color = "blue") +
geom_point(color = "red", size = 3) +
labs(
title = paste("Yield Curve between 13-week and 26-week T-bills on", BoT_date),
x = "Maturity (Years)",
y = "Yield (%)"
) +
theme_minimal()

Analysis of results
In these 3 exercises we have calculated the difference in yields of
the 26-week T-bill yield and the 13-week T-bill yield at the beginning
of the school term. The difference between both yields gives us a total
amount of -0.03, which reveals a higher yield in the 13-week T-bill.
Higher yields on lower maturity bonds is a rather unsual situation,
but it can be explained due to several factors. This higher yield may be
the result of market uncertainty, in which investors look for safer and
long-term securities.
On the other hand, and answering to L7.5, this may be the result of
the expectancy of a FED’s rate cut, which would lead to even lower
yields. This reason would also explain the higher yields in the short
term. The expectancy of lower interest rates matches the direction of
the slope.
Some other reasons may be plausible, such as those regarding
liquidity needs or technical market factors, but we will not further
analyze those options.
L7.6 Did interest rates move in that direction over the school
term?
Load packages
library(quantmod)
library(lubridate)
library(reshape2)
library(ggplot2)
library(xts)
Define End of Term Date
#Define BoT_date
BoT_date <- as.Date("2024-05-01")
# Define End of Term (EoT) date
EoT_date <- as.Date("2024-09-30")
Retrieve Yield Data Over the term
# Retrieve 13-week T-bill yield data over the term
getSymbols("TB3MS", src = "FRED", from = BoT_date, to = EoT_date)
[1] "TB3MS"
TB3MS_term <- TB3MS
# Retrieve 26-week T-bill yield data over the term
getSymbols("TB6MS", src = "FRED", from = BoT_date, to = EoT_date)
[1] "TB6MS"
TB6MS_term <- TB6MS
Adjust to Non-Trading Days
# Function to get yield on a specific date
get_yield_on_date <- function(data, date, use_next = FALSE) {
# Convert index to Date format
index(data) <- as.Date(index(data))
if (use_next) {
# Get the next available date after the specified date
available_dates <- index(data)[index(data) >= date & !is.na(data[index(data)])]
if(length(available_dates) == 0) {
warning(paste("No data available after", date))
return(list(Yield = NA, Date = NA))
}
date_used <- min(available_dates)
} else {
# Get the last available date on or before the specified date
available_dates <- index(data)[index(data) <= date & !is.na(data[index(data)])]
if (length(available_dates) == 0) {
warning(paste("No data available before", date))
return(list(Yield = NA, Date = NA))
}
date_used <- max(available_dates)
}
# Get the yield
yield <- as.numeric(data[date_used])
return(list(
Yield = yield,
Date = as.Date(date_used)
))
}
Plot the yields over time
# Combine the yields into one data frame
yields_combined <- merge(TB3MS_term, TB6MS_term)
colnames(yields_combined) <- c("Yield_13wk", "Yield_26wk")
# Plot the yields over the term
yields_df <- data.frame(Date = index(yields_combined), coredata(yields_combined))
yields_df <- na.omit(yields_df)
# Melt the data for plotting
yields_melted <- melt(yields_df, id.vars = "Date")
# Plot
ggplot(yields_melted, aes(x = Date, y = value, color = variable)) +
geom_line(linewidth = 1) +
labs(title = "13-week and 26-week T-bill Yields Over the Term",
x = "Date",
y = "Yield (%)",
color = "Yield") +
theme_minimal()

Analyze the Movement of Interest Rates
#Get Yields at BoT_date
yield_13wk <- get_yield_on_date(TB3MS_term, BoT_date, use_next = FALSE)
yield_26wk <- get_yield_on_date(TB6MS_term, BoT_date, use_next = FALSE)
# Get yields at EoT_date
yield_13wk_EoT <- get_yield_on_date(TB3MS_term, EoT_date, use_next = FALSE)
yield_26wk_EoT <- get_yield_on_date(TB6MS_term, EoT_date, use_next = FALSE)
# Create a data frame to compare BoT and EoT yields
comparison_df <- data.frame(
Date = c(yield_13wk$Date, yield_13wk_EoT$Date),
Yield_13wk = c(yield_13wk$Yield, yield_13wk_EoT$Yield),
Yield_26wk = c(yield_26wk$Yield, yield_26wk_EoT$Yield),
Period = c("BoT", "EoT")
)
print(comparison_df)
Analysis of results
Interest rates, as we have represented graphically, yields over the
term have fallen progressively. A decrease in yields indicates a
downward movement in the interest rates. This movement matches the
expectation we had extracted in the Beginning of Term, which was the
decrease in yields/interest rates. Furthermore, yet again we have lower
yields in the 13-week t-bill, which may indicate still further decreases
in interest rates. This data matches with the FED rate cut in mid
September, and the a positive forecast of further rate cuts.
L7.14 to L7.17
Define Beginning and End of Term dates
# Define Beginning of Term (BoT) and End of Term (EoT) dates
BoT_date <- as.Date("2023-05-01")
EoT_date <- as.Date("2023-09-30")
L7.14. Difference Between Yields on High-Yield and High-Quality
Corporate Bonds
Load packages
library(quantmod)
Retrieve Yield Data
# Retrieve Moody's Aaa Corporate Bond Yield (High-Quality)
getSymbols("DAAA", src = "FRED", from = BoT_date - 7, to = BoT_date + 7)
[1] "DAAA"
# Retrieve ICE BofA US High Yield Index Effective Yield (High-Yield)
getSymbols("BAMLH0A0HYM2EY", src = "FRED", from = EoT_date - 7, to = EoT_date + 7)
[1] "BAMLH0A0HYM2EY"
Define a Function to Get Yields on Specific Dates
# Function to get yield on a specific date
get_yield_on_date <- function(data, date) {
# Convert index to Date format
index(data) <- as.Date(index(data))
# Get available dates on or before the specified date
available_dates <- index(data)[index(data) <= date & !is.na(data[index(data)])]
if (length(available_dates) == 0) {
warning(paste("No data available on or before", date))
return(list(Yield = NA, Date = NA))
}
date_used <- max(available_dates)
# Get the yield
yield <- as.numeric(data[date_used])
return(list(
Yield = yield,
Date = as.Date(date_used)
))
}
Retrieve Data on Specific Dates
# Get High-Quality Corporate Bond Yield on BoT_date
yield_HQ_BoT <- get_yield_on_date(DAAA, BoT_date)
# Get High-Yield Corporate Bond Yield on EoT_date
yield_HY_EoT <- get_yield_on_date(BAMLH0A0HYM2EY, EoT_date)
Calculate the Difference
Yield difference represents the change between the high-yield
corporate bond yield at the end of the term and the high-quality
corporate bond yield at the beginning of the term
A positive difference indicates that the high-yield bond yield at EoT
is higher than the high-quality bond yield at BoT
# Calculate the yield difference
yield_difference_L714 <- yield_HY_EoT$Yield - yield_HQ_BoT$Yield
# Create a data frame to display the results
results_L714 <- data.frame(
Description = c("High-Quality Corporate Bond Yield at BoT", "High-Yield Corporate Bond Yield at EoT"),
Date = c(yield_HQ_BoT$Date, yield_HY_EoT$Date),
Yield = c(yield_HQ_BoT$Yield, yield_HY_EoT$Yield)
)
print(results_L714)
cat("Yield Difference (High-Yield - High-Quality):", round(yield_difference_L714, 2), "%\n")
Yield Difference (High-Yield - High-Quality): 4.19 %
Analysis of results
We can observe a difference of 4.19 which reflects that the
high-yield will result in higher returns compared to the high quality.
This results are explained due to the already explained dynamics in
which the riskier the investment, the higher its return will be. In the
high-quality bonds we prioritize minimizing the risk at expense of a
lower yield, whereas in the high-yield we will accept a higher risk for
a higher expected return.
L7.15 Change in Long-Term Treasury Bond Yield and Impact on Bond
Prices
Retrieve Yield Data
# Retrieve 10-Year Treasury Yield data
getSymbols("DGS10", src = "FRED", from = BoT_date - 7, to = EoT_date + 7)
[1] "DGS10"
Retrieve Yields on Specified Dates
# Get 10-Year Treasury Yield on BoT_date
yield_10yr_BoT <- get_yield_on_date(DGS10, BoT_date)
# Get 10-Year Treasury Yield on EoT_date
yield_10yr_EoT <- get_yield_on_date(DGS10, EoT_date)
Calculate the Change in Yield
# Calculate the change in yield
yield_change_L715 <- yield_10yr_EoT$Yield - yield_10yr_BoT$Yield
# Create a data frame to display the results
results_L715 <- data.frame(
Date = c(yield_10yr_BoT$Date, yield_10yr_EoT$Date),
Period = c("BoT", "EoT"),
Yield_10yr_Treasury = c(yield_10yr_BoT$Yield, yield_10yr_EoT$Yield)
)
print(results_L715)
cat("Change in 10-Year Treasury Yield (EoT - BoT):", round(yield_change_L715, 2), "%\n")
Change in 10-Year Treasury Yield (EoT - BoT): 1 %
Analysis of results
The bond prices follow an inverse relationship with the bond yields.
Therefore, as we have calculated an appreciation in the yield of a 1%,
we may derive that the price has decreased over the term.
L7.16 Comparing Changes in Yields of Treasury, Municipal, and
Corporate Bonds
Retrieve Yield Data
# Retrieve Treasury Yield data
getSymbols("DGS10", src = "FRED", from = BoT_date - 7, to = EoT_date + 7)
[1] "DGS10"
# Retrieve Corporate Bond Yield data
getSymbols("DAAA", src = "FRED", from = BoT_date - 7, to = EoT_date + 7)
[1] "DAAA"
# Attempt to Retrieve Municipal Bond Yield data
# Note: Municipal bond data is limited on FRED; we may need to use available proxies or acknowledge limitations.
#getSymbols("MUNI10Y", src = "FRED", from = BoT_date - 7, to = EoT_date + 7) #WE ARE NOT ABLE TO FIND ANY DATA ON MUNICIPAL BONDS
Analysis of results
As we have mentioned earlier, we have found certain issued to
retrieve municipal bonds data. However, we can determine from what has
been analyzed so far in previous answers that bond yields have fallen
over the course of the school term, primarily due to the fall in
interest rates and the expectancy of further rate cuts. Other factors
such as inflation and overall economic conditions also affect this
movements.
L7.17 Change in Premium on High-Yield Corporate Bonds Relative to
Treasury Bonds
Retrieve High Yield Corporate Bond Yield on BoT_date
# Retrieve High-Yield Corporate Bond Yield data for BoT_date
getSymbols("BAMLH0A0HYM2EY", src = "FRED", from = BoT_date - 7, to = BoT_date + 7)
[1] "BAMLH0A0HYM2EY"
# Get High-Yield Corporate Bond Yield on BoT_date
yield_HY_BoT <- get_yield_on_date(BAMLH0A0HYM2EY, BoT_date)
#Get Yield on Treasury bond on BoT_date and EoT_date
yield_Treasury_BoT <- get_yield_on_date(DGS10, BoT_date)
yield_Treasury_EoT <- get_yield_on_date(DGS10, EoT_date)
Calculate Premiums
# Premium at BoT
premium_BoT <- yield_HY_BoT$Yield - yield_Treasury_BoT$Yield
# Premium at EoT
premium_EoT <- yield_HY_EoT$Yield - yield_Treasury_EoT$Yield
Compare Premiums
# Create a data frame to display the results
results_L717 <- data.frame(
Date = c(yield_Treasury_BoT$Date, yield_Treasury_EoT$Date),
Period = c("BoT", "EoT"),
Yield_High_Yield_Corporate = c(yield_HY_BoT$Yield, yield_HY_EoT$Yield),
Yield_Treasury = c(yield_Treasury_BoT$Yield, yield_Treasury_EoT$Yield),
Premium = c(premium_BoT, premium_EoT)
)
print(results_L717)
Change in premiums
#Change in premium expressed in percentage points
change_in_premium <- round(premium_EoT, 2) - round(premium_BoT)
cat("change in premium:", change_in_premium)
change in premium: -0.79
Analysis of returns
In this last exercise of this section, we have calculated the premium
of high yield corporate bonds against the treasury bond yields. As we
know, high-yields will have higher risk and higher expected returns. The
premium has fallen 0.79 points during the school term, which may
indicate a reduction of credit risk and an overall improvement in the
economy. This means that there is less risk of not getting non-payments,
and as we know, with lower risks we shall obtain lower expected returns
or yields. Investors necessities or preferences and their shifts may
also have an impact on the premiums as the general risk tolerance
fluctuate in the market.
L11.1 - L11.6
Definitions
Futures Contract
A futures contract is a financial derivative upon someone agrees to
buy or sell a determinate commodity asset or security at an
predetermined price and an specific time in the future. The buyer agrees
and becomes obliged to buy and receive the asset whereas the seller
agrees to provide and make deliver of the asset.
Call Option
A call option is a type of financial contract where the buyer is
given the right to buy a certain asset or instrument at an specified
price and time. The seller on the other hand is obliged to sell the
asset if the buyer exercises the call. The option is bought under a
premium, so if the asset goes down in price and the buyer does not
execute the option, the seller will profit from the premium. However, if
the asset price increases and the buyer executes the option, the profit
the buyer will have is the end value of the stock (payoff) minus the
premium paid for the option. Call options have limited loses for the
buyers (the premium is the maximum loss) but has no profit limit. Call
options are divided into Long Call Options and Short Call Options(in the
short call options, it is the seller the one who promises to sell an
asset at a certain price in the date of expiration)
When using call options, it is often to implement an strategy called
hedging, in which you also take the opposite position in order to
mitigate potential losses. That is, that if we are using call options,
we might also buy put options for the same asset so that we can reduce
the losses in the case that the striking price is not reached at the
date of expiration.
Load Packages
# Load required packages
library(quantmod)
library(lubridate)
library(PerformanceAnalytics)
Define Beginning and End of Term Dates
# Define Beginning of Term (BoT) and End of Term (EoT) dates
BoT_date <- as.Date("2024-05-01")
EoT_date <- as.Date("2024-09-30")
L11.1 Calculating the Difference in the Dollar Value of the S&P
500 Futures Contract
-You purchased an S&P 500 futures contract at the beginning of
the term.
-You sold the same futures contract at the end of the term.
-The contract value is futures price times $250.
Since getting historical futures prices can be challenging, we’ll use
the S&P 500 index (^GSPC) as a proxy for the futures prices. ´
- Retrieve S&P500 index data
start_date <- BoT_date - 7
end_date <- EoT_date + 7
getSymbols("^GSPC", src = "yahoo", from = start_date, to = end_date)
[1] "GSPC"
- Define a Function to Get Prices on Specific Dates
# Function to get the adjusted closing price on a specific date
get_price_on_date <- function(data, date) {
index(data) <- as.Date(index(data))
available_dates <- index(data)[index(data) <= date]
if (length(available_dates) == 0) {
warning(paste("No data available on or before", date))
return(list(Price = NA, Date = NA))
}
date_used <- max(available_dates)
price <- as.numeric(Cl(data[date_used]))
return(list(
Price = price,
Date = as.Date(date_used)
))
}
Get S&P500 prices at BoT and EoT
price_BoT <- get_price_on_date(`GSPC`, BoT_date)
price_EoT <- get_price_on_date(`GSPC`, EoT_date)
cat("S&P 500 Index Price at BoT (", price_BoT$Date, "): ", price_BoT$Price, "\n", sep = "")
S&P 500 Index Price at BoT (19844): 5018.39
cat("S&P 500 Index Price at EoT (", price_EoT$Date, "): ", price_EoT$Price, "\n", sep = "")
S&P 500 Index Price at EoT (19996): 5762.48
Calculate the Contract Values
contract_value_BoT <- price_BoT$Price * 250
contract_value_EoT <- price_EoT$Price * 250
Calculate the difference
difference <- contract_value_EoT - contract_value_BoT
cat("Difference in Contract Values: $", round(difference, 2), "\n", sep = "")
Difference in Contract Values: $186022.5
Analysis
The significant increase in the price of the S&P500 during the
term has led to a final difference in the contract value of 186022.5
USD. In this example we can easily observe how the fluctuation of price
can enormously affect the price of the contract, which makes hedging
strategies much more attractive. Although they may reduce the total
profit, a futures trader will overall benefit from them as loses will be
greatly mitigated and the outcome of a bad operation will not be as
catastrophic as it may be if there is no counterpart that backs it
up.
L11.2 Calculating Your Return from the Futures Position
-You invested an initial margin of 20% of the futures contract value
at BoT -Your return is the gain from the futures position divided by
your initial investment
Calculate Initial Investment
initial_investment <- 0.20 * contract_value_BoT
cat("Initial Investment (20% Margin): $", round(initial_investment, 2), "\n", sep = "")
Initial Investment (20% Margin): $250919.5
Calculate Return on Investment
# Calculate the return
return_futures <- difference / initial_investment
# Print the return as a percentage
cat("Return on Futures Position: ", round(return_futures * 100, 2), "%\n", sep = "")
Return on Futures Position: 74.14%
Analysis
As a follow up from the previous exercise, we have the final return
of the futures position that sums to a total of 74.14% in the duration
of the school term. With such high returns, and as we have explained
before, we shall bare in mind that equally high losses may be obtained.
Therefore, deep knowledge of the underlying asset and a good trading
strategy are extremely important in order to perform such
operations.
L11.3 Annualizing Your Return
-The return calculated is for the duration of the school term (5
months) -To annualize the return, we multiply it by 12/m, where m ~ 5
months
Calculate the annualization
m <- as.numeric(difftime(EoT_date, BoT_date, units = "days")) / 30.44
annualized_return_futures <- return_futures * (12 / m)
cat("Annualized Return on Futures Position: ", round(annualized_return_futures * 100, 2), "%\n", sep = "")
Annualized Return on Futures Position: 178.16%
L11.4 Calculating the Return from Purchasing a Call Option on Apple
Inc. (AAPL)
-Purchase of a call option representing 100 shares of AAPL at BoT
-Determine the return based on the option premiums at BOT and EoT If the
premium at EoT is unavailable, calculate the return based on exercising
the option
We will estimate the option premiums using the Black-Scholes
Model
Retrieve AAPL Stock Prices
getSymbols("AAPL", src = "yahoo", from = start_date, to = end_date)
[1] "AAPL"
price_AAPL_BoT <- get_price_on_date(AAPL, BoT_date)
price_AAPL_EoT <- get_price_on_date(AAPL, EoT_date)
cat("AAPL Stock Price at BoT (", price_AAPL_BoT$Date, "): $", round(price_AAPL_BoT$Price, 2), "\n", sep = "")
AAPL Stock Price at BoT (19844): $169.3
cat("AAPL Stock Price at EoT (", price_AAPL_EoT$Date, "): $", round(price_AAPL_EoT$Price, 2), "\n", sep = "")
AAPL Stock Price at EoT (19996): $233
Set the Strike Price
Strike_Price <- ceiling(price_AAPL_BoT$Price / 5) * 5
cat("Option Strike Price: $", Strike_Price, "\n", sep = "")
Option Strike Price: $170
Estimate Volatility
start_date_vol <- BoT_date - years(1)
getSymbols("AAPL", src = "yahoo", from = start_date_vol, to = BoT_date)
[1] "AAPL"
returns <- na.omit(dailyReturn(Cl(AAPL)))
volatility <- sd(returns) * sqrt(252)
cat("Estimated Annualized Volatility: ", round(volatility * 100, 2), "%\n", sep = "")
Estimated Annualized Volatility: 19.67%
Define the Black-Scholes Function
BlackScholesCall <- function(S, K, r, T, sigma) {
d1 <- (log(S / K) + (r + sigma^2 / 2) * T) / (sigma * sqrt(T))
d2 <- d1 - sigma * sqrt(T)
C <- S * pnorm(d1) - K * exp(-r * T) * pnorm(d2)
return(C)
}
Calculate Option Premiums at BoT and EoT
# Set risk-free rate (e.g., 2%)
risk_free_rate <- 0.02
# Time to expiration (assume option expires on next month's third Friday)
T_BoT <- as.numeric(difftime(as.Date("2024-11-15"), price_AAPL_BoT$Date, units = "days")) / 365
T_EoT <- as.numeric(difftime(as.Date("2024-11-15"), price_AAPL_EoT$Date, units = "days")) / 365
C_BoT <- BlackScholesCall(S = price_AAPL_BoT$Price, K = Strike_Price, r = risk_free_rate, T = T_BoT, sigma = volatility)
C_EoT <- BlackScholesCall(S = price_AAPL_EoT$Price, K = Strike_Price, r = risk_free_rate, T = T_EoT, sigma = volatility)
cat("Option Premium at BoT: $", round(C_BoT, 2), "\n", sep = "")
Option Premium at BoT: $10.32
cat("Option Premium at EoT: $", round(C_EoT, 2), "\n", sep = "")
Option Premium at EoT: $63.43
Calculate the Return from the Option
# Calculate return based on selling the option at EoT
if (!is.na(C_EoT)) {
return_option_sell <- (C_EoT - C_BoT) / C_BoT
cat("Return from Selling the Call Option: ", round(return_option_sell * 100, 2), "%\n", sep = "")
} else {
cat("Option premium at EoT is unavailable.\n")
}
Return from Selling the Call Option: 514.51%
# Calculate return based on exercising the option
if (price_AAPL_EoT$Price > Strike_Price) {
profit_exercise <- (price_AAPL_EoT$Price - Strike_Price) - C_BoT
return_option_exercise <- profit_exercise / C_BoT
cat("Return from Exercising the Call Option: ", round(return_option_exercise * 100, 2), "%\n", sep = "")
} else {
profit_exercise <- -C_BoT
return_option_exercise <- profit_exercise / C_BoT
cat("Option expired worthless. Return from Exercising the Call Option: ", round(return_option_exercise * 100, 2), "%\n", sep = "")
}
Return from Exercising the Call Option: 510.36%
Analysis
In this exercise, we have opted for calculating the premiums with the
use of the Black Scholes Model. This decision has taken due to the
inaccessibility of direct data about the premiums for the options. The
Black-Scholes Model allows us to calculate the theoretical value of
derivatives by taking into account 5 variables: strike price of the
option, current stock price, time to expiration, risk-free rate and
volatility. The estimation obtained with this model may derive from the
real values. When using this model, we should also take into account
that depending on our location, options could be exercised before the
expiration date. However for this exercise we will not take that into
account. We have also taken into account the two options that could
happen when buying this call option: to exercise it or to buy it. When
we sell the call option, the total non-annualized return will be
514.51%, whereas if we exercise it it is 510.36%. In the case of
selling, the profit or return obtained will be calculated with the
premiums. If the premium at the End of Term was unavailable or we
decided to exercise the option, the profit obtained will be the price of
the stock at the moment of exercise minus the strike price and the
premium. Both returns are rather similar, although the return from
selling the option is noticeably higher.
L11.5 Annualizing the Return on Your Option
# Annualize the Returns
annualized_return_option_sell <- (return_option_sell)*(12 / m)
annualized_return_option_exercise <- ((return_option_exercise)*(12 / m))
# Display the Annualized Returns
cat("\nAnnualized Return from Selling the Call Option: ", round(annualized_return_option_sell * 100, 2), "%\n", sep = "")
Annualized Return from Selling the Call Option: 1236.44%
cat("Annualized Return from Exercising the Call Option: ", round(annualized_return_option_exercise * 100, 2), "%\n", sep = "")
Annualized Return from Exercising the Call Option: 1226.47%
L11.6 Comparing the Return on Your Call Option to Investing in the
Stock
Calculate the Return from Investing in AAPL stock
return_stock <- (price_AAPL_EoT$Price - price_AAPL_BoT$Price) / price_AAPL_BoT$Price
annualized_return_stock <- return_stock * (12 / m)
cat("Return from Investing in AAPL Stock: ", round(return_stock * 100, 2), "%\n", sep = "")
Return from Investing in AAPL Stock: 37.63%
cat("Annualized Return on AAPL Stock: ", round(annualized_return_stock * 100, 2), "%\n", sep = "")
Annualized Return on AAPL Stock: 90.42%
Compare the returns
cat("\nComparison of Returns:\n")
Comparison of Returns:
cat("Annualized Return on Call Option: ", round(annualized_return_option_sell * 100, 2), "%\n", sep = "")
Annualized Return on Call Option: 1236.44%
cat("Annualized Return from Exercising the Call Option: ", round(annualized_return_option_exercise * 100, 2), "%\n", sep = "")
Annualized Return from Exercising the Call Option: 1226.47%
cat("Annualized Return on AAPL Stock: ", round(annualized_return_stock * 100, 2), "%\n", sep = "")
Annualized Return on AAPL Stock: 90.42%
Analysis
In this final exercise we compare the returns of the Return of the
Stock with those of the call option, both when selling and when
exercising it. As we can observe, the potential returns of the call
options hugely outweigh those of the Stock itself. In the case of the
call option, as we have mentioned, the potential loss for the buyer is
limited to the premium that they shall pay when buying the option.
However, for the seller of this option, the risk becomes extremely
noticeable.
L11.8 - L11.12. Measuring and explaining exchange rate
movements
Explanations Ahead
In this section we will be measuring and explaining exchange rate
movements. In order to better understand this phenomena we will have to
take into account certain concepts.
Currency fluctuation
When we talk about current fluctuation, we are referring to the
change in the relative value of one against the other. In other words,
is the change in the equivalencies of the value of the currencies.
Exchange Rates
Exchange Rates are the numerical representation of the currency
fluctuation. That is the value of one currency against the other in an
specific moment. Exchange Rates fluctuate and are great economical
indicators. There are several reasons for the fluctuation of exchange
rates, such as interest rates, general macroeconomic data of each
country, political policies and stability, inflation rates, data and
policy, and foreign investments. Another factor that creates fluctuation
in exchange rates is the speculation.
Effects
The fluctuations in currency (and exchange rates) have an impact in
several aspects of the economy. 1. International trade. A weak currency
easily benefits from exports, while a strong one may reduce their export
capability.
2. Inflation. A strong currency will have a lot of import capability and
will be able to keep inflation stable. However, a weak currency will
have higher import costs and will overall increase domestic inflation.
3. Investment. The stability or strengthen of a currency usually
indicate an stable/strong economy and political situation. Therefore, it
will be much more attractive to make an investment in those countries
with a strong currency. Oppositely, a weak currency (or a constantly
changing one) will indicate weakness and instability. 4. Economic
stability and growth. Impacts in GDP, investment, inflation and
international trade all contribute towards the economy of a country,
whether making in stable and strong or weak a unstable.
Before the exercises
Load Packages
# Load required packages
library(quantmod)
library(lubridate)
library(PerformanceAnalytics)
Define Beginning and End of Term Dates
# Define Beginning of Term (BoT) and End of Term (EoT) dates
BoT_date <- as.Date("2024-05-01")
EoT_date <- as.Date("2024-09-30")
L11.8 Determining the Percentage Change in the Value of the British
Pound
Retrieve GPB/USD Exchange Rate Data
# Get GBP/USD exchange rate data
getSymbols("GBPUSD=X", src = "yahoo", from = BoT_date - 7, to = EoT_date + 7, auto.assign = TRUE)
[1] "GBPUSD=X"
# Assign data to a variable
gbp_usd_data <- `GBPUSD=X`
Get exchange Rates at BoT and EoT
# Function to get the exchange rate on a specific date
get_rate_on_date <- function(data, date) {
index(data) <- as.Date(index(data))
available_dates <- index(data)[index(data) <= date]
if (length(available_dates) == 0) {
warning(paste("No data available on or before", date))
return(list(Rate = NA, Date = NA))
}
date_used <- max(available_dates)
rate <- as.numeric(Cl(data[date_used]))
return(list(
Rate = rate,
Date = as.Date(date_used)
))
}
# Get rates at BoT and EoT
gbp_rate_BoT <- get_rate_on_date(gbp_usd_data, BoT_date)
gbp_rate_EoT <- get_rate_on_date(gbp_usd_data, EoT_date)
# Print the exchange rates
cat("GBP/USD Rate at BoT (", gbp_rate_BoT$Date, "): ", round(gbp_rate_BoT$Rate, 4), "\n", sep = "")
GBP/USD Rate at BoT (19844): 1.2539
cat("GBP/USD Rate at EoT (", gbp_rate_EoT$Date, "): ", round(gbp_rate_EoT$Rate, 4), "\n", sep = "")
GBP/USD Rate at EoT (19996): 1.3376
Calculate the Percentage Change
# Calculate the percentage change
gbp_percentage_change <- (gbp_rate_EoT$Rate - gbp_rate_BoT$Rate) / gbp_rate_BoT$Rate * 100
# Print the result
cat("Percentage Change in GBP/USD: ", round(gbp_percentage_change, 2), "%\n", sep = "")
Percentage Change in GBP/USD: 6.67%
Determine Appreciation or Depreciation
if (gbp_percentage_change > 0) {
gbp_result <- "appreciated"
} else if (gbp_percentage_change < 0) {
gbp_result <- "depreciated"
} else {
gbp_result <- "remained the same"
}
cat("The British pound has ", gbp_result, " against the US dollar over the school term.\n", sep = "")
The British pound has appreciated against the US dollar over the school term.
Analysis
The appreciation of the British pound against the US dollar may
indicate, as we have previously explained, an strengthening of UK’s
economy against the US. Although we cannot be certain without much
further analysis of what may have caused this notorious appreciation of
the currency, we can presume is a mix of several factors that have been
already explained. This could include favorable GDP data for the UK, an
aggressive monetary policy from the Bank of England with higher interest
rates, or the stabilization of certain aspects regarding Brexit. On the
other side, the US may have become somewhat less attractive for
investors who look for riskier opportunities, slow inflation with a less
aggressive monetary policy or overall discontent with the political
situation. The upcoming USA Presidential Elections may have risen
certain concerns and created a sense of instability that has been
portrayed in the exchange rate against the British Pound.
L11.9 Determining the Percentage Change in the Value of the Japanese
Yen
Retrieve USD/JPY Exchange Rate Data
# Get USD/JPY exchange rate data
getSymbols("JPY=X", src = "yahoo", from = BoT_date - 7, to = EoT_date + 7, auto.assign = TRUE)
[1] "JPY=X"
# Assign data to a variable
usd_jpy_data <- `JPY=X`
Get Exchange Rates at BoT and EoT
# Get rates at BoT and EoT
jpy_rate_BoT <- get_rate_on_date(usd_jpy_data, BoT_date)
jpy_rate_EoT <- get_rate_on_date(usd_jpy_data, EoT_date)
# Print the exchange rates
cat("USD/JPY Rate at BoT (", jpy_rate_BoT$Date, "): ", round(jpy_rate_BoT$Rate, 4), "\n", sep = "")
USD/JPY Rate at BoT (19844): 155.704
cat("USD/JPY Rate at EoT (", jpy_rate_EoT$Date, "): ", round(jpy_rate_EoT$Rate, 4), "\n", sep = "")
USD/JPY Rate at EoT (19996): 143.71
Calculate the Percentage Rate
# Invert the rates to get JPY per USD
jpy_per_usd_BoT <- 1 / jpy_rate_BoT$Rate
jpy_per_usd_EoT <- 1 / jpy_rate_EoT$Rate
# Calculate the percentage change
jpy_percentage_change <- (jpy_per_usd_EoT - jpy_per_usd_BoT) / jpy_per_usd_BoT * 100
# Print the result
cat("Percentage Change in JPY/USD: ", round(jpy_percentage_change, 2), "%\n", sep = "")
Percentage Change in JPY/USD: 8.35%
Determine Appreciation or Depreciation
if (jpy_percentage_change > 0) {
jpy_result <- "appreciated"
} else if (jpy_percentage_change < 0) {
jpy_result <- "depreciated"
} else {
jpy_result <- "remained the same"
}
cat("The Japanese yen has ", jpy_result, " against the US dollar over the school term.\n", sep = "")
The Japanese yen has appreciated against the US dollar over the school term.
Analysis
Just as we have explained in the previous question. the US may have
faced a period of instability and slowness that could have caused a
lower demand for US dollars. Conversely, the Bank of Japan, may have
adopted a more strict regulation (in opposition with its traditional
approach) due to high inflation or due to normalization strategies,
which may have caused a reaction in the currency markets. Japan may have
also had positive reports or a recovery in its trade balance.
L11.10 Determining the Percentage Change in the Value of the Mexican
Peso
Retrieve USD/MXN Exchange Rate Data
# Get USD/MXN exchange rate data
getSymbols("MXN=X", src = "yahoo", from = BoT_date - 7, to = EoT_date + 7, auto.assign = TRUE)
[1] "MXN=X"
# Assign data to a variable
usd_mxn_data <- `MXN=X`
Get Exchange Rates at BoT and EoT
# Get rates at BoT and EoT
mxn_rate_BoT <- get_rate_on_date(usd_mxn_data, BoT_date)
mxn_rate_EoT <- get_rate_on_date(usd_mxn_data, EoT_date)
# Print the exchange rates
cat("USD/MXN Rate at BoT (", mxn_rate_BoT$Date, "): ", round(mxn_rate_BoT$Rate, 4), "\n", sep = "")
USD/MXN Rate at BoT (19844): 16.9286
cat("USD/MXN Rate at EoT (", mxn_rate_EoT$Date, "): ", round(mxn_rate_EoT$Rate, 4), "\n", sep = "")
USD/MXN Rate at EoT (19996): 19.6636
Calculate the Percentage Change
# Invert the rates to get MXN per USD
mxn_per_usd_BoT <- 1 / mxn_rate_BoT$Rate
mxn_per_usd_EoT <- 1 / mxn_rate_EoT$Rate
# Calculate the percentage change
mxn_percentage_change <- (mxn_per_usd_EoT - mxn_per_usd_BoT) / mxn_per_usd_BoT * 100
# Print the result
cat("Percentage Change in MXN/USD: ", round(mxn_percentage_change, 2), "%\n", sep = "")
Percentage Change in MXN/USD: -13.91%
Determine Appreciation or Depreciation
if (mxn_percentage_change > 0) {
mxn_result <- "appreciated"
} else if (mxn_percentage_change < 0) {
mxn_result <- "depreciated"
} else {
mxn_result <- "remained the same"
}
cat("The Mexican peso has ", mxn_result, " against the US dollar over the school term.\n", sep = "")
The Mexican peso has depreciated against the US dollar over the school term.
Analysis
Have we not seen the previous results, we might have had the initial
thought that these results are the manifestation of a strong US Dollar,
which strengthens against the Mexican Peso. However, we already know
that the USD had weakened against the other two currencies analyzed, so
we may assume that this is not the outcome of an strong USA but rather a
really worsened Mexico. If we take a look into Mexico’s politics during
the Term Period, we will notice that Presidential Elections took place,
with the victory of Claudia Sheinbaum. The difference in positions with
the USA in several international matters may have pushed this drop in
the Mexican Peso, which has not yet stopped as of today, although our
End of Term Date only dates until September.
L11.11 Determining the Per Unit Gain or Loss for British Pound
Futures
Determine the per unit gain or loss if you had purchased British
pound futures at the beginning of the term and sold them at the end of
the term. Use GPB/USD Exchange rates as Proxy.
Calculate the Per Unit Gain or Loss
# Calculate the per unit gain or loss
per_unit_gain_loss <- gbp_rate_EoT$Rate - gbp_rate_BoT$Rate
# Print the result
cat("Per Unit Gain/Loss for GBP Futures: $", round(per_unit_gain_loss, 4), " per GBP\n", sep = "")
Per Unit Gain/Loss for GBP Futures: $0.0837 per GBP
In this exercise we have determined the gain per GPB for the futures
contract.
L11.12 Determining the Dollar Amount of Your Gain or Loss on the
Futures Contract
Given that a single futures contract on British pounds represents
62,500 pounds, determine the dollar amount of your gain or loss.
# Number of pounds per futures contract
contract_size <- 62500
# Total gain or loss
total_gain_loss <- per_unit_gain_loss * contract_size
# Print the result
cat("Total Gain/Loss on Futures Contract: $", round(total_gain_loss, 2), "\n", sep = "")
Total Gain/Loss on Futures Contract: $5229.96
Determine if you Gained or Lost
if (total_gain_loss > 0) {
futures_result <- "gained"
} else if (total_gain_loss < 0) {
futures_result <- "lost"
} else {
futures_result <- "broke even"
}
cat("You have ", futures_result, " $", abs(round(total_gain_loss, 2)), " on the futures contract.\n", sep = "")
You have gained $5229.96 on the futures contract.
With a gain per GPB of 0.0837 USD and an amount of 62500 pounds, we
will have ended at the end of term with a total gain of 5229.96 USD.
This has been possible, as we know, thanks to the appreciation of the
GPB against the USD, which he have already analyzed previously.
LS0tDQp0aXRsZTogIkZpbmFuY2lhbCBNYXJrZXRzIFByb2plY3QiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KIyMgQXV0aG9yczogIkpvc8OpIEx1aXMgU3XDoXJleiBHb256w6FsZXogKDEzNzU3NikgYW5kIEpha2UgT2xpdmVyIEdvZGRhcmQgKDEzNzYzMykiDQojIyBEYXRlOiAiMDItMTItMjAyNCINCiMjIFRlYW0gcGFydGljaXBhdGlvbnM6DQpKb3PDqSBMdWlzIFN1w6FyZXo6IENvZGUgd3JpdGluZyBhbmQgYW5hbHlzaXMgb2YgcmVzdWx0cw0KSmFrZSBPbGl2ZXIgR29kZGFyZDogcHJvamVjdCBzdHJ1Y3R1cmluZywgcmV2aXNpbmcgYW5kIGNvcnJlY3RpbmcgbWlzdGFrZXMgb2YgdGhlIG91dGNvbWUuIA0KDQojIyBBdXRob3JzJyBzdGF0ZW1lbnQgb2Ygbm9uLWluZnJpZ2VtZW50IG9mIG90aGVycycgY29weXJpZ2h0cw0KV2UgaGVyZWJ5IGRlY2xhcmUgdGhhdCB0aGUgd29yayBzdWJtaXR0ZWQgaXMgb3JpZ2luYWwgYW5kIGhhcyBiZWVuIGNyZWF0ZWQgc29sZWx5IGJ5IHVzLiBXZSBjb25maXJtIHRoYXQgd2UgaGF2ZSBub3QgdXNlZCBvciBpbmNvcnBvcmF0ZWQgYW55IG1hdGVyaWFsIHRoYXQgaW5mcmluZ2VzIHVwb24gdGhlIGNvcHlyaWdodHMgb2Ygb3RoZXJzLiBBbGwgc291cmNlcyBhbmQgcmVmZXJlbmNlcyB1c2VkIGluIHRoZSBjcmVhdGlvbiBvZiB0aGlzIHdvcmsgaGF2ZSBiZWVuIHByb3Blcmx5IGFja25vd2xlZGdlZCBhbmQgY2l0ZWQgaW4gYWNjb3JkYW5jZSB3aXRoIGFwcGxpY2FibGUgZ3VpZGVsaW5lcy4NCg0KIyMgIEF1dGhvcnPigJkgc3RhdGVtZW50IGFzIHRvIGhvdyB0aGUgQUkgdG9vbCB3YXMgdXNlZCBkdXJpbmcgdGhlIGFzc2lnbm1lbnQuDQojIyMgTmFtZXMgb2YgVG9vbHMgYW5kIExpbmtzOiANCk9wZW5BSSdzIENoYXRHUFQgKGh0dHBzOi8vb3BlbmFpLmNvbSkuIFZlcnNpb24gdXNlZDogQ2hhdEdQVCBvMS1wcmV2aWV3DQoNCiMjIyBTY29wZSBvZiBBcHBsaWNhdGlvbjogDQpUaGUgQUkgdG9vbCB3YXMgdXRpbGl6ZWQgdG8gZ2VuZXJhdGUgc3RydWN0dXJlZCBleHBsYW5hdGlvbnMsIGFuYWx5emUgZGF0YSB0cmVuZHMsIGFuZCByZWZpbmUgbGFuZ3VhZ2UgZm9yIGNsYXJpdHkgYW5kIGNvaGVyZW5jZS4gSXQgaGFzIGFsc28gYmVlbiB1dGlsaXplZCBhcyB0b29sIGZvciBvcHRpbWl6YXRpb24gYW5kIGVycm9yLXNvbHZpbmcgb2YgdGhlIHByb2R1Y2VkIGNvZGVzLiANCg0KIyMjIFF1YWxpdHkgQ29udHJvbCBQcm9jZWR1cmVzOiANCkdlbmVyYXRlZCBvdXRwdXRzIHdlcmUgcmlnb3JvdXNseSByZXZpZXdlZCBieSB0aGUgYXV0aG9ycyB0byBlbnN1cmUgYWNjdXJhY3ksIHJlbGV2YW5jZSwgYW5kIGFsaWdubWVudCB3aXRoIHRoZSBhc3NpZ25tZW50J3MgcmVxdWlyZW1lbnRzLiBBbGwgZmluYWwgY29udGVudCB1bmRlcndlbnQgbWFudWFsIHZlcmlmaWNhdGlvbiBhbmQgZWRpdHMuDQoNCiMjIyBSZXNwb25zaWJpbGl0eSBTdGF0ZW1lbnQ6IA0KV2UgYXNzdW1lIGZ1bGwgcmVzcG9uc2liaWxpdHkgZm9yIHRoZSBjb250ZW50IG9mIHRoaXMgd29yaywgaW5jbHVkaW5nIGFjY3VyYWN5LCBpbnRlZ3JpdHksIGFuZCBvcmlnaW5hbGl0eS4NCg0KDQoNCiMjIEwxIEludHJvDQoNCiMjIyBMMS4xIFVzZSBzdG9jayBleGNoYW5nZSBxdW90YXRpb25zIHRvIHJlY29yZCB0aGUgc3RvY2sgcHJpY2UgYW5kIGRpdmlkZW5kIG9mIG9uZSBzdG9jayBmcm9tIGVhY2ggc3RvY2sgZXhjaGFuZ2UgaW4gd2hpY2ggeW91IHdvdWxkIGxpa2UgdG8gaW52ZXN0Lg0KDQpTdGFydGluZyBxdWFudG1vZA0KDQpgYGB7cn0NCmxpYnJhcnkocXVhbnRtb2QpDQpgYGANCg0KDQpGdW5jdGlvbiB0byBnZXQgdGhlIHN5bWJvbHMgb24gdGhlIHRpbWUgcGVyaW9kIHJlcXVpcmVkIA0KDQpgYGB7cn0NCmdldF9zdG9ja19pbmZvX2J5X2RhdGUgPC0gZnVuY3Rpb24oc3ltYm9sLCBCb1RfZGF0ZSwgRW9UX2RhdGUpew0KICAgICBzdG9ja19kYXRhIDwtIGdldFN5bWJvbHMoc3ltYm9sLCBmcm9tID0gQm9UX2RhdGUsIHRvID0gRW9UX2RhdGUsIGF1dG8uYXNzaWduID0gRkFMU0UpDQogICAgIHN0YXJ0X3ByaWNlIDwtIGFzLm51bWVyaWMoQ2woc3RvY2tfZGF0YVtCb1RfZGF0ZV0pKQ0KICAgICBlbmRfcHJpY2UgPC0gYXMubnVtZXJpYyhDbChzdG9ja19kYXRhW0VvVF9kYXRlXSkpDQogICAgIGlmIChpcy5udWxsKGVuZF9wcmljZSkgfHwgbGVuZ3RoKGVuZF9wcmljZSkgPT0gMCB8fCBpcy5uYShhcy5udW1lcmljKGVuZF9wcmljZSkpKSB7DQogICAgICAgICBlbmRfcHJpY2UgPC0gYXMubnVtZXJpYyhDbChsYXN0KHN0b2NrX2RhdGFbcGFzdGUwKCIvIiwgRW9UX2RhdGUpXSkpKX0gZWxzZSB7DQogIGVuZF9wcmljZSA8LSBhcy5udW1lcmljKGVuZF9wcmljZSl9DQogICAgIGRpdmlkZW5kcyA8LSBnZXREaXZpZGVuZHMoc3ltYm9sLCBmcm9tID0gQm9UX2RhdGUsIHRvID0gRW9UX2RhdGUsIGF1dG8uYXNzaWduID0gRkFMU0UpDQogICAgIHN0YXJ0X2RpdmlkZW5kIDwtIGlmIChCb1RfZGF0ZSAlaW4lIGluZGV4KGRpdmlkZW5kcykpIHthcy5udW1lcmljKGRpdmlkZW5kc1tCb1RfZGF0ZV0pfSBlbHNlIE5BDQogICAgIGlmIChpcy5udWxsKHN0YXJ0X2RpdmlkZW5kKSB8fCBsZW5ndGgoc3RhcnRfZGl2aWRlbmQpID09IDAgfHwgaXMubmEoYXMubnVtZXJpYyhzdGFydF9kaXZpZGVuZCkpKSB7DQogICAgICAgICBzdGFydF9kaXZpZGVuZCA8LSBhcy5udW1lcmljKGxhc3QoZGl2aWRlbmRzW3Bhc3RlMCgiLyIsIEVvVF9kYXRlKV0pKX0gZWxzZSB7DQogICAgICAgICBzdGFydF9kaXZpZGVuZCA8LSBhcy5udW1lcmljKHN0YXJ0X2RpdmlkZW5kKX0NCiAgICAgZW5kX2RpdmlkZW5kIDwtIGlmKEVvVF9kYXRlICVpbiUgaW5kZXgoZGl2aWRlbmRzKSkgYXMubnVtZXJpYyhkaXZpZGVuZHNbRW9UX2RhdGVdKQ0KICAgICBpZiAoaXMubnVsbChlbmRfZGl2aWRlbmQpIHx8IGxlbmd0aChlbmRfZGl2aWRlbmQpID09IDAgfHwgaXMubmEoYXMubnVtZXJpYyhlbmRfZGl2aWRlbmQpKSkgew0KICAgICAgICAgZW5kX2RpdmlkZW5kIDwtIGFzLm51bWVyaWMobGFzdChkaXZpZGVuZHNbcGFzdGUwKCIvIiwgRW9UX2RhdGUpXSkpfSBlbHNlIHsNCiAgICAgICAgIGVuZF9kaXZpZGVuZCA8LSBhcy5udW1lcmljKGVuZF9kaXZpZGVuZCl9DQogICAgIGxpc3QoDQogICAgICAgICBTdGFydF9QcmljZT0gc3RhcnRfcHJpY2UsDQogICAgICAgICBFbmRfUHJpY2U9IGVuZF9wcmljZSwNCiAgICAgICAgIFN0YXJ0X0RpdmlkZW5kPSBzdGFydF9kaXZpZGVuZCwNCiAgICAgICAgIEVuZF9EaXZpZGVuZD0gZW5kX2RpdmlkZW5kDQogICAgICkNCiB9DQoNCg0KYGBgDQoNCg0KRGV0ZXJtaW5pbmcgdGhlIGRhdGVzIG9mIGJlZ2lubmluZyBhbmQgZW5kDQoNCmBgYHtyfQ0KQm9UX2RhdGUgPC0gIjIwMjQtMDUtMDEiDQpFb1RfZGF0ZSA8LSAiMjAyNC0wOS0zMCINCmBgYA0KDQoNCkRldGVybWluaW5nIHRoZSBzdG9jayBzeW1ib2xzDQoNCmBgYHtyfQ0KbnlzZV9zdG9jayA8LSAiSUJNIg0KbmFzZGFxX3N0b2NrIDwtICJTQlVYIg0KYGBgDQoNCg0KUmV0cmlldmUgaW5mb3JtYXRpb24gZnJvbSBlYWNoIHN0b2NrDQoNCmBgYHtyfQ0KbnlzZV9pbmZvIDwtIGdldF9zdG9ja19pbmZvX2J5X2RhdGUobnlzZV9zdG9jaywgQm9UX2RhdGUsIEVvVF9kYXRlKQ0KbmFzZGFxX2luZm8gPC0gZ2V0X3N0b2NrX2luZm9fYnlfZGF0ZShuYXNkYXFfc3RvY2ssIEJvVF9kYXRlLCBFb1RfZGF0ZSkNCg0KYGBgDQoNCg0KQ3JlYXRlIGEgZGF0YSBmcmFtZSB0byBkaXNwbGF5IHRoZSByZXN1bHRzDQoNCmBgYHtyfQ0Kc3RvY2tfZGF0YSA8LSBkYXRhLmZyYW1lKA0KICBFeGNoYW5nZSA9IGMoIk5ldyBZb3JrIFN0b2NrIEV4Y2hhbmdlIiwgIk5hc2RhcSBNYXJrZXQiKSwNCiAgRmlybSA9IGMobnlzZV9zdG9jaywgbmFzZGFxX3N0b2NrKSwNCiAgQm9UX1ByaWNlID0gYyhueXNlX2luZm8kU3RhcnRfUHJpY2UsIG5hc2RhcV9pbmZvJFN0YXJ0X1ByaWNlKSwNCiAgRW9UX1ByaWNlID0gYyhueXNlX2luZm8kRW5kX1ByaWNlLCBuYXNkYXFfaW5mbyRFbmRfUHJpY2UpLA0KICBCb1RfRGl2aWRlbmQgPSBjKG55c2VfaW5mbyRTdGFydF9EaXZpZGVuZCwgbmFzZGFxX2luZm8kU3RhcnRfRGl2aWRlbmQpLA0KICBFb1RfRGl2aWRlbmQgPSBjKG55c2VfaW5mbyRFbmRfRGl2aWRlbmQsIG5hc2RhcV9pbmZvJEVuZF9EaXZpZGVuZCkpDQpwcmludChzdG9ja19kYXRhKQ0KYGBgDQoNCiMjIyMgQW5hbHlzaXMgb2YgcmVzdWx0cy4gDQpJbiB0aGlzIGV4ZXJjaXNlIHdlIGhhdmUgb2J0YWluZWQgdGhlIHN0b2NrIHByaWNlcyBhbmQgZGl2aWRlbmQgb2YgYW4gc3RvY2sgZnJvbSB0aGUgTmV3IFlvcmsgU3RvY2sgRXhjaGFuZ2UgYW5kIGFub3RoZXIgZnJvbSB0aGUgTmFzZGFxIE1hcmtldCwgYm90aCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzY2hvb2wgdGVybSBkYXRlIChCb1QgZGF0ZSkgYW5kIHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtIGRhdGUgKEVvVCBkYXRlKQ0KRm9yIHRoZSBkZXZlbG9wbWVudCBvZiB0aGlzIGV4ZXJjaXNlLCB3ZSBoYXZlIGRlc2lnbmVkIGEgZnVuY3Rpb24gd2hpY2ggYWxsb3dzIHVzIHRvIGV4dHJhY3QgdGhlIHN0b2NrIHByaWNlIGFzIHdlbGwgYXMgdGhlIGRpdmlkZW5kLCBnaXZpbmcgYSBzb2x1dGlvbiB0byBtYW5hZ2UgdGhlIGxhY2sgb2YgZGF0YSBhdCB0aGUgRW9UIGRhdGUsIHdoaWNoIGlzIGEgbm9uLXRyYWRpbmcgZGF5LiBJbiB0aGlzIHNvbHV0aW9uLCB3aGljaCB3ZSB3aWxsIGhhdmUgdG8gZnVydGhlciBpbXBsZW1lbnQgaW4gdGhlIHJlc3Qgb2YgZXhlcmNpc2VzIHRoYXQgaW52b2x2ZSBvYnRhaW5pbmcgZGF0YSBhdCBFb1QgZGF0ZSwgd2UgaGF2ZSBnaXZlbiBhbiBvcmRlciB0byB1c2UgdGhlIGxhc3QgYXZhaWxhYmxlIGRhdGEgd2hlbiB0aGUgZGF0ZSBzZWxlY3RlZCBoYXMgbm8gYXZhaWxhYmxlIGRhdGEuIEFkZGl0aW9uYWxseSwgYWx0aG91Z2ggaXQgd2lsbCBwcm9iYWJseSBub3QgYmUgbmVlZGVkLCB3ZSBoYXZlIGltcGxlbWVudGVkIGFuIGVxdWl2YWxlbnQgc3lzdGVtIGZvciBvYnRhaW5pbmcgdGhlIGRhdGEgb24gQm9UIGRhdGUsIHNvIHRoYXQgaWYgd2UgZW5jb3VudGVyIGEgbWlzc2luZyB2YWx1ZSwgd2Ugd2lsbCB1c2UgdGhlIG5leHQgYXZhaWxhYmxlIGRhdGEuIA0KUmVnYXJkaW5nIHRoZSByZXN1bHRzIG9mIHRoZSBleGVyY2lzZSwgd2UgY2FuIG9ic2VydmUgYW4gaW5jcmVhc2UgaW4gdGhlIHByaWNlIG9mIHRoZSBvZiBib3RoIHN0b2NrcyBkdXJpbmcgdGhlIHNjaG9vbCB0ZXJtLiBUaGUgaW5jcmVhc2luZyBwcmljZXMgdXN1YWxseSByZXZvbHZlIGFyb3VuZCBwb3NpdGl2ZSBmdXR1cmUgZXhwZWN0YW5jeSBvZiB0aGUgY29tcGFuaWVzIGFzIHdlbGwgYXMgYSBmYXZvcmFibGUgcHJlc2VudGF0aW9uIG9mIHJlc3VsdHMgYXQgdGhlIGVuZCBvZiBlYWNoIHF1YXJ0ZXIuIA0KVGhlIGRpdmlkZW5kcyBoYXZlIG5vdCBzZWVuIG5laXRoZXIgYW4gaW5jcmVhc2Ugbm9yIGEgZGVjcmVhc2UsIHdoaWNoIGluZGljYXRlcyBzdGFiaWxpdHkgaW4gdGhlaXIgaW50ZXJuYWwgZmluYW5jaWFsIG9yZ2FuaXphdGlvbiBhbmQgZ2l2ZXMgYSBmdXJ0aGVyIHNlbnNlIG9mIHNhZmVuZXNzIHRvIHRoZWlyIHN0b2NraG9sZGVycy4gDQoNCg0KDQojIyMgTDEuMiBVc2UgZnV0dXJlcyBwcmljZXMgcXVvdGF0aW9ucyB0byByZWNvcmQgdGhlIHJlY2VudCAo4oCcc2V0dGxl4oCdKSBwcmljZSBvZiB0aGUgZm9sbG93aW5nIGZ1dHVyZXMgKHNlbGVjdCBmdXR1cmVzIHdpdGggZmlyc3Qgc2V0dGxlbWVudCBkYXRlIGJleW9uZCB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybSkgDQoNCkNyZWF0aW5nIGZ1bmN0aW9uIHRvIGV4dHJhY3QgdGhlIHZhbHVlcw0KDQpgYGB7cn0NCmdldF9fZnV0dXJlc19kYXRhX2J5X2RhdGUgPC0gZnVuY3Rpb24oc3ltYm9sLCBmcm9tID0gQm9UX2RhdGUsIHRvID0gRW9UX2RhdGUpIHsNCiAgICAgZnV0dXJlc19kYXRhIDwtIGdldFN5bWJvbHMoc3ltYm9sLCBmcm9tID0gQm9UX2RhdGUsIHRvID0gRW9UX2RhdGUsIGF1dG8uYXNzaWduID0gRkFMU0UpDQogICAgIGlmIChpcy5udWxsKGZ1dHVyZXNfZGF0YSkgfHwgbnJvdyhmdXR1cmVzX2RhdGEpID09IDApIHsNCiAgICAgICAgIHdhcm5pbmcocGFzdGUoIk5vIGRhdGEgZm91bmQgZm9yIHN5bWJvbDoiLCBzeW1ib2wpKQ0KICAgICAgICAgcmV0dXJuKE5BKQ0KICAgICB9DQogICAgQm9UX3ByaWNlIDwtIGFzLm51bWVyaWMoQ2woZnV0dXJlc19kYXRhW0JvVF9kYXRlXSkpDQogRW9UX2RhdGEgPC0gZnV0dXJlc19kYXRhW3Bhc3RlMCgiLyIsIEVvVF9kYXRlKV0NCiBpZihucm93KEVvVF9kYXRhKSA9PSAwKSB7DQogICAgIHdhcm5pbmcocGFzdGUoIk5vIGRhdGEgYXZhaWxhYmxlIG9uIG9yIGJlZm9yZSBFb1RfZGF0ZSBmb3Igc3ltYm9sOiIsIHN5bWJvbCkpDQogICAgIEVvVF9wcmljZSA8LSBOQQ0KIH0gZWxzZSB7DQogICAgIEVvVF9wcmljZSA8LSBhcy5udW1lcmljKGxhc3QoQ2woRW9UX2RhdGEpKSkNCiB9DQogcmV0dXJuKGxpc3QoDQogICAgIFN5bWJvbCA9IHN5bWJvbCwNCiAgICAgQm9UX1ByaWNlID0gQm9UX3ByaWNlLA0KICAgICBFb1RfUHJpY2UgPSBFb1RfcHJpY2UNCiApKQ0KIH0NCmBgYA0KDQp1c2UgdGhlIGZ1bmN0aW9uIGZvciBlYWNoIGZ1dHVyZXMgY29udHJhY3QNCg0KYGBge3J9DQp0cmVhc3VyeV9ib25kIDwtIGdldF9fZnV0dXJlc19kYXRhX2J5X2RhdGUoIlpCPUYiLCBCb1RfZGF0ZSwgRW9UX2RhdGUpDQogIHNwNTAwX2Z1dHVyZXMgPC0gZ2V0X19mdXR1cmVzX2RhdGFfYnlfZGF0ZSgiRVM9RiIsIEJvVF9kYXRlLCBFb1RfZGF0ZSkNCiAgbmFzZGFxIDwtIGdldF9fZnV0dXJlc19kYXRhX2J5X2RhdGUoIl5JWElDIiwgQm9UX2RhdGUsIEVvVF9kYXRlKQ0KIGJyaXRpc2hfcG91bmQgPC0gZ2V0X19mdXR1cmVzX2RhdGFfYnlfZGF0ZSgiNkI9RiIsIEJvVF9kYXRlLCBFb1RfZGF0ZSkNCmBgYA0KDQoNCmJ1aWxkIHRoZSBkYXRhIGZyYW1lDQoNCmBgYHtyfQ0KZnV0dXJlX3ByaWNlcyA8LSBkYXRhLmZyYW1lKA0KICBBc3NldCA9IGMoDQogICAgIlRyZWFzdXJ5IEJvbmQgRnV0dXJlcyBEZWMgMjAyNCIsDQogICAgIlMmUCA1MDAgRnV0dXJlcyBEZWMgMjAyNCIsDQogICAgIk5hc2RhcSBDb21wb3NpdGUgSW5kZXgiLA0KICAgICJCcml0aXNoIFBvdW5kIEZ1dHVyZXMgRGVjIDIwMjQiDQogICksDQogIFN5bWJvbCA9IGMoDQogICAgdHJlYXN1cnlfYm9uZCRTeW1ib2wsDQogICAgc3A1MDBfZnV0dXJlcyRTeW1ib2wsDQogICAgbmFzZGFxJFN5bWJvbCwNCiAgICBicml0aXNoX3BvdW5kJFN5bWJvbA0KICApLA0KICBCb1RfUHJpY2UgPSBjKA0KICAgIHRyZWFzdXJ5X2JvbmQkQm9UX1ByaWNlLA0KICAgIHNwNTAwX2Z1dHVyZXMkQm9UX1ByaWNlLA0KICAgIG5hc2RhcSRCb1RfUHJpY2UsDQogICAgYnJpdGlzaF9wb3VuZCRCb1RfUHJpY2UNCiAgKSwNCiAgRW9UX1ByaWNlID0gYygNCiAgICB0cmVhc3VyeV9ib25kJEVvVF9QcmljZSwNCiAgICBzcDUwMF9mdXR1cmVzJEVvVF9QcmljZSwNCiAgICBuYXNkYXEkRW9UX1ByaWNlLA0KICAgIGJyaXRpc2hfcG91bmQkRW9UX1ByaWNlDQogICkNCikNCmBgYA0KDQpQcmludCB0aGUgZGF0YSBmcmFtZQ0KDQpgYGB7cn0NCnByaW50KGZ1dHVyZV9wcmljZXMpDQpgYGANCg0KIyMjIyBBbmFseXNpcyBvZiB0aGUgcmVzdWx0cw0KSW4gdGhpcyBjYXNlLCB3ZSBoYXZlIGNyZWF0ZWQgYSBmdW5jdGlvbiBpbiBvcmRlciB0byByZXRyaWV2ZSB0aGUgc2V0dGxlIHByaWNlIG9mIHRoZSBkaWZmZXJlbnQgdHlwZXMgb2YgZnV0dXJlcywgd2l0aCB0aGUgZmlyc3Qgc2V0dGxlbWVudCBkYXRlIGJleW9uZCB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybS4gQXMgZG9uZSBiZWZvcmUsIHdlIGhhdmUgYWRqdXN0ZWQgdGhlIGZ1bmN0aW9uIHRvIG1hbmFnZSBub24tdHJhZGluZyBkYXlzLiANCkluIHRoZSBkYXRhIG9idGFpbmVkIHdlIGNhbiBvYnNlcnZlIGFuIGluZGl2aWR1YWwgYXBwcmVjaWF0aW9uIG9mIGVhY2ggb2YgdGhlaXIgcHJpY2VzLCB3aGljaCBtYXkgaW5kaWNhdGUgYW4gb3ZlcmFsbCBncm93dGggaW4gZWNvbm9teS4gSG93ZXZlciwgc29tZSBvdGhlciBmYWN0b3JzIHRoYXQgdXN1YWxseSBhZmZlY3QgZnV0dXJlcyBwcmljZXMsIHN1Y2ggYXMgaW50ZXJlc3QgcmF0ZXMsIG1hY3JvZWNvbm9taWMgZGVjaXNpb25zLCB0aGUgbWFya2V0IHByZWZlcmVuY2VzIGFuZCBzdXBwbHkgYW5kIGRlbWFuZCBjYW4gaGF2ZSBhIHNpZ25pZmljYW50IGltcGFjdCBpbiB0aGUgcHJpY2luZyBvZiB0aGVzZSBhc3NldHMuIA0KDQoNCg0KIyMjIEwxLjMgVXNlIGFuIG9wdGlvbnMgcXVvdGF0aW9ucyB0YWJsZSB0byBzZWxlY3QgYSBjYWxsIG9wdGlvbiBvbiBhIGZpcm0gd2hvc2Ugc3RvY2sgcHJpY2UgeW91IGV4cGVjdCB0byBpbmNyZWFzZSAoc2VsZWN0IHRoZSBvcHRpb24gd2l0aCB0aGUgZmlyc3QgZXhwaXJhdGlvbiBtb250aCBiZXlvbmQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0pDQoNCg0KSW5zdGFsbCBhbmQgbG9hZCBwYWNrYWdlcw0KYGBge3J9DQojIExvYWQgcGFja2FnZXMNCmxpYnJhcnkocXVhbnRtb2QpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeSh0aW1lRGF0ZSkNCmxpYnJhcnkoUlF1YW50TGliKQ0KDQpgYGANCg0KRGVmaW5lIEJvVCBhbmQgRW9UIGRhdGVzDQoNCmBgYHtyfQ0KQm9UX2RhdGUgPC0gYXMuRGF0ZSgiMjAyNC0wNS0wMSIpDQpFb1RfZGF0ZSA8LSBhcy5EYXRlKCIyMDI0LTA5LTMwIikNCmBgYA0KDQoNCkNyZWF0ZSBmdW5jdGlvbiB0byBhZGp1c3QgdG8gbm9uLXRyYWRpbmcgZGF0ZXMgYW5kIG9idGFpbiBzdG9jayBpbmZvcm1hdGlvbg0KDQpgYGB7cn0NCiNnZXR0aW5nIHRoZSBzeW1ib2xzDQpnZXRfc3RvY2tfcHJpY2UgPC0gZnVuY3Rpb24oc3ltYm9sLCBkYXRlLCB1c2VfbmV4dCA9IEZBTFNFKSAgew0KICAgIGRhdGEgPC0gZ2V0U3ltYm9scygNCiAgICAgICAgU3ltYm9scyA9IHN5bWJvbCwNCiAgICAgICAgZnJvbSA9IGRhdGUgLSBkYXlzKDEwKSwNCiAgICAgICAgdG8gPSBkYXRlICsgZGF5cygxMCksDQogICAgICAgIGF1dG8uYXNzaWduID0gRkFMU0UNCg0KICAgICkNCiAgICAjc29sdmluZyBpc3N1ZXMgd2l0aCBub24tdHJhZGluZyBkYXlzDQogICAgaW5kZXgoZGF0YSkgPC0gYXMuRGF0ZShpbmRleChkYXRhKSkNCiAgICBpZiAodXNlX25leHQpIHsNCiAgICAgICAgYXZhaWxhYmxlX2RhdGVzIDwtIGluZGV4KGRhdGEpW2luZGV4KGRhdGEpID49IGRhdGVdDQogICAgICAgIGlmKGxlbmd0aChhdmFpbGFibGVfZGF0ZXMpID09IDApIHsNCiAgICAgICAgICAgIHdhcm5pbmcocGFzdGUoIk5vIGRhdGEgYXZhaWxhYmxlIGFmdGVyIiwgZGF0ZSwgImZvciBzeW1ib2w6Iiwgc3ltYm9sKSkNCiAgICAgICAgICAgIHJldHVybihOQSkNCiAgICAgICAgfQ0KICAgICAgICBkYXRlX3VzZWQgPC0gbWluKGF2YWlsYWJsZV9kYXRlcykNCiAgICB9IGVsc2Ugew0KICAgICAgICBhdmFpbGFibGVfZGF0ZXMgPC0gaW5kZXgoZGF0YSlbaW5kZXgoZGF0YSkgPD0gZGF0ZV0gDQogICAgICAgIGlmIChsZW5ndGgoYXZhaWxhYmxlX2RhdGVzKSA9PSAwKSB7DQogICAgICAgICAgICB3YXJuaW5nKHBhc3RlKCJObyBkYXRhIGF2YWlsYWJsZSBiZWZvcmUiLCBkYXRlLCAiZm9yIHN5bWJvbDoiLCBzeW1ib2wpKQ0KICAgICAgICAgICAgcmV0dXJuKE5BKQ0KICAgICAgICB9DQogICAgICAgIGRhdGVfdXNlZCA8LSBtYXgoYXZhaWxhYmxlX2RhdGVzKQ0KICAgIH0NCiAgICNvYnRhaW5pbmcgcHJpY2UNCiAgICAgcHJpY2UgPC0gYXMubnVtZXJpYyhDbChkYXRhW2RhdGVfdXNlZF0pKQ0KICAgIHJldHVybihsaXN0KA0KICAgICAgICBQcmljZSA9IHByaWNlLCBEYXRlID0gYXMuRGF0ZShkYXRlX3VzZWQpDQogICAgKSkNCn0NCmBgYA0KDQoNCkdldHRpbmcgdGhlIGRhdGEgZm9yIG91ciBzZWxlY3RlZCBzdG9jaw0KDQpgYGB7cn0NCkJvVF9zdG9jayA8LSBnZXRfc3RvY2tfcHJpY2UoIkJBQkEiLCBCb1RfZGF0ZSwgdXNlX25leHQgPSBUUlVFKQ0KRW9UX3N0b2NrIDwtIGdldF9zdG9ja19wcmljZSgiQkFCQSIsIEVvVF9kYXRlLCB1c2VfbmV4dCA9IEZBTFNFKQ0KYGBgDQoNCg0KQ2FsY3VsYXRlIE9wdGlvbiBQcmVtaXVtcyBvbiBCb1QgYW5kIEVvVC4NCk9wdGlvbiBUeXBlOiBDYWxsIE9wdGlvbg0KU3RyaWtlIFByaWNlOiBDbG9zZXN0IHRvIHRoZSBzdG9jayBwcmljZSBhdCBCb1RfZGF0ZQ0KRXhwaXJhdGlvbiBEYXRlOiBGaXJzdCBPcHRpb24gZXhwaXJhdGlvbiBkYXRlIGJleW9uZCBFb1RfRGF0ZQ0KDQpgYGB7cn0NCiMgTG9hZCBuZWNlc3NhcnkgcGFja2FnZXMNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeSh0aW1lRGF0ZSkNCg0KIyBJbml0aWFsaXplIGV4cGlyYXRpb25fZGF0ZXMgYXMgYW4gZW1wdHkgdmVjdG9yIG9mIGNsYXNzIERhdGUNCmV4cGlyYXRpb25fZGF0ZXMgPC0gYXMuRGF0ZShjaGFyYWN0ZXIoKSkNCg0KIyBHZXQgdGhlIGN1cnJlbnQgZGF0ZQ0KY3VycmVudF9kYXRlIDwtIGFzLkRhdGUoU3lzLkRhdGUoKSkNCg0KIyBEZWZpbmUgeW91ciBFb1RfZGF0ZQ0KRW9UX2RhdGUgPC0gYXMuRGF0ZSgiMjAyNC0wOS0zMCIpDQoNCiMgRGVmaW5lIHRoZSBjb3JyZWN0ZWQgdGhpcmRfZnJpZGF5IGZ1bmN0aW9uDQp0aGlyZF9mcmlkYXkgPC0gZnVuY3Rpb24oeWVhciwgbW9udGgpIHsNCiAgICAjIEdldCBhbGwgZGF5cyBpbiB0aGUgbW9udGgNCiAgICBkYXRlcyA8LSBzZXEoDQogICAgICAgIGZyb20gPSBhcy5EYXRlKHBhc3RlMCh5ZWFyLCAiLSIsIG1vbnRoLCAiLTAxIikpLA0KICAgICAgICB0byA9IGFzLkRhdGUocGFzdGUwKHllYXIsICItIiwgbW9udGgsICItIiwgZGF5c19pbl9tb250aChhcy5EYXRlKHBhc3RlMCh5ZWFyLCAiLSIsIG1vbnRoLCAiLTAxIikpKSkpLA0KICAgICAgICBieSA9ICJkYXkiDQogICAgKQ0KICAgIA0KICAgICMgR2V0IGFsbCBGcmlkYXlzIHVzaW5nIHdkYXkoKQ0KICAgIGZyaWRheXMgPC0gZGF0ZXNbd2RheShkYXRlcykgPT0gNl0gICMgNiBjb3JyZXNwb25kcyB0byBGcmlkYXkNCiAgICANCiAgICAjIFJldHVybiB0aGUgdGhpcmQgRnJpZGF5DQogICAgaWYgKGxlbmd0aChmcmlkYXlzKSA+PSAzKSB7DQogICAgICAgIHJldHVybihmcmlkYXlzWzNdKQ0KICAgIH0gZWxzZSB7DQogICAgICAgIHJldHVybihOQSkNCiAgICB9DQp9DQoNCiMgTG9vcCBvdmVyIHRoZSBuZXh0IDE4IG1vbnRocw0KZm9yIChpIGluIDA6MTcpIHsNCiAgICAjIEFkZCBpIG1vbnRocyB0byB0aGUgY3VycmVudCBkYXRlDQogICAgZGF0ZSA8LSBjdXJyZW50X2RhdGUgJW0rJSBtb250aHMoaSkNCiAgICANCiAgICAjIEV4dHJhY3QgdGhlIHllYXIgYW5kIG1vbnRoDQogICAgeXIgPC0geWVhcihkYXRlKQ0KICAgIG1udGggPC0gbW9udGgoZGF0ZSkNCiAgICANCiAgICAjIENhbGN1bGF0ZSB0aGUgdGhpcmQgRnJpZGF5IG9mIHRoZSBtb250aA0KICAgIGV4cF9kYXRlIDwtIHRoaXJkX2ZyaWRheSh5ciwgbW50aCkNCiAgICANCiAgICBpZiAoIWlzLm5hKGV4cF9kYXRlKSkgew0KICAgICAgICBleHBpcmF0aW9uX2RhdGVzIDwtIGMoZXhwaXJhdGlvbl9kYXRlcywgZXhwX2RhdGUpDQogICAgfQ0KfQ0KDQojIEZpbHRlciBleHBpcmF0aW9uIGRhdGVzIGJleW9uZCBFb1RfZGF0ZQ0KZXhwaXJhdGlvbl9kYXRlcyA8LSBleHBpcmF0aW9uX2RhdGVzW2V4cGlyYXRpb25fZGF0ZXMgPiBFb1RfZGF0ZV0NCg0KIyBQcmludCB0aGUgZXhwaXJhdGlvbiBkYXRlcw0KcHJpbnQoZXhwaXJhdGlvbl9kYXRlcykNCg0KYGBgDQoNCg0KR2V0IHN0cmlrZSBwcmljZQ0KYGBge3J9DQpzdHJpa2VfcHJpY2UgPC0gcm91bmQoQm9UX3N0b2NrJFByaWNlLCBkaWdpdHMgPSAtMSkgICMgUm91bmQgdG8gbmVhcmVzdCAxMA0KDQpgYGANCg0KDQpFc3RpbWF0ZSB2b2xhdGlsaXR5DQpgYGB7cn0NCiMgR2V0IGhpc3RvcmljYWwgc3RvY2sgcHJpY2VzIGZvciB0aGUgcGFzdCB5ZWFyIGJlZm9yZSBCb1RfZGF0ZQ0KdGlja2VyIDwtICJCQUJBIg0Kdm9sX2RhdGEgPC0gZ2V0U3ltYm9scygNCiAgU3ltYm9scyA9IHRpY2tlciwNCiAgc3JjID0gInlhaG9vIiwNCiAgZnJvbSA9IEJvVF9zdG9jayREYXRlIC0geWVhcnMoMSksDQogIHRvID0gQm9UX3N0b2NrJERhdGUsDQogIGF1dG8uYXNzaWduID0gRkFMU0UNCikNCg0KIyBDYWxjdWxhdGUgZGFpbHkgcmV0dXJucw0KcmV0dXJucyA8LSBkYWlseVJldHVybihDbCh2b2xfZGF0YSkpDQoNCiMgQ2FsY3VsYXRlIGFubnVhbGl6ZWQgdm9sYXRpbGl0eQ0Kdm9sYXRpbGl0eSA8LSBzZChyZXR1cm5zLCBuYS5ybSA9IFRSVUUpICogc3FydCgyNTIpICAjIDI1MiB0cmFkaW5nIGRheXMgaW4gYSB5ZWFyDQoNCmBgYA0KDQoNClNldCByaXNrLWZyZWUgSW50ZXJlc3QgUmF0ZSBhbmQgRGl2aWRlbmQgWWllbGQNCg0KYGBge3J9DQojUmlzay1mcmVlIGludGVyZXN0IHJhdGUgKGUuZy4sIDIlIGFubnVhbGl6ZWQpDQpyaXNrX2ZyZWVfcmF0ZSA8LSAwLjAyDQojRGl2aWRlbmQgeWllbGQgKGZyb20gWWFob28gRmluYW5jZSBvciBzZXQgdG8gMC4wMDUgZm9yIDAuNSUpDQpkaXZpZGVuZF95aWVsZCA8LSAwLjA1DQpgYGANCg0KDQpDYWxjdWxhdGUgVGltZSB0byBFeHBpcmF0aW9uDQoNCmBgYHtyfQ0KIyBBc3N1bWluZyAnZXhwaXJhdGlvbl9kYXRlcycgaXMgYSB2ZWN0b3Igb2YgRGF0ZSBvYmplY3RzDQpleHBpcmF0aW9uX2RhdGVzIDwtIGV4cGlyYXRpb25fZGF0ZXNbZXhwaXJhdGlvbl9kYXRlcyA+IEVvVF9kYXRlXQ0KDQojIFNlbGVjdCB0aGUgZWFybGllc3QgZXhwaXJhdGlvbiBkYXRlIGJleW9uZCBFb1RfZGF0ZQ0KZXhwaXJhdGlvbl9kYXRlIDwtIGV4cGlyYXRpb25fZGF0ZXNbMV0NCg0KIyBUaW1lIHRvIGV4cGlyYXRpb24gZnJvbSBCb1RfZGF0ZQ0KdGltZV90b19leHBpcmF0aW9uX0JvVCA8LSBhcy5udW1lcmljKGV4cGlyYXRpb25fZGF0ZSAtIEJvVF9zdG9jayREYXRlKSAvIDM2NQ0KDQojIFRpbWUgdG8gZXhwaXJhdGlvbiBmcm9tIEVvVF9kYXRlDQp0aW1lX3RvX2V4cGlyYXRpb25fRW9UIDwtIGFzLm51bWVyaWMoZXhwaXJhdGlvbl9kYXRlIC0gRW9UX3N0b2NrJERhdGUpIC8gMzY1DQpgYGANCg0KDQpVc2UgQmxhY2stU2Nob2xlcyBNb2RlbCB0byBjYWxjdWxhdGUgT3B0aW9uIFByZW1pdW1zDQoNCmBgYHtyfQ0KI0Z1bmN0aW9uIHRvIGNhbGN1bGF0ZSBPcHRpb24gUHJlbWl1bQ0KY2FsY3VsYXRlX29wdGlvbl9wcmVtaXVtIDwtIGZ1bmN0aW9uKFMsIEssIHIsIHRpbWVfdG9fZXhwaXJhdGlvbiwgc2lnbWEsIGRpdmlkZW5kX3lpZWxkKSB7DQogIG9wdGlvbiA8LSBFdXJvcGVhbk9wdGlvbigNCiAgICB0eXBlID0gImNhbGwiLA0KICAgIHVuZGVybHlpbmcgPSBTLA0KICAgIHN0cmlrZSA9IEssDQogICAgZGl2aWRlbmRZaWVsZCA9IGRpdmlkZW5kX3lpZWxkLA0KICAgIHJpc2tGcmVlUmF0ZSA9IHIsDQogICAgbWF0dXJpdHkgPSB0aW1lX3RvX2V4cGlyYXRpb24sDQogICAgdm9sYXRpbGl0eSA9IHNpZ21hDQogICkNCiAgcmV0dXJuKG9wdGlvbiR2YWx1ZSkNCn0NCmBgYA0KDQoNCkNhbGN1bGF0ZSBPcHRpb24gUHJlbWl1bXMNCg0KYGBge3J9DQojIE9wdGlvbiBwcmVtaXVtIG9uIEJvVF9kYXRlDQpCb1RfcHJlbWl1bSA8LSBjYWxjdWxhdGVfb3B0aW9uX3ByZW1pdW0oDQogIFMgPSBCb1Rfc3RvY2skUHJpY2UsDQogIEsgPSBzdHJpa2VfcHJpY2UsDQogIHIgPSByaXNrX2ZyZWVfcmF0ZSwNCiAgdGltZV90b19leHBpcmF0aW9uID0gdGltZV90b19leHBpcmF0aW9uX0JvVCwNCiAgc2lnbWEgPSB2b2xhdGlsaXR5LA0KICBkaXZpZGVuZF95aWVsZCA9IGRpdmlkZW5kX3lpZWxkDQopDQoNCiMgT3B0aW9uIHByZW1pdW0gb24gRW9UX2RhdGUNCkVvVF9wcmVtaXVtIDwtIGNhbGN1bGF0ZV9vcHRpb25fcHJlbWl1bSgNCiAgUyA9IEVvVF9zdG9jayRQcmljZSwNCiAgSyA9IHN0cmlrZV9wcmljZSwNCiAgciA9IHJpc2tfZnJlZV9yYXRlLA0KICB0aW1lX3RvX2V4cGlyYXRpb24gPSB0aW1lX3RvX2V4cGlyYXRpb25fRW9ULA0KICBzaWdtYSA9IHZvbGF0aWxpdHksDQogIGRpdmlkZW5kX3lpZWxkID0gZGl2aWRlbmRfeWllbGQNCikNCmBgYA0KDQoNCkNyZWF0ZSB0YWJsZSBmb3IgcmVzdWx0cw0KYGBge3J9DQpyZXN1bHRzIDwtIGRhdGEuZnJhbWUoDQogICAgU3RvY2sgPSAiQkFCQSIsDQogICAgQm9UX0RhdGUgPSBCb1Rfc3RvY2skRGF0ZSwNCiAgICBCb1RfUHJpY2UgPSBCb1Rfc3RvY2skUHJpY2UsDQogICAgQm9UX09wdGlvbl9QcmVtaXVtID0gQm9UX3ByZW1pdW0sDQogICAgRW9UX0RhdGUgPSBFb1Rfc3RvY2skRGF0ZSwNCiAgICBFb1RfUHJpY2UgPSBFb1Rfc3RvY2skUHJpY2UsDQogICAgRW9UX09wdGlvbl9QcmVtaXVtID0gRW9UX3ByZW1pdW0NCikNCnByaW50KHJlc3VsdHMpDQpgYGANCg0KDQojIyMjIEFuYWx5c2lzIG9mIHJlc3VsdHMNCkluIHRoaXMgZXhlcmNpc2Ugd2UgbXVzdCByZXRyaWV2ZSBkYXRhIG9mIGEgY2FsbCBkYXRhIGZyb20gYSBzdG9jayB3ZSBleHBlY3QgdG8gaW5jcmVhc2UuIEluIHRoZXNlIGNhc2UsIHdlIGhhdmUgY29uc2lkZXJlZCB0byB0YWtlIGludG8gYWNjb3VudCBBbGliYWJhICgiQkFCQSIpLCBhcyB3ZSBjb25zaWRlciB0aGF0IGlzIGEgY29tcGFueSB3aGljaCBpcyBjdXJyZW50bHkgdW5kZXJ2YWx1ZWQgYW5kIGhhcyBhIGh1Z2UgcG90ZW50aWFsIG9mIGdyb3d0aCBpbiB0ZXJtcyBvZiBzdG9jayBwcmljZS4gDQpGb3IgdGhlIGRldmVsb3BtZW50IG9mIHRoaXMgZXhlcmNpc2Ugd2UgaGF2ZSBkZXZlbG9wZWQgYSBuZXcgZnVuY3Rpb24gdG8gZ2V0IG91ciBzc3RvY2sgZGF0YSwgYnV0IGluIHRoaXMgY2FzZSB3ZSBoYXZlIGxlbmd0aGVuZWQgb3VyIHRpbWUgYnJhY2tldCB0byBvYnRhaW4gZGF0YSBib3RoIGZyb20gYmVmb3JlIEJvVCBkYXRlIGFuZCBhZnRlciBFb1QgZGF0ZS4gDQpXZSBoYXZlIGFsc28gZGVmaW5lZCB0aGUgZXhwaXJhdGlvbiBkYXRlcyB0byB0aGUgbW9udGgncyB0aGlyZCBGcmlkYXksIGFuZCB3ZSBoYXZlIHNldCB0aGUgZXhwaXJhdGlvbiBkYXRlcyBhdmFpbGFibGUgdG8gdGhvc2UgYWZ0ZXIgRW9UIGRhdGUuIEFmdGVyd2FyZHMgd2UgaGF2ZSBzdGFibGlzaGVkIHRoZSBzdHJpa2UgcHJpY2UgYW5kLCB3aXRoIHRoZSB1c2Ugb2YgYSBuZXcgZnVuY3Rpb24sIHdlIGhhdmUgY2FsY3VsYXRlZCB0aGUgdm9sYXRpbGl0eS4gQXMgb3VyIGxhc3Qgc3RlcHMgYmVmb3JlIGFwcGx5aW5nIHRoZSBCbGFjay1TY2hvbGVzIG1vZGVsLCB3ZSBoYXZlIGNhbGN1bGF0ZWQgb3VyIHRpbWUgdG8gZXhwaXJhdGlvbiBhbmQgd2UgaGF2ZSBlc3RhYmxpc2hlZCB0aGUgcmlzay1mcmVlIHJhdGUgYW5kIHRoZSBkaXZpZGVuZCB5aWVsZC4gDQpGaW5hbGx5LCB3ZSBoYXZlIGRlZmluZWQgb3VyIGZ1bmN0aW9uIGZvciBhcHBseWluZyB0aGUgQmxhY2stU2Nob2xlcyBtb2RlbCBhbmQgd2UgaGF2ZSByZXRyaWV2ZWQgdGhlIG9wdGlvbiBwcmVtaXVtcyBhdCBCb1QgZGF0ZSBhbmQgRW9UIGRhdGUuIA0KDQpUaGUgcmVzdWx0cyBvYnRhaW5lZCB0aGFua3MgdG8gdGhpcyBjb2RlIGhhcyBsZWQgdXMgdG8gcGVyY2VpdmUgYSBzaWduaWZpY2FudCBhcHByZWNpYXRpb24gaW4gdGhlIG9wdGlvbiBwcmVtaXVtLCB3aGljaCB3ZSBjYW4gYXR0cmlidXRlIHRvIGFuIGltcHJvdmVtZW50IG9mIHRoZSB1bmRlcmx5aW5nIGFzc2V0ICgiQkFCQSIpLiBBbHNvLCB3aGVuIHdlIG9ic2VydmUgdGhlIGNoYW5nZSBpbiBwcmljZSwgaXQgbWF0Y2hlcyB3aXRoIHRoZSBvYnNlcnZhdGlvbiBpbiB0aGUgcHJlbWl1bXMsIG92ZXJhbGwgZGV0ZXJtaW5pbmcgdGhlIGdyZWF0IHBlcmZvcm1hbmNlIG9mIHRoZSBzZWxlY3RlZCBhc3NldCBkdXJpbmcgdGhlIHNjaG9vbCB0ZXJtLiANCg0KDQoNCiMjIyBMMS40IA0KDQpHZXR0aW5nIGRhdGEgZm9yIG91ciBzZWxlY3RlZCBzdG9jaw0KDQpgYGB7cn0NCiMgR2V0IHN0b2NrIHByaWNlcyBvbiBCb1QgYW5kIEVvVCBkYXRlcw0KQm9UX3N0b2NrIDwtIGdldF9zdG9ja19wcmljZSgiSU5HIiwgQm9UX2RhdGUsIHVzZV9uZXh0ID0gVFJVRSkNCkVvVF9zdG9jayA8LSBnZXRfc3RvY2tfcHJpY2UoIklORyIsIEVvVF9kYXRlLCB1c2VfbmV4dCA9IEZBTFNFKQ0KYGBgDQoNCg0KDQpDYWxjdWxhdGUgT3B0aW9uIFByZW1pdW1zIG9uIEJvVCBhbmQgRW9UDQogICtPcHRpb24gdHlwZTogcHV0IG9wdGlvbg0KICArU3RyaWtlIFByaWNlOiBDbG9zZXMgdG8gdGhlIFN0b2NrIHByaWNlIGF0IEJvVF9EYXRlDQogICtFeHBpcmF0aW9uIERhdGU6IEZpcnN0IG9wdGlvbiBleHBpcmF0aW9uIGRhdGUgYmV5b25kIEVvVF9kYXRlDQoNCg0KR2V0IFN0cmlrZSBQcmljZQ0KDQpgYGB7cn0NCiNSb3VuZCB0byB0aGUgbmVhcmVzdCAxMA0Kc3RyaWtlX3ByaWNlIDwtIHJvdW5kKEJvVF9zdG9jayRQcmljZSwgZGlnaXRzID0gLTEpIA0KYGBgDQoNCg0KRXN0aW1hdGUgVm9sYXRpbGl0eQ0KDQpgYGB7cn0NCiMgR2V0IGhpc3RvcmljYWwgc3RvY2sgcHJpY2VzIGZvciB0aGUgcGFzdCB5ZWFyIGJlZm9yZSBCb1RfZGF0ZQ0KdGlja2VyIDwtICJJTkciDQp2b2xfZGF0YSA8LSBnZXRTeW1ib2xzKA0KICBTeW1ib2xzID0gdGlja2VyLA0KICBzcmMgPSAieWFob28iLA0KICBmcm9tID0gQm9UX3N0b2NrJERhdGUgLSB5ZWFycygxKSwNCiAgdG8gPSBCb1Rfc3RvY2skRGF0ZSwNCiAgYXV0by5hc3NpZ24gPSBGQUxTRQ0KKQ0KDQojIENhbGN1bGF0ZSBkYWlseSByZXR1cm5zDQpyZXR1cm5zIDwtIGRhaWx5UmV0dXJuKENsKHZvbF9kYXRhKSkNCg0KIyBDYWxjdWxhdGUgYW5udWFsaXplZCB2b2xhdGlsaXR5DQp2b2xhdGlsaXR5IDwtIHNkKHJldHVybnMsIG5hLnJtID0gVFJVRSkgKiBzcXJ0KDI1MikgICMgMjUyIHRyYWRpbmcgZGF5cyBpbiBhIHllYXINCmBgYA0KDQoNClNldCBSaXNrLUZyZWUgSW50ZXJlc3QgUmF0ZSBhbmQgRGl2aWRlbmQgWWllbGQNCg0KYGBge3J9DQojUmlzay1mcmVlIGludGVyZXN0IHJhdGUgKDIlIGFubnVhbGl6ZWQgZm9yIGV4YW1wbGUpDQpyaXNrX2ZyZWVfcmF0ZSA8LSAwLjAyDQoNCiNEaXZpZGVuZCBZaWVsZCAobW9zdCByZWNlbnQpDQpkaXZpZGVuZF95aWVsZCA8LSAwLjA3NDkNCmBgYA0KDQoNCkNhbGN1bGF0ZSB0aW1lIHRvIGV4cGlyYXRpb24NCg0KYGBge3J9DQojIFRpbWUgdG8gZXhwaXJhdGlvbiBmcm9tIEJvVF9kYXRlDQp0aW1lX3RvX2V4cGlyYXRpb25fQm9UIDwtIGFzLm51bWVyaWMoZXhwaXJhdGlvbl9kYXRlIC0gQm9UX3N0b2NrJERhdGUpIC8gMzY1DQoNCiMgVGltZSB0byBleHBpcmF0aW9uIGZyb20gRW9UX2RhdGUNCnRpbWVfdG9fZXhwaXJhdGlvbl9Fb1QgPC0gYXMubnVtZXJpYyhleHBpcmF0aW9uX2RhdGUgLSBFb1Rfc3RvY2skRGF0ZSkgLyAzNjUNCg0KYGBgDQoNCg0KQ2FsY3VsYXRlIE9wdGlvbiBQcmVtaXVtcw0KDQpgYGB7cn0NCiMgT3B0aW9uIHByZW1pdW0gb24gQm9UX2RhdGUNCkJvVF9wcmVtaXVtIDwtIGNhbGN1bGF0ZV9vcHRpb25fcHJlbWl1bSgNCiAgUyA9IEJvVF9zdG9jayRQcmljZSwNCiAgSyA9IHN0cmlrZV9wcmljZSwNCiAgciA9IHJpc2tfZnJlZV9yYXRlLA0KICB0aW1lX3RvX2V4cGlyYXRpb24gPSB0aW1lX3RvX2V4cGlyYXRpb25fQm9ULA0KICBzaWdtYSA9IHZvbGF0aWxpdHksDQogIGRpdmlkZW5kX3lpZWxkID0gZGl2aWRlbmRfeWllbGQNCikNCg0KIyBPcHRpb24gcHJlbWl1bSBvbiBFb1RfZGF0ZQ0KRW9UX3ByZW1pdW0gPC0gY2FsY3VsYXRlX29wdGlvbl9wcmVtaXVtKA0KICBTID0gRW9UX3N0b2NrJFByaWNlLA0KICBLID0gc3RyaWtlX3ByaWNlLA0KICByID0gcmlza19mcmVlX3JhdGUsDQogIHRpbWVfdG9fZXhwaXJhdGlvbiA9IHRpbWVfdG9fZXhwaXJhdGlvbl9Fb1QsDQogIHNpZ21hID0gdm9sYXRpbGl0eSwNCiAgZGl2aWRlbmRfeWllbGQgPSBkaXZpZGVuZF95aWVsZA0KKQ0KDQpgYGANCg0KDQpDcmVhdGUgdGFibGUgZm9yIFJlc3VsdHMgDQoNCmBgYHtyfQ0KIyBDcmVhdGUgYSBkYXRhIGZyYW1lIHdpdGggdGhlIG9idGFpbmVkIGRhdGENCnJlc3VsdHMgPC0gZGF0YS5mcmFtZSgNCiAgICBTdG9jayA9ICJJTkciLA0KICAgIEJvVF9EYXRlID0gQm9UX3N0b2NrJERhdGUsDQogICAgQm9UX1ByaWNlID0gQm9UX3N0b2NrJFByaWNlLA0KICAgIEJvVF9PcHRpb25fUHJlbWl1bSA9IEJvVF9wcmVtaXVtLA0KICAgIEVvVF9EYXRlID0gRW9UX3N0b2NrJERhdGUsDQogICAgRW9UX1ByaWNlID0gRW9UX3N0b2NrJFByaWNlLA0KICAgIEVvVF9PcHRpb25fUHJlbWl1bSA9IEVvVF9wcmVtaXVtDQopDQoNCiMgRGlzcGxheSB0aGUgcmVzdWx0cw0KcHJpbnQocmVzdWx0cykNCg0KYGBgDQoNCg0KIyMjIyBBbmFseXNpcyBvZiByZXN1bHRzLiANCkluIHRoaXMgY2FzZSwgd2UgaGF2ZSBvbmx5IGhhZCB0byBhcHBseSB0aGUgZnVuY3Rpb25zIGFuZCBwcm9jZXNzIHdlIGhhZCBqdXN0IGFwcGxpZWQgZm9yIHRoZSBjYWxsIG9wdGlvbi4gVGhlIEFzc2V0IHdlIGhhdmUgc2VsZWN0ZWQgaXMgQmFuayBJTkcgd2hpY2ggd2UgaGFkIGV4cGVjdGVkIHRvIGZhbGwuIEhvd2V2ZXIsIGluIHRoZSByZXN1bHRzIG9idGFpbmVkIHdlIGhhdmUgbm90aWNlZCBhbiBhcHByZWNpYXRpb24gaW4gdGhlIHN0b2NrIHZhbHVlIGFzIHdlbGwgYXMgdGhlIHByZW1pdW1zLiBUaGlzIG1lYW5zIHRoYXQgdGhlIHN0b2NrIGhhcyBvdXQgcGVyZm9ybWVkIG91ciBleHBlY3RhdGlvbnMgYW5kIGhhcyBub3QgZmFsbGVuIGR1cmluZyB0aGUgc2Nob29sIHRlcm0uIEhhZCB3ZSBib3VnaHQgdGhlIHB1dCBvcHRpb24gaW4gdGhlIGJlZ2lubmluZyBvZiB0ZXJtIGRhdGUsIHdlIHdvdWxkIGhhdmUgaGFkIGEgbmVnYXRpdmUgYWN0aW9uIG9mIG91ciBvcGVyYXRpb24uIEhvd2V2ZXIsIHdlIHdvdWxkIGxpa2UgdG8gbm90ZSB0aGF0IGluIHRoZSByZWNlbnQgdGltZXMsIElORyBoYXMgYmVlbiBoaXQgd2l0aCBuZWdhdGl2ZSBuZXdzIGFuZCBpbmZvcm1hdGlvbiByZWdhcmRpbmcgbWFzc2l2ZSB3aXRoZHJhd2Fscy4gSG93ZXZlciwgdGhpcyBpbmZvcm1hdGlvbiBhcHBlYXJzIHRvIGhhdmUgYmVlbiBkZWJ1bmtlZCwgYWx0aG91Z2ggdGhlcmUgaGFzIGJlZW4gb2JzZXJ2ZWQgcmVjZW50IG5lZ2F0aXZlIHN0b2NrIG1vdmVtZW50cy4gDQoNCg0KDQojIyMgTDEuNSANCg0KDQpEZWZpbmUgQm9UIGFuZCBFb1QgZGF0ZXMNCg0KYGBge3J9DQpCb1RfZGF0ZSA8LSBhcy5EYXRlKCIyMDI0LTA1LTAxIikNCkVvVF9kYXRlIDwtIGFzLkRhdGUoIjIwMjQtMDktMzAiKQ0KYGBgDQoNCg0KQ3JlYXRlIGEgRnVuY3Rpb24gdG8gUmV0cmlldmUgRXhjaGFuZ2UgUmF0ZXMgd2l0aCBOb24tVHJhZGluZyBkYXkgQWRqdXN0bWVudA0KDQpgYGB7cn0NCmdldF9leGNoYW5nZV9yYXRlIDwtIGZ1bmN0aW9uKHN5bWJvbCwgZGF0ZSwgdXNlX25leHQgPSBGQUxTRSwgaW52ZXJ0ID0gRkFMU0UpIHsNCiAgIyBSZXRyaWV2ZSBleGNoYW5nZSByYXRlIGRhdGEgZnJvbSBGUkVEDQogIGRhdGEgPC0gZ2V0U3ltYm9scyhTeW1ib2xzID0gc3ltYm9sLCBzcmMgPSAiRlJFRCIsIGF1dG8uYXNzaWduID0gRkFMU0UpDQogIA0KICAjIENvbnZlcnQgaW5kZXggdG8gRGF0ZSBmb3JtYXQNCiAgaW5kZXgoZGF0YSkgPC0gYXMuRGF0ZShpbmRleChkYXRhKSkNCiAgDQogICMgQWRqdXN0IGZvciBub24tdHJhZGluZyBkYXlzDQogIGlmICh1c2VfbmV4dCkgew0KICAgICMgRm9yIEJvVF9kYXRlLCBnZXQgdGhlIG5leHQgYXZhaWxhYmxlIGRhdGUgYWZ0ZXIgdGhlIGRhdGUNCiAgICBhdmFpbGFibGVfZGF0ZXMgPC0gaW5kZXgoZGF0YSlbaW5kZXgoZGF0YSkgPj0gZGF0ZSAmICFpcy5uYShkYXRhW2luZGV4KGRhdGEpXSldDQogICAgaWYobGVuZ3RoKGF2YWlsYWJsZV9kYXRlcykgPT0gMCkgew0KICAgICAgd2FybmluZyhwYXN0ZSgiTm8gZGF0YSBhdmFpbGFibGUgYWZ0ZXIiLCBkYXRlLCAiZm9yIHN5bWJvbDoiLCBzeW1ib2wpKQ0KICAgICAgcmV0dXJuKGxpc3QoUmF0ZSA9IE5BLCBEYXRlID0gTkEpKQ0KICAgIH0NCiAgICBkYXRlX3VzZWQgPC0gbWluKGF2YWlsYWJsZV9kYXRlcykNCiAgfSBlbHNlIHsNCiAgICAjIEZvciBFb1RfZGF0ZSwgZ2V0IHRoZSBsYXN0IGF2YWlsYWJsZSBkYXRlIGJlZm9yZSB0aGUgZGF0ZQ0KICAgIGF2YWlsYWJsZV9kYXRlcyA8LSBpbmRleChkYXRhKVtpbmRleChkYXRhKSA8PSBkYXRlICYgIWlzLm5hKGRhdGFbaW5kZXgoZGF0YSldKV0NCiAgICBpZiAobGVuZ3RoKGF2YWlsYWJsZV9kYXRlcykgPT0gMCkgew0KICAgICAgd2FybmluZyhwYXN0ZSgiTm8gZGF0YSBhdmFpbGFibGUgYmVmb3JlIiwgZGF0ZSwgImZvciBzeW1ib2w6Iiwgc3ltYm9sKSkNCiAgICAgIHJldHVybihsaXN0KFJhdGUgPSBOQSwgRGF0ZSA9IE5BKSkNCiAgICB9DQogICAgZGF0ZV91c2VkIDwtIG1heChhdmFpbGFibGVfZGF0ZXMpDQogIH0NCiAgDQogICMgR2V0IHRoZSBleGNoYW5nZSByYXRlDQogIHJhdGUgPC0gYXMubnVtZXJpYyhkYXRhW2RhdGVfdXNlZF0pDQogIA0KICAjIEludmVydCB0aGUgcmF0ZSBpZiBuZWVkZWQgKGZvciBjdXJyZW5jaWVzIHF1b3RlZCBhcyBmb3JlaWduIGN1cnJlbmN5IHBlciBVU0QpDQogIGlmIChpbnZlcnQpIHsNCiAgICByYXRlIDwtIDEgLyByYXRlDQogIH0NCiAgDQogIHJldHVybihsaXN0KA0KICAgIFJhdGUgPSByYXRlLA0KICAgIERhdGUgPSBhcy5EYXRlKGRhdGVfdXNlZCkNCiAgKSkNCn0NCmBgYA0KDQoNClJldHJpZXZlIEV4Y2hhbmdlIFJhdGVzIG9uIEJvVCBhbmQgRW9UIERhdGVzDQpTeW1ib2xzIGluIEZSRUQ6DQpHUEIvVVNEOiBERVhVU1VLDQpKUFkvVVNEOiBERVhKUFVTDQpNWE4vVVNEOiBERVhNWFVTDQooRlJFRCBwcm92aWRlcyBleGNoYW5nZSByYXRlcyBpbiBmb3JlaWduIGN1cnJlbmN5IHVuaXRzIHBlciBVLlMuIGRvbGxhciBmb3IgSlBZIGFuZCBNWE4sIHNvIHdlJ2xsIGludmVydCB0aGVzZSByYXRlcyB0byBnZXQgVVNEIHBlciBmb3JlaWduIGN1cnJlbmN5IHVuaXQpDQoNCmBgYHtyfQ0KIyBSZXRyaWV2ZSBleGNoYW5nZSByYXRlcyBvbiBCb1RfZGF0ZQ0KR0JQX0JvVCA8LSBnZXRfZXhjaGFuZ2VfcmF0ZSgiREVYVVNVSyIsIEJvVF9kYXRlLCB1c2VfbmV4dCA9IFRSVUUpDQpKUFlfQm9UIDwtIGdldF9leGNoYW5nZV9yYXRlKCJERVhKUFVTIiwgQm9UX2RhdGUsIHVzZV9uZXh0ID0gVFJVRSwgaW52ZXJ0ID0gVFJVRSkNCk1YTl9Cb1QgPC0gZ2V0X2V4Y2hhbmdlX3JhdGUoIkRFWE1YVVMiLCBCb1RfZGF0ZSwgdXNlX25leHQgPSBUUlVFLCBpbnZlcnQgPSBUUlVFKQ0KDQojIFJldHJpZXZlIGV4Y2hhbmdlIHJhdGVzIG9uIEVvVF9kYXRlDQpHQlBfRW9UIDwtIGdldF9leGNoYW5nZV9yYXRlKCJERVhVU1VLIiwgRW9UX2RhdGUsIHVzZV9uZXh0ID0gRkFMU0UpDQpKUFlfRW9UIDwtIGdldF9leGNoYW5nZV9yYXRlKCJERVhKUFVTIiwgRW9UX2RhdGUsIHVzZV9uZXh0ID0gRkFMU0UsIGludmVydCA9IFRSVUUpDQpNWE5fRW9UIDwtIGdldF9leGNoYW5nZV9yYXRlKCJERVhNWFVTIiwgRW9UX2RhdGUsIHVzZV9uZXh0ID0gRkFMU0UsIGludmVydCA9IFRSVUUpDQpgYGANCg0KDQpDcmVhdGUgYSBEYXRhIEZyYW1lIHRvIERpc3BsYXkgdGhlIFJlc3VsdHMNCg0KYGBge3J9DQojIENyZWF0ZSBkYXRhIGZyYW1lIHdpdGggdGhlIHJlc3VsdHMNCnJlc3VsdHMgPC0gZGF0YS5mcmFtZSgNCiAgQ3VycmVuY3kgPSBjKCJHQlAvVVNEIiwgIkpQWS9VU0QiLCAiTVhOL1VTRCIpLA0KICBCb1RfRGF0ZSA9IGMoR0JQX0JvVCREYXRlLCBKUFlfQm9UJERhdGUsIE1YTl9Cb1QkRGF0ZSksDQogIEJvVF9SYXRlID0gYyhHQlBfQm9UJFJhdGUsIEpQWV9Cb1QkUmF0ZSwgTVhOX0JvVCRSYXRlKSwNCiAgRW9UX0RhdGUgPSBjKEdCUF9Fb1QkRGF0ZSwgSlBZX0VvVCREYXRlLCBNWE5fRW9UJERhdGUpLA0KICBFb1RfUmF0ZSA9IGMoR0JQX0VvVCRSYXRlLCBKUFlfRW9UJFJhdGUsIE1YTl9Fb1QkUmF0ZSkNCikNCg0KIyBEaXNwbGF5IHRoZSByZXN1bHRzDQpwcmludChyZXN1bHRzKQ0KYGBgDQoNCg0KIyMjIyBBbmFseXNpcyBvZiByZXN1bHRzDQpJbiB0aGlzIGV4ZXJjaXNlIHdlIGhhdmUgZGVzaWduZWQgYSBuZXcgZnVuY3Rpb24gdG8gcmV0cmlldmUgZXhjaGFuZ2UgcmF0ZXMsIGFzIGFsd2F5cyBhZGp1c3RpbmcgaXQgdG8gdGhlIG5vbi10cmFkaW5nIGRheXMuIFdlIGhhdmUgcmV0cmlldmUgdGhlIGRhdGEgb2YgdGhyZWUgZGlmZmVyZW50IGV4Y2hhbmdlIHJhdGVzIGJvdGggb24gQm9UIGRhdGUgYW5kIEVvVCBkYXRlIGFuZCB3ZSBoYXZlIHBvcnRyYXllZCB0aGUgcmVzdWx0IGluIGEgZGF0YSBmcmFtZS4gDQoNCg0KIyMjIEwxLjYgVXNlIGN1cnJlbmN5IG9wdGlvbnMgZGF0YSAoaWYgYXZhaWxhYmxlKSB0byBzZWxlY3QgYSBjYWxsIG9wdGlvbiBvbiBhIGZvcmVpZ24gY3VycmVuY3kgdGhhdCB5b3UgZXhwZWN0IHdpbGwgc3RyZW5ndGhlbiBhZ2FpbnN0IHRoZSBkb2xsYXIgKHNlbGVjdCB0aGUgb3B0aW9uIHdpdGggdGhlIGZpcnN0IGV4cGlyYXRpb24gbW9udGggYmV5b25kIHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtKQ0KDQoNCkxvYWQgcGFja2FnZXMNCg0KYGBge3J9DQojIExvYWQgcGFja2FnZXMNCmxpYnJhcnkocXVhbnRtb2QpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkodGltZURhdGUpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCg0KYGBgDQoNCg0KRGVmaW5lIEJvVCBhbmQgRW9UIERhdGVzDQoNCmBgYHtyfQ0KQm9UX2RhdGUgPC0gYXMuRGF0ZSgiMjAyNC0wNS0wMSIpDQpFb1RfZGF0ZSA8LSBhcy5EYXRlKCIyMDI0LTA5LTMwIikNCmBgYA0KDQoNCkNyZWF0ZSBhIGZ1bmN0aW9uIHRvIEFkanVzdCBmb3IgTm9uLVRyYWRpbmcgRGF5cyBhbmQgT2J0YWluIEV4Y2hhbmdlIFJhdGUgRGF0YQ0KDQpgYGB7cn0NCmdldF9leGNoYW5nZV9yYXRlIDwtIGZ1bmN0aW9uKHN5bWJvbCwgZGF0ZSwgdXNlX25leHQgPSBGQUxTRSkgew0KICAjIERvd25sb2FkIGRhdGEgYXJvdW5kIHRoZSBkYXRlDQogIGRhdGEgPC0gZ2V0U3ltYm9scygNCiAgICBTeW1ib2xzID0gc3ltYm9sLA0KICAgIHNyYyA9ICJ5YWhvbyIsDQogICAgZnJvbSA9IGRhdGUgLSBkYXlzKDEwKSwNCiAgICB0byA9IGRhdGUgKyBkYXlzKDEwKSwNCiAgICBhdXRvLmFzc2lnbiA9IEZBTFNFDQogICkNCiAgDQogICMgQ29udmVydCBpbmRleCB0byBEYXRlIGZvcm1hdA0KICBpbmRleChkYXRhKSA8LSBhcy5EYXRlKGluZGV4KGRhdGEpKQ0KICANCiAgIyBIYW5kbGUgbm9uLXRyYWRpbmcgZGF5cw0KICBpZiAodXNlX25leHQpIHsNCiAgICAjIEZvciBCb1RfZGF0ZSwgZ2V0IHRoZSBuZXh0IGF2YWlsYWJsZSBkYXRlIGFmdGVyIHRoZSBkYXRlDQogICAgYXZhaWxhYmxlX2RhdGVzIDwtIGluZGV4KGRhdGEpW2luZGV4KGRhdGEpID49IGRhdGVdDQogICAgaWYobGVuZ3RoKGF2YWlsYWJsZV9kYXRlcykgPT0gMCkgew0KICAgICAgd2FybmluZyhwYXN0ZSgiTm8gZGF0YSBhdmFpbGFibGUgYWZ0ZXIiLCBkYXRlLCAiZm9yIHN5bWJvbDoiLCBzeW1ib2wpKQ0KICAgICAgcmV0dXJuKGxpc3QoUmF0ZSA9IE5BLCBEYXRlID0gTkEpKQ0KICAgIH0NCiAgICBkYXRlX3VzZWQgPC0gbWluKGF2YWlsYWJsZV9kYXRlcykNCiAgfSBlbHNlIHsNCiAgICAjIEZvciBFb1RfZGF0ZSwgZ2V0IHRoZSBsYXN0IGF2YWlsYWJsZSBkYXRlIGJlZm9yZSB0aGUgZGF0ZQ0KICAgIGF2YWlsYWJsZV9kYXRlcyA8LSBpbmRleChkYXRhKVtpbmRleChkYXRhKSA8PSBkYXRlXQ0KICAgIGlmIChsZW5ndGgoYXZhaWxhYmxlX2RhdGVzKSA9PSAwKSB7DQogICAgICB3YXJuaW5nKHBhc3RlKCJObyBkYXRhIGF2YWlsYWJsZSBiZWZvcmUiLCBkYXRlLCAiZm9yIHN5bWJvbDoiLCBzeW1ib2wpKQ0KICAgICAgcmV0dXJuKGxpc3QoUmF0ZSA9IE5BLCBEYXRlID0gTkEpKQ0KICAgIH0NCiAgICBkYXRlX3VzZWQgPC0gbWF4KGF2YWlsYWJsZV9kYXRlcykNCiAgfQ0KICANCiAgIyBHZXQgdGhlIGV4Y2hhbmdlIHJhdGUNCiAgcmF0ZSA8LSBhcy5udW1lcmljKENsKGRhdGFbZGF0ZV91c2VkXSkpDQogIA0KICByZXR1cm4obGlzdCgNCiAgICBSYXRlID0gcmF0ZSwNCiAgICBEYXRlID0gYXMuRGF0ZShkYXRlX3VzZWQpDQogICkpDQp9DQpgYGANCg0KDQpSZXRyaWV2ZSBFeGNoYWJnZSBSYXRlcyBvbiBCb1QgYW5kIEVvVCBkYXRlcw0KDQpgYGB7cn0NCiMgR2V0IGV4Y2hhbmdlIHJhdGVzIGZvciBDTlkvVVNEDQojIE5vdGU6IE9uIFlhaG9vIEZpbmFuY2UsIHRoZSBzeW1ib2wgZm9yIENOWS9VU0QgaXMgIkNOWT1YIg0KDQpDTllfQm9UIDwtIGdldF9leGNoYW5nZV9yYXRlKCJDTlk9WCIsIEJvVF9kYXRlLCB1c2VfbmV4dCA9IFRSVUUpDQpDTllfRW9UIDwtIGdldF9leGNoYW5nZV9yYXRlKCJDTlk9WCIsIEVvVF9kYXRlLCB1c2VfbmV4dCA9IEZBTFNFKQ0KYGBgDQoNCg0KRGV0ZXJtaW5lIE9wdGlvbiBEZXRhaWxzDQorT3B0aW9uIHR5cGU6IENhbGwgb3B0aW9uDQorU3RyaWtlIFByaWNlOiBVc2UgdGhlIHNwb3QgZXhjaGFuZ2UgcmF0ZSBhdCBCb1RfRGF0ZSAoQXQtVGhlLU1vbmV5KQ0KK0V4cGlyYXRpb24gRGF0ZTogRmlyc3Qgb3B0aW9uIGV4cGlyYXRpb24gZGF0ZSBiZXlvbmQgRW9UX0RhdGUNCg0KDQpHZW5lcmF0ZSBPcHRpb24gRXhwaXJhdGlvbiBEYXRlcw0KDQpgYGB7cn0NCiMgRnVuY3Rpb24gdG8gZ2V0IHRoZSB0aGlyZCBGcmlkYXkgb2YgYSBtb250aA0KdGhpcmRfZnJpZGF5IDwtIGZ1bmN0aW9uKHllYXIsIG1vbnRoKSB7DQogIGRhdGVzIDwtIHNlcSgNCiAgICBmcm9tID0gYXMuRGF0ZShwYXN0ZTAoeWVhciwgIi0iLCBtb250aCwgIi0wMSIpKSwNCiAgICB0byA9IGFzLkRhdGUocGFzdGUwKHllYXIsICItIiwgbW9udGgsICItIiwgZGF5c19pbl9tb250aChhcy5EYXRlKHBhc3RlMCh5ZWFyLCAiLSIsIG1vbnRoLCAiLTAxIikpKSkpLA0KICAgIGJ5ID0gImRheSINCiAgKQ0KICBmcmlkYXlzIDwtIGRhdGVzW3dkYXkoZGF0ZXMpID09IDZdICAjIDYgY29ycmVzcG9uZHMgdG8gRnJpZGF5DQogIGlmIChsZW5ndGgoZnJpZGF5cykgPj0gMykgew0KICAgIHJldHVybihmcmlkYXlzWzNdKQ0KICB9IGVsc2Ugew0KICAgIHJldHVybihOQSkNCiAgfQ0KfQ0KDQojIEdlbmVyYXRlIGV4cGlyYXRpb24gZGF0ZXMgZm9yIHRoZSBuZXh0IDE4IG1vbnRocw0KZXhwaXJhdGlvbl9kYXRlcyA8LSBhcy5EYXRlKGNoYXJhY3RlcigpKQ0KY3VycmVudF9kYXRlIDwtIGFzLkRhdGUoU3lzLkRhdGUoKSkNCg0KZm9yIChpIGluIDA6MTcpIHsNCiAgZGF0ZSA8LSBjdXJyZW50X2RhdGUgJW0rJSBtb250aHMoaSkNCiAgeXIgPC0geWVhcihkYXRlKQ0KICBtbnRoIDwtIG1vbnRoKGRhdGUpDQogIGV4cF9kYXRlIDwtIHRoaXJkX2ZyaWRheSh5ciwgbW50aCkNCiAgaWYgKCFpcy5uYShleHBfZGF0ZSkpIHsNCiAgICBleHBpcmF0aW9uX2RhdGVzIDwtIGMoZXhwaXJhdGlvbl9kYXRlcywgZXhwX2RhdGUpDQogIH0NCn0NCg0KIyBGaWx0ZXIgZXhwaXJhdGlvbiBkYXRlcyBiZXlvbmQgRW9UX2RhdGUNCmV4cGlyYXRpb25fZGF0ZXMgPC0gZXhwaXJhdGlvbl9kYXRlc1tleHBpcmF0aW9uX2RhdGVzID4gRW9UX2RhdGVdDQoNCiMgU2VsZWN0IHRoZSBmaXJzdCBleHBpcmF0aW9uIGRhdGUgYmV5b25kIEVvVF9kYXRlDQppZiAobGVuZ3RoKGV4cGlyYXRpb25fZGF0ZXMpID09IDApIHsNCiAgc3RvcCgiTm8gZXhwaXJhdGlvbiBkYXRlcyBmb3VuZCBiZXlvbmQgRW9UX2RhdGUuIikNCn0NCg0KZXhwaXJhdGlvbl9kYXRlIDwtIGV4cGlyYXRpb25fZGF0ZXNbMV0NCnByaW50KHBhc3RlKCJTZWxlY3RlZCBPcHRpb24gRXhwaXJhdGlvbiBEYXRlOiIsIGV4cGlyYXRpb25fZGF0ZSkpDQpgYGANCg0KDQpDYWxjdWxhdGUgVGltZSB0byBleHBpcmF0aW9uDQoNCmBgYHtyfQ0KIyBUaW1lIHRvIGV4cGlyYXRpb24gZnJvbSBCb1RfZGF0ZQ0KdGltZV90b19leHBpcmF0aW9uX0JvVCA8LSBhcy5udW1lcmljKGV4cGlyYXRpb25fZGF0ZSAtIENOWV9Cb1QkRGF0ZSkgLyAzNjUNCg0KIyBUaW1lIHRvIGV4cGlyYXRpb24gZnJvbSBFb1RfZGF0ZQ0KdGltZV90b19leHBpcmF0aW9uX0VvVCA8LSBhcy5udW1lcmljKGV4cGlyYXRpb25fZGF0ZSAtIENOWV9Fb1QkRGF0ZSkgLyAzNjUNCmBgYA0KDQoNClNldCB0aGUgU3RyaWtlIFByaWNlDQoNCmBgYHtyfQ0Kc3RyaWtlX3ByaWNlIDwtIENOWV9Cb1QkUmF0ZSAgIyBBdC1UaGUtTW9uZXkgb3B0aW9uDQpgYGANCg0KDQpFc3RpbWF0ZSBWb2xhdGlsaXR5DQoNCmBgYHtyfQ0KIyBHZXQgaGlzdG9yaWNhbCBleGNoYW5nZSByYXRlIGRhdGEgZm9yIHRoZSBwYXN0IHllYXIgYmVmb3JlIEJvVF9kYXRlDQp2b2xfZGF0YSA8LSBnZXRTeW1ib2xzKA0KICBTeW1ib2xzID0gIkNOWT1YIiwNCiAgc3JjID0gInlhaG9vIiwNCiAgZnJvbSA9IENOWV9Cb1QkRGF0ZSAtIHllYXJzKDEpLA0KICB0byA9IENOWV9Cb1QkRGF0ZSwNCiAgYXV0by5hc3NpZ24gPSBGQUxTRQ0KKQ0KDQojIENhbGN1bGF0ZSBkYWlseSByZXR1cm5zDQpyZXR1cm5zIDwtIGRhaWx5UmV0dXJuKENsKHZvbF9kYXRhKSkNCg0KIyBDYWxjdWxhdGUgYW5udWFsaXplZCB2b2xhdGlsaXR5DQp2b2xhdGlsaXR5IDwtIHNkKHJldHVybnMsIG5hLnJtID0gVFJVRSkgKiBzcXJ0KDI1MikgICMgMjUyIHRyYWRpbmcgZGF5cyBpbiBhIHllYXINCmBgYA0KDQoNClNldCBEb21lc3RpYyBhbmQgRm9yZWlnbiBSaXNrLUZyZWUgSW50ZXJlc3QgUmF0ZXMNCkRvbWVzdGljIFJpc2stRnJlZSBSYXRlIChyX2RvbWVzdGljKTogVVMgcmlzay1mcmVlIHJhdGUNCkZvcmVpZ24gUmlzay1GcmVlIFJhdGUgKHJfZm9yZWlnbik6IENoaW5lc2Ugcmlzay1mcmVlIHJhdGUNCg0KYGBge3J9DQpyX2RvbWVzdGljIDwtIDAuMDQzDQpyX2ZvcmVpZ24gPC0gMC4wMjA5DQpgYGANCg0KDQpEZWZpbmUgdGhlIEdhcm1hbi1Lb2hsaGFnZW4gTW9kZWwgRnVuY3Rpb24NCg0KYGBge3J9DQpjYWxjdWxhdGVfY3VycmVuY3lfb3B0aW9uX3ByZW1pdW0gPC0gZnVuY3Rpb24oUywgSywgcl9kb21lc3RpYywgcl9mb3JlaWduLCB0aW1lX3RvX2V4cGlyYXRpb24sIHNpZ21hLCBvcHRpb25fdHlwZSA9ICJjYWxsIikgew0KICBkMSA8LSAobG9nKFMgLyBLKSArIChyX2RvbWVzdGljIC0gcl9mb3JlaWduICsgMC41ICogc2lnbWFeMikgKiB0aW1lX3RvX2V4cGlyYXRpb24pIC8gKHNpZ21hICogc3FydCh0aW1lX3RvX2V4cGlyYXRpb24pKQ0KICBkMiA8LSBkMSAtIHNpZ21hICogc3FydCh0aW1lX3RvX2V4cGlyYXRpb24pDQogIA0KICBpZiAob3B0aW9uX3R5cGUgPT0gImNhbGwiKSB7DQogICAgcHJlbWl1bSA8LSBTICogZXhwKC1yX2ZvcmVpZ24gKiB0aW1lX3RvX2V4cGlyYXRpb24pICogcG5vcm0oZDEpIC0gSyAqIGV4cCgtcl9kb21lc3RpYyAqIHRpbWVfdG9fZXhwaXJhdGlvbikgKiBwbm9ybShkMikNCiAgfSBlbHNlIGlmIChvcHRpb25fdHlwZSA9PSAicHV0Iikgew0KICAgIHByZW1pdW0gPC0gSyAqIGV4cCgtcl9kb21lc3RpYyAqIHRpbWVfdG9fZXhwaXJhdGlvbikgKiBwbm9ybSgtZDIpIC0gUyAqIGV4cCgtcl9mb3JlaWduICogdGltZV90b19leHBpcmF0aW9uKSAqIHBub3JtKC1kMSkNCiAgfSBlbHNlIHsNCiAgICBzdG9wKCJJbnZhbGlkIG9wdGlvbiB0eXBlLiBVc2UgJ2NhbGwnIG9yICdwdXQnLiIpDQogIH0NCiAgDQogIHJldHVybihwcmVtaXVtKQ0KfQ0KYGBgDQoNCg0KQ2FsY3VsYXRlIE9wdGlvbiBQcmVtaXVtcw0KDQpgYGB7cn0NCiMgT3B0aW9uIHByZW1pdW0gb24gQm9UX2RhdGUNCkJvVF9wcmVtaXVtIDwtIGNhbGN1bGF0ZV9jdXJyZW5jeV9vcHRpb25fcHJlbWl1bSgNCiAgUyA9IENOWV9Cb1QkUmF0ZSwNCiAgSyA9IHN0cmlrZV9wcmljZSwNCiAgcl9kb21lc3RpYyA9IHJfZG9tZXN0aWMsDQogIHJfZm9yZWlnbiA9IHJfZm9yZWlnbiwNCiAgdGltZV90b19leHBpcmF0aW9uID0gdGltZV90b19leHBpcmF0aW9uX0JvVCwNCiAgc2lnbWEgPSB2b2xhdGlsaXR5LA0KICBvcHRpb25fdHlwZSA9ICJjYWxsIg0KKQ0KDQojIE9wdGlvbiBwcmVtaXVtIG9uIEVvVF9kYXRlDQpFb1RfcHJlbWl1bSA8LSBjYWxjdWxhdGVfY3VycmVuY3lfb3B0aW9uX3ByZW1pdW0oDQogIFMgPSBDTllfRW9UJFJhdGUsDQogIEsgPSBzdHJpa2VfcHJpY2UsDQogIHJfZG9tZXN0aWMgPSByX2RvbWVzdGljLA0KICByX2ZvcmVpZ24gPSByX2ZvcmVpZ24sDQogIHRpbWVfdG9fZXhwaXJhdGlvbiA9IHRpbWVfdG9fZXhwaXJhdGlvbl9Fb1QsDQogIHNpZ21hID0gdm9sYXRpbGl0eSwNCiAgb3B0aW9uX3R5cGUgPSAiY2FsbCINCikNCmBgYA0KDQoNCkNyZWF0ZSBEYXRhIEZyYW1lIHRvIERpc3BsYXkgUmVzdWx0cw0KDQpgYGB7cn0NCiMgQ3JlYXRlIGRhdGEgZnJhbWUgd2l0aCB0aGUgcmVzdWx0cw0KcmVzdWx0cyA8LSBkYXRhLmZyYW1lKA0KICBDdXJyZW5jeSA9ICJDTlkvVVNEIiwNCiAgQm9UX0RhdGUgPSBDTllfQm9UJERhdGUsDQogIEJvVF9SYXRlID0gQ05ZX0JvVCRSYXRlLA0KICBCb1RfT3B0aW9uX1ByZW1pdW0gPSBCb1RfcHJlbWl1bSwNCiAgRW9UX0RhdGUgPSBDTllfRW9UJERhdGUsDQogIEVvVF9SYXRlID0gQ05ZX0VvVCRSYXRlLA0KICBFb1RfT3B0aW9uX1ByZW1pdW0gPSBFb1RfcHJlbWl1bQ0KKQ0KDQojIERpc3BsYXkgdGhlIHJlc3VsdHMNCnByaW50KHJlc3VsdHMpDQpgYGANCg0KDQojIyMjIEFuYWx5c2lzIG9mIHJlc3VsdHMNCg0KSW4gdGhpcyBleGVyY2lzZSB3ZSBoYXZlIHBlcmZvcm1lZCBhIHJhdGhlciBzaW1pbGFyIHByb2Nlc3MgdGhhbiB0aGF0IG9mIEwxLjQgYW5kIEwxLjUuIEhvd2V2ZXIsIGluIHRoaXMgY2FzZSB3ZSBhcmUgc3R1ZHlpbmcgYSBjYWxsIG9wdGlvbiBvbiBhIGN1cnJlbmN5IHRoYXQgd2UgdGhpbmsgbWlnaHQgYXBwcmVjaWF0ZSBpbiB2YWx1ZSBkdXJpbmcgdGhlIHNjaG9vbCB0ZXJtLiBUaGUgY3VycmVuY3kgd2UgaGF2ZSBzZWxlY3RlZCBoYXMgYmVlbiAgdGhlIENoaW5lc2UgWXVhbi4gVGhlIHdlYWtlbmluZyBvZiB0aGUgVVMgVHJlYXN1cnkgSW50ZXJlc3QgaXMgb25lIG9mIHRoZSBtYWluIGRyaXZlcnMgb2YgdGhlIHdlYWtlbmluZyBvZiB0aGUgVVMgRG9sbGFyIGFuZCBwcm9iYWJseSB0aGUgbWFpbiByZWFzb24gZm9yIHRoZSBhcHByZWNpYXRpb24gb2YgdGhlIENoaW5lc2UgWXVhbiBhZ2FpbnN0IGl0LiAgDQpJbiB0aGlzIGNhc2UsIHdlIGhhdmUgbm90IHVzZWQgdGhlIEJsYWNrLVNjaG9sZXMgTW9kZWwsIGJ1dCByYXRoZXIgdGhlIEdhcm1hbi1Lb2hsaGFnZW4gTW9kZWwgRnVuY3Rpb24sIHdoaWNoIGlzIG9mdGVuIHVzZSB0byBwcmljZSBjdXJyZW5jeSBvcHRpb25zLiANCg0KUmVnYXJkaW5nIHRoZSByZXN1bHRzLCBpbiB0aGlzIGNhc2Ugd2UgaGF2ZSBub3QgYmVlbiBhYmxlIHRvIHNlY3VyZSBhIGZhdm9yYWJsZSByZXN1bHQgaW4gdGhlIGNhbGwgb3B0aW9uLCBhcyB0aGUgcmF0ZSBoYXMgZGVwcmVjaWF0ZWQsIGFzIHdlbGwgYXMgdGhlIHByZW1pdW0sIGF0IEVvVC4gVGhpcyByZXN1bHRzIGNhbiBiZSBleHBsYWluZWQgZHVlIHRvIGEgZ3JlYXQgcmFuZ2Ugb2YgZmFjdG9ycyB0aGF0IGluY2x1ZGUgbW9uZXRhcnkgcG9saWN5IG9mIGJvdGggY291bnRyaWVzLCBtYXJrZXQgbW92ZW1lbnRzLCBzdXBwbHkgYW5kIGRlbWFuZCwgbWFjcm9lY29ub21pYyBkYXRhLCBtaWNyb2Vjb25vbWljIGRldGFpbHMgb3IgZXZlbiBzcGVjdWxhdGlvbiBmcm9tIGludmVzdG9ycy4gRWl0aGVyIHdheSwgdGhlIHJlc3VsdHMgZGVwaWN0IGFuIHN0cmVuZ3RoZW4gVVMgRG9sbGFyIGFnYWluc3QgdGhlIENoaW5lc2UgWXVhbiBhbmQgdGhlIGV4ZXJjaXNlIGhlbHBzIHVzIHRvIGV4ZW1wbGlmeSBob3cgYSBjYWxsIG9wdGlvbiBvbiBhIGN1cnJlbmN5IG1heSBiZSBwcmljZWQuIA0KDQoNCg0KIyMjIEwxLjcgVXNlIGN1cnJlbmN5IG9wdGlvbnMgZGF0YSAoaWYgYXZhaWxhYmxlKSB0byBzZWxlY3QgYSBwdXQgb3B0aW9uIG9uIGEgZm9yZWlnbiBjdXJyZW5jeSB0aGF0IHlvdSBleHBlY3Qgd2lsbCB3ZWFrZW4gYWdhaW5zdCB0aGUgZG9sbGFyIChzZWxlY3QgdGhlIG9wdGlvbiB3aXRoIHRoZSBmaXJzdCBleHBpcmF0aW9uIG1vbnRoIGJleW9uZCB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybSkuDQoNClJldHJpZXZlIEV4Y2hhbmdlIFJhdGVzIG9uIEJvVCBhbmQgRW9UIGRhdGVzDQoNCmBgYHtyfQ0KIyBHZXQgZXhjaGFuZ2UgcmF0ZXMgZm9yIEVVUi9VU0QNCiMgTm90ZTogT24gWWFob28gRmluYW5jZSwgdGhlIHN5bWJvbCBmb3IgQ05ZL1VTRCBpcyAiRVVSVVNEPVgiDQoNCkVVUl9Cb1QgPC0gZ2V0X2V4Y2hhbmdlX3JhdGUoIkVVUlVTRD1YIiwgQm9UX2RhdGUsIHVzZV9uZXh0ID0gVFJVRSkNCkVVUl9Fb1QgPC0gZ2V0X2V4Y2hhbmdlX3JhdGUoIkVVUlVTRD1YIiwgRW9UX2RhdGUsIHVzZV9uZXh0ID0gRkFMU0UpDQpgYGANCg0KDQpEZXRlcm1pbmUgT3B0aW9uIERldGFpbHMNCitPcHRpb24gdHlwZTogQ2FsbCBvcHRpb24NCitTdHJpa2UgUHJpY2U6IFVzZSB0aGUgc3BvdCBleGNoYW5nZSByYXRlIGF0IEJvVF9EYXRlIChBdC1UaGUtTW9uZXkpDQorRXhwaXJhdGlvbiBEYXRlOiBGaXJzdCBvcHRpb24gZXhwaXJhdGlvbiBkYXRlIGJleW9uZCBFb1RfRGF0ZQ0KDQoNCkNhbGN1bGF0ZSBUaW1lIHRvIGV4cGlyYXRpb24NCg0KYGBge3J9DQojIFRpbWUgdG8gZXhwaXJhdGlvbiBmcm9tIEJvVF9kYXRlDQp0aW1lX3RvX2V4cGlyYXRpb25fQm9UIDwtIGFzLm51bWVyaWMoZXhwaXJhdGlvbl9kYXRlIC0gRVVSX0JvVCREYXRlKSAvIDM2NQ0KDQojIFRpbWUgdG8gZXhwaXJhdGlvbiBmcm9tIEVvVF9kYXRlDQp0aW1lX3RvX2V4cGlyYXRpb25fRW9UIDwtIGFzLm51bWVyaWMoZXhwaXJhdGlvbl9kYXRlIC0gRVVSX0VvVCREYXRlKSAvIDM2NQ0KYGBgDQoNCg0KU2V0IHRoZSBTdHJpa2UgUHJpY2UNCg0KYGBge3J9DQpzdHJpa2VfcHJpY2UgPC0gRVVSX0JvVCRSYXRlICAjIEF0LVRoZS1Nb25leSBvcHRpb24NCmBgYA0KDQoNCkVzdGltYXRlIFZvbGF0aWxpdHkNCg0KYGBge3J9DQojIEdldCBoaXN0b3JpY2FsIGV4Y2hhbmdlIHJhdGUgZGF0YSBmb3IgdGhlIHBhc3QgeWVhciBiZWZvcmUgQm9UX2RhdGUNCnZvbF9kYXRhIDwtIGdldFN5bWJvbHMoDQogIFN5bWJvbHMgPSAiRVVSVVNEPVgiLA0KICBzcmMgPSAieWFob28iLA0KICBmcm9tID0gRVVSX0JvVCREYXRlIC0geWVhcnMoMSksDQogIHRvID0gRVVSX0JvVCREYXRlLA0KICBhdXRvLmFzc2lnbiA9IEZBTFNFDQopDQoNCiMgQ2FsY3VsYXRlIGRhaWx5IHJldHVybnMNCnJldHVybnMgPC0gZGFpbHlSZXR1cm4oQ2wodm9sX2RhdGEpKQ0KDQojIENhbGN1bGF0ZSBhbm51YWxpemVkIHZvbGF0aWxpdHkNCnZvbGF0aWxpdHkgPC0gc2QocmV0dXJucywgbmEucm0gPSBUUlVFKSAqIHNxcnQoMjUyKSAgIyAyNTIgdHJhZGluZyBkYXlzIGluIGEgeWVhcg0KYGBgDQoNCg0KU2V0IERvbWVzdGljIGFuZCBGb3JlaWduIFJpc2stRnJlZSBJbnRlcmVzdCBSYXRlcw0KRG9tZXN0aWMgUmlzay1GcmVlIFJhdGUgKHJfZG9tZXN0aWMpOiBVUyByaXNrLWZyZWUgcmF0ZQ0KRm9yZWlnbiBSaXNrLUZyZWUgUmF0ZSAocl9mb3JlaWduKTogRXVyb3BlYW4gcmlzay1mcmVlIHJhdGUNCg0KYGBge3J9DQpyX2RvbWVzdGljIDwtIDAuMDQzDQpyX2ZvcmVpZ24gPC0gMC4wMjQ3DQpgYGANCg0KDQpDYWxjdWxhdGUgT3B0aW9uIFByZW1pdW1zDQoNCmBgYHtyfQ0KIyBPcHRpb24gcHJlbWl1bSBvbiBCb1RfZGF0ZQ0KQm9UX3ByZW1pdW0gPC0gY2FsY3VsYXRlX2N1cnJlbmN5X29wdGlvbl9wcmVtaXVtKA0KICBTID0gRVVSX0JvVCRSYXRlLA0KICBLID0gc3RyaWtlX3ByaWNlLA0KICByX2RvbWVzdGljID0gcl9kb21lc3RpYywNCiAgcl9mb3JlaWduID0gcl9mb3JlaWduLA0KICB0aW1lX3RvX2V4cGlyYXRpb24gPSB0aW1lX3RvX2V4cGlyYXRpb25fQm9ULA0KICBzaWdtYSA9IHZvbGF0aWxpdHksDQogIG9wdGlvbl90eXBlID0gInB1dCINCikNCg0KIyBPcHRpb24gcHJlbWl1bSBvbiBFb1RfZGF0ZQ0KRW9UX3ByZW1pdW0gPC0gY2FsY3VsYXRlX2N1cnJlbmN5X29wdGlvbl9wcmVtaXVtKA0KICBTID0gRVVSX0VvVCRSYXRlLA0KICBLID0gc3RyaWtlX3ByaWNlLA0KICByX2RvbWVzdGljID0gcl9kb21lc3RpYywNCiAgcl9mb3JlaWduID0gcl9mb3JlaWduLA0KICB0aW1lX3RvX2V4cGlyYXRpb24gPSB0aW1lX3RvX2V4cGlyYXRpb25fRW9ULA0KICBzaWdtYSA9IHZvbGF0aWxpdHksDQogIG9wdGlvbl90eXBlID0gInB1dCINCikNCmBgYA0KDQoNCkNyZWF0ZSBEYXRhIEZyYW1lIHRvIERpc3BsYXkgUmVzdWx0cw0KDQpgYGB7cn0NCiMgQ3JlYXRlIGRhdGEgZnJhbWUgd2l0aCB0aGUgcmVzdWx0cw0KcmVzdWx0cyA8LSBkYXRhLmZyYW1lKA0KICBDdXJyZW5jeSA9ICJFVVIvVVNEIiwNCiAgQm9UX0RhdGUgPSBFVVJfQm9UJERhdGUsDQogIEJvVF9SYXRlID0gRVVSX0JvVCRSYXRlLA0KICBCb1RfT3B0aW9uX1ByZW1pdW0gPSBCb1RfcHJlbWl1bSwNCiAgRW9UX0RhdGUgPSBFVVJfRW9UJERhdGUsDQogIEVvVF9SYXRlID0gRVVSX0VvVCRSYXRlLA0KICBFb1RfT3B0aW9uX1ByZW1pdW0gPSBFb1RfcHJlbWl1bQ0KKQ0KDQojIERpc3BsYXkgdGhlIHJlc3VsdHMNCnByaW50KHJlc3VsdHMpDQpgYGANCg0KIyMjIyBBbmFseXNpcyBvZiByZXN1bHRzDQpJbiB0aGlzIGxhc3QgZXhlcmNpc2Ugb2YgdGhlIHNlY3Rpb24gd2UgaGF2ZSByZXRyaWV2ZWQgdGhlIGluZm9ybWF0aW9uIG9mIHRoZSBSYXRlIG9mIEV4Y2hhbmdlIEVVUi9VU0QgYW5kIHdlIGhhZCBhbiBpbml0aWFsIGV4cGVjdGF0aW9uIG9mIGEgZGVjcmVhc2UgaW4gdGhlIHZhbHVlIG9mIHRoZSBFVVIgb3ZlciB0aGUgc2Nob29sIHRlcm0uIEhvd2V2ZXIsIG91ciBpbml0aWFsIHRob3VnaHRzIGhhdmUgYmVlbiBwcm92ZW4gd3JvbmcgYXMgd2UgaGF2ZSBvYnRhaW5lZCBhIGhpZ2hlciByYXRlIGF0IHRoZSBFb1QgZGF0ZSBhbmQgdGhlIE9wdGlvbiBQcmVtaXVtIGhhcyBmYWxsZW4uIEluIHRoZSBjYXNlIG9mIGhhdmluZyBidXllZCB0aGlzIHB1dCBvcHRpb24sIHRoZSBvdXRjb21lIHdvdWxkIGhhdmUgcmVzdWx0ZWQgaW4gYSBuZWdhdGl2ZSBvcGVyYXRpb24uIA0KVGhpcyByZXN1bHRzIGRlcGljdCBhbiBzdHJlbmd0aGVuZWQgRXVybyBhZ2FpbnN0IHRoZSBEb2xsYXIuIA0KRXZlbiB0aG91Z2ggb3VyIGluaXRpYWwgaHlwb3RoZXNpcyBvZiB0aGUgbW92ZW1lbnQgb2YgdGhlIEV1cm8gYWdhaW5zdCB0aGUgRG9sbGFyIHdlcmUgd3JvbmcsIHdlIGhhdmUgZGV2ZWxvcGVkIGFuIGFuc3dlciB0aGF0IGV4cGxhaW5zIGhvdyBhIHB1dCBvcHRpb24gb24gYW4gY3VycmVuY3kgZXhjaGFuZ2UgcmF0ZSBtYXkgYmUgcHJpY2VkIGFuZCBob3cgaXRzIHByZW1pdW0gY2FuIGJlIGNhbGN1bGF0ZWQsIHVzaW5nIHRoZSBHYXJtYW4tS29obGhhZ2VuIE1vZGVsIEZ1bmN0aW9uLiANCg0KDQoNCg0KIyMgTDIgRmluYW5jaWFsIG1hcmtldHMgbWljcm9zdHJ1Y3R1cmUNCg0KDQpOYXNkYXEgYW5kIExvbmRvbiBTdG9jayBFeGNoYW5nZSBhcmUgdHdvIG1ham9yIGdsb2JhbCBzdG9jayBleGNoYW5nZXMgd2l0aCBzaWduaWZpY2FudCBpbmZsdWVuY2Ugbm8gZ2xvYmFsIGZpbmFuY2lhbCBtYXJrZXRzLiANCkhpc3RvcmljYWwgU3RvY2sgZGF0YSBmb3IgcmVwcmVzZW50YXRpdmUgaW5kaWNlcyBvZiBib3RoIGV4Y2hhbmdlcyBjYW4gYmUgcmV0cmlldmVkIGFuZCBhbmFseXplZCB1c2luZyBSLiBRdWFsaXRhdGl2ZSBpbmZvcm1hdGlvbiBhYm91dCBhY2ggZXhjaGFuZ2UgaXMgYXZhaWxhYmxlIGZyb20gcmVwdXRhYmxlIHNvdXJjZXMuIA0KDQoNCiMjIyBIeXBvdGhlc2VzDQpUaGVyZSBpcyBhIHNpZ25pZmljYW50IGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIHBlcmZvcm1hbmNlIG9mIE5hc2RhcSBhbmQgdGhlIExTRSBpbmRpY2VzIG92ZXIgdGhlIHNwZWNpZmllZCBwZXJpb2QuIA0KRGlmZmVyZW5jZXMgaW4gbWFya2V0IGNhcGl0YWxpemF0aW9uLCBsaXF1aWRpdHksIGFuZCB0eXBlcyBvZiBpbnN0cnVtZW50cyB0cmFkZWQgaW5mbHVlbmNlIHRoZSBzdGF0aXN0aWNhbCBtZWFzdXJlcyBvYnNlcnZlZA0KVGhlIHRpbWUgem9uZSBkaWZmZXJlbmNlIGFmZmVjdHMgdGhlIHRyYWRpbmcgcGF0dGVybnMgYW5kIGxpcXVpZGl0eSBvZiB0aGUgdHdvIGV4Y2hhbmdlcy4gDQoNCg0KIyMjIERhdGEgUmV0cmlldmFsIGFuZCBQcmVwYXJhdGlvbg0KDQpMb2FkIHJlcXVpcmVkIHBhY2thZ2VzDQpgYGB7cn0NCiMgSW5zdGFsbCBhbmQgbG9hZCByZXF1aXJlZCBwYWNrYWdlcw0KaWYgKCFyZXF1aXJlKCJxdWFudG1vZCIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInF1YW50bW9kIikNCn0NCmlmICghcmVxdWlyZSgiUGVyZm9ybWFuY2VBbmFseXRpY3MiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJQZXJmb3JtYW5jZUFuYWx5dGljcyIpDQp9DQpsaWJyYXJ5KHF1YW50bW9kKQ0KbGlicmFyeShQZXJmb3JtYW5jZUFuYWx5dGljcykNCmBgYA0KDQoNClJldHJpZXZlIEhpc3RvcmljYWwgRGF0YQ0KYGBge3J9DQojIERlZmluZSB0aGUgZGF0ZSByYW5nZQ0Kc3RhcnRfZGF0ZSA8LSBhcy5EYXRlKCIyMDA4LTAxLTAzIikNCmVuZF9kYXRlIDwtIGFzLkRhdGUoIjIwMjMtMDEtMDUiKQ0KDQojIEdldCBoaXN0b3JpY2FsIGRhdGEgZm9yIE5hc2RhcSBDb21wb3NpdGUgSW5kZXgNCmdldFN5bWJvbHMoIl5JWElDIiwgc3JjID0gInlhaG9vIiwgZnJvbSA9IHN0YXJ0X2RhdGUsIHRvID0gZW5kX2RhdGUpDQoNCiMgR2V0IGhpc3RvcmljYWwgZGF0YSBmb3IgRlRTRSAxMDAgSW5kZXgNCmdldFN5bWJvbHMoIl5GVFNFIiwgc3JjID0gInlhaG9vIiwgZnJvbSA9IHN0YXJ0X2RhdGUsIHRvID0gZW5kX2RhdGUpDQpgYGANCg0KDQpEYXRhIENsZWFuaW5nIGFuZCBBbGlnbm1lbnQNCmBgYHtyfQ0KIyBBc3NpZ24gZGF0YSB0byB2YXJpYWJsZXMNCm5hc2RhcV9kYXRhIDwtIGBJWElDYA0KZnRzZV9kYXRhIDwtIGBGVFNFYA0KIyBDaGVjayBmb3IgbWlzc2luZyB2YWx1ZXMNCnN1bShpcy5uYShmdHNlX2RhdGEpKQ0KDQojIEhhbmRsZSBtaXNzaW5nIHZhbHVlcyB1c2luZyBsaW5lYXIgaW50ZXJwb2xhdGlvbg0KZnRzZV9kYXRhIDwtIG5hLmFwcHJveChmdHNlX2RhdGEpDQoNCiMgTWVyZ2UgdGhlIGNsb3NpbmcgcHJpY2VzIGJhc2VkIG9uIGRhdGUNCmNvbWJpbmVkX2RhdGEgPC0gbWVyZ2UoQ2wobmFzZGFxX2RhdGEpLCBDbChmdHNlX2RhdGEpLCBhbGwgPSBGQUxTRSkNCg0KIyBSZW5hbWUgY29sdW1ucyBmb3IgY2xhcml0eQ0KY29sbmFtZXMoY29tYmluZWRfZGF0YSkgPC0gYygiTmFzZGFxX0Nsb3NlIiwgIkZUU0VfQ2xvc2UiKQ0KYGBgDQoNCg0KIyMjIFN0YXRpc3RpY2FsIEFuYWx5c2lzDQoNCg0KIyMjIyBDYWxjdWxhdGUgQmFzaWMgU3RhdGlzdGljcw0KDQoNCkZvciBOYXNkYXENCmBgYHtyfQ0KIyBDYWxjdWxhdGUgYmFzaWMgc3RhdGlzdGljcyBmb3IgTmFzZGFxDQpuYXNkYXFfc3RhdHMgPC0gZGF0YS5mcmFtZSgNCiAgTWVhbiA9IG1lYW4oY29tYmluZWRfZGF0YSROYXNkYXFfQ2xvc2UsIG5hLnJtID0gVFJVRSksDQogIE1lZGlhbiA9IG1lZGlhbihjb21iaW5lZF9kYXRhJE5hc2RhcV9DbG9zZSwgbmEucm0gPSBUUlVFKSwNCiAgU3REZXYgPSBzZChjb21iaW5lZF9kYXRhJE5hc2RhcV9DbG9zZSwgbmEucm0gPSBUUlVFKQ0KKQ0KcHJpbnQobmFzZGFxX3N0YXRzKQ0KYGBgDQoNCg0KRm9yIEZUU0UNCmBgYHtyfQ0KIyBDYWxjdWxhdGUgYmFzaWMgc3RhdGlzdGljcyBmb3IgRlRTRQ0KZnRzZV9zdGF0cyA8LSBkYXRhLmZyYW1lKA0KICBNZWFuID0gbWVhbihjb21iaW5lZF9kYXRhJEZUU0VfQ2xvc2UsIG5hLnJtID0gVFJVRSksDQogIE1lZGlhbiA9IG1lZGlhbihjb21iaW5lZF9kYXRhJEZUU0VfQ2xvc2UsIG5hLnJtID0gVFJVRSksDQogIFN0RGV2ID0gc2QoY29tYmluZWRfZGF0YSRGVFNFX0Nsb3NlLCBuYS5ybSA9IFRSVUUpDQopDQpwcmludChmdHNlX3N0YXRzKQ0KYGBgDQoNCg0KQ2FsY3VsYXRlIENvcnJlbGF0aW9uDQpgYGB7cn0NCiMgQ2FsY3VsYXRlIGNvcnJlbGF0aW9uIGJldHdlZW4gTmFzZGFxIGFuZCBGVFNFIGNsb3NpbmcgcHJpY2VzDQpjb3JyZWxhdGlvbiA8LSBjb3IoY29tYmluZWRfZGF0YSROYXNkYXFfQ2xvc2UsIGNvbWJpbmVkX2RhdGEkRlRTRV9DbG9zZSwgdXNlID0gImNvbXBsZXRlLm9icyIpDQoNCiMgUHJpbnQgdGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50DQpjYXQoIkNvcnJlbGF0aW9uIGJldHdlZW4gTmFzZGFxIGFuZCBGVFNFOiIsIHJvdW5kKGNvcnJlbGF0aW9uLCAyKSwgIlxuIikNCmBgYA0KDQoNCkRpc3BsYXkgUmVzdWx0cw0KYGBge3J9DQoNCiMgQ29tYmluZSBzdGF0aXN0aWNzIGZvciBjb21wYXJpc29uDQpzdGF0c19jb21wYXJpc29uIDwtIHJiaW5kKE5hc2RhcSA9IG5hc2RhcV9zdGF0cywgRlRTRSA9IGZ0c2Vfc3RhdHMpDQoNCiMgU2V0IGNvbHVtbiBuYW1lcw0KY29sbmFtZXMoc3RhdHNfY29tcGFyaXNvbikgPC0gYygiTWVhbiIsICJNZWRpYW4iLCAiU3RhbmRhcmQgRGV2aWF0aW9uIikNCg0KIyBQcmludCB0aGUgc3RhdGlzdGljcw0KcHJpbnQoIkJhc2ljIFN0YXRpc3RpY3MgQ29tcGFyaXNvbjoiKQ0KcHJpbnQocm91bmQoc3RhdHNfY29tcGFyaXNvbiwgMikpDQoNCiMgUHJpbnQgdGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50DQpjYXQoIkNvcnJlbGF0aW9uIGJldHdlZW4gTmFzZGFxIGFuZCBGVFNFOiIsIHJvdW5kKGNvcnJlbGF0aW9uLCAyKSwgIlxuIikNCmBgYA0KDQoNCiMjIyMgQW5hbHlzaXMgb2YgdGhlIGNvcnJlbGF0aW9uDQpUaGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgbWVhc3VyZXMgdGhlIHN0cmVuZ3RoIGFuZCBkaXJlY3Rpb24gb2YgdGhlIHJlbGF0aW9uIGJldHdlZW4gdHdvIHNldHMgb2YgZGF0YSwgb3IgaW4gdGhpcyBjYXNlLCBvZiB0d28gYXNzZXRzLiBUaGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgY2FuIHZhcnkgZnJvbSAtMSB0byAxLCBhbmQgd2l0aCBlYWNoIHZhbHVlIHdlIG9idGFpbiBhIHJlcHJlc2VudGF0aW9uIG9mIGhvdyBpbnRlcmNvbm5lY3RlZCBhcmUgdHdvIGFzc2V0cy4gSW4gdGhlIGNhc2Ugb2YgdGhpcyBleGVyY2lzZSwgd2UgaGF2ZSBvYnRhaW5lZCBhIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IG9mIDAuNjUsIHdoaWNoIGNvbnN0aXR1dGVzIGEgcG9zaXRpdmUgYW5kIHN0cm9uZyBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSB0d28gaW5kZXhlcyBpbiBzdHVkeS4gDQpJbiBicm9hZGVyIHRlcm1zLCB0aGlzIG1lYW5zIHRoYXQgdGhlIHRlbmRlbmNpZXMgb2YgYm90aCBpbmRleGVzIHdpbGwgYmUgc29tZXdoYXQgc2ltaWxhciAgYW5kIHdpbGwgdHJlbmQgaW4gdGhlIHNhbWUgZGlyZWN0aW9uLiANCg0KDQojIyMjIE1hcmtldCBDYXBpdGFsaXphdGlvbg0KDQpNYXJrZXQgY2FwaXRhbGl6YXRpb24gcmVwcmVzZW50cyB0aGUgdG90YWwgdmFsdWUgb2YgYWxsIGxpc3RlZCBjb21wYW5pZXMgb24gYW4gZXhjaGFuZ2UuIEl0J3MgYSBrZXkgaW5kaWNhdG9yIG9mIHRoZSBzaXplIGFuZCBlY29ub21pYyB3ZWlnaHQgb2YgYSBzdG9jayBleGNoYW5nZS4gDQpBbHRob3VnaCB3ZSBkbyBub3QgaGF2ZSBhY2Nlc3MgdG8gZGlyZWN0IGRhdGEsIHdlIHdpbGwgdHJ5IHRvIG1ha2UgdGhlIGNvbXBhcmlzb24gdXNpbmcgdGhlIHRvcCA1IGNvbXBhbmllcyBmcm9tIGVhY2ggZXhjaGFuZ2UuDQoNCg0KSHlwb3RoZXNpczoNCg0KVGhlIE5hc2RhcSBoYXMgYSBsYXJnZXIgbWFya2V0IGNhcGl0YWxpemF0aW9uIGNvbXBhcmVkIHRvIExTRSBkdWUgdG8gaXRzIGNvbmNlbnRyYXRpb24gb2YgbGFyZ2UgdGVjaG5vbG9neSBjb21wYW5pZXMNCg0KDQoNCkltcGxlbWVudGF0aW9uOg0KDQoNCkxvYWQgcGFja2FnZXMNCg0KYGBge3J9DQoNCiMgSW5zdGFsbCBhbmQgbG9hZCByZXF1aXJlZCBwYWNrYWdlcw0KaWYgKCFyZXF1aXJlKCJxdWFudG1vZCIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInF1YW50bW9kIikNCn0NCmxpYnJhcnkocXVhbnRtb2QpDQpsaWJyYXJ5KGRwbHlyKQ0KYGBgDQoNCg0KRGVmaW5lIFRvcCBDb21wYW5pZXMuIFdlIHdpbGwgZXh0cmFjdCB0aGlzIGNvbXBhbmllcyBmcm9tIHRoZSBpbmRleGVzIHdlYnNpdGVzLiANCkxTRSB0b3AgNSBjb21wYW5pZXM6IEF0cmF6ZW5lY2EgUExDLCBTaGVsbCBQTEMsIEhTQkMgSExER1MgUExDLCBVbmlsZXZlciBQTEMsIFJFTFggUExDLiAgDQpOQVNEQVEgdG9wIDUgY29tcGFuaWVzOiBBcHBsZSBJbmMsIE5WSURJQSBjb3JwLCBNaWNyb3NvZnQgQ29ycCwgQW1hem9uLmNvbSBJbmMsIEJyb2FkY29tIEluYy4gDQoNCg0KYGBge3J9DQpuYXNkYXFfc3ltYm9scyA8LSBjKCJBQVBMIiwgIk5WREEiLCAiTVNGVCIsICJBTVpOIiwgIkFWR08iKQ0KbHNlX3N5bWJvbHMgPC0gYygiQVpOLkwiLCAiU0hFTC5MIiwgIkhTQkEuTCIsICJVTFZSLkwiLCAiUkVMLkwiKQ0KDQpgYGANCg0KDQpSZXRyaWV2ZSBNYXJrZXQgQ2FwaXRhbGl6YXRpb24gRGF0YQ0KDQpgYGB7cn0NCg0KIyBJbnN0YWxsIGFuZCBsb2FkIHRpZHlxdWFudA0KaWYgKCFyZXF1aXJlKCJ0aWR5cXVhbnQiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5cXVhbnQiKQ0KfQ0KbGlicmFyeSh0aWR5cXVhbnQpDQpsaWJyYXJ5KGRwbHlyKQ0KYGBgDQoNCg0KR2V0IE1hcmtldCBDYXAgRGF0YQ0KDQpgYGB7cn0NCiMgRnVuY3Rpb24gdG8gZ2V0IG1hcmtldCBjYXAgZGF0YQ0KZ2V0X21hcmtldF9jYXAgPC0gZnVuY3Rpb24oc3ltYm9scykgew0KICAjIFJldHJpZXZlIG1hcmtldCBjYXBpdGFsaXphdGlvbiBkYXRhDQogIGRhdGEgPC0gZ2V0UXVvdGUoc3ltYm9scywgd2hhdCA9IHlhaG9vUUYoIk1hcmtldCBDYXBpdGFsaXphdGlvbiIpKQ0KICANCiAgIyBDb252ZXJ0IHJvd25hbWVzIHRvIGEgY29sdW1uDQogIGRhdGEgPC0gZGF0YSAlPiUNCiAgICByb3duYW1lc190b19jb2x1bW4odmFyID0gInN5bWJvbCIpICU+JQ0KICAgIHJlbmFtZShtYXJrZXRfY2FwID0gYE1hcmtldCBDYXBpdGFsaXphdGlvbmApICU+JQ0KICAgIHNlbGVjdChzeW1ib2wsIG1hcmtldF9jYXApDQogIA0KICByZXR1cm4oZGF0YSkNCn0NCg0KIyBHZXQgbWFya2V0IGNhcCBkYXRhIGZvciBOYXNkYXEgY29tcGFuaWVzDQpuYXNkYXFfbWFya2V0X2NhcCA8LSBnZXRfbWFya2V0X2NhcChuYXNkYXFfc3ltYm9scykNCg0KIyBHZXQgbWFya2V0IGNhcCBkYXRhIGZvciBMU0UgY29tcGFuaWVzDQpsc2VfbWFya2V0X2NhcCA8LSBnZXRfbWFya2V0X2NhcChsc2Vfc3ltYm9scykNCmBgYA0KDQoNClN1bSBNYXJrZXQgQ2Fwcw0KDQpgYGB7cn0NCiMgU3VtIHRoZSBtYXJrZXQgY2Fwcw0KbmFzZGFxX3RvdGFsX21hcmtldF9jYXAgPC0gc3VtKGFzLm51bWVyaWMobmFzZGFxX21hcmtldF9jYXAkbWFya2V0X2NhcCksIG5hLnJtID0gVFJVRSkNCmxzZV90b3RhbF9tYXJrZXRfY2FwIDwtIHN1bShhcy5udW1lcmljKGxzZV9tYXJrZXRfY2FwJG1hcmtldF9jYXApLCBuYS5ybSA9IFRSVUUpDQoNCiMgQ29udmVydCB0byB0cmlsbGlvbnMgZm9yIHJlYWRhYmlsaXR5DQpuYXNkYXFfdG90YWxfbWFya2V0X2NhcF90cmlsbGlvbiA8LSBuYXNkYXFfdG90YWxfbWFya2V0X2NhcCAvIDFlMTINCmxzZV90b3RhbF9tYXJrZXRfY2FwX3RyaWxsaW9uIDwtIGxzZV90b3RhbF9tYXJrZXRfY2FwIC8gMWUxMg0KDQojIFByaW50IHRoZSByZXN1bHRzDQpjYXQoIk5hc2RhcSBUb3AgQ29tcGFuaWVzIFRvdGFsIE1hcmtldCBDYXA6ICQiLCByb3VuZChuYXNkYXFfdG90YWxfbWFya2V0X2NhcF90cmlsbGlvbiwgMiksICIgdHJpbGxpb25cbiIpDQpjYXQoIkxTRSBUb3AgQ29tcGFuaWVzIFRvdGFsIE1hcmtldCBDYXA6ICQiLCByb3VuZChsc2VfdG90YWxfbWFya2V0X2NhcF90cmlsbGlvbiwgMiksICIgdHJpbGxpb25cbiIpDQpgYGANCg0KDQpIYW5kbGUgRXhjaGFuZ2UgUmF0ZXMNCg0KYGBge3J9DQojIEdldCBjdXJyZW50IEdCUCB0byBVU0QgZXhjaGFuZ2UgcmF0ZQ0KZ2V0U3ltYm9scygiR0JQVVNEPVgiLCBzcmMgPSAieWFob28iLCBmcm9tID0gU3lzLkRhdGUoKSAtIDEsIHRvID0gU3lzLkRhdGUoKSkNCmV4Y2hhbmdlX3JhdGUgPC0gYXMubnVtZXJpYyhDbChgR0JQVVNEPVhgKVsxXSkNCg0KIyBDb252ZXJ0IExTRSBtYXJrZXQgY2FwcyB0byBVU0QNCmxzZV9tYXJrZXRfY2FwJG1hcmtldF9jYXBfdXNkIDwtIGFzLm51bWVyaWMobHNlX21hcmtldF9jYXAkbWFya2V0X2NhcCkgKiBleGNoYW5nZV9yYXRlDQoNCiMgU3VtIHRoZSBjb252ZXJ0ZWQgbWFya2V0IGNhcHMNCmxzZV90b3RhbF9tYXJrZXRfY2FwX3VzZCA8LSBzdW0obHNlX21hcmtldF9jYXAkbWFya2V0X2NhcF91c2QsIG5hLnJtID0gVFJVRSkNCmxzZV90b3RhbF9tYXJrZXRfY2FwX3RyaWxsaW9uX3VzZCA8LSBsc2VfdG90YWxfbWFya2V0X2NhcF91c2QgLyAxZTEyDQoNCiMgVXBkYXRlIHRoZSBwcmludCBzdGF0ZW1lbnQNCmNhdCgiTFNFIFRvcCBDb21wYW5pZXMgVG90YWwgTWFya2V0IENhcDogJCIsIHJvdW5kKGxzZV90b3RhbF9tYXJrZXRfY2FwX3RyaWxsaW9uX3VzZCwgMiksICIgdHJpbGxpb24gKGNvbnZlcnRlZCB0byBVU0QpXG4iKQ0KYGBgDQoNCldoZW4gdHJ5aW5nIHRvIHBlcmZvcm0gb3V0IGFuYWx5c2lzIG9mIHRoZSBtYXJrZXQgY2FwaXRhbGl6YXRpb24gd2UgaGF2ZSBlbmNvdW50ZXIgYSBwcm9ibGVtIHR3byByZXRyaWV2ZSBkYXRhIGZyb20gUiwgc28gd2UgY2Fubm90IHBlcmZvcm0gdGhlIG51bWVyaWNhbCBkZW1vbnN0cmF0aW9uLiBIb3dldmVyLCB3ZSB3aWxsIHN0YXRlIHRoYXQgYXMgZmFyIGFzIHRoZSBpbmZvcm1hdGlvbiB3ZSBoYXZlIGJlZW4gYWJsZSB0byBnYXRoZXIsIHRoZSBMU0VHIGhhcyBhIGhpZ2hlciBtYXJrZXQgY2FwaXRhbGl6YXRpb24gdGhhbiBOYXNkYXEsIEluYy4gVGhpcyBtZWFucyB0aGF0IHRoZSBMU0UgaGFzIGEgaGlnaGVyIGNvcnBvcmF0ZSBtYXJrZXQgY2FwaXRhbGl6YXRpb24uIEhvd2V2ZXIsIGlmIHdlIHRha2UgaW50byBhY2NvdW50IHRoZSBhZ2dyZWdhdGUgbWFya2V0IGNhcGl0YWxpemF0aW9uLCB0aGUgdG90YWwgbWFya2V0IHZhbHVlIG9mIHRoZSBhc3NldHMgdHJhZGVkIGluIE5hc2RhcSBncmVhdGx5IHN1cnBhc3MgdGhlIHZhbHVlIG9mIHRob3NlIHRyYWRlZCBpbiB0aGUgTFNFLiANCg0KQSBoaWdoZXIgbWFya2V0IGNhcGl0YWxpemF0aW9uIG1heSBpbmRpY2F0ZSBoaWdoZXIgZWNvbm9taWMgaW5mbHVlbmNlLCBsaXF1aWRpdHkgYW5kIG92ZXJhbGwgaW50ZXJuYXRpb25hbCBhdHRyYWN0aXZlbmVzcy4gSG93ZXZlciwgaW4gdGhpcyBjYXNlIE5hc2RhcSdzIHRob3JvdWdoIGZvY3VzIG9uIHRlY2hub2xvZ2ljYWwgY29tcGFuaWVzIG5hcnJvd3MgaXRzIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBlY29ub215IHdoaWxlIHRoZSBMU0UgaGFzIGEgYnJvYWRlciByYW5nZSBvZiBhc3NldHMuDQoNCg0KIyMjIyBMaXF1aWRpdHkuIA0KDQpJdCByZWZsZWN0cyBob3cgZWFzaWx5IGNhbiBhc3NldHMgYmUgYm91Z2h0IGFuZCBzb2xkIGluIHRoZSBtYXJrZXQuIEhpZ2hlciB0cmFkaW5nIHZvbHVtZXMgaW5kaWNhdGUgaGlnaGVyIGxpcXVpZGl0eS4gDQoNCkh5cG90aGVzaXMuIA0KDQpUaGUgTmFzZGFxIGhhcyBhIGhpZ2hlciBhdmVyYWdlIHRyYWRpbmcgdm9sdW1lcyBjb21wYXJlZCB0byBMU0UgZHVlIHRvIGl0cyBsYXJnZXIgc2l6ZSBhbmQgZ2xvYmFsIGludmVzdG9yIGJhc2UNCg0KV2Ugd2lsbCByZXRyaWV2ZSB0aGUgZGFpbHkgdHJhZGluZyB2b2x1bWUgZGF0YSBmcm9tIHRoZSBpbmRpY2VzIGFuZCBjYWxjdWxhdGUgdGhlIGF2ZXJhZ2UgZGFpbHkgdm9sdW1lIG92ZXIgYW4gc3BlY2lmaWVkIHBlcmlvZC4gDQoNCkZvciB0aGUgVm9sdW1lIERhdGEgd2Ugd2lsbCBiZSB1c2luZyB0aGVpciB0b3AgY29tcGFuaWVzIGFzIGEgcHJveHkuIA0KDQpgYGB7cn0NCm5hc2RhcV92b2x1bWVzIDwtIGxpc3QoKQ0KZm9yIChzeW1ib2wgaW4gbmFzZGFxX3N5bWJvbHMpIHsNCiAgZGF0YSA8LSBnZXRTeW1ib2xzKHN5bWJvbCwgc3JjID0gInlhaG9vIiwgZnJvbSA9IHN0YXJ0X2RhdGUsIHRvID0gZW5kX2RhdGUsIGF1dG8uYXNzaWduID0gRkFMU0UpDQogIG5hc2RhcV92b2x1bWVzW1tzeW1ib2xdXSA8LSBDbChkYXRhKQ0KfQ0KDQojIEdldCB2b2x1bWUgZGF0YSBmb3IgdG9wIExTRSBjb21wYW5pZXMNCmxzZV92b2x1bWVzIDwtIGxpc3QoKQ0KZm9yIChzeW1ib2wgaW4gbHNlX3N5bWJvbHMpIHsNCiAgZGF0YSA8LSBnZXRTeW1ib2xzKHN5bWJvbCwgc3JjID0gInlhaG9vIiwgZnJvbSA9IHN0YXJ0X2RhdGUsIHRvID0gZW5kX2RhdGUsIGF1dG8uYXNzaWduID0gRkFMU0UpDQogIHZvbHVtZV9kYXRhIDwtIFZvKGRhdGEpDQogIA0KICAjIEhhbmRsZSBtaXNzaW5nIHZhbHVlcw0KICBpZiAoYW55KGlzLm5hKHZvbHVtZV9kYXRhKSkpIHsNCiAgICBjYXQoIkhhbmRsaW5nIG1pc3NpbmcgdmFsdWVzIGZvciIsIHN5bWJvbCwgIlxuIikNCiAgICB2b2x1bWVfZGF0YSA8LSBuYS5hcHByb3godm9sdW1lX2RhdGEpDQogIH0NCiAgDQogICMgU3RvcmUgY2xlYW5lZCB2b2x1bWUgZGF0YQ0KICBsc2Vfdm9sdW1lc1tbc3ltYm9sXV0gPC0gdm9sdW1lX2RhdGENCn0NCg0KIyBNZXJnZSBhbmQgYWxpZ24gTFNFIHZvbHVtZXMNCmxzZV92b2x1bWVfZGF0YSA8LSBkby5jYWxsKG1lcmdlLCBsc2Vfdm9sdW1lcykNCg0KIyBSZW1vdmUgYW55IHJlbWFpbmluZyBtaXNzaW5nIHZhbHVlcw0KbHNlX3ZvbHVtZV9kYXRhIDwtIG5hLm9taXQobHNlX3ZvbHVtZV9kYXRhKQ0KYGBgDQoNCg0KV2UgY2FsY3VsYXRlIEF2ZXJhZ2UgVm9sdW1lDQoNCmBgYHtyfQ0KIyBDYWxjdWxhdGUgYXZlcmFnZSB2b2x1bWUgZm9yIE5hc2RhcSBjb21wYW5pZXMNCm5hc2RhcV9hdmdfdm9sdW1lcyA8LSBzYXBwbHkobmFzZGFxX3N5bWJvbHMsIGZ1bmN0aW9uKHN5bWJvbCkgew0KICBkYXRhIDwtIGdldFN5bWJvbHMoc3ltYm9sLCBzcmMgPSAieWFob28iLCBmcm9tID0gc3RhcnRfZGF0ZSwgdG8gPSBlbmRfZGF0ZSwgYXV0by5hc3NpZ24gPSBGQUxTRSkNCiAgbWVhbihWbyhkYXRhKSwgbmEucm0gPSBUUlVFKQ0KfSkNCg0KIyBDYWxjdWxhdGUgYXZlcmFnZSB2b2x1bWUgZm9yIExTRSBjb21wYW5pZXMNCmxzZV9hdmdfdm9sdW1lcyA8LSBzYXBwbHkobHNlX3ZvbHVtZXMsIGZ1bmN0aW9uKHZvbHVtZV9kYXRhKSB7DQogIG1lYW4odm9sdW1lX2RhdGEsIG5hLnJtID0gVFJVRSkNCn0pDQoNCiMgQ2FsY3VsYXRlIHRoZSBvdmVyYWxsIGF2ZXJhZ2Ugdm9sdW1lDQpsc2VfYXZnX3ZvbHVtZSA8LSBtZWFuKGxzZV9hdmdfdm9sdW1lcywgbmEucm0gPSBUUlVFKQ0KDQojIEF2ZXJhZ2Ugdm9sdW1lIGFjcm9zcyB0b3AgY29tcGFuaWVzDQpuYXNkYXFfYXZnX3ZvbHVtZSA8LSBtZWFuKG5hc2RhcV9hdmdfdm9sdW1lcywgbmEucm0gPSBUUlVFKQ0KbHNlX2F2Z192b2x1bWUgPC0gbWVhbihsc2VfYXZnX3ZvbHVtZXMsIG5hLnJtID0gVFJVRSkNCg0KIyBQcmludCByZXN1bHRzDQpjYXQoIkF2ZXJhZ2UgRGFpbHkgVHJhZGluZyBWb2x1bWUgZm9yIE5hc2RhcSBUb3AgQ29tcGFuaWVzOiIsIGZvcm1hdEMobmFzZGFxX2F2Z192b2x1bWUsIGZvcm1hdCA9ICJmIiwgYmlnLm1hcmsgPSAiLCIsIGRpZ2l0cyA9IDApLCAiXG4iKQ0KY2F0KCJBdmVyYWdlIERhaWx5IFRyYWRpbmcgVm9sdW1lIGZvciBMU0UgVG9wIENvbXBhbmllczoiLCBmb3JtYXRDKGxzZV9hdmdfdm9sdW1lLCBmb3JtYXQgPSAiZiIsIGJpZy5tYXJrID0gIiwiLCBkaWdpdHMgPSAwKSwgInNoYXJlc1xuIikNCmBgYA0KDQoNCiMjIyMgQW5hbHlzaXMgb2YgcmVzdWx0cw0KDQpXZSBlbmNvdW50ZXIgc29tZSBsaW1pdGF0aW9uIHJlZ2FyZGluZyB0aGlzIGNvbXBhcmlzb24sIGFzIHRoZSB2b2x1bWUgdW5pdHMgbWF5IGRpZmZlciBiZXR3ZWVuIGV4Y2hhbmdlcyBhbmQgdGhlIHZvbHVtZSBkYXRhIGZvciBpbmRpY2VzIG1heSBub3QgYmUgZGlyZWN0bHkgY29tcGFyYWJsZS4gSG93ZXZlciwgaXQgYmVjb21lcyBub3RpY2VhYmxlIHRoYXQgdGhlIGF2ZXJhZ2UgdHJhZGluZyB2b2x1bWUgZm9yIE5hc2RhcSdzIFRvcCBjb21wYW5pZXMgaXMgc2lnbmlmaWNhbnRseSBoaWdoZXIgdGhhbiB0aGF0IG9mIExTRS4gVGhpcyBpbmRpY2F0ZXMgYSBtb3JlIGFjdGl2ZSBtYXJrZXQgYW5kIGlzIHVuZGVyc3RhbmRhYmx5IGV4cGxhaW5lZCBieSB0aGUgY29uc3RhbnRseSBjaGFuZ2luZyBlbnZpcm9ubWVudCBvZiB0aGUgdGVjaG5vbG9naWNhbCBjb21wYW5pZXMgdHJhZGVkIGluIHRoZSBOYXNkYXEuDQoNCg0KDQojIyMgTnVtYmVyIG9mIElQT3MNCg0KVGhlIG51bWJlciBvZiBJbml0aWFsIFB1YmxpYyBPZmZlcmluZ3MgcmVmbGVjdHMgdGhlIGF0dHJhY3RpdmVuZXNzIG9mIGFuIGV4Y2hhbmdlIGZvciBjb21wYW5pZXMgbG9va2luZyB0byByYWlzZSBjYXBpdGFsLiBEdWUgdG8gbGFjayBvZiBwb3NzaWJpbGl0eSB0byByZXRyaWV2ZSBzdWNoIGRhdGEsIHdlIHdpbGwganVzdCBtZW50aW9uIHRoYXQgcmVjZW50IGRhdGEgc2lnbmFscyBhIGdyZWF0ZXIgbnVtYmVyIG9mIElQT3MgaW4gTmFzZGFxIGNvbXBhcmVkIHRvIHRob3NlIG9mIExTRSwgd2hpY2ggaW5kaWNhdGVzIGEgbXVjaCBtb3JlIGF0dHJhY3RpdmUgc3RvY2sgZXhjaGFuZ2UgYm90aCBmb3IgaW52ZXN0b3JzIGFuZCBmb3IgY29tcGFuaWVzIHdobyBzZWVrIHRvIHJhaXNlIGNhcGl0YWwsIGFuZCBnaXZlcyBhIGdyZWF0IGV4YW1wbGUgb2YgaG93IHJlbWFya2FibGUgYXJlIHNlY3RvciB0cmVuZHMgaW4gdGhlIG1hbmlmZXN0YXRpb24gb2YgSVBPcy4NCg0KDQojIyMgTSZBIEZyZXF1ZW5jeQ0KDQpUaGUgZnJlcXVlbmN5IGluIG1lcmdlcnMgYW5kIGFjcXVpc2l0aW9ucyBtYXkgaW5kaWNhdGUgdGhlIGR5bmFtaXNtIG9mIHRoZSBtYXJrZXQuIA0KDQpUaGlzIGRhdGEgaXMgeWV0IGFnYWluIG5vdCBhdmFpbGFibGUgZGlyZWN0bHkgZnJvbSBSLCBidXQgd2UgbWF5IGZpbmQgaXQgZnJvbSBvdGhlciBzb3VyY2VzLiANCg0KTmFzZGFxOiBhY3RpdmUgTSZBIGVudmlyb25tZW50IGluIHRlY2hub2xvZ3kgYW5kIGJpb3RlY2ggc2VjdG9ycy4NCg0KTFNFOiByZWd1bGFyIE0mQSBhY3Rpdml0eSBhY3Jvc3Mgc2VjdG9ycyBsaWtlIGZpbmFuY2UsIGVuZXJneSBhbmQgbWluaW5nLg0KDQoNCiMjIyBRdWFsaXR5IG9mIGluZm9ybWF0aW9uDQoNCk5hc2RhcToNClJlZ3VsYXRlZCBieSB0aGUgVS5TLiBTZWN1cml0aWVzIGFuZCBFeGNoYW5nZSBDb21taXNzaW9uIChTRUMpLg0KU3RyaWN0IHJlcG9ydGluZyBhbmQgZGlzY2xvc3VyZSByZXF1aXJlbWVudHMuDQpVc2VzIG1hcmtldCBtYWtlcnMgYW5kIGVsZWN0cm9uaWMgY29tbXVuaWNhdGlvbiBuZXR3b3JrcyAoRUNOcykgYXMgZ2F0ZWtlZXBlcnMuDQoNCkxTRToNClJlZ3VsYXRlZCBieSB0aGUgRmluYW5jaWFsIENvbmR1Y3QgQXV0aG9yaXR5IChGQ0EpIGluIHRoZSBVSy4NCkVtcGhhc2lzIG9uIHRyYW5zcGFyZW5jeSBhbmQgbWFya2V0IGludGVncml0eS4NClNwb25zb3JzIGFuZCBub21pbmF0ZWQgYWR2aXNvcnMgKE5vbWFkcykgYWN0IGFzIGdhdGVrZWVwZXJzIGZvciBBSU0uDQoNCg0KIyMjIFRyYWRpbmcgQ29zdHMNCg0KTmFzZGFxOiBUcmFkaW5nIGNvc3RzIGluY2x1ZGUgYnJva2VyYWdlIGZlZXMsIFNFQyBmZWVzLCBhbmQgcG90ZW50aWFsIGV4Y2hhbmdlIGZlZXMuDQpHZW5lcmFsbHkgbG93IGR1ZSB0byBoaWdoIGNvbXBldGl0aW9uIGFtb25nIGJyb2tlcnMuDQoNCkxTRTogVHJhZGluZyBjb3N0cyBtYXkgaW5jbHVkZSBicm9rZXJhZ2UgZmVlcywgc3RhbXAgZHV0eSAoMC41JSBvbiBwdXJjaGFzZXMpLCBhbmQgb3RoZXIgdHJhbnNhY3Rpb24gY29zdHMuDQoNCg0KIyMjIFRyYWRpbmcgSG91cnMgKHRpbWUgem9uZSBkaWZmZXJlbmNlKQ0KDQpXZSBtYXkgcXVhbnRpZnkgdGhlIHRyYWRpbmcgaG91cnMgYW5kIGNhbGN1bGF0ZSB0aGUgb3ZlcmxhcA0KYGBge3J9DQojIE5hc2RhcSB0cmFkaW5nIGhvdXJzOiA5OjMwIEFNIHRvIDQ6MDAgUE0gRVNUDQojIExTRSB0cmFkaW5nIGhvdXJzOiA4OjAwIEFNIHRvIDQ6MzAgUE0gR01UDQoNCiMgQ29udmVydCB0cmFkaW5nIGhvdXJzIHRvIFVUQw0KbmFzZGFxX29wZW5fdXRjIDwtIGFzLlBPU0lYY3QoIjE0OjMwIiwgZm9ybWF0ID0gIiVIOiVNIiwgdHogPSAiVVRDIikgICMgOTozMCBBTSBFU1QgaXMgMTQ6MzAgVVRDDQpuYXNkYXFfY2xvc2VfdXRjIDwtIGFzLlBPU0lYY3QoIjIxOjAwIiwgZm9ybWF0ID0gIiVIOiVNIiwgdHogPSAiVVRDIikgICMgNDowMCBQTSBFU1QgaXMgMjE6MDAgVVRDDQoNCmxzZV9vcGVuX3V0YyA8LSBhcy5QT1NJWGN0KCIwODowMCIsIGZvcm1hdCA9ICIlSDolTSIsIHR6ID0gIlVUQyIpDQpsc2VfY2xvc2VfdXRjIDwtIGFzLlBPU0lYY3QoIjE2OjMwIiwgZm9ybWF0ID0gIiVIOiVNIiwgdHogPSAiVVRDIikNCg0KIyBDYWxjdWxhdGUgb3ZlcmxhcA0Kb3ZlcmxhcF9zdGFydCA8LSBtYXgobmFzZGFxX29wZW5fdXRjLCBsc2Vfb3Blbl91dGMpDQpvdmVybGFwX2VuZCA8LSBtaW4obmFzZGFxX2Nsb3NlX3V0YywgbHNlX2Nsb3NlX3V0YykNCg0KaWYgKG92ZXJsYXBfc3RhcnQgPCBvdmVybGFwX2VuZCkgew0KICBvdmVybGFwX2hvdXJzIDwtIGFzLm51bWVyaWMoZGlmZnRpbWUob3ZlcmxhcF9lbmQsIG92ZXJsYXBfc3RhcnQsIHVuaXRzID0gImhvdXJzIikpDQp9IGVsc2Ugew0KICBvdmVybGFwX2hvdXJzIDwtIDANCn0NCg0KIyBQcmludCByZXN1bHRzDQpjYXQoIk92ZXJsYXAgaW4gVHJhZGluZyBIb3VyczogIiwgb3ZlcmxhcF9ob3VycywgIiBob3Vyc1xuIikNCmBgYA0KDQoNCkhlcmUgd2UgaGF2ZSBjYWxjdWxhdGVkIHRoZSBvdmVybGFwaW5nIGluIHRyYWRpbmcgaG91cnMuIFRoZSBsb3cgb3ZlcmxhcGluZyB0cmFkaW5nIGhvdXJzIGNhbiBoYXZlIGh1Z2UgaW1wYWN0cyBvbiB0aGUgdHJhZGluZyBzdHJhdGVnaWVzLCBhcyB0aGUgaW5mb3JtYXRpb24gZnJvbSBvbmUgbWFya2V0IHdpbGwgYWxyZWFkeSBiZSBpbmNvcnBvcmF0ZWQgYXQgdGhlIG9wZW5pbmcgb2YgdGhlIG90aGVyLiBUaGlzIGNhdXNlcyBzaGlmdHMgaW4gdm9sYXRpbGl0eSBhbmQgaW52ZXN0b3IncyBiZWhhdmlvdXIsIGJ1dCBjYW4gYWxzbyBiZSB1c2VkIGFzIGFuIHN0cmF0ZWdpYyBhZHZhbnRhZ2UgZm9yIGRpdmVyc2lmeWluZyB0aGVpciBpbnZlc3RtZW50cy4gDQoNCg0KDQojIyBMMyBJbnN0cnVtZW504oCZcyBvdmVydmlldyBhbmQgdmFsdWF0aW9uDQoNCg0KIyMjIEwzLjEgQ29tcGFyZSB0aGUgMTMtd2VlayBUcmVhc3VyeSBiaWxsIHJhdGUgKHdoaWNoIGlzIGEgcHJveHkgZm9yIHNob3J0LXRlcm0gaW50ZXJlc3QgcmF0ZXMpIGF0IHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtIHRvIHRoZSByYXRlIHRoYXQgZXhpc3RlZCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzY2hvb2wgdGVybS4gKG5vdGU6IDMtTW9udGggVHJlYXN1cnkgQmlsbCBTZWNvbmRhcnkgTWFya2V0IFJhdGUsIERpc2NvdW50IEJhc2lzIChUQjNNUykpDQoNCg0KbG9hZCBwYWNrYWdlcw0KDQpgYGB7cn0NCmxpYnJhcnkocXVhbnRtb2QpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmBgYA0KDQoNCmRlZmluZSBkYXRlcw0KDQpgYGB7cn0NCiMgRGVmaW5lIEJlZ2lubmluZyBvZiBUZXJtIChCb1QpIGFuZCBFbmQgb2YgVGVybSAoRW9UKSBkYXRlcw0KQm9UX2RhdGUgPC0gYXMuRGF0ZSgiMjAyNC0wNS0wMSIpDQpFb1RfZGF0ZSA8LSBhcy5EYXRlKCIyMDI0LTA5LTMwIikNCmBgYA0KDQoNClJldHJpZXZlIGRhdGENCg0KYGBge3J9DQojIFJldHJpZXZlIFRCM01TIGRhdGEgZnJvbSBGUkVEDQpnZXRTeW1ib2xzKCJUQjNNUyIsIHNyYyA9ICJGUkVEIikNCg0KIyBWaWV3IHRoZSBmaXJzdCBmZXcgcm93cyBvZiBkYXRhDQpoZWFkKFRCM01TKQ0KYGBgDQoNCg0KRnVuY3Rpb24gdG8gYWRqdXN0IHRvIG5vbi10cmFkaW5nIGRheXMNCg0KYGBge3J9DQojIEZ1bmN0aW9uIHRvIGdldCB0aGUgcmF0ZSBvbiBhIHNwZWNpZmljIGRhdGUsIGFkanVzdGluZyBmb3Igbm9uLXRyYWRpbmcgZGF5cw0KZ2V0X3JhdGVfb25fZGF0ZSA8LSBmdW5jdGlvbihkYXRhLCBkYXRlLCB1c2VfbmV4dCA9IEZBTFNFKSB7DQogICMgQ29udmVydCBpbmRleCB0byBEYXRlIGZvcm1hdCBpZiBub3QgYWxyZWFkeQ0KICBpbmRleChkYXRhKSA8LSBhcy5EYXRlKGluZGV4KGRhdGEpKQ0KICANCiAgaWYgKHVzZV9uZXh0KSB7DQogICAgIyBHZXQgdGhlIG5leHQgYXZhaWxhYmxlIGRhdGUgYWZ0ZXIgdGhlIHNwZWNpZmllZCBkYXRlDQogICAgYXZhaWxhYmxlX2RhdGVzIDwtIGluZGV4KGRhdGEpW2luZGV4KGRhdGEpID49IGRhdGUgJiAhaXMubmEoZGF0YVtpbmRleChkYXRhKV0pXQ0KICAgIGlmKGxlbmd0aChhdmFpbGFibGVfZGF0ZXMpID09IDApIHsNCiAgICAgIHdhcm5pbmcocGFzdGUoIk5vIGRhdGEgYXZhaWxhYmxlIGFmdGVyIiwgZGF0ZSkpDQogICAgICByZXR1cm4obGlzdChSYXRlID0gTkEsIERhdGUgPSBOQSkpDQogICAgfQ0KICAgIGRhdGVfdXNlZCA8LSBtaW4oYXZhaWxhYmxlX2RhdGVzKQ0KICB9IGVsc2Ugew0KICAgICMgR2V0IHRoZSBsYXN0IGF2YWlsYWJsZSBkYXRlIGJlZm9yZSBvciBvbiB0aGUgc3BlY2lmaWVkIGRhdGUNCiAgICBhdmFpbGFibGVfZGF0ZXMgPC0gaW5kZXgoZGF0YSlbaW5kZXgoZGF0YSkgPD0gZGF0ZSAmICFpcy5uYShkYXRhW2luZGV4KGRhdGEpXSldDQogICAgaWYgKGxlbmd0aChhdmFpbGFibGVfZGF0ZXMpID09IDApIHsNCiAgICAgIHdhcm5pbmcocGFzdGUoIk5vIGRhdGEgYXZhaWxhYmxlIGJlZm9yZSIsIGRhdGUpKQ0KICAgICAgcmV0dXJuKGxpc3QoUmF0ZSA9IE5BLCBEYXRlID0gTkEpKQ0KICAgIH0NCiAgICBkYXRlX3VzZWQgPC0gbWF4KGF2YWlsYWJsZV9kYXRlcykNCiAgfQ0KICANCiAgIyBHZXQgdGhlIHJhdGUNCiAgcmF0ZSA8LSBhcy5udW1lcmljKGRhdGFbZGF0ZV91c2VkXSkNCiAgDQogIHJldHVybihsaXN0KA0KICAgIFJhdGUgPSByYXRlLA0KICAgIERhdGUgPSBhcy5EYXRlKGRhdGVfdXNlZCkNCiAgKSkNCn0NCmBgYA0KDQoNClJldHJpZXZlIFJhdGVzIG9uIEJvVF9kYXRlIGFuZCBFb1RfZGF0ZQ0KDQpgYGB7cn0NCiMgR2V0IHJhdGUgb24gQm9UX2RhdGUNCkJvVF9yYXRlIDwtIGdldF9yYXRlX29uX2RhdGUoVEIzTVMsIEJvVF9kYXRlLCB1c2VfbmV4dCA9IFRSVUUpDQoNCiMgR2V0IHJhdGUgb24gRW9UX2RhdGUNCkVvVF9yYXRlIDwtIGdldF9yYXRlX29uX2RhdGUoVEIzTVMsIEVvVF9kYXRlLCB1c2VfbmV4dCA9IEZBTFNFKQ0KYGBgDQoNCg0KQ3JlYXRlIERhdGEgRnJhbWUgdG8gZGlzcGxheSByZXN1bHRzDQoNCmBgYHtyfQ0KIyBDcmVhdGUgZGF0YSBmcmFtZSB3aXRoIHRoZSByZXN1bHRzDQpyZXN1bHRzIDwtIGRhdGEuZnJhbWUoDQogIERhdGUgPSBjKEJvVF9yYXRlJERhdGUsIEVvVF9yYXRlJERhdGUpLA0KICBSYXRlID0gYyhCb1RfcmF0ZSRSYXRlLCBFb1RfcmF0ZSRSYXRlKSwNCiAgUGVyaW9kID0gYygiQmVnaW5uaW5nIG9mIFRlcm0iLCAiRW5kIG9mIFRlcm0iKQ0KKQ0KDQojIERpc3BsYXkgdGhlIHJlc3VsdHMNCnByaW50KHJlc3VsdHMpDQpgYGANCg0KDQpDb21wYXJlIHRoZSBSYXRlcw0KDQpgYGB7cn0NCnJhdGVfY2hhbmdlPC0gRW9UX3JhdGUkUmF0ZSAtIEJvVF9yYXRlJFJhdGUNCnByaW50KHBhc3RlKCJUaGUgMTMtd2VlayBUcmVhc3VyeSBiaWxsIHJhdGUgY2hhbmdlZCBieSIsIHJvdW5kKHJhdGVfY2hhbmdlLCAyKSwgInBlcmNlbnRhZ2UgcG9pbnRzIG92ZXIgdGhlIHRlcm0uIikpDQoNCmBgYA0KDQoNCg0KIyMjIyBBbmFseXNpcyBvZiByZXN1bHRzDQoNCkluIHRoaXMgZXhlcmNpc2Ugd2UgaGF2ZSBwZXJmb3JtZWQgYSBjb21wYXJpc29uIG9mIHRoZSBzaG9ydC10ZXJtIGludGVyZXN0IHJhdGUgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgc2Nob29sIGFuZCBhdCB0aGUgZW5kLiBXaGVuIHdlIGNhbGN1bGF0ZSB0aGUgY2hhbmdlLCB3ZSBmaW5kIHRoYXQgdGhlcmUgaGFzIGJlZW4gYSBkZXByZWNpYXRpb24gb2YgdGhlIHJhdGVzLCB3aXRoIGEgY2hhbmdlIG9mIC0wLjUzIHBvaW50cy4NCkEgZmFsbCBpbiB0aGUgVC1iaWxsIHJhdGUgbWF5IGJlIGNhdXNlZCBieSBzZXZlcmFsIGZhY3RvcnMsIHN1Y2ggYXMgYSBmYWxsIGluIGludGVyZXN0IHJhdGVzLCBkZWNlbGVyYXRpb24gb2YgZWNvbm9taWMgZ3Jvd3RoIG9yIGV2ZW4gcmVjZXNzaW9ucyBvciBlY29ub21pYyB1bmNlcnRhaW50eSB3aGljaCBsZWFkcyB0byBoaWdoZXIgZGVtYW5kIGluIFQtYmlsbHMuIEFub3RoZXIgaW50ZXJlc3RpbmcgZmFjdG9yIG1heSBiZSBhIGdlbmVyYWwgZGVzaXJlIGZvciBsaXF1aWQgaW5zdHJ1bWVudHMgdG8gc3RvcmUgdmFsdWUgaW4gdGhlIHNob3J0IHRlcm0gd2l0aCBtaW5pbWFsIHJpc2suIA0KQW55IG9mIHRoZXNlIHJlYXNvbnMgY2FuIGxlYWQgdG8gYSBkZWNyZWFzZSBpbiB0aGUgVC1iaWxsIHJhdGVzLCBhbmQgd2UgYXJlIGluY2xpbmVkIHRvIGJlbGlldmUgdGhhdCBpbiB0aGlzIGNhc2UgaXQgaGFzIGJlZW4gY2F1c2VkIGJ5IHRoZSBmYWxsIG9mIGludGVyZXN0IHJhdGVzIGFuZCBhIGZvcmVzZWVhYmxlIGZ1cnRoZXIgY3V0IGluIHJhdGVzIGJ5IHRoZSBGRUQuIA0KDQoNCg0KIyMjIEwzLjIgV2h5IGludGVyZXN0IHJhdGVzIGNoYW5nZSBvdmVyIHRpbWUuDQoNCkludGVyZXN0IHJhdGVzIGZsdWN0dWF0aW9uIGlzIGEgYnJvYWQgcGhlbm9tZW5vbiBpbmZsdWVuY2VkIGJ5IGEgcmVhbGx5IHdpZGUgcmFuZ2Ugb2YgZmFjdG9ycy4gSG93ZXZlciwgdGhlIG1vc3QgaW1wb3J0YW50IGFzcGVjdHMgY2FuIHN1bW1hcml6ZWQgaW4gc3VwcGx5LCBkZW1hbmQgYW5kIGdvdmVybm1lbnQgcG9saWN5LiANCkhpZ2ggZGVtYW5kIChvciBsb3cgc3VwcGx5KSBvZiBjcmVkaXQgd2lsbCBsZWFkIHRvIGhpZ2hlciBpbnRlcmVzdCByYXRlcyBpbiBtb25leSBsZW5kaW5nIGZyb20gYmFua3MgYW5kIG90aGVyIGluc3RpdHV0aW9ucywgbWFraW5nIGl0IG1vcmUgZXhwZW5zaXZlIHRvIGJvcnJvdy4gT3Bwb3NpdGVseSwgYSBsb3cgZGVtYW5kIChvciBoaWdoIHN1cHBseSkgd2lsbCBsZWFkIHRvIGEgZGVjcmVhc2UgaW4gaW50ZXJlc3QgcmF0ZXMsIG1ha2luZyBib3Jyb3dpbmcgbW9uZXkgY2hlYXBlci4gDQpUaGUgZ292ZXJubWVudCAoY29yIGNlbnRyYWwgYmFuaykgYWxzbyBoYXMgYW4gaW5mbHVlbmNlIGluIHRoZSBmbHVjdHVhdGlvbnMgYXMgaXQgc2V0cyB0aGUgdGFyZ2V0IGludGVyZXN0IHJhdGVzIGF0IHdoaWNoIHRoZW4gYmFua3MgbG9hbiBiZXR3ZWVuIGVhY2ggb3RoZXIuIFRoaXMgY2hhbmdlIGluIHRhcmdldCByYXRlcyBmdXJ0aGVyIGFmZmVjdCB0aGUgcmF0ZXMgYXQgd2hpY2ggdGhlIGNvbW1lcmNpYWwgYmFua3MgbGVuZCBtb25leSB0byB0aGVpciBjdXN0b21lcnMuIA0KQ2VudHJhbCBiYW5rcyBjYW4gYWxzbyBhY3F1aXJlIGdvdmVybm1lbnQgZGVidCB0byBwdXNoIHRoZSBlY29ub215IChpbmNyZWFzZSBzdXBwbHkgYW5kIGxvd2VyIHRoZSBkZW1hbmQpIG9yIHZpY2UgdmVyc2EuIA0KDQpJdCBpcyBpbXBvcnRhbnQgdG8gYWNrbm93bGVkZ2UgdGhhdCB0aGUgQ2VudHJhbCBCYW5rcyB1c2UgdGhlaXIgbW9uZXRhcnkgcG9saWN5IHRvIGluZmx1ZW5jZSB0aGUgaW50ZXJlc3QgcmF0ZXMgaW4gdGhlIFNIT1JULVRFUk0sIGJ1dCB0aGVpciBwb2xpY2llcyBjYW4gY29udHJpYnV0ZSB0byBzaGFwZSB0aGUgaW5mbGF0aW9uIHRhcmdldHMgaW4gdGhlIGxvbmcgdGVybS4gDQoNCg0KDQoNCiMjIEw0IEVmZmljaWVuY3kgb2YgbWFya2V0IGFuZCBpbmZvcm1hdGlvbg0KDQpDaGVjayBpZiBvbiAyNiBPY3RvYmVyIDIwMTcgY29jYSBjb2xhIHNoYXJlcyB3ZXJlIGhpdCBieSB0aGUgYWR2YXJzZSBpbmZvcm1hdGlvbiByZWFsaXplIG9uIHRoZSBtYXJrZXQuIChhc3N1bWUgMjYgaXMgdGhlIGluZm9ybWF0aW9uIHJlYWxlc2UgZGF0ZSkNCg0KDQpMb2FkIHBhY2thZ2VzDQoNCmBgYHtyfQ0KbGlicmFyeShxdWFudG1vZCkNCmBgYA0KDQoNCkRlZmluZSBkYXRlcw0KDQpgYGB7cn0NCmV2ZW50X2RhdGUgPC0gYXMuRGF0ZSgiMjAxNy0xMC0yNiIpDQpzdGFydF9kYXRlIDwtIGV2ZW50X2RhdGUgLSA3DQplbmRfZGF0ZSA8LSBldmVudF9kYXRlICsgNw0KYGBgDQoNCg0KUmV0cmlldmUgQ29jYS1Db2xhIERhdGENCg0KYGBge3J9DQp0aWNrZXIgPC0gIktPIg0KZ2V0U3ltYm9scyhTeW1ib2xzID0gdGlja2VyLCBzY3IgPSAieWFob28iLCBmcm9tID0gc3RhcnRfZGF0ZSwgdG8gPSBlbmRfZGF0ZSkNCmhlYWQoS08pDQpgYGANCg0KDQpQbG90IENsb3NpbmcgcHJpY2VzDQoNCmBgYHtyfQ0KZGV2Lm5ldygpDQpjaGFydFNlcmllcyhLTywgbmFtZSA9ICJDb2NhLUNvbGEgKEtPKSBTdG9jayBQcmljZSIpDQpgYGANCg0KDQpQbG90IHdpdGggVHJhZGluZyBWb2x1bWUNCmBgYHtyfQ0KIyBQbG90IGNsb3NpbmcgcHJpY2VzIHdpdGggdm9sdW1lDQpjaGFydFNlcmllcyhLTywgbmFtZSA9ICJDb2NhLUNvbGEgKEtPKSBTdG9jayBQcmljZSB3aXRoIFZvbHVtZSIsIHRoZW1lID0gY2hhcnRUaGVtZSgid2hpdGUiKSwgVEEgPSAiYWRkVm8oKSIpDQpgYGANCg0KDQpDYWxjdWxhdGUgRGFpbHkgUmV0dXJucw0KYGBge3J9DQojIENhbGN1bGF0ZSBkYWlseSByZXR1cm5zDQpLT19yZXR1cm5zIDwtIGRhaWx5UmV0dXJuKENsKEtPKSkNCg0KIyBWaWV3IHRoZSByZXR1cm5zDQpLT19yZXR1cm5zDQpgYGANCg0KDQpBbmFseXplIHRoZSBSZXR1cm4gb24gMjYgT2N0b2JlciAyMDE3DQpgYGB7cn0NCiMgR2V0IHRoZSByZXR1cm4gb24gdGhlIGV2ZW50IGRhdGUNCmV2ZW50X3JldHVybiA8LSBLT19yZXR1cm5zW2V2ZW50X2RhdGVdDQoNCiMgUHJpbnQgdGhlIHJldHVybg0KcHJpbnQoZXZlbnRfcmV0dXJuKQ0KYGBgDQoNCg0KIyMjIENvbXBhcmUgd2l0aCBNYXJrZXQgSW5kZXggKFMmUCA1MDApDQoNClJldHJpZXZlIFMmUCA1MDANCg0KYGBge3J9DQojIFJldHJpZXZlIFMmUCA1MDAgZGF0YQ0KZ2V0U3ltYm9scygiXkdTUEMiLCBzcmMgPSAieWFob28iLCBmcm9tID0gc3RhcnRfZGF0ZSwgdG8gPSBlbmRfZGF0ZSkNCg0KIyBDYWxjdWxhdGUgZGFpbHkgcmV0dXJucyBmb3IgUyZQIDUwMA0KU1A1MDBfcmV0dXJucyA8LSBkYWlseVJldHVybihDbChHU1BDKSkNCmBgYA0KDQoNCk1lcmdlIGFuZCBDb21wYXJlIFJldHVybnMNCg0KYGBge3J9DQojIE1lcmdlIHRoZSByZXR1cm5zDQpjb21iaW5lZF9yZXR1cm5zIDwtIG1lcmdlKEtPX3JldHVybnMsIFNQNTAwX3JldHVybnMsIGpvaW4gPSAiaW5uZXIiKQ0KY29sbmFtZXMoY29tYmluZWRfcmV0dXJucykgPC0gYygiS09fUmV0dXJuIiwgIlNQNTAwX1JldHVybiIpDQoNCiMgVmlldyBjb21iaW5lZCByZXR1cm5zDQpwcmludChjb21iaW5lZF9yZXR1cm5zKQ0KYGBgDQoNCg0KUGxvdCB0aGUgUmV0dXJucw0KDQpgYGB7cn0NCiMgTG9hZCBnZ3Bsb3QyIGZvciBwbG90dGluZw0KaWYgKCFyZXF1aXJlKCJnZ3Bsb3QyIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQp9DQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgUHJlcGFyZSBkYXRhIGZvciBwbG90dGluZw0KcmV0dXJuc19kZiA8LSBkYXRhLmZyYW1lKERhdGUgPSBpbmRleChjb21iaW5lZF9yZXR1cm5zKSwgY29yZWRhdGEoY29tYmluZWRfcmV0dXJucykpDQoNCiMgTWVsdCB0aGUgZGF0YSBmcmFtZSBmb3IgZ2dwbG90Mg0KaWYgKCFyZXF1aXJlKCJyZXNoYXBlMiIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInJlc2hhcGUyIikNCn0NCmxpYnJhcnkocmVzaGFwZTIpDQpyZXR1cm5zX21lbHRlZCA8LSBtZWx0KHJldHVybnNfZGYsIGlkLnZhcnMgPSAiRGF0ZSIpDQoNCiMgUGxvdCB0aGUgcmV0dXJucw0KZ2dwbG90KHJldHVybnNfbWVsdGVkLCBhZXMoeCA9IERhdGUsIHkgPSB2YWx1ZSwgY29sb3IgPSB2YXJpYWJsZSkpICsNCiAgZ2VvbV9saW5lKHNpemUgPSAxKSArDQogIGxhYnModGl0bGUgPSAiRGFpbHkgUmV0dXJuczogQ29jYS1Db2xhIHZzLiBTJlAgNTAwIiwNCiAgICAgICB4ID0gIkRhdGUiLA0KICAgICAgIHkgPSAiRGFpbHkgUmV0dXJuIiwNCiAgICAgICBjb2xvciA9ICJMZWdlbmQiKSArDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGFzLm51bWVyaWMoZXZlbnRfZGF0ZSksIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gInJlZCIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KDQoNCiMjIyBTdGF0aXN0aWNhbCBBbmFseXNpcw0KDQoNCkNhbGN1bGF0ZSBaLXNjb3JlIGZvciBFdmVudCBEYXRlIFJldHVybg0KDQpgYGB7cn0NCiMgQ2FsY3VsYXRlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBleGNsdWRpbmcgZXZlbnQgZGF0ZQ0KbWVhbl9yZXR1cm4gPC0gbWVhbihLT19yZXR1cm5zWy13aGljaChpbmRleChLT19yZXR1cm5zKSA9PSBldmVudF9kYXRlKV0pDQpzZF9yZXR1cm4gPC0gc2QoS09fcmV0dXJuc1std2hpY2goaW5kZXgoS09fcmV0dXJucykgPT0gZXZlbnRfZGF0ZSldKQ0KDQojIENhbGN1bGF0ZSB6LXNjb3JlDQp6X3Njb3JlIDwtIChhcy5udW1lcmljKGV2ZW50X3JldHVybikgLSBtZWFuX3JldHVybikgLyBzZF9yZXR1cm4NCg0KIyBQcmludCB6LXNjb3JlDQpwcmludChwYXN0ZSgiWi1zY29yZSBvbiIsIGV2ZW50X2RhdGUsICI6Iiwgcm91bmQoel9zY29yZSwgMikpKQ0KYGBgDQoNCg0KIyMjIEFuYWx5c2lzIG9mIHJlc3VsdHMuIA0KDQpJbiB0aGlzIGV4ZXJjaXNlIHdlIGhhdmUgcGVyZm9ybWVkIGFuIHN0dWR5IG9uIHRoZSBDb2NhIENvbGEgc2hhcmVzIG1vdmVtZW50cyBvbiBhbiBzcGVjaWZpZWQgZXZlbnQuIEluIG9yZGVyIHRvIHVudmVpbCB0aGUgYWJub3JtYWwgcmV0dXJucywgd2UgaGF2ZSBmaXJzdCBvYnRhaW5lZCB0aGUgQ29jYSBjb2xhIChLTykgZGF0YSBhbmQgd2UgaGF2ZSBzcGVjaWZpY2FsbHkgb2J0YWluZWQgdGhlIHJldHVybiBvbiB0aGUgZXZlbnQgZGF0ZS4gQWZ0ZXJ3YXJkcywgd2UgaGF2ZSBvYnRhaW5lZCB0aGUgZXF1aXZhbGVudCBkYXRhIGZyb20gdGhlIFMmUDUwMCBpbiBvcmRlciB0byBjb21wYXJlIHRoZSByZXR1cm5zIG9idGFpbmVkIGJ5IHRoZSBtYXJrZXQgaW4gdGhlIGV2ZW50IGRhdGUgc28gYXMgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgdGhlIHJldHVybnMgYXJlIGRldGVybWluZWQgYnkgdGhlIGFkdmVyc2UgaW5mb3JtYXRpb24gcmVnYXJkaW5nIENvY2EgQ29sYSBvciBpZiBpdCB3YXMgcmF0aGVyIGEgZ2VuZXJhbGl6ZWQgbW92ZW1lbnQgb2YgdGhlIG1hcmtldCBhcyBhIHdob2xlLiANCg0KV2hlbiBvYnNlcnZpbmcgdGhlIGdyYXBoaWMgY29tcGFyaXNvbiBiZXR3ZWVuIHRoZSBTJlA1MDAgYW5kIHRoZSBDb2NhIENvbGEgc2hhcmVzLCB3ZSBvYnNlcnZlIHRoYXQgdGhlaXIgdGVuZGVuY3kgbWF0Y2hlcyBxdWl0ZSBmYWlybHksIHNvIG91ciBmaXJzdCBpbnR1aXRpb24gd2lsbCBiZSB0aGF0IHRoZSBpbmZvcm1hdGlvbiBoYWQgbm8gcmVsZXZhbnQgZWZmZWN0IG9uIHRoZSBDb2NhIENvbGEuIFdlIGNhbiBhbHNvIG9ic2VydmUgdGhhdCB0aGUgQ29jYSBDb2xhIFNoYXJlcyBoYXZlIGEgY2xlYXIgcGVhayBpbiB0aGUgZXZlbnQgZGF0ZSB0aGF0IGlzIGZvbGxvd2VkIGJ5IGEgZHJhc3RpYyBmYWxsIGluIHRoZSBkYWlseSByZXR1cm5zLiANCg0KSG93ZXZlciwgaW4gb3JkZXIgdG8gYmV0dGVyIGFzc2VzcyB0aGUgZXZlbnQgYW5kIGl0cyBlZmZlY3RzLCB3ZSBoYXZlIHBlcmZvcm1lZCBhbiBzdGF0aXN0aWNhbCBhbmFseXNpcyB3aXRoIHRoZSBaLVNjb3JlLiBUbyBhbmFseXplIHRoZSByZXN1bHRzIG9mIHRoaXMgc3RhdGlzdGljYWwgc3R1ZHkgd2UgbXVzdCBrbm93IHRoYXQgaWYgb3VyIFotc2NvcmUgaXMgZ3JlYXRlciB0aGFuIDIgKHxaLVNjb3JlfCA+IDIpIHdlIHdpbGwgYmUgYWJsZSB0byBhZmZpcm0gdGhhdCB0aGUgcmV0dXJuIGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IHdpdGggYSBzaWduaWZpY2FuY2UgbGV2ZWwgb2YgNSUuIEZ1cnRoZXJtb3JlIGlmIHRoZSBaLVNjb3JlIGlzIGdyZWF0ZXIgdGhhbiAzLCB3ZSB3aWxsIGJlIGFibGUgdG8gYWZmaXJtIHRoYXQgdGhlIHJldHVybiBpcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCB3aXRoIGEgc2lnbmlmaWNhbmNlIGxldmVsIG9mIDElLiANCkluIHRoZSBwcmVzZW50IGNhc2UsIHRoZSBaLVNjb3JlIHdlIG9idGFpbmVkIGhhcyBhIHZhbHVlIG9mIDIuNjIsIHdoaWNoIGxlYWQgdXMgdG8gY29uY2x1ZGUgdGhhdCB3aXRoIGEgc2lnbmlmaWNhbmNlIGxldmVsIG9mIDUlIChvciB3aXRoIGEgY29uZmlkZW5jZSBsZXZlbCBvZiA5NSUpLCB0aGUgZGFpbHkgcmV0dXJucyBoYXZlIGJlZW4gc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQuIA0KDQpUaGlzIHVsdGltYXRlbHkgbGVhZHMgdXMgdG8gYWZmaXJtIHdpdGhpbiBvdXIgY29uZmlkZW5jZSBsZXZlbCB0aGF0IHRoZSBhZHZlcnNlIGluZm9ybWF0aW9uIHRoYXQgaGl0IHRoZSBDb2NhLUNvbGEgU2hhcmVzIGhhcyBoYWQgYW4gaW1wYWN0IGluIGl0cyBwcmljZSwgd2hpY2ggY2FuIGJlIGJhY2tlZCB1cCB3aXRoIHRoZSBvYnNlcnZhbmNlIG9mIHRoZSBncmFwaGljIGluIHRoZSBldmVudCBkYXRlIGFzIHdlbGwgYXMgdGhlIHRyZW5kIHRoYXQgZm9sbG93cyBpbm1pZGlhdGVseSBhZnRlcndhcmRzLiANCg0KDQoNCiMjIEw1IEZpbmFuY2lhbCBzdGF0ZW1lbnRzIGFuZCBmdW5kYW1lbnRhbCBhbmFseXNpcw0KDQoNCiMjIyBMNS4wIERvd25sb2FkIHRvIFIgdGhlIGZpbmFuY2lhbCBzdGF0ZW1lbnRzIG9mIE1pY3Jvc29mdCAyMDE4LCBzaG93IHRoZSBjb2RlDQoNCmBgYHtyfQ0KIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXMNCmxpYnJhcnkocXVhbnRtb2QpDQpsaWJyYXJ5KHRpZHlyKSAgICAjIEZvciBkYXRhIG1hbmlwdWxhdGlvbiBhbmQgY2xlYW5pbmcNCmxpYnJhcnkoZmlucmVwb3J0cikNCmxpYnJhcnkoWEJSTCkNCg0KIyBTZXQgdXAgdGhlIGF1dGhvcml0eSB0byBFREdBUg0Kb3B0aW9ucyhIVFRQVXNlckFnZW50ID0gImpzMTM3NTc2QHN0dWRlbnRzLnNnaC53YXcucGwiKSANCg0KIyBNaWNyb3NvZnQncyBDSUsgaXMgMDAwMDc4OTAxOQ0KDQojIEdldCB0aGUgbGlzdCBvZiBhdmFpbGFibGUgYW5udWFsIHJlcG9ydHMgZm9yIE1pY3Jvc29mdA0KYW5udWFsX3JlcG9ydHMgPC0gQW5udWFsUmVwb3J0cygiMDAwMDc4OTAxOSIsIGZvcmVpZ24gPSBGQUxTRSkNCg0KIyBWaWV3IHRoZSBhdmFpbGFibGUgcmVwb3J0cw0KcHJpbnQoYW5udWFsX3JlcG9ydHMpDQoNCiMgU3BlY2lmeSB0aGUgeWVhciBmb3Igd2hpY2ggeW91IHdhbnQgdGhlIGZpbmFuY2lhbCBkYXRhDQpyZXBvcnRfeWVhciA8LSAyMDE4DQoNCiMgUmV0cmlldmUgdGhlIGluY29tZSBzdGF0ZW1lbnQNCmluY29tZV9zdGF0ZW1lbnQgPC0gR2V0SW5jb21lKCJNU0ZUIiwgcmVwb3J0X3llYXIpDQoNCiMgVmlldyB0aGUgaW5jb21lIHN0YXRlbWVudA0KcHJpbnQoaW5jb21lX3N0YXRlbWVudCkNCg0KIyBSZXRyaWV2ZSB0aGUgYmFsYW5jZSBzaGVldA0KYmFsYW5jZV9zaGVldCA8LSBHZXRCYWxhbmNlU2hlZXQoIk1TRlQiLCByZXBvcnRfeWVhcikNCg0KIyBWaWV3IHRoZSBiYWxhbmNlIHNoZWV0DQpwcmludChiYWxhbmNlX3NoZWV0KQ0KDQojIFJldHJpZXZlIHRoZSBjYXNoIGZsb3cgc3RhdGVtZW50DQpjYXNoX2Zsb3cgPC0gR2V0Q2FzaEZsb3coIk1TRlQiLCByZXBvcnRfeWVhcikNCg0KIyBWaWV3IHRoZSBjYXNoIGZsb3cgc3RhdGVtZW50DQpwcmludChjYXNoX2Zsb3cpDQoNCmBgYA0KDQojIyMgTDUuMSBJZGVudGlmeSB0aGUgdHlwZXMgb2YgZGVwb3NpdHMgdGhhdCB0aGUgY29tbWVyY2lhbCBiYW5rIHVzZXMgdG8gb2J0YWluIG1vc3Qgb2YgaXRzIGZ1bmRzLg0KDQojIyMjIEpQTW9yZ2FuIENoYXNlIHJlbGllcyBvbiB0d28gbWFpbiB0eXBlcyBvZiBkZXBvc2l0czoNCg0KIyMjIyMgTm9uaW50ZXJlc3QtQmVhcmluZyBEZXBvc2l0czoNCg0KVS5TLiBvZmZpY2VzOiAkNjQzLjc1IGJpbGxpb24gaW4gMjAyMy4NCg0KTm9uLVUuUy4gb2ZmaWNlczogJDIzLjEgYmlsbGlvbi4NCg0KIyMjIyMgSW50ZXJlc3QtQmVhcmluZyBEZXBvc2l0czoNCg0KVS5TLiBvZmZpY2VzOiAkMS4zMDMgdHJpbGxpb24gaW4gMjAyMy4NCg0KTm9uLVUuUy4gb2ZmaWNlczogJDQzMC43NCBiaWxsaW9uLg0KDQpUaGVzZSBkZXBvc2l0cyBpbmNsdWRlIHNhdmluZ3MsIGRlbWFuZCwgYW5kIHRpbWUgZGVwb3NpdHMuIFRoZSBtYWpvcml0eSBvZiBmdW5kaW5nIGNvbWVzIGZyb20gY29uc3VtZXIgYW5kIHdob2xlc2FsZSBvcGVyYXRpbmcgZGVwb3NpdHMsIHdoaWNoIGFyZSBjb25zaWRlcmVkIHN0YWJsZSBzb3VyY2VzIG9mIGxpcXVpZGl0eS4NCg0KDQojIyMgTDUuMiBJZGVudGlmeSB0aGUgbWFpbiB1c2VzIG9mIGZ1bmRzIGJ5IHRoZSBiYW5rLg0KDQojIyMjIEpQTW9yZ2FuIENoYXNlIHByaW1hcmlseSB1c2VzIGl0cyBmdW5kcyBmb3I6DQoNCiMjIyMjIExvYW5zOg0KDQpUb3RhbCBsb2FucyBpbiAyMDIzIGFtb3VudGVkIHRvICQxLjMyNCB0cmlsbGlvbiwgaW5jbHVkaW5nIGNvbnN1bWVyIGFuZCBjb21tZXJjaWFsIGxvYW5zLg0KDQojIyMjIyBJbnZlc3RtZW50czoNCg0KRnVuZHMgYXJlIGFsbG9jYXRlZCB0byBzZWN1cml0aWVzIHBvcnRmb2xpb3MgZm9yIGluY29tZSBnZW5lcmF0aW9uIGFuZCBsaXF1aWRpdHkgbWFuYWdlbWVudC4NCg0KIyMjIyMgTGlxdWlkaXR5Og0KDQpTaWduaWZpY2FudCBjYXNoIHJlc2VydmVzIGFuZCBoaWdoLXF1YWxpdHkgbGlxdWlkIGFzc2V0cyBhcmUgbWFpbnRhaW5lZCB0byBtZWV0IG9ibGlnYXRpb25zLg0KDQojIyMjIyBBY3F1aXNpdGlvbnM6DQpJbnZlc3RtZW50cyBpbiBidXNpbmVzc2VzLCBzdWNoIGFzIHRoZSBhY3F1aXNpdGlvbiBvZiBGaXJzdCBSZXB1YmxpYywgYWxpZ24gd2l0aCBzdHJhdGVnaWMgZ29hbHMuDQoNCg0KIyMjIEw1LjMgRG9lcyBpdCBhcHBlYXIgdGhhdCB0aGUgYmFuayBpcyBhdHRlbXB0aW5nIHRvIGVudGVyIHRoZSBzZWN1cml0aWVzIGluZHVzdHJ5IGJ5IG9mZmVyaW5nIHNlY3VyaXRpZXMgc2VydmljZXM/DQoNClllcywgSlBNb3JnYW4gQ2hhc2UgaXMgZGVlcGx5IGludm9sdmVkIGluIHRoZSBzZWN1cml0aWVzIGluZHVzdHJ5IHRocm91Z2g6DQoNCiMjIyMjIEludmVzdG1lbnQgQmFua2luZzoNCg0KUmFpc2luZyBlcXVpdHkgYW5kIGRlYnQgY2FwaXRhbCwgY29ycG9yYXRlIHN0cmF0ZWd5IGFkdmlzb3J5Lg0KDQojIyMjIyBTZWN1cml0aWVzIFNlcnZpY2VzOg0KDQpDdXN0b2R5LCBmdW5kIGFkbWluaXN0cmF0aW9uLCBhbmQgc2VjdXJpdGllcyBsZW5kaW5nLg0KDQoNCiMjIyBMNS40IERvZXMgaXQgYXBwZWFyIHRoYXQgdGhlIGJhbmsgaXMgYXR0ZW1wdGluZyB0byBlbnRlciB0aGUgaW5zdXJhbmNlIGluZHVzdHJ5IGJ5IG9mZmVyaW5nIGluc3VyYW5jZSBzZXJ2aWNlcz8NCg0KSlBNb3JnYW4gQ2hhc2UgaXMgbm90IHNpZ25pZmljYW50bHkgZXhwYW5kaW5nIGludG8gdHJhZGl0aW9uYWwgaW5zdXJhbmNlIG1hcmtldHMgYnV0IG9mZmVycyBwcm9kdWN0cyBsaWtlIGNyZWRpdCBkZXJpdmF0aXZlcywgd2hpY2ggb3ZlcmxhcCB3aXRoIHNvbWUgaW5zdXJhbmNlLWxpa2UgcmlzayBtYW5hZ2VtZW50IGZ1bmN0aW9ucy4NCg0KDQojIyMgTDUuNSBBc3Nlc3MgdGhlIGJhbmvigJlzIGJhbGFuY2Ugc2hlZXQgZm9yIHRoZSBnYXAgYmV0d2VlbiByYXRlLXNlbnNpdGl2ZSBhc3NldHMgYW5kIGxpYWJpbGl0aWVzLg0KDQpKUE1vcmdhbiBhY3RpdmVseSBtYW5hZ2VzIGludGVyZXN0IHJhdGUgcmlzayBieSBhbGlnbmluZyByYXRlLXNlbnNpdGl2ZSBhc3NldHMgKGxvYW5zLCBzZWN1cml0aWVzKSBhbmQgbGlhYmlsaXRpZXMgKGRlcG9zaXRzLCBib3Jyb3dpbmdzKS4gQmFzZWQgb24gYXZhaWxhYmxlIGRhdGEsIHRoZSBiYW5rIHNlZW1zIHRvIG1haW50YWluIGEgYmFsYW5jZWQgb3Igc2xpZ2h0bHkgcG9zaXRpdmUgZ2FwLg0KDQoNCiMjIyBMNS42LUw1LjEyIEZpbmFuY2lhbCBSYXRpb3MNCg0KUiBDb2RlIGZvciBDYWxjdWxhdGlvbnMNCg0KVGhlIGZvbGxvd2luZyBSIGNvZGUgY29tcHV0ZXMgdGhlc2UgbWV0cmljczoNCg0KYGBge3J9DQojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcw0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojIExvYWQgZGF0YQ0KZmlsZV9wYXRoIDwtICJDOi9Vc2Vycy9VU1VBUklPL09uZURyaXZlL0RvY3VtZW50b3MvMDAwMDAxOTYxNy0yNC0wMDAyMjUueGxzeCINCmJhbGFuY2Vfc2hlZXQgPC0gcmVhZF9leGNlbChmaWxlX3BhdGgsIHNoZWV0ID0gImNvbnNvbGlkYXRlZCBiYWxhbmNlIHNoZWV0IikNCmluY29tZV9zaGVldCA8LSByZWFkX2V4Y2VsKGZpbGVfcGF0aCwgc2hlZXQgPSAiaW5jb21lIikNCg0KIyBFeHRyYWN0IGRhdGENCnRvdGFsX2Fzc2V0cyA8LSBiYWxhbmNlX3NoZWV0ICU+JQ0KICBmaWx0ZXIoZ3JlcGwoIlRvdGFsIGFzc2V0cyIsIGBDb2x1bW4gMWApKSAlPiUNCiAgc2VsZWN0KGAyMDIzYCkgJT4lDQogIHB1bGwoKQ0KDQp0b3RhbF9lcXVpdHkgPC0gYmFsYW5jZV9zaGVldCAlPiUNCiAgZmlsdGVyKGdyZXBsKCJUb3RhbCBzdG9ja2hvbGRlcnMnIGVxdWl0eSIsIGBDb2x1bW4gMWApKSAlPiUNCiAgc2VsZWN0KGAyMDIzYCkgJT4lDQogIHB1bGwoKQ0KDQppbnRlcmVzdF9pbmNvbWUgPC0gaW5jb21lX3NoZWV0ICU+JQ0KICBmaWx0ZXIoZ3JlcGwoIk5ldCBpbnRlcmVzdCBpbmNvbWUiLCBgQ29sdW1uIDFgKSkgJT4lDQogIHNlbGVjdChgMjAyM2ApICU+JQ0KICBwdWxsKCkNCg0KaW50ZXJlc3RfZXhwZW5zZSA8LSBpbmNvbWVfc2hlZXQgJT4lDQogIGZpbHRlcihncmVwbCgiSW50ZXJlc3QgZXhwZW5zZSIsIGBDb2x1bW4gMWApKSAlPiUNCiAgc2VsZWN0KGAyMDIzYCkgJT4lDQogIHB1bGwoKQ0KDQpuZXRfaW5jb21lIDwtIGluY29tZV9zaGVldCAlPiUNCiAgZmlsdGVyKGdyZXBsKCJOZXQgaW5jb21lIiwgYENvbHVtbiAxYCkpICU+JQ0KICBzZWxlY3QoYDIwMjNgKSAlPiUNCiAgcHVsbCgpDQoNCiMgQ2FsY3VsYXRlIHJhdGlvcw0KaW50ZXJlc3RfaW5jb21lX3BlcmNlbnRfYXNzZXRzIDwtIChpbnRlcmVzdF9pbmNvbWUgLyB0b3RhbF9hc3NldHMpICogMTAwDQppbnRlcmVzdF9leHBlbnNlX3BlcmNlbnRfYXNzZXRzIDwtIChpbnRlcmVzdF9leHBlbnNlIC8gdG90YWxfYXNzZXRzKSAqIDEwMA0KbmV0X2ludGVyZXN0X21hcmdpbiA8LSAoaW50ZXJlc3RfaW5jb21lIC0gaW50ZXJlc3RfZXhwZW5zZSkgLyB0b3RhbF9hc3NldHMNCnJldHVybl9vbl9hc3NldHMgPC0gKG5ldF9pbmNvbWUgLyB0b3RhbF9hc3NldHMpICogMTAwDQpyZXR1cm5fb25fZXF1aXR5IDwtIChuZXRfaW5jb21lIC8gdG90YWxfZXF1aXR5KSAqIDEwMA0KDQojIERpc3BsYXkgcmVzdWx0cw0KcmVzdWx0cyA8LSBkYXRhLmZyYW1lKA0KICBNZXRyaWMgPSBjKA0KICAgICJJbnRlcmVzdCBJbmNvbWUgJSBvZiBUb3RhbCBBc3NldHMgKEw1LjYpIiwNCiAgICAiSW50ZXJlc3QgRXhwZW5zZXMgJSBvZiBUb3RhbCBBc3NldHMgKEw1LjcpIiwNCiAgICAiTmV0IEludGVyZXN0IE1hcmdpbiAoTDUuOCkiLA0KICAgICJSZXR1cm4gb24gQXNzZXRzIChMNS4xMSkiLA0KICAgICJSZXR1cm4gb24gRXF1aXR5IChMNS4xMikiDQogICksDQogIFZhbHVlID0gYygNCiAgICBpbnRlcmVzdF9pbmNvbWVfcGVyY2VudF9hc3NldHMsDQogICAgaW50ZXJlc3RfZXhwZW5zZV9wZXJjZW50X2Fzc2V0cywNCiAgICBuZXRfaW50ZXJlc3RfbWFyZ2luLA0KICAgIHJldHVybl9vbl9hc3NldHMsDQogICAgcmV0dXJuX29uX2VxdWl0eQ0KICApDQopDQoNCnByaW50KHJlc3VsdHMpDQoNCiMgT3B0aW9uYWw6IFZpc3VhbGl6YXRpb24NCmdncGxvdChyZXN1bHRzLCBhZXMoeCA9IE1ldHJpYywgeSA9IFZhbHVlKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJzdGVlbGJsdWUiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRmluYW5jaWFsIFJhdGlvcyAoTDUuNiAtIEw1LjEyKSIsDQogICAgeCA9ICJNZXRyaWMiLA0KICAgIHkgPSAiVmFsdWUgKCUpIg0KICApDQpgYGANCg0KDQojIyMgVmlzdWFsIHJlcHJlc2VudGF0aW9uDQoNCmBgYHtyfQ0KZ2dwbG90KHJlc3VsdHMsIGFlcyh4ID0gTWV0cmljLCB5ID0gVmFsdWUpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gInN0ZWVsYmx1ZSIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJGaW5hbmNpYWwgUmF0aW9zIChMNS42IC0gTDUuMTIpIiwNCiAgICB4ID0gIk1ldHJpYyIsDQogICAgeSA9ICJWYWx1ZSAoJSkiDQogICkNCmBgYA0KDQoNCg0KIyMjIEV4cGxhbmF0aW9uIG9mIE1ldHJpY3M6DQoNCkw1LjYgSW50ZXJlc3QgSW5jb21lIGFzICUgb2YgQXNzZXRzOiBNZWFzdXJlcyB0aGUgZWZmaWNpZW5jeSBvZiBhc3NldHMgaW4gZ2VuZXJhdGluZyBpbnRlcmVzdCBpbmNvbWUuDQoNCkw1LjcgSW50ZXJlc3QgRXhwZW5zZXMgYXMgJSBvZiBBc3NldHM6IFNob3dzIHRoZSBjb3N0IG9mIGZ1bmRpbmcgcmVsYXRpdmUgdG8gYXNzZXQgc2l6ZS4NCg0KTDUuOCBOZXQgSW50ZXJlc3QgTWFyZ2luOiBJbmRpY2F0ZXMgcHJvZml0YWJpbGl0eSBmcm9tIGNvcmUgYmFua2luZyBvcGVyYXRpb25zIGFmdGVyIGZ1bmRpbmcgY29zdHMuDQoNCkw1LjExIFJldHVybiBvbiBBc3NldHMgKFJPQSk6IFJlZmxlY3RzIGhvdyB3ZWxsIHRoZSBiYW5rIHVzZXMgYXNzZXRzIHRvIGdlbmVyYXRlIHByb2ZpdC4NCg0KTDUuMTIgUmV0dXJuIG9uIEVxdWl0eSAoUk9FKTogTWVhc3VyZXMgdGhlIHJldHVybnMgZ2VuZXJhdGVkIG9uIHNoYXJlaG9sZGVyIGVxdWl0eS4NCg0KDQojIyMgTDUuMTMgSW1wYWN0IG9mIFJpc2luZyBJbnRlcmVzdCBSYXRlcw0KDQpJbmNyZWFzZSBJbnRlcmVzdCBJbmNvbWU6IExvYW5zIHdpdGggdmFyaWFibGUgcmF0ZXMgd2lsbCB5aWVsZCBoaWdoZXIgaW50ZXJlc3QuDQoNCkluY3JlYXNlIEludGVyZXN0IEV4cGVuc2U6IERlcG9zaXRzIGFuZCBib3Jyb3dpbmdzIHdpbGwgY29zdCBtb3JlLCBwb3RlbnRpYWxseSBjb21wcmVzc2luZyBuZXQgaW50ZXJlc3QgbWFyZ2luLg0KDQoNCiMjIyBMNS4xNCBJbXBhY3Qgb2YgRGV0ZXJpb3JhdGluZyBFY29ub21pYyBDb25kaXRpb25zDQoNCkluY3JlYXNlIGluIExvYW4gTG9zcyBQcm92aXNpb25zOiBIaWdoZXIgZGVmYXVsdHMgb24gbG9hbnMgd291bGQgcmFpc2UgY3JlZGl0IGNvc3RzLg0KDQpSZWR1Y2UgaW4gTm9uLWludGVyZXN0IEluY29tZTogTG93ZXIgYWN0aXZpdHkgaW4gaW52ZXN0bWVudCBiYW5raW5nIGFuZCBhc3NldCBtYW5hZ2VtZW50IGNvdWxkIGh1cnQgZmVlIGluY29tZS4NCg0KDQojIyBMNS4xNS0gTDUuMTkNClRoZSBtdXR1YWwgZnVuZCBjaG9zZW4gd2lsbCBiZSBWYW5ndWFyZCA1MDAgSW5kZXggRnVuZCAoVkZJQVgpDQoNCiMjIyBMNS4xNSBXaGF0IGlzIHRoZSBpbnZlc3RtZW50IG9iamVjdGl2ZSBvZiB0aGlzIG11dHVhbCBmdW5kPyBEbyB5b3UgY29uc2lkZXIgdGhpcyBtdXR1YWwgZnVuZCB0byBoYXZlIGxvdyByaXNrLCBtb2RlcmF0ZSByaXNrLCBvciBoaWdoIHJpc2s/DQpUaGUgVmFuZ3VhcmQgNTAwIEluZGV4IEZ1bmQgYWltcyB0byB0cmFjayB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIFMmUCA1MDAgSW5kZXgsIHdoaWNoIHJlcHJlc2VudHMgNTAwIG9mIHRoZSBsYXJnZXN0IFUuUy4gY29tcGFuaWVzLiBJdHMgb2JqZWN0aXZlIGlzIHRvIHByb3ZpZGUgaW52ZXN0b3JzIHdpdGggZXhwb3N1cmUgdG8gdGhlIGxhcmdlLWNhcCBzZWdtZW50IG9mIHRoZSBVLlMuIGVxdWl0eSBtYXJrZXQsIGZvY3VzaW5nIG9uIGxvbmctdGVybSBncm93dGggb2YgY2FwaXRhbCBhbmQgaW5jb21lIGZyb20gZGl2aWRlbmRzLg0KDQpUaGlzIG11dHVhbCBmdW5kIGlzIGNvbnNpZGVyZWQgdG8gaGF2ZSBtb2RlcmF0ZSByaXNrLiBJdCBpcyBzdGlsbCBzdWJqZWN0IHRvIG1hcmtldCByaXNrIGluaGVyZW50IGluIGVxdWl0eSBpbnZlc3RpbmcuDQoNCiMjIyBMNS4xNiBXaGF0IHdhcyB0aGUgcmV0dXJuIG9uIHRoZSBtdXR1YWwgZnVuZCBsYXN0IHllYXI/IFdoYXQgd2FzIHRoZSBhdmVyYWdlIGFubnVhbCByZXR1cm4gb3ZlciB0aGUgbGFzdCB0aHJlZSB5ZWFycz8NCg0KQXMgb2YgdGhlIGVuZCBvZiAyMDIyOg0KDQpSZXR1cm4gbGFzdCB5ZWFyICgyMDIyKTogQXBwcm94aW1hdGVseSAtMTglLCByZWZsZWN0aW5nIGEgZG93bnR1cm4gaW4gdGhlIFUuUy4gc3RvY2sgbWFya2V0Lg0KQXZlcmFnZSBhbm51YWwgcmV0dXJuIG92ZXIgdGhlIGxhc3QgdGhyZWUgeWVhcnMgKDIwMjAtMjAyMik6IEFwcHJveGltYXRlbHkgNyUgcGVyIHllYXINCg0KIyMjIEw1LjE3IFdoYXQgaXMgYSBrZXkgZWNvbm9taWMgZmFjdG9yIHRoYXQgaW5mbHVlbmNlcyB0aGUgcmV0dXJuIG9uIHRoaXMgbXV0dWFsIGZ1bmQ/DQoNCkl0IGlzIHRoZSBvdmVyYWxsIHBlcmZvcm1hbmNlIG9mIHRoZSBVLlMuIHN0b2NrIG1hcmtldC4gRmFjdG9ycyBzdWNoIGFzIGl0cyBzdG9jayBtYXJrZXQgY29uZGl0aW9ucywgVVMgaW50ZXJlc3QgcmF0ZXMgYW5kIG1hY3JvZWNvbm9taWMgaW5kaWNhdG9ycyBhZmZlY3Qgbm90aWNlYWJseS4gDQoNCiMjIyBMNS4xOCBNdXN0IGFueSBmZWVzIGJlIHBhaWQgd2hlbiBidXlpbmcgb3Igc2VsbGluZyB0aGlzIG11dHVhbCBmdW5kPw0KDQpUaGUgVmFuZ3VhcmQgNTAwIEluZGV4IEZ1bmQgZG9lcyBub3QgY2hhcmdlIGFueSBzYWxlcyBsb2FkcyB3aGVuIGJ1eWluZyBvciBzZWxsaW5nIHNoYXJlcy4NCkhvd2V2ZXIsIGludmVzdG9ycyBzaGFsbCBiZSBhd2FyZSBvZiBleHBlbnNlIHJhdGlvcyBhbmQgYWNjb3VudGluZyBzZXJ2aWNlIGZlZXMuDQoNCiMjIyBMNS4xOSBXaGF0IHdhcyB0aGUgZXhwZW5zZSByYXRpbyBmb3IgdGhpcyBtdXR1YWwgZnVuZCBvdmVyIHRoZSBsYXN0IHllYXI/IERvZXMgdGhpcyByYXRpbyBzZWVtIGhpZ2ggdG8geW91Pw0KDQpUaGUgZXhwZW5zZSByYXRpbyBmb3IgdGhlIFZhbmd1YXJkIDUwMCBJbmRleCBGdW5kIGlzIGFwcHJveGltYXRlbHkgMC4wNCUuDQoNClRoaXMgcmF0aW8gaXMgY29uc2lkZXJlZCB2ZXJ5IGxhdyBjb21wYXJlIHRvIG90aGVyIG11dHVhbCBmdW5kcy4NCg0KDQojIyBMNS4yMCAtIEw1LjIyIFNlY3VyaXRpZXMgRmlybXMNClNlY3VyaXRpZXMgRmlybSBTZWxlY3RlZDogR29sZG1hbiBTYWNocyBHcm91cCwgSW5jLg0KDQojIyMgTDUuMjAgV2hhdCBhcmUgdGhlIG1haW4gdHlwZXMgb2YgYnVzaW5lc3MgY29uZHVjdGVkIGJ5IHRoZSBzZWN1cml0aWVzIGZpcm0/DQoNCkdvbGRtYW4gU2FjaHMgT3BlcmF0ZXMgaW4gc2V2ZXJhbCBidXNpbmVzcyBzZWdtZW50cyBzdWNoIGFzIEludmVzdG1lbnQgQmFua2luZywgR2xvYmFsIE1hcmtldHMsIEFzc2V0IE1hbmFnZW1lbnQgYW5kIENvbnN1bWVyICYgV2VhbHRoIE1hbmFnZW1lbnQuIA0KDQoNCiMjIyBMNS4yMSBTdW1tYXJpemUgYW55IHN0YXRlbWVudHMgbWFkZSBieSB0aGUgc2VjdXJpdGllcyBmaXJtIGluIGl0cyBhbm51YWwgcmVwb3J0IGFib3V0IGhvdyBpdCBtYXkgYmUgYWZmZWN0ZWQgYnkgZXhpc3Rpbmcgb3IgcG90ZW50aWFsIHJlZ3VsYXRpb25zLg0KDQpSZWd1bGF0b3J5IEVudmlyb25tZW50OiBUaGUgZmlybSBvcGVyYXRlcyB1bmRlciBleHRlbnNpdmUgcmVndWxhdGlvbnMgdGhhdCBhZmZlY3QgaXRzIG9wZXJhdGlvbnMsIGNhcGl0YWwgcmVxdWlyZW1lbnRzLCBhbmQgcHJvZml0YWJpbGl0eS4NCg0KQ29tcGxpYW5jZSBDb3N0czpsZWFkcyBoaWdoZXIgb3BlcmF0aW9uYWwgY29zdHMuDQoNClBvdGVudGlhbCBSZWd1bGF0aW9uczogRnV0dXJlIGNoYW5nZXMgY291bGQgaW1wYWN0IGJ1c2luZXNzIGFjdGl2aXRpZXMuDQoNClJpc2sgTWFuYWdlbWVudDogSW1wb3J0YW5jZSBvZiByaWdvcm91cyByaXNrIG1hbmFnZW1lbnQgc3lzdGVtcyB0byBuYXZpZ2F0ZSB0aGUgY29tcGxleCByZWd1bGF0b3J5IGxhbmRzY2FwZS4NCg0KR29sZG1hbiBTYWNocyBhY2tub3dsZWRnZXMgdGhhdCByZWd1bGF0b3J5IGNoYW5nZXMgY291bGQgbGltaXQgY2VydGFpbiBidXNpbmVzcyBwcmFjdGljZXMgYW5kIHJlcXVpcmUgY2VydGFpbiBhZGp1c3RtZW50cy4NCg0KDQojIyMgTDUuMjIgRGVzY3JpYmUgdGhlIHJlY2VudCBwZXJmb3JtYW5jZSBvZiB0aGUgc2VjdXJpdGllcyBmaXJtLCBhbmQgZXhwbGFpbiB3aHkgdGhlIHBlcmZvcm1hbmNlIGhhcyBiZWVuIGZhdm9yYWJsZSBvciB1bmZhdm9yYWJsZS4NCg0KIyMjIyBNaXhlZCBmaW5hbmNpYWwgcmVzdWx0cw0KDQpTdHJlbmd0aHM6IGludmVzdG1lbnQgYmFua2luZyByZXZlbnVlIGFuZCBhc3NldCBtYW5hZ2VtZW50IGdyb3d0aA0KDQpDaGFsbGVuZ2VzOiBHbG9iYWwgTWFya2V0cyBEaXZpc2lvbiBhbmQgcmVndWxhdG9yeSBjb3N0cw0KDQojIyMjIFJlYXNvbnMgZm9yIHBlcmZvcm1hbmNlDQpFY29ub21pYyByZWNvdmVyeSBhbmQgbWFya2V0IHZvbGF0aWxpdHkgYXMgZmF2b3JhYmxlIGZhY3RvcnMNCkludGVyZXN0IHJhdGUgQ2hhbmdlcyBhbmQgZ2VvcG9saXRpY2FsIHJpc2tzIGFzIHVuZmF2b3JhYmxlIGZhY3RvcnMuDQoNCg0KDQoNCiMjIEw2LiBFcXVpdHkNCg0KRXZlbnQgU3R1ZHkgb24gQXBwbGUgSW5jLiAoQUFQTCkNCg0KDQojIyMgT2JqZWN0aXZlOiANClRvIGNvbmR1Y3QgYW4gZXZlbnQgc3R1ZHkgb24gQXBwbGUgSW5jLiAoQUFQTCkgdG8gYW5hbHl6ZSB0aGUgaW1wYWN0IG9mIGEgc2lnbmlmaWNhbnQgY29ycG9yYXRlIGV2ZW50IG9uIGl0cyBzdG9jayByZXR1cm5zLg0KDQoNCiMjIyBFdmVudCBTZWxlY3Rpb246DQoNCldlIHdpbGwgZm9jdXMgb24gQXBwbGUncyBRNCAyMDIwIGVhcm5pbmdzIGFubm91bmNlbWVudCwgd2hpY2ggdG9vayBwbGFjZSBvbiBPY3RvYmVyIDI5LCAyMDIwLg0KDQoNCiMjIyBIeXBvdGhlc2lzOiANClRoZSBlYXJuaW5ncyBhbm5vdW5jZW1lbnQgaGFzIGEgbWVhc3VyYWJsZSBpbXBhY3Qgb24gQXBwbGUncyBzdG9jayBwcmljZSwgcmVzdWx0aW5nIGluIGFibm9ybWFsIHJldHVybnMgYXJvdW5kIHRoZSBldmVudCBkYXRlLg0KDQoNCiMjIyBNZXRob2RvbG9neToNCg0KQ2FsY3VsYXRlIGRhaWx5IHN0b2NrIHJldHVybnMgZm9yIEFBUEwuDQoNCkNyZWF0ZSBhbiBldmVudCBkdW1teSB2YXJpYWJsZSB0byBpc29sYXRlIHRoZSBldmVudCdzIGVmZmVjdC4NCg0KUGVyZm9ybSBhIHJlZ3Jlc3Npb24gYW5hbHlzaXMgdG8gZXN0aW1hdGUgdGhlIGFibm9ybWFsIHJldHVybiBvbiB0aGUgZXZlbnQgZGF0ZS4NCg0KRXh0ZW5kIHRoZSBhbmFseXNpcyB0byBhbiBldmVudCB3aW5kb3cgdG8gY2FwdHVyZSBhbnkgcHJlLSBvciBwb3N0LWV2ZW50IGVmZmVjdHMuDQoNCkFzc2VzcyB0aGUgc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlIG9mIHRoZSByZXN1bHRzLg0KDQoNCiMjIyBSIENvZGUgSW1wbGVtZW50YXRpb24NCg0KYGBge3J9DQojIExvYWQgcmVxdWlyZWQgbGlicmFyaWVzDQpsaWJyYXJ5KHF1YW50bW9kKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCg0KIyBEZWZpbmUgdGhlIHRpY2tlciBzeW1ib2wgYW5kIGRhdGUgcmFuZ2UNCnRpY2tlciA8LSAiQUFQTCINCnN0YXJ0X2RhdGUgPC0gIjIwMjAtMTAtMTUiDQplbmRfZGF0ZSA8LSAiMjAyMC0xMS0xMiINCg0KIyBHZXQgc3RvY2sgZGF0YQ0KZ2V0U3ltYm9scyh0aWNrZXIsIGZyb20gPSBzdGFydF9kYXRlLCB0byA9IGVuZF9kYXRlKQ0KDQojIERlZmluZSB0aGUgZXZlbnQgZGF0ZQ0KZXZlbnRfZGF0ZSA8LSAiMjAyMC0xMC0yOSINCg0KIyBDYWxjdWxhdGUgZGFpbHkgbG9nIHJldHVybnMNCkFBUExfcmV0dXJucyA8LSBkaWZmKGxvZyhBZChnZXQodGlja2VyKSkpKQ0KDQojIENyZWF0ZSBldmVudCBkdW1teSB2YXJpYWJsZQ0KZXZlbnRfZHVtbXkgPC0gaWZlbHNlKGluZGV4KEFBUExfcmV0dXJucykgPT0gZXZlbnRfZGF0ZSwgMSwgMCkNCg0KIyBQZXJmb3JtIHJlZ3Jlc3Npb24gYW5hbHlzaXMNCmV2ZW50X3N0dWR5IDwtIGxtKEFBUExfcmV0dXJucyB+IGV2ZW50X2R1bW15KQ0KDQojIFN1bW1hcml6ZSB0aGUgcmVncmVzc2lvbiByZXN1bHRzDQpzdW1tYXJ5KGV2ZW50X3N0dWR5KQ0KYGBgDQoNCg0KIyMjIE5vdGVzIGNvbiBjb2RlDQoNCg0KIyMjIyBDYWxjdWxhdGluZyBEYWlseSBMb2cgUmV0dXJuczoNCg0KQWQoZ2V0KHRpY2tlcikpOiBFeHRyYWN0cyB0aGUgYWRqdXN0ZWQgY2xvc2luZyBwcmljZXMuDQoNCmRpZmYobG9nKC4uLikpOiBDYWxjdWxhdGVzIHRoZSBkYWlseSBsb2cgcmV0dXJucy4NCg0KDQojIyMjIENyZWF0aW5nIHRoZSBFdmVudCBEdW1teSBWYXJpYWJsZToNCg0KQXNzaWducyBhIHZhbHVlIG9mIDEgdG8gdGhlIGV2ZW50IGRhdGUgYW5kIDAgdG8gYWxsIG90aGVyIGRhdGVzLg0KDQpUaGlzIGR1bW15IHZhcmlhYmxlIGlzb2xhdGVzIHRoZSBlZmZlY3Qgb2YgdGhlIGV2ZW50IG9uIHRoZSBzdG9jayByZXR1cm5zLg0KDQoNCiMjIyMgUGVyZm9ybWluZyBSZWdyZXNzaW9uIEFuYWx5c2lzOg0KDQpSZWdyZXNzZXMgdGhlIGRhaWx5IHJldHVybnMgb24gdGhlIGV2ZW50IGR1bW15IHZhcmlhYmxlLg0KDQpUaGUgY29lZmZpY2llbnQgb2YgZXZlbnRfZHVtbXkgcmVwcmVzZW50cyB0aGUgYWJub3JtYWwgcmV0dXJuIG9uIHRoZSBldmVudCBkYXRlLg0KDQoNCg0KIyMjIEludGVycHJldGluZyB0aGUgUmVncmVzc2lvbiBSZXN1bHRzDQoNCiMjIyMgQ29lZmZpY2llbnQgb2YgZXZlbnRfZHVtbXk6DQoNClJlcHJlc2VudHMgdGhlIGFibm9ybWFsIHJldHVybiBhdHRyaWJ1dGVkIHRvIHRoZSBldmVudC4NCg0KQSBzaWduaWZpY2FudCBwb3NpdGl2ZSBjb2VmZmljaWVudCBzdWdnZXN0cyBhIGZhdm9yYWJsZSBtYXJrZXQgcmVhY3Rpb24uDQoNCkEgc2lnbmlmaWNhbnQgbmVnYXRpdmUgY29lZmZpY2llbnQgaW5kaWNhdGVzIGFuIHVuZmF2b3JhYmxlIHJlYWN0aW9uLg0KDQoNCiMjIyMgU3RhdGlzdGljYWwgU2lnbmlmaWNhbmNlOg0KQ2hlY2sgdGhlIHAtdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBldmVudF9kdW1teSBjb2VmZmljaWVudC4NCg0KQSBwLXZhbHVlIGxlc3MgdGhhbiAwLjA1IHR5cGljYWxseSBpbmRpY2F0ZXMgc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlIGF0IHRoZSA1JSBsZXZlbC4NCg0KDQojIyMgQ29uY2x1c2lvbnMuIA0KQXMgb3VyIHAtdmFsdWUgaXMgMC4xNTg4LCB3ZSBkbyBub3QgaGF2ZSBzdWZmaWNpZW50IGRhdGEgdG8gY29uY2x1ZGUgdGhhdCB0aGVyZSBpcyBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UgYXQgYSBjb25maWRlbmNlIGxldmVsIG9mIDk1JSAob3Igc2lnbmlmaWNhbmNlIGxldmVsIG9mIDUlKS4gDQpUaGlzIG1lYW5zIHRoYXQgd2UgY2Fubm90IGRldGVybWluZSB0aGF0IHRoZXJlIGhhcyBiZWVuIGFuIGFibm9ybWFsIGV2ZW50IGF0IHRoZSBldmVudCBkYXRlLiANCg0KDQojIyMgRXh0ZW5kZWQgRXZlbnQgV2luZG93IEFuYWx5c2lzDQpUbyBjYXB0dXJlIHBvdGVudGlhbCBtYXJrZXQgcmVhY3Rpb25zIGJlZm9yZSBhbmQgYWZ0ZXIgdGhlIGV2ZW50LCB3ZSBleHRlbmQgdGhlIGFuYWx5c2lzIHRvIGFuIGV2ZW50IHdpbmRvdy4NCg0KYGBge3J9DQojIERlZmluZSBldmVudCB3aW5kb3cgKGUuZy4sIC0yIHRvICsyIGRheXMgYXJvdW5kIHRoZSBldmVudCBkYXRlKQ0KZXZlbnRfd2luZG93IDwtIGMoLTIsIDIpDQoNCiMgR2V0IHRoZSBudW1lcmljIHBvc2l0aW9uIG9mIHRoZSBldmVudCBkYXRlIGluIHRoZSByZXR1cm5zIGluZGV4DQpldmVudF9wb3MgPC0gbWF0Y2goYXMuRGF0ZShldmVudF9kYXRlKSwgaW5kZXgoQUFQTF9yZXR1cm5zKSkNCg0KIyBEZWZpbmUgdGhlIHN0YXJ0IGFuZCBlbmQgcG9zaXRpb25zIG9mIHRoZSBldmVudCB3aW5kb3cNCndfYmVnIDwtIGV2ZW50X3BvcyArIGV2ZW50X3dpbmRvd1sxXQ0Kd19lbmQgPC0gZXZlbnRfcG9zICsgZXZlbnRfd2luZG93WzJdDQoNCiMgQWRqdXN0IGV2ZW50X2R1bW15IHRvIG1hcmsgdGhlIGV2ZW50IHdpbmRvdw0KZXZlbnRfZHVtbXlfd2luZG93IDwtIHJlcCgwLCBsZW5ndGgoQUFQTF9yZXR1cm5zKSkNCmV2ZW50X2R1bW15X3dpbmRvd1t3X2JlZzp3X2VuZF0gPC0gMQ0KDQojIENhbGN1bGF0ZSBjdW11bGF0aXZlIGFibm9ybWFsIHJldHVybnMgKENBUikNCkNBUiA8LSBzdW0oQUFQTF9yZXR1cm5zICogZXZlbnRfZHVtbXlfd2luZG93KQ0KDQojIFBlcmZvcm0gdC10ZXN0IHRvIGFzc2VzcyBzaWduaWZpY2FuY2UNCiMgQ2FsY3VsYXRlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiByZXR1cm5zIGluIHRoZSBldmVudCB3aW5kb3cNCmV2ZW50X3dpbmRvd19yZXR1cm5zIDwtIEFBUExfcmV0dXJuc1t3X2JlZzp3X2VuZF0NCnN0ZF9kZXYgPC0gc2QoZXZlbnRfd2luZG93X3JldHVybnMpDQoNCiMgQ2FsY3VsYXRlIHQtc3RhdGlzdGljDQp0X3N0YXQgPC0gQ0FSIC8gKHN0ZF9kZXYgKiBzcXJ0KGxlbmd0aChldmVudF93aW5kb3dfcmV0dXJucykpKQ0KDQojIERlZ3JlZXMgb2YgZnJlZWRvbQ0KZGYgPC0gbGVuZ3RoKGV2ZW50X3dpbmRvd19yZXR1cm5zKSAtIDENCg0KIyBDYWxjdWxhdGUgcC12YWx1ZQ0KcF92YWx1ZSA8LSAyICogcHQoLWFicyh0X3N0YXQpLCBkZiA9IGRmKQ0KDQojIFByaW50IHJlc3VsdHMNCmNhdCgiQ3VtdWxhdGl2ZSBBYm5vcm1hbCBSZXR1cm4gKENBUik6IiwgQ0FSLCAiXG4iKQ0KY2F0KCJ0LXN0YXRpc3RpYzoiLCB0X3N0YXQsICJcbiIpDQpjYXQoInAtdmFsdWU6IiwgcF92YWx1ZSwgIlxuIikNCmBgYA0KDQoNCiMjIyMgRXh0ZW5kZWQgd2luZG93IGFuYWx5c2lzDQpBbHRob3VnaCB3ZSBoYXZlIGZvbGxvd2VkIHRoZSBzdGVwcyB0byBwZXJmb3JtIHRoZSBleHRlbmRlZCB3aW5kb3cgYW5hbHlzaXMgd2UgaGF2ZSBlbmNvdW50ZXJlZCBhIHlldCB1bmtub3duIG1pc3Rha2Ugd2hpY2ggaGFkIGxlZCB1cyB0byBub3Qgb2J0YWluIGFueSB2YWx1ZS4gVGhpcyBleHRlbmRlZCB3aW5kb3cgaXMgc3VwcG9zZWQgdG8gYW5hbHlzZSBvdGhlciBtYXJrZXQgcmVhY3Rpb25zIHRoYXQgaGF2ZSBoYXBwZW5lZCB3aXRoaW4gYSByYW5nZSBmcm9tIHRoZSBldmVudCB3aW5kb3cuIEhhZCB3ZSBvYnRhaW5lZCBhbnkgcmVzdWx0cywgd2UgY291bGQgaGF2ZSBkZXJpdmVkIHRoYXQgaW4gc29tZSBuZWFyYnkgZGF0ZXMgdGhlcmUgaGFkIGJlZW4gYW4gZXZlbnQgb3IgdGhhdCB0aGUgZXZlbnQgaGFkIGJlZW4gb25lIHRoYXQgaGFkIGV4dGVuZGVkIG92ZXIgYSBzZXJpZXMgb2YgZGF0ZXMuICANCg0KDQojIyMjIEN1bXVsYXRpdmUgQWJub3JtYWwgUmV0dXJuDQoNClJlcHJlc2VudHMgdGhlIHRvdGFsIGFibm9ybWFsIHJldHVybiBvdmVyIHRoZSBldmVudCB3aW5kb3cuDQoNCkEgcG9zaXRpdmUgQ0FSIHN1Z2dlc3RzIHRoYXQgdGhlIGV2ZW50IGhhZCBhIGZhdm9yYWJsZSBpbXBhY3Qgb24gc3RvY2sgcmV0dXJucy4NCg0KQSBuZWdhdGl2ZSBDQVIgaW5kaWNhdGVzIGFuIHVuZmF2b3JhYmxlIGltcGFjdC4NCg0KQXMgZGVzY3JpYmVkIGJlZm9yZSwgdGhlIGxhY2sgb2YgcmVzdWx0cyBsZWFkIHVzIHRvIG5vIGZ1cnRoZXIgY29tbWVudHMuIA0KDQoNCg0KDQojIyMgSW50ZXJwcmV0YXRpb246DQoNCiMjIyMgVGhlIHAtdmFsdWUgaXMgZ3JlYXRlciB0aGFuIDAuMDU6DQoNCldlIGZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuDQoNCkNvbmNsdWRlIHRoYXQgdGhlcmUgaXMgbm8gc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBldmlkZW5jZSB0aGF0IHRoZSBldmVudCBhZmZlY3RlZCB0aGUgc3RvY2sgcHJpY2UuDQoNCg0KIyMjIEZpbmFsIFJlbWFya3MNCg0KIyMjIyBFYXJuaW5ncyBhbm5vdW5jZW1lbnRzIA0KVGhleSBvZnRlbiBsZWFkIHRvIGluY3JlYXNlZCB2b2xhdGlsaXR5IGFuZCBjYW4gc2lnbmlmaWNhbnRseSBpbXBhY3Qgc3RvY2sgcHJpY2VzIGRlcGVuZGluZyBvbiB3aGV0aGVyIHRoZSByZXN1bHRzIG1lZXQsIGV4Y2VlZCwgb3IgZmFsbCBzaG9ydCBvZiBtYXJrZXQgZXhwZWN0YXRpb25zLg0KDQoNCiMjIyMgTGltaXRhdGlvbnM6DQoNCg0KVGhlIGFuYWx5c2lzIGFzc3VtZXMgdGhhdCB0aGUgbWFya2V0IGlzIGVmZmljaWVudCBhbmQgdGhhdCBhbnkgYWJub3JtYWwgcmV0dXJucyBhcmUgc29sZWx5IGR1ZSB0byB0aGUgZXZlbnQuDQoNCkV4dGVybmFsIGZhY3RvcnMgKGUuZy4sIG1hY3JvZWNvbm9taWMgbmV3cywgaW5kdXN0cnkgdHJlbmRzKSBjb3VsZCBhbHNvIGluZmx1ZW5jZSBzdG9jayByZXR1cm5zIGR1cmluZyB0aGUgZXZlbnQgd2luZG93Lg0KDQpEYXRhIENvbnN0cmFpbnRzOiBUaGUgYW5hbHlzaXMgaXMgYmFzZWQgb24gaGlzdG9yaWNhbCBkYXRhIHVwIHRvIE5vdmVtYmVyIDEyLCAyMDIwLiBSZXN1bHRzIG1pZ2h0IGRpZmZlciB3aXRoIHVwZGF0ZWQgZGF0YS4NCg0KDQojIyMjIFJlY29tbWVuZGF0aW9uczoNCg0KSW5jbHVkZSBDb250cm9sIFZhcmlhYmxlczogSW5jb3Jwb3JhdGUgbWFya2V0IG9yIGluZHVzdHJ5IHJldHVybnMgdG8gY29udHJvbCBmb3IgYnJvYWRlciBtYXJrZXQgbW92ZW1lbnRzLg0KDQoNClJvYnVzdCBTdGF0aXN0aWNhbCBUZXN0czogdXNlIG1vcmUgc29waGlzdGljYXRlZCBtb2RlbHMgKGUuZy4sIE1hcmtldCBNb2RlbCkgdG8gZXN0aW1hdGUgZXhwZWN0ZWQgcmV0dXJucyBhbmQgYWJub3JtYWwgcmV0dXJucy4NCg0KDQoNCiMjIEw3LjEgLSBMNy4yLiBDb21wYXJpbmcgeWllbGRzIGFtb25nIHNlY3VyaXRpZXMNCg0KIyMjIEV4cGxhbmF0aW9ucyBhaGVhZA0KDQpJbiB0aGlzIHR3byBleGVyY2lzZXMgd2Ugd2lsbCBkaXNjdXNzIHNlY3VyaXRpZXMnIHlpZWxkcy4gV2Ugd2lsbCBub3cgZXhwbGFpbiB3aGF0IGlzIGEgc2VjdXJpdHkuDQoNCiMjIyMgU2VjdXJpdGllcw0KQSBmaW5hbmNpYWwgc2VjdXJpdHkgaXMgYSBjYXRlZ29yeSB0aGF0IGVuZ2xvYmVzIGRpZmZlcmVudCBhIHdpZGUgcmFuZ2Ugb2YgaW52ZXN0bWVudHMuIFRoZXJlIGFyZSB0aHJlZSBtYWluIHR5cGVzOiBlcXVpdHksIGRlYnQgYW5kIGh5YnJpZHMuIA0KU2VjdXJpdGllcyBjYW4gYmUgdHJhZGVkIGJvdGggcHVibGljbHkgYW5kIG92ZXItdGhlLWNvdW50ZXIuIA0KV2hlbiB0YWxraW5nIGFib3V0IHNlY3VyaXRpZXMgd2Ugc2hhbGwgdGFrZSBpbnRvIGFjY291bnQgY29uY2VwdHMgc3VjaCBhcyBJUE9zLCB3aGljaCBjb25zdGl0dXRlIHRoZSBmaXJzdCBzZWxsIG9mIHNlY3VyaXRpZXMgdG8gdGhlIHB1YmxpYy4gU2VjdXJpdGllcyBjYW4gYWxzbyBiZSBvZmZlcmVkIGluIHByaXZhdGUgcGxhY2VtZW50cyBhbmQgdWx0aW1hdGVseSBpbiB0aGUgc2Vjb25kYXJ5IG1hcmtldHMsIE9UQyBhbmQgcHJpdmF0ZSBhbmQgZGlyZWN0IG5lZ290aWF0aW9ucy4gDQoNCg0KIyMjIyBZaWVsZHMNCllpZWxkcyByZWZlciB0byB0aGUgZWFybmluZ3MgZ2VuZXJhdGVkIGJ5IGFuIGludmVzdG1lbnQsIGFuZCBpdCBjYW4gdGFrZSB0aGUgZm9ybSBvZiBkaXZpZGVuZHMgb3IgaW50ZXJlc3QuIEluIHRoZSBwcmVzZW50IGNhc2UsIHdoZW4gd2UgdGFsayBhYm91dCB0aGUgWWllbGQgaXQgd2lsbCBhZG9wdCB0aGUgZm9ybSBvZiBpbnRlcmVzdC4gDQoNCg0KIyMjIEw3LjEgV2hhdCBpcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB5aWVsZCBvbiBjb3Jwb3JhdGUgaGlnaC1xdWFsaXR5IGJvbmRzIGFuZCB0aGUgeWllbGQgb24gVHJlYXN1cnkgYm9uZHMgYXQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0/IEV4cGxhaW4gd2h5IGRvZXMgdGhlIGRpZmZlcmVuY2UgZXhpc3Q/DQoNCg0KIyMjIyBSIGNvZGUgZm9yIGRlbW9uc3RyYXRpb24NCg0KbG9hZCBwYWNrYWdlcw0KDQpgYGB7cn0NCmxpYnJhcnkocXVhbnRtb2QpDQpgYGANCg0KDQpEZWZpbmUgRW9UX2RhdGUNCg0KYGBge3J9DQojIERlZmluZSBFbmQgb2YgVGVybSAoRW9UKSBkYXRlDQpFb1RfZGF0ZSA8LSBhcy5EYXRlKCIyMDI0LTA5LTMwIikNCmBgYA0KDQoNClJldHJpZXZlIFRyZWFzdXJ5IEJvbmQgWWllbGQgRGF0YQ0KDQpgYGB7cn0NCiMgUmV0cmlldmUgMTAtWWVhciBUcmVhc3VyeSB5aWVsZCBkYXRhDQpnZXRTeW1ib2xzKCJER1MxMCIsIHNyYyA9ICJGUkVEIiwgZnJvbSA9IEVvVF9kYXRlIC0gNywgdG8gPSBFb1RfZGF0ZSArIDcpDQoNCiMgVmlldyB0aGUgZGF0YQ0KaGVhZChER1MxMCkNCg0KYGBgDQoNCg0KUmV0cmlldmUgQ29wb3JhdGUgSGlnaC1RdWFsaXR5IEJvbmQgWWllbGQgRGF0YQ0KDQpgYGB7cn0NCiMgUmV0cmlldmUgTW9vZHkncyBBYWEgQ29ycG9yYXRlIEJvbmQgeWllbGQgZGF0YQ0KZ2V0U3ltYm9scygiREFBQSIsIHNyYyA9ICJGUkVEIiwgZnJvbSA9IEVvVF9kYXRlIC0gNywgdG8gPSBFb1RfZGF0ZSArIDcpDQoNCiMgVmlldyB0aGUgZGF0YQ0KaGVhZChEQUFBKQ0KYGBgDQoNCg0KQWRqdXN0IHRvIE5vbi1UcmFkaW5nIERheXMNCg0KYGBge3J9DQojIEZ1bmN0aW9uIHRvIGdldCB5aWVsZCBvbiBhIHNwZWNpZmljIGRhdGUNCmdldF95aWVsZF9vbl9kYXRlIDwtIGZ1bmN0aW9uKGRhdGEsIGRhdGUpIHsNCiAgIyBDb252ZXJ0IGluZGV4IHRvIERhdGUgZm9ybWF0DQogIGluZGV4KGRhdGEpIDwtIGFzLkRhdGUoaW5kZXgoZGF0YSkpDQogIA0KICAjIEdldCBhdmFpbGFibGUgZGF0ZXMgb24gb3IgYmVmb3JlIHRoZSBzcGVjaWZpZWQgZGF0ZQ0KICBhdmFpbGFibGVfZGF0ZXMgPC0gaW5kZXgoZGF0YSlbaW5kZXgoZGF0YSkgPD0gZGF0ZSAmICFpcy5uYShkYXRhW2luZGV4KGRhdGEpXSldDQogIA0KICBpZiAobGVuZ3RoKGF2YWlsYWJsZV9kYXRlcykgPT0gMCkgew0KICAgIHdhcm5pbmcocGFzdGUoIk5vIGRhdGEgYXZhaWxhYmxlIG9uIG9yIGJlZm9yZSIsIGRhdGUpKQ0KICAgIHJldHVybihsaXN0KFlpZWxkID0gTkEsIERhdGUgPSBOQSkpDQogIH0NCiAgDQogIGRhdGVfdXNlZCA8LSBtYXgoYXZhaWxhYmxlX2RhdGVzKQ0KICANCiAgIyBHZXQgdGhlIHlpZWxkDQogIHlpZWxkIDwtIGFzLm51bWVyaWMoZGF0YVtkYXRlX3VzZWRdKQ0KICANCiAgcmV0dXJuKGxpc3QoDQogICAgWWllbGQgPSB5aWVsZCwNCiAgICBEYXRlID0gYXMuRGF0ZShkYXRlX3VzZWQpDQogICkpDQp9DQpgYGANCg0KDQpSZXRyaWV2ZSBZaWVsZHMgb24gRW9UX2RhdGUNCg0KYGBge3J9DQojIEdldCBUcmVhc3VyeSB5aWVsZCBvbiBFb1RfZGF0ZQ0KdHJlYXN1cnlfeWllbGQgPC0gZ2V0X3lpZWxkX29uX2RhdGUoREdTMTAsIEVvVF9kYXRlKQ0KDQojIEdldCBDb3Jwb3JhdGUgQWFhIHlpZWxkIG9uIEVvVF9kYXRlDQpjb3Jwb3JhdGVfeWllbGQgPC0gZ2V0X3lpZWxkX29uX2RhdGUoREFBQSwgRW9UX2RhdGUpDQpgYGANCg0KDQpDYWxjdWxhdGUgdGhlIERpZmZlcmVuY2UNCg0KYGBge3J9DQojIENhbGN1bGF0ZSB0aGUgeWllbGQgZGlmZmVyZW5jZQ0KeWllbGRfZGlmZmVyZW5jZSA8LSBjb3Jwb3JhdGVfeWllbGQkWWllbGQgLSB0cmVhc3VyeV95aWVsZCRZaWVsZA0KDQojIERpc3BsYXkgdGhlIHJlc3VsdHMNCnJlc3VsdHNfTDcxIDwtIGRhdGEuZnJhbWUoDQogIERhdGUgPSB0cmVhc3VyeV95aWVsZCREYXRlLA0KICBUcmVhc3VyeV9ZaWVsZCA9IHRyZWFzdXJ5X3lpZWxkJFlpZWxkLA0KICBDb3Jwb3JhdGVfWWllbGQgPSBjb3Jwb3JhdGVfeWllbGQkWWllbGQsDQogIFlpZWxkX0RpZmZlcmVuY2UgPSB5aWVsZF9kaWZmZXJlbmNlDQopDQoNCnByaW50KHJlc3VsdHNfTDcxKQ0KYGBgDQoNCg0KIyMjIyBBbmFseXNpcyBvZiByZXN1bHRzDQoNCkluIHRoaXMgZXhlcmNpc2Ugd2UgaGF2ZSBvYnRhaW5lZCB0aGUgWWllbGRzIG9mIHR3byBkaWZmZXJlbnQgQm9uZHMgd2l0aCB0aGUgaGVscCBvZiBvdXIgUiBjb2RlLCBpbiB3aGljaCB3ZSBoYXZlIHJldHJpZXZlZCB0aGUgWWllbGRzIGZyb20gdGhlIDEwLVllYXIgVVMgVHJlYXN1cnkgYm9uZCBhbmQgdGhlIE1vb2R5J3MgU2Vhc29uZWQgQWFhIENvcnBvcmF0ZSBCb25kIFlpZWxkLiANCldoZW4gd2UgY29tcGFyZSB0aGVzZSB0d28gYm9uZHMsIHdlIHNoYWxsIGZvcmVzZWUgdGhhdCB0aGUgQ29ycG9yYXRlIEJvbmQgWWllbGQgd2lsbCBtb3N0IGxpa2VseSBiZSBoaWdoZXIgdGhhbiB0aGUgVHJlYXN1cnkgQm9uZC4gRXZlbiB0aG91Z2ggdGhlIGNvcnBvcmF0ZSB5aWVsZCBvZmZlcnMgaGlnaCBxdWFsaXR5IGFuZCBoYXMgYSBoaWdoIHJhdGluZywgdGhlIHRyZWFzdXJ5IGJvbmRzIGFyZSBvdmVyYWxsIGxlc3Mgcmlza3kgYW5kIG9mZmVyIGEgbXVjaCBtb3JlIHN0YWJsZSBvcHRpb24uIFdoZW4gYW4gaW52ZXN0b3IgZGVjaWRlcyB0byBidXkgYSBjb3Jwb3JhdGUgYm9uZCBvdmVyIGEgZ292ZXJubWVudCBib25kICh0aGlzIGlzIGFub3RoZXIgd2F5IG9mIG5hbWluZyB0aGUgdHJlYXN1cnkgYm9uZHMpLCB0aGV5IG1ha2UgYW4gYXNzZXNzbWVudCBvZiB0aGUgcmlzayBsZXZlbCB0aGV5IHdpbGwgYmUgb3BlbiB0byB0b2xlcmF0ZSBhbmQgdGhlIHJldHVybnMgdGhleSB3aWxsIG9idGFpbiBmcm9tIGl0LiBBcyBhIGdlbmVyYWwgcnVsZSwgdGhlIGhpZ2hlciByZXR1cm5zIHdpbGwgYmUgcGFpcmVkIHdpdGggaGlnaGVyIHZvbGF0aWxpdHkgKHJpc2spLiANCg0KDQojIyMgTDcuMiBXaGF0IGlzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHlpZWxkIG9uIGxvbmctdGVybSBUcmVhc3VyeSBib25kcyBhbmQgdGhlIHlpZWxkIG9uIGxvbmctdGVybSBtdW5pY2lwYWwgYm9uZHMgYXQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0/IEV4cGxhaW4gd2h5IGRvZXMgdGhlIGRpZmZlcmVuY2UgZXhpc3Q/DQoNCk11bmljaXBhbCBib25kcyBhcmUgYSB0eXBlIG9mIHNlY3VyaXR5IGlzc3VlZCBieSBsb2NhbCBjb3VudHkgYW5kIHN0YXRlIGdvdmVybm1lbnRzLiBUaGlzIGlzIGEgZGVidCBzZWN1cml0eSB3aGljaCBpcyBvZnRlbiB1c2VkIHRvIGZpbmFuY2UgbG9jYWwgcHJvamVjdHMuIEhvd2V2ZXIsIGRhdGEgYXZhaWxhYmlsaXR5IGZvciB0aGVzZSB0eXBlcyBvZiBib25kcyBhcmUgbm90IGVhc2lseSBhdmFpbGFibGUsIGFuZCB3ZSBjYW5ub3Qgb2J0YWluIHRoZSBEYXRhIGFib3V0IHRoZWlyIHlpZWxkcy4gDQoNCkdpdmVuIHRoZSBsYWNrIG9mIGRhdGEsIHdlIGNhbm5vdCBwZXJmb3JtIGEgcmVhbCByZXByZXNlbnRhdGlvbiwgYnV0IHdlIG1heSBzdXBwb3NlIHRoYXQgbXVuaWNpcGFsIGJvbmRzIHdpbGwgaGF2ZSBoaWdoZXIgeWllbGRzIHRoYW4gbG9uZy10ZXJtIFRyZWFzdXJ5IEJvbmRzLiBNdW5pY2lwYWwgQm9uZHMgYXJlIHVzdWFsbHkgZXhlbnQgZnJvbSB0YXhhdGlvbiwgd2hpY2ggcHJvdmlkZXMgYW4gYWJzb2x1dGUgeWllbGQgcmVhbGx5IGF0dHJhY3RpdmUgZm9yIGludmVzdG9ycy4gDQpJZiB3ZSBhbHNvIGFuYWx5emUgYnJpZWZseSB0aGUgbWFjcm9lY29ub21pYyBzaXR1YXRpb24gb2YgdGhlIFVTLCB0aGUgY3V0IGluIEZFRCByYXRlIHNob3VsZCBwcm9kdWNlIGFuIGluY3JlYXNlIGluIHlpZWxkcyBmb3IgdGhlIGxvbmdlciBkdXJhdGlvbiBib25kcy4gQWRkaXRpb25hbGx5LCB0aGUgY3VycmVudCBzdHJlbmd0aCBvZiB0aGUgVVMgZWNvbm9teSB3aXRoIHRoZSByZWNlbnQgd2luIG9mIERvbmFsZCBUcnVtcCBoYXMgcHJvZHVjZWQgYW4gc3Bpa2UgaW4gbG9uZy10ZXJtIHlpZWxkcy4gDQpIb3dldmVyLCBwYXlpbmcgYXR0ZW50aW9uIHRvIHJlY2VudCBuZXdzIHJlZ2FyZGluZyBtdW5pY2lwYWwgYm9uZHMsIHRoZWlyIG1haW4gYXR0cmFjdGl2ZW5lc3Mgd2hpY2ggaXMgdGhlaXIgdGF4IGV4ZW1wdGlvbnMgbWF5IGJlIGZhY2luZyB0aGUgcmlzayBvZiBiZWluZyBzdXBwcmVzc2VkLiBXZXJlIHRoaXMgdG8gaGFwcGVuLCBtdW5pY2lwYWwgYm9uZHMgbWF5IGJlIGdyZWF0bHkgYWZmZWN0ZWQuIA0KDQoNCg0KIyMgTDcuMyAtIEw3LjYgQXNzZXNzaW5nIHRoZSBmb3JlY2FzdGluZyBhYmlsaXR5IG9mIHRoZSB5aWVsZCBjdXJ2ZQ0KDQojIyMgTDcuMyAtIEw3LjUNCg0KTG9hZCBwYWNrYWdlcw0KDQpgYGB7cn0NCmxpYnJhcnkocXVhbnRtb2QpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoZ2dwbG90MikNCmBgYA0KDQoNCg0KRGVmaW5lIEJvVF9kYXRlDQoNCmBgYHtyfQ0KIyBEZWZpbmUgQmVnaW5uaW5nIG9mIFRlcm0gKEJvVCkgZGF0ZQ0KQm9UX2RhdGUgPC0gYXMuRGF0ZSgiMjAyNC0wNS0wMSIpDQpgYGANCg0KDQpEYXRlIFJhbmdlDQoNCmBgYHtyfQ0KIyBEZWZpbmUgdGhlIGRhdGUgcmFuZ2UNCnN0YXJ0X2RhdGUgPC0gQm9UX2RhdGUgLSA3ICAjIE9uZSB3ZWVrIGJlZm9yZQ0KZW5kX2RhdGUgPC0gQm9UX2RhdGUgKyA3ICAgICMgT25lIHdlZWsgYWZ0ZXINCmBgYA0KDQoNCg0KUmV0cmlldmUgMTN3ZWVrIGFuZCAyNiB3ZWVrIFQtYmlsbCBZaWVsZCBEYXRhDQoxMy13ZWVrIHRiaWxsIHN5bWJvbDogIkRHUzNNTyINCjI2LXdlZWsgdGJpbGwgc3ltYm9sOiAiREdTNk1PIg0KV2UgYXJlIHVzaW5nIHRoZSBkYWlseSB5aWVsZCBkYXRhIGZvciB0aGUgY29uc3RhbnQgbWF0dXJpdHkgcmF0ZSwgYXMgbm8gZGF0YSB3YXMgdG8gYmUgZm91bmQgYW5kIHVzZWQgb3RoZXJ3aXNlDQoNCmBgYHtyfQ0KIyBSZXRyaWV2ZSAxMy13ZWVrIFQtYmlsbCB5aWVsZCBkYXRhDQpnZXRTeW1ib2xzKCJER1MzTU8iLCBzcmMgPSAiRlJFRCIsIGZyb20gPSBzdGFydF9kYXRlLCB0byA9IGVuZF9kYXRlKQ0KDQojIFJldHJpZXZlIDI2LXdlZWsgVC1iaWxsIHlpZWxkIGRhdGENCmdldFN5bWJvbHMoIkRHUzZNTyIsIHNyYyA9ICJGUkVEIiwgZnJvbSA9IHN0YXJ0X2RhdGUsIHRvID0gZW5kX2RhdGUpDQoNCmBgYA0KDQoNCk1lcmdlIFlpZWxkcyBpbnRvIG9uZSBkYXRhIGZyYW1lIGFuZCBjb252ZXJ0aW5nIGl0IHRvIHBsb3QNCg0KYGBge3J9DQojIE1lcmdlIHRoZSB5aWVsZHMgaW50byBvbmUgZGF0YSBmcmFtZQ0KeWllbGRzX2RhdGEgPC0gbWVyZ2UoREdTM01PLCBER1M2TU8sIGpvaW4gPSAiaW5uZXIiKQ0KY29sbmFtZXMoeWllbGRzX2RhdGEpIDwtIGMoIllpZWxkXzEzd2siLCAiWWllbGRfMjZ3ayIpDQojIENvbnZlcnQgdG8gZGF0YSBmcmFtZSBmb3IgcGxvdHRpbmcNCnlpZWxkc19kZiA8LSBkYXRhLmZyYW1lKERhdGUgPSBpbmRleCh5aWVsZHNfZGF0YSksIGNvcmVkYXRhKHlpZWxkc19kYXRhKSkNCg0KIyBSZW1vdmUgcm93cyB3aXRoIE5BIHZhbHVlcw0KeWllbGRzX2RmIDwtIG5hLm9taXQoeWllbGRzX2RmKQ0KDQojUGxvdCBZaWVsZHMgb3ZlciB0aW1lDQojIFBsb3QgdGhlIHlpZWxkcyBvdmVyIHRpbWUNCmdncGxvdCh5aWVsZHNfZGYsIGFlcyh4ID0gRGF0ZSkpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gWWllbGRfMTN3aywgY29sb3IgPSAiMTMtd2VlayBULWJpbGwiKSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBZaWVsZF8yNndrLCBjb2xvciA9ICIyNi13ZWVrIFQtYmlsbCIpKSArDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGFzLm51bWVyaWMoYXMuRGF0ZShCb1RfZGF0ZSkpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJyZWQiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiMTMtd2VlayBhbmQgMjYtd2VlayBULWJpbGwgWWllbGRzIEFyb3VuZCBCb1RfZGF0ZSIsDQogICAgeCA9ICJEYXRlIiwNCiAgICB5ID0gIllpZWxkICglKSIsDQogICAgY29sb3IgPSAiVC1iaWxsIE1hdHVyaXR5Ig0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KDQpBZGp1c3QgdG8gTm9uLVRyYWRpbmcgRGF5cw0KDQpgYGB7cn0NCmdldF95aWVsZF9vbl9kYXRlIDwtIGZ1bmN0aW9uKGRhdGEsIGRhdGUpIHsNCiAgIyBDb252ZXJ0IGluZGV4IHRvIERhdGUgZm9ybWF0DQogIGluZGV4KGRhdGEpIDwtIGFzLkRhdGUoaW5kZXgoZGF0YSkpDQogIA0KICAjIEdldCBhdmFpbGFibGUgZGF0ZXMgb24gb3IgYmVmb3JlIHRoZSBzcGVjaWZpZWQgZGF0ZQ0KICBhdmFpbGFibGVfZGF0ZXMgPC0gaW5kZXgoZGF0YSlbaW5kZXgoZGF0YSkgPD0gZGF0ZSAmICFpcy5uYShkYXRhW2luZGV4KGRhdGEpXSldDQogIA0KICBpZiAobGVuZ3RoKGF2YWlsYWJsZV9kYXRlcykgPT0gMCkgew0KICAgIHdhcm5pbmcocGFzdGUoIk5vIGRhdGEgYXZhaWxhYmxlIG9uIG9yIGJlZm9yZSIsIGRhdGUpKQ0KICAgIHJldHVybihsaXN0KFlpZWxkID0gTkEsIERhdGUgPSBOQSkpDQogIH0NCiAgDQogIGRhdGVfdXNlZCA8LSBtYXgoYXZhaWxhYmxlX2RhdGVzKQ0KICANCiAgIyBHZXQgdGhlIHlpZWxkDQogIHlpZWxkIDwtIGFzLm51bWVyaWMoZGF0YVtkYXRlX3VzZWRdKQ0KICANCiAgcmV0dXJuKGxpc3QoDQogICAgWWllbGQgPSB5aWVsZCwNCiAgICBEYXRlID0gYXMuRGF0ZShkYXRlX3VzZWQpDQogICkpDQp9DQpgYGANCg0KDQpSZXRyaWV2ZSBZaWVsZHMgb24gQm9UX2RhdGUNCg0KYGBge3J9DQojIEdldCAxMy13ZWVrIFQtYmlsbCB5aWVsZCBvbiBCb1RfZGF0ZQ0KeWllbGRfMTN3ayA8LSBnZXRfeWllbGRfb25fZGF0ZShER1MzTU8sIEJvVF9kYXRlKQ0KDQojIEdldCAyNi13ZWVrIFQtYmlsbCB5aWVsZCBvbiBCb1RfZGF0ZQ0KeWllbGRfMjZ3ayA8LSBnZXRfeWllbGRfb25fZGF0ZShER1M2TU8sIEJvVF9kYXRlKQ0KDQpgYGANCg0KDQpDYWxjdWxhdGUgdGhlIERpZmZlcmVuY2UNCg0KYGBge3J9DQojIENhbGN1bGF0ZSB0aGUgeWllbGQgZGlmZmVyZW5jZQ0KeWllbGRfZGlmZmVyZW5jZSA9IHlpZWxkXzI2d2skWWllbGQgLSB5aWVsZF8xM3drJFlpZWxkDQoNCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSB0byBkaXNwbGF5IHRoZSByZXN1bHRzDQpyZXN1bHRzX0w3MyA8LSBkYXRhLmZyYW1lKA0KICBEYXRlID0geWllbGRfMTN3ayREYXRlLA0KICBZaWVsZF8xM3drID0geWllbGRfMTN3ayRZaWVsZCwNCiAgWWllbGRfMjZ3ayA9IHlpZWxkXzI2d2skWWllbGQsDQogIFlpZWxkX0RpZmZlcmVuY2UgPSB5aWVsZF9kaWZmZXJlbmNlDQopDQoNCnByaW50KHJlc3VsdHNfTDczKQ0KDQpgYGANCg0KQWRkaXRpb25hbGx5LCB3ZSBjYW4gcGxvdCBvdXIgcmVzdWx0cyBpbiBvcmRlciB0byBoYXZlIGEgdmlzdWFsIHJlcHJlc2VudGF0aW9uDQoNCmBgYHtyfQ0KIyBDcmVhdGUgYSBkYXRhIGZyYW1lIGZvciBwbG90dGluZyB0aGUgeWllbGQgY3VydmUNCnlpZWxkX2N1cnZlX2RmIDwtIGRhdGEuZnJhbWUoDQogIE1hdHVyaXR5ID0gYygxMy81MiwgMjYvNTIpLCAgIyBDb252ZXJ0IHdlZWtzIHRvIHllYXJzDQogIFlpZWxkID0gYyh5aWVsZF8xM3drJFlpZWxkLCB5aWVsZF8yNndrJFlpZWxkKQ0KKQ0KDQojIFBsb3QgdGhlIHlpZWxkIGN1cnZlIGJldHdlZW4gMTMtd2VlayBhbmQgMjYtd2VlayBULWJpbGxzDQpnZ3Bsb3QoeWllbGRfY3VydmVfZGYsIGFlcyh4ID0gTWF0dXJpdHksIHkgPSBZaWVsZCkpICsNCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAicmVkIiwgc2l6ZSA9IDMpICsNCiAgbGFicygNCiAgICB0aXRsZSA9IHBhc3RlKCJZaWVsZCBDdXJ2ZSBiZXR3ZWVuIDEzLXdlZWsgYW5kIDI2LXdlZWsgVC1iaWxscyBvbiIsIEJvVF9kYXRlKSwNCiAgICB4ID0gIk1hdHVyaXR5IChZZWFycykiLA0KICAgIHkgPSAiWWllbGQgKCUpIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KDQojIyMjIEFuYWx5c2lzIG9mIHJlc3VsdHMNCg0KSW4gdGhlc2UgMyBleGVyY2lzZXMgd2UgaGF2ZSBjYWxjdWxhdGVkIHRoZSBkaWZmZXJlbmNlIGluIHlpZWxkcyBvZiB0aGUgMjYtd2VlayBULWJpbGwgeWllbGQgYW5kIHRoZSAxMy13ZWVrICBULWJpbGwgeWllbGQgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgc2Nob29sIHRlcm0uIA0KVGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBib3RoIHlpZWxkcyBnaXZlcyB1cyBhIHRvdGFsIGFtb3VudCBvZiAtMC4wMywgd2hpY2ggcmV2ZWFscyBhIGhpZ2hlciB5aWVsZCBpbiB0aGUgMTMtd2VlayBULWJpbGwuIA0KDQpIaWdoZXIgeWllbGRzIG9uIGxvd2VyIG1hdHVyaXR5IGJvbmRzIGlzIGEgcmF0aGVyIHVuc3VhbCBzaXR1YXRpb24sIGJ1dCBpdCBjYW4gYmUgZXhwbGFpbmVkIGR1ZSB0byBzZXZlcmFsIGZhY3RvcnMuIFRoaXMgaGlnaGVyIHlpZWxkIG1heSBiZSB0aGUgcmVzdWx0IG9mIG1hcmtldCB1bmNlcnRhaW50eSwgaW4gd2hpY2ggaW52ZXN0b3JzIGxvb2sgZm9yIHNhZmVyIGFuZCBsb25nLXRlcm0gc2VjdXJpdGllcy4gDQoNCk9uIHRoZSBvdGhlciBoYW5kLCBhbmQgYW5zd2VyaW5nIHRvIEw3LjUsIHRoaXMgbWF5IGJlIHRoZSByZXN1bHQgb2YgdGhlIGV4cGVjdGFuY3kgb2YgYSBGRUQncyByYXRlIGN1dCwgd2hpY2ggd291bGQgbGVhZCB0byBldmVuIGxvd2VyIHlpZWxkcy4gVGhpcyByZWFzb24gd291bGQgYWxzbyBleHBsYWluIHRoZSBoaWdoZXIgeWllbGRzIGluIHRoZSBzaG9ydCB0ZXJtLiBUaGUgZXhwZWN0YW5jeSBvZiBsb3dlciBpbnRlcmVzdCByYXRlcyBtYXRjaGVzIHRoZSBkaXJlY3Rpb24gb2YgdGhlIHNsb3BlLiANCg0KU29tZSBvdGhlciByZWFzb25zIG1heSBiZSBwbGF1c2libGUsIHN1Y2ggYXMgdGhvc2UgcmVnYXJkaW5nIGxpcXVpZGl0eSBuZWVkcyBvciB0ZWNobmljYWwgbWFya2V0IGZhY3RvcnMsIGJ1dCB3ZSB3aWxsIG5vdCBmdXJ0aGVyIGFuYWx5emUgdGhvc2Ugb3B0aW9ucy4gDQoNCg0KIyMjIEw3LjYgRGlkIGludGVyZXN0IHJhdGVzIG1vdmUgaW4gdGhhdCBkaXJlY3Rpb24gb3ZlciB0aGUgc2Nob29sIHRlcm0/DQoNCg0KTG9hZCBwYWNrYWdlcw0KDQpgYGB7cn0NCmxpYnJhcnkocXVhbnRtb2QpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkocmVzaGFwZTIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHh0cykNCmBgYA0KDQoNCkRlZmluZSBFbmQgb2YgVGVybSBEYXRlDQoNCmBgYHtyfQ0KI0RlZmluZSBCb1RfZGF0ZQ0KQm9UX2RhdGUgPC0gYXMuRGF0ZSgiMjAyNC0wNS0wMSIpDQojIERlZmluZSBFbmQgb2YgVGVybSAoRW9UKSBkYXRlDQpFb1RfZGF0ZSA8LSBhcy5EYXRlKCIyMDI0LTA5LTMwIikNCmBgYA0KDQoNClJldHJpZXZlIFlpZWxkIERhdGEgT3ZlciB0aGUgdGVybQ0KDQpgYGB7cn0NCiMgUmV0cmlldmUgMTMtd2VlayBULWJpbGwgeWllbGQgZGF0YSBvdmVyIHRoZSB0ZXJtDQpnZXRTeW1ib2xzKCJUQjNNUyIsIHNyYyA9ICJGUkVEIiwgZnJvbSA9IEJvVF9kYXRlLCB0byA9IEVvVF9kYXRlKQ0KVEIzTVNfdGVybSA8LSBUQjNNUw0KDQojIFJldHJpZXZlIDI2LXdlZWsgVC1iaWxsIHlpZWxkIGRhdGEgb3ZlciB0aGUgdGVybQ0KZ2V0U3ltYm9scygiVEI2TVMiLCBzcmMgPSAiRlJFRCIsIGZyb20gPSBCb1RfZGF0ZSwgdG8gPSBFb1RfZGF0ZSkNClRCNk1TX3Rlcm0gPC0gVEI2TVMNCmBgYA0KDQoNCkFkanVzdCB0byBOb24tVHJhZGluZyBEYXlzDQoNCmBgYHtyfQ0KIyBGdW5jdGlvbiB0byBnZXQgeWllbGQgb24gYSBzcGVjaWZpYyBkYXRlDQpnZXRfeWllbGRfb25fZGF0ZSA8LSBmdW5jdGlvbihkYXRhLCBkYXRlLCB1c2VfbmV4dCA9IEZBTFNFKSB7DQogICMgQ29udmVydCBpbmRleCB0byBEYXRlIGZvcm1hdA0KICBpbmRleChkYXRhKSA8LSBhcy5EYXRlKGluZGV4KGRhdGEpKQ0KICANCiAgaWYgKHVzZV9uZXh0KSB7DQogICAgIyBHZXQgdGhlIG5leHQgYXZhaWxhYmxlIGRhdGUgYWZ0ZXIgdGhlIHNwZWNpZmllZCBkYXRlDQogICAgYXZhaWxhYmxlX2RhdGVzIDwtIGluZGV4KGRhdGEpW2luZGV4KGRhdGEpID49IGRhdGUgJiAhaXMubmEoZGF0YVtpbmRleChkYXRhKV0pXQ0KICAgIGlmKGxlbmd0aChhdmFpbGFibGVfZGF0ZXMpID09IDApIHsNCiAgICAgIHdhcm5pbmcocGFzdGUoIk5vIGRhdGEgYXZhaWxhYmxlIGFmdGVyIiwgZGF0ZSkpDQogICAgICByZXR1cm4obGlzdChZaWVsZCA9IE5BLCBEYXRlID0gTkEpKQ0KICAgIH0NCiAgICBkYXRlX3VzZWQgPC0gbWluKGF2YWlsYWJsZV9kYXRlcykNCiAgfSBlbHNlIHsNCiAgICAjIEdldCB0aGUgbGFzdCBhdmFpbGFibGUgZGF0ZSBvbiBvciBiZWZvcmUgdGhlIHNwZWNpZmllZCBkYXRlDQogICAgYXZhaWxhYmxlX2RhdGVzIDwtIGluZGV4KGRhdGEpW2luZGV4KGRhdGEpIDw9IGRhdGUgJiAhaXMubmEoZGF0YVtpbmRleChkYXRhKV0pXQ0KICAgIGlmIChsZW5ndGgoYXZhaWxhYmxlX2RhdGVzKSA9PSAwKSB7DQogICAgICB3YXJuaW5nKHBhc3RlKCJObyBkYXRhIGF2YWlsYWJsZSBiZWZvcmUiLCBkYXRlKSkNCiAgICAgIHJldHVybihsaXN0KFlpZWxkID0gTkEsIERhdGUgPSBOQSkpDQogICAgfQ0KICAgIGRhdGVfdXNlZCA8LSBtYXgoYXZhaWxhYmxlX2RhdGVzKQ0KICB9DQogIA0KICAjIEdldCB0aGUgeWllbGQNCiAgeWllbGQgPC0gYXMubnVtZXJpYyhkYXRhW2RhdGVfdXNlZF0pDQogIA0KICByZXR1cm4obGlzdCgNCiAgICBZaWVsZCA9IHlpZWxkLA0KICAgIERhdGUgPSBhcy5EYXRlKGRhdGVfdXNlZCkNCiAgKSkNCn0NCmBgYA0KDQoNClBsb3QgdGhlIHlpZWxkcyBvdmVyIHRpbWUNCg0KYGBge3J9DQojIENvbWJpbmUgdGhlIHlpZWxkcyBpbnRvIG9uZSBkYXRhIGZyYW1lDQp5aWVsZHNfY29tYmluZWQgPC0gbWVyZ2UoVEIzTVNfdGVybSwgVEI2TVNfdGVybSkNCmNvbG5hbWVzKHlpZWxkc19jb21iaW5lZCkgPC0gYygiWWllbGRfMTN3ayIsICJZaWVsZF8yNndrIikNCg0KIyBQbG90IHRoZSB5aWVsZHMgb3ZlciB0aGUgdGVybQ0KeWllbGRzX2RmIDwtIGRhdGEuZnJhbWUoRGF0ZSA9IGluZGV4KHlpZWxkc19jb21iaW5lZCksIGNvcmVkYXRhKHlpZWxkc19jb21iaW5lZCkpDQp5aWVsZHNfZGYgPC0gbmEub21pdCh5aWVsZHNfZGYpDQoNCiMgTWVsdCB0aGUgZGF0YSBmb3IgcGxvdHRpbmcNCnlpZWxkc19tZWx0ZWQgPC0gbWVsdCh5aWVsZHNfZGYsIGlkLnZhcnMgPSAiRGF0ZSIpDQoNCiMgUGxvdA0KZ2dwbG90KHlpZWxkc19tZWx0ZWQsIGFlcyh4ID0gRGF0ZSwgeSA9IHZhbHVlLCBjb2xvciA9IHZhcmlhYmxlKSkgKw0KICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKw0KICBsYWJzKHRpdGxlID0gIjEzLXdlZWsgYW5kIDI2LXdlZWsgVC1iaWxsIFlpZWxkcyBPdmVyIHRoZSBUZXJtIiwNCiAgICAgICB4ID0gIkRhdGUiLA0KICAgICAgIHkgPSAiWWllbGQgKCUpIiwNCiAgICAgICBjb2xvciA9ICJZaWVsZCIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KDQpBbmFseXplIHRoZSBNb3ZlbWVudCBvZiBJbnRlcmVzdCBSYXRlcw0KDQpgYGB7cn0NCiNHZXQgWWllbGRzIGF0IEJvVF9kYXRlDQp5aWVsZF8xM3drIDwtIGdldF95aWVsZF9vbl9kYXRlKFRCM01TX3Rlcm0sIEJvVF9kYXRlLCB1c2VfbmV4dCA9IEZBTFNFKQ0KeWllbGRfMjZ3ayA8LSBnZXRfeWllbGRfb25fZGF0ZShUQjZNU190ZXJtLCBCb1RfZGF0ZSwgdXNlX25leHQgPSBGQUxTRSkNCg0KIyBHZXQgeWllbGRzIGF0IEVvVF9kYXRlDQp5aWVsZF8xM3drX0VvVCA8LSBnZXRfeWllbGRfb25fZGF0ZShUQjNNU190ZXJtLCBFb1RfZGF0ZSwgdXNlX25leHQgPSBGQUxTRSkNCnlpZWxkXzI2d2tfRW9UIDwtIGdldF95aWVsZF9vbl9kYXRlKFRCNk1TX3Rlcm0sIEVvVF9kYXRlLCB1c2VfbmV4dCA9IEZBTFNFKQ0KDQojIENyZWF0ZSBhIGRhdGEgZnJhbWUgdG8gY29tcGFyZSBCb1QgYW5kIEVvVCB5aWVsZHMNCmNvbXBhcmlzb25fZGYgPC0gZGF0YS5mcmFtZSgNCiAgRGF0ZSA9IGMoeWllbGRfMTN3ayREYXRlLCB5aWVsZF8xM3drX0VvVCREYXRlKSwNCiAgWWllbGRfMTN3ayA9IGMoeWllbGRfMTN3ayRZaWVsZCwgeWllbGRfMTN3a19Fb1QkWWllbGQpLA0KICBZaWVsZF8yNndrID0gYyh5aWVsZF8yNndrJFlpZWxkLCB5aWVsZF8yNndrX0VvVCRZaWVsZCksDQogIFBlcmlvZCA9IGMoIkJvVCIsICJFb1QiKQ0KKQ0KDQpwcmludChjb21wYXJpc29uX2RmKQ0KYGBgDQoNCg0KIyMjIyBBbmFseXNpcyBvZiByZXN1bHRzDQoNCkludGVyZXN0IHJhdGVzLCBhcyB3ZSBoYXZlIHJlcHJlc2VudGVkIGdyYXBoaWNhbGx5LCB5aWVsZHMgb3ZlciB0aGUgdGVybSBoYXZlIGZhbGxlbiBwcm9ncmVzc2l2ZWx5LiBBIGRlY3JlYXNlIGluIHlpZWxkcyBpbmRpY2F0ZXMgYSBkb3dud2FyZCBtb3ZlbWVudCBpbiB0aGUgaW50ZXJlc3QgcmF0ZXMuIFRoaXMgbW92ZW1lbnQgbWF0Y2hlcyB0aGUgZXhwZWN0YXRpb24gd2UgaGFkIGV4dHJhY3RlZCBpbiB0aGUgQmVnaW5uaW5nIG9mIFRlcm0sIHdoaWNoIHdhcyB0aGUgZGVjcmVhc2UgaW4geWllbGRzL2ludGVyZXN0IHJhdGVzLiANCkZ1cnRoZXJtb3JlLCB5ZXQgYWdhaW4gd2UgaGF2ZSBsb3dlciB5aWVsZHMgaW4gdGhlIDEzLXdlZWsgdC1iaWxsLCB3aGljaCBtYXkgaW5kaWNhdGUgc3RpbGwgZnVydGhlciBkZWNyZWFzZXMgaW4gaW50ZXJlc3QgcmF0ZXMuIFRoaXMgZGF0YSBtYXRjaGVzIHdpdGggdGhlIEZFRCByYXRlIGN1dCBpbiBtaWQgU2VwdGVtYmVyLCBhbmQgdGhlIGEgcG9zaXRpdmUgZm9yZWNhc3Qgb2YgZnVydGhlciByYXRlIGN1dHMuIA0KDQoNCg0KIyMgTDcuNyAtIEw3LjkgRXhwbGFpbmluZyBzaGlmdHMgaW4gdGhlIHlpZWxkIGN1cnZlIG92ZXIgdGltZQ0KDQoNCiMjIyBMNy43IERpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbG9uZy10ZXJtIFRyZWFzdXJ5IGJvbmQgeWllbGQgYW5kIHRoZSAxMy13ZWVrIFQtYmlsbCB5aWVsZCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzY2hvb2wgdGVybQ0KDQoNCkxvYWQgUGFja2FnZXMNCg0KYGBge3J9DQpsaWJyYXJ5KHF1YW50bW9kKQ0KYGBgDQoNCg0KRGVmaW5lIEJlZ2lubmluZyBvZiBUZXJtIERhdGUNCg0KYGBge3J9DQojIERlZmluZSBCZWdpbm5pbmcgb2YgVGVybSAoQm9UKSBkYXRlDQpCb1RfZGF0ZSA8LSBhcy5EYXRlKCIyMDI0LTA1LTAxIikNCmBgYA0KDQoNClJldHJpZXZlIHRoZSBZaWVsZCBEYXRhDQoNCmBgYHtyfQ0KIyBSZXRyaWV2ZSAzLU1vbnRoIFQtYmlsbCB5aWVsZCBkYXRhDQpnZXRTeW1ib2xzKCJER1MzTU8iLCBzcmMgPSAiRlJFRCIsIGZyb20gPSBCb1RfZGF0ZSAtIDcsIHRvID0gQm9UX2RhdGUgKyA3KQ0KDQojIFJldHJpZXZlIDEwLVllYXIgVHJlYXN1cnkgeWllbGQgZGF0YQ0KZ2V0U3ltYm9scygiREdTMTAiLCBzcmMgPSAiRlJFRCIsIGZyb20gPSBCb1RfZGF0ZSAtIDcsIHRvID0gQm9UX2RhdGUgKyA3KQ0KYGBgDQoNCg0KQWRqdXN0IGZvciBOb24tVHJhZGluZyBEYXRlcw0KDQpgYGB7cn0NCiMgRnVuY3Rpb24gdG8gZ2V0IHlpZWxkIG9uIGEgc3BlY2lmaWMgZGF0ZQ0KZ2V0X3lpZWxkX29uX2RhdGUgPC0gZnVuY3Rpb24oZGF0YSwgZGF0ZSkgew0KICAjIENvbnZlcnQgaW5kZXggdG8gRGF0ZSBmb3JtYXQNCiAgaW5kZXgoZGF0YSkgPC0gYXMuRGF0ZShpbmRleChkYXRhKSkNCiAgDQogICMgR2V0IGF2YWlsYWJsZSBkYXRlcyBvbiBvciBiZWZvcmUgdGhlIHNwZWNpZmllZCBkYXRlDQogIGF2YWlsYWJsZV9kYXRlcyA8LSBpbmRleChkYXRhKVtpbmRleChkYXRhKSA8PSBkYXRlICYgIWlzLm5hKGRhdGFbaW5kZXgoZGF0YSldKV0NCiAgDQogIGlmIChsZW5ndGgoYXZhaWxhYmxlX2RhdGVzKSA9PSAwKSB7DQogICAgd2FybmluZyhwYXN0ZSgiTm8gZGF0YSBhdmFpbGFibGUgb24gb3IgYmVmb3JlIiwgZGF0ZSkpDQogICAgcmV0dXJuKGxpc3QoWWllbGQgPSBOQSwgRGF0ZSA9IE5BKSkNCiAgfQ0KICANCiAgZGF0ZV91c2VkIDwtIG1heChhdmFpbGFibGVfZGF0ZXMpDQogIA0KICAjIEdldCB0aGUgeWllbGQNCiAgeWllbGQgPC0gYXMubnVtZXJpYyhkYXRhW2RhdGVfdXNlZF0pDQogIA0KICByZXR1cm4obGlzdCgNCiAgICBZaWVsZCA9IHlpZWxkLA0KICAgIERhdGUgPSBhcy5EYXRlKGRhdGVfdXNlZCkNCiAgKSkNCn0NCmBgYA0KDQoNClJldHJpZXZlIFlpZWxkcyBvbiBCb1RfZGF0ZQ0KDQpgYGB7cn0NCiMgR2V0IDMtTW9udGggVC1iaWxsIHlpZWxkIG9uIEJvVF9kYXRlDQp5aWVsZF8zbW9fQm9UIDwtIGdldF95aWVsZF9vbl9kYXRlKERHUzNNTywgQm9UX2RhdGUpDQoNCiMgR2V0IDEwLVllYXIgVHJlYXN1cnkgeWllbGQgb24gQm9UX2RhdGUNCnlpZWxkXzEweXJfQm9UIDwtIGdldF95aWVsZF9vbl9kYXRlKERHUzEwLCBCb1RfZGF0ZSkNCmBgYA0KDQoNCkNhbGN1bGF0ZSB0aGUgRGlmZmVyZW5jZQ0KDQpgYGB7cn0NCiMgQ2FsY3VsYXRlIHRoZSB5aWVsZCBkaWZmZXJlbmNlDQp5aWVsZF9kaWZmZXJlbmNlX0JvVCA8LSB5aWVsZF8xMHlyX0JvVCRZaWVsZCAtIHlpZWxkXzNtb19Cb1QkWWllbGQNCg0KIyBDcmVhdGUgYSBkYXRhIGZyYW1lIHRvIGRpc3BsYXkgdGhlIHJlc3VsdHMNCnJlc3VsdHNfTDc3IDwtIGRhdGEuZnJhbWUoDQogIERhdGUgPSB5aWVsZF8zbW9fQm9UJERhdGUsDQogIFlpZWxkXzNtbyA9IHlpZWxkXzNtb19Cb1QkWWllbGQsDQogIFlpZWxkXzEweXIgPSB5aWVsZF8xMHlyX0JvVCRZaWVsZCwNCiAgWWllbGRfRGlmZmVyZW5jZSA9IHlpZWxkX2RpZmZlcmVuY2VfQm9UDQopDQoNCnByaW50KHJlc3VsdHNfTDc3KQ0KYGBgDQoNCg0KIyMjIyBBbmFseXNpcyBvZiByZXN1bHRzDQoNClRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGxvbmctdGVybSBUcmVhc3VyeSBCb25kIFlpZWxkIGFuZCB0aGUgMTMtd2VlayB0cmVhc3VyeSBib25kIHlpZWxkIHdhcyBhIHRvdGFsIG9mIC0wLjgzLiBBIGxvd2VyIHlpZWxkIG9uIHRoZSBzaG9ydCB0ZXJtIHRyZWFzdXJ5IGJvbmQgDQoNCg0KIyMjIEw3LjguIERpZmZlcmVuY2UgQmV0d2VlbiBMb25nLVRlcm0gVHJlYXN1cnkgQm9uZCBZaWVsZCBhbmQgMTMtd2VlayBULWJpbGwgWWllbGQgYXQgRW5kIG9mIFRlcm0gDQoNCg0KRGVmaW5lIEVuZCBvZiBUZXJtIERhdGUNCg0KYGBge3J9DQojIERlZmluZSBFbmQgb2YgVGVybSAoRW9UKSBkYXRlDQpFb1RfZGF0ZSA8LSBhcy5EYXRlKCIyMDI0LTA5LTMwIikNCmBgYA0KDQoNClJldHJpZXZlIHRoZSBZaWVsZCBEYXRhDQoNCmBgYHtyfQ0KIyBSZXRyaWV2ZSAzLU1vbnRoIFQtYmlsbCB5aWVsZCBkYXRhDQpnZXRTeW1ib2xzKCJER1MzTU8iLCBzcmMgPSAiRlJFRCIsIGZyb20gPSBFb1RfZGF0ZSAtIDcsIHRvID0gRW9UX2RhdGUgKyA3KQ0KDQojIFJldHJpZXZlIDEwLVllYXIgVHJlYXN1cnkgeWllbGQgZGF0YQ0KZ2V0U3ltYm9scygiREdTMTAiLCBzcmMgPSAiRlJFRCIsIGZyb20gPSBFb1RfZGF0ZSAtIDcsIHRvID0gRW9UX2RhdGUgKyA3KQ0KYGBgDQoNCg0KQWRqdXN0IHRvIE5vbi1UcmFkaW5nIERheXMNCg0KYGBge3J9DQojIEZ1bmN0aW9uIHRvIGdldCB5aWVsZCBvbiBhIHNwZWNpZmljIGRhdGUNCmdldF95aWVsZF9vbl9kYXRlIDwtIGZ1bmN0aW9uKGRhdGEsIGRhdGUpIHsNCiAgIyBDb252ZXJ0IGluZGV4IHRvIERhdGUgZm9ybWF0DQogIGluZGV4KGRhdGEpIDwtIGFzLkRhdGUoaW5kZXgoZGF0YSkpDQogIA0KICAjIEdldCBhdmFpbGFibGUgZGF0ZXMgb24gb3IgYmVmb3JlIHRoZSBzcGVjaWZpZWQgZGF0ZQ0KICBhdmFpbGFibGVfZGF0ZXMgPC0gaW5kZXgoZGF0YSlbaW5kZXgoZGF0YSkgPD0gZGF0ZSAmICFpcy5uYShkYXRhW2luZGV4KGRhdGEpXSldDQogIA0KICBpZiAobGVuZ3RoKGF2YWlsYWJsZV9kYXRlcykgPT0gMCkgew0KICAgIHdhcm5pbmcocGFzdGUoIk5vIGRhdGEgYXZhaWxhYmxlIG9uIG9yIGJlZm9yZSIsIGRhdGUpKQ0KICAgIHJldHVybihsaXN0KFlpZWxkID0gTkEsIERhdGUgPSBOQSkpDQogIH0NCiAgDQogIGRhdGVfdXNlZCA8LSBtYXgoYXZhaWxhYmxlX2RhdGVzKQ0KICANCiAgIyBHZXQgdGhlIHlpZWxkDQogIHlpZWxkIDwtIGFzLm51bWVyaWMoZGF0YVtkYXRlX3VzZWRdKQ0KICANCiAgcmV0dXJuKGxpc3QoDQogICAgWWllbGQgPSB5aWVsZCwNCiAgICBEYXRlID0gYXMuRGF0ZShkYXRlX3VzZWQpDQogICkpDQp9DQpgYGANCg0KDQpSZXRyaWV2ZSB0aGUgWWllbGRzIG9uIEVvVF9kYXRlDQoNCmBgYHtyfQ0KIyBHZXQgMy1Nb250aCBULWJpbGwgeWllbGQgb24gRW9UX2RhdGUNCnlpZWxkXzNtb19Fb1QgPC0gZ2V0X3lpZWxkX29uX2RhdGUoREdTM01PLCBFb1RfZGF0ZSkNCg0KIyBHZXQgMTAtWWVhciBUcmVhc3VyeSB5aWVsZCBvbiBFb1RfZGF0ZQ0KeWllbGRfMTB5cl9Fb1QgPC0gZ2V0X3lpZWxkX29uX2RhdGUoREdTMTAsIEVvVF9kYXRlKQ0KYGBgDQoNCg0KQ2FsY3VsYXRlIHRoZSBEaWZmZXJlbmNlDQoNCmBgYHtyfQ0KIyBDYWxjdWxhdGUgdGhlIHlpZWxkIGRpZmZlcmVuY2UNCnlpZWxkX2RpZmZlcmVuY2VfRW9UIDwtIHlpZWxkXzEweXJfRW9UJFlpZWxkIC0geWllbGRfM21vX0VvVCRZaWVsZA0KDQojIENyZWF0ZSBhIGRhdGEgZnJhbWUgdG8gZGlzcGxheSB0aGUgcmVzdWx0cw0KcmVzdWx0c19MNzggPC0gZGF0YS5mcmFtZSgNCiAgRGF0ZSA9IHlpZWxkXzNtb19Fb1QkRGF0ZSwNCiAgWWllbGRfM21vID0geWllbGRfM21vX0VvVCRZaWVsZCwNCiAgWWllbGRfMTB5ciA9IHlpZWxkXzEweXJfRW9UJFlpZWxkLA0KICBZaWVsZF9EaWZmZXJlbmNlID0geWllbGRfZGlmZmVyZW5jZV9Fb1QNCikNCg0KcHJpbnQocmVzdWx0c19MNzgpDQpgYGANCg0KDQojIyMgTDcuOS4gRGVzY3JpYmUgSG93IHRoZSBZaWVsZCBDdXJ2ZSBDaGFuZ2VkIE92ZXIgdGhlIFNjaG9vbCBUZXJtDQoNCg0KQ29tcGFyaXNvbiBvZiBSZXN1bHRzDQoNCmBgYHtyfQ0KIyBDcmVhdGUgYSBkYXRhIGZyYW1lIHRvIGNvbXBhcmUgQm9UIGFuZCBFb1QgeWllbGRzDQpjb21wYXJpc29uX2RmIDwtIGRhdGEuZnJhbWUoDQogIERhdGUgPSBjKHlpZWxkXzNtb19Cb1QkRGF0ZSwgeWllbGRfM21vX0VvVCREYXRlKSwNCiAgWWllbGRfM21vID0gYyh5aWVsZF8zbW9fQm9UJFlpZWxkLCB5aWVsZF8zbW9fRW9UJFlpZWxkKSwNCiAgWWllbGRfMTB5ciA9IGMoeWllbGRfMTB5cl9Cb1QkWWllbGQsIHlpZWxkXzEweXJfRW9UJFlpZWxkKSwNCiAgWWllbGRfRGlmZmVyZW5jZSA9IGMoeWllbGRfZGlmZmVyZW5jZV9Cb1QsIHlpZWxkX2RpZmZlcmVuY2VfRW9UKSwNCiAgUGVyaW9kID0gYygiQm9UIiwgIkVvVCIpDQopDQoNCnByaW50KGNvbXBhcmlzb25fZGYpDQpgYGANCg0KDQpZaWVsZCBEaWZmZXJlbmNlDQoNCmBgYHtyfQ0KI1lpZWxkIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgMTAteWVhciBUcmVhc3VyeSBCb25kIGFuZCB0aGUgMy1tb250aCBULWJpbGwgaW4gQm9UX2RhdGUNCnJvdW5kKHlpZWxkX2RpZmZlcmVuY2VfQm9ULCAyKSAjRGlmZmVyZW5jZSBpbiBwZXJjZW50YWdlIHBvaW50cw0KI1lpZWxkIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgMTAteWVhciBUcmVhc3VyeSBCb25kIGFuZCB0aGUgMy1tb250aCBULWJpbGwgaW4gRW9UX2RhdGUNCnJvdW5kKHlpZWxkX2RpZmZlcmVuY2VfRW9ULCAyKQ0KYGBgDQoNCg0KIyMjIyBBbmFseXNpcyBvZiByZXN1bHRzDQpGcm9tIHRoZSBhbnN3ZXJzIG9mIEw3LjcgdG8gTDcuOSB3ZSBoYXZlIG9idGFpbmVkIHRoYXQgdGhlIGRpZmZlcmVuY2UgaW4geWllbGRzIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGVybSB3YXMgLTAuODMgYW5kIGF0IHRoZSBlbmQgb2YgdGVybSB3YXMgLTAuOTIuIA0KSW4gYm90aCBjYXNlcywgdGhlIGhpZ2hlciB5aWVsZCBpbiB0aGUgc2hvcnRlci10ZXJtIHRyZWFzdXJ5IGJvbmRzIGFuZCB0aGUgZGVjcmVhc2luZyB5aWVsZHMgaW5kaWNhdGUgYW4gYWNjb3JkaW5nbHkgZmFsbCBpbiB0aGUgaW50ZXJlc3QgcmF0ZXMgYW5kIGFuIGV4cGVjdGFuY3kgZm9yIGZ1cnRoZXIgZGVjcmVhc2VzIGluIGludGVyZXN0IHJhdGVzLiANCg0KTW9uZXRhcnkgcG9saWNpZXMgYW5kIG1hcmtldCBleHBlY3RhbmN5IGNydWNpYWxseSBhbHRlciB0aGUgYmVoYXZpb3VyIG9mIHRoZSBib25kIHlpZWxkcywgYXMgaW52ZXN0b3JzIHRyeSB0byBhZGFwdCB0byB0aGUgbWFya2V0IGZsdWN0dWF0aW9ucyBhbmQgcG9zaXRpb24gdGhlbXNlbHZlcyBmb3IgdGhlIGZ1dHVyZSBzaXR1YXRpb24uIFRoZSBpbnRlcmVzdCByYXRlcywgYXMgd2UgaGF2ZSBleHBsYWluZWQsIGxlYWRzIHRvIHRoZSBhY2NlcHRhbmNlIG9mIGxvd2VyIHlpZWxkcyBpbiB0aGUgbG9uZy10ZXJtIHRyZWFzdXJ5IGJvbmRzIGFzIHRoZXkgYXJlIGV4cGVjdGVkIHRvIGZhbGwgZXZlbiBtb3JlLiANCg0KDQoNCiMjIEw3LjEwIC0gTDcuMTENCg0KDQojIyMgTDcuMTAgRGlkIHRoZSBGZWQgY2hhbmdlIHRoZSBmZWRlcmFsIGZ1bmRzIHJhdGUgb3ZlciB0aGUgc2Nob29sIHRlcm0/DQoNClRvIGRldGVybWluZSBpZiB0aGVyZSB3YXMgYSBjaGFuZ2UgaW4gZmVkZXJhbCBmdW5kcyByYXRlIG92ZXIgdGhlIHNjaG9vbCB0ZXJtIHdlIGNhbiBhbmFseXplIHRoZSBkYXRhIGZyb20gaGUgRmVkZXJhbCBSZXNlcnZlIEVjb25vbWljIERhdGEgKEZSRUQpIGRhdGFiYXNlDQoNCmBgYHtyfQ0KbGlicmFyeShxdWFudG1vZCkNCg0KIyBEZWZpbmUgdGhlIHN0YXJ0IGFuZCBlbmQgZGF0ZXMNCnN0YXJ0X2RhdGUgPC0gYXMuRGF0ZSgiMjAyNC0wNS0wMSIpDQplbmRfZGF0ZSA8LSBhcy5EYXRlKCIyMDI0LTA5LTMwIikNCg0KIyBHZXQgdGhlIEVmZmVjdGl2ZSBGZWRlcmFsIEZ1bmRzIFJhdGUgKGRhaWx5IGZyZXF1ZW5jeSkgZGF0YSBmcm9tIEZSRUQNCmdldFN5bWJvbHMoIkRGRiIsIHNyYyA9ICJGUkVEIikNCg0KIyBTdWJzZXQgdGhlIGRhdGEgZm9yIHRoZSBzcGVjaWZpZWQgcGVyaW9kDQpmZWRfZnVuZHNfZGFpbHkgPC0gd2luZG93KERGRiwgc3RhcnQgPSBzdGFydF9kYXRlLCBlbmQgPSBlbmRfZGF0ZSkNCg0KIyBDaGVjayBpZiBkYXRhIGlzIGF2YWlsYWJsZSBmb3IgdGhlIGVuZCBkYXRlDQppZiAoZW5kX2RhdGUgJWluJSBpbmRleChmZWRfZnVuZHNfZGFpbHkpKSB7DQogIHByaW50KCJEYXRhIGlzIGF2YWlsYWJsZSBmb3IgdGhlIGVuZCBkYXRlLiIpDQp9IGVsc2Ugew0KICBwcmludCgiRGF0YSBpcyBub3QgYXZhaWxhYmxlIGZvciB0aGUgZW5kIGRhdGUuIFVzaW5nIHRoZSBsYXN0IGF2YWlsYWJsZSBkYXRlLiIpDQogIGFjdHVhbF9lbmRfZGF0ZSA8LSB0YWlsKGluZGV4KGZlZF9mdW5kc19kYWlseSksIDEpDQogIHByaW50KHBhc3RlKCJMYXN0IGF2YWlsYWJsZSBkYXRlIGluIGRhdGE6IiwgYWN0dWFsX2VuZF9kYXRlKSkNCn0NCg0KIyBQbG90IHRoZSBkYXRhIHdpdGggYWRqdXN0ZWQgeS1heGlzIGxpbWl0cw0KbWluX3JhdGUgPC0gbWluKGZlZF9mdW5kc19kYWlseSwgbmEucm0gPSBUUlVFKQ0KbWF4X3JhdGUgPC0gbWF4KGZlZF9mdW5kc19kYWlseSwgbmEucm0gPSBUUlVFKQ0KeV9taW4gPC0gbWluX3JhdGUgLSAwLjAxICAjIFN1YnRyYWN0aW5nIDAuMDElDQp5X21heCA8LSBtYXhfcmF0ZSArIDAuMDEgICMgQWRkaW5nIDAuMDElDQoNCnBsb3QoZmVkX2Z1bmRzX2RhaWx5LCB0eXBlID0gIm8iLCBwY2ggPSAyMCwgY29sID0gImJsdWUiLA0KICAgICBtYWluID0gIkVmZmVjdGl2ZSBGZWRlcmFsIEZ1bmRzIFJhdGUgKE1heSAyMDIzIC0gU2VwdGVtYmVyIDIwMjMpIiwNCiAgICAgeWxhYiA9ICJJbnRlcmVzdCBSYXRlICglKSIsIHlsaW0gPSBjKHlfbWluLCB5X21heCkpDQpncmlkKCkNCg0KYGBgDQoNCg0KVGhlIEZlZCBsb3dlcmVkIHRoZSB0YXJnZXQgcmF0ZSBpbiByZXNwb25zZSB0byBlY29ub21pYyBjb25kaXRpb25zIHRoYXQgd2FycmFudGVkIGEgbW9yZSBhY2NvbW1vZGF0aXZlIG1vbmV0YXJ5IHBvbGljeS4gVGhpcyBjaGFuZ2Ugd2FzIGFpbWVkIGF0IHN0aW11bGF0aW5nIGVjb25vbWljIGFjdGl2aXR5IGFtaWQgc2lnbnMgb2Ygc2xvd2luZyBncm93dGgsIGRlY2xpbmluZyBpbmZsYXRpb24sIG9yIG90aGVyIGZpbmFuY2lhbCBjaGFsbGVuZ2VzIGZhY2luZyB0aGUgZWNvbm9teSBkdXJpbmcgdGhhdCBwZXJpb2QuDQoNCg0KIyMjIEw3LjExIERvIHlvdSB0aGluayB0aGUgbW92ZW1lbnRzIGluIGludGVyZXN0IHJhdGVzIG92ZXIgdGhlIHNjaG9vbCB0ZXJtIHdlcmUgY2F1c2VkIGJ5IHRoZSBGZWTigJlzIG1vbmV0YXJ5IHBvbGljeT8gRXhwbGFpbi4NCg0KWWVzLCB0aGUgbW92ZW1lbnRzIGluIGludGVyZXN0IHJhdGVzIG92ZXIgdGhlIHNjaG9vbCB0ZXJtIHdlcmUgc2lnbmlmaWNhbnRseSBpbmZsdWVuY2VkIGJ5IHRoZSBGZWTigJlzIG1vbmV0YXJ5IHBvbGljeSBhY3Rpb25zLiBIZXJlJ3Mgd2h5Og0KDQojIyMjIERpcmVjdCBJbXBhY3Qgb2YgZmVkIHJhdGVzDQpTaG9ydC10ZXJtIHJhdGVzIHJlZHVjZWQuDQpFeHBhbnNpb25hcnkgbW9uZXRhcnkgcG9saWN5LiANCg0KIyMjIyBNYXJrZXQgZXhwZWN0YXRpb25zIGFuZCBSZWFjdGlvbnMNCg0KIyMjIyBUcmFuc21pc3Npb24gdG8gTG9uZ2VyLVRlcm0gUmF0ZXMNCg0KWWllbGQgQ3VydmUgRWZmZWN0czogQSByYXRlIGN1dCBjYW4gbGVhZCB0byBsb3dlciB5aWVsZHMgb24gbWVkaXVtIGFuZCBsb25nLXRlcm0gc2VjdXJpdGllcyBhcyBpbnZlc3RvcnMgYWRqdXN0IHRoZWlyIHBvcnRmb2xpb3MgaW4gcmVzcG9uc2UgdG8gdGhlIG5ldyByYXRlIGVudmlyb25tZW50Lg0KDQpJbmZsYXRpb24gRXhwZWN0YXRpb25zOiBMb3dlciBpbnRlcmVzdCByYXRlcyBjYW4gaW5mbHVlbmNlIGV4cGVjdGF0aW9ucyBvZiBmdXR1cmUgaW5mbGF0aW9uLCB3aGljaCBpbiB0dXJuIGFmZmVjdCBsb25nLXRlcm0gaW50ZXJlc3QgcmF0ZXMuDQoNCiMjIyMgRWNvbm9taWMgSW5kaWNhdG9ycw0KU3RpbXVsYXRpbmcgQm9ycm93aW5nIGFuZCBTcGVuZGluZw0KRGVjbGluaW5nIGluZHVzdHJpYWwgcHJvZHVjdGlvbiBhbmQgY29uc3VtZXIgc3BlbmRpbmcNCg0KIyMjIyBHTG9iYWwgRWNvbm9taWMgRmFjdG9ycw0KR2xvYmFsIGVjb25vbWljIHNsb3dkb3ducyBjYW4gcHJvbXB0IGxvd2VyIHJhdGVzLiANCg0KDQojIyBMNy4xMiAtIEw3LjEzDQoNCiMjIyBMNy4xMiBEaWZmZXJlbmNlIEJldHdlZW4gOTAtRGF5IENvbW1lcmNpYWwgUGFwZXIgWWllbGQgYW5kIDEzLXdlZWsgVC1iaWxsIFlpZWxkIGF0IEVuZCBvZiBUZXJtDQoNCg0KTG9hZCBwYWNrYWdlcw0KDQpgYGB7cn0NCmxpYnJhcnkocXVhbnRtb2QpDQpgYGANCg0KDQpEZWZpbmUgdGhlIEJlZ2lubmluZyBhbmQgRW5kIG9mIFRlcm0gRGF0ZXMNCg0KYGBge3J9DQojIERlZmluZSBCZWdpbm5pbmcgb2YgVGVybSAoQm9UKSBhbmQgRW5kIG9mIFRlcm0gKEVvVCkgZGF0ZXMNCkJvVF9kYXRlIDwtIGFzLkRhdGUoIjIwMjQtMDUtMDEiKQ0KRW9UX2RhdGUgPC0gYXMuRGF0ZSgiMjAyNC0wOS0zMCIpDQpgYGANCg0KDQpSZXRyaWV2ZSBZaWVsZCBEYXRhDQoNCmBgYHtyfQ0KIyBSZXRyaWV2ZSAzLU1vbnRoIENvbW1lcmNpYWwgUGFwZXIgeWllbGQgZGF0YQ0KZ2V0U3ltYm9scygiQ1BGM00iLCBzcmMgPSAiRlJFRCIsIGZyb20gPSBCb1RfZGF0ZSAtIDcsIHRvID0gRW9UX2RhdGUgKyA3KQ0KDQojIFJldHJpZXZlIDMtTW9udGggVHJlYXN1cnkgQ29uc3RhbnQgTWF0dXJpdHkgUmF0ZSBkYXRhDQpnZXRTeW1ib2xzKCJER1MzTU8iLCBzcmMgPSAiRlJFRCIsIGZyb20gPSBCb1RfZGF0ZSAtIDcsIHRvID0gRW9UX2RhdGUgKyA3KQ0KDQpgYGANCg0KDQpBZGp1c3QgdG8gTm9uLVRyYWRpbmcgRGF5cw0KDQpgYGB7cn0NCiMgRnVuY3Rpb24gdG8gZ2V0IHlpZWxkIG9uIGEgc3BlY2lmaWMgZGF0ZQ0KZ2V0X3lpZWxkX29uX2RhdGUgPC0gZnVuY3Rpb24oZGF0YSwgZGF0ZSkgew0KICAjIENvbnZlcnQgaW5kZXggdG8gRGF0ZSBmb3JtYXQNCiAgaW5kZXgoZGF0YSkgPC0gYXMuRGF0ZShpbmRleChkYXRhKSkNCiAgDQogICMgR2V0IGF2YWlsYWJsZSBkYXRlcyBvbiBvciBiZWZvcmUgdGhlIHNwZWNpZmllZCBkYXRlDQogIGF2YWlsYWJsZV9kYXRlcyA8LSBpbmRleChkYXRhKVtpbmRleChkYXRhKSA8PSBkYXRlICYgIWlzLm5hKGRhdGFbaW5kZXgoZGF0YSldKV0NCiAgDQogIGlmIChsZW5ndGgoYXZhaWxhYmxlX2RhdGVzKSA9PSAwKSB7DQogICAgd2FybmluZyhwYXN0ZSgiTm8gZGF0YSBhdmFpbGFibGUgb24gb3IgYmVmb3JlIiwgZGF0ZSkpDQogICAgcmV0dXJuKGxpc3QoWWllbGQgPSBOQSwgRGF0ZSA9IE5BKSkNCiAgfQ0KICANCiAgZGF0ZV91c2VkIDwtIG1heChhdmFpbGFibGVfZGF0ZXMpDQogIA0KICAjIEdldCB0aGUgeWllbGQNCiAgeWllbGQgPC0gYXMubnVtZXJpYyhkYXRhW2RhdGVfdXNlZF0pDQogIA0KICByZXR1cm4obGlzdCgNCiAgICBZaWVsZCA9IHlpZWxkLA0KICAgIERhdGUgPSBhcy5EYXRlKGRhdGVfdXNlZCkNCiAgKSkNCn0NCmBgYA0KDQoNClJldHJpZXZlIFlpZWxkcyBvbiBFb1RfZGF0ZQ0KDQpgYGB7cn0NCiMgR2V0IDkwLURheSBDb21tZXJjaWFsIFBhcGVyIHlpZWxkIG9uIEVvVF9kYXRlDQp5aWVsZF9DUF9Fb1QgPC0gZ2V0X3lpZWxkX29uX2RhdGUoQ1BGM00sIEVvVF9kYXRlKQ0KDQojIEdldCAxMy13ZWVrIFQtYmlsbCB5aWVsZCBvbiBFb1RfZGF0ZQ0KeWllbGRfVEJpbGxfRW9UIDwtIGdldF95aWVsZF9vbl9kYXRlKERHUzNNTywgRW9UX2RhdGUpDQpgYGANCg0KDQpDYWxjdWxhdGUgdGhlIFByZW1pdW0gYXQgRW9UDQoNCmBgYHtyfQ0KIyBDYWxjdWxhdGUgdGhlIHlpZWxkIHByZW1pdW0NCnByZW1pdW1fRW9UIDwtIHlpZWxkX0NQX0VvVCRZaWVsZCAtIHlpZWxkX1RCaWxsX0VvVCRZaWVsZA0KDQojIENyZWF0ZSBhIGRhdGEgZnJhbWUgdG8gZGlzcGxheSB0aGUgcmVzdWx0cw0KcmVzdWx0c19MNzEyIDwtIGRhdGEuZnJhbWUoDQogIERhdGUgPSB5aWVsZF9UQmlsbF9Fb1QkRGF0ZSwNCiAgWWllbGRfQ29tbWVyY2lhbF9QYXBlciA9IHlpZWxkX0NQX0VvVCRZaWVsZCwNCiAgWWllbGRfVF9CaWxsID0geWllbGRfVEJpbGxfRW9UJFlpZWxkLA0KICBQcmVtaXVtID0gcHJlbWl1bV9Fb1QNCikNCg0KcHJpbnQocmVzdWx0c19MNzEyKQ0KYGBgDQoNCg0KIyMjIyBBbmFseXNpcyBvZiByZXN1bHRzDQpJbiB0aGlzIGV4ZXJjaXNlIHdlIGFyZSBjb21wYXJpbmcgdGhlIHlpZWxkcyBvZiBhIGNvbW1lcmNpYWwgcGFwZXIgYWdhaW5zdCBhIFQtYmlsbC4gQXMgd2UgaGF2ZSBhbHJlYWR5IGV4cGxhaW5lZCBwcmV2aW91cyBzZWN0aW9ucywgdGhlIFQtYmlsbHMgYXJlIGlzc3VlZCBieSB0aGUgVVMgZ292ZXJubWVudCBhbmQgYXJlIGNvbnNpZGVyZWQgcmlzay1mcmVlLiBHaXZlbiB0aGF0IHRoZSBjb21tZXJjaWFsIHBhcGVycyBkbyBub3Qgb2ZmZXIgc3VjaCBhIHNhZmUgcmlzayBwcm9maWxlLCB0aGUgaGlnaGVyIHJpc2sgbXVzdCBiZSBjb21wZW5zYXRlZCB3aXRoIGhpZ2hlciB5aWVsZHMuIFRoaXMgcHJlbWl1bSBtYXkgZmx1Y3R1YXRlIGdpdmVuIHNvbWUgZWNvbm9taWMgZmFjdG9ycyByZWxhdGVkIHRvIHN0YWJpbGl0eSBhbmQgdW5jZXJ0YWludHkuIA0KDQoNCg0KIyMjIEw3LjEzIENvbXBhcmUgdGhlIFByZW1pdW0gYXQgQmVnaW5uaW5nIGFuZCBFbmQgb2YgVGVybQ0KDQoNClJldHJpZXZlIHRoZSBZaWVsZHMgb24gQm9UX2RhdGUNCg0KYGBge3J9DQojIEdldCA5MC1EYXkgQ29tbWVyY2lhbCBQYXBlciB5aWVsZCBvbiBCb1RfZGF0ZQ0KeWllbGRfQ1BfQm9UIDwtIGdldF95aWVsZF9vbl9kYXRlKENQRjNNLCBCb1RfZGF0ZSkNCg0KIyBHZXQgMTMtd2VlayBULWJpbGwgeWllbGQgb24gQm9UX2RhdGUNCnlpZWxkX1RCaWxsX0JvVCA8LSBnZXRfeWllbGRfb25fZGF0ZShER1MzTU8sIEJvVF9kYXRlKQ0KDQpgYGANCg0KDQpDYWxjdWxhdGUgdGhlIFByZW1pdW0gYXQgQm9UDQoNCmBgYHtyfQ0KIyBDYWxjdWxhdGUgdGhlIHlpZWxkIHByZW1pdW0gYXQgQm9UDQpwcmVtaXVtX0JvVCA8LSB5aWVsZF9DUF9Cb1QkWWllbGQgLSB5aWVsZF9UQmlsbF9Cb1QkWWllbGQNCg0KIyBDcmVhdGUgYSBkYXRhIGZyYW1lIHRvIGRpc3BsYXkgdGhlIHJlc3VsdHMNCnJlc3VsdHNfTDcxMyA8LSBkYXRhLmZyYW1lKA0KICBEYXRlID0geWllbGRfVEJpbGxfQm9UJERhdGUsDQogIFlpZWxkX0NvbW1lcmNpYWxfUGFwZXIgPSB5aWVsZF9DUF9Cb1QkWWllbGQsDQogIFlpZWxkX1RfQmlsbCA9IHlpZWxkX1RCaWxsX0JvVCRZaWVsZCwNCiAgUHJlbWl1bSA9IHByZW1pdW1fQm9UDQopDQoNCnByaW50KHJlc3VsdHNfTDcxMykNCmBgYA0KDQoNCkNvbXBhcmUgdGhlIFByZW1pdW1zDQoNCmBgYHtyfQ0KIyBDcmVhdGUgYSBjb21wYXJpc29uIGRhdGEgZnJhbWUNCmNvbXBhcmlzb25fcHJlbWl1bXMgPC0gZGF0YS5mcmFtZSgNCiAgRGF0ZSA9IGMoeWllbGRfVEJpbGxfQm9UJERhdGUsIHlpZWxkX1RCaWxsX0VvVCREYXRlKSwNCiAgUGVyaW9kID0gYygiQm9UIiwgIkVvVCIpLA0KICBZaWVsZF9Db21tZXJjaWFsX1BhcGVyID0gYyh5aWVsZF9DUF9Cb1QkWWllbGQsIHlpZWxkX0NQX0VvVCRZaWVsZCksDQogIFlpZWxkX1RfQmlsbCA9IGMoeWllbGRfVEJpbGxfQm9UJFlpZWxkLCB5aWVsZF9UQmlsbF9Fb1QkWWllbGQpLA0KICBQcmVtaXVtID0gYyhwcmVtaXVtX0JvVCwgcHJlbWl1bV9Fb1QpDQopDQoNCnByaW50KGNvbXBhcmlzb25fcHJlbWl1bXMpDQpgYGANCg0KDQpDaGFuZ2UgaW4gUHJlbWl1bQ0KDQpgYGB7cn0NCiNQcmVtaXVtIGluY3JlYXNlL2RlY3JlYXNlIGluICUgcG9pbnRzDQpwcmVtaXVtX2NoYW5nZSA8LSByb3VuZChwcmVtaXVtX0JvVCwgMikgLSByb3VuZChwcmVtaXVtX0VvVCwgMikNCnByaW50KHByZW1pdW1fY2hhbmdlKQ0KYGBgDQoNCg0KIyMjIyBBbmFseXNpcyBvZiByZXN1bHRzDQoNCkluIHRoaXMgZXhlcmNpc2Ugd2UgaGF2ZSB0YWtlbiB0aGUgcHJlbWl1bXMgYXQgQm9UIGFuZCBFb1QgYW5kIHdlIGhhdmUgcG9ydHJheWVkIHRoZSBjb21wYXJpc29uIGluIGEgZGF0YS5mcmFtZS4gDQpGcm9tIHRoZSByZXN1bHRzLCB3ZSBoYXZlIG9ic2VydmVkIHRoYXQgYm90aCB5aWVsZHMgaGF2ZSBkZWNyZWFzZWQgb3ZlciB0aW1lLiBIb3dldmVyLCB0aGUgY29ycG9yYXRlIHlpZWxkIGhhcyBkZWNyZWFzZWQgbGVzcyB0aGFuIHRoZSBULWJpbGwsIHdoaWNoIGhhcyBsZWQgdG8gYSBmaW5hbCBwcmVtaXVtIG9mIDAuMTMgaW4gZmF2b3VyIGZvciB0aGUgY29tbWVyY2lhbCBwYXBlci4gVGhlc2UgZWZmZWN0cyBtYXkgaGF2ZSBiZWVuIGNhdXNlZCBieSBwb3NpdGl2ZSByZXN1bHRzIGFuZCB0aGUgYWxyZWFkeSBzdHVkaWVkIGRlY3JlYXNlIGluIGludGVyZXN0IHJhdGVzIHRoYXQgY2F1c2VkIHRoZSBkZWNyZWFzZSBvZiB0aGUgdC1iaWxsIHlpZWxkcy4gDQpXZSBtdXN0IG1lbnRpb24gdGhhdCB0aGUgaW5pdGlhbCBzaXR1YXRpb24sIGluIHdoaWNoIHRoZSBULWJpbGwgeWllbGQgaXMgaGlnaGVyIHRoYW4gdGhlIGNvbW1lcmNpYWwgcGFwZXIgaXMgYWJub3JtYWwsIGFzIHVzdWFsbHkgdC1iaWxsIHlpZWxkcyBjb250YWluIGEgbG93IHJpc2sgcHJvZmlsZSBhbmQgZ2VuZXJhbGx5IGxvd2VyIHRoYW4gdGhlIGNvbW1lcmNpYWwgeWllbGRzLCB3aGljaCBvZmZlciBoaWdoZXIgeWllbGRzIGFuZCBoaWdoZXIgcmlzay4gDQoNCg0KDQojIyBMNy4xNCB0byBMNy4xNw0KDQoNCkRlZmluZSBCZWdpbm5pbmcgYW5kIEVuZCBvZiBUZXJtIGRhdGVzDQoNCmBgYHtyfQ0KIyBEZWZpbmUgQmVnaW5uaW5nIG9mIFRlcm0gKEJvVCkgYW5kIEVuZCBvZiBUZXJtIChFb1QpIGRhdGVzDQpCb1RfZGF0ZSA8LSBhcy5EYXRlKCIyMDIzLTA1LTAxIikNCkVvVF9kYXRlIDwtIGFzLkRhdGUoIjIwMjMtMDktMzAiKQ0KYGBgDQoNCg0KIyMjIEw3LjE0LiBEaWZmZXJlbmNlIEJldHdlZW4gWWllbGRzIG9uIEhpZ2gtWWllbGQgYW5kIEhpZ2gtUXVhbGl0eSBDb3Jwb3JhdGUgQm9uZHMNCg0KDQpMb2FkIHBhY2thZ2VzDQoNCmBgYHtyfQ0KbGlicmFyeShxdWFudG1vZCkNCmBgYA0KDQoNClJldHJpZXZlIFlpZWxkIERhdGENCg0KYGBge3J9DQojIFJldHJpZXZlIE1vb2R5J3MgQWFhIENvcnBvcmF0ZSBCb25kIFlpZWxkIChIaWdoLVF1YWxpdHkpDQpnZXRTeW1ib2xzKCJEQUFBIiwgc3JjID0gIkZSRUQiLCBmcm9tID0gQm9UX2RhdGUgLSA3LCB0byA9IEJvVF9kYXRlICsgNykNCg0KIyBSZXRyaWV2ZSBJQ0UgQm9mQSBVUyBIaWdoIFlpZWxkIEluZGV4IEVmZmVjdGl2ZSBZaWVsZCAoSGlnaC1ZaWVsZCkNCmdldFN5bWJvbHMoIkJBTUxIMEEwSFlNMkVZIiwgc3JjID0gIkZSRUQiLCBmcm9tID0gRW9UX2RhdGUgLSA3LCB0byA9IEVvVF9kYXRlICsgNykNCmBgYA0KDQoNCkRlZmluZSBhIEZ1bmN0aW9uIHRvIEdldCBZaWVsZHMgb24gU3BlY2lmaWMgRGF0ZXMNCg0KYGBge3J9DQojIEZ1bmN0aW9uIHRvIGdldCB5aWVsZCBvbiBhIHNwZWNpZmljIGRhdGUNCmdldF95aWVsZF9vbl9kYXRlIDwtIGZ1bmN0aW9uKGRhdGEsIGRhdGUpIHsNCiAgIyBDb252ZXJ0IGluZGV4IHRvIERhdGUgZm9ybWF0DQogIGluZGV4KGRhdGEpIDwtIGFzLkRhdGUoaW5kZXgoZGF0YSkpDQogIA0KICAjIEdldCBhdmFpbGFibGUgZGF0ZXMgb24gb3IgYmVmb3JlIHRoZSBzcGVjaWZpZWQgZGF0ZQ0KICBhdmFpbGFibGVfZGF0ZXMgPC0gaW5kZXgoZGF0YSlbaW5kZXgoZGF0YSkgPD0gZGF0ZSAmICFpcy5uYShkYXRhW2luZGV4KGRhdGEpXSldDQogIA0KICBpZiAobGVuZ3RoKGF2YWlsYWJsZV9kYXRlcykgPT0gMCkgew0KICAgIHdhcm5pbmcocGFzdGUoIk5vIGRhdGEgYXZhaWxhYmxlIG9uIG9yIGJlZm9yZSIsIGRhdGUpKQ0KICAgIHJldHVybihsaXN0KFlpZWxkID0gTkEsIERhdGUgPSBOQSkpDQogIH0NCiAgDQogIGRhdGVfdXNlZCA8LSBtYXgoYXZhaWxhYmxlX2RhdGVzKQ0KICANCiAgIyBHZXQgdGhlIHlpZWxkDQogIHlpZWxkIDwtIGFzLm51bWVyaWMoZGF0YVtkYXRlX3VzZWRdKQ0KICANCiAgcmV0dXJuKGxpc3QoDQogICAgWWllbGQgPSB5aWVsZCwNCiAgICBEYXRlID0gYXMuRGF0ZShkYXRlX3VzZWQpDQogICkpDQp9DQpgYGANCg0KDQpSZXRyaWV2ZSBEYXRhIG9uIFNwZWNpZmljIERhdGVzDQoNCmBgYHtyfQ0KIyBHZXQgSGlnaC1RdWFsaXR5IENvcnBvcmF0ZSBCb25kIFlpZWxkIG9uIEJvVF9kYXRlDQp5aWVsZF9IUV9Cb1QgPC0gZ2V0X3lpZWxkX29uX2RhdGUoREFBQSwgQm9UX2RhdGUpDQoNCiMgR2V0IEhpZ2gtWWllbGQgQ29ycG9yYXRlIEJvbmQgWWllbGQgb24gRW9UX2RhdGUNCnlpZWxkX0hZX0VvVCA8LSBnZXRfeWllbGRfb25fZGF0ZShCQU1MSDBBMEhZTTJFWSwgRW9UX2RhdGUpDQpgYGANCg0KDQpDYWxjdWxhdGUgdGhlIERpZmZlcmVuY2UNCg0KWWllbGQgZGlmZmVyZW5jZSByZXByZXNlbnRzIHRoZSBjaGFuZ2UgYmV0d2VlbiB0aGUgaGlnaC15aWVsZCBjb3Jwb3JhdGUgYm9uZCB5aWVsZCBhdCB0aGUgZW5kIG9mIHRoZSB0ZXJtIGFuZCB0aGUgaGlnaC1xdWFsaXR5IGNvcnBvcmF0ZSBib25kIHlpZWxkIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHRlcm0NCg0KQSBwb3NpdGl2ZSBkaWZmZXJlbmNlIGluZGljYXRlcyB0aGF0IHRoZSBoaWdoLXlpZWxkIGJvbmQgeWllbGQgYXQgRW9UIGlzIGhpZ2hlciB0aGFuIHRoZSBoaWdoLXF1YWxpdHkgYm9uZCB5aWVsZCBhdCBCb1QNCg0KYGBge3J9DQojIENhbGN1bGF0ZSB0aGUgeWllbGQgZGlmZmVyZW5jZQ0KeWllbGRfZGlmZmVyZW5jZV9MNzE0IDwtIHlpZWxkX0hZX0VvVCRZaWVsZCAtIHlpZWxkX0hRX0JvVCRZaWVsZA0KDQojIENyZWF0ZSBhIGRhdGEgZnJhbWUgdG8gZGlzcGxheSB0aGUgcmVzdWx0cw0KcmVzdWx0c19MNzE0IDwtIGRhdGEuZnJhbWUoDQogIERlc2NyaXB0aW9uID0gYygiSGlnaC1RdWFsaXR5IENvcnBvcmF0ZSBCb25kIFlpZWxkIGF0IEJvVCIsICJIaWdoLVlpZWxkIENvcnBvcmF0ZSBCb25kIFlpZWxkIGF0IEVvVCIpLA0KICBEYXRlID0gYyh5aWVsZF9IUV9Cb1QkRGF0ZSwgeWllbGRfSFlfRW9UJERhdGUpLA0KICBZaWVsZCA9IGMoeWllbGRfSFFfQm9UJFlpZWxkLCB5aWVsZF9IWV9Fb1QkWWllbGQpDQopDQoNCnByaW50KHJlc3VsdHNfTDcxNCkNCmNhdCgiWWllbGQgRGlmZmVyZW5jZSAoSGlnaC1ZaWVsZCAtIEhpZ2gtUXVhbGl0eSk6Iiwgcm91bmQoeWllbGRfZGlmZmVyZW5jZV9MNzE0LCAyKSwgIiVcbiIpDQpgYGANCg0KDQojIyMjIEFuYWx5c2lzIG9mIHJlc3VsdHMNCg0KV2UgY2FuIG9ic2VydmUgYSBkaWZmZXJlbmNlIG9mIDQuMTkgd2hpY2ggcmVmbGVjdHMgdGhhdCB0aGUgaGlnaC15aWVsZCB3aWxsIHJlc3VsdCBpbiBoaWdoZXIgcmV0dXJucyBjb21wYXJlZCB0byB0aGUgaGlnaCBxdWFsaXR5LiBUaGlzIHJlc3VsdHMgYXJlIGV4cGxhaW5lZCBkdWUgdG8gdGhlIGFscmVhZHkgZXhwbGFpbmVkIGR5bmFtaWNzIGluIHdoaWNoIHRoZSByaXNraWVyIHRoZSBpbnZlc3RtZW50LCB0aGUgaGlnaGVyIGl0cyByZXR1cm4gd2lsbCBiZS4gSW4gdGhlIGhpZ2gtcXVhbGl0eSBib25kcyB3ZSBwcmlvcml0aXplIG1pbmltaXppbmcgdGhlIHJpc2sgYXQgZXhwZW5zZSBvZiBhIGxvd2VyIHlpZWxkLCB3aGVyZWFzIGluIHRoZSBoaWdoLXlpZWxkIHdlIHdpbGwgYWNjZXB0IGEgaGlnaGVyIHJpc2sgZm9yIGEgaGlnaGVyIGV4cGVjdGVkIHJldHVybi4gDQoNCg0KDQojIyMgTDcuMTUgQ2hhbmdlIGluIExvbmctVGVybSBUcmVhc3VyeSBCb25kIFlpZWxkIGFuZCBJbXBhY3Qgb24gQm9uZCBQcmljZXMNCg0KDQpSZXRyaWV2ZSBZaWVsZCBEYXRhDQoNCmBgYHtyfQ0KIyBSZXRyaWV2ZSAxMC1ZZWFyIFRyZWFzdXJ5IFlpZWxkIGRhdGENCmdldFN5bWJvbHMoIkRHUzEwIiwgc3JjID0gIkZSRUQiLCBmcm9tID0gQm9UX2RhdGUgLSA3LCB0byA9IEVvVF9kYXRlICsgNykNCmBgYA0KDQoNClJldHJpZXZlIFlpZWxkcyBvbiBTcGVjaWZpZWQgRGF0ZXMNCg0KYGBge3J9DQojIEdldCAxMC1ZZWFyIFRyZWFzdXJ5IFlpZWxkIG9uIEJvVF9kYXRlDQp5aWVsZF8xMHlyX0JvVCA8LSBnZXRfeWllbGRfb25fZGF0ZShER1MxMCwgQm9UX2RhdGUpDQoNCiMgR2V0IDEwLVllYXIgVHJlYXN1cnkgWWllbGQgb24gRW9UX2RhdGUNCnlpZWxkXzEweXJfRW9UIDwtIGdldF95aWVsZF9vbl9kYXRlKERHUzEwLCBFb1RfZGF0ZSkNCmBgYA0KDQoNCkNhbGN1bGF0ZSB0aGUgQ2hhbmdlIGluIFlpZWxkDQoNCmBgYHtyfQ0KIyBDYWxjdWxhdGUgdGhlIGNoYW5nZSBpbiB5aWVsZA0KeWllbGRfY2hhbmdlX0w3MTUgPC0geWllbGRfMTB5cl9Fb1QkWWllbGQgLSB5aWVsZF8xMHlyX0JvVCRZaWVsZA0KDQojIENyZWF0ZSBhIGRhdGEgZnJhbWUgdG8gZGlzcGxheSB0aGUgcmVzdWx0cw0KcmVzdWx0c19MNzE1IDwtIGRhdGEuZnJhbWUoDQogIERhdGUgPSBjKHlpZWxkXzEweXJfQm9UJERhdGUsIHlpZWxkXzEweXJfRW9UJERhdGUpLA0KICBQZXJpb2QgPSBjKCJCb1QiLCAiRW9UIiksDQogIFlpZWxkXzEweXJfVHJlYXN1cnkgPSBjKHlpZWxkXzEweXJfQm9UJFlpZWxkLCB5aWVsZF8xMHlyX0VvVCRZaWVsZCkNCikNCg0KcHJpbnQocmVzdWx0c19MNzE1KQ0KY2F0KCJDaGFuZ2UgaW4gMTAtWWVhciBUcmVhc3VyeSBZaWVsZCAoRW9UIC0gQm9UKToiLCByb3VuZCh5aWVsZF9jaGFuZ2VfTDcxNSwgMiksICIlXG4iKQ0KYGBgDQoNCg0KIyMjIyBBbmFseXNpcyBvZiByZXN1bHRzDQoNClRoZSBib25kIHByaWNlcyBmb2xsb3cgYW4gaW52ZXJzZSByZWxhdGlvbnNoaXAgd2l0aCB0aGUgYm9uZCB5aWVsZHMuIFRoZXJlZm9yZSwgYXMgd2UgaGF2ZSBjYWxjdWxhdGVkIGFuIGFwcHJlY2lhdGlvbiBpbiB0aGUgeWllbGQgb2YgYSAxJSwgd2UgbWF5IGRlcml2ZSB0aGF0IHRoZSBwcmljZSBoYXMgZGVjcmVhc2VkIG92ZXIgdGhlIHRlcm0uICANCg0KIyMjIEw3LjE2IENvbXBhcmluZyBDaGFuZ2VzIGluIFlpZWxkcyBvZiBUcmVhc3VyeSwgTXVuaWNpcGFsLCBhbmQgQ29ycG9yYXRlIEJvbmRzDQoNCg0KUmV0cmlldmUgWWllbGQgRGF0YQ0KDQpgYGB7cn0NCiMgUmV0cmlldmUgVHJlYXN1cnkgWWllbGQgZGF0YQ0KZ2V0U3ltYm9scygiREdTMTAiLCBzcmMgPSAiRlJFRCIsIGZyb20gPSBCb1RfZGF0ZSAtIDcsIHRvID0gRW9UX2RhdGUgKyA3KQ0KDQojIFJldHJpZXZlIENvcnBvcmF0ZSBCb25kIFlpZWxkIGRhdGENCmdldFN5bWJvbHMoIkRBQUEiLCBzcmMgPSAiRlJFRCIsIGZyb20gPSBCb1RfZGF0ZSAtIDcsIHRvID0gRW9UX2RhdGUgKyA3KQ0KDQojIEF0dGVtcHQgdG8gUmV0cmlldmUgTXVuaWNpcGFsIEJvbmQgWWllbGQgZGF0YQ0KIyBOb3RlOiBNdW5pY2lwYWwgYm9uZCBkYXRhIGlzIGxpbWl0ZWQgb24gRlJFRDsgd2UgbWF5IG5lZWQgdG8gdXNlIGF2YWlsYWJsZSBwcm94aWVzIG9yIGFja25vd2xlZGdlIGxpbWl0YXRpb25zLg0KI2dldFN5bWJvbHMoIk1VTkkxMFkiLCBzcmMgPSAiRlJFRCIsIGZyb20gPSBCb1RfZGF0ZSAtIDcsIHRvID0gRW9UX2RhdGUgKyA3KSAjV0UgQVJFIE5PVCBBQkxFIFRPIEZJTkQgQU5ZIERBVEEgT04gTVVOSUNJUEFMIEJPTkRTDQoNCg0KYGBgDQoNCg0KIyMjIyBBbmFseXNpcyBvZiByZXN1bHRzDQpBcyB3ZSBoYXZlIG1lbnRpb25lZCBlYXJsaWVyLCB3ZSBoYXZlIGZvdW5kIGNlcnRhaW4gaXNzdWVkIHRvIHJldHJpZXZlIG11bmljaXBhbCBib25kcyBkYXRhLiBIb3dldmVyLCB3ZSBjYW4gZGV0ZXJtaW5lIGZyb20gd2hhdCBoYXMgYmVlbiBhbmFseXplZCBzbyBmYXIgaW4gcHJldmlvdXMgYW5zd2VycyB0aGF0IGJvbmQgeWllbGRzIGhhdmUgZmFsbGVuIG92ZXIgdGhlIGNvdXJzZSBvZiB0aGUgc2Nob29sIHRlcm0sIHByaW1hcmlseSBkdWUgdG8gdGhlIGZhbGwgaW4gaW50ZXJlc3QgcmF0ZXMgYW5kIHRoZSBleHBlY3RhbmN5IG9mIGZ1cnRoZXIgcmF0ZSBjdXRzLiBPdGhlciBmYWN0b3JzIHN1Y2ggYXMgaW5mbGF0aW9uIGFuZCBvdmVyYWxsIGVjb25vbWljIGNvbmRpdGlvbnMgYWxzbyBhZmZlY3QgdGhpcyBtb3ZlbWVudHMuIA0KDQoNCiMjIyBMNy4xNyBDaGFuZ2UgaW4gUHJlbWl1bSBvbiBIaWdoLVlpZWxkIENvcnBvcmF0ZSBCb25kcyBSZWxhdGl2ZSB0byBUcmVhc3VyeSBCb25kcw0KDQoNClJldHJpZXZlIEhpZ2ggWWllbGQgQ29ycG9yYXRlIEJvbmQgWWllbGQgb24gQm9UX2RhdGUNCg0KYGBge3J9DQojIFJldHJpZXZlIEhpZ2gtWWllbGQgQ29ycG9yYXRlIEJvbmQgWWllbGQgZGF0YSBmb3IgQm9UX2RhdGUNCmdldFN5bWJvbHMoIkJBTUxIMEEwSFlNMkVZIiwgc3JjID0gIkZSRUQiLCBmcm9tID0gQm9UX2RhdGUgLSA3LCB0byA9IEJvVF9kYXRlICsgNykNCg0KIyBHZXQgSGlnaC1ZaWVsZCBDb3Jwb3JhdGUgQm9uZCBZaWVsZCBvbiBCb1RfZGF0ZQ0KeWllbGRfSFlfQm9UIDwtIGdldF95aWVsZF9vbl9kYXRlKEJBTUxIMEEwSFlNMkVZLCBCb1RfZGF0ZSkNCiNHZXQgWWllbGQgb24gVHJlYXN1cnkgYm9uZCBvbiBCb1RfZGF0ZSBhbmQgRW9UX2RhdGUNCnlpZWxkX1RyZWFzdXJ5X0JvVCA8LSBnZXRfeWllbGRfb25fZGF0ZShER1MxMCwgQm9UX2RhdGUpDQp5aWVsZF9UcmVhc3VyeV9Fb1QgPC0gZ2V0X3lpZWxkX29uX2RhdGUoREdTMTAsIEVvVF9kYXRlKQ0KYGBgDQoNCg0KQ2FsY3VsYXRlIFByZW1pdW1zDQoNCmBgYHtyfQ0KIyBQcmVtaXVtIGF0IEJvVA0KcHJlbWl1bV9Cb1QgPC0geWllbGRfSFlfQm9UJFlpZWxkIC0geWllbGRfVHJlYXN1cnlfQm9UJFlpZWxkDQoNCiMgUHJlbWl1bSBhdCBFb1QNCnByZW1pdW1fRW9UIDwtIHlpZWxkX0hZX0VvVCRZaWVsZCAtIHlpZWxkX1RyZWFzdXJ5X0VvVCRZaWVsZA0KYGBgDQoNCg0KQ29tcGFyZSBQcmVtaXVtcw0KDQpgYGB7cn0NCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSB0byBkaXNwbGF5IHRoZSByZXN1bHRzDQpyZXN1bHRzX0w3MTcgPC0gZGF0YS5mcmFtZSgNCiAgRGF0ZSA9IGMoeWllbGRfVHJlYXN1cnlfQm9UJERhdGUsIHlpZWxkX1RyZWFzdXJ5X0VvVCREYXRlKSwNCiAgUGVyaW9kID0gYygiQm9UIiwgIkVvVCIpLA0KICBZaWVsZF9IaWdoX1lpZWxkX0NvcnBvcmF0ZSA9IGMoeWllbGRfSFlfQm9UJFlpZWxkLCB5aWVsZF9IWV9Fb1QkWWllbGQpLA0KICBZaWVsZF9UcmVhc3VyeSA9IGMoeWllbGRfVHJlYXN1cnlfQm9UJFlpZWxkLCB5aWVsZF9UcmVhc3VyeV9Fb1QkWWllbGQpLA0KICBQcmVtaXVtID0gYyhwcmVtaXVtX0JvVCwgcHJlbWl1bV9Fb1QpDQopDQoNCnByaW50KHJlc3VsdHNfTDcxNykNCmBgYA0KDQoNCkNoYW5nZSBpbiBwcmVtaXVtcw0KDQpgYGB7cn0NCiNDaGFuZ2UgaW4gcHJlbWl1bSBleHByZXNzZWQgaW4gcGVyY2VudGFnZSBwb2ludHMNCmNoYW5nZV9pbl9wcmVtaXVtIDwtIHJvdW5kKHByZW1pdW1fRW9ULCAyKSAtIHJvdW5kKHByZW1pdW1fQm9UKQ0KY2F0KCJjaGFuZ2UgaW4gcHJlbWl1bToiLCBjaGFuZ2VfaW5fcHJlbWl1bSkNCmBgYA0KDQoNCiMjIyMgQW5hbHlzaXMgb2YgcmV0dXJucw0KSW4gdGhpcyBsYXN0IGV4ZXJjaXNlIG9mIHRoaXMgc2VjdGlvbiwgd2UgaGF2ZSBjYWxjdWxhdGVkIHRoZSBwcmVtaXVtIG9mIGhpZ2ggeWllbGQgY29ycG9yYXRlIGJvbmRzIGFnYWluc3QgdGhlIHRyZWFzdXJ5IGJvbmQgeWllbGRzLiBBcyB3ZSBrbm93LCBoaWdoLXlpZWxkcyB3aWxsIGhhdmUgaGlnaGVyIHJpc2sgYW5kIGhpZ2hlciBleHBlY3RlZCByZXR1cm5zLiBUaGUgcHJlbWl1bSBoYXMgZmFsbGVuIDAuNzkgcG9pbnRzIGR1cmluZyB0aGUgc2Nob29sIHRlcm0sIHdoaWNoIG1heSBpbmRpY2F0ZSBhIHJlZHVjdGlvbiBvZiBjcmVkaXQgcmlzayBhbmQgYW4gb3ZlcmFsbCBpbXByb3ZlbWVudCBpbiB0aGUgZWNvbm9teS4gVGhpcyBtZWFucyB0aGF0IHRoZXJlIGlzIGxlc3MgcmlzayBvZiBub3QgZ2V0dGluZyBub24tcGF5bWVudHMsIGFuZCBhcyB3ZSBrbm93LCB3aXRoIGxvd2VyIHJpc2tzIHdlIHNoYWxsIG9idGFpbiBsb3dlciBleHBlY3RlZCByZXR1cm5zIG9yIHlpZWxkcy4gDQpJbnZlc3RvcnMgbmVjZXNzaXRpZXMgb3IgcHJlZmVyZW5jZXMgYW5kIHRoZWlyIHNoaWZ0cyBtYXkgYWxzbyBoYXZlIGFuIGltcGFjdCBvbiB0aGUgcHJlbWl1bXMgYXMgdGhlIGdlbmVyYWwgcmlzayB0b2xlcmFuY2UgZmx1Y3R1YXRlIGluIHRoZSBtYXJrZXQuIA0KDQoNCg0KDQojIyBMOCBQb3J0Zm9saW8gLSBNYXJrb3ZpdHoNClJlcGxpY2F0ZSB0aGUgYmFzaWMgaWRlYSBvZiB0aGUgcG9ydGZvbGlvIGNhc2UNCg0KIyMjIE1hcmtvd2l0eiBQb3J0Zm9saW8gVGhlb3J5DQpBbHRob3VnaCBpdCB3aWxsIGJlIGV4cGxhaW5lZCBpbiBmdXJ0aGVyIGRldGFpbCBpbiB0aGUgbmV4dCBxdWVzdGlvbiwgd2UgY2FuIGludHJvZHVjZSB0aGUgTWFya293aXR6IHRoZW9yeSBhcyBhIHBvcnRmb2xpbyBzZWxlY3Rpb24gc3RyYXRlZ3kgdGhhdCBzZWVrcyB0byBtYXhpbWl6ZSB0aGUgZXhwZWN0ZWQgcmV0dXJuIGZvciBhIGdpdmVuIHJpc2sgKG9yIHRvIGZpbmQgdGhlIG1pbmltdW0gcmlzayBmb3IgYSBnaXZlbiByZXR1cm4pLiBUaGlzIG1ldGhvZCBjb25zaWRlcnMgdG90YWwgcmlzaywgdGhhdCBpcyBzeXN0ZW1hdGljIGFuZCBzcGVjaWZpYyByaXNrLiANCg0KIyMjIFIgY29kZSBmb3IgZGVtb25zdHJhdGlvbg0KDQpMb2FkIFJlcXVpcmVkIFBhY2thZ2VzDQoNCmBgYHtyfQ0KIyBJbnN0YWxsIHJlcXVpcmVkIHBhY2thZ2VzIGlmIG5vdCBhbHJlYWR5IGluc3RhbGxlZA0KaWYgKCFyZXF1aXJlKCJQZXJmb3JtYW5jZUFuYWx5dGljcyIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoIlBlcmZvcm1hbmNlQW5hbHl0aWNzIikNCn0NCmxpYnJhcnkocXVhbnRtb2QpDQpsaWJyYXJ5KFBlcmZvcm1hbmNlQW5hbHl0aWNzKQ0KDQpgYGANCg0KDQpSZXRyaWV2ZSBIaXN0b3JpY2FsIFN0b2NrIERhdGENCg0KYGBge3J9DQojIERlZmluZSBzdG9jayBzeW1ib2xzDQpzeW1ib2xzIDwtIGMoIkFNWk4iLCAiVFNMQSIpDQoNCiMgU2V0IHRoZSBkYXRlIHJhbmdlDQpzdGFydF9kYXRlIDwtICIyMDE4LTAxLTAxIg0KZW5kX2RhdGUgPC0gIjIwMjMtMTItMzEiICAjIEFkanVzdCB0aGUgZW5kIGRhdGUgaWYgbmVlZGVkDQoNCiMgR2V0IGhpc3RvcmljYWwgZGF0YSBmb3IgQW1hem9uIGFuZCBUZXNsYQ0KZ2V0U3ltYm9scyhzeW1ib2xzLCBmcm9tID0gc3RhcnRfZGF0ZSwgdG8gPSBlbmRfZGF0ZSwgYXV0by5hc3NpZ24gPSBUUlVFKQ0KDQojIEV4dHJhY3QgYWRqdXN0ZWQgY2xvc2luZyBwcmljZXMNCnByaWNlcyA8LSBtZXJnZShBZChBTVpOKSwgQWQoVFNMQSkpDQpjb2xuYW1lcyhwcmljZXMpIDwtIHN5bWJvbHMNCmBgYA0KDQoNCkNhbGN1bGF0ZSBEYWlseSBSZXR1cm5zDQoNCmBgYHtyfQ0KIyBDYWxjdWxhdGUgZGFpbHkgcmV0dXJucw0KcmV0dXJucyA8LSBuYS5vbWl0KFJPQyhwcmljZXMsIHR5cGUgPSAiZGlzY3JldGUiKSkNCmBgYA0KDQoNCkNhbGN1bGF0ZSBFeHBlY3RlZCBSZXR1cm5zIGFuZCBDb3ZhcmlhbmNlIE1hdHJpeA0KDQpgYGB7cn0NCiMgQ2FsY3VsYXRlIGV4cGVjdGVkIGRhaWx5IHJldHVybnMgKG1lYW4gcmV0dXJucykNCm11IDwtIGNvbE1lYW5zKHJldHVybnMpDQoNCiMgQ2FsY3VsYXRlIHRoZSBjb3ZhcmlhbmNlIG1hdHJpeA0KY292X21hdCA8LSBjb3YocmV0dXJucykNCmBgYA0KDQoNClNldCB1cCBQb3J0Zm9saW8gV2VpZ2h0cw0KDQpgYGB7cn0NCiMgRXF1YWwgd2VpZ2h0cyBmb3IgQU1aTiBhbmQgVFNMQQ0Kd2VpZ2h0cyA8LSBjKDAuNSwgMC41KQ0KbmFtZXMod2VpZ2h0cykgPC0gc3ltYm9scw0KDQpgYGANCg0KDQpDYWxjdWxhdGUgUG9ydGZvbGlvIEV4cGVjdGVkIFJldHVybiBhbmQgVmFyaWFuY2UNCg0KYGBge3J9DQojIENhbGN1bGF0ZSBwb3J0Zm9saW8gZXhwZWN0ZWQgZGFpbHkgcmV0dXJuDQpwb3J0Zm9saW9fcmV0dXJuX2RhaWx5IDwtIHN1bSh3ZWlnaHRzICogbXUpDQoNCiMgQ2FsY3VsYXRlIHBvcnRmb2xpbyBkYWlseSB2YXJpYW5jZQ0KcG9ydGZvbGlvX3ZhcmlhbmNlX2RhaWx5IDwtIHQod2VpZ2h0cykgJSolIGNvdl9tYXQgJSolIHdlaWdodHMNCmBgYA0KDQoNCg0KQW5udWFsaXplIHRoZSBFeHBlY3RlZCBSZXR1cm4gYW5kIFZvbGF0aWxpdHkNCg0KYGBge3J9DQojIEFubnVhbGl6ZSBleHBlY3RlZCByZXR1cm4NCnBvcnRmb2xpb19yZXR1cm5fYW5udWFsIDwtIHBvcnRmb2xpb19yZXR1cm5fZGFpbHkgKiAyNTINCg0KIyBBbm51YWxpemUgdm9sYXRpbGl0eSAoc3RhbmRhcmQgZGV2aWF0aW9uKQ0KcG9ydGZvbGlvX3ZvbGF0aWxpdHlfYW5udWFsIDwtIHNxcnQocG9ydGZvbGlvX3ZhcmlhbmNlX2RhaWx5ICogMjUyKQ0KYGBgDQoNCg0KUHJpbnQgdGhlIHJlc3VsdHMNCg0KYGBge3J9DQojIFByaW50IHJlc3VsdHMNCnByaW50KHBhc3RlKCJQb3J0Zm9saW8gZXhwZWN0ZWQgYW5udWFsIHJldHVybjoiLCByb3VuZChwb3J0Zm9saW9fcmV0dXJuX2FubnVhbCAqIDEwMCwgMiksICIlIikpDQpwcmludChwYXN0ZSgiUG9ydGZvbGlvIGFubnVhbGl6ZWQgdm9sYXRpbGl0eToiLCByb3VuZChwb3J0Zm9saW9fdm9sYXRpbGl0eV9hbm51YWwgKiAxMDAsIDIpLCAiJSIpKQ0KDQpgYGANCg0KDQojIyMgQW5hbHlzaXMgb2YgcmVzdWx0cw0KSW4gdGhpcyBleGFtcGxlLCB3ZSBoYXZlIGNyZWF0ZWQgYSBwb3J0Zm9saW8gd2hpY2ggb25seSBjb250YWlucyB0d28gYXNzZXRzLiBCb3RoIGFzc2V0cyBoYXZlIHRoZSBzYW1lIHdlaWdodCBhbmQgd2UgYXJlIG9ubHkgZXZhbHVhdGluZyB0aGUgZXhwZWN0ZWQgYW5udWFsIHJldHVybiBhbmQgdGhlIHZvbGF0aWxpdHkuIA0KV2UgbWF5IG5vdGljZSB0aGF0IHRoZSB2b2xhdGlsaXR5IGlzIHF1aXRlIGhpZ2ggaW4gdGhpcyBjYXNlLiBWb2xhdGlsaXR5LCBtZWFzdXJlZCBieSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uLCBtZWFzdXJlcyB0b3RhbCByaXNrLiBUaGVyZWZvcmUsIHRoZSB2b2xhdGlsaXR5IHBvcnRyYXllZCBpbiB0aGlzIGV4YW1wbGUgaXMgY29uc2lkZXJhYmx5IGhpZ2ggZm9yIHRoZSBpbnZlc3RvciwgYW5kIHByZXN1bWFibHkgbm90IGEgZGVzaXJlZCBvbmUuIFRoZSBtYWluIHdheSB0byBsZXNzZW4gdGhpcyByaXNrIGlzIGJ5IGRpdmVyc2lmeWluZywgdGhpcyBpcywgZWxpbWluYXRpbmcgdGhlIHVuc3lzdGVtYXRpYyByaXNrIGJ5IG1peGluZyBkaWZmZXJlbnQgdHlwZXMgb2YgYXNzZXRzIGFuZCBpbnZlc3RtZW50cyBpbnRvIHRoZSBzYW1lIHBvcnRmb2xpby4gDQoNCg0KIyMjIEZpbmFsIENvbW1lbnRzDQpJbiB0aGUgZm9sbG93aW5nIGV4ZXJjaXNlIHdlIHdpbGwgZGl2ZSBmdXJ0aGVyIGludG8gdGhlIGNoYXJhY3RlcmlzdGljcyBvZiB0aGUgTWFya293aXR6IFBvcnRmb2xpbyBUaGVvcnkgYW5kIHdlIHdpbGwgY29tcGFyZSBpdCB0byBhbm90aGVyIG1vZGVsOiBDQVBNLiANCg0KDQoNCg0KIyMgTDkgUG9ydGZvbGlvIC0gQ0FQTQ0KDQoNCg0KIyMjIEludHJvZHVjdGlvbg0KVGhlIE1hcmtvd2l0eiBQb3J0Zm9saW8gVGhlb3J5IGFuZCB0aGUgQ2FwaXRhbCBBc3NldCBQcmljaW5nIE1vZGVsIChDQVBNKSBhcmUgdHdvIGRpZmZlcmVudCBhcHByb2FjaGVzIGZvciBwb3J0Zm9saW8gc2VsZWN0aW9uIGFuZCBhc3NldCBwcmljaW5nLiBUaGlzIHR3byBkaWZmZXJlbnQgbWV0aG9kcyBoYXZlIHRoZSBzY29wZSBvZiBtYWtpbmcgaW52ZXN0bWVudCBkZWNpc2lvbnMgYW5kIG9wdGltaXplIHRoZW0sIGJ1dCBlYWNoIGhhdmUgdGhlaXIgb3duIGFzc3VtcHRpb25zLCBhcHByb2FjaGVzIGFuZCBhcHBsaWNhdGlvbnMuIA0KDQoNCiMjIyBNYXJrb3dpdHogUG9ydGZvbGlvIFRoZW9yeQ0KDQojIyMjIE92ZXJ2aWV3DQoNCiAgRGV2ZWxvcGVkIGJ5OiBIYXJyeSBNYXJrb3dpdHogaW4gMTk1Mi4NCg0KICBDb25jZXB0OiBBbHNvIGtub3duIGFzIE1lYW4tVmFyaWFuY2UgT3B0aW1pemF0aW9uIChNVk8pLg0KDQogIE9iamVjdGl2ZTogVG8gYnVpbGQgYW4gb3B0aW1hbCBwb3J0Zm9saW8gdGhhdCBvZmZlcnMgdGhlIG1heGltdW0gZXhwZWN0ZWQgcmV0dXJuIGZvciBhIGdpdmVuIGxldmVsIG9mIHJpc2ssIG9yIGVxdWl2YWxlbnRseSwgdGhlIG1pbmltdW0gcmlzayBmb3IgYSBnaXZlbiBsZXZlbCBvZiBleHBlY3RlZCByZXR1cm4uDQoNCg0KIyMjIyBNYWluIEVsZW1lbnRzDQoNCiAgRXhwZWN0ZWQgUmV0dXJuOiBUaGUgd2VpZ2h0ZWQgYXZlcmFnZSBvZiB0aGUgZXhwZWN0ZWQgcmV0dXJucyBvZiB0aGUgYXNzZXRzIGluIHRoZSBwb3J0Zm9saW8uDQoNCiAgUmlzayAoVmFyaWFuY2Ugb3IgU3RhbmRhcmQgRGV2aWF0aW9uKTogVGhlIHBvcnRmb2xpbydzIHRvdGFsIHJpc2sgaXMgbWVhc3VyZWQgYnkgdGhlIHZhcmlhbmNlIChvciBzdGFuZGFyZCBkZXZpYXRpb24pIG9mIGl0cyByZXR1cm5zLg0KDQogIENvdmFyaWFuY2U6IEFjY291bnRzIGZvciBob3cgYXNzZXRzIG1vdmUgdG9nZXRoZXI7IGRpdmVyc2lmaWNhdGlvbiBiZW5lZml0cyBhcmlzZSB3aGVuIGFzc2V0IHJldHVybnMgYXJlIG5vdCBwZXJmZWN0bHkgY29ycmVsYXRlZC4NClBlcmZlY3RseSBjb3JyZWxhdGVkIGFzc2V0cyB3aWxsIGhhdmUgYSBiZXRhIG9mIDEgb3IgLTEsIHdoZXJlYXMgdGhlIHJlc3Qgd2lsbCBoYXZlIGJldGFzIGluLWJldHdlZW4gdGhvc2UgdHdvIHZhbHVlcy4gDQoNCg0KIyMjIyBBc3N1bXB0aW9ucw0KDQogIEludmVzdG9ycyBhcmUgcmF0aW9uYWwgYW5kIHJpc2stYXZlcnNlLg0KDQogIFJldHVybnMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLg0KDQogIFBlcmZlY3QgSW5mb3JtYXRpb24gaW4gdGhlIG1hcmtldDsgTWFya2V0cyBhcmUgZWZmaWNpZW50Lg0KDQogIEludmVzdG9ycyBjb25zaWRlciBvbmx5IHRoZSBtZWFuIGFuZCB2YXJpYW5jZSBvZiByZXR1cm5zLg0KDQogIE5vIHRyYW5zYWN0aW9uIGNvc3RzIG9yIHRheGVzLg0KDQogIEFzc2V0cyBhcmUgaW5maW5pdGVseSBkaXZpc2libGUuDQoNCg0KIyMjIyBFZmZpY2llbnQgRnJvbnRpZXINCiAgVGhlIHNldCBvZiBvcHRpbWFsIHBvcnRmb2xpb3MgdGhhdCBvZmZlciB0aGUgaGlnaGVzdCBleHBlY3RlZCByZXR1cm4gZm9yIGEgZ2l2ZW4gbGV2ZWwgb2Ygcmlzay4NCg0KICBJbnZlc3RvcnMgY2hvb3NlIHBvcnRmb2xpb3Mgb24gdGhlIGVmZmljaWVudCBmcm9udGllciBiYXNlZCBvbiB0aGVpciByaXNrIHByZWZlcmVuY2UuDQoNCg0KDQojIyMgQ2FwaXRhbCBBc3NldCBQcmljaW5nIE1vZGVsIChDQVBNKQ0KDQoNCiMjIyMgT3ZlcnZpZXcNCiAgRGV2ZWxvcGVkIGJ5OiBXaWxsaWFtIFNoYXJwZSwgSm9obiBMaW50bmVyLCBhbmQgSmFuIE1vc3NpbiBpbiB0aGUgMTk2MHMuDQoNCiAgQ29uY2VwdDogQSBtb2RlbCB0aGF0IGRlc2NyaWJlcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGV4cGVjdGVkIHJldHVybiBvZiBhbiBhc3NldCBhbmQgaXRzIHN5c3RlbWF0aWMgcmlzaywgbWVhc3VyZWQgYnkgYmV0YSAozrIpLg0KDQogIE9iamVjdGl2ZTogVG8gZGV0ZXJtaW5lIHRoZSBleHBlY3RlZCByZXR1cm4gb24gYW4gYXNzZXQgb3IgcG9ydGZvbGlvLCBjb25zaWRlcmluZyBpdHMgcmlzayByZWxhdGl2ZSB0byB0aGUgbWFya2V0Lg0KDQoNCiMjIyMgS2V5IENvbXBvbmVudHMNCiAgUmlzay1GcmVlIFJhdGUgKFJmKTogVGhlIHJldHVybiBvZiBhbiBpbnZlc3RtZW50IHdpdGggemVybyByaXNrLCB0eXBpY2FsbHkgZ292ZXJubWVudCBib25kcy4gVGhpcyBpbnZlc3RtZW50IGhhcyBhIM6yID0gMA0KDQogIE1hcmtldCBSZXR1cm4gKFJtKTogVGhlIGV4cGVjdGVkIHJldHVybiBvZiB0aGUgbWFya2V0IHBvcnRmb2xpby4NCg0KICBCZXRhICjOsik6IE1lYXN1cmVzIHRoZSBzZW5zaXRpdml0eSBvZiB0aGUgYXNzZXQncyByZXR1cm5zIHRvIHRoZSByZXR1cm5zIG9mIHRoZSBtYXJrZXQgcG9ydGZvbGlvLg0KDQogIEV4cGVjdGVkIFJldHVybiBGb3JtdWxhOg0KRShSaSkgPSBSZiArIM6yaShFKFJtKS1SZikNCndoZXJlOg0KRShSaSkgaXMgdGhlIGV4cGVjdGVkIHJldHVybiBvZiBhc3NldCAiaSINCs6yaSBpcyB0aGUgYmV0YSBvZiBhc3NldCBpDQpFKFJtKSBpcyB0aGUgZXhwZWN0ZWQgbWFya2V0IHJldHVybg0KDQoNCiMjIyMgQXNzdW1wdGlvbnMNCg0KICBJbnZlc3RvcnMgaG9sZCBkaXZlcnNpZmllZCBwb3J0Zm9saW9zIChtYXJrZXQgcG9ydGZvbGlvKSB0aGF0IGVsaW1pbmF0ZSB1bnN5c3RlbWF0aWMgcmlzay4NCg0KICBNYXJrZXRzIGFyZSBlZmZpY2llbnQ7IGFsbCBpbnZlc3RvcnMgaGF2ZSB0aGUgc2FtZSBpbmZvcm1hdGlvbi4NCg0KICBJbnZlc3RvcnMgY2FuIGJvcnJvdyBhbmQgbGVuZCB1bmxpbWl0ZWQgYW1vdW50cyBhdCB0aGUgcmlzay1mcmVlIHJhdGUgKE9SIHNob3J0IHNlbGxpbmcgc2hhbGwgYmUgYWxsb3dlZCkNCg0KICBObyB0YXhlcyBvciB0cmFuc2FjdGlvbiBjb3N0cy4NCg0KICBTaW5nbGUtcGVyaW9kIGludmVzdG1lbnQgaG9yaXpvbi4NCg0KDQojIyMjIFNlY3VyaXR5IE1hcmtldCBMaW5lIChTTUwpDQpBIGdyYXBoaWNhbCByZXByZXNlbnRhdGlvbiBvZiB0aGUgQ0FQTSwgc2hvd2luZyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gZXhwZWN0ZWQgcmV0dXJuIGFuZCBiZXRhLg0KQXNzZXRzIHBsb3R0ZWQgYWJvdmUgdGhlIFNNTCBhcmUgdW5kZXJ2YWx1ZWQ7IHRob3NlIGJlbG93IGFyZSBvdmVydmFsdWVkLiBUaGlzIGNhbiBoZWxwIHVzIGtub3cgKHJlYWxseSBhcHByb3hpbWF0ZWx5KSB3aGV0aGVyIGFuIGFzc2V0IHNoYWxsIGJlIGJvdWdodCBvciBzZWxsLiBJbiB0aGUgY2FzZSBvZiBhbiBhc3NldCBiZWluZyBvdmVydmFsdWVkLCB3ZSBzaG91bGQgc2VsbCBpdCBhcyBpdCB3aWxsIGV2ZW50dWFsbHkgZHJvcCB0byB0aGUgc2VjdXJpdHkgbWFya2V0IGxpbmUuIElmIGFuIGFzc2V0IGlzIHVuZGVydmFsdWVkLCB3ZSBzaG91bGQgYnV5IGl0IGFzIGl0cyBjdXJyZW50IHByaWNlIGRvZXMgbm90IHJlcHJlc2VudCB0aGUgbWFya2V0IHByaWNlIGl0IHNob3VsZCBoYXZlIGFuZCBpdCB3aWxsIGV2ZW50dWFsbHkgYXBwcmVjaWF0ZS4gDQoNCg0KIyMjIERpZmZlcmVuY2VzIEJldHdlZW4gQ0FQTSBhbmQgTWFya293aXR6IFBvcnRmb2xpbyBUaGVvcnkNCg0KIyMjIyAxLiBQdXJwb3NlIGFuZCBBcHBsaWNhdGlvbg0KDQoNCiMjIyMjIE1hcmtvd2l0eiBQb3J0Zm9saW8gVGhlb3J5Og0KDQpGb2N1c2VzIG9uIHBvcnRmb2xpbyBzZWxlY3Rpb24gYnkgb3B0aW1pemluZyB0aGUgdHJhZGUtb2ZmIGJldHdlZW4gZXhwZWN0ZWQgcmV0dXJuIGFuZCByaXNrLg0KSGVscHMgaW52ZXN0b3JzIGNvbnN0cnVjdCBhbiBlZmZpY2llbnQgcG9ydGZvbGlvIGJhc2VkIG9uIHRoZWlyIHJpc2sgdG9sZXJhbmNlLg0KDQoNCiMjIyMjIENBUE06DQoNCkZvY3VzZXMgb24gYXNzZXQgcHJpY2luZyBieSByZWxhdGluZyBleHBlY3RlZCByZXR1cm4gdG8gc3lzdGVtYXRpYyByaXNrLg0KUHJvdmlkZXMgYSB3YXkgdG8gcHJpY2UgaW5kaXZpZHVhbCBzZWN1cml0aWVzIGFuZCBkZXRlcm1pbmUgZXhwZWN0ZWQgcmV0dXJucyBiYXNlZCBvbiBtYXJrZXQgcmlzay4NCg0KDQojIyMjIDIuIFJpc2sgQ29uc2lkZXJhdGlvbg0KDQojIyMjIyBNYXJrb3dpdHo6DQoNCiAgQ29uc2lkZXJzIHRvdGFsIHJpc2sgKHN0YW5kYXJkIGRldmlhdGlvbiBvciB2YXJpYW5jZSksIGluY2x1ZGluZyBib3RoIHN5c3RlbWF0aWMgYW5kIHVuc3lzdGVtYXRpYyByaXNrLg0KDQogIEVtcGhhc2l6ZXMgdGhlIGltcG9ydGFuY2Ugb2YgZGl2ZXJzaWZpY2F0aW9uIHRvIHJlZHVjZSB1bnN5c3RlbWF0aWMgcmlzay4NCg0KDQojIyMjIyBDQVBNOg0KDQogIENvbnNpZGVycyBvbmx5IHN5c3RlbWF0aWMgcmlzayAoYmV0YSksIGFzc3VtaW5nIHVuc3lzdGVtYXRpYyByaXNrIGlzIGVsaW1pbmF0ZWQgdGhyb3VnaCBkaXZlcnNpZmljYXRpb24uDQoNCiAgQmV0YSBtZWFzdXJlcyB0aGUgYXNzZXQncyBzZW5zaXRpdml0eSB0byBtYXJrZXQgbW92ZW1lbnRzLg0KDQoNCiMjIyMgMy4gQXNzdW1wdGlvbnMgQWJvdXQgRGl2ZXJzaWZpY2F0aW9uDQoNCiMjIyMjIE1hcmtvd2l0ejoNCg0KICBBc3N1bWVzIGludmVzdG9ycyBjYW4gYW5kIHNob3VsZCBkaXZlcnNpZnkgdGhlaXIgcG9ydGZvbGlvcyB0byBvcHRpbWl6ZSByaXNrLXJldHVybiB0cmFkZS1vZmZzLg0KDQogIERpdmVyc2lmaWNhdGlvbiByZWR1Y2VzIHRvdGFsIHJpc2suDQoNCg0KIyMjIyMgQ0FQTToNCg0KICBBc3N1bWVzIGludmVzdG9ycyBhbHJlYWR5IGhvbGQgdGhlIG1hcmtldCBwb3J0Zm9saW8sIHdoaWNoIGlzIGZ1bGx5IGRpdmVyc2lmaWVkLg0KICBUaGVyZWZvcmUsIG9ubHkgc3lzdGVtYXRpYyByaXNrIG1hdHRlcnMgaW4gcHJpY2luZyBhc3NldHMuDQoNCg0KIyMjIyA0LiBPdXRwdXQgYW5kIFVzZQ0KDQojIyMjIyBNYXJrb3dpdHo6DQoNCiAgUHJvdmlkZXMgdGhlIGVmZmljaWVudCBmcm9udGllciBvZiBvcHRpbWFsIHBvcnRmb2xpb3MuDQoNCiAgSW52ZXN0b3JzIGNob29zZSBwb3J0Zm9saW9zIGJhc2VkIG9uIHRoZWlyIHJpc2sgcHJlZmVyZW5jZXMuDQoNCg0KIyMjIyMgQ0FQTToNCg0KICBQcm92aWRlcyB0aGUgZXhwZWN0ZWQgcmV0dXJuIG9mIGFuIGFzc2V0IGdpdmVuIGl0cyBiZXRhLg0KDQogIFVzZWQgdG8gYXNzZXNzIHdoZXRoZXIgYW4gYXNzZXQgaXMgZmFpcmx5IHByaWNlZC4NCg0KDQojIyMjIDUuIE1hcmtldCBFcXVpbGlicml1bQ0KDQojIyMjIyBNYXJrb3dpdHo6DQoNCiAgRG9lcyBub3QgYXNzdW1lIG1hcmtldCBlcXVpbGlicml1bTsgaXQncyBhIG5vcm1hdGl2ZSBtb2RlbCBzdWdnZXN0aW5nIGhvdyBpbnZlc3RvcnMgc2hvdWxkIGFsbG9jYXRlIGFzc2V0cy4NCg0KDQojIyMjIyBDQVBNOg0KDQogIEFzc3VtZXMgbWFya2V0IGVxdWlsaWJyaXVtIHdoZXJlIHN1cHBseSBhbmQgZGVtYW5kIGFyZSBiYWxhbmNlZC4NCg0KICBQcmljZXMgYWRqdXN0IHNvIHRoYXQgZXhwZWN0ZWQgcmV0dXJucyBhcmUgY29uc2lzdGVudCB3aXRoIHJpc2suDQoNCg0KIyMjIyA2LiBQcmFjdGljYWwgSW1wbGVtZW50YXRpb24NCg0KIyMjIyMgTWFya293aXR6Og0KDQogIENvbXB1dGF0aW9uYWxseSBpbnRlbnNpdmUsIGVzcGVjaWFsbHkgd2l0aCBtYW55IGFzc2V0cyBkdWUgdG8gdGhlIGNvdmFyaWFuY2UgbWF0cml4Lg0KDQogIFJlcXVpcmVzIGVzdGltYXRlcyBvZiBleHBlY3RlZCByZXR1cm5zLCB2YXJpYW5jZXMsIGFuZCBjb3ZhcmlhbmNlcy4NCg0KDQojIyMjIyBDQVBNOg0KDQogIFNpbXBsZXIgdG8gaW1wbGVtZW50IHNpbmNlIGl0IHJlcXVpcmVzIGVzdGltYXRpbmcgYmV0YSBhbmQgZXhwZWN0ZWQgbWFya2V0IHJldHVybi4NCiAgDQogIEJldGEgY2FuIGJlIGVzdGltYXRlZCB1c2luZyByZWdyZXNzaW9uIGFuYWx5c2lzIG9uIGhpc3RvcmljYWwgZGF0YS4NCg0KDQojIyMgUiBJbXBsZW1lbnRhdGlvbiBFeGFtcGxlDQpUbyBpbGx1c3RyYXRlIHRoZSBkaWZmZXJlbmNlcywgd2UgY2FuIHVzZSBSIHRvIHBlcmZvcm0gYm90aCBhIE1hcmtvd2l0eiBwb3J0Zm9saW8gb3B0aW1pemF0aW9uIGFuZCBhIENBUE0gYW5hbHlzaXMuDQoNCiMjIyMgTWFya293aXR6IFBvcnRmb2xpbyBPcHRpbWl6YXRpb24NCg0KTG9hZCBsaWJyYXJpZXMNCg0KYGBge3J9DQojIEluc3RhbGwgYW5kIGxvYWQgcmVxdWlyZWQgcGFja2FnZXMNCmlmICghcmVxdWlyZSgicXVhbnRtb2QiKSkgaW5zdGFsbC5wYWNrYWdlcygicXVhbnRtb2QiKQ0KaWYgKCFyZXF1aXJlKCJQb3J0Zm9saW9BbmFseXRpY3MiKSkgaW5zdGFsbC5wYWNrYWdlcygiUG9ydGZvbGlvQW5hbHl0aWNzIikNCmlmICghcmVxdWlyZSgiUk9JIikpIGluc3RhbGwucGFja2FnZXMoIlJPSSIpDQppZiAoIXJlcXVpcmUoIlJPSS5wbHVnaW4ucXVhZHByb2ciKSkgaW5zdGFsbC5wYWNrYWdlcygiUk9JLnBsdWdpbi5xdWFkcHJvZyIpDQppZiAoIXJlcXVpcmUoIlBlcmZvcm1hbmNlQW5hbHl0aWNzIikpIGluc3RhbGwucGFja2FnZXMoIlBlcmZvcm1hbmNlQW5hbHl0aWNzIikNCg0KbGlicmFyeShxdWFudG1vZCkNCmxpYnJhcnkoUG9ydGZvbGlvQW5hbHl0aWNzKQ0KbGlicmFyeShST0kpDQpsaWJyYXJ5KFJPSS5wbHVnaW4ucXVhZHByb2cpDQpsaWJyYXJ5KFBlcmZvcm1hbmNlQW5hbHl0aWNzKQ0KYGBgDQoNCg0KUmV0cmlldmUgZGF0YQ0KDQpgYGB7cn0NCiMgRGVmaW5lIGEgc2V0IG9mIGFzc2V0cw0Kc3ltYm9scyA8LSBjKCJBQVBMIiwgIk1TRlQiLCAiR09PRyIsICJBTVpOIikNCg0KIyBHZXQgaGlzdG9yaWNhbCBwcmljZSBkYXRhDQpnZXRTeW1ib2xzKHN5bWJvbHMsIGZyb20gPSAiMjAyMC0wMS0wMSIsIHRvID0gIjIwMjMtMDEtMDEiKQ0KYGBgDQoNCg0KTWVyZ2UgRGF0YSBhbmQgb2J0YWluIHJldHVybnMgKGVsaW1pbmF0aW5nIG5vbi1leGlzdGluZyBkYXRhKQ0KDQpgYGB7cn0NCiMgTWVyZ2UgYWRqdXN0ZWQgY2xvc2luZyBwcmljZXMNCnByaWNlcyA8LSBkby5jYWxsKG1lcmdlLCBsYXBwbHkoc3ltYm9scywgZnVuY3Rpb24oeCkgQWQoZ2V0KHgpKSkpDQoNCiMgQ2FsY3VsYXRlIHJldHVybnMNCnJldHVybnMgPC0gbmEub21pdChSZXR1cm4uY2FsY3VsYXRlKHByaWNlcykpDQpgYGANCg0KDQpDcmVhdGUgcG9ydGZvbGlvIHNwZWNpZmljYXRpb25zIGFuZCBvcHRpbWl6ZSBpdA0KDQpgYGB7cn0NCiMgQ3JlYXRlIHBvcnRmb2xpbyBzcGVjaWZpY2F0aW9uDQpwb3J0X3NwZWMgPC0gcG9ydGZvbGlvLnNwZWMoYXNzZXRzID0gc3ltYm9scykNCnBvcnRfc3BlYyA8LSBhZGQuY29uc3RyYWludChwb3J0X3NwZWMsIHR5cGUgPSAiZnVsbF9pbnZlc3RtZW50IikNCnBvcnRfc3BlYyA8LSBhZGQuY29uc3RyYWludChwb3J0X3NwZWMsIHR5cGUgPSAibG9uZ19vbmx5IikNCnBvcnRfc3BlYyA8LSBhZGQub2JqZWN0aXZlKHBvcnRfc3BlYywgdHlwZSA9ICJyaXNrIiwgbmFtZSA9ICJTdGREZXYiKQ0KcG9ydF9zcGVjIDwtIGFkZC5vYmplY3RpdmUocG9ydF9zcGVjLCB0eXBlID0gInJldHVybiIsIG5hbWUgPSAibWVhbiIpDQoNCiMgT3B0aW1pemUgcG9ydGZvbGlvIHRvIGZpbmQgdGhlIG1pbmltdW0gdmFyaWFuY2UgcG9ydGZvbGlvDQpvcHRfcG9ydCA8LSBvcHRpbWl6ZS5wb3J0Zm9saW8oUiA9IHJldHVybnMsIHBvcnRmb2xpbyA9IHBvcnRfc3BlYywgb3B0aW1pemVfbWV0aG9kID0gIlJPSSIpDQpgYGANCg0KDQpDcmVhdGUgZGF0YSBmcmFtZSBhbmQgcHJpbnQgcmVzdWx0cw0KDQpgYGB7cn0NCm1hcmtvd2l0el9yZXN1bHRzIDwtIGRhdGEuZnJhbWUoDQogIFN0b2NrID0gc3ltYm9scywNCiAgV2VpZ2h0cyA9IG9wdF9wb3J0JHdlaWdodHMNCikNCnByaW50KG1hcmtvd2l0el9yZXN1bHRzKQ0KYGBgDQoNCg0KQ29uc3RydWN0IGZpbmFsIHBvcnRmb2xpbyByZXR1cm5zIHJldHVybnMgZnJvbSB0aGUgb3B0aW1pemVkIHdlaWdodHMNCg0KYGBge3J9DQpmaW5hbF9wb3J0Zm9saW9fcmV0dXJucyA8LSBSZXR1cm4ucG9ydGZvbGlvKFIgPSByZXR1cm5zLCB3ZWlnaHRzID0gb3B0X3BvcnQkd2VpZ2h0cykNCmBgYA0KDQoNCkNvbXB1dGUgYW5udWFsaXplZCBzdGF0aXN0aWNzIChyZXR1cm4sIHN0YW5kYXJkIGRldmlhdGlvbiwgU2hhcnBlIHJhdGlvLCBldGMuKQ0KDQpgYGB7cn0NCmFubnVhbF9zdGF0cyA8LSB0YWJsZS5Bbm51YWxpemVkUmV0dXJucyhmaW5hbF9wb3J0Zm9saW9fcmV0dXJucykNCnByaW50KGFubnVhbF9zdGF0cykNCmBgYA0KDQojIyMjIyBBbm51YWxpemVkIFJldHVybiAoMjAuMzYlKQ0KDQpUaGlzIGltcGxpZXMgdGhhdCwgaWYgdGhlIGRhaWx5IHJldHVybnMgb2JzZXJ2ZWQgZHVyaW5nIG91ciBoaXN0b3JpY2FsIHNhbXBsZSBwZXJpb2Qgd2VyZSB0byBjb250aW51ZSwgdGhlIHBvcnRmb2xpbyB3b3VsZCBlYXJuIHJvdWdobHkgMjAlIHBlciB5ZWFyLiBJdCBpcyBpbXBvcnRhbnQgdG8gcmVtZW1iZXIgdGhhdCB0aGlzIHJldHVybiBpcyBoaXN0b3JpY2FsbHkgYmFzZWQgYW5kIG5vdCBhIGd1YXJhbnRlZWQgZnV0dXJlIHBlcmZvcm1hbmNlLg0KDQojIyMjIyBBbm51YWxpemVkIFN0YW5kYXJkIERldmlhdGlvbiAoMzYuMTclKQ0KDQpBIHN0YW5kYXJkIGRldmlhdGlvbiBvZiAzNiUgaW5kaWNhdGVzIGEgcmVsYXRpdmVseSBoaWdoIGxldmVsIG9mIHZvbGF0aWxpdHkuIEluIHByYWN0aWNhbCB0ZXJtcywgdGhlIHBvcnRmb2xpb+KAmXMgdmFsdWUgY291bGQgZmx1Y3R1YXRlIHNpZ25pZmljYW50bHkgYXJvdW5kIGl0cyBhdmVyYWdlIHJldHVybi4gSW52ZXN0b3JzIG5lZWQgdG8gZGVjaWRlIGlmIHRoaXMgbGV2ZWwgb2YgcmlzayBhbGlnbnMgd2l0aCB0aGVpciByaXNrIHRvbGVyYW5jZS4NCg0KIyMjIyMgQW5udWFsaXplZCBTaGFycGUgUmF0aW8gKDAuNTYyOSkNCg0KVGhlIFNoYXJwZSBSYXRpbyBtZWFzdXJlcyB0aGUgcG9ydGZvbGlv4oCZcyByaXNrLWFkanVzdGVkIHJldHVybi4gQSByYXRpbyBvZiAwLjU2IGluZGljYXRlcyB0aGF0LCBoaXN0b3JpY2FsbHksIHRoZSBwb3J0Zm9saW/igJlzIHJldHVybiBleGNlZWRlZCB0aGUgcmlzay1mcmVlIHJhdGUgYnkgMC41NiUgZm9yIGV2ZXJ5IDElIG9mIHZvbGF0aWxpdHkuIFdoaWxlIGEgU2hhcnBlIFJhdGlvIGFib3ZlIDEuMCBpcyBvZnRlbiBjb25zaWRlcmVkIHN0cm9uZywgYSByYXRpbyBhcm91bmQgMC414oCTMC43IGNhbiBiZSB2aWV3ZWQgYXMgYWNjZXB0YWJsZSBvciBtb2RlcmF0ZSwgZGVwZW5kaW5nIG9uIHRoZSBhc3NldCBjbGFzcy4NCg0KDQojIyMjIENBUE0gQW5hbHlzaXMNCg0KTG9hZCBsaWJyYXJpZXMgYW5kIHJldHJpZXZlIGRhdGENCg0KYGBge3J9DQpsaWJyYXJ5KHF1YW50bW9kKQ0KbGlicmFyeShQZXJmb3JtYW5jZUFuYWx5dGljcykNCg0KIyBEZWZpbmUgdGhlIHN0b2NrIHN5bWJvbHMNCnN5bWJvbHMgPC0gYygiQUFQTCIsICJNU0ZUIiwgIkdPT0ciLCAiQU1aTiIpDQoNCiMgR2V0IGhpc3RvcmljYWwgZGF0YSBmb3IgYXNzZXRzIGFuZCBtYXJrZXQNCmdldFN5bWJvbHMoYyhzeW1ib2xzLCAiXkdTUEMiKSwgZnJvbSA9ICIyMDE4LTAxLTAxIiwgdG8gPSAiMjAyMy0xMi0zMSIpDQpgYGANCg0KDQpEZWZpbmUgYmV0YXMsIGV4cGVjdGVkIHJldHVybnMsIHJpc2sgZnJlZSByYXRlIGFuZCBvbWl0IG5vbi1leGlzdGVudCBkYXRhIGluIHJldHVybnMNCg0KYGBgIHtyfQ0KIyBJbml0aWFsaXplIHZlY3RvcnMgdG8gc3RvcmUgYmV0YXMgYW5kIGV4cGVjdGVkIHJldHVybnMNCmJldGFzIDwtIG51bWVyaWMobGVuZ3RoKHN5bWJvbHMpKQ0KZXhwZWN0ZWRfcmV0dXJucyA8LSBudW1lcmljKGxlbmd0aChzeW1ib2xzKSkNCg0KIyBEZWZpbmUgdGhlIGFubnVhbCByaXNrLWZyZWUgcmF0ZQ0Kcmlza19mcmVlX3JhdGUgPC0gMC4wMyAgIyAzJQ0KDQojIENhbGN1bGF0ZSBkYWlseSBtYXJrZXQgcmV0dXJucw0KbWFya2V0X3JldHVybnMgPC0gbmEub21pdChST0MoQWQoR1NQQykpKQ0KYGBgDQoNCg0KQ2FsY3VsYXRlIGJldGFzIGFuZCBleHBlY3RlZCByZXR1cm5zDQoNCmBgYCB7cn0NCiMgTG9vcCBvdmVyIGVhY2ggc3ltYm9sIHRvIGNhbGN1bGF0ZSBiZXRhIGFuZCBleHBlY3RlZCByZXR1cm4NCmZvciAoaSBpbiAxOmxlbmd0aChzeW1ib2xzKSkgew0KICAjIEdldCBzdG9jayByZXR1cm5zDQogIHN0b2NrX2RhdGEgPC0gZ2V0KHN5bWJvbHNbaV0pDQogIHN0b2NrX3JldHVybnMgPC0gbmEub21pdChST0MoQWQoc3RvY2tfZGF0YSkpKQ0KICANCiAgIyBBbGlnbiBkYXRlcyB3aXRoIG1hcmtldCByZXR1cm5zDQogIHJldHVybnNfZGF0YSA8LSBtZXJnZShzdG9ja19yZXR1cm5zLCBtYXJrZXRfcmV0dXJucywgYWxsID0gRkFMU0UpDQogIA0KICAjIENhbGN1bGF0ZSBiZXRhDQogIGJldGEgPC0gQ0FQTS5iZXRhKFJhID0gcmV0dXJuc19kYXRhWywxXSwgUmIgPSByZXR1cm5zX2RhdGFbLDJdKQ0KICBiZXRhc1tpXSA8LSBiZXRhDQoNCiAgIyBDYWxjdWxhdGUgZXhwZWN0ZWQgcmV0dXJuIHVzaW5nIENBUE0NCiAgYW5udWFsX21hcmtldF9yZXR1cm4gPC0gbWVhbihyZXR1cm5zX2RhdGFbLDJdKSAqIDI1MiAgIyBBbm51YWxpemUgbWFya2V0IHJldHVybg0KICBleHBlY3RlZF9yZXR1cm4gPC0gcmlza19mcmVlX3JhdGUgKyBiZXRhICogKGFubnVhbF9tYXJrZXRfcmV0dXJuIC0gcmlza19mcmVlX3JhdGUpDQogIGV4cGVjdGVkX3JldHVybnNbaV0gPC0gZXhwZWN0ZWRfcmV0dXJuDQogIA0KICAjIFByaW50IHJlc3VsdHMgZm9yIGVhY2ggc3RvY2sNCiAgY2F0KCJTdG9jazoiLCBzeW1ib2xzW2ldLCAiXG4iKQ0KICBjYXQoIkJldGE6Iiwgcm91bmQoYmV0YSwgNCksICJcbiIpDQogIGNhdCgiRXhwZWN0ZWQgUmV0dXJuOiIsIHJvdW5kKGV4cGVjdGVkX3JldHVybiAqIDEwMCwgMiksICIlXG5cbiIpDQp9DQoNCmBgYA0KDQoNCkNyZWF0ZSBkYXRhIGZyYW1lIGFuZCBwcmludCByZXN1bHRzDQoNCmBgYHtyfQ0KIyBDcmVhdGUgYSBkYXRhIGZyYW1lIHdpdGggdGhlIHJlc3VsdHMNCmNhcG1fcmVzdWx0cyA8LSBkYXRhLmZyYW1lKA0KICBTdG9jayA9IHN5bWJvbHMsDQogIEJldGEgPSByb3VuZChiZXRhcywgNCksDQogIEV4cGVjdGVkX1JldHVybiA9IHJvdW5kKGV4cGVjdGVkX3JldHVybnMgKiAxMDAsIDIpDQopDQoNCnByaW50KGNhcG1fcmVzdWx0cykNCmBgYA0KDQoNCg0KIyMjIENvbmNsdXNpb25zDQoNCk1hcmtvd2l0eiBQb3J0Zm9saW8gVGhlb3J5IGZvY3VzZXMgb24gY29uc3RydWN0aW5nIG9wdGltYWwgcG9ydGZvbGlvcyBieSBjb25zaWRlcmluZyB0b3RhbCByaXNrIGFuZCByZXR1cm4sIGhlbHBpbmcgaW52ZXN0b3JzIG1ha2UgZGVjaXNpb25zIGJhc2VkIG9uIHRoZWlyIHJpc2sgdG9sZXJhbmNlLg0KQ0FQTSBwcm92aWRlcyBhIG1ldGhvZCB0byBwcmljZSBpbmRpdmlkdWFsIGFzc2V0cyBieSByZWxhdGluZyBleHBlY3RlZCByZXR1cm5zIHRvIHN5c3RlbWF0aWMgcmlzaywgYXNzdW1pbmcgaW52ZXN0b3JzIGhvbGQgZGl2ZXJzaWZpZWQgcG9ydGZvbGlvcy4NCg0KVGhlIG1haW4gZGlmZmVyZW5jZSBsaWVzIGluIHRoZWlyIHRyZWF0bWVudCBvZiByaXNrOg0KICBNYXJrb3dpdHogY29uc2lkZXJzIGJvdGggc3lzdGVtYXRpYyBhbmQgdW5zeXN0ZW1hdGljIHJpc2suDQogIENBUE0gY29uc2lkZXJzIG9ubHkgc3lzdGVtYXRpYyByaXNrLCBhcyB1bnN5c3RlbWF0aWMgcmlzayBpcyBhc3N1bWVkIHRvIGJlIGRpdmVyc2lmaWVkIGF3YXkuDQoNCkluIHRoZSByZXN1bHRzIHdlIGNhbiBzZWUgdGhhdCB0aGUgb3V0Y29tZSBvZiB0aGUgTWFya293aXR6IG9wdGltaXphdGlvbiBpcyB0aGUgd2VpZ2h0IG9mIGVhY2ggYXNzZXQgaW4gdGhlIHBvcnRmb2xpbywgd2hlcmVhcyBvdXIgb3V0Y29tZSBmcm9tIHRoZSBDQVBNIGlzIHRoZSBiZXRhcyBhbmQgZXhwZWN0ZWQgcmV0dXJucyBvZiB0aGUgYXNzZXQuIA0KDQoNCiMjIyBJbXBsaWNhdGlvbnMgZm9yIEludmVzdG9ycw0KDQojIyMjIFBvcnRmb2xpbyBDb25zdHJ1Y3Rpb246DQoNCiAgVXNlIE1hcmtvd2l0eidzIGZyYW1ld29yayB0byBidWlsZCBhIGRpdmVyc2lmaWVkIHBvcnRmb2xpbyB0aGF0IGFsaWducyB3aXRoIHJpc2sgcHJlZmVyZW5jZXMuDQoNCg0KIyMjIyBBc3NldCBQcmljaW5nIGFuZCBFeHBlY3RlZCBSZXR1cm5zOg0KDQogIFVzZSBDQVBNIHRvIGVzdGltYXRlIHRoZSBleHBlY3RlZCByZXR1cm4gb2YgYW4gYXNzZXQgYmFzZWQgb24gaXRzIG1hcmtldCByaXNrIGFuZCB0byBhc3Nlc3Mgd2hldGhlciBpdCdzIG92ZXJ2YWx1ZWQgb3IgdW5kZXJ2YWx1ZWQuDQoNCg0KIyMjIEZpbmFsIGNvbW1lbnRzLiANCg0KV2UgaGF2ZSBvYnNlcnZlZCB0aGFua3MgdG8gb3VyIHJlcHJlc2VudGF0aW9ucyB0aGF0IGV2ZW4gaWYgYm90aCBtb2RlbHMgaGF2ZSBhIHNpbWlsYXIgb2JqZWN0aXZlLCB3aGljaCBpcyB0aGUgb3B0aW1pemF0aW9uIG9mIHRoZSByZXR1cm5zIGZvciB0aGUgaW52ZXN0b3JzLCBlYWNoIG9uZSBkb2VzIGl0IGluIGEgd2hvbGUgZGlmZmVyZW50IHdheSwgd2l0aCBkaWZmZXJlbnQgYXNzdW1wdGlvbnMsIGRpZmZlcmVudCB0cmVhdG1lbnQgb2YgcmlzayBhbmQgd2l0aCBhIGRpZmZlcmVudCByZXN1bHRzIHNjb3BlLiANCg0KDQoNCiMjIEwxMCBXQUNDDQoNCiMjIyBXQUNDIHJlcGxpY2F0aW9uDQoNCkxvYWQgbGlicmFyeQ0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShxdWFudG1vZCkNCmBgYA0KDQoNClJldHJpZXZlIHN0b2NrIGRhdGENCg0KYGBge3J9DQpnZXRTeW1ib2xzKCJBQVBMIikNCmBgYA0KDQoNCkRlZmluZSB0aGUgTnVtYmVyIG9mIE91dHN0YW5kaW5nIFNoYXJlcw0KDQpgYGB7cn0NCm91dHN0YW5kaW5nX3NoYXJlcyA8LSAxNjAwMDAwMDAwMCAgIyAxNiBiaWxsaW9uIHNoYXJlcw0KYGBgDQoNCg0KQ2FsY3VsYXRlIE1hcmtldCBDYXBpdGFsaXphdGlvbg0KDQpgYGB7cn0NCm1hcmtldF9jYXAgPC0gbGFzdChBQVBMJEFBUEwuQWRqdXN0ZWQpICogb3V0c3RhbmRpbmdfc2hhcmVzDQpgYGANCg0KDQpEZWZpbmUgdGhlIENvc3Qgb2YgRGVidA0KDQpgYGB7cn0NCmNvc3Rfb2ZfZGVidCA8LSAwLjAyICAjIDIlDQpgYGANCg0KDQpEZWZpbmUgVGF4IFJhdGUgQXBwbGljYWJsZSB0byBBcHBsZQ0KDQpgYGB7cn0NCnRheF9yYXRlIDwtIDAuMjEgICMgMjElDQpgYGANCg0KDQpPYnRhaW4gQmV0YSBmb3IgQXBwbGUncyBTdG9jaw0KDQpgYGB7cn0NCmJldGEgPC0gMS4yICAjIEJldGEgb2YgMS4yIGluZGljYXRlcyBoaWdoZXIgdm9sYXRpbGl0eSB0aGFuIHRoZSBtYXJrZXQNCmBgYA0KDQoNCkRlZmluZSB0aGUgUmlzay1GcmVlIFJhdGUNCg0KYGBge3J9DQpyaXNrX2ZyZWVfcmF0ZSA8LSAwLjAxNSANCmBgYA0KDQoNCkRlZmluZSB0aGUgTWFya2V0IFJpc2sgUHJlbWl1bQ0KDQpgYGB7cn0NCm1hcmtldF9yaXNrX3ByZW1pdW0gPC0gMC4wNg0KYGBgDQoNCg0KQ2FsY3VsYXRlIHRoZSBDb3N0IG9mIEVxdWl0eSB1c2luZyBDQVBNIE1vZGVsDQoNCmBgYHtyfQ0KY29zdF9vZl9lcXVpdHkgPC0gcmlza19mcmVlX3JhdGUgKyBiZXRhICogbWFya2V0X3Jpc2tfcHJlbWl1bQ0KYGBgDQoNCg0KRGVmaW5lIHRoZSBNYXJrZXQgVmFsdWUgb2YgRGVidA0KDQpgYGB7cn0NCm1hcmtldF92YWx1ZV9vZl9kZWJ0IDwtIDEwMGU5ICAjICQxMDAgYmlsbGlvbg0KYGBgDQoNCg0KQ2FsY3VsYXRlIFRvdGFsIE1hcmtldCBWYWx1ZQ0KDQpgYGB7cn0NCnRvdGFsX21hcmtldF92YWx1ZSA8LSBtYXJrZXRfY2FwICsgbWFya2V0X3ZhbHVlX29mX2RlYnQNCmBgYA0KDQoNCkNhbGN1bGF0ZSBXZWlnaHRzIG9mIERlYnQgYW5kIEVxdWl0eQ0KDQpgYGB7cn0NCndlaWdodF9vZl9kZWJ0IDwtIG1hcmtldF92YWx1ZV9vZl9kZWJ0IC8gdG90YWxfbWFya2V0X3ZhbHVlDQp3ZWlnaHRfb2ZfZXF1aXR5IDwtIG1hcmtldF9jYXAgLyB0b3RhbF9tYXJrZXRfdmFsdWUNCmBgYA0KDQoNCkNhbGN1bGF0ZSBXQUNDDQoNCmBgYHtyfQ0Kd2FjYyA8LSAod2VpZ2h0X29mX2RlYnQgKiBjb3N0X29mX2RlYnQgKiAoMSAtIHRheF9yYXRlKSkgKyAod2VpZ2h0X29mX2VxdWl0eSAqIGNvc3Rfb2ZfZXF1aXR5KQ0KYGBgDQoNCg0KRGlzcGxheSB0aGUgV0FDQw0KDQpgYGB7cn0NCmNhdCgiV0FDQyBmb3IgQXBwbGUgSW5jLjoiLCByb3VuZCh3YWNjICogMTAwLCAyKSwgIiUiKQ0KYGBgDQoNCg0KIyMjIEFuYWx5c2lzIG9mIHJlc3VsdHMuDQoNCkluIHRoaXMgZXhlcmNpc2Ugd2UgaGF2ZSByZXBsaWNhdGVkIGEgYmFzaWMgZXhhbXBsZSBvZiBXQUNDLiANCldBQ0MgcmVwcmVzZW50cyB0aGUgbWluaW11bSBhdmVyYWdlIHJldHVybiBBcHBsZSBtdXN0IGVhcm4gb24gaXRzIGV4aXN0aW5nIGFzc2V0cyB0byBzYXRpc2Z5IGl0cyBpbnZlc3RvcnMgYW5kIGNyZWRpdG9ycywgd2hpY2ggaW4gdGhpcyBjYXNlIG11c3QgYmUgOC41MiUuDQpUaGUgbG93ZXIgdGhlIFdBQ0MsIHRoZSBtb3JlIHByb2plY3RzIHRoZSBjb21wYW55IGNhbiB0YWtlIG9uIGdpdmVuIHRoZXkgaGF2ZSBwb3NpdGl2ZSBuZXQgcHJlc2VudCB2YWx1ZXMuIA0KV0FDQyBtYXkgdXNlIGluIGl0cyBjYWxjdWxhdGlvbnMgdGhlIGFmdGVyLXRheCBjb3N0IG9mIGRlYnQsIGFzIGludGVyZXN0IGlzIHRheC1kZWR1Y3RpYmxlLg0KQSBnb29kIGFzc2Vzc21lbnQgaW4gdGhlIG1peCBvZiBkZWJ0IGFuZCBlcXVpdHkgZmluYW5jaW5nIGlzIGNydWNpYWwgZm9yIHRoZSBzdGFiaWxpdHkgb2YgYSBjb21wYW55IGFuZCBpdHMgY2FwaXRhbCBzdHJ1Y3R1cmUuIA0KDQpUaGUgV0FDQyBhcHByb2FjaGVkIG1heSBiZSB1c2VkIGFzIGEgcG93ZXJmdWwgdG9vbCB0byBhc3NlcyBkaWZmZXJlbnQga2luZHMgb2Ygc2l0dWF0aW9uIHRoYXQgYSBjb21wYW55IG1heSBmYWNlLCBzdWNoIGFzIHByb2plY3QgZXZhbHVhdGlvbiwgY29ycG9yYXRlIGZpbmFuY2UgZGVjaXNpb25zIChtJkEgYW5kIGNhcGl0YWwgYnVkZ2V0aW5nKS4gSXQgaXMgYWxzbyBhIHVzZWZ1bCB0b29sIHVzZWQgZm9yIGludmVzdG9yIGFuYWx5c2lzLiANCg0KDQoNCiMjIEwxMS4xIC0gTDExLjYNCg0KDQojIyMgRGVmaW5pdGlvbnMNCg0KIyMjIyBGdXR1cmVzIENvbnRyYWN0DQoNCkEgZnV0dXJlcyBjb250cmFjdCBpcyBhIGZpbmFuY2lhbCBkZXJpdmF0aXZlIHVwb24gc29tZW9uZSBhZ3JlZXMgdG8gYnV5IG9yIHNlbGwgYSBkZXRlcm1pbmF0ZSBjb21tb2RpdHkgYXNzZXQgb3Igc2VjdXJpdHkgYXQgYW4gcHJlZGV0ZXJtaW5lZCBwcmljZSBhbmQgYW4gc3BlY2lmaWMgdGltZSBpbiB0aGUgZnV0dXJlLiBUaGUgYnV5ZXIgYWdyZWVzIGFuZCBiZWNvbWVzIG9ibGlnZWQgdG8gYnV5IGFuZCByZWNlaXZlIHRoZSBhc3NldCB3aGVyZWFzIHRoZSBzZWxsZXIgYWdyZWVzIHRvIHByb3ZpZGUgYW5kIG1ha2UgZGVsaXZlciBvZiB0aGUgYXNzZXQuIA0KDQojIyMjIENhbGwgT3B0aW9uDQoNCkEgY2FsbCBvcHRpb24gaXMgYSB0eXBlIG9mIGZpbmFuY2lhbCBjb250cmFjdCB3aGVyZSB0aGUgYnV5ZXIgaXMgZ2l2ZW4gdGhlIHJpZ2h0IHRvIGJ1eSBhIGNlcnRhaW4gYXNzZXQgb3IgaW5zdHJ1bWVudCBhdCBhbiBzcGVjaWZpZWQgcHJpY2UgYW5kIHRpbWUuIFRoZSBzZWxsZXIgb24gdGhlIG90aGVyIGhhbmQgaXMgb2JsaWdlZCB0byBzZWxsIHRoZSBhc3NldCBpZiB0aGUgYnV5ZXIgZXhlcmNpc2VzIHRoZSBjYWxsLiANClRoZSBvcHRpb24gaXMgYm91Z2h0IHVuZGVyIGEgcHJlbWl1bSwgc28gaWYgdGhlIGFzc2V0IGdvZXMgZG93biBpbiBwcmljZSBhbmQgdGhlIGJ1eWVyIGRvZXMgbm90IGV4ZWN1dGUgdGhlIG9wdGlvbiwgdGhlIHNlbGxlciB3aWxsIHByb2ZpdCBmcm9tIHRoZSBwcmVtaXVtLiBIb3dldmVyLCBpZiB0aGUgYXNzZXQgcHJpY2UgaW5jcmVhc2VzIGFuZCB0aGUgYnV5ZXIgZXhlY3V0ZXMgdGhlIG9wdGlvbiwgdGhlIHByb2ZpdCB0aGUgYnV5ZXIgd2lsbCBoYXZlIGlzIHRoZSBlbmQgdmFsdWUgb2YgdGhlIHN0b2NrIChwYXlvZmYpIG1pbnVzIHRoZSBwcmVtaXVtIHBhaWQgZm9yIHRoZSBvcHRpb24uIA0KQ2FsbCBvcHRpb25zIGhhdmUgbGltaXRlZCBsb3NlcyBmb3IgdGhlIGJ1eWVycyAodGhlIHByZW1pdW0gaXMgdGhlIG1heGltdW0gbG9zcykgYnV0IGhhcyBubyBwcm9maXQgbGltaXQuIA0KQ2FsbCBvcHRpb25zIGFyZSBkaXZpZGVkIGludG8gTG9uZyBDYWxsIE9wdGlvbnMgYW5kIFNob3J0IENhbGwgT3B0aW9ucyhpbiB0aGUgc2hvcnQgY2FsbCBvcHRpb25zLCBpdCBpcyB0aGUgc2VsbGVyIHRoZSBvbmUgd2hvIHByb21pc2VzIHRvIHNlbGwgYW4gYXNzZXQgYXQgYSBjZXJ0YWluIHByaWNlIGluIHRoZSBkYXRlIG9mIGV4cGlyYXRpb24pDQoNCldoZW4gdXNpbmcgY2FsbCBvcHRpb25zLCBpdCBpcyBvZnRlbiB0byBpbXBsZW1lbnQgYW4gc3RyYXRlZ3kgY2FsbGVkIGhlZGdpbmcsIGluIHdoaWNoIHlvdSBhbHNvIHRha2UgdGhlIG9wcG9zaXRlIHBvc2l0aW9uIGluIG9yZGVyIHRvIG1pdGlnYXRlIHBvdGVudGlhbCBsb3NzZXMuIFRoYXQgaXMsIHRoYXQgaWYgd2UgYXJlIHVzaW5nIGNhbGwgb3B0aW9ucywgd2UgbWlnaHQgYWxzbyBidXkgcHV0IG9wdGlvbnMgZm9yIHRoZSBzYW1lIGFzc2V0IHNvIHRoYXQgd2UgY2FuIHJlZHVjZSB0aGUgbG9zc2VzIGluIHRoZSBjYXNlIHRoYXQgdGhlIHN0cmlraW5nIHByaWNlIGlzIG5vdCByZWFjaGVkIGF0IHRoZSBkYXRlIG9mIGV4cGlyYXRpb24uIA0KDQoNCkxvYWQgUGFja2FnZXMNCg0KYGBge3J9DQojIExvYWQgcmVxdWlyZWQgcGFja2FnZXMNCmxpYnJhcnkocXVhbnRtb2QpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpDQpgYGANCg0KDQpEZWZpbmUgQmVnaW5uaW5nIGFuZCBFbmQgb2YgVGVybSBEYXRlcw0KDQpgYGB7cn0NCiMgRGVmaW5lIEJlZ2lubmluZyBvZiBUZXJtIChCb1QpIGFuZCBFbmQgb2YgVGVybSAoRW9UKSBkYXRlcw0KQm9UX2RhdGUgPC0gYXMuRGF0ZSgiMjAyNC0wNS0wMSIpDQpFb1RfZGF0ZSA8LSBhcy5EYXRlKCIyMDI0LTA5LTMwIikNCmBgYA0KDQoNCg0KIyMjIEwxMS4xIENhbGN1bGF0aW5nIHRoZSBEaWZmZXJlbmNlIGluIHRoZSBEb2xsYXIgVmFsdWUgb2YgdGhlIFMmUCA1MDAgRnV0dXJlcyBDb250cmFjdA0KIA0KICAtWW91IHB1cmNoYXNlZCBhbiBTJlAgNTAwIGZ1dHVyZXMgY29udHJhY3QgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgdGVybS4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIC1Zb3Ugc29sZCB0aGUgc2FtZSBmdXR1cmVzIGNvbnRyYWN0IGF0IHRoZSBlbmQgb2YgdGhlIHRlcm0uDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgLVRoZSBjb250cmFjdCB2YWx1ZSBpcyBmdXR1cmVzIHByaWNlIHRpbWVzICQyNTAuDQoNClNpbmNlIGdldHRpbmcgaGlzdG9yaWNhbCBmdXR1cmVzIHByaWNlcyBjYW4gYmUgY2hhbGxlbmdpbmcsIHdlJ2xsIHVzZSB0aGUgUyZQIDUwMCBpbmRleCAoXkdTUEMpIGFzIGEgcHJveHkgZm9yIHRoZSBmdXR1cmVzIHByaWNlcy4NCsK0DQoNCjEuIFJldHJpZXZlIFMmUDUwMCBpbmRleCBkYXRhDQoNCmBgYHtyfQ0Kc3RhcnRfZGF0ZSA8LSBCb1RfZGF0ZSAtIDcNCmVuZF9kYXRlIDwtIEVvVF9kYXRlICsgNw0KDQpnZXRTeW1ib2xzKCJeR1NQQyIsIHNyYyA9ICJ5YWhvbyIsIGZyb20gPSBzdGFydF9kYXRlLCB0byA9IGVuZF9kYXRlKQ0KDQpgYGANCg0KDQoyLiBEZWZpbmUgYSBGdW5jdGlvbiB0byBHZXQgUHJpY2VzIG9uIFNwZWNpZmljIERhdGVzDQoNCmBgYHtyfQ0KIyBGdW5jdGlvbiB0byBnZXQgdGhlIGFkanVzdGVkIGNsb3NpbmcgcHJpY2Ugb24gYSBzcGVjaWZpYyBkYXRlDQpnZXRfcHJpY2Vfb25fZGF0ZSA8LSBmdW5jdGlvbihkYXRhLCBkYXRlKSB7DQogIGluZGV4KGRhdGEpIDwtIGFzLkRhdGUoaW5kZXgoZGF0YSkpDQogIA0KICBhdmFpbGFibGVfZGF0ZXMgPC0gaW5kZXgoZGF0YSlbaW5kZXgoZGF0YSkgPD0gZGF0ZV0NCiAgDQogIGlmIChsZW5ndGgoYXZhaWxhYmxlX2RhdGVzKSA9PSAwKSB7DQogICAgd2FybmluZyhwYXN0ZSgiTm8gZGF0YSBhdmFpbGFibGUgb24gb3IgYmVmb3JlIiwgZGF0ZSkpDQogICAgcmV0dXJuKGxpc3QoUHJpY2UgPSBOQSwgRGF0ZSA9IE5BKSkNCiAgfQ0KICANCiAgZGF0ZV91c2VkIDwtIG1heChhdmFpbGFibGVfZGF0ZXMpDQogIA0KICBwcmljZSA8LSBhcy5udW1lcmljKENsKGRhdGFbZGF0ZV91c2VkXSkpDQogIA0KICByZXR1cm4obGlzdCgNCiAgICBQcmljZSA9IHByaWNlLA0KICAgIERhdGUgPSBhcy5EYXRlKGRhdGVfdXNlZCkNCiAgKSkNCn0NCmBgYA0KDQoNCkdldCBTJlA1MDAgcHJpY2VzIGF0IEJvVCBhbmQgRW9UDQoNCmBgYHtyfQ0KcHJpY2VfQm9UIDwtIGdldF9wcmljZV9vbl9kYXRlKGBHU1BDYCwgQm9UX2RhdGUpDQpwcmljZV9Fb1QgPC0gZ2V0X3ByaWNlX29uX2RhdGUoYEdTUENgLCBFb1RfZGF0ZSkNCg0KY2F0KCJTJlAgNTAwIEluZGV4IFByaWNlIGF0IEJvVCAoIiwgcHJpY2VfQm9UJERhdGUsICIpOiAiLCBwcmljZV9Cb1QkUHJpY2UsICJcbiIsIHNlcCA9ICIiKQ0KY2F0KCJTJlAgNTAwIEluZGV4IFByaWNlIGF0IEVvVCAoIiwgcHJpY2VfRW9UJERhdGUsICIpOiAiLCBwcmljZV9Fb1QkUHJpY2UsICJcbiIsIHNlcCA9ICIiKQ0KYGBgDQoNCg0KQ2FsY3VsYXRlIHRoZSBDb250cmFjdCBWYWx1ZXMNCg0KYGBge3J9DQpjb250cmFjdF92YWx1ZV9Cb1QgPC0gcHJpY2VfQm9UJFByaWNlICogMjUwDQpjb250cmFjdF92YWx1ZV9Fb1QgPC0gcHJpY2VfRW9UJFByaWNlICogMjUwDQpgYGANCg0KDQpDYWxjdWxhdGUgdGhlIGRpZmZlcmVuY2UNCg0KYGBge3J9DQpkaWZmZXJlbmNlIDwtIGNvbnRyYWN0X3ZhbHVlX0VvVCAtIGNvbnRyYWN0X3ZhbHVlX0JvVA0KDQpjYXQoIkRpZmZlcmVuY2UgaW4gQ29udHJhY3QgVmFsdWVzOiAkIiwgcm91bmQoZGlmZmVyZW5jZSwgMiksICJcbiIsIHNlcCA9ICIiKQ0KYGBgDQoNCg0KIyMjIyBBbmFseXNpcw0KDQpUaGUgc2lnbmlmaWNhbnQgaW5jcmVhc2UgaW4gdGhlIHByaWNlIG9mIHRoZSBTJlA1MDAgZHVyaW5nIHRoZSB0ZXJtIGhhcyBsZWQgdG8gYSBmaW5hbCBkaWZmZXJlbmNlIGluIHRoZSBjb250cmFjdCB2YWx1ZSBvZiAxODYwMjIuNSBVU0QuIEluIHRoaXMgZXhhbXBsZSB3ZSBjYW4gZWFzaWx5IG9ic2VydmUgaG93IHRoZSBmbHVjdHVhdGlvbiBvZiBwcmljZSBjYW4gZW5vcm1vdXNseSBhZmZlY3QgdGhlIHByaWNlIG9mIHRoZSBjb250cmFjdCwgd2hpY2ggbWFrZXMgaGVkZ2luZyBzdHJhdGVnaWVzIG11Y2ggbW9yZSBhdHRyYWN0aXZlLiBBbHRob3VnaCB0aGV5IG1heSByZWR1Y2UgdGhlIHRvdGFsIHByb2ZpdCwgYSBmdXR1cmVzIHRyYWRlciB3aWxsIG92ZXJhbGwgYmVuZWZpdCBmcm9tIHRoZW0gYXMgbG9zZXMgd2lsbCBiZSBncmVhdGx5IG1pdGlnYXRlZCBhbmQgdGhlIG91dGNvbWUgb2YgYSBiYWQgb3BlcmF0aW9uIHdpbGwgbm90IGJlIGFzIGNhdGFzdHJvcGhpYyBhcyBpdCBtYXkgYmUgaWYgdGhlcmUgaXMgbm8gY291bnRlcnBhcnQgdGhhdCBiYWNrcyBpdCB1cC4gDQoNCg0KDQojIyMgTDExLjIgQ2FsY3VsYXRpbmcgWW91ciBSZXR1cm4gZnJvbSB0aGUgRnV0dXJlcyBQb3NpdGlvbg0KICAtWW91IGludmVzdGVkIGFuIGluaXRpYWwgbWFyZ2luIG9mIDIwJSBvZiB0aGUgZnV0dXJlcyBjb250cmFjdCB2YWx1ZSBhdCBCb1QNCiAgLVlvdXIgcmV0dXJuIGlzIHRoZSBnYWluIGZyb20gdGhlIGZ1dHVyZXMgcG9zaXRpb24gZGl2aWRlZCBieSB5b3VyIGluaXRpYWwgaW52ZXN0bWVudA0KDQoNCkNhbGN1bGF0ZSBJbml0aWFsIEludmVzdG1lbnQNCg0KYGBge3J9DQppbml0aWFsX2ludmVzdG1lbnQgPC0gMC4yMCAqIGNvbnRyYWN0X3ZhbHVlX0JvVA0KDQpjYXQoIkluaXRpYWwgSW52ZXN0bWVudCAoMjAlIE1hcmdpbik6ICQiLCByb3VuZChpbml0aWFsX2ludmVzdG1lbnQsIDIpLCAiXG4iLCBzZXAgPSAiIikNCmBgYA0KDQoNCkNhbGN1bGF0ZSBSZXR1cm4gb24gSW52ZXN0bWVudA0KDQpgYGB7cn0NCiMgQ2FsY3VsYXRlIHRoZSByZXR1cm4NCnJldHVybl9mdXR1cmVzIDwtIGRpZmZlcmVuY2UgLyBpbml0aWFsX2ludmVzdG1lbnQNCg0KIyBQcmludCB0aGUgcmV0dXJuIGFzIGEgcGVyY2VudGFnZQ0KY2F0KCJSZXR1cm4gb24gRnV0dXJlcyBQb3NpdGlvbjogIiwgcm91bmQocmV0dXJuX2Z1dHVyZXMgKiAxMDAsIDIpLCAiJVxuIiwgc2VwID0gIiIpDQpgYGANCg0KDQojIyMjIEFuYWx5c2lzDQpBcyBhIGZvbGxvdyB1cCBmcm9tIHRoZSBwcmV2aW91cyBleGVyY2lzZSwgd2UgaGF2ZSB0aGUgZmluYWwgcmV0dXJuIG9mIHRoZSBmdXR1cmVzIHBvc2l0aW9uIHRoYXQgc3VtcyB0byBhIHRvdGFsIG9mIDc0LjE0JSBpbiB0aGUgZHVyYXRpb24gb2YgdGhlIHNjaG9vbCB0ZXJtLiBXaXRoIHN1Y2ggaGlnaCByZXR1cm5zLCBhbmQgYXMgd2UgaGF2ZSBleHBsYWluZWQgYmVmb3JlLCB3ZSBzaGFsbCBiYXJlIGluIG1pbmQgdGhhdCBlcXVhbGx5IGhpZ2ggbG9zc2VzIG1heSBiZSBvYnRhaW5lZC4gVGhlcmVmb3JlLCBkZWVwIGtub3dsZWRnZSBvZiB0aGUgdW5kZXJseWluZyBhc3NldCBhbmQgYSBnb29kIHRyYWRpbmcgc3RyYXRlZ3kgYXJlIGV4dHJlbWVseSBpbXBvcnRhbnQgaW4gb3JkZXIgdG8gcGVyZm9ybSBzdWNoIG9wZXJhdGlvbnMuIA0KDQoNCg0KIyMjIEwxMS4zIEFubnVhbGl6aW5nIFlvdXIgUmV0dXJuDQogIC1UaGUgcmV0dXJuIGNhbGN1bGF0ZWQgaXMgZm9yIHRoZSBkdXJhdGlvbiBvZiB0aGUgc2Nob29sIHRlcm0gKDUgbW9udGhzKQ0KICAtVG8gYW5udWFsaXplIHRoZSByZXR1cm4sIHdlIG11bHRpcGx5IGl0IGJ5IDEyL20sIHdoZXJlIG0gfiA1IG1vbnRocyANCg0KDQpDYWxjdWxhdGUgdGhlIGFubnVhbGl6YXRpb24NCg0KYGBge3J9DQptIDwtIGFzLm51bWVyaWMoZGlmZnRpbWUoRW9UX2RhdGUsIEJvVF9kYXRlLCB1bml0cyA9ICJkYXlzIikpIC8gMzAuNDQNCg0KYW5udWFsaXplZF9yZXR1cm5fZnV0dXJlcyA8LSByZXR1cm5fZnV0dXJlcyAqICgxMiAvIG0pDQoNCmNhdCgiQW5udWFsaXplZCBSZXR1cm4gb24gRnV0dXJlcyBQb3NpdGlvbjogIiwgcm91bmQoYW5udWFsaXplZF9yZXR1cm5fZnV0dXJlcyAqIDEwMCwgMiksICIlXG4iLCBzZXAgPSAiIikNCmBgYA0KDQoNCiMjIyMgQ29tbWVudHMNClByZXZpb3VzbHksIHdlIGhhZCBvbmx5IG9idGFpbmVkIHRoZSBkaWZmZXJlbmNlIGluIHRoZSBmdXR1cmVzIGNvbnRyYWN0IHByaWNlIGFuZCB0aGUgcmV0dXJuIG9idGFpbmVkIGluIHRoZSBkdXJhdGlvbiBvZiB0aGUgc2Nob29sIHRlcm0uIE5vdywgd2UgaGF2ZSBvYnRhaW5lZCB0aGUgYW5udWFsaXplZCByZXR1cm4sIHdoaWNoIGRlcGljdHMgdGhlIGF2ZXJhZ2UgcmF0ZSBvZiByZXR1cm4gcGVyIHllYXIuIFdlIGFubnVhbGl6ZSBvdXIgcmV0dXJucyB0byBiZXR0ZXIgY29tcGFyZSB0aGVtIHdpdGggb3RoZXIgcG9zc2libGUgc3R1ZGllZCByZXR1cm5zLCBhcyByZXR1cm5zIGFyZSB1c3VhbGx5IHByZXNlbnRlZCBhcyBwZXIgeWVhci4gDQoNCg0KIyMjIEwxMS40IENhbGN1bGF0aW5nIHRoZSBSZXR1cm4gZnJvbSBQdXJjaGFzaW5nIGEgQ2FsbCBPcHRpb24gb24gQXBwbGUgSW5jLiAoQUFQTCkNCiAgDQogIC1QdXJjaGFzZSBvZiBhIGNhbGwgb3B0aW9uIHJlcHJlc2VudGluZyAxMDAgc2hhcmVzIG9mIEFBUEwgYXQgQm9UDQogIC1EZXRlcm1pbmUgdGhlIHJldHVybiBiYXNlZCBvbiB0aGUgb3B0aW9uIHByZW1pdW1zIGF0IEJPVCBhbmQgRW9UDQogIElmIHRoZSBwcmVtaXVtIGF0IEVvVCBpcyB1bmF2YWlsYWJsZSwgY2FsY3VsYXRlIHRoZSByZXR1cm4gYmFzZWQgb24gZXhlcmNpc2luZyB0aGUgb3B0aW9uDQoNCldlIHdpbGwgZXN0aW1hdGUgdGhlIG9wdGlvbiBwcmVtaXVtcyB1c2luZyB0aGUgQmxhY2stU2Nob2xlcyBNb2RlbA0KDQoNCg0KUmV0cmlldmUgQUFQTCBTdG9jayBQcmljZXMNCg0KYGBge3J9DQpnZXRTeW1ib2xzKCJBQVBMIiwgc3JjID0gInlhaG9vIiwgZnJvbSA9IHN0YXJ0X2RhdGUsIHRvID0gZW5kX2RhdGUpDQoNCnByaWNlX0FBUExfQm9UIDwtIGdldF9wcmljZV9vbl9kYXRlKEFBUEwsIEJvVF9kYXRlKQ0KcHJpY2VfQUFQTF9Fb1QgPC0gZ2V0X3ByaWNlX29uX2RhdGUoQUFQTCwgRW9UX2RhdGUpDQoNCmNhdCgiQUFQTCBTdG9jayBQcmljZSBhdCBCb1QgKCIsIHByaWNlX0FBUExfQm9UJERhdGUsICIpOiAkIiwgcm91bmQocHJpY2VfQUFQTF9Cb1QkUHJpY2UsIDIpLCAiXG4iLCBzZXAgPSAiIikNCmNhdCgiQUFQTCBTdG9jayBQcmljZSBhdCBFb1QgKCIsIHByaWNlX0FBUExfRW9UJERhdGUsICIpOiAkIiwgcm91bmQocHJpY2VfQUFQTF9Fb1QkUHJpY2UsIDIpLCAiXG4iLCBzZXAgPSAiIikNCmBgYA0KDQoNClNldCB0aGUgU3RyaWtlIFByaWNlDQoNCmBgYHtyfQ0KU3RyaWtlX1ByaWNlIDwtIGNlaWxpbmcocHJpY2VfQUFQTF9Cb1QkUHJpY2UgLyA1KSAqIDUNCg0KY2F0KCJPcHRpb24gU3RyaWtlIFByaWNlOiAkIiwgU3RyaWtlX1ByaWNlLCAiXG4iLCBzZXAgPSAiIikNCmBgYA0KDQoNCkVzdGltYXRlIFZvbGF0aWxpdHkNCg0KYGBge3J9DQpzdGFydF9kYXRlX3ZvbCA8LSBCb1RfZGF0ZSAtIHllYXJzKDEpDQpnZXRTeW1ib2xzKCJBQVBMIiwgc3JjID0gInlhaG9vIiwgZnJvbSA9IHN0YXJ0X2RhdGVfdm9sLCB0byA9IEJvVF9kYXRlKQ0KDQpyZXR1cm5zIDwtIG5hLm9taXQoZGFpbHlSZXR1cm4oQ2woQUFQTCkpKQ0KDQp2b2xhdGlsaXR5IDwtIHNkKHJldHVybnMpICogc3FydCgyNTIpDQoNCmNhdCgiRXN0aW1hdGVkIEFubnVhbGl6ZWQgVm9sYXRpbGl0eTogIiwgcm91bmQodm9sYXRpbGl0eSAqIDEwMCwgMiksICIlXG4iLCBzZXAgPSAiIikNCmBgYA0KDQoNCkRlZmluZSB0aGUgQmxhY2stU2Nob2xlcyBGdW5jdGlvbg0KDQpgYGB7cn0NCkJsYWNrU2Nob2xlc0NhbGwgPC0gZnVuY3Rpb24oUywgSywgciwgVCwgc2lnbWEpIHsNCiAgZDEgPC0gKGxvZyhTIC8gSykgKyAociArIHNpZ21hXjIgLyAyKSAqIFQpIC8gKHNpZ21hICogc3FydChUKSkNCiAgZDIgPC0gZDEgLSBzaWdtYSAqIHNxcnQoVCkNCiAgQyA8LSBTICogcG5vcm0oZDEpIC0gSyAqIGV4cCgtciAqIFQpICogcG5vcm0oZDIpDQogIHJldHVybihDKQ0KfQ0KYGBgDQoNCg0KQ2FsY3VsYXRlIE9wdGlvbiBQcmVtaXVtcyBhdCBCb1QgYW5kIEVvVA0KDQpgYGB7cn0NCiMgU2V0IHJpc2stZnJlZSByYXRlIChlLmcuLCAyJSkNCnJpc2tfZnJlZV9yYXRlIDwtIDAuMDINCg0KIyBUaW1lIHRvIGV4cGlyYXRpb24gKGFzc3VtZSBvcHRpb24gZXhwaXJlcyBvbiBuZXh0IG1vbnRoJ3MgdGhpcmQgRnJpZGF5KQ0KVF9Cb1QgPC0gYXMubnVtZXJpYyhkaWZmdGltZShhcy5EYXRlKCIyMDI0LTExLTE1IiksIHByaWNlX0FBUExfQm9UJERhdGUsIHVuaXRzID0gImRheXMiKSkgLyAzNjUNClRfRW9UIDwtIGFzLm51bWVyaWMoZGlmZnRpbWUoYXMuRGF0ZSgiMjAyNC0xMS0xNSIpLCBwcmljZV9BQVBMX0VvVCREYXRlLCB1bml0cyA9ICJkYXlzIikpIC8gMzY1IA0KQ19Cb1QgPC0gQmxhY2tTY2hvbGVzQ2FsbChTID0gcHJpY2VfQUFQTF9Cb1QkUHJpY2UsIEsgPSBTdHJpa2VfUHJpY2UsIHIgPSByaXNrX2ZyZWVfcmF0ZSwgVCA9IFRfQm9ULCBzaWdtYSA9IHZvbGF0aWxpdHkpDQpDX0VvVCA8LSBCbGFja1NjaG9sZXNDYWxsKFMgPSBwcmljZV9BQVBMX0VvVCRQcmljZSwgSyA9IFN0cmlrZV9QcmljZSwgciA9IHJpc2tfZnJlZV9yYXRlLCBUID0gVF9Fb1QsIHNpZ21hID0gdm9sYXRpbGl0eSkNCg0KY2F0KCJPcHRpb24gUHJlbWl1bSBhdCBCb1Q6ICQiLCByb3VuZChDX0JvVCwgMiksICJcbiIsIHNlcCA9ICIiKQ0KY2F0KCJPcHRpb24gUHJlbWl1bSBhdCBFb1Q6ICQiLCByb3VuZChDX0VvVCwgMiksICJcbiIsIHNlcCA9ICIiKQ0KYGBgDQoNCg0KQ2FsY3VsYXRlIHRoZSBSZXR1cm4gZnJvbSB0aGUgT3B0aW9uDQoNCmBgYHtyfQ0KIyBDYWxjdWxhdGUgcmV0dXJuIGJhc2VkIG9uIHNlbGxpbmcgdGhlIG9wdGlvbiBhdCBFb1QNCmlmICghaXMubmEoQ19Fb1QpKSB7DQogIHJldHVybl9vcHRpb25fc2VsbCA8LSAoQ19Fb1QgLSBDX0JvVCkgLyBDX0JvVA0KICBjYXQoIlJldHVybiBmcm9tIFNlbGxpbmcgdGhlIENhbGwgT3B0aW9uOiAiLCByb3VuZChyZXR1cm5fb3B0aW9uX3NlbGwgKiAxMDAsIDIpLCAiJVxuIiwgc2VwID0gIiIpDQp9IGVsc2Ugew0KICBjYXQoIk9wdGlvbiBwcmVtaXVtIGF0IEVvVCBpcyB1bmF2YWlsYWJsZS5cbiIpDQp9DQoNCiMgQ2FsY3VsYXRlIHJldHVybiBiYXNlZCBvbiBleGVyY2lzaW5nIHRoZSBvcHRpb24NCmlmIChwcmljZV9BQVBMX0VvVCRQcmljZSA+IFN0cmlrZV9QcmljZSkgew0KICBwcm9maXRfZXhlcmNpc2UgPC0gKHByaWNlX0FBUExfRW9UJFByaWNlIC0gU3RyaWtlX1ByaWNlKSAtIENfQm9UDQogIHJldHVybl9vcHRpb25fZXhlcmNpc2UgPC0gcHJvZml0X2V4ZXJjaXNlIC8gQ19Cb1QNCiAgY2F0KCJSZXR1cm4gZnJvbSBFeGVyY2lzaW5nIHRoZSBDYWxsIE9wdGlvbjogIiwgcm91bmQocmV0dXJuX29wdGlvbl9leGVyY2lzZSAqIDEwMCwgMiksICIlXG4iLCBzZXAgPSAiIikNCn0gZWxzZSB7DQogIHByb2ZpdF9leGVyY2lzZSA8LSAtQ19Cb1QNCiAgcmV0dXJuX29wdGlvbl9leGVyY2lzZSA8LSBwcm9maXRfZXhlcmNpc2UgLyBDX0JvVA0KICBjYXQoIk9wdGlvbiBleHBpcmVkIHdvcnRobGVzcy4gUmV0dXJuIGZyb20gRXhlcmNpc2luZyB0aGUgQ2FsbCBPcHRpb246ICIsIHJvdW5kKHJldHVybl9vcHRpb25fZXhlcmNpc2UgKiAxMDAsIDIpLCAiJVxuIiwgc2VwID0gIiIpDQp9DQoNCmBgYA0KDQoNCiMjIyMgQW5hbHlzaXMNCg0KSW4gdGhpcyBleGVyY2lzZSwgd2UgaGF2ZSBvcHRlZCBmb3IgY2FsY3VsYXRpbmcgdGhlIHByZW1pdW1zIHdpdGggdGhlIHVzZSBvZiB0aGUgQmxhY2sgU2Nob2xlcyBNb2RlbC4gVGhpcyBkZWNpc2lvbiBoYXMgdGFrZW4gZHVlIHRvIHRoZSBpbmFjY2Vzc2liaWxpdHkgb2YgZGlyZWN0IGRhdGEgYWJvdXQgdGhlIHByZW1pdW1zIGZvciB0aGUgb3B0aW9ucy4gVGhlIEJsYWNrLVNjaG9sZXMgTW9kZWwgYWxsb3dzIHVzIHRvIGNhbGN1bGF0ZSB0aGUgdGhlb3JldGljYWwgdmFsdWUgb2YgZGVyaXZhdGl2ZXMgYnkgdGFraW5nIGludG8gYWNjb3VudCA1IHZhcmlhYmxlczogc3RyaWtlIHByaWNlIG9mIHRoZSBvcHRpb24sIGN1cnJlbnQgc3RvY2sgcHJpY2UsIHRpbWUgdG8gZXhwaXJhdGlvbiwgcmlzay1mcmVlIHJhdGUgYW5kIHZvbGF0aWxpdHkuIFRoZSBlc3RpbWF0aW9uIG9idGFpbmVkIHdpdGggdGhpcyBtb2RlbCBtYXkgZGVyaXZlIGZyb20gdGhlIHJlYWwgdmFsdWVzLiANCldoZW4gdXNpbmcgdGhpcyBtb2RlbCwgd2Ugc2hvdWxkIGFsc28gdGFrZSBpbnRvIGFjY291bnQgdGhhdCBkZXBlbmRpbmcgb24gb3VyIGxvY2F0aW9uLCBvcHRpb25zIGNvdWxkIGJlIGV4ZXJjaXNlZCBiZWZvcmUgdGhlIGV4cGlyYXRpb24gZGF0ZS4gSG93ZXZlciBmb3IgdGhpcyBleGVyY2lzZSB3ZSB3aWxsIG5vdCB0YWtlIHRoYXQgaW50byBhY2NvdW50LiANCldlIGhhdmUgYWxzbyB0YWtlbiBpbnRvIGFjY291bnQgdGhlIHR3byBvcHRpb25zIHRoYXQgY291bGQgaGFwcGVuIHdoZW4gYnV5aW5nIHRoaXMgY2FsbCBvcHRpb246IHRvIGV4ZXJjaXNlIGl0IG9yIHRvIGJ1eSBpdC4gDQpXaGVuIHdlIHNlbGwgdGhlIGNhbGwgb3B0aW9uLCB0aGUgdG90YWwgbm9uLWFubnVhbGl6ZWQgcmV0dXJuIHdpbGwgYmUgNTE0LjUxJSwgd2hlcmVhcyBpZiB3ZSBleGVyY2lzZSBpdCBpdCBpcyA1MTAuMzYlLiANCkluIHRoZSBjYXNlIG9mIHNlbGxpbmcsIHRoZSBwcm9maXQgb3IgcmV0dXJuIG9idGFpbmVkIHdpbGwgYmUgY2FsY3VsYXRlZCB3aXRoIHRoZSBwcmVtaXVtcy4gSWYgdGhlIHByZW1pdW0gYXQgdGhlIEVuZCBvZiBUZXJtIHdhcyB1bmF2YWlsYWJsZSBvciB3ZSBkZWNpZGVkIHRvIGV4ZXJjaXNlIHRoZSBvcHRpb24sIHRoZSBwcm9maXQgb2J0YWluZWQgd2lsbCBiZSB0aGUgcHJpY2Ugb2YgdGhlIHN0b2NrIGF0IHRoZSBtb21lbnQgb2YgZXhlcmNpc2UgbWludXMgdGhlIHN0cmlrZSBwcmljZSBhbmQgdGhlIHByZW1pdW0uIEJvdGggcmV0dXJucyBhcmUgcmF0aGVyIHNpbWlsYXIsIGFsdGhvdWdoIHRoZSByZXR1cm4gZnJvbSBzZWxsaW5nIHRoZSBvcHRpb24gaXMgbm90aWNlYWJseSBoaWdoZXIuIA0KDQojIyMgTDExLjUgQW5udWFsaXppbmcgdGhlIFJldHVybiBvbiBZb3VyIE9wdGlvbg0KDQpgYGB7cn0NCiMgQW5udWFsaXplIHRoZSBSZXR1cm5zDQphbm51YWxpemVkX3JldHVybl9vcHRpb25fc2VsbCA8LSAocmV0dXJuX29wdGlvbl9zZWxsKSooMTIgLyBtKQ0KYW5udWFsaXplZF9yZXR1cm5fb3B0aW9uX2V4ZXJjaXNlIDwtICgocmV0dXJuX29wdGlvbl9leGVyY2lzZSkqKDEyIC8gbSkpIA0KDQojIERpc3BsYXkgdGhlIEFubnVhbGl6ZWQgUmV0dXJucw0KY2F0KCJcbkFubnVhbGl6ZWQgUmV0dXJuIGZyb20gU2VsbGluZyB0aGUgQ2FsbCBPcHRpb246ICIsIHJvdW5kKGFubnVhbGl6ZWRfcmV0dXJuX29wdGlvbl9zZWxsICogMTAwLCAyKSwgIiVcbiIsIHNlcCA9ICIiKQ0KY2F0KCJBbm51YWxpemVkIFJldHVybiBmcm9tIEV4ZXJjaXNpbmcgdGhlIENhbGwgT3B0aW9uOiAiLCByb3VuZChhbm51YWxpemVkX3JldHVybl9vcHRpb25fZXhlcmNpc2UgKiAxMDAsIDIpLCAiJVxuIiwgc2VwID0gIiIpDQpgYGANCg0KDQojIyMjIENvbW1lbnRzDQoNCldpdGggdGhlIGFubnVhbGl6YXRpb24gb2YgdGhlIHJlc3VsdHMgd2Ugb2J0YWluIGEgcmV0dXJuIG9mIDEyMzYuNDQlIGFuZCAxMjI2LjQ3JSByZXNwZWN0aXZlbHkuIEFzIHdlIGtub3csIHRoZSBhbm51YWxpemF0aW9uIGlzIHVzdWFsbHkgZG9uZSBpbiBvcmRlciB0byBiZXR0ZXIgY29tcGFyZSB0aGUgcmV0dXJucyB3aXRoIG90aGVycy4gDQoNCg0KDQojIyMgTDExLjYgQ29tcGFyaW5nIHRoZSBSZXR1cm4gb24gWW91ciBDYWxsIE9wdGlvbiB0byBJbnZlc3RpbmcgaW4gdGhlIFN0b2NrDQoNCg0KQ2FsY3VsYXRlIHRoZSBSZXR1cm4gZnJvbSBJbnZlc3RpbmcgaW4gQUFQTCBzdG9jaw0KDQpgYGB7cn0NCnJldHVybl9zdG9jayA8LSAocHJpY2VfQUFQTF9Fb1QkUHJpY2UgLSBwcmljZV9BQVBMX0JvVCRQcmljZSkgLyBwcmljZV9BQVBMX0JvVCRQcmljZQ0KDQphbm51YWxpemVkX3JldHVybl9zdG9jayA8LSByZXR1cm5fc3RvY2sgKiAoMTIgLyBtKQ0KDQpjYXQoIlJldHVybiBmcm9tIEludmVzdGluZyBpbiBBQVBMIFN0b2NrOiAiLCByb3VuZChyZXR1cm5fc3RvY2sgKiAxMDAsIDIpLCAiJVxuIiwgc2VwID0gIiIpDQpjYXQoIkFubnVhbGl6ZWQgUmV0dXJuIG9uIEFBUEwgU3RvY2s6ICIsIHJvdW5kKGFubnVhbGl6ZWRfcmV0dXJuX3N0b2NrICogMTAwLCAyKSwgIiVcbiIsIHNlcCA9ICIiKQ0KYGBgDQoNCg0KQ29tcGFyZSB0aGUgcmV0dXJucw0KDQpgYGB7cn0NCmNhdCgiXG5Db21wYXJpc29uIG9mIFJldHVybnM6XG4iKQ0KY2F0KCJBbm51YWxpemVkIFJldHVybiBvbiBDYWxsIE9wdGlvbjogIiwgcm91bmQoYW5udWFsaXplZF9yZXR1cm5fb3B0aW9uX3NlbGwgKiAxMDAsIDIpLCAiJVxuIiwgc2VwID0gIiIpDQpjYXQoIkFubnVhbGl6ZWQgUmV0dXJuIGZyb20gRXhlcmNpc2luZyB0aGUgQ2FsbCBPcHRpb246ICIsIHJvdW5kKGFubnVhbGl6ZWRfcmV0dXJuX29wdGlvbl9leGVyY2lzZSAqIDEwMCwgMiksICIlXG4iLCBzZXAgPSAiIikNCmNhdCgiQW5udWFsaXplZCBSZXR1cm4gb24gQUFQTCBTdG9jazogIiwgcm91bmQoYW5udWFsaXplZF9yZXR1cm5fc3RvY2sgKiAxMDAsIDIpLCAiJVxuIiwgc2VwID0gIiIpDQpgYGANCg0KDQojIyMjIEFuYWx5c2lzDQpJbiB0aGlzIGZpbmFsIGV4ZXJjaXNlIHdlIGNvbXBhcmUgdGhlIHJldHVybnMgb2YgdGhlIFJldHVybiBvZiB0aGUgU3RvY2sgd2l0aCB0aG9zZSBvZiB0aGUgY2FsbCBvcHRpb24sIGJvdGggd2hlbiBzZWxsaW5nIGFuZCB3aGVuIGV4ZXJjaXNpbmcgaXQuIEFzIHdlIGNhbiBvYnNlcnZlLCB0aGUgcG90ZW50aWFsIHJldHVybnMgb2YgdGhlIGNhbGwgb3B0aW9ucyBodWdlbHkgb3V0d2VpZ2ggdGhvc2Ugb2YgdGhlIFN0b2NrIGl0c2VsZi4gSW4gdGhlIGNhc2Ugb2YgdGhlIGNhbGwgb3B0aW9uLCBhcyB3ZSBoYXZlIG1lbnRpb25lZCwgdGhlIHBvdGVudGlhbCBsb3NzIGZvciB0aGUgYnV5ZXIgaXMgbGltaXRlZCB0byB0aGUgcHJlbWl1bSB0aGF0IHRoZXkgc2hhbGwgcGF5IHdoZW4gYnV5aW5nIHRoZSBvcHRpb24uIEhvd2V2ZXIsIGZvciB0aGUgc2VsbGVyIG9mIHRoaXMgb3B0aW9uLCB0aGUgcmlzayBiZWNvbWVzIGV4dHJlbWVseSBub3RpY2VhYmxlLiANCg0KDQoNCiMjIEwxMS43IERldGVybWluaW5nIFN3YXAgUGF5bWVudHMNCg0KDQojIyMgRGVmaW5pdGlvbnMNCg0KIyMjIyBTd2Fwcw0KU3dhcHMgYXJlIGEga2luZCBvZiBkZXJpdmF0aXZlIGNvbnRyYWN0IGluIHdoaWNoIHRoZSB0d28gcGFydGllcyBpbnZvbHZlZCBleGNoYW5nZSBhc3NldHMgd2l0aCB0aGVpciBjb3JyZXNwb25kaW5nIGNhc2ggZmxvd3Mgb3ZlciBhbiBlc3RhYmxpc2hlZCBwZXJpb2Qgb2YgdGltZS4gT25lIG9mIHRoZSB0d28gY2FzaCBmbG93cyBpbnZvbHZlZCB3aWxsIGJlIGZpeGVkLCB3aGVyZWFzIHRoZSBvdGhlciBvbmUgd2lsbCBiZSB2YXJpYWJsZSBhbmQgZGVwZW5kZW50IG9uIGFuIGluZGV4IHByaWNlLCBpbnRlcmVzdCByYXRlIG9yIGN1cnJlbmN5IGV4Y2hhbmdlIHJhdGUuIFRoZSB2YXJpYWJsZSBuYXR1cmUgb2Ygb25lIHBhcnR5IGFnYWluc3QgdGhlIGZpeGVkIG9uZSBvZiB0aGUgb3RoZXIgcmVzdWx0cyBpbiBzb21lIHN3YXAgY29udHJhY3RzIGJlaW5nIHZlcnkgcmlza3kgYW5kIHRoZXkgaW52b2x2ZSBncmVhdCBzcGVjaWFsaXphdGlvbiBhbmQgYSBkZWVwIHVuZGVyc3RhbmRpbmcgb2YgdGhlIHVuZGVybHlpbmcgaW5kZXgvcmF0ZS4gDQpUaGlzIGNvbnRyYWN0cyBhcmUgdHJhZGVkIGluIHRoZSBvdmVyLXRoZS1jb3VudGVyIG1hcmtldCAoT1RDKSBhbmQgYXJlIG5lZ290aWF0ZWQgaW5kaXZpZHVhbGx5IGFuZCBwcml2YXRlbHkuIFRoaXMgY2hhcmFjdGVyaXN0aWNzIG1heSBsZWFkIHRvIHRoaW5raW5nIHRoYXQgdGhpcyBjb250cmFjdHMgYXJlIG5vdCBwYXJ0aWN1bGFybHkgbGlxdWlkIGJ1dCB0aGUgcmVhbGl0eSBpbiB0aGlzIGNhc2UgaXMgcXVpdGUgY291bnRlci1pbnR1aXRpdmUgYW5kIHRoZXJlIGlzIGdyZWF0IGludGVyZXN0IGluIHRoZSBTd2FwIE1hcmtldC4gDQoNCg0KIyMjIFIgQ29kZQ0KDQoNCkxvYWQgcGFja2FnZXMNCg0KYGBge3J9DQpsaWJyYXJ5KHF1YW50bW9kKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpgYGANCg0KDQpEZWZpbmUgdGhlIEJlZ2lubmluZyBhbmQgRW5kIG9mIFRlcm0gRGF0ZXMNCg0KYGBge3J9DQpCb1RfZGF0ZSA8LSBhcy5EYXRlKCIyMDI0LTA1LTAxIikNCkVvVF9kYXRlIDwtIGFzLkRhdGUoIjIwMjQtMDktMzAiKQ0KDQpgYGANCg0KDQpEZWZpbmUgU3dhcCBUZXJtcw0KDQpgYGB7cn0NCm5vdGlvbmFsX2Ftb3VudCA8LSAxMDAwMDAwMA0KDQpmaXhlZF9yYXRlIDwtIDAuMDYNCmBgYA0KDQoNCkNhbGN1bGF0ZSB0aGUgVGltZSBQZXJpb2Qgb2YgdGhlIFN3YXANCg0KYGBge3J9DQpkYXlzX2JldHdlZW4gPC0gYXMubnVtZXJpYyhkaWZmdGltZShFb1RfZGF0ZSwgQm9UX2RhdGUsIHVuaXRzID0gImRheXMiKSkNCg0KeWVhcl9mcmFjdGlvbiA8LSBkYXlzX2JldHdlZW4gLyAzNjANCg0KY2F0KCJEYXlzIGJldHdlZW4gQm9UIGFuZCBFb1Q6IiwgZGF5c19iZXR3ZWVuLCAiZGF5c1xuIikNCmNhdCgiWWVhciBmcmFjdGlvbiAodXNpbmcgQWN0dWFsLzM2MCk6Iiwgcm91bmQoeWVhcl9mcmFjdGlvbiwgNiksICJcbiIpDQpgYGANCg0KDQpDYWxjdWxhdGUgdGhlIEZpeGVkLVJhdGUgUGF5bWVudA0KDQpgYGB7cn0NCmZpeGVkX3BheW1lbnQgPC0gbm90aW9uYWxfYW1vdW50ICogZml4ZWRfcmF0ZSAqIHllYXJfZnJhY3Rpb24NCg0KY2F0KCJGaXhlZC1SYXRlIFBheW1lbnQ6ICQiLCByb3VuZChmaXhlZF9wYXltZW50LCAyKSwgIlxuIiwgc2VwID0gIiIpDQoNCmBgYA0KDQoNCg0KUmV0cmlldmUgdGhlIDI2LXdlZWsgVGJpbGwgUmF0ZSBhdCBFb3QNCg0KDQpHZXQgdGhlIFQtYmlsbCBSYXRlIERhdGENCg0KYGBge3J9DQpnZXRTeW1ib2xzKCJEVEI2Iiwgc3JjID0gIkZSRUQiLCBmcm9tID0gRW9UX2RhdGUgLSA3LCB0byA9IEVvVF9kYXRlICsgNykNCg0KYGBgDQoNCg0KRXh0cmFjdCB0aGUgUmF0ZSBhdCBFT1QNCg0KYGBge3J9DQpnZXRfcmF0ZV9vbl9kYXRlIDwtIGZ1bmN0aW9uKGRhdGEsIGRhdGUpIHsNCiAgaW5kZXgoZGF0YSkgPC0gYXMuRGF0ZShpbmRleChkYXRhKSkNCiAgDQogIGF2YWlsYWJsZV9kYXRlcyA8LSBpbmRleChkYXRhKVtpbmRleChkYXRhKSA8PSBkYXRlICYgIWlzLm5hKGRhdGFbaW5kZXgoZGF0YSldKV0NCiAgDQogIGlmIChsZW5ndGgoYXZhaWxhYmxlX2RhdGVzKSA9PSAwKSB7DQogICAgd2FybmluZyhwYXN0ZSgiTm8gZGF0YSBhdmFpbGFibGUgb24gb3IgYmVmb3JlIiwgZGF0ZSkpDQogICAgcmV0dXJuKGxpc3QoUmF0ZSA9IE5BLCBEYXRlID0gTkEpKQ0KICB9DQogIA0KICBkYXRlX3VzZWQgPC0gbWF4KGF2YWlsYWJsZV9kYXRlcykNCiAgDQogICMgR2V0IHRoZSByYXRlDQogIHJhdGUgPC0gYXMubnVtZXJpYyhkYXRhW2RhdGVfdXNlZF0pIC8gMTAwICAjIENvbnZlcnQgcGVyY2VudGFnZSB0byBkZWNpbWFsDQogIA0KICByZXR1cm4obGlzdCgNCiAgICBSYXRlID0gcmF0ZSwNCiAgICBEYXRlID0gYXMuRGF0ZShkYXRlX3VzZWQpDQogICkpDQp9DQoNCnRfYmlsbF9yYXRlX0VvVCA8LSBnZXRfcmF0ZV9vbl9kYXRlKERUQjYsIEVvVF9kYXRlKQ0KDQpjYXQoIjI2LXdlZWsgVC1iaWxsIFJhdGUgYXQgRW9UICgiLCB0X2JpbGxfcmF0ZV9Fb1QkRGF0ZSwgIik6ICIsIHJvdW5kKHRfYmlsbF9yYXRlX0VvVCRSYXRlICogMTAwLCAyKSwgIiVcbiIsIHNlcCA9ICIiKQ0KYGBgDQoNCg0KQ2FsY3VsYXRlIHRoZSBGTG9hdGluZy1SYXRlIFBheW1lbnQNCg0KYGBge3J9DQojIEZsb2F0aW5nLXJhdGUgcGF5bWVudCBjYWxjdWxhdGlvbg0KZmxvYXRpbmdfcGF5bWVudCA8LSBub3Rpb25hbF9hbW91bnQgKiB0X2JpbGxfcmF0ZV9Fb1QkUmF0ZSAqIHllYXJfZnJhY3Rpb24NCg0KIyBQcmludCB0aGUgZmxvYXRpbmctcmF0ZSBwYXltZW50DQpjYXQoIkZsb2F0aW5nLVJhdGUgUGF5bWVudDogJCIsIHJvdW5kKGZsb2F0aW5nX3BheW1lbnQsIDIpLCAiXG4iLCBzZXAgPSAiIikNCmBgYA0KDQoNCkNvbXB1dGUgdGhlIE5ldCBQYXltZW50DQoNCmBgYHtyfQ0KIyBOZXQgcGF5bWVudA0KbmV0X3BheW1lbnQgPC0gZmxvYXRpbmdfcGF5bWVudCAtIGZpeGVkX3BheW1lbnQNCg0KIyBEZXRlcm1pbmUgaWYgeW91IGdhaW4gb3IgbG9zZQ0KaWYgKG5ldF9wYXltZW50ID4gMCkgew0KICByZXN1bHQgPC0gImdhaW4iDQp9IGVsc2UgaWYgKG5ldF9wYXltZW50IDwgMCkgew0KICByZXN1bHQgPC0gImxvc2UiDQp9IGVsc2Ugew0KICByZXN1bHQgPC0gImJyZWFrIGV2ZW4iDQp9DQoNCiMgUHJpbnQgdGhlIG5ldCBwYXltZW50IGFuZCByZXN1bHQNCmNhdCgiTmV0IFBheW1lbnQ6ICQiLCByb3VuZChuZXRfcGF5bWVudCwgMiksICJcbiIsIHNlcCA9ICIiKQ0KY2F0KCJZb3UgIiwgcmVzdWx0LCAiIG9uIHRoZSBzd2FwLlxuIiwgc2VwID0gIiIpDQpgYGANCg0KDQojIyMgQW5hbHlzaXMgb2YgcmVzdWx0cw0KDQpUaGlzIGxvc3Mgb2NjdXJzIGJlY2F1c2UgdGhlIGZsb2F0aW5nIHJhdGUgeW91IHJlY2VpdmUgaXMgbG93ZXIgdGhhbiB0aGUgZml4ZWQgcmF0ZSB5b3UgcGF5Lg0KSW50ZXJlc3QgUmF0ZSBNb3ZlbWVudHM6IEluIHRoaXMgc2NlbmFyaW8sIHRoZSAyNi13ZWVrIFQtYmlsbCByYXRlIGF0IEVvVCB3YXMgbG93ZXIgdGhhbiB0aGUgZml4ZWQgcmF0ZSBhZ3JlZWQgdXBvbi4gVGhpcyByZXN1bHRlZCBpbiBhIG5ldCBsb3NzIGZvciB5b3Ugb24gdGhlIHN3YXAuDQpSYXRlIGF0IEVvVCB3YXMgMC4wNDIzDQoNClJpc2sgTWFuYWdlbWVudDogU3dhcHMgYXJlIHVzZWQgdG8gbWFuYWdlIGludGVyZXN0IHJhdGUgcmlzay4gQnkgZW50ZXJpbmcgaW50byB0aGlzIHN3YXAsIHlvdSB3ZXJlIHNwZWN1bGF0aW5nIHRoYXQgdGhlIDI2LXdlZWsgVC1iaWxsIHJhdGUgYXQgRW9UIHdvdWxkIGJlIGhpZ2hlciB0aGFuIDYlLg0KDQpBcyB3ZSBoYXZlIG1lbnRpb25lZCBpbiB0aGUgYmVnaW5uaW5nLCBhIGRlZXAga25vd2xlZGdlIG9mIHRoZSB1bmRlcmx5aW5nIGFzc2V0L2ludGVyZXN0L2luZGV4IGlzIGNydWNpYWwgd2hlbiBlbnRlcmluZyBhIHN3YXAgY29udHJhY3QgYXMgdGhlIHByaWNlIHJpc2sgd2lsbCBiZSBkZXRlcm1pbmVkIGJ5IHRoZW0uIEluIHRoaXMgY2FzZSwgdGhlIGxvd2VyLXRoYW4tZXhwZWN0ZWQgcmF0ZSBoYXMgbGVkIHRvIGEgc2lnbmlmaWNhbnQgbG9zcy4NCg0KDQoNCiMjIEwxMS44IC0gTDExLjEyLiBNZWFzdXJpbmcgYW5kIGV4cGxhaW5pbmcgZXhjaGFuZ2UgcmF0ZSBtb3ZlbWVudHMNCg0KIyMjIEV4cGxhbmF0aW9ucyBBaGVhZA0KDQpJbiB0aGlzIHNlY3Rpb24gd2Ugd2lsbCBiZSBtZWFzdXJpbmcgYW5kIGV4cGxhaW5pbmcgZXhjaGFuZ2UgcmF0ZSBtb3ZlbWVudHMuIEluIG9yZGVyIHRvIGJldHRlciB1bmRlcnN0YW5kIHRoaXMgcGhlbm9tZW5hIHdlIHdpbGwgaGF2ZSB0byB0YWtlIGludG8gYWNjb3VudCBjZXJ0YWluIGNvbmNlcHRzLiANCg0KDQojIyMjIEN1cnJlbmN5IGZsdWN0dWF0aW9uDQpXaGVuIHdlIHRhbGsgYWJvdXQgY3VycmVudCBmbHVjdHVhdGlvbiwgd2UgYXJlIHJlZmVycmluZyB0byB0aGUgY2hhbmdlIGluIHRoZSByZWxhdGl2ZSB2YWx1ZSBvZiBvbmUgYWdhaW5zdCB0aGUgb3RoZXIuIEluIG90aGVyIHdvcmRzLCBpcyB0aGUgY2hhbmdlIGluIHRoZSBlcXVpdmFsZW5jaWVzIG9mIHRoZSB2YWx1ZSBvZiB0aGUgY3VycmVuY2llcy4gDQoNCg0KIyMjIyBFeGNoYW5nZSBSYXRlcw0KRXhjaGFuZ2UgUmF0ZXMgYXJlIHRoZSBudW1lcmljYWwgcmVwcmVzZW50YXRpb24gb2YgdGhlIGN1cnJlbmN5IGZsdWN0dWF0aW9uLiBUaGF0IGlzIHRoZSB2YWx1ZSBvZiBvbmUgY3VycmVuY3kgYWdhaW5zdCB0aGUgb3RoZXIgaW4gYW4gc3BlY2lmaWMgbW9tZW50LiBFeGNoYW5nZSBSYXRlcyBmbHVjdHVhdGUgYW5kIGFyZSBncmVhdCBlY29ub21pY2FsIGluZGljYXRvcnMuIFRoZXJlIGFyZSBzZXZlcmFsIHJlYXNvbnMgZm9yIHRoZSBmbHVjdHVhdGlvbiBvZiBleGNoYW5nZSByYXRlcywgc3VjaCBhcyBpbnRlcmVzdCByYXRlcywgZ2VuZXJhbCBtYWNyb2Vjb25vbWljIGRhdGEgb2YgZWFjaCBjb3VudHJ5LCBwb2xpdGljYWwgcG9saWNpZXMgYW5kIHN0YWJpbGl0eSwgaW5mbGF0aW9uIHJhdGVzLCBkYXRhIGFuZCBwb2xpY3ksIGFuZCBmb3JlaWduIGludmVzdG1lbnRzLiANCkFub3RoZXIgZmFjdG9yIHRoYXQgY3JlYXRlcyBmbHVjdHVhdGlvbiBpbiBleGNoYW5nZSByYXRlcyBpcyB0aGUgc3BlY3VsYXRpb24uIA0KDQoNCiMjIyMgRWZmZWN0cw0KVGhlIGZsdWN0dWF0aW9ucyBpbiBjdXJyZW5jeSAoYW5kIGV4Y2hhbmdlIHJhdGVzKSBoYXZlIGFuIGltcGFjdCBpbiBzZXZlcmFsIGFzcGVjdHMgb2YgdGhlIGVjb25vbXkuIA0KICAxLiBJbnRlcm5hdGlvbmFsIHRyYWRlLiBBIHdlYWsgY3VycmVuY3kgZWFzaWx5IGJlbmVmaXRzIGZyb20gZXhwb3J0cywgd2hpbGUgYSBzdHJvbmcgb25lIG1heSByZWR1Y2UgdGhlaXIgZXhwb3J0IGNhcGFiaWxpdHkuICANCiAgMi4gSW5mbGF0aW9uLiBBIHN0cm9uZyBjdXJyZW5jeSB3aWxsIGhhdmUgYSBsb3Qgb2YgaW1wb3J0IGNhcGFiaWxpdHkgYW5kIHdpbGwgYmUgYWJsZSB0byBrZWVwIGluZmxhdGlvbiBzdGFibGUuIEhvd2V2ZXIsIGEgd2VhayBjdXJyZW5jeSB3aWxsIGhhdmUgaGlnaGVyIGltcG9ydCBjb3N0cyBhbmQgd2lsbCBvdmVyYWxsIGluY3JlYXNlIGRvbWVzdGljIGluZmxhdGlvbi4gDQogIDMuIEludmVzdG1lbnQuIFRoZSBzdGFiaWxpdHkgb3Igc3RyZW5ndGhlbiBvZiBhIGN1cnJlbmN5IHVzdWFsbHkgaW5kaWNhdGUgYW4gc3RhYmxlL3N0cm9uZyBlY29ub215IGFuZCBwb2xpdGljYWwgc2l0dWF0aW9uLiBUaGVyZWZvcmUsIGl0IHdpbGwgYmUgbXVjaCBtb3JlIGF0dHJhY3RpdmUgdG8gbWFrZSBhbiBpbnZlc3RtZW50IGluIHRob3NlIGNvdW50cmllcyB3aXRoIGEgc3Ryb25nIGN1cnJlbmN5LiBPcHBvc2l0ZWx5LCBhIHdlYWsgY3VycmVuY3kgKG9yIGEgY29uc3RhbnRseSBjaGFuZ2luZyBvbmUpIHdpbGwgaW5kaWNhdGUgd2Vha25lc3MgYW5kIGluc3RhYmlsaXR5LiANCiAgNC4gRWNvbm9taWMgc3RhYmlsaXR5IGFuZCBncm93dGguIEltcGFjdHMgaW4gR0RQLCBpbnZlc3RtZW50LCBpbmZsYXRpb24gYW5kIGludGVybmF0aW9uYWwgdHJhZGUgYWxsIGNvbnRyaWJ1dGUgdG93YXJkcyB0aGUgZWNvbm9teSBvZiBhIGNvdW50cnksIHdoZXRoZXIgbWFraW5nIGluIHN0YWJsZSBhbmQgc3Ryb25nIG9yIHdlYWsgYSB1bnN0YWJsZS4gDQoNCg0KIyMjIEJlZm9yZSB0aGUgZXhlcmNpc2VzDQoNCkxvYWQgUGFja2FnZXMNCg0KYGBge3J9DQojIExvYWQgcmVxdWlyZWQgcGFja2FnZXMNCmxpYnJhcnkocXVhbnRtb2QpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpDQoNCmBgYA0KDQoNCkRlZmluZSBCZWdpbm5pbmcgYW5kIEVuZCBvZiBUZXJtIERhdGVzDQoNCmBgYHtyfQ0KIyBEZWZpbmUgQmVnaW5uaW5nIG9mIFRlcm0gKEJvVCkgYW5kIEVuZCBvZiBUZXJtIChFb1QpIGRhdGVzDQpCb1RfZGF0ZSA8LSBhcy5EYXRlKCIyMDI0LTA1LTAxIikNCkVvVF9kYXRlIDwtIGFzLkRhdGUoIjIwMjQtMDktMzAiKQ0KDQpgYGANCg0KDQojIyMgTDExLjggRGV0ZXJtaW5pbmcgdGhlIFBlcmNlbnRhZ2UgQ2hhbmdlIGluIHRoZSBWYWx1ZSBvZiB0aGUgQnJpdGlzaCBQb3VuZA0KDQoNClJldHJpZXZlIEdQQi9VU0QgRXhjaGFuZ2UgUmF0ZSBEYXRhDQoNCmBgYHtyfQ0KIyBHZXQgR0JQL1VTRCBleGNoYW5nZSByYXRlIGRhdGENCmdldFN5bWJvbHMoIkdCUFVTRD1YIiwgc3JjID0gInlhaG9vIiwgZnJvbSA9IEJvVF9kYXRlIC0gNywgdG8gPSBFb1RfZGF0ZSArIDcsIGF1dG8uYXNzaWduID0gVFJVRSkNCg0KIyBBc3NpZ24gZGF0YSB0byBhIHZhcmlhYmxlDQpnYnBfdXNkX2RhdGEgPC0gYEdCUFVTRD1YYA0KYGBgDQoNCg0KR2V0IGV4Y2hhbmdlIFJhdGVzIGF0IEJvVCBhbmQgRW9UDQoNCmBgYHtyfQ0KIyBGdW5jdGlvbiB0byBnZXQgdGhlIGV4Y2hhbmdlIHJhdGUgb24gYSBzcGVjaWZpYyBkYXRlDQpnZXRfcmF0ZV9vbl9kYXRlIDwtIGZ1bmN0aW9uKGRhdGEsIGRhdGUpIHsNCiAgaW5kZXgoZGF0YSkgPC0gYXMuRGF0ZShpbmRleChkYXRhKSkNCiAgDQogIGF2YWlsYWJsZV9kYXRlcyA8LSBpbmRleChkYXRhKVtpbmRleChkYXRhKSA8PSBkYXRlXQ0KICANCiAgaWYgKGxlbmd0aChhdmFpbGFibGVfZGF0ZXMpID09IDApIHsNCiAgICB3YXJuaW5nKHBhc3RlKCJObyBkYXRhIGF2YWlsYWJsZSBvbiBvciBiZWZvcmUiLCBkYXRlKSkNCiAgICByZXR1cm4obGlzdChSYXRlID0gTkEsIERhdGUgPSBOQSkpDQogIH0NCiAgDQogIGRhdGVfdXNlZCA8LSBtYXgoYXZhaWxhYmxlX2RhdGVzKQ0KICANCiAgcmF0ZSA8LSBhcy5udW1lcmljKENsKGRhdGFbZGF0ZV91c2VkXSkpDQogIA0KICByZXR1cm4obGlzdCgNCiAgICBSYXRlID0gcmF0ZSwNCiAgICBEYXRlID0gYXMuRGF0ZShkYXRlX3VzZWQpDQogICkpDQp9DQoNCiMgR2V0IHJhdGVzIGF0IEJvVCBhbmQgRW9UDQpnYnBfcmF0ZV9Cb1QgPC0gZ2V0X3JhdGVfb25fZGF0ZShnYnBfdXNkX2RhdGEsIEJvVF9kYXRlKQ0KZ2JwX3JhdGVfRW9UIDwtIGdldF9yYXRlX29uX2RhdGUoZ2JwX3VzZF9kYXRhLCBFb1RfZGF0ZSkNCg0KIyBQcmludCB0aGUgZXhjaGFuZ2UgcmF0ZXMNCmNhdCgiR0JQL1VTRCBSYXRlIGF0IEJvVCAoIiwgZ2JwX3JhdGVfQm9UJERhdGUsICIpOiAiLCByb3VuZChnYnBfcmF0ZV9Cb1QkUmF0ZSwgNCksICJcbiIsIHNlcCA9ICIiKQ0KY2F0KCJHQlAvVVNEIFJhdGUgYXQgRW9UICgiLCBnYnBfcmF0ZV9Fb1QkRGF0ZSwgIik6ICIsIHJvdW5kKGdicF9yYXRlX0VvVCRSYXRlLCA0KSwgIlxuIiwgc2VwID0gIiIpDQpgYGANCg0KDQpDYWxjdWxhdGUgdGhlIFBlcmNlbnRhZ2UgQ2hhbmdlDQoNCmBgYHtyfQ0KIyBDYWxjdWxhdGUgdGhlIHBlcmNlbnRhZ2UgY2hhbmdlDQpnYnBfcGVyY2VudGFnZV9jaGFuZ2UgPC0gKGdicF9yYXRlX0VvVCRSYXRlIC0gZ2JwX3JhdGVfQm9UJFJhdGUpIC8gZ2JwX3JhdGVfQm9UJFJhdGUgKiAxMDANCg0KIyBQcmludCB0aGUgcmVzdWx0DQpjYXQoIlBlcmNlbnRhZ2UgQ2hhbmdlIGluIEdCUC9VU0Q6ICIsIHJvdW5kKGdicF9wZXJjZW50YWdlX2NoYW5nZSwgMiksICIlXG4iLCBzZXAgPSAiIikNCmBgYA0KDQoNCkRldGVybWluZSBBcHByZWNpYXRpb24gb3IgRGVwcmVjaWF0aW9uDQoNCmBgYHtyfQ0KaWYgKGdicF9wZXJjZW50YWdlX2NoYW5nZSA+IDApIHsNCiAgZ2JwX3Jlc3VsdCA8LSAiYXBwcmVjaWF0ZWQiDQp9IGVsc2UgaWYgKGdicF9wZXJjZW50YWdlX2NoYW5nZSA8IDApIHsNCiAgZ2JwX3Jlc3VsdCA8LSAiZGVwcmVjaWF0ZWQiDQp9IGVsc2Ugew0KICBnYnBfcmVzdWx0IDwtICJyZW1haW5lZCB0aGUgc2FtZSINCn0NCg0KY2F0KCJUaGUgQnJpdGlzaCBwb3VuZCBoYXMgIiwgZ2JwX3Jlc3VsdCwgIiBhZ2FpbnN0IHRoZSBVUyBkb2xsYXIgb3ZlciB0aGUgc2Nob29sIHRlcm0uXG4iLCBzZXAgPSAiIikNCmBgYA0KDQoNCiMjIyMgQW5hbHlzaXMNClRoZSBhcHByZWNpYXRpb24gb2YgdGhlIEJyaXRpc2ggcG91bmQgYWdhaW5zdCB0aGUgVVMgZG9sbGFyIG1heSBpbmRpY2F0ZSwgYXMgd2UgaGF2ZSBwcmV2aW91c2x5IGV4cGxhaW5lZCwgYW4gc3RyZW5ndGhlbmluZyBvZiBVSydzIGVjb25vbXkgYWdhaW5zdCB0aGUgVVMuIEFsdGhvdWdoIHdlIGNhbm5vdCBiZSBjZXJ0YWluIHdpdGhvdXQgbXVjaCBmdXJ0aGVyIGFuYWx5c2lzIG9mIHdoYXQgbWF5IGhhdmUgY2F1c2VkIHRoaXMgbm90b3Jpb3VzIGFwcHJlY2lhdGlvbiBvZiB0aGUgY3VycmVuY3ksIHdlIGNhbiBwcmVzdW1lIGlzIGEgbWl4IG9mIHNldmVyYWwgZmFjdG9ycyB0aGF0IGhhdmUgYmVlbiBhbHJlYWR5IGV4cGxhaW5lZC4gVGhpcyBjb3VsZCBpbmNsdWRlIGZhdm9yYWJsZSBHRFAgZGF0YSBmb3IgdGhlIFVLLCBhbiBhZ2dyZXNzaXZlIG1vbmV0YXJ5IHBvbGljeSBmcm9tIHRoZSBCYW5rIG9mIEVuZ2xhbmQgd2l0aCBoaWdoZXIgaW50ZXJlc3QgcmF0ZXMsIG9yIHRoZSBzdGFiaWxpemF0aW9uIG9mIGNlcnRhaW4gYXNwZWN0cyByZWdhcmRpbmcgQnJleGl0LiBPbiB0aGUgb3RoZXIgc2lkZSwgdGhlIFVTIG1heSBoYXZlIGJlY29tZSBzb21ld2hhdCBsZXNzIGF0dHJhY3RpdmUgZm9yIGludmVzdG9ycyB3aG8gbG9vayBmb3Igcmlza2llciBvcHBvcnR1bml0aWVzLCBzbG93IGluZmxhdGlvbiB3aXRoIGEgbGVzcyBhZ2dyZXNzaXZlIG1vbmV0YXJ5IHBvbGljeSBvciBvdmVyYWxsIGRpc2NvbnRlbnQgd2l0aCB0aGUgcG9saXRpY2FsIHNpdHVhdGlvbi4gVGhlIHVwY29taW5nIFVTQSBQcmVzaWRlbnRpYWwgRWxlY3Rpb25zIG1heSBoYXZlIHJpc2VuIGNlcnRhaW4gY29uY2VybnMgYW5kIGNyZWF0ZWQgYSBzZW5zZSBvZiBpbnN0YWJpbGl0eSB0aGF0IGhhcyBiZWVuIHBvcnRyYXllZCBpbiB0aGUgZXhjaGFuZ2UgcmF0ZSBhZ2FpbnN0IHRoZSBCcml0aXNoIFBvdW5kLiANCg0KDQojIyMgTDExLjkgRGV0ZXJtaW5pbmcgdGhlIFBlcmNlbnRhZ2UgQ2hhbmdlIGluIHRoZSBWYWx1ZSBvZiB0aGUgSmFwYW5lc2UgWWVuDQoNCg0KUmV0cmlldmUgVVNEL0pQWSBFeGNoYW5nZSBSYXRlIERhdGENCg0KYGBge3J9DQojIEdldCBVU0QvSlBZIGV4Y2hhbmdlIHJhdGUgZGF0YQ0KZ2V0U3ltYm9scygiSlBZPVgiLCBzcmMgPSAieWFob28iLCBmcm9tID0gQm9UX2RhdGUgLSA3LCB0byA9IEVvVF9kYXRlICsgNywgYXV0by5hc3NpZ24gPSBUUlVFKQ0KDQojIEFzc2lnbiBkYXRhIHRvIGEgdmFyaWFibGUNCnVzZF9qcHlfZGF0YSA8LSBgSlBZPVhgDQpgYGANCg0KDQpHZXQgRXhjaGFuZ2UgUmF0ZXMgYXQgQm9UIGFuZCBFb1QNCg0KYGBge3J9DQojIEdldCByYXRlcyBhdCBCb1QgYW5kIEVvVA0KanB5X3JhdGVfQm9UIDwtIGdldF9yYXRlX29uX2RhdGUodXNkX2pweV9kYXRhLCBCb1RfZGF0ZSkNCmpweV9yYXRlX0VvVCA8LSBnZXRfcmF0ZV9vbl9kYXRlKHVzZF9qcHlfZGF0YSwgRW9UX2RhdGUpDQoNCiMgUHJpbnQgdGhlIGV4Y2hhbmdlIHJhdGVzDQpjYXQoIlVTRC9KUFkgUmF0ZSBhdCBCb1QgKCIsIGpweV9yYXRlX0JvVCREYXRlLCAiKTogIiwgcm91bmQoanB5X3JhdGVfQm9UJFJhdGUsIDQpLCAiXG4iLCBzZXAgPSAiIikNCmNhdCgiVVNEL0pQWSBSYXRlIGF0IEVvVCAoIiwganB5X3JhdGVfRW9UJERhdGUsICIpOiAiLCByb3VuZChqcHlfcmF0ZV9Fb1QkUmF0ZSwgNCksICJcbiIsIHNlcCA9ICIiKQ0KYGBgDQoNCg0KQ2FsY3VsYXRlIHRoZSBQZXJjZW50YWdlIFJhdGUNCg0KYGBge3J9DQojIEludmVydCB0aGUgcmF0ZXMgdG8gZ2V0IEpQWSBwZXIgVVNEDQpqcHlfcGVyX3VzZF9Cb1QgPC0gMSAvIGpweV9yYXRlX0JvVCRSYXRlDQpqcHlfcGVyX3VzZF9Fb1QgPC0gMSAvIGpweV9yYXRlX0VvVCRSYXRlDQoNCiMgQ2FsY3VsYXRlIHRoZSBwZXJjZW50YWdlIGNoYW5nZQ0KanB5X3BlcmNlbnRhZ2VfY2hhbmdlIDwtIChqcHlfcGVyX3VzZF9Fb1QgLSBqcHlfcGVyX3VzZF9Cb1QpIC8ganB5X3Blcl91c2RfQm9UICogMTAwDQoNCiMgUHJpbnQgdGhlIHJlc3VsdA0KY2F0KCJQZXJjZW50YWdlIENoYW5nZSBpbiBKUFkvVVNEOiAiLCByb3VuZChqcHlfcGVyY2VudGFnZV9jaGFuZ2UsIDIpLCAiJVxuIiwgc2VwID0gIiIpDQpgYGANCg0KDQpEZXRlcm1pbmUgQXBwcmVjaWF0aW9uIG9yIERlcHJlY2lhdGlvbg0KDQpgYGB7cn0NCmlmIChqcHlfcGVyY2VudGFnZV9jaGFuZ2UgPiAwKSB7DQogIGpweV9yZXN1bHQgPC0gImFwcHJlY2lhdGVkIg0KfSBlbHNlIGlmIChqcHlfcGVyY2VudGFnZV9jaGFuZ2UgPCAwKSB7DQogIGpweV9yZXN1bHQgPC0gImRlcHJlY2lhdGVkIg0KfSBlbHNlIHsNCiAganB5X3Jlc3VsdCA8LSAicmVtYWluZWQgdGhlIHNhbWUiDQp9DQoNCmNhdCgiVGhlIEphcGFuZXNlIHllbiBoYXMgIiwganB5X3Jlc3VsdCwgIiBhZ2FpbnN0IHRoZSBVUyBkb2xsYXIgb3ZlciB0aGUgc2Nob29sIHRlcm0uXG4iLCBzZXAgPSAiIikNCmBgYA0KDQoNCiMjIyMgQW5hbHlzaXMNCkp1c3QgYXMgd2UgaGF2ZSBleHBsYWluZWQgaW4gdGhlIHByZXZpb3VzIHF1ZXN0aW9uLiB0aGUgVVMgbWF5IGhhdmUgZmFjZWQgYSBwZXJpb2Qgb2YgaW5zdGFiaWxpdHkgYW5kIHNsb3duZXNzIHRoYXQgY291bGQgaGF2ZSBjYXVzZWQgYSBsb3dlciBkZW1hbmQgZm9yIFVTIGRvbGxhcnMuIENvbnZlcnNlbHksIHRoZSBCYW5rIG9mIEphcGFuLCBtYXkgaGF2ZSBhZG9wdGVkIGEgbW9yZSBzdHJpY3QgcmVndWxhdGlvbiAoaW4gb3Bwb3NpdGlvbiB3aXRoIGl0cyB0cmFkaXRpb25hbCBhcHByb2FjaCkgZHVlIHRvIGhpZ2ggaW5mbGF0aW9uIG9yIGR1ZSB0byBub3JtYWxpemF0aW9uIHN0cmF0ZWdpZXMsIHdoaWNoIG1heSBoYXZlIGNhdXNlZCBhIHJlYWN0aW9uIGluIHRoZSBjdXJyZW5jeSBtYXJrZXRzLiBKYXBhbiBtYXkgaGF2ZSBhbHNvIGhhZCBwb3NpdGl2ZSByZXBvcnRzIG9yIGEgcmVjb3ZlcnkgaW4gaXRzIHRyYWRlIGJhbGFuY2UuIA0KDQoNCiMjIyBMMTEuMTAgRGV0ZXJtaW5pbmcgdGhlIFBlcmNlbnRhZ2UgQ2hhbmdlIGluIHRoZSBWYWx1ZSBvZiB0aGUgTWV4aWNhbiBQZXNvDQoNCg0KUmV0cmlldmUgVVNEL01YTiBFeGNoYW5nZSBSYXRlIERhdGENCg0KYGBge3J9DQojIEdldCBVU0QvTVhOIGV4Y2hhbmdlIHJhdGUgZGF0YQ0KZ2V0U3ltYm9scygiTVhOPVgiLCBzcmMgPSAieWFob28iLCBmcm9tID0gQm9UX2RhdGUgLSA3LCB0byA9IEVvVF9kYXRlICsgNywgYXV0by5hc3NpZ24gPSBUUlVFKQ0KDQojIEFzc2lnbiBkYXRhIHRvIGEgdmFyaWFibGUNCnVzZF9teG5fZGF0YSA8LSBgTVhOPVhgDQpgYGANCg0KDQpHZXQgRXhjaGFuZ2UgUmF0ZXMgYXQgQm9UIGFuZCBFb1QNCg0KYGBge3J9DQojIEdldCByYXRlcyBhdCBCb1QgYW5kIEVvVA0KbXhuX3JhdGVfQm9UIDwtIGdldF9yYXRlX29uX2RhdGUodXNkX214bl9kYXRhLCBCb1RfZGF0ZSkNCm14bl9yYXRlX0VvVCA8LSBnZXRfcmF0ZV9vbl9kYXRlKHVzZF9teG5fZGF0YSwgRW9UX2RhdGUpDQoNCiMgUHJpbnQgdGhlIGV4Y2hhbmdlIHJhdGVzDQpjYXQoIlVTRC9NWE4gUmF0ZSBhdCBCb1QgKCIsIG14bl9yYXRlX0JvVCREYXRlLCAiKTogIiwgcm91bmQobXhuX3JhdGVfQm9UJFJhdGUsIDQpLCAiXG4iLCBzZXAgPSAiIikNCmNhdCgiVVNEL01YTiBSYXRlIGF0IEVvVCAoIiwgbXhuX3JhdGVfRW9UJERhdGUsICIpOiAiLCByb3VuZChteG5fcmF0ZV9Fb1QkUmF0ZSwgNCksICJcbiIsIHNlcCA9ICIiKQ0KYGBgDQoNCg0KQ2FsY3VsYXRlIHRoZSBQZXJjZW50YWdlIENoYW5nZQ0KDQpgYGB7cn0NCiMgSW52ZXJ0IHRoZSByYXRlcyB0byBnZXQgTVhOIHBlciBVU0QNCm14bl9wZXJfdXNkX0JvVCA8LSAxIC8gbXhuX3JhdGVfQm9UJFJhdGUNCm14bl9wZXJfdXNkX0VvVCA8LSAxIC8gbXhuX3JhdGVfRW9UJFJhdGUNCg0KIyBDYWxjdWxhdGUgdGhlIHBlcmNlbnRhZ2UgY2hhbmdlDQpteG5fcGVyY2VudGFnZV9jaGFuZ2UgPC0gKG14bl9wZXJfdXNkX0VvVCAtIG14bl9wZXJfdXNkX0JvVCkgLyBteG5fcGVyX3VzZF9Cb1QgKiAxMDANCg0KIyBQcmludCB0aGUgcmVzdWx0DQpjYXQoIlBlcmNlbnRhZ2UgQ2hhbmdlIGluIE1YTi9VU0Q6ICIsIHJvdW5kKG14bl9wZXJjZW50YWdlX2NoYW5nZSwgMiksICIlXG4iLCBzZXAgPSAiIikNCmBgYA0KDQoNCkRldGVybWluZSBBcHByZWNpYXRpb24gb3IgRGVwcmVjaWF0aW9uDQoNCmBgYHtyfQ0KaWYgKG14bl9wZXJjZW50YWdlX2NoYW5nZSA+IDApIHsNCiAgbXhuX3Jlc3VsdCA8LSAiYXBwcmVjaWF0ZWQiDQp9IGVsc2UgaWYgKG14bl9wZXJjZW50YWdlX2NoYW5nZSA8IDApIHsNCiAgbXhuX3Jlc3VsdCA8LSAiZGVwcmVjaWF0ZWQiDQp9IGVsc2Ugew0KICBteG5fcmVzdWx0IDwtICJyZW1haW5lZCB0aGUgc2FtZSINCn0NCg0KY2F0KCJUaGUgTWV4aWNhbiBwZXNvIGhhcyAiLCBteG5fcmVzdWx0LCAiIGFnYWluc3QgdGhlIFVTIGRvbGxhciBvdmVyIHRoZSBzY2hvb2wgdGVybS5cbiIsIHNlcCA9ICIiKQ0KYGBgDQoNCg0KIyMjIyBBbmFseXNpcw0KSGF2ZSB3ZSBub3Qgc2VlbiB0aGUgcHJldmlvdXMgcmVzdWx0cywgd2UgbWlnaHQgaGF2ZSBoYWQgdGhlIGluaXRpYWwgdGhvdWdodCB0aGF0IHRoZXNlIHJlc3VsdHMgYXJlIHRoZSBtYW5pZmVzdGF0aW9uIG9mIGEgc3Ryb25nIFVTIERvbGxhciwgd2hpY2ggc3RyZW5ndGhlbnMgYWdhaW5zdCB0aGUgTWV4aWNhbiBQZXNvLiBIb3dldmVyLCB3ZSBhbHJlYWR5IGtub3cgdGhhdCB0aGUgVVNEIGhhZCB3ZWFrZW5lZCBhZ2FpbnN0IHRoZSBvdGhlciB0d28gY3VycmVuY2llcyBhbmFseXplZCwgc28gd2UgbWF5IGFzc3VtZSB0aGF0IHRoaXMgaXMgbm90IHRoZSBvdXRjb21lIG9mIGFuIHN0cm9uZyBVU0EgYnV0IHJhdGhlciBhIHJlYWxseSB3b3JzZW5lZCBNZXhpY28uIA0KSWYgd2UgdGFrZSBhIGxvb2sgaW50byBNZXhpY28ncyBwb2xpdGljcyBkdXJpbmcgdGhlIFRlcm0gUGVyaW9kLCB3ZSB3aWxsIG5vdGljZSB0aGF0IFByZXNpZGVudGlhbCBFbGVjdGlvbnMgdG9vayBwbGFjZSwgd2l0aCB0aGUgdmljdG9yeSBvZiBDbGF1ZGlhIFNoZWluYmF1bS4gVGhlIGRpZmZlcmVuY2UgaW4gcG9zaXRpb25zIHdpdGggdGhlIFVTQSBpbiBzZXZlcmFsIGludGVybmF0aW9uYWwgbWF0dGVycyBtYXkgaGF2ZSBwdXNoZWQgdGhpcyBkcm9wIGluIHRoZSBNZXhpY2FuIFBlc28sIHdoaWNoIGhhcyBub3QgeWV0IHN0b3BwZWQgYXMgb2YgdG9kYXksIGFsdGhvdWdoIG91ciBFbmQgb2YgVGVybSBEYXRlIG9ubHkgZGF0ZXMgdW50aWwgU2VwdGVtYmVyLiANCg0KDQojIyMgTDExLjExIERldGVybWluaW5nIHRoZSBQZXIgVW5pdCBHYWluIG9yIExvc3MgZm9yIEJyaXRpc2ggUG91bmQgRnV0dXJlcw0KDQoNCkRldGVybWluZSB0aGUgcGVyIHVuaXQgZ2FpbiBvciBsb3NzIGlmIHlvdSBoYWQgcHVyY2hhc2VkIEJyaXRpc2ggcG91bmQgZnV0dXJlcyBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSB0ZXJtIGFuZCBzb2xkIHRoZW0gYXQgdGhlIGVuZCBvZiB0aGUgdGVybS4NClVzZSBHUEIvVVNEIEV4Y2hhbmdlIHJhdGVzIGFzIFByb3h5LiANCg0KDQpDYWxjdWxhdGUgdGhlIFBlciBVbml0IEdhaW4gb3IgTG9zcw0KDQpgYGB7cn0NCiMgQ2FsY3VsYXRlIHRoZSBwZXIgdW5pdCBnYWluIG9yIGxvc3MNCnBlcl91bml0X2dhaW5fbG9zcyA8LSBnYnBfcmF0ZV9Fb1QkUmF0ZSAtIGdicF9yYXRlX0JvVCRSYXRlDQoNCiMgUHJpbnQgdGhlIHJlc3VsdA0KY2F0KCJQZXIgVW5pdCBHYWluL0xvc3MgZm9yIEdCUCBGdXR1cmVzOiAkIiwgcm91bmQocGVyX3VuaXRfZ2Fpbl9sb3NzLCA0KSwgIiBwZXIgR0JQXG4iLCBzZXAgPSAiIikNCmBgYA0KDQpJbiB0aGlzIGV4ZXJjaXNlIHdlIGhhdmUgZGV0ZXJtaW5lZCB0aGUgZ2FpbiBwZXIgR1BCIGZvciB0aGUgZnV0dXJlcyBjb250cmFjdC4NCg0KDQojIyMgTDExLjEyIERldGVybWluaW5nIHRoZSBEb2xsYXIgQW1vdW50IG9mIFlvdXIgR2FpbiBvciBMb3NzIG9uIHRoZSBGdXR1cmVzIENvbnRyYWN0DQoNCkdpdmVuIHRoYXQgYSBzaW5nbGUgZnV0dXJlcyBjb250cmFjdCBvbiBCcml0aXNoIHBvdW5kcyByZXByZXNlbnRzIDYyLDUwMCBwb3VuZHMsIGRldGVybWluZSB0aGUgZG9sbGFyIGFtb3VudCBvZiB5b3VyIGdhaW4gb3IgbG9zcy4NCg0KYGBge3J9DQojIE51bWJlciBvZiBwb3VuZHMgcGVyIGZ1dHVyZXMgY29udHJhY3QNCmNvbnRyYWN0X3NpemUgPC0gNjI1MDANCg0KIyBUb3RhbCBnYWluIG9yIGxvc3MNCnRvdGFsX2dhaW5fbG9zcyA8LSBwZXJfdW5pdF9nYWluX2xvc3MgKiBjb250cmFjdF9zaXplDQoNCiMgUHJpbnQgdGhlIHJlc3VsdA0KY2F0KCJUb3RhbCBHYWluL0xvc3Mgb24gRnV0dXJlcyBDb250cmFjdDogJCIsIHJvdW5kKHRvdGFsX2dhaW5fbG9zcywgMiksICJcbiIsIHNlcCA9ICIiKQ0KYGBgDQoNCg0KRGV0ZXJtaW5lIGlmIHlvdSBHYWluZWQgb3IgTG9zdA0KDQpgYGB7cn0NCmlmICh0b3RhbF9nYWluX2xvc3MgPiAwKSB7DQogIGZ1dHVyZXNfcmVzdWx0IDwtICJnYWluZWQiDQp9IGVsc2UgaWYgKHRvdGFsX2dhaW5fbG9zcyA8IDApIHsNCiAgZnV0dXJlc19yZXN1bHQgPC0gImxvc3QiDQp9IGVsc2Ugew0KICBmdXR1cmVzX3Jlc3VsdCA8LSAiYnJva2UgZXZlbiINCn0NCg0KY2F0KCJZb3UgaGF2ZSAiLCBmdXR1cmVzX3Jlc3VsdCwgIiAkIiwgYWJzKHJvdW5kKHRvdGFsX2dhaW5fbG9zcywgMikpLCAiIG9uIHRoZSBmdXR1cmVzIGNvbnRyYWN0LlxuIiwgc2VwID0gIiIpDQpgYGANCg0KV2l0aCBhIGdhaW4gcGVyIEdQQiBvZiAwLjA4MzcgVVNEIGFuZCBhbiBhbW91bnQgb2YgNjI1MDAgcG91bmRzLCB3ZSB3aWxsIGhhdmUgZW5kZWQgYXQgdGhlIGVuZCBvZiB0ZXJtIHdpdGggYSB0b3RhbCBnYWluIG9mIDUyMjkuOTYgVVNELiBUaGlzIGhhcyBiZWVuIHBvc3NpYmxlLCBhcyB3ZSBrbm93LCB0aGFua3MgdG8gdGhlIGFwcHJlY2lhdGlvbiBvZiB0aGUgR1BCIGFnYWluc3QgdGhlIFVTRCwgd2hpY2ggaGUgaGF2ZSBhbHJlYWR5IGFuYWx5emVkIHByZXZpb3VzbHkuIA0KDQoNCg0KDQojIyBMMTIgQ2FwaXRhbCByZXF1aXJlbWVudHMNCkwxMi4xIENhbGN1bGF0ZSB0aGUgb3BlcmF0aW9uYWwsIG1hcmtldCBhbmQgY3JlZGl0IHJpc2sgY2FwaXRhbCByZXF1aXJlbWVudHMgZm9yIEJhbmsgb2YgQW1lcmljYSBhbmQgRGV1dHNjaGUgQmFuayBhcyBvZiBEZWNlbWJlciAzMSwgbGFzdCB5ZWFyLCB3aGljaCBiYW5rIGhhcyBiZXR0ZXIgY2FwaXRhbCBiYXNlPw0KDQoNCiMjIyBEZWZpbml0aW9ucw0KDQojIyMjIE9wZXJhdGlvbmFsIFJpc2sgDQoNCldlIGNhbiBkZWZpbmUgb3BlcmF0aW9uYWwgcmlzayBhcyBhIHR5cGUgb2YgYnVzaW5lc3MgcmlzayBkZXJpdmVkIGZyb20gdGhlIGRhaWx5IGFjdGl2aXR5IG9mIHRoZSBjb21wYW55LiBUaGF0IGlzIHRoZSByaXNrIGRlcml2ZWQgZnJvbSB3aXRoaW4gdGhlIGNvbXBhbnkgcmF0aGVyIHRoYW4gZXh0ZXJuYWwgZm9yY2VzIG9yIGV2ZW50cy4gVGhpcyByaXNrIGluY2x1ZGVzIGZhY3RvcnMgc3VjaCBhcyBwZW9wbGUsIHN5c3RlbXMgYW5kIGludGVybmFsIHByb2NlZHVyZXMuIA0KDQoNCiMjIyMgTWFya2V0IFJpc2sNCg0KTWFya2V0IFJpc2ssIGFsc28ga25vd24gYXMgc3lzdGVtYXRpYyByaXNrLCBjb21wcmlzZXMgYSBzZXJpZXMgb2YgZmFjdG9ycyB0aGF0IGNhbm5vdCBiZSBpbmRpdmlkdWFsaXplZCBidXQgcmF0aGVyIGFmZmVjdCB0aGUgbWFya2V0IGFzIGEgd2hvbGUsIHdpdGhvdXQgdGhlIGNoYW5jZSBvZiBlbGltaW5hdGluZyBpdCB0aHJvdWdoIGRpdmVyc2lmaWNhdGlvbi4gVGhpcyByaXNrIGlzIHVzdWFsbHkgYWZmZWN0ZWQgb3IgbWFkZSBub3RpY2VhYmxlIGJ5IGNoYW5nZXMgb3IgbW92ZW1lbnRzIG9uIHRoZSBtYXJrZXQgcHJpY2UgYW5kIHRoZSBpbnRlcmVzdCByYXRlcywgc28gaXQgaGFzIGFuIHN0cm9uZyBsaW5rIHdpdGggcG9saXRpY3MgYW5kIGVjb25vbWljIGN5Y2xlcy4gDQoNCg0KIyMjIyBDcmVkaXQgUmlzaw0KDQpDcmVkaXQgcmlzayBtZWFzdXJlcyB0aGUgcHJvYmFiaWxpdHkgb2Ygbm90IGJlaW5nIHBheWVkIGJhY2sgYnkgYSBib3Jyb3dlci4gVGhpcyBpcywgdGhlIHJpc2sgb2Ygbm90IGJlaW5nIGFibGUgdG8gcmVjb2xsZWN0IHRoZSBwcmluY2lwYWwgYW5kIHRoZSBpbnRlcmVzdHMsIGxlYWRpbmcgdG8gYSBsb3NzIG9yIGF0IGxlYXN0IGFuIGludGVycnVwdGlvbiBhbmQgZGVsYXkuIFRoaXMgcmlzayBpcyB1c3VhbGx5IGFzc2Vzc2VkIGJ5IGNhcmVmdWxseSBhbmFseXppbmcgdGhlIGJvcnJvd2VyIGFuZCB0YWtpbmcgaW50byBhY2NvdW50IGFsbCBmYWN0b3JzIHRoYXQgY291bGQgbGVhZCB0byBub24tcGF5bWVudC4gV2hlbiB0YWxraW5nIGFib3V0IGNvcnBvcmF0ZSBib25kIGlzc3VlcnMsIHRoZXJlIGFyZSBjcmVkaXQtcmF0aW5nIGFnZW5jaWVzIHdoaWNoIGV2YWx1YXRlIHRoZSBjcmVkaXQgcmlzayBpbiBvcmRlciB0byBpbmZvcm0gdGhlIGludmVzdG9ycyBvZiB0aGUgcHJvYmFiaWxpdHkgb2YgcmVjaWV2aW5nIGJhY2sgdGhlaXIgaW52ZXN0bWVudC4gDQpUaGUgaGlnaGVyIHRoZSBjcmVkaXQgcmlzayBpcywgdGhlIGdyZWF0ZXIgdGhlIGludGVyZXN0IHRoYXQgdGhlIGxlbmRlciBvciBpbnZlc3RvciB3aWxsIGRlbWFuZCwgYXMgdGhlIGNyZWRpdCByaXNrIG11c3QgYmUgY291bnRlcmJhbGFuY2VkIHdpdGggaGlnaGVyIHJld2FyZHMuIA0KDQoNCiMjIyMgUmlzay1XZWlnaHRlZCBBc3NldHMgKFJXQSkNCg0KSW4gdGhlIGV4cGxhbmF0aW9ucyB0aGF0IGZvbGxvdywgd2Ugd2lsbCBiZSB1c2luZyBSV0EgaW4gb3JkZXIgdG8gcmVmZXIgdG8gdGhlIGFzc2V0cyB0aGF0IGEgYmFuayBtdXN0IGhhdmUgdG8gY29tcGx5IHdpdGggdGhlaXIgcmlzayBwcm9maWxlIGFuZCBtaW5pbWl6ZSB0aGVpciByaXNrIG9mIGluc29sdmVuY3ksIHdpdGhpbiB0aGVpciBkZXNpcmVkIGxpbWl0cyBhbmQgb2JqZWN0aXZlcy4gDQoNCg0KIyMjIyBCYXNlbCBJSUkNCg0KQmFzZWwgSUlJIGlzIGFuIGludGVybmF0aW9uYWwgcmVndWxhdGlvbiBkZXNpZ25lZCB0byBhc3N1cmUgdGhlIGJhbmtpbmcgc3lzdGVtJ3Mgc3RhYmlsaXR5IGJ5IHN0YW5kYXJkaXppbmcgdGhlIG1pbmltdW0gY2FwaXRhbCByZXNlcnZlIHJlcXVpcmVtZW50cy4gDQpUaGlzIHJlcXVpcmVtZW50cyBhcmUgZGl2aWRlZCBpbiBjb21tb24gZXF1aXR5IHRpZXJzICgxIGFuZCAyKSwgd2hpY2ggc2hhbGwgYWRkIHRvIGEgbWluaW11bSBvZiA4JS4gVGhpcyA4JSBoYXMgc3RheWVkIHRoZSBzYW1lIHNpbmNlIHRoZSBCYXNlbCBJIHJlZ3VsYXRpb24uIEhvd2V2ZXIsIHRoZXJlIGhhcyBiZWVuIGFuIGFkZGl0aW9uIGluIHRoaXMgc3lzdGVtIHdpdGggdGhlIGltcGxlbWVudGF0aW9uIG9mIGJ1ZmZlcnMsIHdoaWNoIGludHJvZHVjZSBuZXcgcmVxdWlyZW1lbnRzIGZvciBiYW5rczogQ2FwaXRhbCBDb25zZXJ2YXRpb24gQnVmZmVyIChDQ0IsIDIuNSUpLCBDb3VudGVyY3ljbGljYWwgQ2FwaXRhbCBCdWZmZXIgKENDeUIsIDAgdG8gMi41JSksIEdsb2JhbCBTeXN0ZW1hdGljYWxseSBJbXBvcnRhbnQgQmFuayAoRy1TSUIsIDEgdG8gMy41JSBvZiBSV0EpLg0KT3RoZXIgcmVndWxhdGlvbnMgaW4gTGV2ZXJhZ2UgYW5kIExpcXVpZGl0eSBoYXZlIGFsc28gYmVlbiBpbnRyb2R1Y2VkLCBhbHRob3VnaCB3ZSB3aWxsIG5vdCBkaXZlIGludG8gdGhvc2UuIA0KDQoNCiMjIyBDb21wbGV0ZSBBbmFseXNpcyBvZiBDYXBpdGFsIFJlcXVpcmVtZW50cyBhbmQgQ29tcGFyaXNvbg0KDQpGb3IgdGhpcyBhbmFseXNpcywgd2UgaGF2ZSBvYnRhaW5lZCB0aGUgMTAtayBmaWxpbmcgb2YgQmFuayBvZiBBbWVyaWNhIHJlcG9ydGluZyBmb3IgMjAyMyBhbmQgdGhlIDIwLUYgZmlsaW5nIG9mIERldXRzY2hlIEJhbmsgcmVwb3J0aW5nIGZvciAyMDIzLg0KDQoNCiMjIyMgMS4gQmFuayBvZiBBbWVyaWNhIChCT0ZBKQ0KDQojIyMjIyBGcm9tIHRoZSAxMC1LIGZpbGluZywgQk9GQSdzIHJpc2std2VpZ2h0ZWQgYXNzZXRzIChSV0FzKSBhcyBvZiBEZWNlbWJlciAzMSwgMjAyMywgYXJlIGNhdGVnb3JpemVkIGFzIGZvbGxvd3M6DQoNCiAgQ3JlZGl0IFJpc2sgUldBOiAkMSwzOTUgYmlsbGlvbi4NCg0KICBNYXJrZXQgUmlzayBSV0E6ICQxMTkgYmlsbGlvbi4NCg0KICBPcGVyYXRpb25hbCBSaXNrIFJXQTogJDM1NyBiaWxsaW9uIChCT0ZBIDEwaykuDQoNCg0KIyMjIyMgVXNpbmcgdGhlIEJhc2VsIElJSSBtaW5pbXVtIGNhcGl0YWwgcmVxdWlyZW1lbnRzICg4JSksIHRoZSBjYXBpdGFsIHJlcXVpcmVtZW50cyBmb3IgQk9GQSBhcmU6DQoNCkNyZWRpdCBSaXNrIENhcGl0YWwgUmVxdWlyZW1lbnQ6ICQxMTEuNiBiaWxsaW9uLg0KDQpNYXJrZXQgUmlzayBDYXBpdGFsIFJlcXVpcmVtZW50OiAkOS41MiBiaWxsaW9uLg0KDQpPcGVyYXRpb25hbCBSaXNrIENhcGl0YWwgUmVxdWlyZW1lbnQ6ICQyOC41NiBiaWxsaW9uLg0KDQoNCiMjIyMgMi4gRGV1dHNjaGUgQmFuaw0KDQojIyMjIyBCYXNlZCBvbiB0aGUgMjAtRiBmaWxpbmcsIERldXRzY2hlIEJhbmsncyBSV0FzIGFzIG9mIERlY2VtYmVyIDMxLCAyMDIzLCBhcmU6DQoNCkNyZWRpdCBSaXNrIFJXQTog4oKsMjY1Ljc5IGJpbGxpb24uDQoNCk1hcmtldCBSaXNrIFJXQTog4oKsMjEuNTEgYmlsbGlvbi4NCg0KT3BlcmF0aW9uYWwgUmlzayBSV0E6IOKCrDU3LjE1IGJpbGxpb24gKDIwRiBEZXV0c2NoZSkuDQoNCg0KIyMjIyMgQXBwbHlpbmcgdGhlIDglIEJhc2VsIElJSSByZXF1aXJlbWVudDoNCg0KQ3JlZGl0IFJpc2sgQ2FwaXRhbCBSZXF1aXJlbWVudDog4oKsMjEuMjYgYmlsbGlvbi4NCg0KTWFya2V0IFJpc2sgQ2FwaXRhbCBSZXF1aXJlbWVudDog4oKsMS43MiBiaWxsaW9uLg0KDQpPcGVyYXRpb25hbCBSaXNrIENhcGl0YWwgUmVxdWlyZW1lbnQ6IOKCrDQuNTcgYmlsbGlvbi4NCg0KDQoNCiMjIyBDb21wYXJpc29uOiBCT0ZBIHZzLiBEZXV0c2NoZSBCYW5rDQoNCiMjIyMgMS4gQ3JlZGl0IFJpc2sgQ2FwaXRhbA0KDQpCT0ZBOiAkMTExLjYgYmlsbGlvbi4NCg0KRGV1dHNjaGUgQmFuazog4oKsMjEuMjYgYmlsbGlvbiAofiQyMi41MyBiaWxsaW9uIGFzc3VtaW5nIOKCrDEgPSAkMS4wNikuDQoNCkFuYWx5c2lzOiBCT0ZBIGhhcyBhIHNpZ25pZmljYW50bHkgaGlnaGVyIGNyZWRpdCByaXNrIGNhcGl0YWwgcmVxdWlyZW1lbnQsIHJlZmxlY3RpbmcgYSBsYXJnZXIgcG9ydGZvbGlvIG9mIGxvYW5zIGFuZCBjb3VudGVycGFydHkgZXhwb3N1cmVzLg0KDQoNCiMjIyMgMi4gTWFya2V0IFJpc2sgQ2FwaXRhbA0KDQpCT0ZBOiAkOS41MiBiaWxsaW9uLg0KDQpEZXV0c2NoZSBCYW5rOiDigqwxLjcyIGJpbGxpb24gKH4kMS44MiBiaWxsaW9uKS4NCg0KQW5hbHlzaXM6IEJPRkEncyBtYXJrZXQgcmlzayBleHBvc3VyZSBpcyBtdWNoIGxhcmdlciwgbGlrZWx5IGR1ZSB0byBleHRlbnNpdmUgdHJhZGluZyBhbmQgaW52ZXN0bWVudCBhY3Rpdml0aWVzIGluIGdsb2JhbCBtYXJrZXRzLiANCg0KDQojIyMjIDMuIE9wZXJhdGlvbmFsIFJpc2sgQ2FwaXRhbA0KDQpCT0ZBOiAkMjguNTYgYmlsbGlvbi4NCg0KRGV1dHNjaGUgQmFuazog4oKsNC41NyBiaWxsaW9uICh+JDQuODQgYmlsbGlvbikuDQoNCkFuYWx5c2lzOiBCT0ZBJ3Mgb3BlcmF0aW9uYWwgcmlzayBjYXBpdGFsIGlzIHNpZ25pZmljYW50bHkgaGlnaGVyLCBzdWdnZXN0aW5nIG1vcmUgY29tcGxleCBvcGVyYXRpb25zIG9yIGEgbGFyZ2VyIGdlb2dyYXBoaWMgcHJlc2VuY2UgcmVxdWlyaW5nIGhpZ2hlciByZXNlcnZlcy4gQXMgd2Uga25vdywgb3BlcmF0aW9uYWwgcmlzayBpbmNsdWRlcyBwZW9wbGUsIHN5c3RlbXMgYW5kIGludGVybmFsIHByb2NlZHVyZXMsIHNvIHRoZSBoaWdoZXIgdGhlIGFtb3VudCBvZiBvcGVyYXRpb25zIGFuZCB0aGUgbGFyZ2VyIGdlb2dyYXBoaWMgZXh0ZW5zaW9uLCB0aGUgcmlza2llciBhbmQgbW9yZSBkaWZmaWN1bHQgdG8gbWFuYWdlIGl0IGdldHMuIA0KDQoNCg0KIyMjIENvbmNsdXNpb246IFdoaWNoIEJhbmsgSGFzIGEgQmV0dGVyIENhcGl0YWwgQmFzZT8NCg0KQk9GQTogSGlnaGVyIG92ZXJhbGwgY2FwaXRhbCByZXF1aXJlbWVudHMgcmVmbGVjdCBpdHMgdmFzdCBvcGVyYXRpb25zLCBsYXJnZXIgYXNzZXQgYmFzZSwgYW5kIHNpZ25pZmljYW50IGdsb2JhbCBtYXJrZXQgcHJlc2VuY2UuIEhvd2V2ZXIsIHRoZSBoaWdoZXIgb3BlcmF0aW9uYWwgYW5kIG1hcmtldCByaXNrIGNhcGl0YWwgcmVxdWlyZW1lbnRzIGluZGljYXRlIGdyZWF0ZXIgcmlzayBleHBvc3VyZS4NCg0KRGV1dHNjaGUgQmFuazogUmVsYXRpdmVseSBsb3dlciBjYXBpdGFsIHJlcXVpcmVtZW50cyBhY3Jvc3MgYWxsIGNhdGVnb3JpZXMgc3VnZ2VzdCBhIHNtYWxsZXIgZ2xvYmFsIGZvb3RwcmludCBvciBsZXNzIGNvbXBsZXggb3BlcmF0aW9ucy4gSG93ZXZlciwgdGhpcyBjb3VsZCBhbHNvIHJlZmxlY3QgZGlmZmVyZW5jZXMgaW4gcmlzayBhcHBldGl0ZSBvciBvcGVyYXRpb25hbCBzY2FsZS4NCg0KQmV0dGVyIENhcGl0YWwgQmFzZTogQk9GQSBob2xkcyBhIHN0cm9uZ2VyIGNhcGl0YWwgYmFzZSBpbiBhYnNvbHV0ZSB0ZXJtcywgZ2l2ZW4gaXRzIGhpZ2hlciBjYXBpdGFsIGFsbG9jYXRpb25zLiBIb3dldmVyLCBEZXV0c2NoZSBCYW5rJ3MgbG93ZXIgcmlzayBleHBvc3VyZXMgbWF5IHRyYW5zbGF0ZSBpbnRvIGEgbW9yZSBlZmZpY2llbnQgY2FwaXRhbCBzdHJ1Y3R1cmUuIFRoZSBjaG9pY2UgZGVwZW5kcyBvbiB3aGV0aGVyIG9uZSBwcmlvcml0aXplcyBhYnNvbHV0ZSBzdHJlbmd0aCAoQk9GQSkgb3IgcmVsYXRpdmUgZWZmaWNpZW5jeSAoRGV1dHNjaGUgQmFuaykuDQo=
Comments
Previously, we had only obtained the difference in the futures contract price and the return obtained in the duration of the school term. Now, we have obtained the annualized return, which depicts the average rate of return per year. We annualize our returns to better compare them with other possible studied returns, as returns are usually presented as per year.