Piotr Staszkiewicz
Z2024
Team Members: 3
Author 1 (L1,L2,L8,L9,L11,L12),
Author 2 (L2,L4,L5,L6,L9,L10),
Author 3 (L3,L7,L10)
Statements:
Author’s statement for non-infringement of others’ copyrights: We
confirm that the work of our group project is an original creation that
does not knowingly infringe upon any copyright of any third party.
Author’s statement as to how the AI tool was used during the
assignment: During our project, we utilised the use of ChatGPT. We used
ChatGPT to help us correct any errors in our code and give us a guide on
how to download data correctly to our code. We used quality control
measures including cross-referencing data with what was available on
edgar sec and FRED. We as the authors are fully responsible for the
context.
Authors’ statements on the use of the task under a public access
license: The data we accessed and downloaded from edgar sec and FRED was
public domain data which we are permitted to use in our project under a
public access license.
About Authors:
Author 1: Seonggyu Jeon, South Korea
Author 2: Kristella Wong Kah Hing,
Singapore
Author 3: Charles Maddison , Great
Britain
________________________________________________________
L1 Intro: Basic parameters of the market
For this section, we will assume the school term to be our beginning
and end term.
Meaning that the Beginning of Term (BoT) is May 01,2024 and the End
of Term (EoT) will be September 30, 2024.
And that the first settlement beyond the term will be in the month of
October.
# Create an empty data frame with separate columns dedicated for BoT and EoT
table_data <- data.frame(Category = character(),
BoT = numeric(),
EoT = numeric(),
stringsAsFactors = FALSE)
# Function to add rows to the table
add_row <- function(category, BoT_value, EoT_value)
{table_data <<-rbind(table_data, data.frame(Category = category,
BoT = BoT_value,
EoT = EoT_value))}
# Populate the table with relevant data
# Stock market index information (Data from Yahoo Finance)
add_row("S&P 500 (stock) index level:", 5018.39, 5762.48)
add_row("Nasdaq Composite (stock) index level:", 15605.48, 18189.17)
# Interest rate information (Data from Federal Reserve)
add_row("Prime rate:", 8.25, 8.00)
add_row("Federal funds rate:", 5.33, 4.83)
add_row("Commercial paper rate (90 days):", 5.37, 4.64)
add_row("Certificate of deposit rate (3-month):", 5.28, 4.68)
add_row("Treasury bill rate (13 weeks):", 5.25, 4.72)
add_row("Treasury bill rate (26 weeks):", 5.17, 4.23)
# Bond yield information (Data from Federal Reserve Bank and S&P Global)
add_row("Treasury long-term bond yield:", 4.64, 3.78)
add_row("Corporate (Master) bond yield:", 5.25, 4.37)
add_row("High-yield corporate bond yield:", 3.81, 4.68)
add_row("Tax-exempt (7–12-year) bond yield:", 159.19, 136.83)
# View the final table
print(table_data)
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.
For this section we have decided to select the New York Stock
Exchange (NYSE) and Nasdaq with stocks from Chevron Corporation (CVX)
and Apple Inc. (AAPL) respectively.
#Search for Chevron Corporation (CVX) stock
# Install the packages if not already installed
install.packages("quantmod")
Installing package into ‘/cloud/lib/x86_64-pc-linux-gnu-library/4.4’
(as ‘lib’ is unspecified)
trying URL 'http://rspm/default/__linux__/focal/latest/src/contrib/quantmod_0.4.26.tar.gz'
Content type 'application/x-gzip' length 155782 bytes (152 KB)
==================================================
downloaded 152 KB
* installing *source* package ‘quantmod’ ...
** package ‘quantmod’ successfully unpacked and MD5 sums checked
** using staged installation
** R
** demo
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (quantmod)
The downloaded source packages are in
‘/tmp/RtmpoJPRZy/downloaded_packages’
install.packages('finreportr')
Installing package into ‘/cloud/lib/x86_64-pc-linux-gnu-library/4.4’
(as ‘lib’ is unspecified)
trying URL 'http://rspm/default/__linux__/focal/latest/src/contrib/finreportr_1.0.4.tar.gz'
Content type 'application/x-gzip' length 27598 bytes (26 KB)
==================================================
downloaded 26 KB
* installing *source* package ‘finreportr’ ...
** package ‘finreportr’ successfully unpacked and MD5 sums checked
** using staged installation
** R
** data
*** moving datasets to lazyload DB
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** installing vignettes
** testing if installed package can be loaded from temporary location
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (finreportr)
The downloaded source packages are in
‘/tmp/RtmpoJPRZy/downloaded_packages’
install.packages('edgar')
Installing package into ‘/cloud/lib/x86_64-pc-linux-gnu-library/4.4’
(as ‘lib’ is unspecified)
trying URL 'http://rspm/default/__linux__/focal/latest/src/contrib/edgar_2.0.7.tar.gz'
Content type 'application/x-gzip' length 386237 bytes (377 KB)
==================================================
downloaded 377 KB
* installing *source* package ‘edgar’ ...
** package ‘edgar’ successfully unpacked and MD5 sums checked
** using staged installation
** R
** data
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (edgar)
The downloaded source packages are in
‘/tmp/RtmpoJPRZy/downloaded_packages’
install.packages('XBRL')
Installing package into ‘/cloud/lib/x86_64-pc-linux-gnu-library/4.4’
(as ‘lib’ is unspecified)
trying URL 'http://rspm/default/__linux__/focal/latest/src/contrib/XBRL_0.99.19.1.tar.gz'
Content type 'application/x-gzip' length 49435 bytes (48 KB)
==================================================
downloaded 48 KB
* installing *source* package ‘XBRL’ ...
** package ‘XBRL’ successfully unpacked and MD5 sums checked
** using staged installation
checking for xml2-config... /usr/bin/xml2-config
xml2 version 2.9.10 found!
configure: creating ./config.status
config.status: creating src/Makevars
** libs
using C compiler: ‘gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0’
using C++ compiler: ‘g++ (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0’
gcc -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/include/libxml2 -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/Rcpp/include' -I/usr/local/include -fpic -g -O2 -c registerDynamicSymbol.c -o registerDynamicSymbol.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/include/libxml2 -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/Rcpp/include' -I/usr/local/include -fpic -g -O2 -c xbrlFree.cpp -o xbrlFree.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/include/libxml2 -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/Rcpp/include' -I/usr/local/include -fpic -g -O2 -c xbrlGetImportNames.cpp -o xbrlGetImportNames.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/include/libxml2 -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/Rcpp/include' -I/usr/local/include -fpic -g -O2 -c xbrlGetLinkbaseNames.cpp -o xbrlGetLinkbaseNames.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/include/libxml2 -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/Rcpp/include' -I/usr/local/include -fpic -g -O2 -c xbrlGetSchemaName.cpp -o xbrlGetSchemaName.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/include/libxml2 -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/Rcpp/include' -I/usr/local/include -fpic -g -O2 -c xbrlParse.cpp -o xbrlParse.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/include/libxml2 -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/Rcpp/include' -I/usr/local/include -fpic -g -O2 -c xbrlProcessArcs.cpp -o xbrlProcessArcs.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/include/libxml2 -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/Rcpp/include' -I/usr/local/include -fpic -g -O2 -c xbrlProcessContexts.cpp -o xbrlProcessContexts.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/include/libxml2 -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/Rcpp/include' -I/usr/local/include -fpic -g -O2 -c xbrlProcessElements.cpp -o xbrlProcessElements.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/include/libxml2 -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/Rcpp/include' -I/usr/local/include -fpic -g -O2 -c xbrlProcessFacts.cpp -o xbrlProcessFacts.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/include/libxml2 -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/Rcpp/include' -I/usr/local/include -fpic -g -O2 -c xbrlProcessFootnotes.cpp -o xbrlProcessFootnotes.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/include/libxml2 -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/Rcpp/include' -I/usr/local/include -fpic -g -O2 -c xbrlProcessLabels.cpp -o xbrlProcessLabels.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/include/libxml2 -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/Rcpp/include' -I/usr/local/include -fpic -g -O2 -c xbrlProcessRoles.cpp -o xbrlProcessRoles.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/include/libxml2 -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/Rcpp/include' -I/usr/local/include -fpic -g -O2 -c xbrlProcessUnits.cpp -o xbrlProcessUnits.o
g++ -std=gnu++17 -shared -L/opt/R/4.4.2/lib/R/lib -L/usr/local/lib -o XBRL.so registerDynamicSymbol.o xbrlFree.o xbrlGetImportNames.o xbrlGetLinkbaseNames.o xbrlGetSchemaName.o xbrlParse.o xbrlProcessArcs.o xbrlProcessContexts.o xbrlProcessElements.o xbrlProcessFacts.o xbrlProcessFootnotes.o xbrlProcessLabels.o xbrlProcessRoles.o xbrlProcessUnits.o -lxml2 -L/opt/R/4.4.2/lib/R/lib -lR
installing to /cloud/lib/x86_64-pc-linux-gnu-library/4.4/00LOCK-XBRL/00new/XBRL/libs
** R
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
** checking absolute paths in shared objects and dynamic libraries
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (XBRL)
The downloaded source packages are in
‘/tmp/RtmpoJPRZy/downloaded_packages’
install.packages('dplyr')
Installing package into ‘/cloud/lib/x86_64-pc-linux-gnu-library/4.4’
(as ‘lib’ is unspecified)
trying URL 'http://rspm/default/__linux__/focal/latest/src/contrib/dplyr_1.1.4.tar.gz'
Content type 'application/x-gzip' length 1206177 bytes (1.2 MB)
==================================================
downloaded 1.2 MB
* installing *source* package ‘dplyr’ ...
** package ‘dplyr’ successfully unpacked and MD5 sums checked
** using staged installation
** libs
using C++ compiler: ‘g++ (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0’
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c chop.cpp -o chop.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c filter.cpp -o filter.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c funs.cpp -o funs.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c group_by.cpp -o group_by.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c group_data.cpp -o group_data.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c imports.cpp -o imports.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c init.cpp -o init.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c mask.cpp -o mask.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c mutate.cpp -o mutate.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c reconstruct.cpp -o reconstruct.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c slice.cpp -o slice.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c summarise.cpp -o summarise.o
g++ -std=gnu++17 -shared -L/opt/R/4.4.2/lib/R/lib -L/usr/local/lib -o dplyr.so chop.o filter.o funs.o group_by.o group_data.o imports.o init.o mask.o mutate.o reconstruct.o slice.o summarise.o -L/opt/R/4.4.2/lib/R/lib -lR
installing to /cloud/lib/x86_64-pc-linux-gnu-library/4.4/00LOCK-dplyr/00new/dplyr/libs
** R
** data
*** moving datasets to lazyload DB
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
*** copying figures
** building package indices
** installing vignettes
** testing if installed package can be loaded from temporary location
** checking absolute paths in shared objects and dynamic libraries
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (dplyr)
The downloaded source packages are in
‘/tmp/RtmpoJPRZy/downloaded_packages’
library(quantmod)
Loading required package: xts
Loading required package: zoo
Attaching package: ‘zoo’
The following objects are masked from ‘package:base’:
as.Date, as.Date.numeric
Loading required package: TTR
Registered S3 method overwritten by 'quantmod':
method from
as.zoo.data.frame zoo
library(finreportr)
library(edgar)
library(XBRL)
library(dplyr)
######################### Warning from 'xts' package ##########################
# #
# The dplyr lag() function breaks how base R's lag() function is supposed to #
# work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or #
# source() into this session won't work correctly. #
# #
# Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
# conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop #
# dplyr from breaking base R's lag() function. #
# #
# Code in packages is not affected. It's protected by R's namespace mechanism #
# Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning. #
# #
###############################################################################
Attaching package: ‘dplyr’
The following object is masked _by_ ‘.GlobalEnv’:
add_row
The following objects are masked from ‘package:xts’:
first, last
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
# Download Chevron Corporation (CVX) data
getSymbols("CVX", from = "2000-01-01")
[1] "CVX"
# View the first few rows of the data
head(CVX)
CVX.Open CVX.High CVX.Low CVX.Close CVX.Volume CVX.Adjusted
2000-01-03 42.93750 42.93750 41.28125 41.81250 4387600 16.61121
2000-01-04 41.46875 42.06250 41.25000 41.81250 3702400 16.61121
2000-01-05 41.53125 43.28125 41.53125 42.56250 5567600 16.90917
2000-01-06 42.65625 44.59375 42.65625 44.37500 4353400 17.62923
2000-01-07 45.00000 45.43750 44.50000 45.15625 4487400 17.93961
2000-01-10 45.03125 45.03125 43.84375 43.93750 2104800 17.45543
# Specify the date of interest (BoT)
date_of_interest1 <- "2024-05-01"
# Specify the date of interest (EoT)
date_of_interest2 <- "2024-09-30"
# Extract the adjusted closing price for the NYSE index on that date (BoT)
nyse_price_1 <- CVX[date_of_interest1, "CVX.Adjusted"]
print(nyse_price_1)
CVX.Adjusted
2024-05-01 154.7069
# Extract the adjusted closing price for the NYSE index on that date (EoT)
nyse_price_2 <- CVX[date_of_interest2, "CVX.Adjusted"]
print(nyse_price_2)
CVX.Adjusted
2024-09-30 145.7829
The price of Chevron Corporation Stock is 154.7069 and 145.7829 for
BoT and EoT respectively.
# Find the dividend for CVX:
symbol <- "CVX"
dividends <- getDividends(symbol, from = "2020-01-01", to = "2024-12-31")
# View the first few rows of dividend data
head(dividends)
CVX.div
2020-02-14 1.29
2020-05-18 1.29
2020-08-18 1.29
2020-11-17 1.29
2021-02-16 1.29
2021-05-18 1.34
# Extract dividend data for specific dates
dates_of_interest <- as.Date(c("2024-05-01", "2024-09-30"))
dividend_on_dates <- dividends[dates_of_interest]
print(dividend_on_dates)
CVX.div
# Since there is no dividend for the exact point in time, we will get the one that is closest!
closest_dividends <- sapply(dates_of_interest, function(date) {
closest_date <- index(dividends)[which.max(index(dividends) <= date)]
dividends[closest_date]})
names(closest_dividends) <- dates_of_interest
print(closest_dividends)
2024-05-01 2024-09-30
1.29 1.29
The Dividends are both 1.29.
#Search for Apple Inc. (AAPL) stock
# Download Apple Inc. (AAPL) data
getSymbols("AAPL", from = "2000-01-01")
[1] "AAPL"
# View the first few rows of the data
head(AAPL)
AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume AAPL.Adjusted
2000-01-03 0.936384 1.004464 0.907924 0.999442 535796800 0.8430765
2000-01-04 0.966518 0.987723 0.903460 0.915179 512377600 0.7719967
2000-01-05 0.926339 0.987165 0.919643 0.928571 778321600 0.7832934
2000-01-06 0.947545 0.955357 0.848214 0.848214 767972800 0.7155085
2000-01-07 0.861607 0.901786 0.852679 0.888393 460734400 0.7494013
2000-01-10 0.910714 0.912946 0.845982 0.872768 505064000 0.7362211
# Specify the date of interest (BoT)
date_of_interest1 <- "2024-05-01"
# Specify the date of interest (EoT)
date_of_interest2 <- "2024-09-30"
# Extract the adjusted closing price for the NYSE index on that date (BoT)
nasdaq_price_1 <- AAPL[date_of_interest1, "AAPL.Adjusted"]
print(nasdaq_price_1)
AAPL.Adjusted
2024-05-01 168.6896
# Extract the adjusted closing price for the NYSE index on that date (EoT)
nasdaq_price_2 <- AAPL[date_of_interest2, "AAPL.Adjusted"]
print(nasdaq_price_2)
AAPL.Adjusted
2024-09-30 232.7439
The price of Apple Inc. Stock is 168.6896 and 232.7439 for BoT and
EoT respectively.
# Find the dividend for AAPL:
symbol <- "AAPL"
dividends <- getDividends(symbol, from = "2020-01-01", to = "2024-12-31")
# View the first few rows of dividend data
head(dividends)
AAPL.div
2020-02-07 0.1925
2020-05-08 0.2050
2020-08-07 0.2050
2020-11-06 0.2050
2021-02-05 0.2050
2021-05-07 0.2200
# Extract dividend data for specific dates
dates_of_interest <- as.Date(c("2024-05-01", "2024-09-30"))
dividend_on_dates <- dividends[dates_of_interest]
print(dividend_on_dates)
AAPL.div
# Since there is no dividend for the exact point in time, we will get the one that is closest!
closest_dividends <- sapply(dates_of_interest, function(date) {
closest_date <- index(dividends)[which.max(index(dividends) <= date)]
dividends[closest_date]})
names(closest_dividends) <- dates_of_interest
print(closest_dividends)
2024-05-01 2024-09-30
0.1925 0.1925
The Dividends are both 0.1925.
# Create an empty data frame with separate columns dedicated for BoT and EoT
table_data <- data.frame(Description = character(),
BoT = numeric(),
EoT = numeric(),
stringsAsFactors = FALSE)
# Function to add rows to the table
add_row <- function(category, BoT_value, EoT_value)
{table_data <<-rbind(table_data, data.frame(Category = category,
BoT = BoT_value,
EoT = EoT_value))}
# Populate the table with relevant data
# Stock market information
add_row("New York Stock Exchange: Stock price: CVX", 154.7069, 145.7829)
add_row("Chevron Corporation (CVX) Dividend:", 1.29, 1.29)
add_row("Nasdaq Market: Stock price:AAPL", 168.6896, 232.7439)
add_row("Apple Inc. (AAPL) Dividend:", 0.1925, 0.1925)
# View the final table
print(table_data)
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):
# Create an empty data frame with separate columns dedicated for BoT and EoT
table_data <- data.frame(Description = character(),
BoT = numeric(),
EoT = numeric(),
stringsAsFactors = FALSE)
# Function to add rows to the table
add_row <- function(category, BoT_value, EoT_value)
{table_data <<-rbind(table_data, data.frame(Category = category,
BoT = BoT_value,
EoT = EoT_value))}
# Populate the table with relevant data
# Market information
add_row("Treasury bond futures:", 115.03, 124.19)
add_row("S&P 500 index futures:", 5158.00, 5814.25)
add_row("Nasdaq Market: Stock price:", 17868.50, 20261.25)
add_row("British pound futures:", 1.2549, 1.3374)
# View the final table
print(table_data)
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):
We strongly belive that Apple Inc. (AAPL) stock will increase by
looking at the continuous increase in share prices, thus here’s a
selected call option we have decided:
Name of Firm: Apple Inc. (AAPL)
Expiration Month: December 2024
Strike Price: $230
# Create an empty data frame with separate columns dedicated for BoT and EoT
table_data <- data.frame(Description = character(),
BoT = numeric(),
EoT = numeric(),
stringsAsFactors = FALSE)
# Function to add rows to the table
add_row <- function(category, BoT_value, EoT_value)
{table_data <<-rbind(table_data, data.frame(Category = category,
BoT = BoT_value,
EoT = EoT_value))}
# Populate the table with relevant data
# Stock market information
add_row("Stock price:", 168.6896, 232.7439)
add_row("Option premium", NA, 8.05)
print(table_data)
Explanation for Strike price and call option selection: We chose
Apple Inc. (AAPL) as the call option for a firm whose stock price is
expected to rise. This is because Apple has strong market presence,
consistent growth, and solid financial foundation. It is important to
well-establish the strike price since it determines how much the option
premium will cost and the likelihood of it becoming profitable. With
Apple’s stock price at $168.69 at the beginning of the term (BoT) and
projected to reach $232.74 by the end of the term (EoT), selecting a
strike price slightly above the BoT price, such as $230 or $235, offers
a good balance.
In a call option if the strike price is too lower the actual price,
the premium increases significantly. This is because higher strike price
has a lower probability of expiring in the money. Also, the option
premium encompasses the intrinsic value and time value. And, if there is
a bigger difference between Stock price and Strike Price, the intrinsic
value increases. (When the Strike price < Stock price). Thus, having
a $230 strike price keeps the premium cost manageable while maintaining
a strong chance that the option will end in the money (ITM) by the end
of the term.
For context, a call option becomes in the money when the stock price
exceeds the strike price. With Apple’s stock projected to hit $232.74,
choosing a strike price of $230 would generate an intrinsic value of:
Stock Price at EoT − Strike Price = 232.74 − 230 = $2.74
Also, the price paid to acquire the premium, plays a critical role as
well since for example, if stock is at 232.74 and the strike price is
$230, the premium could be around 10 (By approximating from the current
premium for the respective strike price= 8.05). If the stock ends at
$250, the payoff would be 250-230-10 = $10 in profit per share.
We were not able to find the value of option premium between our
assumed term so we made assumptions based on the first expiration month
from now. Meaning we assumed the price of premium for options that
expire in December as if they would expire in October.
Use an options quotations table to select a put option on a firm
where you expect the stock price to decrease (select the option with the
first expiration month beyond the end of the school term):
Name of Firm: Chevron Corporation (CVX)
Expiration Month: December 2024
Strike Price: $150
table_data <- data.frame(Description = character(),
BoT = numeric(),
EoT = numeric(),
stringsAsFactors = FALSE)
add_row <- function(category, BoT_value, EoT_value)
{table_data <<-rbind(table_data, data.frame(Category = category,
BoT = BoT_value,
EoT = EoT_value))}
# Populate the table with relevant data
add_row("Stock price:", 154.7069, 145.7829)
add_row("Option premium", NA, 10.32)
print(table_data)
Explanation for Strike price and put option selection: We chose
Chevron Corporation (CVX) as the firm for the put option due to its
declining stock price trend, reflected in the beginning of term (BoT)
price of $154.71 and end of term (EoT) price of $145.78. Reverse from
the call option, the holder of the put option profit from the decline in
share price. The strike price is also important here as it determines
the cost of the premium and the potential profitability. For Chevron,
selecting a strike price of $150.00 offers a good balance between
affordability and the likelihood of the option being in the money (ITM)
by expiration. It is certainly better than the premium for strike prices
at $140 since the premium nearly doubles at the respective price.
For a put option (and even for call option), the closer the strike
price is to the current stock price, the higher the premium is due to
increased intrinsic value and time value. The calculation for intrinsic
value and payoff is reverse from the call option.
We also made the same assumption as in the previous question
regarding EoT.
Due to the initial assumption of the option expiring right after the
end of term, we have not considered how time remaining of options could
affect the strike price and premium. Furthermore, for put options, a
higher risk free-interest can also reduce their value. This occurs
because the present value of the strike price decreases as interest rate
rises which in turn reduces the intrinsic value. In the perspective of
an investor, they might prefer to allocate fund into higher yielding
alternatives because higher interest rates makes risk-free investments
more appealing. Which in turn can reduce the demand for these put
options.
So in reality, there would have been more factors that needed to be
kept in mind while answeing this question.
Use a currency exchange rate table to record exchange rates:
# Create an empty data frame with separate columns dedicated for BoT and EoT
table_data <- data.frame(Description = character(),
BoT = numeric(),
EoT = numeric(),
stringsAsFactors = FALSE)
# Function to add rows to the table
add_row <- function(category, BoT_value, EoT_value)
{table_data <<-rbind(table_data, data.frame(Category = category,
BoT = BoT_value,
EoT = EoT_value))}
# Populate the table with relevant data
# Market information
add_row("Exchange rate of the British pound (in $):", 1.2525 , 1.3370 )
add_row("Exchange rate of the Japanese yen (in $):", 0.006472, 0.006961)
add_row("Exchange rate of the Mexican peso (in $):", 0.0588, 0.0506)
# View the final table
print(table_data)
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):
Currency: British Pound (GBP)
Expiration month: December
Strike price: 1.30
table_data <- data.frame(Description = character(),
BoT = numeric(),
EoT = numeric(),
stringsAsFactors = FALSE)
add_row <- function(category, BoT_value, EoT_value)
{table_data <<-rbind(table_data, data.frame(Category = category,
BoT = BoT_value,
EoT = EoT_value))}
# Populate the table with relevant data
add_row("Currency’s existing value:", 1.2525 , 1.3370)
add_row("Option premium", NA, 0.005)
# It is quite hard to know the option premium for a strike price of 1.30 since the pound has depreciated to 1.27 and the premium is 0.005 at at market price.
print(table_data)
Explanation for Strike price and put option selection: We believed
that a call option for the British pond was the most logical choice for
a call option, since it would be profitable to capitalize on the pound’s
appreciation. Infact, out of the three options it signaled the strongest
market confidence as well as it’s strength compared to other currencies.
Similar to the previous questions, a strike price of 1.30 from a
projected increase from EoT at 1.337 suggests the call option would most
likely end in the money.
However, if we assume that the end of term is December, then due to
the slight depreciation of the pound, keeping the strike price at 1.3
will not be ideal.
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):
Currency:Mexican peso (MXN)
Expiration month: December
Strike price: 0.051
table_data <- data.frame(Description = character(),
BoT = numeric(),
EoT = numeric(),
stringsAsFactors = FALSE)
add_row <- function(category, BoT_value, EoT_value)
{table_data <<-rbind(table_data, data.frame(Category = category,
BoT = BoT_value,
EoT = EoT_value))}
# Populate the table with relevant data
add_row("Currency’s existing value:", 0.0588, 0.0506)
add_row("Option premium", NA, 0.0018)
print(table_data)
Explanation for Strike price and put option selection: Opposite to
the British Pound the Mexican Peso shows a clear weakening trend against
the U.S. Dollar. As a result, it is an ideal candidate for a put
option.BoT rate of 0.0588 is close to our chosen strike price of 0.0580
in order to ensure a reasonable premium cost without being exposed to
much risk. The exchange rate is projected to fall below 0.0506, which is
well below the strike price, meaning that the option is likely to end in
the money. Which is again, because the further the spot price falls
below the strike price, the larger the intrinsic value and the higher
the profit.
The option premium values were used from the assumption that the
option expired in December even though we were calculating for the
School terms.
________________________________________________________
L2 Financial Markets Microstructure
Compare your national country local exchange index with US or
London.
Install the necessary packages
Let’s compare the S&P 500 and Singapore Exchange Index.
# Download historical data for S&P 500 and Singapore Exchange Index
getSymbols("^GSPC", src = "yahoo") # S&P 500
[1] "GSPC"
getSymbols("^STI", src = "yahoo") # Straits Times Index (SGX)
Warning: ^STI 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] "STI"
The data from 1 January 2010 to 1 January 2023 will be trimmed and
cleaned.
# Fill in NA with an approximation data
STI <- na.approx(STI)
# Fill in NA with an approximation data
STI <- na.approx(STI)
# Trim data for the comparison period
start_date <- "2010-01-01"
end_date <- "2023-01-01"
GSPC <- subset(GSPC, index(GSPC) >= start_date & index(GSPC) <= end_date)
STI <- subset(STI, index(STI) >= start_date & index(STI) <= end_date)
# Check if the data is well trimmed
print(GSPC[rownames(GSPC) >= "2010-01-01" & rownames(GSPC) <= "2010-01-02", ])
GSPC.Open GSPC.High GSPC.Low GSPC.Close GSPC.Volume GSPC.Adjusted
print(STI[rownames(STI) >= "2010-01-01" & rownames(STI) <= "2010-01-02", ])
STI.Open STI.High STI.Low STI.Close STI.Volume STI.Adjusted
# Merge the datasets
aligned_data <- merge(GSPC, STI)
# Remove missing values
cleaned_data <- na.omit(aligned_data)
After data is cleanned and trimmed, we can now compare the statistics
between the S&P 500 and Singapore Exchange Index
# Calculate statistics for S&P 500
nasdaq_stats <- c(mean(GSPC[, 4], na.rm = TRUE),
median(GSPC[, 4], na.rm = TRUE),
sd(GSPC[, 4], na.rm = TRUE))
# Calculate statistics for Singapore Exchange (SGX)
sgx_stats <- c(mean(STI[, 4], na.rm = TRUE),
median(STI[, 4], na.rm = TRUE),
sd(STI[, 4], na.rm = TRUE))
# Calculate Coefficient of Variation for S&P 500 and SGX
cv_nasdaq <- nasdaq_stats[3] / nasdaq_stats[1] * 100
cv_sgx <- sgx_stats[3] / sgx_stats[1] * 100
# Add Coefficient of Variation to statistics
nasdaq_stats <- c(nasdaq_stats, cv_nasdaq)
sgx_stats <- c(sgx_stats, cv_sgx)
# Combine statistics into a single data frame
stats_comparison <- rbind(nasdaq_stats, sgx_stats)
# Name the columns
colnames(stats_comparison) <- c("Mean", "Median", "Standard Deviation", "Coefficient of Variation")
# Name the rows
rownames(stats_comparison) <- c("S&P 500", "Singapore Exchange (SGX)")
# Print the rounded result
print(round(stats_comparison, 2))
Mean Median Standard Deviation Coefficient of Variation
S&P 500 2401.49 2125.03 988.94 41.18
Singapore Exchange (SGX) 3093.40 3139.98 236.20 7.64
As the S&P 500 has a coefficient of variation that is almost 4
times that of the SGX, we can conclude that the S&P 500 is more
volatile and riskier than the SGX. A higher coefficient of variation
reflects greater uncertainty in the S&P 500’s performance, meaning
that its returns are more likely to deviate from its average value.
Investors in the S&P 500 can expect larger deviations from the mean,
either in the form of large gains or significant losses. SGX’s lower
coefficient of variation implies greater stability and predictability in
its returns. It is less volatile, making it a safer choice for investors
who prioritize consistent performance and are risk-averse. Investors
should assess their risk tolerance when choosing between these indices.
If an investor prefers higher potential returns and is comfortable with
more volatility, the S&P 500 might be more appealing. Conversely, if
an investor prefers stability and lower volatility, the SGX might be a
better option.
Let us compare the cumulative returns between the S&P 500 and SGX
from 2010 to 2023.
# Check the first few rows to verify data
head(GSPC)
GSPC.Open GSPC.High GSPC.Low GSPC.Close GSPC.Volume GSPC.Adjusted
2010-01-04 1116.56 1133.87 1116.56 1132.99 3991400000 1132.99
2010-01-05 1132.66 1136.63 1129.66 1136.52 2491020000 1136.52
2010-01-06 1135.71 1139.19 1133.95 1137.14 4972660000 1137.14
2010-01-07 1136.27 1142.46 1131.32 1141.69 5270680000 1141.69
2010-01-08 1140.52 1145.39 1136.22 1144.98 4389590000 1144.98
2010-01-11 1145.96 1149.74 1142.02 1146.98 4255780000 1146.98
head(STI)
STI.Open STI.High STI.Low STI.Close STI.Volume STI.Adjusted
2010-01-04 2897.62 2897.62 2886.43 2894.55 0 2894.55
2010-01-05 2894.55 2923.91 2894.55 2920.28 0 2920.28
2010-01-06 2920.28 2937.98 2919.74 2930.49 0 2930.49
2010-01-07 2930.49 2945.06 2901.24 2913.25 0 2913.25
2010-01-08 2913.25 2932.72 2909.41 2922.76 0 2922.76
2010-01-11 2922.76 2947.08 2922.76 2933.53 0 2933.53
First, we calculate the daily returns of S&P500 and SGX.
# Calculate daily returns for both indices
GSPC_returns <- dailyReturn(GSPC)
STI_returns <- dailyReturn(STI)
Next, we calculate the cumulative returns of S&P500 and SGX.
# Calculate cumulative returns
GSPC_cumulative_returns <- cumsum(GSPC_returns)
STI_cumulative_returns <- cumsum(STI_returns)
Finally, we can compare them with a line graph.
plot(index(GSPC_cumulative_returns), GSPC_cumulative_returns, type = "l", col = "blue",
xlab = "Date", ylab = "Cumulative Returns", main = "Cumulative Returns: S&P 500 vs SGX (2010-2023)")
lines(index(STI_cumulative_returns), STI_cumulative_returns, col = "red")
legend("topleft", legend = c("S&P 500", "SGX"), col = c("blue", "red"), lty = 1)

From 2010 to 2020, the cumulative returns of the S&P 500 has
experienced significant growth. However, the cumulative returns of the
SGX have remained largely flat, showing little movement over the past
decade. As such, we can conclude that investing in the S&P 500
generates a higher return compared to the SGX.
Here, the cumulative results are important because they show how
structural differences, such as sector composition and growth engines,
affect the returns of each index in the long run. For example, the
strength of the S&P 500 index can be attributed to the economic
recovery since 2008 and the rise of tech giants such as Apple, Amazon,
and Microsoft. These sectors have driven continued growth and high
returns. On the other hand, SGX’s flat cumulative returns over the same
period generally reflect its reliance on finance, real estate, and raw
materials that have not experienced the same explosive growth as the
U.S. tech sector.
Thus, we believe that the strong gowth in the S&P 500 was driven
by strong economic recovery post-2008 financial crisis and the rise of
technology companies like Apple, Amazon, and Microsoft. On the other
hand, SGX’s performance was constrained by its sector composition, which
is dominated by financials, real estate, and commodities, sectors that
generally did not experience the same explosive growth as the U.S. tech
sector. Therefore, while the SGX provides stability and lower
volatility, it lacked the growth drivers that propelled the S&P 500
to higher returns. As such, the S&P 500 clearly outperformed the
SGX, offering higher capital appreciation and overall returns for
investors willing to accept its inherent volatility.
________________________________________________________
L3 Instrument’s overview and valuation
L3.1
We are going to find and compare the 13-week treasury bill rates at
the end of the school termm and compare to the beginning of the school
term.
library(quantmod)
getSymbols("TB3MS", src = "FRED")
[1] "TB3MS"
These are the monthly published 3-month treasury bill secondary
market rates
We will first find the monthly average for the end of term at
September 2024.
EoT_Rate <- TB3MS["2024-09-1"]
print(EoT_Rate)
TB3MS
2024-09-01 4.72
We will now find the monthly average monthly rate at the beginning of
the school term at May 2024.
BoT_Rate <- TB3MS["2024-05-1"]
print(BoT_Rate)
TB3MS
2024-05-01 5.25
Comparing the rates we see that at the end of the school term, the
interest rate is 0.53 percentage points lower than the beginning of the
school term.
L3.2
Interest rates change over time for a number of reasons:
Firstly, the federal reserve set benchmark interest rates. This is to
control inflation and to influence economic activity, with lower rates
encouraging economic participation, and higher rates attempting to
control inflation and slow down the economy.
With respect to inflation. Higher inflation causes money to lose
purchasing power, so lenders demand higher interest rates to offset the
cost.
Another reason can be global crises or economic uncertainty. Shocks
to the economy or uncertainty about the future can drop interest rates
as investors flock to safe assets such as treasury bills.
Relating to the treasury bill rates. Treasury bill short term rates
are often closely linked to interest rates as their demand is determined
by investor sentiment about the market.
________________________________________________________
L4 Efficiency of market and information
Check if on 26 October 2017 coca cola shares were hit by the adverse
information realize on the market. (assume 26 is the information release
date)
library(quantmod)
library(ggplot2)
# Download historical data for KO from 2017-10-01 to 2017-11-01
getSymbols("KO", from = "2017-10-01", to = "2017-11-01")
[1] "KO"
# Set the event date
event_date <- "2017-10-26"
# Calculate the log returns of KO Adjusted prices
KO_returns <- diff(log(KO$KO.Adjusted))
# Create the event dummy variable (1 for event date, 0 otherwise)
event_dummy <- ifelse(index(KO_returns) == event_date, 1, 0)
# Run the event study regression model (excluding the first element for lag)
event_study <- lm(KO_returns[-1] ~ event_dummy[-1])
# Display the summary of the event study model
summary(event_study)
Call:
lm(formula = KO_returns[-1] ~ event_dummy[-1])
Residuals:
Min 1Q Median 3Q Max
-0.005673 -0.003688 -0.000888 0.002982 0.008974
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.001105 0.001060 1.042 0.310
event_dummy[-1] 0.002796 0.004857 0.576 0.572
Residual standard error: 0.00474 on 19 degrees of freedom
Multiple R-squared: 0.01714, Adjusted R-squared: -0.03459
F-statistic: 0.3314 on 1 and 19 DF, p-value: 0.5716
# Set the event date (October 26, 2017)
event_date <- "2017-10-26"
# Calculate the log returns of KO Adjusted prices
KO_returns <- diff(log(KO$KO.Adjusted))
# Define the event window (-2 to +2 days around the event)
event_window <- c(-2, 2)
# Get the numeric position of the event date in the returns vector
poz <- match(as.Date(event_date), index(KO_returns))
# Define the start and end of the event window
w_beg <- poz + event_window[1]
w_end <- poz + event_window[2]
# Define the event dummy for the event window (1 for event window, 0 otherwise)
event_dummy <- rep(0, length(KO_returns)) # Initialize the dummy variable
event_dummy[w_beg:w_end] <- 1 # Set the event window to 1
# Calculate Cumulative Abnormal Returns (CAR) over the event window
CAR <- cumsum(KO_returns[-1] * event_dummy[-1])[(w_beg - 1):(w_end - 1)]
# Test for significance (t-statistic and p-value)
t_stat <- CAR[length(CAR)] / sd(CAR) / sqrt(length(CAR))
p_value <- 2 * pt(-abs(t_stat), df = length(CAR) - 1)
# Print the results
cat("Cumulative Abnormal Return:", CAR[length(CAR)], "\n")
Cumulative Abnormal Return: -0.009980466
cat("t-statistic:", t_stat, "\n")
t-statistic: -1.436364
cat("p-value:", p_value, "\n")
p-value: 0.2242493
The Cumulative Abnormal Return over the event window is negative at
-0.998%. This suggestes that Coca-Cola’s stock underperformed relative
to its expected return during this period. While this negative CAR
indicates a potential adverse market reaction to the information
released on October 26, 2017, it is essential to evaluate its
statistical significance to confirm whether the event had a meaningful
impact.
The T-statistic plays a key role here. Based under the null
hypothesis, it measures how far the observed CAR deviates from zero
relative to its standard error. A high T-statistic with the absolute
value exceeding a critical threshold (for example, 95% confidence level)
would indicate that the CAR is unlikely to have occurred by chance.
Therefore, it suggests a significant market impact. However in this
case, the T-statistic is low, and the p-value is greater than 0.05. This
means the null hypothesis cannot be rejected This implies that the
adverse information release on October 26, 2017, did not cause a
statistically significant abnormal return.
While the cumulative nature of CAR is important for assessing the
overall impact across the event window, its interpretation must be
supported by statistical significance. Without a significant
T-statistic, the observed CAR could simply reflect random market
fluctuations rather than a true reaction to the event. To sum up,
although the CAR is negative, the T-statistic shows the result is not
statistically significant. This suggests the event did not have a
measurable impact on Coca-Cola’s stock price.
________________________________________________________
L5 Financial statements and fundamental
analysis
Download to R the financial statements of Microsoft 2018,
show the code Download the necessary packages and retrieve the
annual report of Microsoft 2018
install.packages('tidyr')
Installing package into ‘/cloud/lib/x86_64-pc-linux-gnu-library/4.4’
(as ‘lib’ is unspecified)
trying URL 'http://rspm/default/__linux__/focal/latest/src/contrib/tidyr_1.3.1.tar.gz'
Content type 'application/x-gzip' length 804973 bytes (786 KB)
==================================================
downloaded 786 KB
* installing *source* package ‘tidyr’ ...
** package ‘tidyr’ successfully unpacked and MD5 sums checked
** using staged installation
** libs
using C++ compiler: ‘g++ (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0’
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/cpp11/include' -I/usr/local/include -fpic -g -O2 -c cpp11.cpp -o cpp11.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/cpp11/include' -I/usr/local/include -fpic -g -O2 -c melt.cpp -o melt.o
g++ -std=gnu++17 -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I'/cloud/lib/x86_64-pc-linux-gnu-library/4.4/cpp11/include' -I/usr/local/include -fpic -g -O2 -c simplifyPieces.cpp -o simplifyPieces.o
g++ -std=gnu++17 -shared -L/opt/R/4.4.2/lib/R/lib -L/usr/local/lib -o tidyr.so cpp11.o melt.o simplifyPieces.o -L/opt/R/4.4.2/lib/R/lib -lR
installing to /cloud/lib/x86_64-pc-linux-gnu-library/4.4/00LOCK-tidyr/00new/tidyr/libs
** R
** data
*** moving datasets to lazyload DB
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
*** copying figures
** building package indices
** installing vignettes
** testing if installed package can be loaded from temporary location
** checking absolute paths in shared objects and dynamic libraries
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (tidyr)
The downloaded source packages are in
‘/tmp/RtmpoJPRZy/downloaded_packages’
library(tidyr)
# set up the authority to Edgar
options(HTTPUserAgent = "kw137465@student.sgh.waw.pl")
# Get financial
AnnualReports(0000789019, foreign = FALSE)
Commercial bank operations
We have selected JPMorgan Chase & Co. as our commercial
bank and derived our analysis from the 10-k annual report of JPM 2023
from EDGAR to answer the following questions:
L5.1 Identify the types of deposits that the commercial bank
uses to obtain most of its funds.
The types of deposits that JPM uses to obtain most of its funds is
time deposits.
L5.2 Identify the main uses of funds by the bank.
c. Summarize any statements made by the commercial bank in its annual
report about how recent or potential regulations will affect its
performance.
The main uses of funds include securities investment and loans. The
Volcker Rule, which restricts banks from engaging in proprietary trading
is an important regulation affecting JPMorgan’s investment banking and
trading activities. JPMorgan has taken steps to ensure compliance with
the rule, which can impact its proprietary trading activities and reduce
the amount of capital it can deploy in certain trading strategies. The
rule has led to increased compliance costs and operational adjustments,
as JPMorgan must ensure that it does not engage in prohibited
activities.
L5.3 Does it appear that the bank is attempting to enter the
securities industry by offering securities services? If so, explain
how.
Yes. JPMorgan Chase has a substantial presence in securities trading.
It engages in market-making, proprietary trading, and investment
management in various equity, fixed-income, derivatives, and foreign
exchange markets. Moreover, JPMorgan’s Investment Bank division
underwrites a wide variety of debt and equity securities. This includes
initial public offerings, debt offerings and syndicated loans.
Additionally, JPMorgan offers investment management services through its
Asset & Wealth Management division. By managing funds and
portfolios, JPMorgan actively invests in securities on behalf of its
clients, offering access to equity and fixed income markets. This
involves creating and managing securities portfolios, which directly
ties JPMorgan to the securities industry.
L5.4 Does it appear that the bank is attempting to enter the
insurance industry by offering insurance services? If so, explain
how.
Yes. JPMorgan Chase offers insurance solutions to its high-net-worth
individuals and institutional clients through its Private Banking and
Wealth Management divisions. While the bank doesn’t directly underwrite
insurance policies, it works with third-party insurers to provide a
range of life, disability, and long-term care insurance products. Also,
JPMorgan’s Commercial Banking division offers insurance brokerage
services to business clients. This includes risk management solutions
and the placement of insurance coverage with third-party insurers. By
acting as a broker and intermediary between clients and insurance
carriers, JPMorgan is involved in the distribution of insurance
products.
Commercial bank management
L5.5 Assess the bank’s balance sheet as well as any comments
in its annual report about the gap between its rate-sensitive assets and
its rate-sensitive liabilities. Does it appear that the bank has a
positive gap or a negative gap?
The bank rate-sensitive assets are deposits with banks, federal funds
sold and securities purchased under resale agreements, securities
borrowed, trading assets, available-for-sale securities,
held-to-maturity securities, investment securities, and loans. They add
up to $4,056,670. The bank rate-sensitive liabilities are
interest-bearing deposits, federal funds purchased, short-term
borrowings, trading liabilities, beneficial interests issued by
consolidated VIEs and long-term debt. They add up to $3,257,208 Since
the bank has rate-sensitive assets greater than its rate-sensitive
liabilities, it results in a positive gap of $799,462. This means that
the bank has more rate-sensitive assets than liabilities in the
short-term. When interest rates rise, the income from the bank’s assets
increases faster than the cost of its liabilities. This situation
benefits the bank in a rising interest rate environment.
L5.6 Determine the bank’s interest income as a percentage of
its total assets.
JPM interest income as a percentage of its total assets = 170,588 /
3,875,393 = 4.40%
L5.7 Determine the bank’s interest expenses as a percentage
of its total assets.
JPM interest expenses as a percentage of its total assets = 81,321 /
3,875,393 = 2.10%
L5.8 Determine the bank’s net interest margin.
JPM net interest margin = net interest income / average
interest-earning assets The earning assets in JPM are Deposits with
Banks, Federal Funds Sold and Securities Purchased under Resale
Agreements, Securities Borrowed, Trading Assets, Available-for-Sale
Securities, Held-to-Maturity Securities, Investment Securities and
Loans. Beginning earning assets = 3,872,542 Ending earning assets =
4,056,670 JPM net interest margin = ( 170,588 - 81,321 ) / (3,872,542 +
4,056,670)/2 x 100 = 2.25%
L5.9 Determine the bank’s noninterest income as a percentage
of its total assets. Determine the bank’s noninterest expenses (do not
include the addition to loan loss reserves here) as a percentage of its
total assets.
JPM non-interest income as a percentage of its total assets = 68,837
/ 3,875,393 x 100 = 1.78% JPM non-interest expenses as a percentage of
its total assets = (87,172 - 22,420) / 3,875,393 x 100 = 1.67%
L5.10 Determine the bank’s addition to loan loss reserves as
a percentage of its total assets.
JPM addition to loan loss reserves as a percentage of its total
assets = 22,420 / 3,875,393 x 100 = 0.58%
L5.11 Determine the bank’s return on assets.
JPM return on assets = 49,552 / 3,875,393 = 0.0128
L5.12 Determine the bank’s return on equity.
JPM return on equity = 49,552 / 327,878 = 0.151
L5.13 Identify the bank’s income statement items described
previously that would be affected if interest rates rise in the next
year, and explain how they would be affected.
Rate-sensitive assets such as loans, trading assets,
available-for-sale securities, and securities purchased under resale
agreements will generate higher income when interest rates rise.
Rate-sensitive liabilities such as interest-bearing deposits, federal
funds purchased, short-term borrowings, and long-term debt will also
become more expensive as interest rates increase. Since the bank’s
rate-sensitive assets are greater than its rate-sensitive liabilities, a
rise in interest rates will cause the interest income from these assets
to increase faster than the interest expense on its liabilities. Hence,
this leads to a net positive effect on the bank’s profitability.
L5.14 Identify the bank’s income statement items described
previously that would be affected if U.S. economic conditions
deteriorate, and explain how they would be affected
Rate-sensitive assets such as loans, securities, and trading assets
could see a reduction in interest income as economic conditions worsen.
Rate-sensitive liabilities such as interest-bearing deposits, federal
funds purchased, and short-term borrowings could see a decrease in
interest expense if the Federal Reserve lowers interest rates in
response to a slowing economy. The income from rate-sensitive assets
might decrease more than the reduction in interest expense from
liabilities, leading to a decline in the bank’s profitability.
Mutual funds
We have selected Fidelity Contrafund as our mutual fund and derived
our analysis from the 2024 prospectus of Fidelity Contrafund from EDGAR
to answer the following questions:
L5.15 What is the investment objective of this mutual fund?
Do you consider this mutual fund to have low risk, moderate risk, or
high risk?
The Fidelity Contrafund is a U.S. large-cap growth mutual fund.
According to its prospectus, its investment objective is to seek capital
appreciation by investing primarily in growth stocks of large companies.
The fund invests in companies that are expected to have above-average
earnings growth, particularly those that are undervalued relative to
their growth potential. We consider this mutual fund to be of moderate
risk. This fund does not invest in highly speculative stocks or
extremely volatile assets, but it is still subject to fluctuations that
can come with investing in growth stocks, especially during periods of
market volatility.
L5.16 What was the return on the mutual fund last year? What
was the average annual return over the last three years?
According to the prospectus, its return in 2023 was 39.47%. Its
average annual return over the last 3 years is 17.84%.
L5.17 What is a key economic factor that influences the
return on this mutual fund? (That is, are the fund’s returns highly
influenced by U.S. stock market conditions? By U.S. interest rates? By
foreign stock market conditions? By foreign interest
rates?)
The fund is highly influenced by the U.S. stock market conditions.
Since it focuses on investing in large-cap U.S. companies, U.S. stock
market conditions have a significant impact on the fund’s performance. A
growing US economy generally leads to higher corporate profits, which
boosts the stock prices of companies in which the fund invests.
L5.18 Must any fees be paid when buying or selling this
mutual fund?
Yes. When buying this mutual fund, a management fee (which fluctuates
based on the fund’s performance relative to a securities market index)
0f 0.39% is paid.
L5.19 What was the expense ratio for this mutual fund over
the last year? Does this ratio seem high to you?
The expense ratio is 0.39%. This ratio is low to us. In the mutual
fund industry, the average expense ratio for an actively managed equity
fund is typically around 0.60% to 1.00%. As such, a 0.39% ratio is below
average for a mutual fund fund.
Securities firms
We have selected JPMorgan Chase & Co. as our securities firm and
derived our analysis from the 10-k annual report of JPM 2023 from EDGAR
to answer the following questions:
L5.20 What are the main types of business conducted by the
securities firm?
JPMorgan operates through three main business segments - Investment
Banking, Global Markets and Asset Management. The Investment Banking
division is part of J.P. Morgan and focuses on helping clients raise
capital, manage risk, and execute strategic transactions. The Global
Markets division serves institutional investors, hedge funds,
governments, and other large entities by providing access to capital
markets and facilitating transactions. The Asset Management division
focuses on helping clients achieve their investment goals by managing
diversified portfolios across various asset classes.
L5.21 Summarize any statements made by the securities firm in
its annual report about how it may be affected by existing or potential
regulations.
According to the 2023 annual report, JPMorgan’s regulatory capital
requirements are set by the Federal Reserve for the firm as a
consolidated financial holding company and by the OCC for its principal
subsidiary, JPMorgan Chase Bank, N.A. These requirements follow the
Basel III framework, which establishes minimum capital ratios and
overall capital adequacy standards for large U.S. banks. JPMorgan uses
two approaches to calculate its Risk-Weighted Assets (RWA): the
Standardized and Advanced approaches, with capital adequacy assessed
based on the lower of the two. The firm must maintain minimum levels of
CET1 capital, Tier 1 capital, Total capital, Tier 1 leverage, and the
Supplementary Leverage Ratio (SLR). Failure to meet these capital
requirements could lead to regulatory action by the Federal Reserve.
L5.22 Describe the recent performance of the securities firm,
and explain why the performance has been favorable or
unfavorable.
In 2023, JPMogran experienced strong earnings growth. JPMorgan saw
continued growth in both net interest income and non-interest income,
benefiting from a favorable interest rate environment in the first half
of the year, which helped boost revenues from lending and investment
activities. The Federal Reserve’s interest rate hikes during 2023
positively impacted JPMorgan’s net interest income, especially in its
consumer banking and corporate lending businesses. As interest rates
increased, the bank earned more on loans and deposits, boosting
profitability. Also, JPMorgan’s capital position remained solid with a
strong CET1 ratio, which provided a cushion against economic
uncertainties. The firm’s proactive risk management strategy helped it
navigate potential market disruptions effectively.
________________________________________________________
L6 Equity
According to MorningStar, dividend per share of Microsoft are 2.30,
2.54, 2.79 for 2021, 2022 and 2023 respectively.
The stock price of Microsoft was $375.95 at the end of 2023.
We assume a required rate of return of 10%
Using the dividend discount model, estimated value of a share is
derived as follows:
Estimated value = 2.30 /(1.10) + 2.54 /(1.10)^2 + 2.79/(1.10)^3 +
375.95(1.10)^3 = $288.74
________________________________________________________
L7 Fixed income
Comparing yields among securities.
L7.1
High quality corporate bonds are AAA rated, which we will download
from FRED, and then get the yield rate for the end of the school
term.
We will use the average yield rate for the month of September
2024
getSymbols("AAA", src = "FRED")
[1] "AAA"
EoT_AAA_Rate <- AAA["2024-09-1"]
print(EoT_AAA_Rate)
AAA
2024-09-01 4.68
For September 2024, the high-quality corporate yield was 4.68%
We will now find the yield on treasury bonds. We will use the data
for a 10-year treasury yield bond.
getSymbols("DGS10", src = "FRED")
[1] "DGS10"
EoT_10year_Rate <- DGS10["2024-09-30"]
print(EoT_10year_Rate)
DGS10
2024-09-30 3.81
The yield on 10-year treasury bonds at the end of the school term is
3.81%
The difference in yield between corporate high quality bond and
treasury bonds is that the yield on corporate bonds is higher.
This difference is known as the credit spread. The credit spread
exists because corporate bonds are more likely to default, where
treasury bonds are fully supported by the government and are virtually
risk free. So, the credit spread provides higher yields in order to
attract investors.
There is also an associated liquidity risk. Treasury bonds are traded
constantly and are highly liquid, allowing them to be easily traded.
Where corporate bonds are more limited in their liquidity, meaning they
can be more difficult to trade. This also drives up the yield.
L7.2
From the previous task the yield on 10-year treasury bonds at the end
of the term is 3.81%.
We will now find the yield on long-term municipal bonds for the same
date.
Unfortunately, we were unable to access municipal yield data from
FRED, so we will analyse what generally creates differences in these
yield rates.
The difference between the yield on long-term treasury bonds and
long-term municipal bonds is due credit risk and tax advantages.
Municipal bonds are generally safe, but they still have higher risk than
treasury bonds, causing the yield to be higher to compensate for the
credit risk.
Municipal bonds have tax advantages over treasury bonds, as treasury
bonds are taxed at a federal level through capital gains tax, where
municipal bonds are not. This means investors are willing to accept a
lower yield compared to treasury bonds.
The difference between the yield rates on these types of bonds will
ultimately depend on the specific credit and liquidity risk of the
municipal bonds, and the investors tax situation.
Assessing the forecasting ability of the yield curve.
L7.3
We will download the yields for the 13-week and 26-week T-bills at
the beginning of the school term.
getSymbols("DTB3", src = "FRED")
[1] "DTB3"
BoT_13week_Rate <- DTB3["2024-05-1"]
print(BoT_13week_Rate)
DTB3
2024-05-01 5.26
The 13-week T-bill yield at the beginning of the term is 5.26%
getSymbols("DTB6", src = "FRED")
[1] "DTB6"
BoT_26week_Rate <- DTB6["2024-05-1"]
print(BoT_26week_Rate)
DTB6
2024-05-01 5.17
The 26-week T-bill yield at the beginning of the term is 5.17%
At the beginning of the school term the 26-week T-bill yield rate was
0.09 percentage points lower than the 13-week T-bill.
L7.4
The shorter-term T-bill having a higher yield rate indicates that the
yield curve is downwards sloping at the beginning of the school
term.
L7.5
Attributing the downward slope of the curve to expectations theory,
this difference indicates that the market expected lower future interest
rates.
This could be due to slowing economic growth, and the federal reserve
planning to lower interest rates to boost economic activity.
L7.6
We will download the federal funds rate to look at interest
rates.
getSymbols("FEDFUNDS", src = "FRED")
[1] "FEDFUNDS"
BoT_Interest_Rate <- FEDFUNDS["2024-05-1"]
print(BoT_Interest_Rate)
FEDFUNDS
2024-05-01 5.33
At the beginning of the term for the month of May the effective
interest rate was 5.33%.
EoT_Interest_Rate <- FEDFUNDS["2024-09-1"]
print(EoT_Interest_Rate)
FEDFUNDS
2024-09-01 5.13
At the end of the term for the month of September the effective
interest rate was 5.13%.
Over the school term, interest rates did move in that direction and
experienced a decrease in interest rates. This is in line with what the
market expected.
#Explaining shifts in the yield curve over time.
L7.7
We know at the beginning of the school term the 13-week T-bill rate
was 5.26%.
We will now find the yield on a 10-year long term treasury bond at
the same period.
getSymbols("DGS10", src = "FRED")
[1] "DGS10"
BoT_10year_Rate <- DGS10["2024-05-1"]
print(BoT_10year_Rate)
DGS10
2024-05-01 4.63
We see at the beginning of the school term the long-term treasury
bond is 4.63%.
At the beginning of the school term the 13-week T-bill yield was 0.63
percentage points higher than the long-term treasury bond.
L7.8
We know that at the end of the term the 10-year long term treasury
bond yield was 3.81%.
We will now find the 13-week T-bill yield at the end of the school
term.
getSymbols("DTB3", src = "FRED")
[1] "DTB3"
EoT_13week_Rate <- DTB3["2024-09-30"]
print(EoT_13week_Rate)
DTB3
2024-09-30 4.52
We see that at the end of the school term the 13-week T-bill yield
was 4.52%.
At the end of the school term the 13-week T-bill yield was 0.71
percentage points higher than the long-term treasury bond yield.
L7.9
Based on the previous two questions, we see that over the school term
the 13-week T-bill yield dropped from 5.26% to 4.52%, and the long-term
treasury bond yield dropped from 4.63% to 3.81%.
Since the yields in both securities fell over the school term, we
observe a downward shift in the yield curve. The long-term treasury
bonds yield dropped by 0.82 percentage points and the short term 13-week
T-bill yields dropped by 0.74 percentage points.
The long term treasury bond yields dropped by a greater amount than
the 13-week T-bill yields. This indicates that the yield curve became
more flat.
The yield curve flattening implies that investors expect lower future
economic growth and inflation, meaning investors anticipate lower future
interest rates.
The Fed’s influence on interest rates.
L7.10
We will download the federal fund rates at the beginning and end of
the school term.
getSymbols("FEDFUNDS", src = "FRED")
[1] "FEDFUNDS"
BoT_Interest_Rate <- FEDFUNDS["2024-05-1"]
print(BoT_Interest_Rate)
FEDFUNDS
2024-05-01 5.33
At the beginning of the term for the month of May the federal fund
rate was 5.33%.
EoT_Interest_Rate <- FEDFUNDS["2024-09-1"]
print(EoT_Interest_Rate)
FEDFUNDS
2024-09-01 5.13
At the end of the term for the month of September the federal fund
rate was 5.13%. We can see that over the school term the federal funds
rate did change from 5.33% to 5.13% for a 0.20 percentage point
decrease.
L7.11
Movements in interest rates over the school term would have been
caused by the Fed’s monetary policy.
Over the school term the Fed shifted towards monetary easing by
decreasing the interest rate. This likely would’ve been in response to
softening inflation and weaker economic activity.
Monetary easing would’ve helped improve economic momentum and trying
to accelerate market activity.
Measuring and explaining premiums on money market securities.
L7.12
We will now find the data for the yields on 90-day commercial paper
at the end of the school term.
We are unable to download the 90-day commercial paper data from FRED,
so we will use 3-Month AA Financial Commercial Paper Rate as a
proxy.
getSymbols("DCPF3M", src = "FRED")
[1] "DCPF3M"
EoT_90day_Rate <- DCPF3M["2024-09-1/2024-09-30"]
print(EoT_90day_Rate)
DCPF3M
2024-09-02 NA
2024-09-03 5.02
2024-09-04 NA
2024-09-05 NA
2024-09-06 NA
2024-09-09 4.99
2024-09-10 NA
2024-09-11 NA
2024-09-12 5.03
2024-09-13 NA
2024-09-16 NA
2024-09-17 NA
2024-09-18 NA
2024-09-19 4.62
2024-09-20 4.64
2024-09-23 NA
2024-09-24 NA
2024-09-25 NA
2024-09-26 NA
2024-09-27 NA
2024-09-30 NA
We can see the rate for the date closest to the end of the term is
4.64% on 2024-09-20.
We will now find the 13-week T-bill yield for the same date for a
fair comparison.
getSymbols("DTB3", src = "FRED")
[1] "DTB3"
print(DTB3["2024-09-20"])
DTB3
2024-09-20 4.56
We see here that the 13-week T-bill yield on 2024-09-20 was
4.56%.
The 90-day commercial paper yield is higher than the 13-week T-bill
yield, indicating a premium on the 90-day commercial paper yield.
The main reason for a premium on commercial paper yields is that
T-bills are issued by the government and are effectively risk free.
Commercial paper is issued by corporations and have a greater credit
risk since repayment depends on the financial health of the issuer.
Another reason for the premium can be credited to lower liquidity of
commercial papers, as they are traded less than the widely traded
T-bills.
L7.13
The premium on 90-day commercial papers over 13-week T-bill yields at
the end of the school term on 2024-09-20 was a 0.08% premium.
We will now find the premium that existed at the beginning of the
school term, using the same proxy for 90-day commercial paper we used
previously.
getSymbols("DCPF3M", src = "FRED")
[1] "DCPF3M"
print(DCPF3M["2024-05-1/2024-05-30"])
DCPF3M
2024-05-01 NA
2024-05-02 5.37
2024-05-03 5.37
2024-05-06 5.37
2024-05-07 5.34
2024-05-08 5.33
2024-05-09 5.30
2024-05-10 NA
2024-05-13 NA
2024-05-14 NA
2024-05-15 5.29
2024-05-16 NA
2024-05-17 NA
2024-05-20 5.26
2024-05-21 NA
2024-05-22 5.34
2024-05-23 5.30
2024-05-24 5.29
2024-05-27 NA
2024-05-28 5.33
2024-05-29 5.36
2024-05-30 NA
We see the yield closest to the beginning of the school term was
5.37% on 2024-05-02.
We will now find the 13-week T-bill yield for the same date.
getSymbols("DTB3", src = "FRED")
[1] "DTB3"
print(DTB3["2024-05-2"])
DTB3
2024-05-02 5.25
On 2024-05-02 the 13-week T-bill yield was 5.25%.
The commercial paper premium on this date was a 0.12% premium.
This data shows that the premium at the beginning of the school term
was greater than at the end of the school term.
The narrowing spread over the school term indicates improving
corporate credit conditions, as there is a smaller premium required to
attract investors, meaning investors had an increased confidence in
lower corporate credit risk.
Explaining bond premiums and price movements.
L7.14
We are going to download the yields for high-quality corporate bonds
at the beginning and end of the school term.
BoT_AAA_Rate <- AAA["2024-05-1"]
print(BoT_AAA_Rate)
AAA
2024-05-01 5.25
We see at the beginning of the school term high-quality corporate
bonds yield was 5.25%.
For the end of the school term we will use the average for September
2024.
EoT_AAA_Rate <- AAA["2024-09-1"]
print(EoT_AAA_Rate)
AAA
2024-09-01 4.68
We see at the end of the school term high-quality corporate bonds
yield was 4.68%.
Over the school term high-quality corporate bond yield dropped 0.57%
from 5.25% to 4.68%.
L7.15
We are now going to compare long-term treasury bond yields at the
beginning and end of the school term, using 10-year treasury bonds.
From L7.7 and L7.8 we know that the 10-year long-term treasury bond
yield was 4.63% at the beginning of the school term and 3.81% at the end
of the school term.
Over the school term long-term treasury bond yield dropped. This
means that the price of long-term treasury bonds has risen over the
school term, due to the inverse relationship between bond yields and
price.
L7.16
Unfortunately we are unable to access yield data on municipal bonds,
but we can assume they moved in close relation to treasury bonds, as
municipal bonds are also issued by the government and considered to be
generally risk free.
Using answers to the previous questions, we observe that over the
school term treasury bond and corporate bond yields moved in the same
direction and decreased over the school term.
The bond yields also decreased by a similar amount, around
0.50%-0.75%.
Different types of bonds have their yields generally move together
for a few reasons.
Firstly, bond yields are heavily influenced by federal reserve
interest rates. When the fed changes interest rates, it affects the cost
of borrowing for all entities, causing bond yields to change
accordingly.
Secondly, expectations on inflation. Where inflation affects the real
returns on bonds, so changes in inflation expectation will change the
yields on bonds. In this case expectations of lower inflation reduced
the yield on bonds.
Generally, yields on different types of bonds often change in line
with each other as they all respond to the same macroeconomic
factors.
L7.17
We are going to compare the yield premiums on high-quality corporate
bonds to treasury bonds at the beginning and end of the school term.
We know from previous questions that the yields on high-quality
corporate bonds at the beginning and end of the school term were 5.25%
and 4.68% respectively.
Again from previous questions, we know the yields on long term
treasury bonds at the beginning and end of the school term was 4.63% and
3.81% respectively.
This allows us to find the premiums on the high-quality corporate
bonds at the beginning and end of the school term to be 0.62% and 0.87%
respectively.
This shows us that over the school term the premium on high-quality
corporate bonds has increased.
This increase will be due to investors expectations of economic
conditions. During economic uncertainty or expected economic
deceleration, investors have a higher perceived credit risk on corporate
bonds, meaning that corporate bonds need to have higher yields to
attract investors.
________________________________________________________
L8 Portfolio - Markovitz
#Replicate the basic idea of the protfolio case
Modern Portfolio Theory (MPT), by Harry Markowitz, represents a
fundamental paradigm shift in investment portfolio construction by
introducing a quantitative approach to asset allocation. The theory
provides a framework for investors to optimize portfolio composition by
systematically balancing risk and return through diversification.
The core principle of MPT is the construction of an “efficient
portfolio” that either maximizes expected returns for a given level of
risk or minimizes risk for a predetermined expected return. This
optimization is achieved by rigorously analyzing two critical
statistical properties of asset returns:
Mean (Expected Return): A measure of the anticipated performance of
individual securities
Variance-Covariance Matrix: A comprehensive representation of both
individual asset risk and the interdependencies between assets
We will use 20 different stock portfolio that ranges from the
technology sector, financial sector healthcare sector and consumer
sector to ensure diversity in replicating the basic idea of the
portfolio case.
install.packages('quantmod')
Error in install.packages : Updating loaded packages
library(quantmod)
install.packages('PerformanceAnalytics')
Installing package into ‘/cloud/lib/x86_64-pc-linux-gnu-library/4.4’
(as ‘lib’ is unspecified)
trying URL 'http://rspm/default/__linux__/focal/latest/src/contrib/PerformanceAnalytics_2.0.8.tar.gz'
Content type 'application/x-gzip' length 1854619 bytes (1.8 MB)
==================================================
downloaded 1.8 MB
* installing *source* package ‘PerformanceAnalytics’ ...
** package ‘PerformanceAnalytics’ successfully unpacked and MD5 sums checked
** using staged installation
** libs
using C compiler: ‘gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0’
gcc -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c MCAHelper.c -o MCAHelper.o
gcc -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c NCEHelper.c -o NCEHelper.o
gcc -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c comomentsEstimators.c -o comomentsEstimators.o
gcc -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c comomentsHelper.c -o comomentsHelper.o
gcc -I"/opt/R/4.4.2/lib/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c init.c -o init.o
gcc -shared -L/opt/R/4.4.2/lib/R/lib -L/usr/local/lib -o PerformanceAnalytics.so MCAHelper.o NCEHelper.o comomentsEstimators.o comomentsHelper.o init.o -L/opt/R/4.4.2/lib/R/lib -lR
installing to /cloud/lib/x86_64-pc-linux-gnu-library/4.4/00LOCK-PerformanceAnalytics/00new/PerformanceAnalytics/libs
** R
** data
*** moving datasets to lazyload DB
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** installing vignettes
** testing if installed package can be loaded from temporary location
** checking absolute paths in shared objects and dynamic libraries
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (PerformanceAnalytics)
The downloaded source packages are in
‘/tmp/RtmpoJPRZy/downloaded_packages’
library(PerformanceAnalytics)
Attaching package: ‘PerformanceAnalytics’
The following objects are masked _by_ ‘.GlobalEnv’:
prices, weights
The following object is masked from ‘package:graphics’:
legend
install.packages('ggplot2')
Error in install.packages : Updating loaded packages
# Load necessary libraries
library(quantmod)
library(PerformanceAnalytics)
library(ggplot2)
We tried expanding the number of stocks to 20 in order to fully
diversify our portfolio.
# Define the stock tickers for the portfolio
tickers <- c("AAPL", "MSFT", "GOOG", "AMZN", "TSLA",
"META", "NVDA", "JPM", "V", "UNH",
"PG", "HD", "DIS", "XOM", "CVX",
"KO", "PEP", "MCD", "INTC", "ADBE")
# Fetch historical adjusted closing prices from Yahoo Finance
getSymbols(tickers, from = "2018-01-01", to = "2023-12-31")
[1] "AAPL" "MSFT" "GOOG" "AMZN" "TSLA" "META" "NVDA" "JPM" "V" "UNH" "PG" "HD"
[13] "DIS" "XOM" "CVX" "KO" "PEP" "MCD" "INTC" "ADBE"
# Combine all stock prices into a single xts object and calculate daily returns
prices <- do.call(merge, lapply(tickers, function(t) Cl(get(t))))
returns <- na.omit(ROC(prices))
# Calculate expected returns and covariance matrix for the stocks
mu <- colMeans(returns)
cov_mat <- cov(returns)
# Equal weights for simplicity: Dividing 1 by the number of stocks
weights <- rep(1 / length(tickers), length(tickers))
# Calculate portfolio expected return and variance
portfolio_return <- sum(weights * mu)
portfolio_variance <- t(weights) %*% cov_mat %*% weights
# Calculate annualized portfolio return and volatility
annual_return <- portfolio_return * 252
annual_volatility <- sqrt(portfolio_variance * 252)
# Print the results with annotations
print(paste("Annualized Portfolio Expected Return:", round(annual_return * 100, 2), "%"))
[1] "Annualized Portfolio Expected Return: 13.44 %"
print(paste("Annualized Portfolio Volatility:", round(annual_volatility * 100, 2), "%"))
[1] "Annualized Portfolio Volatility: 22.71 %"
With the aid of Chat GPT we were able to develop the code for
generating random portfolios.
# Define a simple function to generate random portfolios
random_portfolios <- function(num_portfolios, returns, num_assets) {
portfolio_returns <- numeric(num_portfolios)
portfolio_risks <- numeric(num_portfolios)
portfolio_weights <- matrix(nrow = num_portfolios, ncol = num_assets)
for (i in 1:num_portfolios) {
weights <- runif(num_assets)
weights <- weights / sum(weights)
portfolio_weights[i, ] <- weights
portfolio_returns[i] <- sum(weights * colMeans(returns)) * 252
portfolio_risks[i] <- sqrt(t(weights) %*% cov(returns) %*% weights) * sqrt(252)
}
data.frame(Return = portfolio_returns, Risk = portfolio_risks)
}
# Generate random portfolios
num_assets <- length(tickers)
portfolios_data <- random_portfolios(5000, returns, num_assets)
Normally it is not ideal to randomize portfolios or even its weight
since it would mean ignoring market conditions, investor goals, and risk
tolerance. It also indicates that the investor does not take into
consideration the potential correlation between assets.It ultimately is
assuming that there are equal returns and equal risk which is highly
unlikely in real-life situations. However, just for the purpose of
recreating a simple basic model, we decided to randomize them.
We used the data to plot a scatter plot of the randomized portfolios
made up of 20 stocks.
# Visualize the Efficient Frontier using ggplot2
ggplot(portfolios_data, aes(x = Risk, y = Return)) +
geom_point(alpha = 0.4, color = "blue") +
ggtitle("Efficient Frontier of 20 Stocks") +
xlab("Annualized Risk (Volatility)") +
ylab("Annualized Return") +
theme_minimal()

We would expect the Efficient Frontier to become more of a curved
line bending at low volatility as the number of Stocks in the portfolio
increases.
________________________________________________________
L9 Portfolio - CAMP
#State the difference between CAPM and Markovitz
1) In Markowitz’s theory, risk is defined as the
standard deviation of portfolio returns. It looks at both systematic and
unsystematic risks. CAPM focuses only on systematic risk, which is
measured by beta. CAPM assumes that investors hold well-diversified
portfolios where unsystematic risk is negligible.
2) Markowitz is primarily used for portfolio
construction. It helps investors allocate assets in such a way that the
portfolio has the best possible return for a given level of risk. In
contrast, CAPM is primarily used to determine the expected return of an
asset based on its systematic risk relative to the market. It is also
used to determine whether a particular investment offers an appropriate
return for its risk
3) Markowitz focuses on finding the efficient
frontier and minimizing standard deviation of portfolio. It involves
calculating the covariance between return of assets in the portfolio. On
the other hand, the key equation for CAPM is E(Ri) = Rf + βi ( E(Rm) -
Rf ).
Installing necessary packages:
install.packages("quadprog")
Error in install.packages : Updating loaded packages
library(quadprog)
Download historic data and see returns. (for Meta, Nvidia and Morgan
Stanley)
symbols <- c("META", "NVDA", "JPM")
getSymbols(symbols, from="2020-01-01", to="2023-12-31")
[1] "META" "NVDA" "JPM"
returns <- na.omit(ROC(merge(META[,6], NVDA[,6], JPM[,6]), type="discrete"))
colnames(returns) <- symbols
head(returns)
META NVDA JPM
2020-01-03 -0.005291175 -0.016006153 -0.0131964273
2020-01-06 0.018833611 0.004193930 -0.0007952446
2020-01-07 0.002163555 0.012106357 -0.0170005679
2020-01-08 0.010138056 0.001875670 0.0078006841
2020-01-09 0.014311026 0.010982675 0.0036515468
2020-01-10 -0.001099490 0.005349125 -0.0099678871
We now have daily returns for different companies in different
sectors of technology, semiconductors and financials.
These sectors represent some-what varying risk-return profiles,
useful for portfolio diversification analysis.
CAPM Analysis:
# Define parameters for CAPM
# Beta was found based on school term
Rf <- 0.038 # Risk-free rate as calculated above question
Rm <- 0.081 # Expected market return
Beta_META <- 1.31
Beta_NVDA <- 1.64
Beta_JPM <- 1.25
# CAPM Expected Returns
Ex_Re_META <- Rf + Beta_META * (Rm - Rf)
Ex_Re_NVDA <- Rf + Beta_NVDA * (Rm - Rf)
Ex_Re_JPM <- Rf + Beta_JPM * (Rm - Rf)
# Output CAPM results
cat("Expected Return (CAPM) for META:", round(Ex_Re_META * 100, 2), "%\n")
Expected Return (CAPM) for META: 9.43 %
cat("Expected Return (CAPM) for NVDA:", round(Ex_Re_NVDA * 100, 2), "%\n")
Expected Return (CAPM) for NVDA: 10.85 %
cat("Expected Return (CAPM) for JPM:", round(Ex_Re_JPM * 100, 2), "%\n")
Expected Return (CAPM) for JPM: 9.18 %
META and NVDA exhibit higher expected returns due to their higher
betas, reflecting greater sensitivity to market movements.
JPM, with a lower beta, has a lower expected return, indicating lower
systematic risk exposure.
Therefore, investors seeking higher returns may lean towards META or
NVDA but must accept higher volatility. JPM provides stability with
lower returns.
Markowitz Portfolio Optimization
#Calculate mean returns & covariance:
mean_returns <- colMeans(returns)
cov_matrix <- cov(returns)
# Define the constraints:
num_assets <- ncol(returns)
Amat <- cbind(rep(1, num_assets), diag(num_assets))
bvec <- c(1, rep(0, num_assets))
Dmat <- 2 * cov_matrix
dvec <- rep(0, num_assets)
# Solve for optimal portfolio weights
opt_portfolio <- solve.QP(Dmat, dvec, Amat, bvec, meq=1)
weights <- opt_portfolio$solution
# Calculate expected portfolio return and risk according to formula
expected_portfolio_return <- sum(mean_returns * weights)
portfolio_risk <- sqrt(t(weights) %*% cov_matrix %*% weights)
Portfolio results:
cat("Optimal Portfolio Weights (Markowitz):\n")
Optimal Portfolio Weights (Markowitz):
print(round(weights, 4))
[1] 0.2483 0.0553 0.6965
cat("Expected Portfolio Return:", round(expected_portfolio_return * 100, 2), "%\n")
Expected Portfolio Return: 0.08 %
cat("Portfolio Risk (Standard Deviation):", round(portfolio_risk * 100, 2), "%\n")
Portfolio Risk (Standard Deviation): 1.99 %
The optimal weights reveal how much to allocate to META, NVDA, and
JPM to achieve the best risk-return tradeoff.
By considering both systematic and unsystematic risks, Markowitz
provides a diversified allocation.
Therefore, in the case of risk-averse investors, this allocation
minimizes standard deviation while maximizing returns.
Briefly comparing CAPM with Markowitz based on the
calculations:
CAPM helps decide if an individual asset provides sufficient returns
for its risk.
Markowitz is useful for constructing a portfolio that achieves
optimal diversification.
________________________________________________________
L10 WACC
Replicate the book case of WACC
Bond data: Market values and Yields to Maturity.
Using bonds: Microsoft Corp. 5.2% Bond maturing on June 1,
2039, Microsoft Corp. 5.3% Bond maturing on February 8,
2041, Microsoft Corp. 4.25% Bond maturing on February
6, 2047
bond_values <- c(1e9, 1e9, 1.088485e9) # Market values of bonds in USD
bond_ytms <- c(0.0442, 0.0442, 0.0425) # Yields to maturity in decimal form
Calculate the total market value of bonds:
total_value <- sum(bond_values)
Calculate the weights for each bond (proportion of total
debt):
weights <- bond_values / total_value
Calculate the weighted average Yield to Maturity
(YTM):
weighted_avg_ytm <- sum(weights * bond_ytms)
Output the pre-tax cost of debt:
pre_tax_cost_of_debt <- weighted_avg_ytm
pre_tax_cost_of_debt
[1] 0.04360086
We have the cost of debt at 4.36%
The federal tax rate is 21%
Define the stock (Microsoft) and market index (S&P
500):
getSymbols("MSFT", src = "yahoo", from = "2020-01-01", to = Sys.Date())
[1] "MSFT"
getSymbols("^GSPC", src = "yahoo", from = "2020-01-01", to = Sys.Date())
[1] "GSPC"
Extract the adjusted closing prices:
msft_prices <- Cl(MSFT)
sp500_prices <- Cl(GSPC)
Calculate daily returns:
msft_returns <- dailyReturn(msft_prices)
sp500_returns <- dailyReturn(sp500_prices)
Calculate beta using the covariance of Microsoft and the
market, divided by the variance of the market:
beta_msft <- cov(msft_returns, sp500_returns) / var(sp500_returns)
Output the beta value
beta_msft
daily.returns
daily.returns 1.174345
We have the beta as 1.174345
For the risk free rate we can use the 10-year government
treasury bond yield.
Get the 10-year U.S. Treasury yield from FRED:
getSymbols("GS10", src = "FRED")
[1] "GS10"
Show the latest value of the 10-year Treasury
yield:
latest_risk_free_rate <- tail(GS10[, 1], 1)
latest_risk_free_rate
GS10
2024-12-01 4.39
Here we see the risk free rate is 4.39%.
Historically, the expected market return rate is
8-10%. For this casse we will use 8% to get the market risk
premium.
expected_market_return <- 0.08
Get the current 10-year U.S. Treasury yield from
FRED:
getSymbols("GS10", src = "FRED")
[1] "GS10"
risk_free_rate <- tail(GS10[, 1], 1) / 100
Calculate the market risk premium:
market_risk_premium <- expected_market_return - risk_free_rate
market_risk_premium
GS10
2024-12-01 0.0361
Here we get the market risk premium to be 3.61%.
Now we have our data, we can go ahead with the WACC
calculation.
Microsoft currently has spproximately 7.433 billion
outstanding shares
We can calculate the market capitalisation:
market_cap <- last(MSFT$MSFT.Adjusted) * 7433000000
We will now use the following variables defined
previously:
cost_of_debt <- 0.046
tax_rate <- 0.21
beta <- 1.17
risk_free_rate <-0.0439
market_risk_premium <- 0.0361
Now calculate the cost of equity using CAPM:
cost_of_equity <- risk_free_rate + beta * market_risk_premium
Based off Microsoft’s financial statements their market value
of debt is 61.47 billion.
market_value_of_debt <- 61.47e9
Calculate total market value:
total_market_value <- market_cap + market_value_of_debt
Calculate weights of debt and equity:
weight_of_debt <- market_value_of_debt / total_market_value
weight_of_equity <- market_cap / total_market_value
Calculate WACC for Microsoft:
wacc <- (weight_of_debt * cost_of_debt * (1 - tax_rate)) + (weight_of_equity * cost_of_equity)
cat("WACC for Microsoft:", wacc * 100, "%")
WACC for Microsoft: 8.518555 %
We see here Microsoft’s WACC is 8.52%.
________________________________________________________
L11 Derivatives
L11.1
# S&P 500 Futures Parameters
BoT_futures_price <- 5158.00
EoT_futures_price <- 5814.25
contract_multiplier <- 250
# Dollar values
BoT_value <- BoT_futures_price * contract_multiplier
EoT_value <- EoT_futures_price * contract_multiplier
# Difference
futures_difference <- EoT_value - BoT_value
print(paste("Difference in contract value:", futures_difference, "USD"))
[1] "Difference in contract value: 164062.5 USD"
futures_difference/(02*BoT_value)
[1] 0.06361477
L11.2
# Margin and Initial Investment
initial_margin <- 0.20
initial_investment <- BoT_value * initial_margin
# Return on Futures Position
futures_return <- futures_difference / initial_investment
print(paste("Return from futures position:", round(futures_return * 100, 2), "%"))
[1] "Return from futures position: 63.61 %"
We can say that this 63.61% return from an S&P 500 futures
position highlights successful leverage use and favorable market
conditions for the strategy used. But at the same time it also reminds
of the volatile and risky nature of futures trading.
L11.3
# School term duration (in months)
school_term_months <- 5
# Annualized Return
annualized_return <- futures_return * (12 / school_term_months)
print(paste("Annualized return:", round(annualized_return * 100, 2), "%"))
[1] "Annualized return: 152.68 %"
L11.4
We will use for this section the Chevron Corporation (CVX) Stock
Since we could’n’t find the premium for the terms, we assumed
BoT_premium to be the strike price and EoT_premium to be the market
price at the end of the term
# Call Option Parameters
BoT_stock_price <- 154.7069
EoT_stock_price <- 145.7829
strike_price <- 150
BoT_premium <- 10.32
EoT_premium <- 16.05
# Option Return
option_return <- (EoT_premium - BoT_premium) / BoT_premium
print(paste("Call option return:", round(option_return * 100, 2), "%"))
[1] "Call option return: 55.52 %"
Achieving a 55.52% return on a call option signals a successful
investment, since the underlying asset surpassed the strike price
significantly. This portrays the leverage effect of options, where small
market movements can greatly amplify returns. However, this also
highlights the importance of precise market timing and careful risk
management, as options are particularly sensitive to timing and market
volatility. Thus, it would be also useful to consider options as a way
of hedging in portfolios.
L11.5
# Annualized Return
annualized_option_return <- option_return * (12 / school_term_months)
print(paste("Annualized call option return:", round(annualized_option_return * 100, 2), "%"))
[1] "Annualized call option return: 133.26 %"
L11.6
# Stock Return
stock_return <- (EoT_stock_price - BoT_stock_price) / BoT_stock_price
print(paste("Stock return:", round(stock_return * 100, 2), "%"))
[1] "Stock return: -5.77 %"
print(paste("Option return is", round(option_return / stock_return, 2), "times the stock return."))
[1] "Option return is -9.63 times the stock return."
Determining swap payments
L11.7
# Swap Parameters
notional_amount <- 10000000
fixed_rate <- 0.06
floating_rate <- 0.0423
# Payments
fixed_payment <- notional_amount * fixed_rate
floating_payment <- notional_amount * floating_rate
swap_difference <- fixed_payment - floating_payment
# Results
print(paste("Fixed payment:", fixed_payment, "USD"))
[1] "Fixed payment: 6e+05 USD"
print(paste("Floating payment:", floating_payment, "USD"))
[1] "Floating payment: 423000 USD"
print(paste("Net swap difference:", swap_difference, "USD"))
[1] "Net swap difference: 177000 USD"
We gained $177,000 from the swap because the fixed rate we agreed to
pay which was 6%, was higher than the equivalent T-bill rate at the end
of the school term period. Essentially, this means that the interest
rate environment worked in our favor, with lower than expected floating
rates compared to our fixed rate commitment, which ultimately lead to a
net benefit from the swap.
Measuring and explaining exchange rate movements
# Exchange Rates
BoT_rates <- c(GBP = 1.2525, JPY = 0.0064, MXN = 0.0588)
EoT_rates <- c(GBP = 1.3370, JPY = 0.0069, MXN = 0.0506)
# Calculate percentage changes
percentage_changes <- (EoT_rates - BoT_rates) / BoT_rates * 100
L11.8
print(paste("GBP Change:", round(percentage_changes["GBP"], 2), "%"))
[1] "GBP Change: 6.75 %"
The pound appreciated against the US Dollar
11.9
print(paste("JPY Change:", round(percentage_changes["JPY"], 2), "%"))
[1] "JPY Change: 7.81 %"
The Yen appreciated against the US Dollar
L11.10
print(paste("MXN Change:", round(percentage_changes["MXN"], 2), "%"))
[1] "MXN Change: -13.95 %"
The Peso decreciated against the US Dollar
L11.12
# British Pound Futures
BoT_GBP_price <- 1.2525
EoT_GBP_price <- 1.3370
# Is it a gain or loss Per unit?
GBP_per_unit_gain <- EoT_GBP_price - BoT_GBP_price
print(paste("Per unit gain on GBP futures:", round(GBP_per_unit_gain, 4), "USD"))
[1] "Per unit gain on GBP futures: 0.0845 USD"
L11.12
# Contract size for British Pound Futures
contract_size <- 62500
# Total gain or loss
GBP_total_gain <- GBP_per_unit_gain * contract_size
print(paste("Total gain on GBP futures:", round(GBP_total_gain, 2), "USD"))
[1] "Total gain on GBP futures: 5281.25 USD"
________________________________________________________
L12 Capital requirements
L12.1
Both Bank of America and Deutsche Bank maintain strong capital
buffers to manage risks and meet, infact exceed their respective
regulatory requirements.
But, if we want to compare which has a better capital base: By the
end of 2023, Common Equity Tier 1 (CET1) ratio, a measure of financial
strength for Deutsche Bank’s was 13.7%. This is higher than Bank of
America’s 11.6%. These ratios indicate how much core capital each bank
holds relative to their risk-weighted assets, which are adjusted for the
likelihood of potential losses. Both banks comfortably exceed their
minimum CET1 requirements which is 9.5% for Bank of America and 10.55%
for Deutsche Bank. These regulatory minimums are set to ensure that
banks can absorb losses during economic stress. Therefore, excess
capital above these levels provides a cushion for unexpected risks. As a
result, Deutsche Bank’s higher CET1 ratio and reduction of €13 billion
in risk-weighted assets, suggest it has a relatively stronger buffer
against potential losses, enhancing its financial stability over Bank of
America.
________________________________________________________
LS0tCnRpdGxlOiAiRmluYWNpYWwgTWFya2V0cyBFWC4wIE9ibGlnYXRvcnkgRXhlcnNpc2UiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KClBpb3RyIFN0YXN6a2lld2ljegoKWjIwMjQKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCgojICoqVGVhbSBNZW1iZXJzOiAzICoqCiAgKipBdXRob3IgMSoqICooTDEsTDIsTDgsTDksTDExLEwxMikqLCAKCiAgKipBdXRob3IgMioqICooTDIsTDQsTDUsTDYsTDksTDEwKSosIAoKICAqKkF1dGhvciAzKiogKihMMyxMNyxMMTApKgoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KIyAqKlN0YXRlbWVudHM6KioKPkF1dGhvcuKAmXMgc3RhdGVtZW50IGZvciBub24taW5mcmluZ2VtZW50IG9mIG90aGVyc+KAmSBjb3B5cmlnaHRzOgpXZSBjb25maXJtIHRoYXQgdGhlIHdvcmsgb2Ygb3VyIGdyb3VwIHByb2plY3QgaXMgYW4gb3JpZ2luYWwgY3JlYXRpb24gdGhhdCBkb2VzIG5vdCBrbm93aW5nbHkgaW5mcmluZ2UgdXBvbiBhbnkgY29weXJpZ2h0IG9mIGFueSB0aGlyZCBwYXJ0eS4KCj5BdXRob3LigJlzIHN0YXRlbWVudCBhcyB0byBob3cgdGhlIEFJIHRvb2wgd2FzIHVzZWQgZHVyaW5nIHRoZSBhc3NpZ25tZW50OgpEdXJpbmcgb3VyIHByb2plY3QsIHdlIHV0aWxpc2VkIHRoZSB1c2Ugb2YgQ2hhdEdQVC4gCldlIHVzZWQgQ2hhdEdQVCB0byBoZWxwIHVzIGNvcnJlY3QgYW55IGVycm9ycyBpbiBvdXIgY29kZSBhbmQgZ2l2ZSB1cyBhIGd1aWRlIG9uIGhvdyB0byBkb3dubG9hZCBkYXRhIGNvcnJlY3RseSB0byBvdXIgY29kZS4gCldlIHVzZWQgcXVhbGl0eSBjb250cm9sIG1lYXN1cmVzIGluY2x1ZGluZyBjcm9zcy1yZWZlcmVuY2luZyBkYXRhIHdpdGggd2hhdCB3YXMgYXZhaWxhYmxlIG9uIGVkZ2FyIHNlYyBhbmQgRlJFRC4gCldlIGFzIHRoZSBhdXRob3JzIGFyZSBmdWxseSByZXNwb25zaWJsZSBmb3IgdGhlIGNvbnRleHQuIAoKPkF1dGhvcnPigJkgc3RhdGVtZW50cyBvbiB0aGUgdXNlIG9mIHRoZSB0YXNrIHVuZGVyIGEgcHVibGljIGFjY2VzcyBsaWNlbnNlOgpUaGUgZGF0YSB3ZSBhY2Nlc3NlZCBhbmQgZG93bmxvYWRlZCBmcm9tIGVkZ2FyIHNlYyBhbmQgRlJFRCB3YXMgcHVibGljIGRvbWFpbiBkYXRhIHdoaWNoIHdlIGFyZSBwZXJtaXR0ZWQgdG8gdXNlIGluIG91ciBwcm9qZWN0IHVuZGVyIGEgcHVibGljIGFjY2VzcyBsaWNlbnNlLiAKCgojICoqQWJvdXQgQXV0aG9yczoqKiAKKipBdXRob3IgMToqKiBTZW9uZ2d5dSBKZW9uLCAqU291dGggS29yZWEqCgoqKkF1dGhvciAyOioqIEtyaXN0ZWxsYSBXb25nIEthaCBIaW5nLCAqU2luZ2Fwb3JlKgoKKipBdXRob3IgMzoqKiBDaGFybGVzIE1hZGRpc29uICwgKkdyZWF0IEJyaXRhaW4qIAoKIyBfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwoKIyAqKkwxIEludHJvOiBCYXNpYyBwYXJhbWV0ZXJzIG9mIHRoZSBtYXJrZXQqKgoKRm9yIHRoaXMgc2VjdGlvbiwgd2Ugd2lsbCBhc3N1bWUgdGhlIHNjaG9vbCB0ZXJtIHRvIGJlIG91ciBiZWdpbm5pbmcgYW5kIGVuZCB0ZXJtLiAKCk1lYW5pbmcgdGhhdCB0aGUgQmVnaW5uaW5nIG9mIFRlcm0gKEJvVCkgaXMgTWF5IDAxLDIwMjQgYW5kIHRoZSBFbmQgb2YgVGVybSAoRW9UKSB3aWxsIGJlIFNlcHRlbWJlciAzMCwgMjAyNC4gCgpBbmQgdGhhdCB0aGUgZmlyc3Qgc2V0dGxlbWVudCBiZXlvbmQgdGhlIHRlcm0gd2lsbCBiZSBpbiB0aGUgbW9udGggb2YgT2N0b2Jlci4KCmBgYHtyfQojIENyZWF0ZSBhbiBlbXB0eSBkYXRhIGZyYW1lIHdpdGggc2VwYXJhdGUgY29sdW1ucyBkZWRpY2F0ZWQgZm9yIEJvVCBhbmQgRW9UCnRhYmxlX2RhdGEgPC0gZGF0YS5mcmFtZShDYXRlZ29yeSA9IGNoYXJhY3RlcigpLAogIEJvVCA9IG51bWVyaWMoKSwKICBFb1QgPSBudW1lcmljKCksCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKIyBGdW5jdGlvbiB0byBhZGQgcm93cyB0byB0aGUgdGFibGUKYWRkX3JvdyA8LSBmdW5jdGlvbihjYXRlZ29yeSwgQm9UX3ZhbHVlLCBFb1RfdmFsdWUpIAogIHt0YWJsZV9kYXRhIDw8LXJiaW5kKHRhYmxlX2RhdGEsIGRhdGEuZnJhbWUoQ2F0ZWdvcnkgPSBjYXRlZ29yeSwKICAgIEJvVCA9IEJvVF92YWx1ZSwKICAgIEVvVCA9IEVvVF92YWx1ZSkpfQoKIyBQb3B1bGF0ZSB0aGUgdGFibGUgd2l0aCByZWxldmFudCBkYXRhCgojIFN0b2NrIG1hcmtldCBpbmRleCBpbmZvcm1hdGlvbiAoRGF0YSBmcm9tIFlhaG9vIEZpbmFuY2UpCmFkZF9yb3coIlMmUCA1MDAgKHN0b2NrKSBpbmRleCBsZXZlbDoiLCA1MDE4LjM5LCA1NzYyLjQ4KSAgCmFkZF9yb3coIk5hc2RhcSBDb21wb3NpdGUgKHN0b2NrKSBpbmRleCBsZXZlbDoiLCAxNTYwNS40OCwgMTgxODkuMTcpCgojIEludGVyZXN0IHJhdGUgaW5mb3JtYXRpb24gKERhdGEgZnJvbSBGZWRlcmFsIFJlc2VydmUpCmFkZF9yb3coIlByaW1lIHJhdGU6IiwgOC4yNSwgOC4wMCkKYWRkX3JvdygiRmVkZXJhbCBmdW5kcyByYXRlOiIsIDUuMzMsIDQuODMpCmFkZF9yb3coIkNvbW1lcmNpYWwgcGFwZXIgcmF0ZSAoOTAgZGF5cyk6IiwgNS4zNywgNC42NCkKYWRkX3JvdygiQ2VydGlmaWNhdGUgb2YgZGVwb3NpdCByYXRlICgzLW1vbnRoKToiLCA1LjI4LCA0LjY4KQphZGRfcm93KCJUcmVhc3VyeSBiaWxsIHJhdGUgKDEzIHdlZWtzKToiLCA1LjI1LCA0LjcyKQphZGRfcm93KCJUcmVhc3VyeSBiaWxsIHJhdGUgKDI2IHdlZWtzKToiLCA1LjE3LCA0LjIzKQoKIyBCb25kIHlpZWxkIGluZm9ybWF0aW9uIChEYXRhIGZyb20gRmVkZXJhbCBSZXNlcnZlIEJhbmsgYW5kIFMmUCBHbG9iYWwpCmFkZF9yb3coIlRyZWFzdXJ5IGxvbmctdGVybSBib25kIHlpZWxkOiIsIDQuNjQsIDMuNzgpCmFkZF9yb3coIkNvcnBvcmF0ZSAoTWFzdGVyKSBib25kIHlpZWxkOiIsIDUuMjUsIDQuMzcpCmFkZF9yb3coIkhpZ2gteWllbGQgY29ycG9yYXRlIGJvbmQgeWllbGQ6IiwgMy44MSwgNC42OCkKYWRkX3JvdygiVGF4LWV4ZW1wdCAoN+KAkzEyLXllYXIpIGJvbmQgeWllbGQ6IiwgMTU5LjE5LCAxMzYuODMpCgojIFZpZXcgdGhlIGZpbmFsIHRhYmxlCnByaW50KHRhYmxlX2RhdGEpCmBgYAojIFVzZSBzdG9jayBleGNoYW5nZSBxdW90YXRpb25zIHRvIHJlY29yZCB0aGUgc3RvY2sgcHJpY2UgYW5kIGRpdmlkZW5kIG9mIG9uZSBzdG9jayBmcm9tIGVhY2ggc3RvY2sgZXhjaGFuZ2UgaW4gd2hpY2ggeW91IHdvdWxkIGxpa2UgdG8gaW52ZXN0LgoKRm9yIHRoaXMgc2VjdGlvbiB3ZSBoYXZlIGRlY2lkZWQgdG8gc2VsZWN0IHRoZSBOZXcgWW9yayBTdG9jayBFeGNoYW5nZSAoTllTRSkgYW5kIE5hc2RhcSB3aXRoIHN0b2NrcyBmcm9tIENoZXZyb24gQ29ycG9yYXRpb24gKENWWCkgYW5kIEFwcGxlIEluYy4gKEFBUEwpIHJlc3BlY3RpdmVseS4KCmBgYHtyfQojU2VhcmNoIGZvciBDaGV2cm9uIENvcnBvcmF0aW9uIChDVlgpIHN0b2NrCgojIEluc3RhbGwgdGhlIHBhY2thZ2VzIGlmIG5vdCBhbHJlYWR5IGluc3RhbGxlZAppbnN0YWxsLnBhY2thZ2VzKCJxdWFudG1vZCIpCmluc3RhbGwucGFja2FnZXMoJ2ZpbnJlcG9ydHInKQppbnN0YWxsLnBhY2thZ2VzKCdlZGdhcicpCmluc3RhbGwucGFja2FnZXMoJ1hCUkwnKQppbnN0YWxsLnBhY2thZ2VzKCdkcGx5cicpCmxpYnJhcnkocXVhbnRtb2QpCmxpYnJhcnkoZmlucmVwb3J0cikKbGlicmFyeShlZGdhcikgCmxpYnJhcnkoWEJSTCkgIApsaWJyYXJ5KGRwbHlyKSAKCmBgYAoKYGBge3J9CiMgRG93bmxvYWQgQ2hldnJvbiBDb3Jwb3JhdGlvbiAoQ1ZYKSBkYXRhCmdldFN5bWJvbHMoIkNWWCIsIGZyb20gPSAiMjAwMC0wMS0wMSIpCgojIFZpZXcgdGhlIGZpcnN0IGZldyByb3dzIG9mIHRoZSBkYXRhCmhlYWQoQ1ZYKQoKIyBTcGVjaWZ5IHRoZSBkYXRlIG9mIGludGVyZXN0IChCb1QpCmRhdGVfb2ZfaW50ZXJlc3QxIDwtICIyMDI0LTA1LTAxIgoKIyBTcGVjaWZ5IHRoZSBkYXRlIG9mIGludGVyZXN0IChFb1QpCmRhdGVfb2ZfaW50ZXJlc3QyIDwtICIyMDI0LTA5LTMwIgoKIyBFeHRyYWN0IHRoZSBhZGp1c3RlZCBjbG9zaW5nIHByaWNlIGZvciB0aGUgTllTRSBpbmRleCBvbiB0aGF0IGRhdGUgKEJvVCkKbnlzZV9wcmljZV8xIDwtIENWWFtkYXRlX29mX2ludGVyZXN0MSwgIkNWWC5BZGp1c3RlZCJdCnByaW50KG55c2VfcHJpY2VfMSkKCiMgRXh0cmFjdCB0aGUgYWRqdXN0ZWQgY2xvc2luZyBwcmljZSBmb3IgdGhlIE5ZU0UgaW5kZXggb24gdGhhdCBkYXRlIChFb1QpCm55c2VfcHJpY2VfMiA8LSBDVlhbZGF0ZV9vZl9pbnRlcmVzdDIsICJDVlguQWRqdXN0ZWQiXQpwcmludChueXNlX3ByaWNlXzIpCgpgYGAKVGhlIHByaWNlIG9mIENoZXZyb24gQ29ycG9yYXRpb24gU3RvY2sgaXMgMTU0LjcwNjkgYW5kIDE0NS43ODI5IGZvciBCb1QgYW5kIEVvVCByZXNwZWN0aXZlbHkuIAoKYGBge3J9CiMgRmluZCB0aGUgZGl2aWRlbmQgZm9yIENWWDoKc3ltYm9sIDwtICJDVlgiCgpkaXZpZGVuZHMgPC0gZ2V0RGl2aWRlbmRzKHN5bWJvbCwgZnJvbSA9ICIyMDIwLTAxLTAxIiwgdG8gPSAiMjAyNC0xMi0zMSIpCgojIFZpZXcgdGhlIGZpcnN0IGZldyByb3dzIG9mIGRpdmlkZW5kIGRhdGEKaGVhZChkaXZpZGVuZHMpCgojIEV4dHJhY3QgZGl2aWRlbmQgZGF0YSBmb3Igc3BlY2lmaWMgZGF0ZXMKZGF0ZXNfb2ZfaW50ZXJlc3QgPC0gYXMuRGF0ZShjKCIyMDI0LTA1LTAxIiwgIjIwMjQtMDktMzAiKSkKZGl2aWRlbmRfb25fZGF0ZXMgPC0gZGl2aWRlbmRzW2RhdGVzX29mX2ludGVyZXN0XQpwcmludChkaXZpZGVuZF9vbl9kYXRlcykKCiMgU2luY2UgdGhlcmUgaXMgbm8gZGl2aWRlbmQgZm9yIHRoZSBleGFjdCBwb2ludCBpbiB0aW1lLCB3ZSB3aWxsIGdldCB0aGUgb25lIHRoYXQgaXMgY2xvc2VzdCEKY2xvc2VzdF9kaXZpZGVuZHMgPC0gc2FwcGx5KGRhdGVzX29mX2ludGVyZXN0LCBmdW5jdGlvbihkYXRlKSB7CiAgY2xvc2VzdF9kYXRlIDwtIGluZGV4KGRpdmlkZW5kcylbd2hpY2gubWF4KGluZGV4KGRpdmlkZW5kcykgPD0gZGF0ZSldCiAgZGl2aWRlbmRzW2Nsb3Nlc3RfZGF0ZV19KQpuYW1lcyhjbG9zZXN0X2RpdmlkZW5kcykgPC0gZGF0ZXNfb2ZfaW50ZXJlc3QKcHJpbnQoY2xvc2VzdF9kaXZpZGVuZHMpCmBgYApUaGUgRGl2aWRlbmRzIGFyZSBib3RoIDEuMjkuIAoKYGBge3J9CiNTZWFyY2ggZm9yIEFwcGxlIEluYy4gKEFBUEwpIHN0b2NrCgojIERvd25sb2FkIEFwcGxlIEluYy4gKEFBUEwpIGRhdGEKZ2V0U3ltYm9scygiQUFQTCIsIGZyb20gPSAiMjAwMC0wMS0wMSIpCgojIFZpZXcgdGhlIGZpcnN0IGZldyByb3dzIG9mIHRoZSBkYXRhCmhlYWQoQUFQTCkKCiMgU3BlY2lmeSB0aGUgZGF0ZSBvZiBpbnRlcmVzdCAoQm9UKQpkYXRlX29mX2ludGVyZXN0MSA8LSAiMjAyNC0wNS0wMSIKCiMgU3BlY2lmeSB0aGUgZGF0ZSBvZiBpbnRlcmVzdCAoRW9UKQpkYXRlX29mX2ludGVyZXN0MiA8LSAiMjAyNC0wOS0zMCIKCiMgRXh0cmFjdCB0aGUgYWRqdXN0ZWQgY2xvc2luZyBwcmljZSBmb3IgdGhlIE5ZU0UgaW5kZXggb24gdGhhdCBkYXRlIChCb1QpCm5hc2RhcV9wcmljZV8xIDwtIEFBUExbZGF0ZV9vZl9pbnRlcmVzdDEsICJBQVBMLkFkanVzdGVkIl0KcHJpbnQobmFzZGFxX3ByaWNlXzEpCgojIEV4dHJhY3QgdGhlIGFkanVzdGVkIGNsb3NpbmcgcHJpY2UgZm9yIHRoZSBOWVNFIGluZGV4IG9uIHRoYXQgZGF0ZSAoRW9UKQpuYXNkYXFfcHJpY2VfMiA8LSBBQVBMW2RhdGVfb2ZfaW50ZXJlc3QyLCAiQUFQTC5BZGp1c3RlZCJdCnByaW50KG5hc2RhcV9wcmljZV8yKQpgYGAKVGhlIHByaWNlIG9mIEFwcGxlIEluYy4gU3RvY2sgaXMgMTY4LjY4OTYgYW5kIDIzMi43NDM5IGZvciBCb1QgYW5kIEVvVCByZXNwZWN0aXZlbHkuIAoKYGBge3J9CiMgRmluZCB0aGUgZGl2aWRlbmQgZm9yIEFBUEw6CnN5bWJvbCA8LSAiQUFQTCIKCmRpdmlkZW5kcyA8LSBnZXREaXZpZGVuZHMoc3ltYm9sLCBmcm9tID0gIjIwMjAtMDEtMDEiLCB0byA9ICIyMDI0LTEyLTMxIikKCiMgVmlldyB0aGUgZmlyc3QgZmV3IHJvd3Mgb2YgZGl2aWRlbmQgZGF0YQpoZWFkKGRpdmlkZW5kcykKCiMgRXh0cmFjdCBkaXZpZGVuZCBkYXRhIGZvciBzcGVjaWZpYyBkYXRlcwpkYXRlc19vZl9pbnRlcmVzdCA8LSBhcy5EYXRlKGMoIjIwMjQtMDUtMDEiLCAiMjAyNC0wOS0zMCIpKQpkaXZpZGVuZF9vbl9kYXRlcyA8LSBkaXZpZGVuZHNbZGF0ZXNfb2ZfaW50ZXJlc3RdCnByaW50KGRpdmlkZW5kX29uX2RhdGVzKQoKIyBTaW5jZSB0aGVyZSBpcyBubyBkaXZpZGVuZCBmb3IgdGhlIGV4YWN0IHBvaW50IGluIHRpbWUsIHdlIHdpbGwgZ2V0IHRoZSBvbmUgdGhhdCBpcyBjbG9zZXN0IQpjbG9zZXN0X2RpdmlkZW5kcyA8LSBzYXBwbHkoZGF0ZXNfb2ZfaW50ZXJlc3QsIGZ1bmN0aW9uKGRhdGUpIHsKICBjbG9zZXN0X2RhdGUgPC0gaW5kZXgoZGl2aWRlbmRzKVt3aGljaC5tYXgoaW5kZXgoZGl2aWRlbmRzKSA8PSBkYXRlKV0KICBkaXZpZGVuZHNbY2xvc2VzdF9kYXRlXX0pCm5hbWVzKGNsb3Nlc3RfZGl2aWRlbmRzKSA8LSBkYXRlc19vZl9pbnRlcmVzdApwcmludChjbG9zZXN0X2RpdmlkZW5kcykKYGBgCgpUaGUgRGl2aWRlbmRzIGFyZSBib3RoIDAuMTkyNS4gIAoKYGBge3J9CiMgQ3JlYXRlIGFuIGVtcHR5IGRhdGEgZnJhbWUgd2l0aCBzZXBhcmF0ZSBjb2x1bW5zIGRlZGljYXRlZCBmb3IgQm9UIGFuZCBFb1QKdGFibGVfZGF0YSA8LSBkYXRhLmZyYW1lKERlc2NyaXB0aW9uID0gY2hhcmFjdGVyKCksCiAgQm9UID0gbnVtZXJpYygpLAogIEVvVCA9IG51bWVyaWMoKSwKICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgojIEZ1bmN0aW9uIHRvIGFkZCByb3dzIHRvIHRoZSB0YWJsZQphZGRfcm93IDwtIGZ1bmN0aW9uKGNhdGVnb3J5LCBCb1RfdmFsdWUsIEVvVF92YWx1ZSkgCiAge3RhYmxlX2RhdGEgPDwtcmJpbmQodGFibGVfZGF0YSwgZGF0YS5mcmFtZShDYXRlZ29yeSA9IGNhdGVnb3J5LAogICAgQm9UID0gQm9UX3ZhbHVlLAogICAgRW9UID0gRW9UX3ZhbHVlKSl9CgojIFBvcHVsYXRlIHRoZSB0YWJsZSB3aXRoIHJlbGV2YW50IGRhdGEKCiMgU3RvY2sgbWFya2V0IGluZm9ybWF0aW9uCmFkZF9yb3coIk5ldyBZb3JrIFN0b2NrIEV4Y2hhbmdlOiBTdG9jayBwcmljZTogQ1ZYIiwgMTU0LjcwNjksIDE0NS43ODI5KSAgCmFkZF9yb3coIkNoZXZyb24gQ29ycG9yYXRpb24gKENWWCkgRGl2aWRlbmQ6IiwgMS4yOSwgMS4yOSkKYWRkX3JvdygiTmFzZGFxIE1hcmtldDogU3RvY2sgcHJpY2U6QUFQTCIsIDE2OC42ODk2LCAyMzIuNzQzOSkgIAphZGRfcm93KCJBcHBsZSBJbmMuIChBQVBMKSBEaXZpZGVuZDoiLCAwLjE5MjUsIDAuMTkyNSkKCiMgVmlldyB0aGUgZmluYWwgdGFibGUKcHJpbnQodGFibGVfZGF0YSkKYGBgCgojIFVzZSBmdXR1cmVzIHByaWNlcyBxdW90YXRpb25zIHRvIHJlY29yZCB0aGUgcmVjZW50ICjigJxzZXR0bGXigJ0pIHByaWNlIG9mIHRoZSBmb2xsb3dpbmcgZnV0dXJlcyAoc2VsZWN0IGZ1dHVyZXMgd2l0aCBmaXJzdCBzZXR0bGVtZW50IGRhdGUgYmV5b25kIHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtKToKCmBgYHtyfQojIENyZWF0ZSBhbiBlbXB0eSBkYXRhIGZyYW1lIHdpdGggc2VwYXJhdGUgY29sdW1ucyBkZWRpY2F0ZWQgZm9yIEJvVCBhbmQgRW9UCnRhYmxlX2RhdGEgPC0gZGF0YS5mcmFtZShEZXNjcmlwdGlvbiA9IGNoYXJhY3RlcigpLAogIEJvVCA9IG51bWVyaWMoKSwKICBFb1QgPSBudW1lcmljKCksCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKIyBGdW5jdGlvbiB0byBhZGQgcm93cyB0byB0aGUgdGFibGUKYWRkX3JvdyA8LSBmdW5jdGlvbihjYXRlZ29yeSwgQm9UX3ZhbHVlLCBFb1RfdmFsdWUpIAogIHt0YWJsZV9kYXRhIDw8LXJiaW5kKHRhYmxlX2RhdGEsIGRhdGEuZnJhbWUoQ2F0ZWdvcnkgPSBjYXRlZ29yeSwKICAgIEJvVCA9IEJvVF92YWx1ZSwKICAgIEVvVCA9IEVvVF92YWx1ZSkpfQoKIyBQb3B1bGF0ZSB0aGUgdGFibGUgd2l0aCByZWxldmFudCBkYXRhCgojIE1hcmtldCBpbmZvcm1hdGlvbgphZGRfcm93KCJUcmVhc3VyeSBib25kIGZ1dHVyZXM6IiwgMTE1LjAzLCAxMjQuMTkpICAKYWRkX3JvdygiUyZQIDUwMCBpbmRleCBmdXR1cmVzOiIsIDUxNTguMDAsIDU4MTQuMjUpCmFkZF9yb3coIk5hc2RhcSBNYXJrZXQ6IFN0b2NrIHByaWNlOiIsIDE3ODY4LjUwLCAyMDI2MS4yNSkgIAphZGRfcm93KCJCcml0aXNoIHBvdW5kIGZ1dHVyZXM6IiwgMS4yNTQ5LCAxLjMzNzQpCgojIFZpZXcgdGhlIGZpbmFsIHRhYmxlCnByaW50KHRhYmxlX2RhdGEpCmBgYAoKIyBVc2UgYW4gb3B0aW9ucyBxdW90YXRpb25zIHRhYmxlIHRvIHNlbGVjdCBhIGNhbGwgb3B0aW9uIG9uIGEgZmlybSB3aG9zZSBzdG9jayBwcmljZSB5b3UgZXhwZWN0IHRvIGluY3JlYXNlIChzZWxlY3QgdGhlIG9wdGlvbiB3aXRoIHRoZSBmaXJzdCBleHBpcmF0aW9uIG1vbnRoIGJleW9uZCB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybSk6CgpXZSBzdHJvbmdseSBiZWxpdmUgdGhhdCBBcHBsZSBJbmMuIChBQVBMKSBzdG9jayB3aWxsIGluY3JlYXNlIGJ5IGxvb2tpbmcgYXQgdGhlIGNvbnRpbnVvdXMgaW5jcmVhc2UgaW4gc2hhcmUgcHJpY2VzLCB0aHVzIGhlcmUncyBhIHNlbGVjdGVkIGNhbGwgb3B0aW9uIHdlIGhhdmUgZGVjaWRlZDoKCk5hbWUgb2YgRmlybTogQXBwbGUgSW5jLiAoQUFQTCkKCkV4cGlyYXRpb24gTW9udGg6IERlY2VtYmVyIDIwMjQKClN0cmlrZSBQcmljZTogJDIzMAoKCmBgYHtyfQojIENyZWF0ZSBhbiBlbXB0eSBkYXRhIGZyYW1lIHdpdGggc2VwYXJhdGUgY29sdW1ucyBkZWRpY2F0ZWQgZm9yIEJvVCBhbmQgRW9UCnRhYmxlX2RhdGEgPC0gZGF0YS5mcmFtZShEZXNjcmlwdGlvbiA9IGNoYXJhY3RlcigpLAogIEJvVCA9IG51bWVyaWMoKSwKICBFb1QgPSBudW1lcmljKCksCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKIyBGdW5jdGlvbiB0byBhZGQgcm93cyB0byB0aGUgdGFibGUKYWRkX3JvdyA8LSBmdW5jdGlvbihjYXRlZ29yeSwgQm9UX3ZhbHVlLCBFb1RfdmFsdWUpIAogIHt0YWJsZV9kYXRhIDw8LXJiaW5kKHRhYmxlX2RhdGEsIGRhdGEuZnJhbWUoQ2F0ZWdvcnkgPSBjYXRlZ29yeSwKICAgIEJvVCA9IEJvVF92YWx1ZSwKICAgIEVvVCA9IEVvVF92YWx1ZSkpfQoKIyBQb3B1bGF0ZSB0aGUgdGFibGUgd2l0aCByZWxldmFudCBkYXRhCgojIFN0b2NrIG1hcmtldCBpbmZvcm1hdGlvbgphZGRfcm93KCJTdG9jayBwcmljZToiLCAxNjguNjg5NiwgMjMyLjc0MzkpICAKYWRkX3JvdygiT3B0aW9uIHByZW1pdW0iLCBOQSwgOC4wNSkKCnByaW50KHRhYmxlX2RhdGEpCmBgYAoKCkV4cGxhbmF0aW9uIGZvciBTdHJpa2UgcHJpY2UgYW5kIGNhbGwgb3B0aW9uIHNlbGVjdGlvbjoKV2UgY2hvc2UgQXBwbGUgSW5jLiAoQUFQTCkgYXMgdGhlIGNhbGwgb3B0aW9uIGZvciBhIGZpcm0gd2hvc2Ugc3RvY2sgcHJpY2UgaXMgZXhwZWN0ZWQgdG8gcmlzZS4gVGhpcyBpcyBiZWNhdXNlIEFwcGxlIGhhcyBzdHJvbmcgbWFya2V0IHByZXNlbmNlLCBjb25zaXN0ZW50IGdyb3d0aCwgYW5kIHNvbGlkIGZpbmFuY2lhbCBmb3VuZGF0aW9uLiBJdCBpcyBpbXBvcnRhbnQgdG8gd2VsbC1lc3RhYmxpc2ggdGhlIHN0cmlrZSBwcmljZSBzaW5jZSBpdCBkZXRlcm1pbmVzIGhvdyBtdWNoIHRoZSBvcHRpb24gcHJlbWl1bSB3aWxsIGNvc3QgYW5kIHRoZSBsaWtlbGlob29kIG9mIGl0IGJlY29taW5nIHByb2ZpdGFibGUuIFdpdGggQXBwbGXigJlzIHN0b2NrIHByaWNlIGF0ICQxNjguNjkgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgdGVybSAoQm9UKSBhbmQgcHJvamVjdGVkIHRvIHJlYWNoICQyMzIuNzQgYnkgdGhlIGVuZCBvZiB0aGUgdGVybSAoRW9UKSwgc2VsZWN0aW5nIGEgc3RyaWtlIHByaWNlIHNsaWdodGx5IGFib3ZlIHRoZSBCb1QgcHJpY2UsIHN1Y2ggYXMgJDIzMCBvciAkMjM1LCBvZmZlcnMgYSBnb29kIGJhbGFuY2UuIAoKSW4gYSBjYWxsIG9wdGlvbiBpZiB0aGUgc3RyaWtlIHByaWNlIGlzIHRvbyBsb3dlciB0aGUgYWN0dWFsIHByaWNlLCB0aGUgcHJlbWl1bSBpbmNyZWFzZXMgc2lnbmlmaWNhbnRseS4gVGhpcyBpcyBiZWNhdXNlIGhpZ2hlciBzdHJpa2UgcHJpY2UgaGFzIGEgbG93ZXIgcHJvYmFiaWxpdHkgb2YgZXhwaXJpbmcgaW4gdGhlIG1vbmV5LiBBbHNvLCB0aGUgb3B0aW9uIHByZW1pdW0gZW5jb21wYXNzZXMgdGhlIGludHJpbnNpYyB2YWx1ZSBhbmQgdGltZSB2YWx1ZS4gQW5kLCBpZiB0aGVyZSBpcyBhIGJpZ2dlciBkaWZmZXJlbmNlIGJldHdlZW4gU3RvY2sgcHJpY2UgYW5kIFN0cmlrZSBQcmljZSwgdGhlIGludHJpbnNpYyB2YWx1ZSBpbmNyZWFzZXMuIChXaGVuIHRoZSBTdHJpa2UgcHJpY2UgPCBTdG9jayBwcmljZSkuIFRodXMsIGhhdmluZyBhICQyMzAgc3RyaWtlIHByaWNlIGtlZXBzIHRoZSBwcmVtaXVtIGNvc3QgbWFuYWdlYWJsZSB3aGlsZSBtYWludGFpbmluZyBhIHN0cm9uZyBjaGFuY2UgdGhhdCB0aGUgb3B0aW9uIHdpbGwgZW5kIGluIHRoZSBtb25leSAoSVRNKSBieSB0aGUgZW5kIG9mIHRoZSB0ZXJtLiAKCkZvciBjb250ZXh0LCBhIGNhbGwgb3B0aW9uIGJlY29tZXMgaW4gdGhlIG1vbmV5IHdoZW4gdGhlIHN0b2NrIHByaWNlIGV4Y2VlZHMgdGhlIHN0cmlrZSBwcmljZS4gV2l0aCBBcHBsZeKAmXMgc3RvY2sgcHJvamVjdGVkIHRvIGhpdCAkMjMyLjc0LCBjaG9vc2luZyBhIHN0cmlrZSBwcmljZSBvZiAkMjMwIHdvdWxkIGdlbmVyYXRlIGFuIGludHJpbnNpYyB2YWx1ZSBvZjogU3RvY2sgUHJpY2UgYXQgRW9UIOKIkgpTdHJpa2UgUHJpY2UgPSAyMzIuNzQg4oiSIDIzMCA9ICQyLjc0CgpBbHNvLCB0aGUgcHJpY2UgcGFpZCB0byBhY3F1aXJlIHRoZSBwcmVtaXVtLCBwbGF5cyBhIGNyaXRpY2FsIHJvbGUgYXMgd2VsbCBzaW5jZSBmb3IgZXhhbXBsZSwgaWYgc3RvY2sgaXMgYXQgMjMyLjc0IGFuZCB0aGUgc3RyaWtlIHByaWNlIGlzICQyMzAsIHRoZSBwcmVtaXVtIGNvdWxkIGJlIGFyb3VuZCAxMCAoQnkgYXBwcm94aW1hdGluZyBmcm9tIHRoZSBjdXJyZW50IHByZW1pdW0gZm9yIHRoZSByZXNwZWN0aXZlIHN0cmlrZSBwcmljZT0gOC4wNSkuIElmIHRoZSBzdG9jayBlbmRzIGF0ICQyNTAsIHRoZSBwYXlvZmYgd291bGQgYmUgMjUwLTIzMC0xMCA9ICQxMCBpbiBwcm9maXQgcGVyIHNoYXJlLiAKCldlIHdlcmUgbm90IGFibGUgdG8gZmluZCB0aGUgdmFsdWUgb2Ygb3B0aW9uIHByZW1pdW0gYmV0d2VlbiBvdXIgYXNzdW1lZCB0ZXJtIHNvIHdlIG1hZGUgYXNzdW1wdGlvbnMgYmFzZWQgb24gdGhlIGZpcnN0IGV4cGlyYXRpb24gbW9udGggZnJvbSBub3cuIE1lYW5pbmcgd2UgYXNzdW1lZCB0aGUgcHJpY2Ugb2YgcHJlbWl1bSBmb3Igb3B0aW9ucyB0aGF0IGV4cGlyZSBpbiBEZWNlbWJlciBhcyBpZiB0aGV5IHdvdWxkIGV4cGlyZSBpbiBPY3RvYmVyLiAKCgojIFVzZSBhbiBvcHRpb25zIHF1b3RhdGlvbnMgdGFibGUgdG8gc2VsZWN0IGEgcHV0IG9wdGlvbiBvbiBhIGZpcm0gd2hlcmUgeW91IGV4cGVjdCB0aGUgc3RvY2sgcHJpY2UgdG8gZGVjcmVhc2UgKHNlbGVjdCB0aGUgb3B0aW9uIHdpdGggdGhlIGZpcnN0IGV4cGlyYXRpb24gbW9udGggYmV5b25kIHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtKToKCk5hbWUgb2YgRmlybTogQ2hldnJvbiBDb3Jwb3JhdGlvbiAoQ1ZYKQoKRXhwaXJhdGlvbiBNb250aDogRGVjZW1iZXIgMjAyNAoKU3RyaWtlIFByaWNlOiAkMTUwCgoKYGBge3J9CnRhYmxlX2RhdGEgPC0gZGF0YS5mcmFtZShEZXNjcmlwdGlvbiA9IGNoYXJhY3RlcigpLAogIEJvVCA9IG51bWVyaWMoKSwKICBFb1QgPSBudW1lcmljKCksCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKYWRkX3JvdyA8LSBmdW5jdGlvbihjYXRlZ29yeSwgQm9UX3ZhbHVlLCBFb1RfdmFsdWUpIAogIHt0YWJsZV9kYXRhIDw8LXJiaW5kKHRhYmxlX2RhdGEsIGRhdGEuZnJhbWUoQ2F0ZWdvcnkgPSBjYXRlZ29yeSwKICAgIEJvVCA9IEJvVF92YWx1ZSwKICAgIEVvVCA9IEVvVF92YWx1ZSkpfQoKIyBQb3B1bGF0ZSB0aGUgdGFibGUgd2l0aCByZWxldmFudCBkYXRhCgphZGRfcm93KCJTdG9jayBwcmljZToiLCAxNTQuNzA2OSwgMTQ1Ljc4MjkpICAKYWRkX3JvdygiT3B0aW9uIHByZW1pdW0iLCBOQSwgMTAuMzIpCgpwcmludCh0YWJsZV9kYXRhKQpgYGAKCkV4cGxhbmF0aW9uIGZvciBTdHJpa2UgcHJpY2UgYW5kIHB1dCBvcHRpb24gc2VsZWN0aW9uOgpXZSBjaG9zZSBDaGV2cm9uIENvcnBvcmF0aW9uIChDVlgpIGFzIHRoZSBmaXJtIGZvciB0aGUgcHV0IG9wdGlvbiBkdWUgdG8gaXRzIGRlY2xpbmluZyBzdG9jayBwcmljZSB0cmVuZCwgcmVmbGVjdGVkIGluIHRoZSBiZWdpbm5pbmcgb2YgdGVybSAoQm9UKSBwcmljZSBvZiAkMTU0LjcxIGFuZCBlbmQgb2YgdGVybSAoRW9UKSBwcmljZSBvZiAkMTQ1Ljc4LiBSZXZlcnNlIGZyb20gdGhlIGNhbGwgb3B0aW9uLCB0aGUgaG9sZGVyIG9mIHRoZSBwdXQgb3B0aW9uIHByb2ZpdCBmcm9tIHRoZSBkZWNsaW5lIGluIHNoYXJlIHByaWNlLiBUaGUgc3RyaWtlIHByaWNlIGlzIGFsc28gaW1wb3J0YW50IGhlcmUgYXMgaXQgZGV0ZXJtaW5lcyB0aGUgY29zdCBvZiB0aGUgcHJlbWl1bSBhbmQgdGhlIHBvdGVudGlhbCBwcm9maXRhYmlsaXR5LiBGb3IgQ2hldnJvbiwgc2VsZWN0aW5nIGEgc3RyaWtlIHByaWNlIG9mICQxNTAuMDAgb2ZmZXJzIGEgZ29vZCBiYWxhbmNlIGJldHdlZW4gYWZmb3JkYWJpbGl0eSBhbmQgdGhlIGxpa2VsaWhvb2Qgb2YgdGhlIG9wdGlvbiBiZWluZyBpbiB0aGUgbW9uZXkgKElUTSkgYnkgZXhwaXJhdGlvbi4gSXQgaXMgY2VydGFpbmx5IGJldHRlciB0aGFuIHRoZSBwcmVtaXVtIGZvciBzdHJpa2UgcHJpY2VzIGF0ICQxNDAgc2luY2UgdGhlIHByZW1pdW0gbmVhcmx5IGRvdWJsZXMgYXQgdGhlIHJlc3BlY3RpdmUgcHJpY2UuIAoKRm9yIGEgcHV0IG9wdGlvbiAoYW5kIGV2ZW4gZm9yIGNhbGwgb3B0aW9uKSwgdGhlIGNsb3NlciB0aGUgc3RyaWtlIHByaWNlIGlzIHRvIHRoZSBjdXJyZW50IHN0b2NrIHByaWNlLCB0aGUgaGlnaGVyIHRoZSBwcmVtaXVtIGlzIGR1ZSB0byBpbmNyZWFzZWQgaW50cmluc2ljIHZhbHVlIGFuZCB0aW1lIHZhbHVlLgpUaGUgY2FsY3VsYXRpb24gZm9yIGludHJpbnNpYyB2YWx1ZSBhbmQgcGF5b2ZmIGlzIHJldmVyc2UgZnJvbSB0aGUgY2FsbCBvcHRpb24uIAoKV2UgYWxzbyBtYWRlIHRoZSBzYW1lIGFzc3VtcHRpb24gYXMgaW4gdGhlIHByZXZpb3VzIHF1ZXN0aW9uIHJlZ2FyZGluZyBFb1QuIAoKRHVlIHRvIHRoZSBpbml0aWFsIGFzc3VtcHRpb24gb2YgdGhlIG9wdGlvbiBleHBpcmluZyByaWdodCBhZnRlciB0aGUgZW5kIG9mIHRlcm0sIHdlIGhhdmUgbm90IGNvbnNpZGVyZWQgaG93IHRpbWUgcmVtYWluaW5nIG9mIG9wdGlvbnMgY291bGQgYWZmZWN0IHRoZSBzdHJpa2UgcHJpY2UgYW5kIHByZW1pdW0uIEZ1cnRoZXJtb3JlLCBmb3IgcHV0IG9wdGlvbnMsIGEgaGlnaGVyIHJpc2sgZnJlZS1pbnRlcmVzdCBjYW4gYWxzbyByZWR1Y2UgdGhlaXIgdmFsdWUuIFRoaXMgb2NjdXJzIGJlY2F1c2UgdGhlIHByZXNlbnQgdmFsdWUgb2YgdGhlIHN0cmlrZSBwcmljZSBkZWNyZWFzZXMgYXMgaW50ZXJlc3QgcmF0ZSByaXNlcyB3aGljaCBpbiB0dXJuIHJlZHVjZXMgdGhlIGludHJpbnNpYyB2YWx1ZS4gSW4gdGhlIHBlcnNwZWN0aXZlIG9mIGFuIGludmVzdG9yLCB0aGV5IG1pZ2h0IHByZWZlciB0byBhbGxvY2F0ZSBmdW5kIGludG8gaGlnaGVyIHlpZWxkaW5nIGFsdGVybmF0aXZlcyBiZWNhdXNlIGhpZ2hlciBpbnRlcmVzdCByYXRlcyBtYWtlcyByaXNrLWZyZWUgaW52ZXN0bWVudHMgbW9yZSBhcHBlYWxpbmcuIFdoaWNoIGluIHR1cm4gY2FuIHJlZHVjZSB0aGUgZGVtYW5kIGZvciB0aGVzZSBwdXQgb3B0aW9ucy4gCgpTbyBpbiByZWFsaXR5LCB0aGVyZSB3b3VsZCBoYXZlIGJlZW4gbW9yZSBmYWN0b3JzIHRoYXQgbmVlZGVkIHRvIGJlIGtlcHQgaW4gbWluZCB3aGlsZSBhbnN3ZWluZyB0aGlzIHF1ZXN0aW9uLiAKCiMgVXNlIGEgY3VycmVuY3kgZXhjaGFuZ2UgcmF0ZSB0YWJsZSB0byByZWNvcmQgZXhjaGFuZ2UgcmF0ZXM6CmBgYHtyfQojIENyZWF0ZSBhbiBlbXB0eSBkYXRhIGZyYW1lIHdpdGggc2VwYXJhdGUgY29sdW1ucyBkZWRpY2F0ZWQgZm9yIEJvVCBhbmQgRW9UCnRhYmxlX2RhdGEgPC0gZGF0YS5mcmFtZShEZXNjcmlwdGlvbiA9IGNoYXJhY3RlcigpLAogIEJvVCA9IG51bWVyaWMoKSwKICBFb1QgPSBudW1lcmljKCksCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKIyBGdW5jdGlvbiB0byBhZGQgcm93cyB0byB0aGUgdGFibGUKYWRkX3JvdyA8LSBmdW5jdGlvbihjYXRlZ29yeSwgQm9UX3ZhbHVlLCBFb1RfdmFsdWUpIAogIHt0YWJsZV9kYXRhIDw8LXJiaW5kKHRhYmxlX2RhdGEsIGRhdGEuZnJhbWUoQ2F0ZWdvcnkgPSBjYXRlZ29yeSwKICAgIEJvVCA9IEJvVF92YWx1ZSwKICAgIEVvVCA9IEVvVF92YWx1ZSkpfQoKIyBQb3B1bGF0ZSB0aGUgdGFibGUgd2l0aCByZWxldmFudCBkYXRhCgojIE1hcmtldCBpbmZvcm1hdGlvbgphZGRfcm93KCJFeGNoYW5nZSByYXRlIG9mIHRoZSBCcml0aXNoIHBvdW5kIChpbiAkKToiLCAxLjI1MjUgLCAxLjMzNzAgKSAgCmFkZF9yb3coIkV4Y2hhbmdlIHJhdGUgb2YgdGhlIEphcGFuZXNlIHllbiAoaW4gJCk6IiwgMC4wMDY0NzIsIDAuMDA2OTYxKQphZGRfcm93KCJFeGNoYW5nZSByYXRlIG9mIHRoZSBNZXhpY2FuIHBlc28gKGluICQpOiIsIDAuMDU4OCwgMC4wNTA2KSAgCgojIFZpZXcgdGhlIGZpbmFsIHRhYmxlCnByaW50KHRhYmxlX2RhdGEpCmBgYAoKIyBVc2UgY3VycmVuY3kgb3B0aW9ucyBkYXRhIChpZiBhdmFpbGFibGUpIHRvIHNlbGVjdCBhIGNhbGwgb3B0aW9uIG9uIGEgZm9yZWlnbiBjdXJyZW5jeSB0aGF0IHlvdSBleHBlY3Qgd2lsbCBzdHJlbmd0aGVuIGFnYWluc3QgdGhlIGRvbGxhciAoc2VsZWN0IHRoZSBvcHRpb24gd2l0aCB0aGUgZmlyc3QgZXhwaXJhdGlvbiBtb250aCBiZXlvbmQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0pOgoKQ3VycmVuY3k6IEJyaXRpc2ggUG91bmQgKEdCUCkgCgpFeHBpcmF0aW9uIG1vbnRoOiBEZWNlbWJlciAKClN0cmlrZSBwcmljZTogMS4zMAoKCmBgYHtyfQp0YWJsZV9kYXRhIDwtIGRhdGEuZnJhbWUoRGVzY3JpcHRpb24gPSBjaGFyYWN0ZXIoKSwKICBCb1QgPSBudW1lcmljKCksCiAgRW9UID0gbnVtZXJpYygpLAogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCmFkZF9yb3cgPC0gZnVuY3Rpb24oY2F0ZWdvcnksIEJvVF92YWx1ZSwgRW9UX3ZhbHVlKSAKICB7dGFibGVfZGF0YSA8PC1yYmluZCh0YWJsZV9kYXRhLCBkYXRhLmZyYW1lKENhdGVnb3J5ID0gY2F0ZWdvcnksCiAgICBCb1QgPSBCb1RfdmFsdWUsIAogICAgRW9UID0gRW9UX3ZhbHVlKSl9CgojIFBvcHVsYXRlIHRoZSB0YWJsZSB3aXRoIHJlbGV2YW50IGRhdGEKCmFkZF9yb3coIkN1cnJlbmN54oCZcyBleGlzdGluZyB2YWx1ZToiLCAxLjI1MjUgLCAxLjMzNzApICAKYWRkX3JvdygiT3B0aW9uIHByZW1pdW0iLCBOQSwgMC4wMDUpIAoKIyBJdCBpcyBxdWl0ZSBoYXJkIHRvIGtub3cgdGhlIG9wdGlvbiBwcmVtaXVtIGZvciBhIHN0cmlrZSBwcmljZSBvZiAxLjMwIHNpbmNlIHRoZSBwb3VuZCBoYXMgZGVwcmVjaWF0ZWQgdG8gMS4yNyBhbmQgdGhlIHByZW1pdW0gaXMgMC4wMDUgYXQgYXQgbWFya2V0IHByaWNlLiAKCnByaW50KHRhYmxlX2RhdGEpCmBgYAoKRXhwbGFuYXRpb24gZm9yIFN0cmlrZSBwcmljZSBhbmQgcHV0IG9wdGlvbiBzZWxlY3Rpb246CldlIGJlbGlldmVkIHRoYXQgYSBjYWxsIG9wdGlvbiBmb3IgdGhlIEJyaXRpc2ggcG9uZCB3YXMgdGhlIG1vc3QgbG9naWNhbCBjaG9pY2UgZm9yIGEgY2FsbCBvcHRpb24sIHNpbmNlIGl0IHdvdWxkIGJlIHByb2ZpdGFibGUgdG8gY2FwaXRhbGl6ZSBvbiB0aGUgcG91bmQncyBhcHByZWNpYXRpb24uIEluZmFjdCwgb3V0IG9mIHRoZSB0aHJlZSBvcHRpb25zIGl0IHNpZ25hbGVkIHRoZSBzdHJvbmdlc3QgbWFya2V0IGNvbmZpZGVuY2UgYXMgd2VsbCBhcyBpdCdzIHN0cmVuZ3RoIGNvbXBhcmVkIHRvIG90aGVyIGN1cnJlbmNpZXMuIFNpbWlsYXIgdG8gdGhlIHByZXZpb3VzIHF1ZXN0aW9ucywgYSBzdHJpa2UgcHJpY2Ugb2YgMS4zMCBmcm9tIGEgcHJvamVjdGVkIGluY3JlYXNlIGZyb20gRW9UIGF0IDEuMzM3IHN1Z2dlc3RzIHRoZSBjYWxsIG9wdGlvbiB3b3VsZCBtb3N0IGxpa2VseSBlbmQgaW4gdGhlIG1vbmV5LiAKCkhvd2V2ZXIsIGlmIHdlIGFzc3VtZSB0aGF0IHRoZSBlbmQgb2YgdGVybSBpcyBEZWNlbWJlciwgdGhlbiBkdWUgdG8gdGhlIHNsaWdodCBkZXByZWNpYXRpb24gb2YgdGhlIHBvdW5kLCBrZWVwaW5nIHRoZSBzdHJpa2UgcHJpY2UgYXQgMS4zIHdpbGwgbm90IGJlIGlkZWFsLiAKCgojIFVzZSBjdXJyZW5jeSBvcHRpb25zIGRhdGEgKGlmIGF2YWlsYWJsZSkgdG8gc2VsZWN0IGEgcHV0IG9wdGlvbiBvbiBhIGZvcmVpZ24gY3VycmVuY3kgdGhhdCB5b3UgZXhwZWN0IHdpbGwgd2Vha2VuIGFnYWluc3QgdGhlIGRvbGxhciAoc2VsZWN0IHRoZSBvcHRpb24gd2l0aCB0aGUgZmlyc3QgZXhwaXJhdGlvbiBtb250aCBiZXlvbmQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0pOgoKQ3VycmVuY3k6TWV4aWNhbiBwZXNvIChNWE4pCgpFeHBpcmF0aW9uIG1vbnRoOiBEZWNlbWJlciAKClN0cmlrZSBwcmljZTogMC4wNTEKCgpgYGB7cn0KdGFibGVfZGF0YSA8LSBkYXRhLmZyYW1lKERlc2NyaXB0aW9uID0gY2hhcmFjdGVyKCksCiAgQm9UID0gbnVtZXJpYygpLAogIEVvVCA9IG51bWVyaWMoKSwKICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgphZGRfcm93IDwtIGZ1bmN0aW9uKGNhdGVnb3J5LCBCb1RfdmFsdWUsIEVvVF92YWx1ZSkgCiAge3RhYmxlX2RhdGEgPDwtcmJpbmQodGFibGVfZGF0YSwgZGF0YS5mcmFtZShDYXRlZ29yeSA9IGNhdGVnb3J5LAogICAgQm9UID0gQm9UX3ZhbHVlLAogICAgRW9UID0gRW9UX3ZhbHVlKSl9CgojIFBvcHVsYXRlIHRoZSB0YWJsZSB3aXRoIHJlbGV2YW50IGRhdGEKCmFkZF9yb3coIkN1cnJlbmN54oCZcyBleGlzdGluZyB2YWx1ZToiLCAwLjA1ODgsIDAuMDUwNikgIAphZGRfcm93KCJPcHRpb24gcHJlbWl1bSIsIE5BLCAwLjAwMTgpCgpwcmludCh0YWJsZV9kYXRhKQpgYGAKCkV4cGxhbmF0aW9uIGZvciBTdHJpa2UgcHJpY2UgYW5kIHB1dCBvcHRpb24gc2VsZWN0aW9uOgpPcHBvc2l0ZSB0byB0aGUgQnJpdGlzaCBQb3VuZCB0aGUgTWV4aWNhbiBQZXNvIHNob3dzIGEgY2xlYXIgd2Vha2VuaW5nIHRyZW5kIGFnYWluc3QgdGhlIFUuUy4gRG9sbGFyLiBBcyBhIHJlc3VsdCwgaXQgaXMgYW4gaWRlYWwgY2FuZGlkYXRlIGZvciBhIHB1dCBvcHRpb24uQm9UIHJhdGUgb2YgMC4wNTg4IGlzIGNsb3NlIHRvIG91ciBjaG9zZW4gc3RyaWtlIHByaWNlIG9mIDAuMDU4MCBpbiBvcmRlciB0byBlbnN1cmUgYSByZWFzb25hYmxlIHByZW1pdW0gY29zdCB3aXRob3V0IGJlaW5nIGV4cG9zZWQgdG8gbXVjaCByaXNrLiBUaGUgZXhjaGFuZ2UgcmF0ZSBpcyBwcm9qZWN0ZWQgdG8gZmFsbCBiZWxvdyAgMC4wNTA2LCB3aGljaCBpcyB3ZWxsIGJlbG93IHRoZSBzdHJpa2UgcHJpY2UsIG1lYW5pbmcgdGhhdCB0aGUgb3B0aW9uIGlzIGxpa2VseSB0byBlbmQgaW4gdGhlIG1vbmV5LiBXaGljaCBpcyBhZ2FpbiwgYmVjYXVzZSB0aGUgZnVydGhlciB0aGUgc3BvdCBwcmljZSBmYWxscyBiZWxvdyB0aGUgc3RyaWtlIHByaWNlLCB0aGUgbGFyZ2VyIHRoZSBpbnRyaW5zaWMgdmFsdWUgYW5kIHRoZSBoaWdoZXIgdGhlIHByb2ZpdC4KClRoZSBvcHRpb24gcHJlbWl1bSB2YWx1ZXMgd2VyZSB1c2VkIGZyb20gdGhlIGFzc3VtcHRpb24gdGhhdCB0aGUgb3B0aW9uIGV4cGlyZWQgaW4gRGVjZW1iZXIgZXZlbiB0aG91Z2ggd2Ugd2VyZSBjYWxjdWxhdGluZyBmb3IgdGhlIFNjaG9vbCB0ZXJtcy4gCgojIF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCgojICoqTDIgRmluYW5jaWFsIE1hcmtldHMgTWljcm9zdHJ1Y3R1cmUqKgoKIyBDb21wYXJlIHlvdXIgbmF0aW9uYWwgY291bnRyeSBsb2NhbCBleGNoYW5nZSBpbmRleCB3aXRoIFVTIG9yIExvbmRvbi4KCkluc3RhbGwgdGhlIG5lY2Vzc2FyeSBwYWNrYWdlcwoKTGV0J3MgY29tcGFyZSB0aGUgUyZQIDUwMCBhbmQgU2luZ2Fwb3JlIEV4Y2hhbmdlIEluZGV4LgoKYGBge3J9CiMgRG93bmxvYWQgaGlzdG9yaWNhbCBkYXRhIGZvciBTJlAgNTAwIGFuZCBTaW5nYXBvcmUgRXhjaGFuZ2UgSW5kZXgKZ2V0U3ltYm9scygiXkdTUEMiLCBzcmMgPSAieWFob28iKSAgIyBTJlAgNTAwCmdldFN5bWJvbHMoIl5TVEkiLCBzcmMgPSAieWFob28iKSAgICAjIFN0cmFpdHMgVGltZXMgSW5kZXggKFNHWCkKYGBgCgpUaGUgZGF0YSBmcm9tIDEgSmFudWFyeSAyMDEwIHRvIDEgSmFudWFyeSAyMDIzIHdpbGwgYmUgdHJpbW1lZCBhbmQgY2xlYW5lZC4KCmBgYHtyfQojIEZpbGwgaW4gTkEgd2l0aCBhbiBhcHByb3hpbWF0aW9uIGRhdGEKU1RJIDwtIG5hLmFwcHJveChTVEkpCmBgYAoKYGBge3J9CiMgRmlsbCBpbiBOQSB3aXRoIGFuIGFwcHJveGltYXRpb24gZGF0YQpTVEkgPC0gbmEuYXBwcm94KFNUSSkKYGBgCgpgYGB7cn0KIyBUcmltIGRhdGEgZm9yIHRoZSBjb21wYXJpc29uIHBlcmlvZApzdGFydF9kYXRlIDwtICIyMDEwLTAxLTAxIgplbmRfZGF0ZSA8LSAiMjAyMy0wMS0wMSIKR1NQQyA8LSBzdWJzZXQoR1NQQywgaW5kZXgoR1NQQykgPj0gc3RhcnRfZGF0ZSAmIGluZGV4KEdTUEMpIDw9IGVuZF9kYXRlKQpTVEkgPC0gc3Vic2V0KFNUSSwgaW5kZXgoU1RJKSA+PSBzdGFydF9kYXRlICYgaW5kZXgoU1RJKSA8PSBlbmRfZGF0ZSkKYGBgCgpgYGB7cn0KIyBDaGVjayBpZiB0aGUgZGF0YSBpcyB3ZWxsIHRyaW1tZWQKcHJpbnQoR1NQQ1tyb3duYW1lcyhHU1BDKSA+PSAiMjAxMC0wMS0wMSIgJiByb3duYW1lcyhHU1BDKSA8PSAiMjAxMC0wMS0wMiIsIF0pCnByaW50KFNUSVtyb3duYW1lcyhTVEkpID49ICIyMDEwLTAxLTAxIiAmIHJvd25hbWVzKFNUSSkgPD0gIjIwMTAtMDEtMDIiLCBdKQpgYGAKCmBgYHtyfQojIE1lcmdlIHRoZSBkYXRhc2V0cwphbGlnbmVkX2RhdGEgPC0gbWVyZ2UoR1NQQywgU1RJKQpgYGAKCmBgYHtyfQojIFJlbW92ZSBtaXNzaW5nIHZhbHVlcyAKY2xlYW5lZF9kYXRhIDwtIG5hLm9taXQoYWxpZ25lZF9kYXRhKQpgYGAKCkFmdGVyIGRhdGEgaXMgY2xlYW5uZWQgYW5kIHRyaW1tZWQsIHdlIGNhbiBub3cgY29tcGFyZSB0aGUgc3RhdGlzdGljcyBiZXR3ZWVuIHRoZSBTJlAgNTAwIGFuZCBTaW5nYXBvcmUgRXhjaGFuZ2UgSW5kZXgKCmBgYHtyfQojIENhbGN1bGF0ZSBzdGF0aXN0aWNzIGZvciBTJlAgNTAwCm5hc2RhcV9zdGF0cyA8LSBjKG1lYW4oR1NQQ1ssIDRdLCBuYS5ybSA9IFRSVUUpLCAKICAgICAgICAgICAgICAgICAgbWVkaWFuKEdTUENbLCA0XSwgbmEucm0gPSBUUlVFKSwgCiAgICAgICAgICAgICAgICAgIHNkKEdTUENbLCA0XSwgbmEucm0gPSBUUlVFKSkgIAoKIyBDYWxjdWxhdGUgc3RhdGlzdGljcyBmb3IgU2luZ2Fwb3JlIEV4Y2hhbmdlIChTR1gpCnNneF9zdGF0cyA8LSBjKG1lYW4oU1RJWywgNF0sIG5hLnJtID0gVFJVRSksIAogICAgICAgICAgICAgICBtZWRpYW4oU1RJWywgNF0sIG5hLnJtID0gVFJVRSksIAogICAgICAgICAgICAgICBzZChTVElbLCA0XSwgbmEucm0gPSBUUlVFKSkgCgojIENhbGN1bGF0ZSBDb2VmZmljaWVudCBvZiBWYXJpYXRpb24gZm9yIFMmUCA1MDAgYW5kIFNHWApjdl9uYXNkYXEgPC0gbmFzZGFxX3N0YXRzWzNdIC8gbmFzZGFxX3N0YXRzWzFdICogMTAwIApjdl9zZ3ggPC0gc2d4X3N0YXRzWzNdIC8gc2d4X3N0YXRzWzFdICogMTAwIAoKIyBBZGQgQ29lZmZpY2llbnQgb2YgVmFyaWF0aW9uIHRvIHN0YXRpc3RpY3MKbmFzZGFxX3N0YXRzIDwtIGMobmFzZGFxX3N0YXRzLCBjdl9uYXNkYXEpCnNneF9zdGF0cyA8LSBjKHNneF9zdGF0cywgY3Zfc2d4KQoKIyBDb21iaW5lIHN0YXRpc3RpY3MgaW50byBhIHNpbmdsZSBkYXRhIGZyYW1lCnN0YXRzX2NvbXBhcmlzb24gPC0gcmJpbmQobmFzZGFxX3N0YXRzLCBzZ3hfc3RhdHMpCgojIE5hbWUgdGhlIGNvbHVtbnMKY29sbmFtZXMoc3RhdHNfY29tcGFyaXNvbikgPC0gYygiTWVhbiIsICJNZWRpYW4iLCAiU3RhbmRhcmQgRGV2aWF0aW9uIiwgIkNvZWZmaWNpZW50IG9mIFZhcmlhdGlvbiIpCgojIE5hbWUgdGhlIHJvd3MKcm93bmFtZXMoc3RhdHNfY29tcGFyaXNvbikgPC0gYygiUyZQIDUwMCIsICJTaW5nYXBvcmUgRXhjaGFuZ2UgKFNHWCkiKQoKIyBQcmludCB0aGUgcm91bmRlZCByZXN1bHQKcHJpbnQocm91bmQoc3RhdHNfY29tcGFyaXNvbiwgMikpCmBgYAoKQXMgdGhlIFMmUCA1MDAgaGFzIGEgY29lZmZpY2llbnQgb2YgdmFyaWF0aW9uIHRoYXQgaXMgYWxtb3N0IDQgdGltZXMgdGhhdCBvZiB0aGUgU0dYLCB3ZSBjYW4gY29uY2x1ZGUgdGhhdCB0aGUgUyZQIDUwMCBpcyBtb3JlIHZvbGF0aWxlIGFuZCByaXNraWVyIHRoYW4gdGhlIFNHWC4gQSBoaWdoZXIgY29lZmZpY2llbnQgb2YgdmFyaWF0aW9uIHJlZmxlY3RzIGdyZWF0ZXIgdW5jZXJ0YWludHkgaW4gdGhlIFMmUCA1MDDigJlzIHBlcmZvcm1hbmNlLCBtZWFuaW5nIHRoYXQgaXRzIHJldHVybnMgYXJlIG1vcmUgbGlrZWx5IHRvIGRldmlhdGUgZnJvbSBpdHMgYXZlcmFnZSB2YWx1ZS4gSW52ZXN0b3JzIGluIHRoZSBTJlAgNTAwIGNhbiBleHBlY3QgbGFyZ2VyIGRldmlhdGlvbnMgZnJvbSB0aGUgbWVhbiwgZWl0aGVyIGluIHRoZSBmb3JtIG9mIGxhcmdlIGdhaW5zIG9yIHNpZ25pZmljYW50IGxvc3Nlcy4gU0dYJ3MgbG93ZXIgY29lZmZpY2llbnQgb2YgdmFyaWF0aW9uIGltcGxpZXMgZ3JlYXRlciBzdGFiaWxpdHkgYW5kIHByZWRpY3RhYmlsaXR5IGluIGl0cyByZXR1cm5zLiBJdCBpcyBsZXNzIHZvbGF0aWxlLCBtYWtpbmcgaXQgYSBzYWZlciBjaG9pY2UgZm9yIGludmVzdG9ycyB3aG8gcHJpb3JpdGl6ZSBjb25zaXN0ZW50IHBlcmZvcm1hbmNlIGFuZCBhcmUgcmlzay1hdmVyc2UuIEludmVzdG9ycyBzaG91bGQgYXNzZXNzIHRoZWlyIHJpc2sgdG9sZXJhbmNlIHdoZW4gY2hvb3NpbmcgYmV0d2VlbiB0aGVzZSBpbmRpY2VzLiBJZiBhbiBpbnZlc3RvciBwcmVmZXJzIGhpZ2hlciBwb3RlbnRpYWwgcmV0dXJucyBhbmQgaXMgY29tZm9ydGFibGUgd2l0aCBtb3JlIHZvbGF0aWxpdHksIHRoZSBTJlAgNTAwIG1pZ2h0IGJlIG1vcmUgYXBwZWFsaW5nLiBDb252ZXJzZWx5LCBpZiBhbiBpbnZlc3RvciBwcmVmZXJzIHN0YWJpbGl0eSBhbmQgbG93ZXIgdm9sYXRpbGl0eSwgdGhlIFNHWCBtaWdodCBiZSBhIGJldHRlciBvcHRpb24uCgpMZXQgdXMgY29tcGFyZSB0aGUgY3VtdWxhdGl2ZSByZXR1cm5zIGJldHdlZW4gdGhlIFMmUCA1MDAgYW5kIFNHWCBmcm9tIDIwMTAgdG8gMjAyMy4KCmBgYHtyfQojIENoZWNrIHRoZSBmaXJzdCBmZXcgcm93cyB0byB2ZXJpZnkgZGF0YQpoZWFkKEdTUEMpCmhlYWQoU1RJKQpgYGAKCkZpcnN0LCB3ZSBjYWxjdWxhdGUgdGhlIGRhaWx5IHJldHVybnMgb2YgUyZQNTAwIGFuZCBTR1guCgpgYGB7cn0KIyBDYWxjdWxhdGUgZGFpbHkgcmV0dXJucyBmb3IgYm90aCBpbmRpY2VzCkdTUENfcmV0dXJucyA8LSBkYWlseVJldHVybihHU1BDKQpTVElfcmV0dXJucyA8LSBkYWlseVJldHVybihTVEkpCmBgYAoKTmV4dCwgd2UgY2FsY3VsYXRlIHRoZSBjdW11bGF0aXZlIHJldHVybnMgb2YgUyZQNTAwIGFuZCBTR1guCgpgYGB7cn0KIyBDYWxjdWxhdGUgY3VtdWxhdGl2ZSByZXR1cm5zIApHU1BDX2N1bXVsYXRpdmVfcmV0dXJucyA8LSBjdW1zdW0oR1NQQ19yZXR1cm5zKQpTVElfY3VtdWxhdGl2ZV9yZXR1cm5zIDwtIGN1bXN1bShTVElfcmV0dXJucykKYGBgCgpGaW5hbGx5LCB3ZSBjYW4gY29tcGFyZSB0aGVtIHdpdGggYSBsaW5lIGdyYXBoLgoKYGBge3J9CnBsb3QoaW5kZXgoR1NQQ19jdW11bGF0aXZlX3JldHVybnMpLCBHU1BDX2N1bXVsYXRpdmVfcmV0dXJucywgdHlwZSA9ICJsIiwgY29sID0gImJsdWUiLCAKICAgICB4bGFiID0gIkRhdGUiLCB5bGFiID0gIkN1bXVsYXRpdmUgUmV0dXJucyIsIG1haW4gPSAiQ3VtdWxhdGl2ZSBSZXR1cm5zOiBTJlAgNTAwIHZzIFNHWCAoMjAxMC0yMDIzKSIpCmxpbmVzKGluZGV4KFNUSV9jdW11bGF0aXZlX3JldHVybnMpLCBTVElfY3VtdWxhdGl2ZV9yZXR1cm5zLCBjb2wgPSAicmVkIikKbGVnZW5kKCJ0b3BsZWZ0IiwgbGVnZW5kID0gYygiUyZQIDUwMCIsICJTR1giKSwgY29sID0gYygiYmx1ZSIsICJyZWQiKSwgbHR5ID0gMSkKYGBgCgpGcm9tIDIwMTAgdG8gMjAyMCwgdGhlIGN1bXVsYXRpdmUgcmV0dXJucyBvZiB0aGUgUyZQIDUwMCBoYXMgZXhwZXJpZW5jZWQgc2lnbmlmaWNhbnQgZ3Jvd3RoLiBIb3dldmVyLCB0aGUgY3VtdWxhdGl2ZSByZXR1cm5zIG9mIHRoZSBTR1ggaGF2ZSByZW1haW5lZCBsYXJnZWx5IGZsYXQsIHNob3dpbmcgbGl0dGxlIG1vdmVtZW50IG92ZXIgdGhlIHBhc3QgZGVjYWRlLiBBcyBzdWNoLCB3ZSBjYW4gY29uY2x1ZGUgdGhhdCBpbnZlc3RpbmcgaW4gdGhlIFMmUCA1MDAgZ2VuZXJhdGVzIGEgaGlnaGVyIHJldHVybiBjb21wYXJlZCB0byB0aGUgU0dYLgoKSGVyZSwgdGhlIGN1bXVsYXRpdmUgcmVzdWx0cyBhcmUgaW1wb3J0YW50IGJlY2F1c2UgdGhleSBzaG93IGhvdyBzdHJ1Y3R1cmFsIGRpZmZlcmVuY2VzLCBzdWNoIGFzIHNlY3RvciBjb21wb3NpdGlvbiBhbmQgZ3Jvd3RoIGVuZ2luZXMsIGFmZmVjdCB0aGUgcmV0dXJucyBvZiBlYWNoIGluZGV4IGluIHRoZSBsb25nIHJ1bi4gRm9yIGV4YW1wbGUsIHRoZSBzdHJlbmd0aCBvZiB0aGUgUyZQIDUwMCBpbmRleCBjYW4gYmUgYXR0cmlidXRlZCB0byB0aGUgZWNvbm9taWMgcmVjb3Zlcnkgc2luY2UgMjAwOCBhbmQgdGhlIHJpc2Ugb2YgdGVjaCBnaWFudHMgc3VjaCBhcyBBcHBsZSwgQW1hem9uLCBhbmQgTWljcm9zb2Z0LiBUaGVzZSBzZWN0b3JzIGhhdmUgZHJpdmVuIGNvbnRpbnVlZCBncm93dGggYW5kIGhpZ2ggcmV0dXJucy4gT24gdGhlIG90aGVyIGhhbmQsIFNHWCdzIGZsYXQgY3VtdWxhdGl2ZSByZXR1cm5zIG92ZXIgdGhlIHNhbWUgcGVyaW9kIGdlbmVyYWxseSByZWZsZWN0IGl0cyByZWxpYW5jZSBvbiBmaW5hbmNlLCByZWFsIGVzdGF0ZSwgYW5kIHJhdyBtYXRlcmlhbHMgdGhhdCBoYXZlIG5vdCBleHBlcmllbmNlZCB0aGUgc2FtZSBleHBsb3NpdmUgZ3Jvd3RoIGFzIHRoZSBVLlMuIHRlY2ggc2VjdG9yLgoKVGh1cywgd2UgYmVsaWV2ZSB0aGF0IHRoZSBzdHJvbmcgZ293dGggaW4gdGhlIFMmUCA1MDAgd2FzIGRyaXZlbiBieSBzdHJvbmcgZWNvbm9taWMgcmVjb3ZlcnkgcG9zdC0yMDA4IGZpbmFuY2lhbCBjcmlzaXMgYW5kIHRoZSByaXNlIG9mIHRlY2hub2xvZ3kgY29tcGFuaWVzIGxpa2UgQXBwbGUsIEFtYXpvbiwgYW5kIE1pY3Jvc29mdC4gT24gdGhlIG90aGVyIGhhbmQsIFNHWOKAmXMgcGVyZm9ybWFuY2Ugd2FzIGNvbnN0cmFpbmVkIGJ5IGl0cyBzZWN0b3IgY29tcG9zaXRpb24sIHdoaWNoIGlzIGRvbWluYXRlZCBieSBmaW5hbmNpYWxzLCByZWFsIGVzdGF0ZSwgYW5kIGNvbW1vZGl0aWVzLCBzZWN0b3JzIHRoYXQgZ2VuZXJhbGx5IGRpZCBub3QgZXhwZXJpZW5jZSB0aGUgc2FtZSBleHBsb3NpdmUgZ3Jvd3RoIGFzIHRoZSBVLlMuIHRlY2ggc2VjdG9yLiBUaGVyZWZvcmUsIHdoaWxlIHRoZSBTR1ggcHJvdmlkZXMgc3RhYmlsaXR5IGFuZCBsb3dlciB2b2xhdGlsaXR5LCBpdCBsYWNrZWQgdGhlIGdyb3d0aCBkcml2ZXJzIHRoYXQgcHJvcGVsbGVkIHRoZSBTJlAgNTAwIHRvIGhpZ2hlciByZXR1cm5zLiBBcyBzdWNoLCB0aGUgUyZQIDUwMCBjbGVhcmx5IG91dHBlcmZvcm1lZCB0aGUgU0dYLCBvZmZlcmluZyBoaWdoZXIgY2FwaXRhbCBhcHByZWNpYXRpb24gYW5kIG92ZXJhbGwgcmV0dXJucyBmb3IgaW52ZXN0b3JzIHdpbGxpbmcgdG8gYWNjZXB0IGl0cyBpbmhlcmVudCB2b2xhdGlsaXR5LgoKCiMgX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KCiMgKipMMyBJbnN0cnVtZW504oCZcyBvdmVydmlldyBhbmQgdmFsdWF0aW9uKioKCioqTDMuMSoqCgpXZSBhcmUgZ29pbmcgdG8gZmluZCBhbmQgY29tcGFyZSB0aGUgMTMtd2VlayB0cmVhc3VyeSBiaWxsIHJhdGVzIGF0IHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtbSBhbmQgY29tcGFyZSB0byB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzY2hvb2wgdGVybS4KYGBge3J9CmxpYnJhcnkocXVhbnRtb2QpCmdldFN5bWJvbHMoIlRCM01TIiwgc3JjID0gIkZSRUQiKQpgYGAKVGhlc2UgYXJlIHRoZSBtb250aGx5IHB1Ymxpc2hlZCAzLW1vbnRoIHRyZWFzdXJ5IGJpbGwgc2Vjb25kYXJ5IG1hcmtldCByYXRlcwoKV2Ugd2lsbCBmaXJzdCBmaW5kIHRoZSBtb250aGx5IGF2ZXJhZ2UgZm9yIHRoZSBlbmQgb2YgdGVybSBhdCBTZXB0ZW1iZXIgMjAyNC4KYGBge3J9CkVvVF9SYXRlIDwtIFRCM01TWyIyMDI0LTA5LTEiXQpwcmludChFb1RfUmF0ZSkKYGBgCgpXZSB3aWxsIG5vdyBmaW5kIHRoZSBtb250aGx5IGF2ZXJhZ2UgbW9udGhseSByYXRlIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHNjaG9vbCB0ZXJtIGF0IE1heSAyMDI0LgpgYGB7cn0KQm9UX1JhdGUgPC0gVEIzTVNbIjIwMjQtMDUtMSJdCnByaW50KEJvVF9SYXRlKQpgYGAKQ29tcGFyaW5nIHRoZSByYXRlcyB3ZSBzZWUgdGhhdCBhdCB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybSwgdGhlIGludGVyZXN0IHJhdGUgaXMgMC41MyBwZXJjZW50YWdlIHBvaW50cyBsb3dlciB0aGFuIHRoZSBiZWdpbm5pbmcgb2YgdGhlIHNjaG9vbCB0ZXJtLgoKKipMMy4yKioKCkludGVyZXN0IHJhdGVzIGNoYW5nZSBvdmVyIHRpbWUgZm9yIGEgbnVtYmVyIG9mIHJlYXNvbnM6CgpGaXJzdGx5LCB0aGUgZmVkZXJhbCByZXNlcnZlIHNldCBiZW5jaG1hcmsgaW50ZXJlc3QgcmF0ZXMuIFRoaXMgaXMgdG8gY29udHJvbCBpbmZsYXRpb24gYW5kIHRvIGluZmx1ZW5jZSBlY29ub21pYyBhY3Rpdml0eSwgd2l0aCBsb3dlciByYXRlcyBlbmNvdXJhZ2luZyBlY29ub21pYyBwYXJ0aWNpcGF0aW9uLCBhbmQgaGlnaGVyIHJhdGVzIGF0dGVtcHRpbmcgdG8gY29udHJvbCBpbmZsYXRpb24gYW5kIHNsb3cgZG93biB0aGUgZWNvbm9teS4KCldpdGggcmVzcGVjdCB0byBpbmZsYXRpb24uIEhpZ2hlciBpbmZsYXRpb24gY2F1c2VzIG1vbmV5IHRvIGxvc2UgcHVyY2hhc2luZyBwb3dlciwgc28gbGVuZGVycyBkZW1hbmQgaGlnaGVyIGludGVyZXN0IHJhdGVzIHRvIG9mZnNldCB0aGUgY29zdC4gCgpBbm90aGVyIHJlYXNvbiBjYW4gYmUgZ2xvYmFsIGNyaXNlcyBvciBlY29ub21pYyB1bmNlcnRhaW50eS4gU2hvY2tzIHRvIHRoZSBlY29ub215IG9yIHVuY2VydGFpbnR5IGFib3V0IHRoZSBmdXR1cmUgY2FuIGRyb3AgaW50ZXJlc3QgcmF0ZXMgYXMgaW52ZXN0b3JzIGZsb2NrIHRvIHNhZmUgYXNzZXRzIHN1Y2ggYXMgdHJlYXN1cnkgYmlsbHMuCgpSZWxhdGluZyB0byB0aGUgdHJlYXN1cnkgYmlsbCByYXRlcy4gVHJlYXN1cnkgYmlsbCBzaG9ydCB0ZXJtIHJhdGVzIGFyZSBvZnRlbiBjbG9zZWx5IGxpbmtlZCB0byBpbnRlcmVzdCByYXRlcyBhcyB0aGVpciBkZW1hbmQgaXMgZGV0ZXJtaW5lZCBieSBpbnZlc3RvciBzZW50aW1lbnQgYWJvdXQgdGhlIG1hcmtldC4KCgojIF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCgojICoqTDQgRWZmaWNpZW5jeSBvZiBtYXJrZXQgYW5kIGluZm9ybWF0aW9uKioKCkNoZWNrIGlmIG9uIDI2IE9jdG9iZXIgMjAxNyBjb2NhIGNvbGEgc2hhcmVzIHdlcmUgaGl0IGJ5IHRoZSBhZHZlcnNlIGluZm9ybWF0aW9uIHJlYWxpemUgb24gdGhlIG1hcmtldC4gKGFzc3VtZSAyNiBpcyB0aGUgaW5mb3JtYXRpb24gcmVsZWFzZSBkYXRlKQoKYGBge3J9CmxpYnJhcnkocXVhbnRtb2QpCmxpYnJhcnkoZ2dwbG90MikKYGBgCgpgYGB7cn0KIyBEb3dubG9hZCBoaXN0b3JpY2FsIGRhdGEgZm9yIEtPIGZyb20gMjAxNy0xMC0wMSB0byAyMDE3LTExLTAxCmdldFN5bWJvbHMoIktPIiwgZnJvbSA9ICIyMDE3LTEwLTAxIiwgdG8gPSAiMjAxNy0xMS0wMSIpCmBgYAoKYGBge3J9CiMgU2V0IHRoZSBldmVudCBkYXRlCmV2ZW50X2RhdGUgPC0gIjIwMTctMTAtMjYiCmBgYAoKYGBge3J9CiMgQ2FsY3VsYXRlIHRoZSBsb2cgcmV0dXJucyBvZiBLTyBBZGp1c3RlZCBwcmljZXMKS09fcmV0dXJucyA8LSBkaWZmKGxvZyhLTyRLTy5BZGp1c3RlZCkpCmBgYAoKYGBge3J9CiMgQ3JlYXRlIHRoZSBldmVudCBkdW1teSB2YXJpYWJsZSAoMSBmb3IgZXZlbnQgZGF0ZSwgMCBvdGhlcndpc2UpCmV2ZW50X2R1bW15IDwtIGlmZWxzZShpbmRleChLT19yZXR1cm5zKSA9PSBldmVudF9kYXRlLCAxLCAwKQpgYGAKCmBgYHtyfQojIFJ1biB0aGUgZXZlbnQgc3R1ZHkgcmVncmVzc2lvbiBtb2RlbCAoZXhjbHVkaW5nIHRoZSBmaXJzdCBlbGVtZW50IGZvciBsYWcpCmV2ZW50X3N0dWR5IDwtIGxtKEtPX3JldHVybnNbLTFdIH4gZXZlbnRfZHVtbXlbLTFdKQpgYGAKCmBgYHtyfQojIERpc3BsYXkgdGhlIHN1bW1hcnkgb2YgdGhlIGV2ZW50IHN0dWR5IG1vZGVsCnN1bW1hcnkoZXZlbnRfc3R1ZHkpCmBgYAoKYGBge3J9CiMgU2V0IHRoZSBldmVudCBkYXRlIChPY3RvYmVyIDI2LCAyMDE3KQpldmVudF9kYXRlIDwtICIyMDE3LTEwLTI2IgoKIyBDYWxjdWxhdGUgdGhlIGxvZyByZXR1cm5zIG9mIEtPIEFkanVzdGVkIHByaWNlcwpLT19yZXR1cm5zIDwtIGRpZmYobG9nKEtPJEtPLkFkanVzdGVkKSkKCiMgRGVmaW5lIHRoZSBldmVudCB3aW5kb3cgKC0yIHRvICsyIGRheXMgYXJvdW5kIHRoZSBldmVudCkKZXZlbnRfd2luZG93IDwtIGMoLTIsIDIpCgojIEdldCB0aGUgbnVtZXJpYyBwb3NpdGlvbiBvZiB0aGUgZXZlbnQgZGF0ZSBpbiB0aGUgcmV0dXJucyB2ZWN0b3IKcG96IDwtIG1hdGNoKGFzLkRhdGUoZXZlbnRfZGF0ZSksIGluZGV4KEtPX3JldHVybnMpKQoKIyBEZWZpbmUgdGhlIHN0YXJ0IGFuZCBlbmQgb2YgdGhlIGV2ZW50IHdpbmRvdwp3X2JlZyA8LSBwb3ogKyBldmVudF93aW5kb3dbMV0Kd19lbmQgPC0gcG96ICsgZXZlbnRfd2luZG93WzJdCgojIERlZmluZSB0aGUgZXZlbnQgZHVtbXkgZm9yIHRoZSBldmVudCB3aW5kb3cgKDEgZm9yIGV2ZW50IHdpbmRvdywgMCBvdGhlcndpc2UpCmV2ZW50X2R1bW15IDwtIHJlcCgwLCBsZW5ndGgoS09fcmV0dXJucykpICAjIEluaXRpYWxpemUgdGhlIGR1bW15IHZhcmlhYmxlCmV2ZW50X2R1bW15W3dfYmVnOndfZW5kXSA8LSAxICAjIFNldCB0aGUgZXZlbnQgd2luZG93IHRvIDEKCiMgQ2FsY3VsYXRlIEN1bXVsYXRpdmUgQWJub3JtYWwgUmV0dXJucyAoQ0FSKSBvdmVyIHRoZSBldmVudCB3aW5kb3cKQ0FSIDwtIGN1bXN1bShLT19yZXR1cm5zWy0xXSAqIGV2ZW50X2R1bW15Wy0xXSlbKHdfYmVnIC0gMSk6KHdfZW5kIC0gMSldCgojIFRlc3QgZm9yIHNpZ25pZmljYW5jZSAodC1zdGF0aXN0aWMgYW5kIHAtdmFsdWUpCnRfc3RhdCA8LSBDQVJbbGVuZ3RoKENBUildIC8gc2QoQ0FSKSAvIHNxcnQobGVuZ3RoKENBUikpCnBfdmFsdWUgPC0gMiAqIHB0KC1hYnModF9zdGF0KSwgZGYgPSBsZW5ndGgoQ0FSKSAtIDEpCgojIFByaW50IHRoZSByZXN1bHRzCmNhdCgiQ3VtdWxhdGl2ZSBBYm5vcm1hbCBSZXR1cm46IiwgQ0FSW2xlbmd0aChDQVIpXSwgIlxuIikKY2F0KCJ0LXN0YXRpc3RpYzoiLCB0X3N0YXQsICJcbiIpCmNhdCgicC12YWx1ZToiLCBwX3ZhbHVlLCAiXG4iKQpgYGAKClRoZSBDdW11bGF0aXZlIEFibm9ybWFsIFJldHVybiBvdmVyIHRoZSBldmVudCB3aW5kb3cgaXMgbmVnYXRpdmUgYXQgLTAuOTk4JS4gVGhpcyBzdWdnZXN0ZXMgdGhhdCBDb2NhLUNvbGHigJlzIHN0b2NrIHVuZGVycGVyZm9ybWVkIHJlbGF0aXZlIHRvIGl0cyBleHBlY3RlZCByZXR1cm4gZHVyaW5nIHRoaXMgcGVyaW9kLiBXaGlsZSB0aGlzIG5lZ2F0aXZlIENBUiBpbmRpY2F0ZXMgYSBwb3RlbnRpYWwgYWR2ZXJzZSBtYXJrZXQgcmVhY3Rpb24gdG8gdGhlIGluZm9ybWF0aW9uIHJlbGVhc2VkIG9uIE9jdG9iZXIgMjYsIDIwMTcsIGl0IGlzIGVzc2VudGlhbCB0byBldmFsdWF0ZSBpdHMgc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlIHRvIGNvbmZpcm0gd2hldGhlciB0aGUgZXZlbnQgaGFkIGEgbWVhbmluZ2Z1bCBpbXBhY3QuCgpUaGUgVC1zdGF0aXN0aWMgcGxheXMgYSBrZXkgcm9sZSBoZXJlLiBCYXNlZCB1bmRlciB0aGUgbnVsbCBoeXBvdGhlc2lzLCBpdCBtZWFzdXJlcyBob3cgZmFyIHRoZSBvYnNlcnZlZCBDQVIgZGV2aWF0ZXMgZnJvbSB6ZXJvIHJlbGF0aXZlIHRvIGl0cyBzdGFuZGFyZCBlcnJvci4gQSBoaWdoIFQtc3RhdGlzdGljIHdpdGggdGhlIGFic29sdXRlIHZhbHVlIGV4Y2VlZGluZyBhIGNyaXRpY2FsIHRocmVzaG9sZCAoZm9yIGV4YW1wbGUsIDk1JSBjb25maWRlbmNlIGxldmVsKSB3b3VsZCBpbmRpY2F0ZSB0aGF0IHRoZSBDQVIgaXMgdW5saWtlbHkgdG8gaGF2ZSBvY2N1cnJlZCBieSBjaGFuY2UuIFRoZXJlZm9yZSwgaXQgc3VnZ2VzdHMgYSBzaWduaWZpY2FudCBtYXJrZXQgaW1wYWN0LiBIb3dldmVyIGluIHRoaXMgY2FzZSwgdGhlIFQtc3RhdGlzdGljIGlzIGxvdywgYW5kIHRoZSBwLXZhbHVlIGlzIGdyZWF0ZXIgdGhhbiAwLjA1LiBUaGlzIG1lYW5zIHRoZSBudWxsIGh5cG90aGVzaXMgY2Fubm90IGJlIHJlamVjdGVkIFRoaXMgaW1wbGllcyB0aGF0IHRoZSBhZHZlcnNlIGluZm9ybWF0aW9uIHJlbGVhc2Ugb24gT2N0b2JlciAyNiwgMjAxNywgZGlkIG5vdCBjYXVzZSBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgYWJub3JtYWwgcmV0dXJuLgoKV2hpbGUgdGhlIGN1bXVsYXRpdmUgbmF0dXJlIG9mIENBUiBpcyBpbXBvcnRhbnQgZm9yIGFzc2Vzc2luZyB0aGUgb3ZlcmFsbCBpbXBhY3QgYWNyb3NzIHRoZSBldmVudCB3aW5kb3csIGl0cyBpbnRlcnByZXRhdGlvbiBtdXN0IGJlIHN1cHBvcnRlZCBieSBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UuIFdpdGhvdXQgYSBzaWduaWZpY2FudCBULXN0YXRpc3RpYywgdGhlIG9ic2VydmVkIENBUiBjb3VsZCBzaW1wbHkgcmVmbGVjdCByYW5kb20gbWFya2V0IGZsdWN0dWF0aW9ucyByYXRoZXIgdGhhbiBhIHRydWUgcmVhY3Rpb24gdG8gdGhlIGV2ZW50LiBUbyBzdW0gdXAsIGFsdGhvdWdoIHRoZSBDQVIgaXMgbmVnYXRpdmUsIHRoZSBULXN0YXRpc3RpYyBzaG93cyB0aGUgcmVzdWx0IGlzIG5vdCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LiBUaGlzIHN1Z2dlc3RzIHRoZSBldmVudCBkaWQgbm90IGhhdmUgYSBtZWFzdXJhYmxlIGltcGFjdCBvbiBDb2NhLUNvbGHigJlzIHN0b2NrIHByaWNlLgoKCiMgX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KCiMgKipMNSBGaW5hbmNpYWwgc3RhdGVtZW50cyBhbmQgZnVuZGFtZW50YWwgYW5hbHlzaXMqKgoqKkRvd25sb2FkIHRvIFIgdGhlIGZpbmFuY2lhbCBzdGF0ZW1lbnRzIG9mIE1pY3Jvc29mdCAyMDE4LCBzaG93IHRoZSBjb2RlKioKRG93bmxvYWQgdGhlIG5lY2Vzc2FyeSBwYWNrYWdlcyBhbmQgcmV0cmlldmUgdGhlIGFubnVhbCByZXBvcnQgb2YgTWljcm9zb2Z0IDIwMTgKCmBgYHtyfQppbnN0YWxsLnBhY2thZ2VzKCd0aWR5cicpCmxpYnJhcnkodGlkeXIpCiMgc2V0IHVwIHRoZSBhdXRob3JpdHkgdG8gRWRnYXIgICAgIApvcHRpb25zKEhUVFBVc2VyQWdlbnQgPSAia3cxMzc0NjVAc3R1ZGVudC5zZ2gud2F3LnBsIikgCiMgR2V0IGZpbmFuY2lhbCAgICAgIApBbm51YWxSZXBvcnRzKDAwMDA3ODkwMTksIGZvcmVpZ24gPSBGQUxTRSkgCmBgYAoKIyBDb21tZXJjaWFsIGJhbmsgb3BlcmF0aW9ucwoKCioqV2UgaGF2ZSBzZWxlY3RlZCBKUE1vcmdhbiBDaGFzZSAmIENvLiBhcyBvdXIgY29tbWVyY2lhbCBiYW5rIGFuZCBkZXJpdmVkIG91ciBhbmFseXNpcyBmcm9tIHRoZSAxMC1rIGFubnVhbCByZXBvcnQgb2YgSlBNIDIwMjMgZnJvbSBFREdBUiB0byBhbnN3ZXIgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnM6KioKCgoqKkw1LjEgSWRlbnRpZnkgdGhlIHR5cGVzIG9mIGRlcG9zaXRzIHRoYXQgdGhlIGNvbW1lcmNpYWwgYmFuayB1c2VzIHRvIG9idGFpbiBtb3N0IG9mIGl0cyBmdW5kcy4qKgoKVGhlIHR5cGVzIG9mIGRlcG9zaXRzIHRoYXQgSlBNIHVzZXMgdG8gb2J0YWluIG1vc3Qgb2YgaXRzIGZ1bmRzIGlzIHRpbWUgZGVwb3NpdHMuCgoqKkw1LjIgSWRlbnRpZnkgdGhlIG1haW4gdXNlcyBvZiBmdW5kcyBieSB0aGUgYmFuay4gYy4gU3VtbWFyaXplIGFueSBzdGF0ZW1lbnRzIG1hZGUgYnkgdGhlIGNvbW1lcmNpYWwgYmFuayBpbiBpdHMgYW5udWFsIHJlcG9ydCBhYm91dCBob3cgcmVjZW50IG9yIHBvdGVudGlhbCByZWd1bGF0aW9ucyB3aWxsIGFmZmVjdCBpdHMgcGVyZm9ybWFuY2UuKioKClRoZSBtYWluIHVzZXMgb2YgZnVuZHMgaW5jbHVkZSBzZWN1cml0aWVzIGludmVzdG1lbnQgYW5kIGxvYW5zLgpUaGUgVm9sY2tlciBSdWxlLCB3aGljaCByZXN0cmljdHMgYmFua3MgZnJvbSBlbmdhZ2luZyBpbiBwcm9wcmlldGFyeSB0cmFkaW5nIGlzIGFuIGltcG9ydGFudCByZWd1bGF0aW9uIGFmZmVjdGluZyBKUE1vcmdhbuKAmXMgaW52ZXN0bWVudCBiYW5raW5nIGFuZCB0cmFkaW5nIGFjdGl2aXRpZXMuIEpQTW9yZ2FuIGhhcyB0YWtlbiBzdGVwcyB0byBlbnN1cmUgY29tcGxpYW5jZSB3aXRoIHRoZSBydWxlLCB3aGljaCBjYW4gaW1wYWN0IGl0cyBwcm9wcmlldGFyeSB0cmFkaW5nIGFjdGl2aXRpZXMgYW5kIHJlZHVjZSB0aGUgYW1vdW50IG9mIGNhcGl0YWwgaXQgY2FuIGRlcGxveSBpbiBjZXJ0YWluIHRyYWRpbmcgc3RyYXRlZ2llcy4gVGhlIHJ1bGUgaGFzIGxlZCB0byBpbmNyZWFzZWQgY29tcGxpYW5jZSBjb3N0cyBhbmQgb3BlcmF0aW9uYWwgYWRqdXN0bWVudHMsIGFzIEpQTW9yZ2FuIG11c3QgZW5zdXJlIHRoYXQgaXQgZG9lcyBub3QgZW5nYWdlIGluIHByb2hpYml0ZWQgYWN0aXZpdGllcy4KCioqTDUuMyBEb2VzIGl0IGFwcGVhciB0aGF0IHRoZSBiYW5rIGlzIGF0dGVtcHRpbmcgdG8gZW50ZXIgdGhlIHNlY3VyaXRpZXMgaW5kdXN0cnkgYnkgb2ZmZXJpbmcgc2VjdXJpdGllcyBzZXJ2aWNlcz8gSWYgc28sIGV4cGxhaW4gaG93LioqCgpZZXMuIEpQTW9yZ2FuIENoYXNlIGhhcyBhIHN1YnN0YW50aWFsIHByZXNlbmNlIGluIHNlY3VyaXRpZXMgdHJhZGluZy4gSXQgZW5nYWdlcyBpbiBtYXJrZXQtbWFraW5nLCBwcm9wcmlldGFyeSB0cmFkaW5nLCBhbmQgaW52ZXN0bWVudCBtYW5hZ2VtZW50IGluIHZhcmlvdXMgZXF1aXR5LCBmaXhlZC1pbmNvbWUsIGRlcml2YXRpdmVzLCBhbmQgZm9yZWlnbiBleGNoYW5nZSBtYXJrZXRzLiBNb3Jlb3ZlciwgSlBNb3JnYW7igJlzIEludmVzdG1lbnQgQmFuayBkaXZpc2lvbiB1bmRlcndyaXRlcyBhIHdpZGUgdmFyaWV0eSBvZiBkZWJ0IGFuZCBlcXVpdHkgc2VjdXJpdGllcy4gVGhpcyBpbmNsdWRlcyBpbml0aWFsIHB1YmxpYyBvZmZlcmluZ3MsIGRlYnQgb2ZmZXJpbmdzIGFuZCBzeW5kaWNhdGVkIGxvYW5zLiBBZGRpdGlvbmFsbHksIEpQTW9yZ2FuIG9mZmVycyBpbnZlc3RtZW50IG1hbmFnZW1lbnQgc2VydmljZXMgdGhyb3VnaCBpdHMgQXNzZXQgJiBXZWFsdGggTWFuYWdlbWVudCBkaXZpc2lvbi4gQnkgbWFuYWdpbmcgZnVuZHMgYW5kIHBvcnRmb2xpb3MsIEpQTW9yZ2FuIGFjdGl2ZWx5IGludmVzdHMgaW4gc2VjdXJpdGllcyBvbiBiZWhhbGYgb2YgaXRzIGNsaWVudHMsIG9mZmVyaW5nIGFjY2VzcyB0byBlcXVpdHkgYW5kIGZpeGVkIGluY29tZSBtYXJrZXRzLiBUaGlzIGludm9sdmVzIGNyZWF0aW5nIGFuZCBtYW5hZ2luZyBzZWN1cml0aWVzIHBvcnRmb2xpb3MsIHdoaWNoIGRpcmVjdGx5IHRpZXMgSlBNb3JnYW4gdG8gdGhlIHNlY3VyaXRpZXMgaW5kdXN0cnkuCgoqKkw1LjQgRG9lcyBpdCBhcHBlYXIgdGhhdCB0aGUgYmFuayBpcyBhdHRlbXB0aW5nIHRvIGVudGVyIHRoZSBpbnN1cmFuY2UgaW5kdXN0cnkgYnkgb2ZmZXJpbmcgaW5zdXJhbmNlIHNlcnZpY2VzPyBJZiBzbywgZXhwbGFpbiBob3cuKioKClllcy4gSlBNb3JnYW4gQ2hhc2Ugb2ZmZXJzIGluc3VyYW5jZSBzb2x1dGlvbnMgdG8gaXRzIGhpZ2gtbmV0LXdvcnRoIGluZGl2aWR1YWxzIGFuZCBpbnN0aXR1dGlvbmFsIGNsaWVudHMgdGhyb3VnaCBpdHMgUHJpdmF0ZSBCYW5raW5nIGFuZCBXZWFsdGggTWFuYWdlbWVudCBkaXZpc2lvbnMuIFdoaWxlIHRoZSBiYW5rIGRvZXNu4oCZdCBkaXJlY3RseSB1bmRlcndyaXRlIGluc3VyYW5jZSBwb2xpY2llcywgaXQgd29ya3Mgd2l0aCB0aGlyZC1wYXJ0eSBpbnN1cmVycyB0byBwcm92aWRlIGEgcmFuZ2Ugb2YgbGlmZSwgZGlzYWJpbGl0eSwgYW5kIGxvbmctdGVybSBjYXJlIGluc3VyYW5jZSBwcm9kdWN0cy4gQWxzbywgSlBNb3JnYW7igJlzIENvbW1lcmNpYWwgQmFua2luZyBkaXZpc2lvbiBvZmZlcnMgaW5zdXJhbmNlIGJyb2tlcmFnZSBzZXJ2aWNlcyB0byBidXNpbmVzcyBjbGllbnRzLiBUaGlzIGluY2x1ZGVzIHJpc2sgbWFuYWdlbWVudCBzb2x1dGlvbnMgYW5kIHRoZSBwbGFjZW1lbnQgb2YgaW5zdXJhbmNlIGNvdmVyYWdlIHdpdGggdGhpcmQtcGFydHkgaW5zdXJlcnMuIEJ5IGFjdGluZyBhcyBhIGJyb2tlciBhbmQgaW50ZXJtZWRpYXJ5IGJldHdlZW4gY2xpZW50cyBhbmQgaW5zdXJhbmNlIGNhcnJpZXJzLCBKUE1vcmdhbiBpcyBpbnZvbHZlZCBpbiB0aGUgZGlzdHJpYnV0aW9uIG9mIGluc3VyYW5jZSBwcm9kdWN0cy4KCiMgQ29tbWVyY2lhbCBiYW5rIG1hbmFnZW1lbnQKCioqTDUuNSBBc3Nlc3MgdGhlIGJhbmvigJlzIGJhbGFuY2Ugc2hlZXQgYXMgd2VsbCBhcyBhbnkgY29tbWVudHMgaW4gaXRzIGFubnVhbCByZXBvcnQgYWJvdXQgdGhlIGdhcCBiZXR3ZWVuIGl0cyByYXRlLXNlbnNpdGl2ZSBhc3NldHMgYW5kIGl0cyByYXRlLXNlbnNpdGl2ZSBsaWFiaWxpdGllcy4gRG9lcyBpdCBhcHBlYXIgdGhhdCB0aGUgYmFuayBoYXMgYSBwb3NpdGl2ZSBnYXAgb3IgYSBuZWdhdGl2ZSBnYXA/KioKClRoZSBiYW5rIHJhdGUtc2Vuc2l0aXZlIGFzc2V0cyBhcmUgZGVwb3NpdHMgd2l0aCBiYW5rcywgZmVkZXJhbCBmdW5kcyBzb2xkIGFuZCBzZWN1cml0aWVzIHB1cmNoYXNlZCB1bmRlciByZXNhbGUgYWdyZWVtZW50cywgc2VjdXJpdGllcyBib3Jyb3dlZCwgdHJhZGluZyBhc3NldHMsIGF2YWlsYWJsZS1mb3Itc2FsZSBzZWN1cml0aWVzLCBoZWxkLXRvLW1hdHVyaXR5IHNlY3VyaXRpZXMsIGludmVzdG1lbnQgc2VjdXJpdGllcywgYW5kIGxvYW5zLiBUaGV5IGFkZCB1cCB0byAkNCwwNTYsNjcwLiBUaGUgYmFuayByYXRlLXNlbnNpdGl2ZSBsaWFiaWxpdGllcyBhcmUgaW50ZXJlc3QtYmVhcmluZyBkZXBvc2l0cywgZmVkZXJhbCBmdW5kcyBwdXJjaGFzZWQsIHNob3J0LXRlcm0gYm9ycm93aW5ncywgdHJhZGluZyBsaWFiaWxpdGllcywgYmVuZWZpY2lhbCBpbnRlcmVzdHMgaXNzdWVkIGJ5IGNvbnNvbGlkYXRlZCBWSUVzIGFuZCBsb25nLXRlcm0gZGVidC4gVGhleSBhZGQgdXAgdG8gJDMsMjU3LDIwOCBTaW5jZSB0aGUgYmFuayBoYXMgcmF0ZS1zZW5zaXRpdmUgYXNzZXRzIGdyZWF0ZXIgdGhhbiBpdHMgcmF0ZS1zZW5zaXRpdmUgbGlhYmlsaXRpZXMsIGl0IHJlc3VsdHMgaW4gYSBwb3NpdGl2ZSBnYXAgb2YgJDc5OSw0NjIuIFRoaXMgbWVhbnMgdGhhdCB0aGUgYmFuayBoYXMgbW9yZSByYXRlLXNlbnNpdGl2ZSBhc3NldHMgdGhhbiBsaWFiaWxpdGllcyBpbiB0aGUgc2hvcnQtdGVybS4gV2hlbiBpbnRlcmVzdCByYXRlcyByaXNlLCB0aGUgaW5jb21lIGZyb20gdGhlIGJhbmvigJlzIGFzc2V0cyBpbmNyZWFzZXMgZmFzdGVyIHRoYW4gdGhlIGNvc3Qgb2YgaXRzIGxpYWJpbGl0aWVzLiBUaGlzIHNpdHVhdGlvbiBiZW5lZml0cyB0aGUgYmFuayBpbiBhIHJpc2luZyBpbnRlcmVzdCByYXRlIGVudmlyb25tZW50LgoKKipMNS42IERldGVybWluZSB0aGUgYmFua+KAmXMgaW50ZXJlc3QgaW5jb21lIGFzIGEgcGVyY2VudGFnZSBvZiBpdHMgdG90YWwgYXNzZXRzLioqCgpKUE0gaW50ZXJlc3QgaW5jb21lIGFzIGEgcGVyY2VudGFnZSBvZiBpdHMgdG90YWwgYXNzZXRzID0gMTcwLDU4OCAvIDMsODc1LDM5MyA9IDQuNDAlCgoqKkw1LjcgRGV0ZXJtaW5lIHRoZSBiYW5r4oCZcyBpbnRlcmVzdCBleHBlbnNlcyBhcyBhIHBlcmNlbnRhZ2Ugb2YgaXRzIHRvdGFsIGFzc2V0cy4qKgoKSlBNIGludGVyZXN0IGV4cGVuc2VzIGFzIGEgcGVyY2VudGFnZSBvZiBpdHMgdG90YWwgYXNzZXRzID0gODEsMzIxIC8gMyw4NzUsMzkzID0gMi4xMCUKCioqTDUuOCBEZXRlcm1pbmUgdGhlIGJhbmvigJlzIG5ldCBpbnRlcmVzdCBtYXJnaW4uKioKCkpQTSBuZXQgaW50ZXJlc3QgbWFyZ2luID0gbmV0IGludGVyZXN0IGluY29tZSAvIGF2ZXJhZ2UgaW50ZXJlc3QtZWFybmluZyBhc3NldHMgVGhlIGVhcm5pbmcgYXNzZXRzIGluIEpQTSBhcmUgRGVwb3NpdHMgd2l0aCBCYW5rcywgRmVkZXJhbCBGdW5kcyBTb2xkIGFuZCBTZWN1cml0aWVzIFB1cmNoYXNlZCB1bmRlciBSZXNhbGUgQWdyZWVtZW50cywgU2VjdXJpdGllcyBCb3Jyb3dlZCwgVHJhZGluZyBBc3NldHMsIEF2YWlsYWJsZS1mb3ItU2FsZSBTZWN1cml0aWVzLCBIZWxkLXRvLU1hdHVyaXR5IFNlY3VyaXRpZXMsIEludmVzdG1lbnQgU2VjdXJpdGllcyBhbmQgTG9hbnMuIEJlZ2lubmluZyBlYXJuaW5nIGFzc2V0cyA9IDMsODcyLDU0MiBFbmRpbmcgZWFybmluZyBhc3NldHMgPSA0LDA1Niw2NzAgSlBNIG5ldCBpbnRlcmVzdCBtYXJnaW4gPSAoIDE3MCw1ODggLSA4MSwzMjEgKSAvICgzLDg3Miw1NDIgKyA0LDA1Niw2NzApLzIgeCAxMDAgPSAyLjI1JQoKKipMNS45IERldGVybWluZSB0aGUgYmFua+KAmXMgbm9uaW50ZXJlc3QgaW5jb21lIGFzIGEgcGVyY2VudGFnZSBvZiBpdHMgdG90YWwgYXNzZXRzLiBEZXRlcm1pbmUgdGhlIGJhbmvigJlzIG5vbmludGVyZXN0IGV4cGVuc2VzIChkbyBub3QgaW5jbHVkZSB0aGUgYWRkaXRpb24gdG8gbG9hbiBsb3NzIHJlc2VydmVzIGhlcmUpIGFzIGEgcGVyY2VudGFnZSBvZiBpdHMgdG90YWwgYXNzZXRzLioqCgpKUE0gbm9uLWludGVyZXN0IGluY29tZSBhcyBhIHBlcmNlbnRhZ2Ugb2YgaXRzIHRvdGFsIGFzc2V0cyA9IDY4LDgzNyAvIDMsODc1LDM5MyB4IDEwMCA9IDEuNzglIEpQTSBub24taW50ZXJlc3QgZXhwZW5zZXMgYXMgYSBwZXJjZW50YWdlIG9mIGl0cyB0b3RhbCBhc3NldHMgPSAoODcsMTcyIC0gMjIsNDIwKSAvIDMsODc1LDM5MyB4IDEwMCA9IDEuNjclCgoqKkw1LjEwIERldGVybWluZSB0aGUgYmFua+KAmXMgYWRkaXRpb24gdG8gbG9hbiBsb3NzIHJlc2VydmVzIGFzIGEgcGVyY2VudGFnZSBvZiBpdHMgdG90YWwgYXNzZXRzLioqCgpKUE0gYWRkaXRpb24gdG8gbG9hbiBsb3NzIHJlc2VydmVzIGFzIGEgcGVyY2VudGFnZSBvZiBpdHMgdG90YWwgYXNzZXRzID0gMjIsNDIwIC8gMyw4NzUsMzkzIHggMTAwID0gMC41OCUKCioqTDUuMTEgRGV0ZXJtaW5lIHRoZSBiYW5r4oCZcyByZXR1cm4gb24gYXNzZXRzLioqCgpKUE0gcmV0dXJuIG9uIGFzc2V0cyA9IDQ5LDU1MiAvIDMsODc1LDM5MyA9IDAuMDEyOAoKKipMNS4xMiBEZXRlcm1pbmUgdGhlIGJhbmvigJlzIHJldHVybiBvbiBlcXVpdHkuKioKCkpQTSByZXR1cm4gb24gZXF1aXR5ID0gNDksNTUyIC8gMzI3LDg3OCA9IDAuMTUxCgoqKkw1LjEzIElkZW50aWZ5IHRoZSBiYW5r4oCZcyBpbmNvbWUgc3RhdGVtZW50IGl0ZW1zIGRlc2NyaWJlZCBwcmV2aW91c2x5IHRoYXQgd291bGQgYmUgYWZmZWN0ZWQgaWYgaW50ZXJlc3QgcmF0ZXMgcmlzZSBpbiB0aGUgbmV4dCB5ZWFyLCBhbmQgZXhwbGFpbiBob3cgdGhleSB3b3VsZCBiZSBhZmZlY3RlZC4qKgoKUmF0ZS1zZW5zaXRpdmUgYXNzZXRzIHN1Y2ggYXMgbG9hbnMsIHRyYWRpbmcgYXNzZXRzLCBhdmFpbGFibGUtZm9yLXNhbGUgc2VjdXJpdGllcywgYW5kIHNlY3VyaXRpZXMgcHVyY2hhc2VkIHVuZGVyIHJlc2FsZSBhZ3JlZW1lbnRzIHdpbGwgZ2VuZXJhdGUgaGlnaGVyIGluY29tZSB3aGVuIGludGVyZXN0IHJhdGVzIHJpc2UuIFJhdGUtc2Vuc2l0aXZlIGxpYWJpbGl0aWVzIHN1Y2ggYXMgaW50ZXJlc3QtYmVhcmluZyBkZXBvc2l0cywgZmVkZXJhbCBmdW5kcyBwdXJjaGFzZWQsIHNob3J0LXRlcm0gYm9ycm93aW5ncywgYW5kIGxvbmctdGVybSBkZWJ0IHdpbGwgYWxzbyBiZWNvbWUgbW9yZSBleHBlbnNpdmUgYXMgaW50ZXJlc3QgcmF0ZXMgaW5jcmVhc2UuIFNpbmNlIHRoZSBiYW5r4oCZcyByYXRlLXNlbnNpdGl2ZSBhc3NldHMgYXJlIGdyZWF0ZXIgdGhhbiBpdHMgcmF0ZS1zZW5zaXRpdmUgbGlhYmlsaXRpZXMsIGEgcmlzZSBpbiBpbnRlcmVzdCByYXRlcyB3aWxsIGNhdXNlIHRoZSBpbnRlcmVzdCBpbmNvbWUgZnJvbSB0aGVzZSBhc3NldHMgdG8gaW5jcmVhc2UgZmFzdGVyIHRoYW4gdGhlIGludGVyZXN0IGV4cGVuc2Ugb24gaXRzIGxpYWJpbGl0aWVzLiBIZW5jZSwgdGhpcyBsZWFkcyB0byBhIG5ldCBwb3NpdGl2ZSBlZmZlY3Qgb24gdGhlIGJhbmvigJlzIHByb2ZpdGFiaWxpdHkuCgoqKkw1LjE0IElkZW50aWZ5IHRoZSBiYW5r4oCZcyBpbmNvbWUgc3RhdGVtZW50IGl0ZW1zIGRlc2NyaWJlZCBwcmV2aW91c2x5IHRoYXQgd291bGQgYmUgYWZmZWN0ZWQgaWYgVS5TLiBlY29ub21pYyBjb25kaXRpb25zIGRldGVyaW9yYXRlLCBhbmQgZXhwbGFpbiBob3cgdGhleSB3b3VsZCBiZSBhZmZlY3RlZCoqCgpSYXRlLXNlbnNpdGl2ZSBhc3NldHMgc3VjaCBhcyBsb2Fucywgc2VjdXJpdGllcywgYW5kIHRyYWRpbmcgYXNzZXRzIGNvdWxkIHNlZSBhIHJlZHVjdGlvbiBpbiBpbnRlcmVzdCBpbmNvbWUgYXMgZWNvbm9taWMgY29uZGl0aW9ucyB3b3JzZW4uIFJhdGUtc2Vuc2l0aXZlIGxpYWJpbGl0aWVzIHN1Y2ggYXMgaW50ZXJlc3QtYmVhcmluZyBkZXBvc2l0cywgZmVkZXJhbCBmdW5kcyBwdXJjaGFzZWQsIGFuZCBzaG9ydC10ZXJtIGJvcnJvd2luZ3MgY291bGQgc2VlIGEgZGVjcmVhc2UgaW4gaW50ZXJlc3QgZXhwZW5zZSBpZiB0aGUgRmVkZXJhbCBSZXNlcnZlIGxvd2VycyBpbnRlcmVzdCByYXRlcyBpbiByZXNwb25zZSB0byBhIHNsb3dpbmcgZWNvbm9teS4gVGhlIGluY29tZSBmcm9tIHJhdGUtc2Vuc2l0aXZlIGFzc2V0cyBtaWdodCBkZWNyZWFzZSBtb3JlIHRoYW4gdGhlIHJlZHVjdGlvbiBpbiBpbnRlcmVzdCBleHBlbnNlIGZyb20gbGlhYmlsaXRpZXMsIGxlYWRpbmcgdG8gYSBkZWNsaW5lIGluIHRoZSBiYW5r4oCZcyBwcm9maXRhYmlsaXR5LgoKIyBNdXR1YWwgZnVuZHMKCldlIGhhdmUgc2VsZWN0ZWQgRmlkZWxpdHkgQ29udHJhZnVuZCBhcyBvdXIgbXV0dWFsIGZ1bmQgYW5kIGRlcml2ZWQgb3VyIGFuYWx5c2lzIGZyb20gdGhlIDIwMjQgcHJvc3BlY3R1cyBvZiBGaWRlbGl0eSBDb250cmFmdW5kIGZyb20gRURHQVIgdG8gYW5zd2VyIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb25zOgoKKipMNS4xNSBXaGF0IGlzIHRoZSBpbnZlc3RtZW50IG9iamVjdGl2ZSBvZiB0aGlzIG11dHVhbCBmdW5kPyBEbyB5b3UgY29uc2lkZXIgdGhpcyBtdXR1YWwgZnVuZCB0byBoYXZlIGxvdyByaXNrLCBtb2RlcmF0ZSByaXNrLCBvciBoaWdoIHJpc2s/KioKClRoZSBGaWRlbGl0eSBDb250cmFmdW5kIGlzIGEgVS5TLiBsYXJnZS1jYXAgZ3Jvd3RoIG11dHVhbCBmdW5kLiBBY2NvcmRpbmcgdG8gaXRzIHByb3NwZWN0dXMsIGl0cyBpbnZlc3RtZW50IG9iamVjdGl2ZSBpcyB0byBzZWVrIGNhcGl0YWwgYXBwcmVjaWF0aW9uIGJ5IGludmVzdGluZyBwcmltYXJpbHkgaW4gZ3Jvd3RoIHN0b2NrcyBvZiBsYXJnZSBjb21wYW5pZXMuIFRoZSBmdW5kIGludmVzdHMgaW4gY29tcGFuaWVzIHRoYXQgYXJlIGV4cGVjdGVkIHRvIGhhdmUgYWJvdmUtYXZlcmFnZSBlYXJuaW5ncyBncm93dGgsIHBhcnRpY3VsYXJseSB0aG9zZSB0aGF0IGFyZSB1bmRlcnZhbHVlZCByZWxhdGl2ZSB0byB0aGVpciBncm93dGggcG90ZW50aWFsLiBXZSBjb25zaWRlciB0aGlzIG11dHVhbCBmdW5kIHRvIGJlIG9mIG1vZGVyYXRlIHJpc2suIFRoaXMgZnVuZCBkb2VzIG5vdCBpbnZlc3QgaW4gaGlnaGx5IHNwZWN1bGF0aXZlIHN0b2NrcyBvciBleHRyZW1lbHkgdm9sYXRpbGUgYXNzZXRzLCBidXQgaXQgaXMgc3RpbGwgc3ViamVjdCB0byBmbHVjdHVhdGlvbnMgdGhhdCBjYW4gY29tZSB3aXRoIGludmVzdGluZyBpbiBncm93dGggc3RvY2tzLCBlc3BlY2lhbGx5IGR1cmluZyBwZXJpb2RzIG9mIG1hcmtldCB2b2xhdGlsaXR5LgoKKipMNS4xNiBXaGF0IHdhcyB0aGUgcmV0dXJuIG9uIHRoZSBtdXR1YWwgZnVuZCBsYXN0IHllYXI/IFdoYXQgd2FzIHRoZSBhdmVyYWdlIGFubnVhbCByZXR1cm4gb3ZlciB0aGUgbGFzdCB0aHJlZSB5ZWFycz8qKgoKQWNjb3JkaW5nIHRvIHRoZSBwcm9zcGVjdHVzLCBpdHMgcmV0dXJuIGluIDIwMjMgd2FzIDM5LjQ3JS4gSXRzIGF2ZXJhZ2UgYW5udWFsIHJldHVybiBvdmVyIHRoZSBsYXN0IDMgeWVhcnMgaXMgMTcuODQlLgoKKipMNS4xNyBXaGF0IGlzIGEga2V5IGVjb25vbWljIGZhY3RvciB0aGF0IGluZmx1ZW5jZXMgdGhlIHJldHVybiBvbiB0aGlzIG11dHVhbCBmdW5kPyAoVGhhdCBpcywgYXJlIHRoZSBmdW5k4oCZcyByZXR1cm5zIGhpZ2hseSBpbmZsdWVuY2VkIGJ5IFUuUy4gc3RvY2sgbWFya2V0IGNvbmRpdGlvbnM/IEJ5IFUuUy4gaW50ZXJlc3QgcmF0ZXM/IEJ5IGZvcmVpZ24gc3RvY2sgbWFya2V0IGNvbmRpdGlvbnM/IEJ5IGZvcmVpZ24gaW50ZXJlc3QgcmF0ZXM/KSoqCgpUaGUgZnVuZCBpcyBoaWdobHkgaW5mbHVlbmNlZCBieSB0aGUgVS5TLiBzdG9jayBtYXJrZXQgY29uZGl0aW9ucy4gU2luY2UgaXQgZm9jdXNlcyBvbiBpbnZlc3RpbmcgaW4gbGFyZ2UtY2FwIFUuUy4gY29tcGFuaWVzLCBVLlMuIHN0b2NrIG1hcmtldCBjb25kaXRpb25zIGhhdmUgYSBzaWduaWZpY2FudCBpbXBhY3Qgb24gdGhlIGZ1bmTigJlzIHBlcmZvcm1hbmNlLiBBIGdyb3dpbmcgVVMgZWNvbm9teSBnZW5lcmFsbHkgbGVhZHMgdG8gaGlnaGVyIGNvcnBvcmF0ZSBwcm9maXRzLCB3aGljaCBib29zdHMgdGhlIHN0b2NrIHByaWNlcyBvZiBjb21wYW5pZXMgaW4gd2hpY2ggdGhlIGZ1bmQgaW52ZXN0cy4KCioqTDUuMTggTXVzdCBhbnkgZmVlcyBiZSBwYWlkIHdoZW4gYnV5aW5nIG9yIHNlbGxpbmcgdGhpcyBtdXR1YWwgZnVuZD8qKgoKWWVzLiBXaGVuIGJ1eWluZyB0aGlzIG11dHVhbCBmdW5kLCBhIG1hbmFnZW1lbnQgZmVlICh3aGljaCBmbHVjdHVhdGVzIGJhc2VkIG9uIHRoZSBmdW5k4oCZcyBwZXJmb3JtYW5jZSByZWxhdGl2ZSB0byBhIHNlY3VyaXRpZXMgbWFya2V0IGluZGV4KSAwZiAwLjM5JSBpcyBwYWlkLgoKKipMNS4xOSBXaGF0IHdhcyB0aGUgZXhwZW5zZSByYXRpbyBmb3IgdGhpcyBtdXR1YWwgZnVuZCBvdmVyIHRoZSBsYXN0IHllYXI/IERvZXMgdGhpcyByYXRpbyBzZWVtIGhpZ2ggdG8geW91PyoqCgpUaGUgZXhwZW5zZSByYXRpbyBpcyAwLjM5JS4gVGhpcyByYXRpbyBpcyBsb3cgdG8gdXMuIEluIHRoZSBtdXR1YWwgZnVuZCBpbmR1c3RyeSwgdGhlIGF2ZXJhZ2UgZXhwZW5zZSByYXRpbyBmb3IgYW4gYWN0aXZlbHkgbWFuYWdlZCBlcXVpdHkgZnVuZCBpcyB0eXBpY2FsbHkgYXJvdW5kIDAuNjAlIHRvIDEuMDAlLiBBcyBzdWNoLCBhIDAuMzklIHJhdGlvIGlzIGJlbG93IGF2ZXJhZ2UgZm9yIGEgbXV0dWFsIGZ1bmQgZnVuZC4KCiMgU2VjdXJpdGllcyBmaXJtcwoKV2UgaGF2ZSBzZWxlY3RlZCBKUE1vcmdhbiBDaGFzZSAmIENvLiBhcyBvdXIgc2VjdXJpdGllcyBmaXJtIGFuZCBkZXJpdmVkIG91ciBhbmFseXNpcyBmcm9tIHRoZSAxMC1rIGFubnVhbCByZXBvcnQgb2YgSlBNIDIwMjMgZnJvbSBFREdBUiB0byBhbnN3ZXIgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnM6CgoqKkw1LjIwIFdoYXQgYXJlIHRoZSBtYWluIHR5cGVzIG9mIGJ1c2luZXNzIGNvbmR1Y3RlZCBieSB0aGUgc2VjdXJpdGllcyBmaXJtPyoqCgpKUE1vcmdhbiBvcGVyYXRlcyB0aHJvdWdoIHRocmVlIG1haW4gYnVzaW5lc3Mgc2VnbWVudHMgLSBJbnZlc3RtZW50IEJhbmtpbmcsIEdsb2JhbCBNYXJrZXRzIGFuZCBBc3NldCBNYW5hZ2VtZW50LiBUaGUgSW52ZXN0bWVudCBCYW5raW5nIGRpdmlzaW9uIGlzIHBhcnQgb2YgSi5QLiBNb3JnYW4gYW5kIGZvY3VzZXMgb24gaGVscGluZyBjbGllbnRzIHJhaXNlIGNhcGl0YWwsIG1hbmFnZSByaXNrLCBhbmQgZXhlY3V0ZSBzdHJhdGVnaWMgdHJhbnNhY3Rpb25zLiBUaGUgR2xvYmFsIE1hcmtldHMgZGl2aXNpb24gc2VydmVzIGluc3RpdHV0aW9uYWwgaW52ZXN0b3JzLCBoZWRnZSBmdW5kcywgZ292ZXJubWVudHMsIGFuZCBvdGhlciBsYXJnZSBlbnRpdGllcyBieSBwcm92aWRpbmcgYWNjZXNzIHRvIGNhcGl0YWwgbWFya2V0cyBhbmQgZmFjaWxpdGF0aW5nIHRyYW5zYWN0aW9ucy4gVGhlIEFzc2V0IE1hbmFnZW1lbnQgZGl2aXNpb24gZm9jdXNlcyBvbiBoZWxwaW5nIGNsaWVudHMgYWNoaWV2ZSB0aGVpciBpbnZlc3RtZW50IGdvYWxzIGJ5IG1hbmFnaW5nIGRpdmVyc2lmaWVkIHBvcnRmb2xpb3MgYWNyb3NzIHZhcmlvdXMgYXNzZXQgY2xhc3Nlcy4KCioqTDUuMjEgU3VtbWFyaXplIGFueSBzdGF0ZW1lbnRzIG1hZGUgYnkgdGhlIHNlY3VyaXRpZXMgZmlybSBpbiBpdHMgYW5udWFsIHJlcG9ydCBhYm91dCBob3cgaXQgbWF5IGJlIGFmZmVjdGVkIGJ5IGV4aXN0aW5nIG9yIHBvdGVudGlhbCByZWd1bGF0aW9ucy4qKgoKQWNjb3JkaW5nIHRvIHRoZSAyMDIzIGFubnVhbCByZXBvcnQsIEpQTW9yZ2Fu4oCZcyByZWd1bGF0b3J5IGNhcGl0YWwgcmVxdWlyZW1lbnRzIGFyZSBzZXQgYnkgdGhlIEZlZGVyYWwgUmVzZXJ2ZSBmb3IgdGhlIGZpcm0gYXMgYSBjb25zb2xpZGF0ZWQgZmluYW5jaWFsIGhvbGRpbmcgY29tcGFueSBhbmQgYnkgdGhlIE9DQyBmb3IgaXRzIHByaW5jaXBhbCBzdWJzaWRpYXJ5LCBKUE1vcmdhbiBDaGFzZSBCYW5rLCBOLkEuIFRoZXNlIHJlcXVpcmVtZW50cyBmb2xsb3cgdGhlIEJhc2VsIElJSSBmcmFtZXdvcmssIHdoaWNoIGVzdGFibGlzaGVzIG1pbmltdW0gY2FwaXRhbCByYXRpb3MgYW5kIG92ZXJhbGwgY2FwaXRhbCBhZGVxdWFjeSBzdGFuZGFyZHMgZm9yIGxhcmdlIFUuUy4gYmFua3MuIEpQTW9yZ2FuIHVzZXMgdHdvIGFwcHJvYWNoZXMgdG8gY2FsY3VsYXRlIGl0cyBSaXNrLVdlaWdodGVkIEFzc2V0cyAoUldBKTogdGhlIFN0YW5kYXJkaXplZCBhbmQgQWR2YW5jZWQgYXBwcm9hY2hlcywgd2l0aCBjYXBpdGFsIGFkZXF1YWN5IGFzc2Vzc2VkIGJhc2VkIG9uIHRoZSBsb3dlciBvZiB0aGUgdHdvLiBUaGUgZmlybSBtdXN0IG1haW50YWluIG1pbmltdW0gbGV2ZWxzIG9mIENFVDEgY2FwaXRhbCwgVGllciAxIGNhcGl0YWwsIFRvdGFsIGNhcGl0YWwsIFRpZXIgMSBsZXZlcmFnZSwgYW5kIHRoZSBTdXBwbGVtZW50YXJ5IExldmVyYWdlIFJhdGlvIChTTFIpLiBGYWlsdXJlIHRvIG1lZXQgdGhlc2UgY2FwaXRhbCByZXF1aXJlbWVudHMgY291bGQgbGVhZCB0byByZWd1bGF0b3J5IGFjdGlvbiBieSB0aGUgRmVkZXJhbCBSZXNlcnZlLgoKKipMNS4yMiBEZXNjcmliZSB0aGUgcmVjZW50IHBlcmZvcm1hbmNlIG9mIHRoZSBzZWN1cml0aWVzIGZpcm0sIGFuZCBleHBsYWluIHdoeSB0aGUgcGVyZm9ybWFuY2UgaGFzIGJlZW4gZmF2b3JhYmxlIG9yIHVuZmF2b3JhYmxlLioqCgpJbiAyMDIzLCBKUE1vZ3JhbiBleHBlcmllbmNlZCBzdHJvbmcgZWFybmluZ3MgZ3Jvd3RoLiBKUE1vcmdhbiBzYXcgY29udGludWVkIGdyb3d0aCBpbiBib3RoIG5ldCBpbnRlcmVzdCBpbmNvbWUgYW5kIG5vbi1pbnRlcmVzdCBpbmNvbWUsIGJlbmVmaXRpbmcgZnJvbSBhIGZhdm9yYWJsZSBpbnRlcmVzdCByYXRlIGVudmlyb25tZW50IGluIHRoZSBmaXJzdCBoYWxmIG9mIHRoZSB5ZWFyLCB3aGljaCBoZWxwZWQgYm9vc3QgcmV2ZW51ZXMgZnJvbSBsZW5kaW5nIGFuZCBpbnZlc3RtZW50IGFjdGl2aXRpZXMuIFRoZSBGZWRlcmFsIFJlc2VydmXigJlzIGludGVyZXN0IHJhdGUgaGlrZXMgZHVyaW5nIDIwMjMgcG9zaXRpdmVseSBpbXBhY3RlZCBKUE1vcmdhbuKAmXMgbmV0IGludGVyZXN0IGluY29tZSwgZXNwZWNpYWxseSBpbiBpdHMgY29uc3VtZXIgYmFua2luZyBhbmQgY29ycG9yYXRlIGxlbmRpbmcgYnVzaW5lc3Nlcy4gQXMgaW50ZXJlc3QgcmF0ZXMgaW5jcmVhc2VkLCB0aGUgYmFuayBlYXJuZWQgbW9yZSBvbiBsb2FucyBhbmQgZGVwb3NpdHMsIGJvb3N0aW5nIHByb2ZpdGFiaWxpdHkuIEFsc28sIEpQTW9yZ2Fu4oCZcyBjYXBpdGFsIHBvc2l0aW9uIHJlbWFpbmVkIHNvbGlkIHdpdGggYSBzdHJvbmcgQ0VUMSByYXRpbywgd2hpY2ggcHJvdmlkZWQgYSBjdXNoaW9uIGFnYWluc3QgZWNvbm9taWMgdW5jZXJ0YWludGllcy4gVGhlIGZpcm3igJlzIHByb2FjdGl2ZSByaXNrIG1hbmFnZW1lbnQgc3RyYXRlZ3kgaGVscGVkIGl0IG5hdmlnYXRlIHBvdGVudGlhbCBtYXJrZXQgZGlzcnVwdGlvbnMgZWZmZWN0aXZlbHkuCgojIF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCgojICoqTDYgRXF1aXR5KioKCkFjY29yZGluZyB0byBNb3JuaW5nU3RhciwgZGl2aWRlbmQgcGVyIHNoYXJlIG9mIE1pY3Jvc29mdCBhcmUgMi4zMCwgMi41NCwgMi43OSBmb3IgMjAyMSwgMjAyMiBhbmQgMjAyMyByZXNwZWN0aXZlbHkuCgpUaGUgc3RvY2sgcHJpY2Ugb2YgTWljcm9zb2Z0IHdhcyAkMzc1Ljk1IGF0IHRoZSBlbmQgb2YgMjAyMy4KCldlIGFzc3VtZSBhIHJlcXVpcmVkIHJhdGUgb2YgcmV0dXJuIG9mIDEwJQoKVXNpbmcgdGhlIGRpdmlkZW5kIGRpc2NvdW50IG1vZGVsLCBlc3RpbWF0ZWQgdmFsdWUgb2YgYSBzaGFyZSBpcyBkZXJpdmVkIGFzIGZvbGxvd3M6CgpFc3RpbWF0ZWQgdmFsdWUgPSAyLjMwIC8oMS4xMCkgKyAyLjU0IC8oMS4xMCleMiArIDIuNzkvKDEuMTApXjMgKyAzNzUuOTUoMS4xMCleMyA9ICQyODguNzQKCiMgX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KIyAqKkw3IEZpeGVkIGluY29tZSoqCgojIENvbXBhcmluZyB5aWVsZHMgYW1vbmcgc2VjdXJpdGllcy4KCioqTDcuMSoqCgpIaWdoIHF1YWxpdHkgY29ycG9yYXRlIGJvbmRzIGFyZSBBQUEgcmF0ZWQsIHdoaWNoIHdlIHdpbGwgZG93bmxvYWQgZnJvbSBGUkVELCBhbmQgdGhlbiBnZXQgdGhlIHlpZWxkIHJhdGUgZm9yIHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtLgoKV2Ugd2lsbCB1c2UgdGhlIGF2ZXJhZ2UgeWllbGQgcmF0ZSBmb3IgdGhlIG1vbnRoIG9mIFNlcHRlbWJlciAyMDI0CmBgYHtyfQpnZXRTeW1ib2xzKCJBQUEiLCBzcmMgPSAiRlJFRCIpCkVvVF9BQUFfUmF0ZSA8LSBBQUFbIjIwMjQtMDktMSJdCnByaW50KEVvVF9BQUFfUmF0ZSkKYGBgCgpGb3IgU2VwdGVtYmVyIDIwMjQsIHRoZSBoaWdoLXF1YWxpdHkgY29ycG9yYXRlIHlpZWxkIHdhcyA0LjY4JQoKV2Ugd2lsbCBub3cgZmluZCB0aGUgeWllbGQgb24gdHJlYXN1cnkgYm9uZHMuIFdlIHdpbGwgdXNlIHRoZSBkYXRhIGZvciBhIDEwLXllYXIgdHJlYXN1cnkgeWllbGQgYm9uZC4KYGBge3J9CmdldFN5bWJvbHMoIkRHUzEwIiwgc3JjID0gIkZSRUQiKQpFb1RfMTB5ZWFyX1JhdGUgPC0gREdTMTBbIjIwMjQtMDktMzAiXQpwcmludChFb1RfMTB5ZWFyX1JhdGUpCmBgYAoKVGhlIHlpZWxkIG9uIDEwLXllYXIgdHJlYXN1cnkgYm9uZHMgYXQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0gaXMgMy44MSUKClRoZSBkaWZmZXJlbmNlIGluIHlpZWxkIGJldHdlZW4gY29ycG9yYXRlIGhpZ2ggcXVhbGl0eSBib25kIGFuZCB0cmVhc3VyeSBib25kcyBpcyB0aGF0IHRoZSB5aWVsZCBvbiBjb3Jwb3JhdGUgYm9uZHMgaXMgaGlnaGVyLgoKVGhpcyBkaWZmZXJlbmNlIGlzIGtub3duIGFzIHRoZSBjcmVkaXQgc3ByZWFkLiBUaGUgY3JlZGl0IHNwcmVhZCBleGlzdHMgYmVjYXVzZSBjb3Jwb3JhdGUgYm9uZHMgYXJlIG1vcmUgbGlrZWx5IHRvIGRlZmF1bHQsIHdoZXJlIHRyZWFzdXJ5IGJvbmRzIGFyZSBmdWxseSBzdXBwb3J0ZWQgYnkgdGhlIGdvdmVybm1lbnQgYW5kIGFyZSB2aXJ0dWFsbHkgcmlzayBmcmVlLiBTbywgdGhlIGNyZWRpdCBzcHJlYWQgcHJvdmlkZXMgaGlnaGVyIHlpZWxkcyBpbiBvcmRlciB0byBhdHRyYWN0IGludmVzdG9ycy4KClRoZXJlIGlzIGFsc28gYW4gYXNzb2NpYXRlZCBsaXF1aWRpdHkgcmlzay4gVHJlYXN1cnkgYm9uZHMgYXJlIHRyYWRlZCBjb25zdGFudGx5IGFuZCBhcmUgaGlnaGx5IGxpcXVpZCwgYWxsb3dpbmcgdGhlbSB0byBiZSBlYXNpbHkgdHJhZGVkLiBXaGVyZSBjb3Jwb3JhdGUgYm9uZHMgYXJlIG1vcmUgbGltaXRlZCBpbiB0aGVpciBsaXF1aWRpdHksIG1lYW5pbmcgdGhleSBjYW4gYmUgbW9yZSBkaWZmaWN1bHQgdG8gdHJhZGUuIFRoaXMgYWxzbyBkcml2ZXMgdXAgdGhlIHlpZWxkLgoKCioqTDcuMioqCgpGcm9tIHRoZSBwcmV2aW91cyB0YXNrIHRoZSB5aWVsZCBvbiAxMC15ZWFyIHRyZWFzdXJ5IGJvbmRzIGF0IHRoZSBlbmQgb2YgdGhlIHRlcm0gaXMgMy44MSUuCgpXZSB3aWxsIG5vdyBmaW5kIHRoZSB5aWVsZCBvbiBsb25nLXRlcm0gbXVuaWNpcGFsIGJvbmRzIGZvciB0aGUgc2FtZSBkYXRlLiAKClVuZm9ydHVuYXRlbHksIHdlIHdlcmUgdW5hYmxlIHRvIGFjY2VzcyBtdW5pY2lwYWwgeWllbGQgZGF0YSBmcm9tIEZSRUQsIHNvIHdlIHdpbGwgYW5hbHlzZSB3aGF0IGdlbmVyYWxseSBjcmVhdGVzIGRpZmZlcmVuY2VzIGluIHRoZXNlIHlpZWxkIHJhdGVzLgoKVGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgeWllbGQgb24gbG9uZy10ZXJtIHRyZWFzdXJ5IGJvbmRzIGFuZCBsb25nLXRlcm0gbXVuaWNpcGFsIGJvbmRzIGlzIGR1ZSBjcmVkaXQgcmlzayBhbmQgdGF4IGFkdmFudGFnZXMuIE11bmljaXBhbCBib25kcyBhcmUgZ2VuZXJhbGx5IHNhZmUsIGJ1dCB0aGV5IHN0aWxsIGhhdmUgaGlnaGVyIHJpc2sgdGhhbiB0cmVhc3VyeSBib25kcywgY2F1c2luZyB0aGUgeWllbGQgdG8gYmUgaGlnaGVyIHRvIGNvbXBlbnNhdGUgZm9yIHRoZSBjcmVkaXQgcmlzay4KCk11bmljaXBhbCBib25kcyBoYXZlIHRheCBhZHZhbnRhZ2VzIG92ZXIgdHJlYXN1cnkgYm9uZHMsIGFzIHRyZWFzdXJ5IGJvbmRzIGFyZSB0YXhlZCBhdCBhIGZlZGVyYWwgbGV2ZWwgdGhyb3VnaCBjYXBpdGFsIGdhaW5zIHRheCwgd2hlcmUgbXVuaWNpcGFsIGJvbmRzIGFyZSBub3QuIFRoaXMgbWVhbnMgaW52ZXN0b3JzIGFyZSB3aWxsaW5nIHRvIGFjY2VwdCBhIGxvd2VyIHlpZWxkIGNvbXBhcmVkIHRvIHRyZWFzdXJ5IGJvbmRzLiAKClRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHlpZWxkIHJhdGVzIG9uIHRoZXNlIHR5cGVzIG9mIGJvbmRzIHdpbGwgdWx0aW1hdGVseSBkZXBlbmQgb24gdGhlIHNwZWNpZmljIGNyZWRpdCBhbmQgbGlxdWlkaXR5IHJpc2sgb2YgdGhlIG11bmljaXBhbCBib25kcywgYW5kIHRoZSBpbnZlc3RvcnMgdGF4IHNpdHVhdGlvbi4gCgoKIyBBc3Nlc3NpbmcgdGhlIGZvcmVjYXN0aW5nIGFiaWxpdHkgb2YgdGhlIHlpZWxkIGN1cnZlLgoKKipMNy4zKioKCldlIHdpbGwgZG93bmxvYWQgdGhlIHlpZWxkcyBmb3IgdGhlIDEzLXdlZWsgYW5kIDI2LXdlZWsgVC1iaWxscyBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzY2hvb2wgdGVybS4KYGBge3J9CmdldFN5bWJvbHMoIkRUQjMiLCBzcmMgPSAiRlJFRCIpCkJvVF8xM3dlZWtfUmF0ZSA8LSBEVEIzWyIyMDI0LTA1LTEiXQpwcmludChCb1RfMTN3ZWVrX1JhdGUpCmBgYApUaGUgMTMtd2VlayBULWJpbGwgeWllbGQgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgdGVybSBpcyA1LjI2JQpgYGB7cn0KZ2V0U3ltYm9scygiRFRCNiIsIHNyYyA9ICJGUkVEIikKQm9UXzI2d2Vla19SYXRlIDwtIERUQjZbIjIwMjQtMDUtMSJdCnByaW50KEJvVF8yNndlZWtfUmF0ZSkKYGBgClRoZSAyNi13ZWVrIFQtYmlsbCB5aWVsZCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSB0ZXJtIGlzIDUuMTclCgpBdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzY2hvb2wgdGVybSB0aGUgMjYtd2VlayBULWJpbGwgeWllbGQgcmF0ZSB3YXMgMC4wOSBwZXJjZW50YWdlIHBvaW50cyBsb3dlciB0aGFuIHRoZSAxMy13ZWVrIFQtYmlsbC4KCgoqKkw3LjQqKgoKVGhlIHNob3J0ZXItdGVybSBULWJpbGwgaGF2aW5nIGEgaGlnaGVyIHlpZWxkIHJhdGUgaW5kaWNhdGVzIHRoYXQgdGhlIHlpZWxkIGN1cnZlIGlzIGRvd253YXJkcyBzbG9waW5nIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHNjaG9vbCB0ZXJtLiAKCgoqKkw3LjUqKgoKQXR0cmlidXRpbmcgdGhlIGRvd253YXJkIHNsb3BlIG9mIHRoZSBjdXJ2ZSB0byBleHBlY3RhdGlvbnMgdGhlb3J5LCB0aGlzIGRpZmZlcmVuY2UgaW5kaWNhdGVzIHRoYXQgdGhlIG1hcmtldCBleHBlY3RlZCBsb3dlciBmdXR1cmUgaW50ZXJlc3QgcmF0ZXMuIAoKVGhpcyBjb3VsZCBiZSBkdWUgdG8gc2xvd2luZyBlY29ub21pYyBncm93dGgsIGFuZCB0aGUgZmVkZXJhbCByZXNlcnZlIHBsYW5uaW5nIHRvIGxvd2VyIGludGVyZXN0IHJhdGVzIHRvIGJvb3N0IGVjb25vbWljIGFjdGl2aXR5LgoKCioqTDcuNioqCgpXZSB3aWxsIGRvd25sb2FkIHRoZSBmZWRlcmFsIGZ1bmRzIHJhdGUgdG8gbG9vayBhdCBpbnRlcmVzdCByYXRlcy4KYGBge3J9CmdldFN5bWJvbHMoIkZFREZVTkRTIiwgc3JjID0gIkZSRUQiKQpCb1RfSW50ZXJlc3RfUmF0ZSA8LSBGRURGVU5EU1siMjAyNC0wNS0xIl0KcHJpbnQoQm9UX0ludGVyZXN0X1JhdGUpCmBgYApBdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSB0ZXJtIGZvciB0aGUgbW9udGggb2YgTWF5IHRoZSBlZmZlY3RpdmUgaW50ZXJlc3QgcmF0ZSB3YXMgNS4zMyUuCgpgYGB7cn0KRW9UX0ludGVyZXN0X1JhdGUgPC0gRkVERlVORFNbIjIwMjQtMDktMSJdCnByaW50KEVvVF9JbnRlcmVzdF9SYXRlKQpgYGAKQXQgdGhlIGVuZCBvZiB0aGUgdGVybSBmb3IgdGhlIG1vbnRoIG9mIFNlcHRlbWJlciB0aGUgZWZmZWN0aXZlIGludGVyZXN0IHJhdGUgd2FzIDUuMTMlLgoKT3ZlciB0aGUgc2Nob29sIHRlcm0sIGludGVyZXN0IHJhdGVzIGRpZCBtb3ZlIGluIHRoYXQgZGlyZWN0aW9uIGFuZCBleHBlcmllbmNlZCBhIGRlY3JlYXNlIGluIGludGVyZXN0IHJhdGVzLiBUaGlzIGlzIGluIGxpbmUgd2l0aCB3aGF0IHRoZSBtYXJrZXQgZXhwZWN0ZWQuIAoKI0V4cGxhaW5pbmcgc2hpZnRzIGluIHRoZSB5aWVsZCBjdXJ2ZSBvdmVyIHRpbWUuCgoqKkw3LjcqKiAKCldlIGtub3cgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgc2Nob29sIHRlcm0gdGhlIDEzLXdlZWsgVC1iaWxsIHJhdGUgd2FzIDUuMjYlLgoKV2Ugd2lsbCBub3cgZmluZCB0aGUgeWllbGQgb24gYSAxMC15ZWFyIGxvbmcgdGVybSB0cmVhc3VyeSBib25kIGF0IHRoZSBzYW1lIHBlcmlvZC4gCmBgYHtyfQpnZXRTeW1ib2xzKCJER1MxMCIsIHNyYyA9ICJGUkVEIikKQm9UXzEweWVhcl9SYXRlIDwtIERHUzEwWyIyMDI0LTA1LTEiXQpwcmludChCb1RfMTB5ZWFyX1JhdGUpCmBgYApXZSBzZWUgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgc2Nob29sIHRlcm0gdGhlIGxvbmctdGVybSB0cmVhc3VyeSBib25kIGlzIDQuNjMlLgoKQXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgc2Nob29sIHRlcm0gdGhlIDEzLXdlZWsgVC1iaWxsIHlpZWxkIHdhcyAwLjYzIHBlcmNlbnRhZ2UgcG9pbnRzIGhpZ2hlciB0aGFuIHRoZSBsb25nLXRlcm0gdHJlYXN1cnkgYm9uZC4KCgoqKkw3LjgqKgoKV2Uga25vdyB0aGF0IGF0IHRoZSBlbmQgb2YgdGhlIHRlcm0gdGhlIDEwLXllYXIgbG9uZyB0ZXJtIHRyZWFzdXJ5IGJvbmQgeWllbGQgd2FzIDMuODElLgoKV2Ugd2lsbCBub3cgZmluZCB0aGUgMTMtd2VlayBULWJpbGwgeWllbGQgYXQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0uCmBgYHtyfQpnZXRTeW1ib2xzKCJEVEIzIiwgc3JjID0gIkZSRUQiKQpFb1RfMTN3ZWVrX1JhdGUgPC0gRFRCM1siMjAyNC0wOS0zMCJdCnByaW50KEVvVF8xM3dlZWtfUmF0ZSkKYGBgCldlIHNlZSB0aGF0IGF0IHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtIHRoZSAxMy13ZWVrIFQtYmlsbCB5aWVsZCB3YXMgNC41MiUuCgpBdCB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybSB0aGUgMTMtd2VlayBULWJpbGwgeWllbGQgd2FzIDAuNzEgcGVyY2VudGFnZSBwb2ludHMgaGlnaGVyIHRoYW4gdGhlIGxvbmctdGVybSB0cmVhc3VyeSBib25kIHlpZWxkLgoKCioqTDcuOSoqCgpCYXNlZCBvbiB0aGUgcHJldmlvdXMgdHdvIHF1ZXN0aW9ucywgd2Ugc2VlIHRoYXQgb3ZlciB0aGUgc2Nob29sIHRlcm0gdGhlIDEzLXdlZWsgVC1iaWxsIHlpZWxkIGRyb3BwZWQgZnJvbSA1LjI2JSB0byA0LjUyJSwgYW5kIHRoZSBsb25nLXRlcm0gdHJlYXN1cnkgYm9uZCB5aWVsZCBkcm9wcGVkIGZyb20gNC42MyUgdG8gMy44MSUuCgpTaW5jZSB0aGUgeWllbGRzIGluIGJvdGggc2VjdXJpdGllcyBmZWxsIG92ZXIgdGhlIHNjaG9vbCB0ZXJtLCB3ZSBvYnNlcnZlIGEgZG93bndhcmQgc2hpZnQgaW4gdGhlIHlpZWxkIGN1cnZlLiBUaGUgbG9uZy10ZXJtIHRyZWFzdXJ5IGJvbmRzIHlpZWxkIGRyb3BwZWQgYnkgMC44MiBwZXJjZW50YWdlIHBvaW50cyBhbmQgdGhlIHNob3J0IHRlcm0gMTMtd2VlayBULWJpbGwgeWllbGRzIGRyb3BwZWQgYnkgMC43NCBwZXJjZW50YWdlIHBvaW50cy4KClRoZSBsb25nIHRlcm0gdHJlYXN1cnkgYm9uZCB5aWVsZHMgZHJvcHBlZCBieSBhIGdyZWF0ZXIgYW1vdW50IHRoYW4gdGhlIDEzLXdlZWsgVC1iaWxsIHlpZWxkcy4gVGhpcyBpbmRpY2F0ZXMgdGhhdCB0aGUgeWllbGQgY3VydmUgYmVjYW1lIG1vcmUgZmxhdC4KClRoZSB5aWVsZCBjdXJ2ZSBmbGF0dGVuaW5nIGltcGxpZXMgdGhhdCBpbnZlc3RvcnMgZXhwZWN0IGxvd2VyIGZ1dHVyZSBlY29ub21pYyBncm93dGggYW5kIGluZmxhdGlvbiwgbWVhbmluZyBpbnZlc3RvcnMgYW50aWNpcGF0ZSBsb3dlciBmdXR1cmUgaW50ZXJlc3QgcmF0ZXMuIAoKIyBUaGUgRmVkJ3MgaW5mbHVlbmNlIG9uIGludGVyZXN0IHJhdGVzLgoKKipMNy4xMCoqCgpXZSB3aWxsIGRvd25sb2FkIHRoZSBmZWRlcmFsIGZ1bmQgcmF0ZXMgYXQgdGhlIGJlZ2lubmluZyBhbmQgZW5kIG9mIHRoZSBzY2hvb2wgdGVybS4KYGBge3J9CmdldFN5bWJvbHMoIkZFREZVTkRTIiwgc3JjID0gIkZSRUQiKQpCb1RfSW50ZXJlc3RfUmF0ZSA8LSBGRURGVU5EU1siMjAyNC0wNS0xIl0KcHJpbnQoQm9UX0ludGVyZXN0X1JhdGUpCmBgYApBdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSB0ZXJtIGZvciB0aGUgbW9udGggb2YgTWF5IHRoZSBmZWRlcmFsIGZ1bmQgcmF0ZSB3YXMgNS4zMyUuCgpgYGB7cn0KRW9UX0ludGVyZXN0X1JhdGUgPC0gRkVERlVORFNbIjIwMjQtMDktMSJdCnByaW50KEVvVF9JbnRlcmVzdF9SYXRlKQpgYGAKQXQgdGhlIGVuZCBvZiB0aGUgdGVybSBmb3IgdGhlIG1vbnRoIG9mIFNlcHRlbWJlciB0aGUgZmVkZXJhbCBmdW5kIHJhdGUgd2FzIDUuMTMlLgpXZSBjYW4gc2VlIHRoYXQgb3ZlciB0aGUgc2Nob29sIHRlcm0gdGhlIGZlZGVyYWwgZnVuZHMgcmF0ZSBkaWQgY2hhbmdlIGZyb20gNS4zMyUgdG8gNS4xMyUgZm9yIGEgMC4yMCBwZXJjZW50YWdlIHBvaW50IGRlY3JlYXNlLiAKCgoqKkw3LjExKioKCk1vdmVtZW50cyBpbiBpbnRlcmVzdCByYXRlcyBvdmVyIHRoZSBzY2hvb2wgdGVybSB3b3VsZCBoYXZlIGJlZW4gY2F1c2VkIGJ5IHRoZSBGZWQncyBtb25ldGFyeSBwb2xpY3kuCgpPdmVyIHRoZSBzY2hvb2wgdGVybSB0aGUgRmVkIHNoaWZ0ZWQgdG93YXJkcyBtb25ldGFyeSBlYXNpbmcgYnkgZGVjcmVhc2luZyB0aGUgaW50ZXJlc3QgcmF0ZS4gVGhpcyBsaWtlbHkgd291bGQndmUgYmVlbiBpbiByZXNwb25zZSB0byBzb2Z0ZW5pbmcgaW5mbGF0aW9uIGFuZCB3ZWFrZXIgZWNvbm9taWMgYWN0aXZpdHkuCgpNb25ldGFyeSBlYXNpbmcgd291bGQndmUgaGVscGVkIGltcHJvdmUgZWNvbm9taWMgbW9tZW50dW0gYW5kIHRyeWluZyB0byBhY2NlbGVyYXRlIG1hcmtldCBhY3Rpdml0eS4gCgojIE1lYXN1cmluZyBhbmQgZXhwbGFpbmluZyBwcmVtaXVtcyBvbiBtb25leSBtYXJrZXQgc2VjdXJpdGllcy4KCioqTDcuMTIqKgoKV2Ugd2lsbCBub3cgZmluZCB0aGUgZGF0YSBmb3IgdGhlIHlpZWxkcyBvbiA5MC1kYXkgY29tbWVyY2lhbCBwYXBlciBhdCB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybS4KCldlIGFyZSB1bmFibGUgdG8gZG93bmxvYWQgdGhlIDkwLWRheSBjb21tZXJjaWFsIHBhcGVyIGRhdGEgZnJvbSBGUkVELCBzbyB3ZSB3aWxsIHVzZSAzLU1vbnRoIEFBIEZpbmFuY2lhbCBDb21tZXJjaWFsIFBhcGVyIFJhdGUgYXMgYSBwcm94eS4KYGBge3J9CmdldFN5bWJvbHMoIkRDUEYzTSIsIHNyYyA9ICJGUkVEIikKRW9UXzkwZGF5X1JhdGUgPC0gRENQRjNNWyIyMDI0LTA5LTEvMjAyNC0wOS0zMCJdCnByaW50KEVvVF85MGRheV9SYXRlKQpgYGAKCldlIGNhbiBzZWUgdGhlIHJhdGUgZm9yIHRoZSBkYXRlIGNsb3Nlc3QgdG8gdGhlIGVuZCBvZiB0aGUgdGVybSBpcyA0LjY0JSBvbiAyMDI0LTA5LTIwLgoKV2Ugd2lsbCBub3cgZmluZCB0aGUgMTMtd2VlayBULWJpbGwgeWllbGQgZm9yIHRoZSBzYW1lIGRhdGUgZm9yIGEgZmFpciBjb21wYXJpc29uLgpgYGB7cn0KZ2V0U3ltYm9scygiRFRCMyIsIHNyYyA9ICJGUkVEIikKcHJpbnQoRFRCM1siMjAyNC0wOS0yMCJdKQpgYGAKV2Ugc2VlIGhlcmUgdGhhdCB0aGUgMTMtd2VlayBULWJpbGwgeWllbGQgb24gMjAyNC0wOS0yMCB3YXMgNC41NiUuCgpUaGUgOTAtZGF5IGNvbW1lcmNpYWwgcGFwZXIgeWllbGQgaXMgaGlnaGVyIHRoYW4gdGhlIDEzLXdlZWsgVC1iaWxsIHlpZWxkLCBpbmRpY2F0aW5nIGEgcHJlbWl1bSBvbiB0aGUgOTAtZGF5IGNvbW1lcmNpYWwgcGFwZXIgeWllbGQuCgpUaGUgbWFpbiByZWFzb24gZm9yIGEgcHJlbWl1bSAgb24gY29tbWVyY2lhbCBwYXBlciB5aWVsZHMgaXMgdGhhdCBULWJpbGxzIGFyZSBpc3N1ZWQgYnkgdGhlIGdvdmVybm1lbnQgYW5kIGFyZSBlZmZlY3RpdmVseSByaXNrIGZyZWUuIENvbW1lcmNpYWwgcGFwZXIgaXMgaXNzdWVkIGJ5IGNvcnBvcmF0aW9ucyBhbmQgaGF2ZSBhIGdyZWF0ZXIgY3JlZGl0IHJpc2sgc2luY2UgcmVwYXltZW50IGRlcGVuZHMgb24gdGhlIGZpbmFuY2lhbCBoZWFsdGggb2YgdGhlIGlzc3Vlci4KCkFub3RoZXIgcmVhc29uIGZvciB0aGUgcHJlbWl1bSBjYW4gYmUgY3JlZGl0ZWQgdG8gbG93ZXIgbGlxdWlkaXR5IG9mIGNvbW1lcmNpYWwgcGFwZXJzLCBhcyB0aGV5IGFyZSB0cmFkZWQgbGVzcyB0aGFuIHRoZSB3aWRlbHkgdHJhZGVkIFQtYmlsbHMuCgoKKipMNy4xMyoqCgpUaGUgcHJlbWl1bSBvbiA5MC1kYXkgY29tbWVyY2lhbCBwYXBlcnMgb3ZlciAxMy13ZWVrIFQtYmlsbCB5aWVsZHMgYXQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0gb24gMjAyNC0wOS0yMCB3YXMgYSAwLjA4JSBwcmVtaXVtLiAKCldlIHdpbGwgbm93IGZpbmQgdGhlIHByZW1pdW0gdGhhdCBleGlzdGVkIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHNjaG9vbCB0ZXJtLCB1c2luZyB0aGUgc2FtZSBwcm94eSBmb3IgOTAtZGF5IGNvbW1lcmNpYWwgcGFwZXIgd2UgdXNlZCBwcmV2aW91c2x5LgpgYGB7cn0KZ2V0U3ltYm9scygiRENQRjNNIiwgc3JjID0gIkZSRUQiKQpwcmludChEQ1BGM01bIjIwMjQtMDUtMS8yMDI0LTA1LTMwIl0pCmBgYApXZSBzZWUgdGhlIHlpZWxkIGNsb3Nlc3QgdG8gdGhlIGJlZ2lubmluZyBvZiB0aGUgc2Nob29sIHRlcm0gd2FzIDUuMzclIG9uIDIwMjQtMDUtMDIuCgpXZSB3aWxsIG5vdyBmaW5kIHRoZSAxMy13ZWVrIFQtYmlsbCB5aWVsZCBmb3IgdGhlIHNhbWUgZGF0ZS4KYGBge3J9CmdldFN5bWJvbHMoIkRUQjMiLCBzcmMgPSAiRlJFRCIpCnByaW50KERUQjNbIjIwMjQtMDUtMiJdKQpgYGAKT24gMjAyNC0wNS0wMiB0aGUgMTMtd2VlayBULWJpbGwgeWllbGQgd2FzIDUuMjUlLgoKVGhlIGNvbW1lcmNpYWwgcGFwZXIgcHJlbWl1bSBvbiB0aGlzIGRhdGUgd2FzIGEgMC4xMiUgcHJlbWl1bS4KClRoaXMgZGF0YSBzaG93cyB0aGF0IHRoZSBwcmVtaXVtIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHNjaG9vbCB0ZXJtIHdhcyBncmVhdGVyIHRoYW4gYXQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0uCgpUaGUgbmFycm93aW5nIHNwcmVhZCBvdmVyIHRoZSBzY2hvb2wgdGVybSBpbmRpY2F0ZXMgaW1wcm92aW5nIGNvcnBvcmF0ZSBjcmVkaXQgY29uZGl0aW9ucywgYXMgdGhlcmUgaXMgYSBzbWFsbGVyIHByZW1pdW0gcmVxdWlyZWQgdG8gYXR0cmFjdCBpbnZlc3RvcnMsIG1lYW5pbmcgaW52ZXN0b3JzIGhhZCBhbiBpbmNyZWFzZWQgY29uZmlkZW5jZSBpbiBsb3dlciBjb3Jwb3JhdGUgY3JlZGl0IHJpc2suCgojIEV4cGxhaW5pbmcgYm9uZCBwcmVtaXVtcyBhbmQgcHJpY2UgbW92ZW1lbnRzLgoKKipMNy4xNCoqCgpXZSBhcmUgZ29pbmcgdG8gZG93bmxvYWQgdGhlIHlpZWxkcyBmb3IgaGlnaC1xdWFsaXR5IGNvcnBvcmF0ZSBib25kcyBhdCB0aGUgYmVnaW5uaW5nIGFuZCBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtLgpgYGB7cn0KQm9UX0FBQV9SYXRlIDwtIEFBQVsiMjAyNC0wNS0xIl0KcHJpbnQoQm9UX0FBQV9SYXRlKQpgYGAKV2Ugc2VlIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHNjaG9vbCB0ZXJtIGhpZ2gtcXVhbGl0eSBjb3Jwb3JhdGUgYm9uZHMgeWllbGQgd2FzIDUuMjUlLiAKCkZvciB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybSB3ZSB3aWxsIHVzZSB0aGUgYXZlcmFnZSBmb3IgU2VwdGVtYmVyIDIwMjQuCmBgYHtyfQpFb1RfQUFBX1JhdGUgPC0gQUFBWyIyMDI0LTA5LTEiXQpwcmludChFb1RfQUFBX1JhdGUpCmBgYApXZSBzZWUgYXQgdGhlIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0gaGlnaC1xdWFsaXR5IGNvcnBvcmF0ZSBib25kcyB5aWVsZCB3YXMgNC42OCUuCgpPdmVyIHRoZSBzY2hvb2wgdGVybSBoaWdoLXF1YWxpdHkgY29ycG9yYXRlIGJvbmQgeWllbGQgZHJvcHBlZCAwLjU3JSBmcm9tIDUuMjUlIHRvIDQuNjglLgoKCioqTDcuMTUqKgoKV2UgYXJlIG5vdyBnb2luZyB0byBjb21wYXJlIGxvbmctdGVybSB0cmVhc3VyeSBib25kIHlpZWxkcyBhdCB0aGUgYmVnaW5uaW5nIGFuZCBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtLCB1c2luZyAxMC15ZWFyIHRyZWFzdXJ5IGJvbmRzLgoKRnJvbSBMNy43IGFuZCBMNy44IHdlIGtub3cgdGhhdCB0aGUgMTAteWVhciBsb25nLXRlcm0gdHJlYXN1cnkgYm9uZCB5aWVsZCB3YXMgNC42MyUgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgc2Nob29sIHRlcm0gYW5kIDMuODElIGF0IHRoZSBlbmQgb2YgdGhlIHNjaG9vbCB0ZXJtLgoKT3ZlciB0aGUgc2Nob29sIHRlcm0gbG9uZy10ZXJtIHRyZWFzdXJ5IGJvbmQgeWllbGQgZHJvcHBlZC4gVGhpcyBtZWFucyB0aGF0IHRoZSBwcmljZSBvZiBsb25nLXRlcm0gdHJlYXN1cnkgYm9uZHMgaGFzIHJpc2VuIG92ZXIgdGhlIHNjaG9vbCB0ZXJtLCBkdWUgdG8gdGhlIGludmVyc2UgcmVsYXRpb25zaGlwIGJldHdlZW4gYm9uZCB5aWVsZHMgYW5kIHByaWNlLgoKCioqTDcuMTYqKgoKVW5mb3J0dW5hdGVseSB3ZSBhcmUgdW5hYmxlIHRvIGFjY2VzcyB5aWVsZCBkYXRhIG9uIG11bmljaXBhbCBib25kcywgYnV0IHdlIGNhbiBhc3N1bWUgdGhleSBtb3ZlZCBpbiBjbG9zZSByZWxhdGlvbiB0byB0cmVhc3VyeSBib25kcywgYXMgbXVuaWNpcGFsIGJvbmRzIGFyZSBhbHNvIGlzc3VlZCBieSB0aGUgZ292ZXJubWVudCBhbmQgY29uc2lkZXJlZCB0byBiZSBnZW5lcmFsbHkgcmlzayBmcmVlLgoKVXNpbmcgYW5zd2VycyB0byB0aGUgcHJldmlvdXMgcXVlc3Rpb25zLCB3ZSBvYnNlcnZlIHRoYXQgb3ZlciB0aGUgc2Nob29sIHRlcm0gdHJlYXN1cnkgYm9uZCBhbmQgY29ycG9yYXRlIGJvbmQgeWllbGRzIG1vdmVkIGluIHRoZSBzYW1lIGRpcmVjdGlvbiBhbmQgZGVjcmVhc2VkIG92ZXIgdGhlIHNjaG9vbCB0ZXJtLgoKVGhlIGJvbmQgeWllbGRzIGFsc28gZGVjcmVhc2VkIGJ5IGEgc2ltaWxhciBhbW91bnQsIGFyb3VuZCAwLjUwJS0wLjc1JS4KCkRpZmZlcmVudCB0eXBlcyBvZiBib25kcyBoYXZlIHRoZWlyIHlpZWxkcyBnZW5lcmFsbHkgbW92ZSB0b2dldGhlciBmb3IgYSBmZXcgcmVhc29ucy4KCkZpcnN0bHksIGJvbmQgeWllbGRzIGFyZSBoZWF2aWx5IGluZmx1ZW5jZWQgYnkgZmVkZXJhbCByZXNlcnZlIGludGVyZXN0IHJhdGVzLiBXaGVuIHRoZSBmZWQgY2hhbmdlcyBpbnRlcmVzdCByYXRlcywgaXQgYWZmZWN0cyB0aGUgY29zdCBvZiBib3Jyb3dpbmcgZm9yIGFsbCBlbnRpdGllcywgY2F1c2luZyBib25kIHlpZWxkcyB0byBjaGFuZ2UgYWNjb3JkaW5nbHkuCgpTZWNvbmRseSwgZXhwZWN0YXRpb25zIG9uIGluZmxhdGlvbi4gV2hlcmUgaW5mbGF0aW9uIGFmZmVjdHMgdGhlIHJlYWwgcmV0dXJucyBvbiBib25kcywgc28gY2hhbmdlcyBpbiBpbmZsYXRpb24gZXhwZWN0YXRpb24gd2lsbCBjaGFuZ2UgdGhlIHlpZWxkcyBvbiBib25kcy4gSW4gdGhpcyBjYXNlIGV4cGVjdGF0aW9ucyBvZiBsb3dlciBpbmZsYXRpb24gcmVkdWNlZCB0aGUgeWllbGQgb24gYm9uZHMuCgpHZW5lcmFsbHksIHlpZWxkcyBvbiBkaWZmZXJlbnQgdHlwZXMgb2YgYm9uZHMgb2Z0ZW4gY2hhbmdlIGluIGxpbmUgd2l0aCBlYWNoIG90aGVyIGFzIHRoZXkgYWxsIHJlc3BvbmQgdG8gdGhlIHNhbWUgbWFjcm9lY29ub21pYyBmYWN0b3JzLiAKCgoqKkw3LjE3KioKCldlIGFyZSBnb2luZyB0byBjb21wYXJlIHRoZSB5aWVsZCBwcmVtaXVtcyBvbiBoaWdoLXF1YWxpdHkgY29ycG9yYXRlIGJvbmRzIHRvIHRyZWFzdXJ5IGJvbmRzIGF0IHRoZSBiZWdpbm5pbmcgYW5kIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0uCgpXZSBrbm93IGZyb20gcHJldmlvdXMgcXVlc3Rpb25zIHRoYXQgdGhlIHlpZWxkcyBvbiBoaWdoLXF1YWxpdHkgY29ycG9yYXRlIGJvbmRzIGF0IHRoZSBiZWdpbm5pbmcgYW5kIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0gd2VyZSA1LjI1JSBhbmQgNC42OCUgcmVzcGVjdGl2ZWx5LgoKQWdhaW4gZnJvbSBwcmV2aW91cyBxdWVzdGlvbnMsIHdlIGtub3cgdGhlIHlpZWxkcyBvbiBsb25nIHRlcm0gdHJlYXN1cnkgYm9uZHMgYXQgdGhlIGJlZ2lubmluZyBhbmQgZW5kIG9mIHRoZSBzY2hvb2wgdGVybSB3YXMgNC42MyUgYW5kIDMuODElIHJlc3BlY3RpdmVseS4KClRoaXMgYWxsb3dzIHVzIHRvIGZpbmQgdGhlIHByZW1pdW1zIG9uIHRoZSBoaWdoLXF1YWxpdHkgY29ycG9yYXRlIGJvbmRzIGF0IHRoZSBiZWdpbm5pbmcgYW5kIGVuZCBvZiB0aGUgc2Nob29sIHRlcm0gdG8gYmUgMC42MiUgYW5kIDAuODclIHJlc3BlY3RpdmVseS4gCgpUaGlzIHNob3dzIHVzIHRoYXQgb3ZlciB0aGUgc2Nob29sIHRlcm0gdGhlIHByZW1pdW0gb24gaGlnaC1xdWFsaXR5IGNvcnBvcmF0ZSBib25kcyBoYXMgaW5jcmVhc2VkLiAKClRoaXMgaW5jcmVhc2Ugd2lsbCBiZSBkdWUgdG8gaW52ZXN0b3JzIGV4cGVjdGF0aW9ucyBvZiBlY29ub21pYyBjb25kaXRpb25zLiBEdXJpbmcgZWNvbm9taWMgdW5jZXJ0YWludHkgb3IgZXhwZWN0ZWQgZWNvbm9taWMgZGVjZWxlcmF0aW9uLCBpbnZlc3RvcnMgaGF2ZSBhIGhpZ2hlciBwZXJjZWl2ZWQgY3JlZGl0IHJpc2sgb24gY29ycG9yYXRlIGJvbmRzLCBtZWFuaW5nIHRoYXQgY29ycG9yYXRlIGJvbmRzIG5lZWQgdG8gaGF2ZSBoaWdoZXIgeWllbGRzIHRvIGF0dHJhY3QgaW52ZXN0b3JzLgoKIyBfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwoKIyAqKkw4IFBvcnRmb2xpbyAtIE1hcmtvdml0eioqCiNSZXBsaWNhdGUgdGhlIGJhc2ljIGlkZWEgb2YgdGhlIHByb3Rmb2xpbyBjYXNlCgpNb2Rlcm4gUG9ydGZvbGlvIFRoZW9yeSAoTVBUKSwgYnkgSGFycnkgTWFya293aXR6LCByZXByZXNlbnRzIGEgZnVuZGFtZW50YWwgcGFyYWRpZ20gc2hpZnQgaW4gaW52ZXN0bWVudCBwb3J0Zm9saW8gY29uc3RydWN0aW9uIGJ5IGludHJvZHVjaW5nIGEgcXVhbnRpdGF0aXZlIGFwcHJvYWNoIHRvIGFzc2V0IGFsbG9jYXRpb24uIFRoZSB0aGVvcnkgcHJvdmlkZXMgYSBmcmFtZXdvcmsgZm9yIGludmVzdG9ycyB0byBvcHRpbWl6ZSBwb3J0Zm9saW8gY29tcG9zaXRpb24gYnkgc3lzdGVtYXRpY2FsbHkgYmFsYW5jaW5nIHJpc2sgYW5kIHJldHVybiB0aHJvdWdoIGRpdmVyc2lmaWNhdGlvbi4KClRoZSBjb3JlIHByaW5jaXBsZSBvZiBNUFQgaXMgdGhlIGNvbnN0cnVjdGlvbiBvZiBhbiAiZWZmaWNpZW50IHBvcnRmb2xpbyIgdGhhdCBlaXRoZXIgbWF4aW1pemVzIGV4cGVjdGVkIHJldHVybnMgZm9yIGEgZ2l2ZW4gbGV2ZWwgb2YgcmlzayBvciBtaW5pbWl6ZXMgcmlzayBmb3IgYSBwcmVkZXRlcm1pbmVkIGV4cGVjdGVkIHJldHVybi4gVGhpcyBvcHRpbWl6YXRpb24gaXMgYWNoaWV2ZWQgYnkgcmlnb3JvdXNseSBhbmFseXppbmcgdHdvIGNyaXRpY2FsIHN0YXRpc3RpY2FsIHByb3BlcnRpZXMgb2YgYXNzZXQgcmV0dXJuczoKCk1lYW4gKEV4cGVjdGVkIFJldHVybik6IEEgbWVhc3VyZSBvZiB0aGUgYW50aWNpcGF0ZWQgcGVyZm9ybWFuY2Ugb2YgaW5kaXZpZHVhbCBzZWN1cml0aWVzCgpWYXJpYW5jZS1Db3ZhcmlhbmNlIE1hdHJpeDogQSBjb21wcmVoZW5zaXZlIHJlcHJlc2VudGF0aW9uIG9mIGJvdGggaW5kaXZpZHVhbCBhc3NldCByaXNrIGFuZCB0aGUgaW50ZXJkZXBlbmRlbmNpZXMgYmV0d2VlbiBhc3NldHMKCldlIHdpbGwgdXNlIDIwIGRpZmZlcmVudCBzdG9jayBwb3J0Zm9saW8gdGhhdCByYW5nZXMgZnJvbSB0aGUgdGVjaG5vbG9neSBzZWN0b3IsIGZpbmFuY2lhbCBzZWN0b3IgaGVhbHRoY2FyZSBzZWN0b3IgYW5kIGNvbnN1bWVyIHNlY3RvciB0byBlbnN1cmUgZGl2ZXJzaXR5IGluIHJlcGxpY2F0aW5nIHRoZSBiYXNpYyBpZGVhIG9mIHRoZSBwb3J0Zm9saW8gY2FzZS4gCgpgYGB7cn0KaW5zdGFsbC5wYWNrYWdlcygncXVhbnRtb2QnKQoKbGlicmFyeShxdWFudG1vZCkKCmluc3RhbGwucGFja2FnZXMoJ1BlcmZvcm1hbmNlQW5hbHl0aWNzJykKCmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpCgppbnN0YWxsLnBhY2thZ2VzKCdnZ3Bsb3QyJykKCmBgYApgYGB7cn0KIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXMKbGlicmFyeShxdWFudG1vZCkKbGlicmFyeShQZXJmb3JtYW5jZUFuYWx5dGljcykKbGlicmFyeShnZ3Bsb3QyKQpgYGAKCldlIHRyaWVkIGV4cGFuZGluZyB0aGUgbnVtYmVyIG9mIHN0b2NrcyB0byAyMCBpbiBvcmRlciB0byBmdWxseSBkaXZlcnNpZnkgb3VyIHBvcnRmb2xpby4gCmBgYHtyfQojIERlZmluZSB0aGUgc3RvY2sgdGlja2VycyBmb3IgdGhlIHBvcnRmb2xpbwp0aWNrZXJzIDwtIGMoIkFBUEwiLCAiTVNGVCIsICJHT09HIiwgIkFNWk4iLCAiVFNMQSIsCiAgICAgICAgICAgICAiTUVUQSIsICJOVkRBIiwgIkpQTSIsICJWIiwgIlVOSCIsCiAgICAgICAgICAgICAiUEciLCAiSEQiLCAiRElTIiwgIlhPTSIsICJDVlgiLAogICAgICAgICAgICAgIktPIiwgIlBFUCIsICJNQ0QiLCAiSU5UQyIsICJBREJFIikKCiMgRmV0Y2ggaGlzdG9yaWNhbCBhZGp1c3RlZCBjbG9zaW5nIHByaWNlcyBmcm9tIFlhaG9vIEZpbmFuY2UKZ2V0U3ltYm9scyh0aWNrZXJzLCBmcm9tID0gIjIwMTgtMDEtMDEiLCB0byA9ICIyMDIzLTEyLTMxIikKCiMgQ29tYmluZSBhbGwgc3RvY2sgcHJpY2VzIGludG8gYSBzaW5nbGUgeHRzIG9iamVjdCBhbmQgY2FsY3VsYXRlIGRhaWx5IHJldHVybnMKcHJpY2VzIDwtIGRvLmNhbGwobWVyZ2UsIGxhcHBseSh0aWNrZXJzLCBmdW5jdGlvbih0KSBDbChnZXQodCkpKSkKcmV0dXJucyA8LSBuYS5vbWl0KFJPQyhwcmljZXMpKQoKIyBDYWxjdWxhdGUgZXhwZWN0ZWQgcmV0dXJucyBhbmQgY292YXJpYW5jZSBtYXRyaXggZm9yIHRoZSBzdG9ja3MKbXUgPC0gY29sTWVhbnMocmV0dXJucykKY292X21hdCA8LSBjb3YocmV0dXJucykKCiMgRXF1YWwgd2VpZ2h0cyBmb3Igc2ltcGxpY2l0eTogRGl2aWRpbmcgMSBieSB0aGUgbnVtYmVyIG9mIHN0b2Nrcwp3ZWlnaHRzIDwtIHJlcCgxIC8gbGVuZ3RoKHRpY2tlcnMpLCBsZW5ndGgodGlja2VycykpCgojIENhbGN1bGF0ZSBwb3J0Zm9saW8gZXhwZWN0ZWQgcmV0dXJuIGFuZCB2YXJpYW5jZQpwb3J0Zm9saW9fcmV0dXJuIDwtIHN1bSh3ZWlnaHRzICogbXUpCnBvcnRmb2xpb192YXJpYW5jZSA8LSB0KHdlaWdodHMpICUqJSBjb3ZfbWF0ICUqJSB3ZWlnaHRzCgojIENhbGN1bGF0ZSBhbm51YWxpemVkIHBvcnRmb2xpbyByZXR1cm4gYW5kIHZvbGF0aWxpdHkKYW5udWFsX3JldHVybiA8LSBwb3J0Zm9saW9fcmV0dXJuICogMjUyCmFubnVhbF92b2xhdGlsaXR5IDwtIHNxcnQocG9ydGZvbGlvX3ZhcmlhbmNlICogMjUyKQoKIyBQcmludCB0aGUgcmVzdWx0cyB3aXRoIGFubm90YXRpb25zCnByaW50KHBhc3RlKCJBbm51YWxpemVkIFBvcnRmb2xpbyBFeHBlY3RlZCBSZXR1cm46Iiwgcm91bmQoYW5udWFsX3JldHVybiAqIDEwMCwgMiksICIlIikpCnByaW50KHBhc3RlKCJBbm51YWxpemVkIFBvcnRmb2xpbyBWb2xhdGlsaXR5OiIsIHJvdW5kKGFubnVhbF92b2xhdGlsaXR5ICogMTAwLCAyKSwgIiUiKSkKYGBgCgpXaXRoIHRoZSBhaWQgb2YgQ2hhdCBHUFQgd2Ugd2VyZSBhYmxlIHRvIGRldmVsb3AgdGhlIGNvZGUgZm9yIGdlbmVyYXRpbmcgcmFuZG9tIHBvcnRmb2xpb3MuIApgYGB7cn0KIyBEZWZpbmUgYSBzaW1wbGUgZnVuY3Rpb24gdG8gZ2VuZXJhdGUgcmFuZG9tIHBvcnRmb2xpb3MKcmFuZG9tX3BvcnRmb2xpb3MgPC0gZnVuY3Rpb24obnVtX3BvcnRmb2xpb3MsIHJldHVybnMsIG51bV9hc3NldHMpIHsKICAgIHBvcnRmb2xpb19yZXR1cm5zIDwtIG51bWVyaWMobnVtX3BvcnRmb2xpb3MpCiAgICBwb3J0Zm9saW9fcmlza3MgPC0gbnVtZXJpYyhudW1fcG9ydGZvbGlvcykKICAgIHBvcnRmb2xpb193ZWlnaHRzIDwtIG1hdHJpeChucm93ID0gbnVtX3BvcnRmb2xpb3MsIG5jb2wgPSBudW1fYXNzZXRzKQogICAgCiAgICBmb3IgKGkgaW4gMTpudW1fcG9ydGZvbGlvcykgewogICAgICAgIHdlaWdodHMgPC0gcnVuaWYobnVtX2Fzc2V0cykKICAgICAgICB3ZWlnaHRzIDwtIHdlaWdodHMgLyBzdW0od2VpZ2h0cykKICAgICAgICBwb3J0Zm9saW9fd2VpZ2h0c1tpLCBdIDwtIHdlaWdodHMKICAgICAgICAKICAgICAgICBwb3J0Zm9saW9fcmV0dXJuc1tpXSA8LSBzdW0od2VpZ2h0cyAqIGNvbE1lYW5zKHJldHVybnMpKSAqIDI1MgogICAgICAgIHBvcnRmb2xpb19yaXNrc1tpXSA8LSBzcXJ0KHQod2VpZ2h0cykgJSolIGNvdihyZXR1cm5zKSAlKiUgd2VpZ2h0cykgKiBzcXJ0KDI1MikKICAgIH0KICAgIAogICAgZGF0YS5mcmFtZShSZXR1cm4gPSBwb3J0Zm9saW9fcmV0dXJucywgUmlzayA9IHBvcnRmb2xpb19yaXNrcykKfQoKIyBHZW5lcmF0ZSByYW5kb20gcG9ydGZvbGlvcwpudW1fYXNzZXRzIDwtIGxlbmd0aCh0aWNrZXJzKQpwb3J0Zm9saW9zX2RhdGEgPC0gcmFuZG9tX3BvcnRmb2xpb3MoNTAwMCwgcmV0dXJucywgbnVtX2Fzc2V0cykKYGBgCgpOb3JtYWxseSBpdCBpcyBub3QgaWRlYWwgdG8gcmFuZG9taXplIHBvcnRmb2xpb3Mgb3IgZXZlbiBpdHMgd2VpZ2h0IHNpbmNlIGl0IHdvdWxkIG1lYW4gaWdub3JpbmcgbWFya2V0IGNvbmRpdGlvbnMsIGludmVzdG9yIGdvYWxzLCBhbmQgcmlzayB0b2xlcmFuY2UuIEl0IGFsc28gaW5kaWNhdGVzIHRoYXQgdGhlIGludmVzdG9yIGRvZXMgbm90IHRha2UgaW50byBjb25zaWRlcmF0aW9uIHRoZSBwb3RlbnRpYWwgY29ycmVsYXRpb24gYmV0d2VlbiBhc3NldHMuSXQgdWx0aW1hdGVseSBpcyBhc3N1bWluZyB0aGF0IHRoZXJlIGFyZSBlcXVhbCByZXR1cm5zIGFuZCBlcXVhbCByaXNrIHdoaWNoIGlzIGhpZ2hseSB1bmxpa2VseSBpbiByZWFsLWxpZmUgc2l0dWF0aW9ucy4gSG93ZXZlciwganVzdCBmb3IgdGhlIHB1cnBvc2Ugb2YgcmVjcmVhdGluZyBhIHNpbXBsZSBiYXNpYyBtb2RlbCwgd2UgZGVjaWRlZCB0byByYW5kb21pemUgdGhlbS4gCgpXZSB1c2VkIHRoZSBkYXRhIHRvIHBsb3QgYSBzY2F0dGVyIHBsb3Qgb2YgdGhlIHJhbmRvbWl6ZWQgcG9ydGZvbGlvcyBtYWRlIHVwIG9mIDIwIHN0b2Nrcy4gCmBgYHtyfQojIFZpc3VhbGl6ZSB0aGUgRWZmaWNpZW50IEZyb250aWVyIHVzaW5nIGdncGxvdDIKZ2dwbG90KHBvcnRmb2xpb3NfZGF0YSwgYWVzKHggPSBSaXNrLCB5ID0gUmV0dXJuKSkgKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNCwgY29sb3IgPSAiYmx1ZSIpICsKICAgIGdndGl0bGUoIkVmZmljaWVudCBGcm9udGllciBvZiAyMCBTdG9ja3MiKSArCiAgICB4bGFiKCJBbm51YWxpemVkIFJpc2sgKFZvbGF0aWxpdHkpIikgKwogICAgeWxhYigiQW5udWFsaXplZCBSZXR1cm4iKSArCiAgICB0aGVtZV9taW5pbWFsKCkKCmBgYApXZSB3b3VsZCBleHBlY3QgdGhlIEVmZmljaWVudCBGcm9udGllciB0byBiZWNvbWUgbW9yZSBvZiBhIGN1cnZlZCBsaW5lIGJlbmRpbmcgYXQgbG93IHZvbGF0aWxpdHkgYXMgdGhlIG51bWJlciBvZiBTdG9ja3MgaW4gdGhlIHBvcnRmb2xpbyBpbmNyZWFzZXMuIAoKIyBfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwoKIyAqKkw5IFBvcnRmb2xpbyAtIENBTVAqKgoKI1N0YXRlIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gQ0FQTSBhbmQgTWFya292aXR6CgoqKjEpKiogIEluIE1hcmtvd2l0euKAmXMgdGhlb3J5LCByaXNrIGlzIGRlZmluZWQgYXMgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBwb3J0Zm9saW8gcmV0dXJucy4gSXQgbG9va3MgYXQgYm90aCBzeXN0ZW1hdGljIGFuZCB1bnN5c3RlbWF0aWMgcmlza3MuIENBUE0gZm9jdXNlcyBvbmx5IG9uIHN5c3RlbWF0aWMgcmlzaywgd2hpY2ggaXMgbWVhc3VyZWQgYnkgYmV0YS4gQ0FQTSBhc3N1bWVzIHRoYXQgaW52ZXN0b3JzIGhvbGQgd2VsbC1kaXZlcnNpZmllZCBwb3J0Zm9saW9zIHdoZXJlIHVuc3lzdGVtYXRpYyByaXNrIGlzIG5lZ2xpZ2libGUuCgoqKjIpKiogIE1hcmtvd2l0eiBpcyBwcmltYXJpbHkgdXNlZCBmb3IgcG9ydGZvbGlvIGNvbnN0cnVjdGlvbi4gSXQgaGVscHMgaW52ZXN0b3JzIGFsbG9jYXRlIGFzc2V0cyBpbiBzdWNoIGEgd2F5IHRoYXQgdGhlIHBvcnRmb2xpbyBoYXMgdGhlIGJlc3QgcG9zc2libGUgcmV0dXJuIGZvciBhIGdpdmVuIGxldmVsIG9mIHJpc2suIEluIGNvbnRyYXN0LCBDQVBNIGlzIHByaW1hcmlseSB1c2VkIHRvIGRldGVybWluZSB0aGUgZXhwZWN0ZWQgcmV0dXJuIG9mIGFuIGFzc2V0IGJhc2VkIG9uIGl0cyBzeXN0ZW1hdGljIHJpc2sgcmVsYXRpdmUgdG8gdGhlIG1hcmtldC4gSXQgaXMgYWxzbyB1c2VkIHRvIGRldGVybWluZSB3aGV0aGVyIGEgcGFydGljdWxhciBpbnZlc3RtZW50IG9mZmVycyBhbiBhcHByb3ByaWF0ZSByZXR1cm4gZm9yIGl0cyByaXNrCgoqKjMpKiogIE1hcmtvd2l0eiBmb2N1c2VzIG9uIGZpbmRpbmcgdGhlIGVmZmljaWVudCBmcm9udGllciBhbmQgbWluaW1pemluZyBzdGFuZGFyZCBkZXZpYXRpb24gb2YgcG9ydGZvbGlvLiBJdCBpbnZvbHZlcyBjYWxjdWxhdGluZyB0aGUgY292YXJpYW5jZSBiZXR3ZWVuIHJldHVybiBvZiBhc3NldHMgaW4gdGhlIHBvcnRmb2xpby4gT24gdGhlIG90aGVyIGhhbmQsIHRoZSBrZXkgZXF1YXRpb24gZm9yIENBUE0gaXMgRShSaSkgPSBSZiArIM6yaSAoIEUoUm0pIC0gUmYgKS4KCkluc3RhbGxpbmcgbmVjZXNzYXJ5IHBhY2thZ2VzOgpgYGB7cn0KaW5zdGFsbC5wYWNrYWdlcygicXVhZHByb2ciKQoKbGlicmFyeShxdWFkcHJvZykKCmBgYAoKRG93bmxvYWQgaGlzdG9yaWMgZGF0YSBhbmQgc2VlIHJldHVybnMuIChmb3IgTWV0YSwgTnZpZGlhIGFuZCBNb3JnYW4gU3RhbmxleSkKYGBge3J9CnN5bWJvbHMgPC0gYygiTUVUQSIsICJOVkRBIiwgIkpQTSIpCgpnZXRTeW1ib2xzKHN5bWJvbHMsIGZyb209IjIwMjAtMDEtMDEiLCB0bz0iMjAyMy0xMi0zMSIpCgpyZXR1cm5zIDwtIG5hLm9taXQoUk9DKG1lcmdlKE1FVEFbLDZdLCBOVkRBWyw2XSwgSlBNWyw2XSksIHR5cGU9ImRpc2NyZXRlIikpCmNvbG5hbWVzKHJldHVybnMpIDwtIHN5bWJvbHMKCmhlYWQocmV0dXJucykKYGBgCgpXZSBub3cgaGF2ZSBkYWlseSByZXR1cm5zIGZvciBkaWZmZXJlbnQgY29tcGFuaWVzIGluIGRpZmZlcmVudCBzZWN0b3JzIG9mIHRlY2hub2xvZ3ksIHNlbWljb25kdWN0b3JzIGFuZCBmaW5hbmNpYWxzLgoKVGhlc2Ugc2VjdG9ycyByZXByZXNlbnQgc29tZS13aGF0IHZhcnlpbmcgcmlzay1yZXR1cm4gcHJvZmlsZXMsIHVzZWZ1bCBmb3IgcG9ydGZvbGlvIGRpdmVyc2lmaWNhdGlvbiBhbmFseXNpcy4KCiMgQ0FQTSBBbmFseXNpczoKCmBgYHtyfQojIERlZmluZSBwYXJhbWV0ZXJzIGZvciBDQVBNCiMgQmV0YSB3YXMgZm91bmQgYmFzZWQgb24gc2Nob29sIHRlcm0gClJmIDwtIDAuMDM4ICAgICAgICAjIFJpc2stZnJlZSByYXRlIGFzIGNhbGN1bGF0ZWQgYWJvdmUgcXVlc3Rpb24KUm0gPC0gMC4wODEgICAgICAgICAgICMgRXhwZWN0ZWQgbWFya2V0IHJldHVybgpCZXRhX01FVEEgPC0gMS4zMSAgICAKQmV0YV9OVkRBIDwtIDEuNjQgICAgCkJldGFfSlBNIDwtIDEuMjUgICAgIAoKIyBDQVBNIEV4cGVjdGVkIFJldHVybnMKRXhfUmVfTUVUQSA8LSBSZiArIEJldGFfTUVUQSAqIChSbSAtIFJmKQpFeF9SZV9OVkRBIDwtIFJmICsgQmV0YV9OVkRBICogKFJtIC0gUmYpCkV4X1JlX0pQTSA8LSBSZiArIEJldGFfSlBNICogKFJtIC0gUmYpCgojIE91dHB1dCBDQVBNIHJlc3VsdHMKY2F0KCJFeHBlY3RlZCBSZXR1cm4gKENBUE0pIGZvciBNRVRBOiIsIHJvdW5kKEV4X1JlX01FVEEgKiAxMDAsIDIpLCAiJVxuIikKY2F0KCJFeHBlY3RlZCBSZXR1cm4gKENBUE0pIGZvciBOVkRBOiIsIHJvdW5kKEV4X1JlX05WREEgKiAxMDAsIDIpLCAiJVxuIikKY2F0KCJFeHBlY3RlZCBSZXR1cm4gKENBUE0pIGZvciBKUE06Iiwgcm91bmQoRXhfUmVfSlBNICogMTAwLCAyKSwgIiVcbiIpCgpgYGAKCk1FVEEgYW5kIE5WREEgZXhoaWJpdCBoaWdoZXIgZXhwZWN0ZWQgcmV0dXJucyBkdWUgdG8gdGhlaXIgaGlnaGVyIGJldGFzLCByZWZsZWN0aW5nIGdyZWF0ZXIgc2Vuc2l0aXZpdHkgdG8gbWFya2V0IG1vdmVtZW50cy4KCkpQTSwgd2l0aCBhIGxvd2VyIGJldGEsIGhhcyBhIGxvd2VyIGV4cGVjdGVkIHJldHVybiwgaW5kaWNhdGluZyBsb3dlciBzeXN0ZW1hdGljIHJpc2sgZXhwb3N1cmUuCgpUaGVyZWZvcmUsIGludmVzdG9ycyBzZWVraW5nIGhpZ2hlciByZXR1cm5zIG1heSBsZWFuIHRvd2FyZHMgTUVUQSBvciBOVkRBIGJ1dCBtdXN0IGFjY2VwdCBoaWdoZXIgdm9sYXRpbGl0eS4gSlBNIHByb3ZpZGVzIHN0YWJpbGl0eSB3aXRoIGxvd2VyIHJldHVybnMuCgoKIyBNYXJrb3dpdHogUG9ydGZvbGlvIE9wdGltaXphdGlvbgoKYGBge3J9CiNDYWxjdWxhdGUgbWVhbiByZXR1cm5zICYgY292YXJpYW5jZTogCm1lYW5fcmV0dXJucyA8LSBjb2xNZWFucyhyZXR1cm5zKQpjb3ZfbWF0cml4IDwtIGNvdihyZXR1cm5zKQoKIyBEZWZpbmUgdGhlIGNvbnN0cmFpbnRzOiAKbnVtX2Fzc2V0cyA8LSBuY29sKHJldHVybnMpCkFtYXQgPC0gY2JpbmQocmVwKDEsIG51bV9hc3NldHMpLCBkaWFnKG51bV9hc3NldHMpKSAKYnZlYyA8LSBjKDEsIHJlcCgwLCBudW1fYXNzZXRzKSkgICAgICAgICAgICAgICAgICAgCkRtYXQgPC0gMiAqIGNvdl9tYXRyaXgKZHZlYyA8LSByZXAoMCwgbnVtX2Fzc2V0cykKCiMgU29sdmUgZm9yIG9wdGltYWwgcG9ydGZvbGlvIHdlaWdodHMKb3B0X3BvcnRmb2xpbyA8LSBzb2x2ZS5RUChEbWF0LCBkdmVjLCBBbWF0LCBidmVjLCBtZXE9MSkKd2VpZ2h0cyA8LSBvcHRfcG9ydGZvbGlvJHNvbHV0aW9uCgojIENhbGN1bGF0ZSBleHBlY3RlZCBwb3J0Zm9saW8gcmV0dXJuIGFuZCByaXNrIGFjY29yZGluZyB0byBmb3JtdWxhCmV4cGVjdGVkX3BvcnRmb2xpb19yZXR1cm4gPC0gc3VtKG1lYW5fcmV0dXJucyAqIHdlaWdodHMpCnBvcnRmb2xpb19yaXNrIDwtIHNxcnQodCh3ZWlnaHRzKSAlKiUgY292X21hdHJpeCAlKiUgd2VpZ2h0cykKCmBgYAoKUG9ydGZvbGlvIHJlc3VsdHM6CmBgYHtyfQpjYXQoIk9wdGltYWwgUG9ydGZvbGlvIFdlaWdodHMgKE1hcmtvd2l0eik6XG4iKQpwcmludChyb3VuZCh3ZWlnaHRzLCA0KSkKY2F0KCJFeHBlY3RlZCBQb3J0Zm9saW8gUmV0dXJuOiIsIHJvdW5kKGV4cGVjdGVkX3BvcnRmb2xpb19yZXR1cm4gKiAxMDAsIDIpLCAiJVxuIikKY2F0KCJQb3J0Zm9saW8gUmlzayAoU3RhbmRhcmQgRGV2aWF0aW9uKToiLCByb3VuZChwb3J0Zm9saW9fcmlzayAqIDEwMCwgMiksICIlXG4iKQoKYGBgCgpUaGUgb3B0aW1hbCB3ZWlnaHRzIHJldmVhbCBob3cgbXVjaCB0byBhbGxvY2F0ZSB0byBNRVRBLCBOVkRBLCBhbmQgSlBNIHRvIGFjaGlldmUgdGhlIGJlc3Qgcmlzay1yZXR1cm4gdHJhZGVvZmYuCgpCeSBjb25zaWRlcmluZyBib3RoIHN5c3RlbWF0aWMgYW5kIHVuc3lzdGVtYXRpYyByaXNrcywgTWFya293aXR6IHByb3ZpZGVzIGEgZGl2ZXJzaWZpZWQgYWxsb2NhdGlvbi4KClRoZXJlZm9yZSwgaW4gdGhlIGNhc2Ugb2Ygcmlzay1hdmVyc2UgaW52ZXN0b3JzLCB0aGlzIGFsbG9jYXRpb24gbWluaW1pemVzIHN0YW5kYXJkIGRldmlhdGlvbiB3aGlsZSBtYXhpbWl6aW5nIHJldHVybnMuCgoKKipCcmllZmx5IGNvbXBhcmluZyBDQVBNIHdpdGggTWFya293aXR6IGJhc2VkIG9uIHRoZSBjYWxjdWxhdGlvbnM6KioKCkNBUE0gaGVscHMgZGVjaWRlIGlmIGFuIGluZGl2aWR1YWwgYXNzZXQgcHJvdmlkZXMgc3VmZmljaWVudCByZXR1cm5zIGZvciBpdHMgcmlzay4KCk1hcmtvd2l0eiBpcyB1c2VmdWwgZm9yIGNvbnN0cnVjdGluZyBhIHBvcnRmb2xpbyB0aGF0IGFjaGlldmVzIG9wdGltYWwgZGl2ZXJzaWZpY2F0aW9uLgoKIyBfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwoKIyAqKkwxMCBXQUNDKioKCioqUmVwbGljYXRlIHRoZSBib29rIGNhc2Ugb2YgV0FDQyoqCgoqKkJvbmQgZGF0YTogTWFya2V0IHZhbHVlcyBhbmQgWWllbGRzIHRvIE1hdHVyaXR5LioqCioqVXNpbmcgYm9uZHM6IE1pY3Jvc29mdCBDb3JwLiA1LjIlIEJvbmQgbWF0dXJpbmcgb24gSnVuZSAxLCAyMDM5LCoqCioqTWljcm9zb2Z0IENvcnAuIDUuMyUgQm9uZCBtYXR1cmluZyBvbiBGZWJydWFyeSA4LCAyMDQxLCoqCioqTWljcm9zb2Z0IENvcnAuIDQuMjUlIEJvbmQgbWF0dXJpbmcgb24gRmVicnVhcnkgNiwgMjA0NyoqCmBgYHtyfQpib25kX3ZhbHVlcyA8LSBjKDFlOSwgMWU5LCAxLjA4ODQ4NWU5KSAgIyBNYXJrZXQgdmFsdWVzIG9mIGJvbmRzIGluIFVTRApib25kX3l0bXMgPC0gYygwLjA0NDIsIDAuMDQ0MiwgMC4wNDI1KSAgIyBZaWVsZHMgdG8gbWF0dXJpdHkgaW4gZGVjaW1hbCBmb3JtCmBgYAoqKkNhbGN1bGF0ZSB0aGUgdG90YWwgbWFya2V0IHZhbHVlIG9mIGJvbmRzOioqCmBgYHtyfQp0b3RhbF92YWx1ZSA8LSBzdW0oYm9uZF92YWx1ZXMpCmBgYAoqKkNhbGN1bGF0ZSB0aGUgd2VpZ2h0cyBmb3IgZWFjaCBib25kIChwcm9wb3J0aW9uIG9mIHRvdGFsIGRlYnQpOioqCmBgYHtyfQp3ZWlnaHRzIDwtIGJvbmRfdmFsdWVzIC8gdG90YWxfdmFsdWUKYGBgCioqQ2FsY3VsYXRlIHRoZSB3ZWlnaHRlZCBhdmVyYWdlIFlpZWxkIHRvIE1hdHVyaXR5IChZVE0pOioqCmBgYHtyfQp3ZWlnaHRlZF9hdmdfeXRtIDwtIHN1bSh3ZWlnaHRzICogYm9uZF95dG1zKQpgYGAKKipPdXRwdXQgdGhlIHByZS10YXggY29zdCBvZiBkZWJ0OioqCmBgYHtyfQpwcmVfdGF4X2Nvc3Rfb2ZfZGVidCA8LSB3ZWlnaHRlZF9hdmdfeXRtCnByZV90YXhfY29zdF9vZl9kZWJ0CmBgYApXZSBoYXZlIHRoZSAqKmNvc3Qgb2YgZGVidCBhdCA0LjM2JSoqCgoqKlRoZSBmZWRlcmFsIHRheCByYXRlIGlzIDIxJSoqCgoqKkRlZmluZSB0aGUgc3RvY2sgKE1pY3Jvc29mdCkgYW5kIG1hcmtldCBpbmRleCAoUyZQIDUwMCk6KioKYGBge3J9CmdldFN5bWJvbHMoIk1TRlQiLCBzcmMgPSAieWFob28iLCBmcm9tID0gIjIwMjAtMDEtMDEiLCB0byA9IFN5cy5EYXRlKCkpCmdldFN5bWJvbHMoIl5HU1BDIiwgc3JjID0gInlhaG9vIiwgZnJvbSA9ICIyMDIwLTAxLTAxIiwgdG8gPSBTeXMuRGF0ZSgpKSAgCmBgYAoqKkV4dHJhY3QgdGhlIGFkanVzdGVkIGNsb3NpbmcgcHJpY2VzOioqCmBgYHtyfQptc2Z0X3ByaWNlcyA8LSBDbChNU0ZUKQpzcDUwMF9wcmljZXMgPC0gQ2woR1NQQykKYGBgCioqQ2FsY3VsYXRlIGRhaWx5IHJldHVybnM6KioKYGBge3J9Cm1zZnRfcmV0dXJucyA8LSBkYWlseVJldHVybihtc2Z0X3ByaWNlcykKc3A1MDBfcmV0dXJucyA8LSBkYWlseVJldHVybihzcDUwMF9wcmljZXMpCmBgYAoqKkNhbGN1bGF0ZSBiZXRhIHVzaW5nIHRoZSBjb3ZhcmlhbmNlIG9mIE1pY3Jvc29mdCBhbmQgdGhlIG1hcmtldCwgZGl2aWRlZCBieSB0aGUgdmFyaWFuY2Ugb2YgdGhlIG1hcmtldDoqKgpgYGB7cn0KYmV0YV9tc2Z0IDwtIGNvdihtc2Z0X3JldHVybnMsIHNwNTAwX3JldHVybnMpIC8gdmFyKHNwNTAwX3JldHVybnMpCmBgYAoqKk91dHB1dCB0aGUgYmV0YSB2YWx1ZSoqCmBgYHtyfQpiZXRhX21zZnQKYGBgCioqV2UgaGF2ZSB0aGUgYmV0YSBhcyAxLjE3NDM0NSoqCgoqKkZvciB0aGUgcmlzayBmcmVlIHJhdGUgd2UgY2FuIHVzZSB0aGUgMTAteWVhciBnb3Zlcm5tZW50IHRyZWFzdXJ5IGJvbmQgeWllbGQuKioKCioqR2V0IHRoZSAxMC15ZWFyIFUuUy4gVHJlYXN1cnkgeWllbGQgZnJvbSBGUkVEOioqCmBgYHtyfQpnZXRTeW1ib2xzKCJHUzEwIiwgc3JjID0gIkZSRUQiKQpgYGAKKipTaG93IHRoZSBsYXRlc3QgdmFsdWUgb2YgdGhlIDEwLXllYXIgVHJlYXN1cnkgeWllbGQ6KioKYGBge3J9CmxhdGVzdF9yaXNrX2ZyZWVfcmF0ZSA8LSB0YWlsKEdTMTBbLCAxXSwgMSkKbGF0ZXN0X3Jpc2tfZnJlZV9yYXRlCmBgYApIZXJlIHdlIHNlZSB0aGUgKipyaXNrIGZyZWUgcmF0ZSBpcyA0LjM5JS4qKgoKKipIaXN0b3JpY2FsbHksIHRoZSBleHBlY3RlZCBtYXJrZXQgcmV0dXJuIHJhdGUgaXMgOC0xMCUuKiogRm9yIHRoaXMgY2Fzc2Ugd2Ugd2lsbCB1c2UgOCUgdG8gZ2V0IHRoZSBtYXJrZXQgcmlzayBwcmVtaXVtLgpgYGB7cn0KZXhwZWN0ZWRfbWFya2V0X3JldHVybiA8LSAwLjA4CmBgYAoqKkdldCB0aGUgY3VycmVudCAxMC15ZWFyIFUuUy4gVHJlYXN1cnkgeWllbGQgZnJvbSBGUkVEOioqCmBgYHtyfQpnZXRTeW1ib2xzKCJHUzEwIiwgc3JjID0gIkZSRUQiKQpyaXNrX2ZyZWVfcmF0ZSA8LSB0YWlsKEdTMTBbLCAxXSwgMSkgLyAxMDAgIApgYGAKKipDYWxjdWxhdGUgdGhlIG1hcmtldCByaXNrIHByZW1pdW06KioKYGBge3J9Cm1hcmtldF9yaXNrX3ByZW1pdW0gPC0gZXhwZWN0ZWRfbWFya2V0X3JldHVybiAtIHJpc2tfZnJlZV9yYXRlCm1hcmtldF9yaXNrX3ByZW1pdW0KYGBgCkhlcmUgd2UgZ2V0IHRoZSAqKm1hcmtldCByaXNrIHByZW1pdW0gdG8gYmUgMy42MSUuKioKCioqTm93IHdlIGhhdmUgb3VyIGRhdGEsIHdlIGNhbiBnbyBhaGVhZCB3aXRoIHRoZSBXQUNDIGNhbGN1bGF0aW9uLioqCgoqKk1pY3Jvc29mdCBjdXJyZW50bHkgaGFzIHNwcHJveGltYXRlbHkgNy40MzMgYmlsbGlvbiBvdXRzdGFuZGluZyBzaGFyZXMqKgoKKipXZSBjYW4gY2FsY3VsYXRlIHRoZSBtYXJrZXQgY2FwaXRhbGlzYXRpb246KioKYGBge3J9Cm1hcmtldF9jYXAgPC0gbGFzdChNU0ZUJE1TRlQuQWRqdXN0ZWQpICogNzQzMzAwMDAwMApgYGAKKipXZSB3aWxsIG5vdyB1c2UgdGhlIGZvbGxvd2luZyB2YXJpYWJsZXMgZGVmaW5lZCBwcmV2aW91c2x5OioqCmBgYHtyfQpjb3N0X29mX2RlYnQgPC0gMC4wNDYKdGF4X3JhdGUgPC0gMC4yMQpiZXRhIDwtIDEuMTcKcmlza19mcmVlX3JhdGUgPC0wLjA0MzkKbWFya2V0X3Jpc2tfcHJlbWl1bSA8LSAwLjAzNjEKYGBgCioqTm93IGNhbGN1bGF0ZSB0aGUgY29zdCBvZiBlcXVpdHkgdXNpbmcgQ0FQTToqKgpgYGB7cn0KY29zdF9vZl9lcXVpdHkgPC0gcmlza19mcmVlX3JhdGUgKyBiZXRhICogbWFya2V0X3Jpc2tfcHJlbWl1bQpgYGAKKipCYXNlZCBvZmYgTWljcm9zb2Z0J3MgZmluYW5jaWFsIHN0YXRlbWVudHMgdGhlaXIgbWFya2V0IHZhbHVlIG9mIGRlYnQgaXMqKiA2MS40NyBiaWxsaW9uLgpgYGB7cn0KbWFya2V0X3ZhbHVlX29mX2RlYnQgPC0gNjEuNDdlOQpgYGAKKipDYWxjdWxhdGUgdG90YWwgbWFya2V0IHZhbHVlOioqCmBgYHtyfQp0b3RhbF9tYXJrZXRfdmFsdWUgPC0gbWFya2V0X2NhcCArIG1hcmtldF92YWx1ZV9vZl9kZWJ0CmBgYAoqKkNhbGN1bGF0ZSB3ZWlnaHRzIG9mIGRlYnQgYW5kIGVxdWl0eToqKgpgYGB7cn0Kd2VpZ2h0X29mX2RlYnQgPC0gbWFya2V0X3ZhbHVlX29mX2RlYnQgLyB0b3RhbF9tYXJrZXRfdmFsdWUKd2VpZ2h0X29mX2VxdWl0eSA8LSBtYXJrZXRfY2FwIC8gdG90YWxfbWFya2V0X3ZhbHVlCmBgYAoqKkNhbGN1bGF0ZSBXQUNDIGZvciBNaWNyb3NvZnQ6KioKYGBge3J9CndhY2MgPC0gKHdlaWdodF9vZl9kZWJ0ICogY29zdF9vZl9kZWJ0ICogKDEgLSB0YXhfcmF0ZSkpICsgKHdlaWdodF9vZl9lcXVpdHkgKiBjb3N0X29mX2VxdWl0eSkKCmNhdCgiV0FDQyBmb3IgTWljcm9zb2Z0OiIsIHdhY2MgKiAxMDAsICIlIikKYGBgCiMgV2Ugc2VlIGhlcmUgTWljcm9zb2Z0J3MgKipXQUNDIGlzIDguNTIlLioqCgoKIyBfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwoKIyAqKkwxMSBEZXJpdmF0aXZlcyoqCgoqKkwxMS4xKioKCmBgYHtyfQojIFMmUCA1MDAgRnV0dXJlcyBQYXJhbWV0ZXJzCkJvVF9mdXR1cmVzX3ByaWNlIDwtIDUxNTguMDAKRW9UX2Z1dHVyZXNfcHJpY2UgPC0gNTgxNC4yNQpjb250cmFjdF9tdWx0aXBsaWVyIDwtIDI1MAoKIyBEb2xsYXIgdmFsdWVzCkJvVF92YWx1ZSA8LSBCb1RfZnV0dXJlc19wcmljZSAqIGNvbnRyYWN0X211bHRpcGxpZXIKRW9UX3ZhbHVlIDwtIEVvVF9mdXR1cmVzX3ByaWNlICogY29udHJhY3RfbXVsdGlwbGllcgoKIyBEaWZmZXJlbmNlCmZ1dHVyZXNfZGlmZmVyZW5jZSA8LSBFb1RfdmFsdWUgLSBCb1RfdmFsdWUKcHJpbnQocGFzdGUoIkRpZmZlcmVuY2UgaW4gY29udHJhY3QgdmFsdWU6IiwgZnV0dXJlc19kaWZmZXJlbmNlLCAiVVNEIikpCgpmdXR1cmVzX2RpZmZlcmVuY2UvKDAyKkJvVF92YWx1ZSkKYGBgCgoqKkwxMS4yKioKCmBgYHtyfQojIE1hcmdpbiBhbmQgSW5pdGlhbCBJbnZlc3RtZW50CmluaXRpYWxfbWFyZ2luIDwtIDAuMjAKaW5pdGlhbF9pbnZlc3RtZW50IDwtIEJvVF92YWx1ZSAqIGluaXRpYWxfbWFyZ2luCgojIFJldHVybiBvbiBGdXR1cmVzIFBvc2l0aW9uCmZ1dHVyZXNfcmV0dXJuIDwtIGZ1dHVyZXNfZGlmZmVyZW5jZSAvIGluaXRpYWxfaW52ZXN0bWVudApwcmludChwYXN0ZSgiUmV0dXJuIGZyb20gZnV0dXJlcyBwb3NpdGlvbjoiLCByb3VuZChmdXR1cmVzX3JldHVybiAqIDEwMCwgMiksICIlIikpCmBgYApXZSBjYW4gc2F5IHRoYXQgdGhpcyA2My42MSUgcmV0dXJuIGZyb20gYW4gUyZQIDUwMCBmdXR1cmVzIHBvc2l0aW9uIGhpZ2hsaWdodHMgc3VjY2Vzc2Z1bCBsZXZlcmFnZSB1c2UgYW5kIGZhdm9yYWJsZSBtYXJrZXQgY29uZGl0aW9ucyBmb3IgdGhlIHN0cmF0ZWd5IHVzZWQuIEJ1dCBhdCB0aGUgc2FtZSB0aW1lIGl0IGFsc28gcmVtaW5kcyBvZiB0aGUgdm9sYXRpbGUgYW5kIHJpc2t5IG5hdHVyZSBvZiBmdXR1cmVzIHRyYWRpbmcuIAoKKipMMTEuMyoqCgpgYGB7cn0KIyBTY2hvb2wgdGVybSBkdXJhdGlvbiAoaW4gbW9udGhzKQpzY2hvb2xfdGVybV9tb250aHMgPC0gNQoKIyBBbm51YWxpemVkIFJldHVybgphbm51YWxpemVkX3JldHVybiA8LSBmdXR1cmVzX3JldHVybiAqICgxMiAvIHNjaG9vbF90ZXJtX21vbnRocykKcHJpbnQocGFzdGUoIkFubnVhbGl6ZWQgcmV0dXJuOiIsIHJvdW5kKGFubnVhbGl6ZWRfcmV0dXJuICogMTAwLCAyKSwgIiUiKSkKCmBgYAoKKipMMTEuNCoqCgpXZSB3aWxsIHVzZSBmb3IgdGhpcyBzZWN0aW9uIHRoZSBDaGV2cm9uIENvcnBvcmF0aW9uIChDVlgpIFN0b2NrClNpbmNlIHdlIGNvdWxkJ24ndCBmaW5kIHRoZSBwcmVtaXVtIGZvciB0aGUgdGVybXMsIHdlIGFzc3VtZWQgQm9UX3ByZW1pdW0gdG8gYmUgdGhlIHN0cmlrZSBwcmljZSBhbmQgRW9UX3ByZW1pdW0gdG8gYmUgdGhlIG1hcmtldCBwcmljZSBhdCB0aGUgZW5kIG9mIHRoZSB0ZXJtCmBgYHtyfQojIENhbGwgT3B0aW9uIFBhcmFtZXRlcnMKQm9UX3N0b2NrX3ByaWNlIDwtIDE1NC43MDY5CkVvVF9zdG9ja19wcmljZSA8LSAxNDUuNzgyOQpzdHJpa2VfcHJpY2UgPC0gMTUwCkJvVF9wcmVtaXVtIDwtIDEwLjMyIApFb1RfcHJlbWl1bSA8LSAxNi4wNQoKIyBPcHRpb24gUmV0dXJuCm9wdGlvbl9yZXR1cm4gPC0gKEVvVF9wcmVtaXVtIC0gQm9UX3ByZW1pdW0pIC8gQm9UX3ByZW1pdW0KcHJpbnQocGFzdGUoIkNhbGwgb3B0aW9uIHJldHVybjoiLCByb3VuZChvcHRpb25fcmV0dXJuICogMTAwLCAyKSwgIiUiKSkKCmBgYApBY2hpZXZpbmcgYSA1NS41MiUgcmV0dXJuIG9uIGEgY2FsbCBvcHRpb24gc2lnbmFscyBhIHN1Y2Nlc3NmdWwgaW52ZXN0bWVudCwgc2luY2UgdGhlIHVuZGVybHlpbmcgYXNzZXQgc3VycGFzc2VkIHRoZSBzdHJpa2UgcHJpY2Ugc2lnbmlmaWNhbnRseS4gVGhpcyBwb3J0cmF5cyB0aGUgbGV2ZXJhZ2UgZWZmZWN0IG9mIG9wdGlvbnMsIHdoZXJlIHNtYWxsIG1hcmtldCBtb3ZlbWVudHMgY2FuIGdyZWF0bHkgYW1wbGlmeSByZXR1cm5zLiBIb3dldmVyLCB0aGlzIGFsc28gaGlnaGxpZ2h0cyB0aGUgaW1wb3J0YW5jZSBvZiBwcmVjaXNlIG1hcmtldCB0aW1pbmcgYW5kIGNhcmVmdWwgcmlzayBtYW5hZ2VtZW50LCBhcyBvcHRpb25zIGFyZSBwYXJ0aWN1bGFybHkgc2Vuc2l0aXZlIHRvIHRpbWluZyBhbmQgbWFya2V0IHZvbGF0aWxpdHkuIFRodXMsIGl0IHdvdWxkIGJlIGFsc28gdXNlZnVsIHRvIGNvbnNpZGVyIG9wdGlvbnMgYXMgYSB3YXkgb2YgaGVkZ2luZyBpbiBwb3J0Zm9saW9zLiAKCioqTDExLjUqKgoKYGBge3J9CiMgQW5udWFsaXplZCBSZXR1cm4KYW5udWFsaXplZF9vcHRpb25fcmV0dXJuIDwtIG9wdGlvbl9yZXR1cm4gKiAoMTIgLyBzY2hvb2xfdGVybV9tb250aHMpCnByaW50KHBhc3RlKCJBbm51YWxpemVkIGNhbGwgb3B0aW9uIHJldHVybjoiLCByb3VuZChhbm51YWxpemVkX29wdGlvbl9yZXR1cm4gKiAxMDAsIDIpLCAiJSIpKQpgYGAKCioqTDExLjYqKgoKYGBge3J9CiMgU3RvY2sgUmV0dXJuCnN0b2NrX3JldHVybiA8LSAoRW9UX3N0b2NrX3ByaWNlIC0gQm9UX3N0b2NrX3ByaWNlKSAvIEJvVF9zdG9ja19wcmljZQpwcmludChwYXN0ZSgiU3RvY2sgcmV0dXJuOiIsIHJvdW5kKHN0b2NrX3JldHVybiAqIDEwMCwgMiksICIlIikpCnByaW50KHBhc3RlKCJPcHRpb24gcmV0dXJuIGlzIiwgcm91bmQob3B0aW9uX3JldHVybiAvIHN0b2NrX3JldHVybiwgMiksICJ0aW1lcyB0aGUgc3RvY2sgcmV0dXJuLiIpKQoKYGBgCgojIERldGVybWluaW5nIHN3YXAgcGF5bWVudHMKCioqTDExLjcqKgoKYGBge3J9CiMgU3dhcCBQYXJhbWV0ZXJzCm5vdGlvbmFsX2Ftb3VudCA8LSAxMDAwMDAwMApmaXhlZF9yYXRlIDwtIDAuMDYKZmxvYXRpbmdfcmF0ZSA8LSAwLjA0MjMKCiMgUGF5bWVudHMKZml4ZWRfcGF5bWVudCA8LSBub3Rpb25hbF9hbW91bnQgKiBmaXhlZF9yYXRlCmZsb2F0aW5nX3BheW1lbnQgPC0gbm90aW9uYWxfYW1vdW50ICogZmxvYXRpbmdfcmF0ZQpzd2FwX2RpZmZlcmVuY2UgPC0gZml4ZWRfcGF5bWVudCAtIGZsb2F0aW5nX3BheW1lbnQKCiMgUmVzdWx0cwpwcmludChwYXN0ZSgiRml4ZWQgcGF5bWVudDoiLCBmaXhlZF9wYXltZW50LCAiVVNEIikpCnByaW50KHBhc3RlKCJGbG9hdGluZyBwYXltZW50OiIsIGZsb2F0aW5nX3BheW1lbnQsICJVU0QiKSkKcHJpbnQocGFzdGUoIk5ldCBzd2FwIGRpZmZlcmVuY2U6Iiwgc3dhcF9kaWZmZXJlbmNlLCAiVVNEIikpCgpgYGAKV2UgZ2FpbmVkICQxNzcsMDAwIGZyb20gdGhlIHN3YXAgYmVjYXVzZSB0aGUgZml4ZWQgcmF0ZSB3ZSBhZ3JlZWQgdG8gcGF5IHdoaWNoIHdhcyA2JSwgIHdhcyBoaWdoZXIgdGhhbiB0aGUgZXF1aXZhbGVudCBULWJpbGwgcmF0ZSBhdCB0aGUgZW5kIG9mIHRoZSBzY2hvb2wgdGVybSBwZXJpb2QuIEVzc2VudGlhbGx5LCB0aGlzIG1lYW5zIHRoYXQgdGhlIGludGVyZXN0IHJhdGUgZW52aXJvbm1lbnQgd29ya2VkIGluIG91ciBmYXZvciwgd2l0aCBsb3dlciB0aGFuIGV4cGVjdGVkIGZsb2F0aW5nIHJhdGVzIGNvbXBhcmVkIHRvIG91ciBmaXhlZCByYXRlIGNvbW1pdG1lbnQsIHdoaWNoIHVsdGltYXRlbHkgbGVhZCB0byBhIG5ldCBiZW5lZml0IGZyb20gdGhlIHN3YXAuCgojIE1lYXN1cmluZyBhbmQgZXhwbGFpbmluZyBleGNoYW5nZSByYXRlIG1vdmVtZW50cwoKYGBge3J9CiMgRXhjaGFuZ2UgUmF0ZXMKQm9UX3JhdGVzIDwtIGMoR0JQID0gMS4yNTI1LCBKUFkgPSAwLjAwNjQsIE1YTiA9IDAuMDU4OCkKRW9UX3JhdGVzIDwtIGMoR0JQID0gMS4zMzcwLCBKUFkgPSAwLjAwNjksIE1YTiA9IDAuMDUwNikKCiMgQ2FsY3VsYXRlIHBlcmNlbnRhZ2UgY2hhbmdlcwpwZXJjZW50YWdlX2NoYW5nZXMgPC0gKEVvVF9yYXRlcyAtIEJvVF9yYXRlcykgLyBCb1RfcmF0ZXMgKiAxMDAKYGBgCgoqKkwxMS44KioKCmBgYHtyfQpwcmludChwYXN0ZSgiR0JQIENoYW5nZToiLCByb3VuZChwZXJjZW50YWdlX2NoYW5nZXNbIkdCUCJdLCAyKSwgIiUiKSkKYGBgClRoZSBwb3VuZCBhcHByZWNpYXRlZCBhZ2FpbnN0IHRoZSBVUyBEb2xsYXIKCioqMTEuOSoqCgpgYGB7cn0KcHJpbnQocGFzdGUoIkpQWSBDaGFuZ2U6Iiwgcm91bmQocGVyY2VudGFnZV9jaGFuZ2VzWyJKUFkiXSwgMiksICIlIikpCmBgYApUaGUgWWVuIGFwcHJlY2lhdGVkIGFnYWluc3QgdGhlIFVTIERvbGxhcgoKKipMMTEuMTAqKgoKYGBge3J9CnByaW50KHBhc3RlKCJNWE4gQ2hhbmdlOiIsIHJvdW5kKHBlcmNlbnRhZ2VfY2hhbmdlc1siTVhOIl0sIDIpLCAiJSIpKQpgYGAKVGhlIFBlc28gZGVjcmVjaWF0ZWQgYWdhaW5zdCB0aGUgVVMgRG9sbGFyCgoqKkwxMS4xMioqCgpgYGB7cn0KIyBCcml0aXNoIFBvdW5kIEZ1dHVyZXMKQm9UX0dCUF9wcmljZSA8LSAxLjI1MjUKRW9UX0dCUF9wcmljZSA8LSAxLjMzNzAKCiMgSXMgaXQgYSBnYWluIG9yIGxvc3MgUGVyIHVuaXQ/CkdCUF9wZXJfdW5pdF9nYWluIDwtIEVvVF9HQlBfcHJpY2UgLSBCb1RfR0JQX3ByaWNlCnByaW50KHBhc3RlKCJQZXIgdW5pdCBnYWluIG9uIEdCUCBmdXR1cmVzOiIsIHJvdW5kKEdCUF9wZXJfdW5pdF9nYWluLCA0KSwgIlVTRCIpKQoKYGBgCgoqKkwxMS4xMioqCgpgYGB7cn0KIyBDb250cmFjdCBzaXplIGZvciBCcml0aXNoIFBvdW5kIEZ1dHVyZXMKY29udHJhY3Rfc2l6ZSA8LSA2MjUwMAoKIyBUb3RhbCBnYWluIG9yIGxvc3MKR0JQX3RvdGFsX2dhaW4gPC0gR0JQX3Blcl91bml0X2dhaW4gKiBjb250cmFjdF9zaXplCnByaW50KHBhc3RlKCJUb3RhbCBnYWluIG9uIEdCUCBmdXR1cmVzOiIsIHJvdW5kKEdCUF90b3RhbF9nYWluLCAyKSwgIlVTRCIpKQoKYGBgCgojIF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCgojICoqTDEyIENhcGl0YWwgcmVxdWlyZW1lbnRzKioKKipMMTIuMSoqCgpCb3RoIEJhbmsgb2YgQW1lcmljYSBhbmQgRGV1dHNjaGUgQmFuayBtYWludGFpbiBzdHJvbmcgY2FwaXRhbCBidWZmZXJzIHRvIG1hbmFnZSByaXNrcyBhbmQgbWVldCwgaW5mYWN0IGV4Y2VlZCB0aGVpciByZXNwZWN0aXZlIHJlZ3VsYXRvcnkgcmVxdWlyZW1lbnRzLiAKCkJ1dCwgaWYgd2Ugd2FudCB0byBjb21wYXJlIHdoaWNoIGhhcyBhIGJldHRlciBjYXBpdGFsIGJhc2U6CkJ5IHRoZSBlbmQgb2YgMjAyMywgQ29tbW9uIEVxdWl0eSBUaWVyIDEgKENFVDEpIHJhdGlvLCBhIG1lYXN1cmUgb2YgZmluYW5jaWFsIHN0cmVuZ3RoIGZvciBEZXV0c2NoZSBCYW5r4oCZcyB3YXMgMTMuNyUuIFRoaXMgaXMgaGlnaGVyIHRoYW4gQmFuayBvZiBBbWVyaWNh4oCZcyAxMS42JS4gVGhlc2UgcmF0aW9zIGluZGljYXRlIGhvdyBtdWNoIGNvcmUgY2FwaXRhbCBlYWNoIGJhbmsgaG9sZHMgcmVsYXRpdmUgdG8gdGhlaXIgcmlzay13ZWlnaHRlZCBhc3NldHMsIHdoaWNoIGFyZSBhZGp1c3RlZCBmb3IgdGhlIGxpa2VsaWhvb2Qgb2YgcG90ZW50aWFsIGxvc3Nlcy4gQm90aCBiYW5rcyBjb21mb3J0YWJseSBleGNlZWQgdGhlaXIgbWluaW11bSBDRVQxIHJlcXVpcmVtZW50cyB3aGljaCBpcyA5LjUlIGZvciBCYW5rIG9mIEFtZXJpY2EgYW5kIDEwLjU1JSBmb3IgRGV1dHNjaGUgQmFuay4gVGhlc2UgIHJlZ3VsYXRvcnkgbWluaW11bXMgYXJlIHNldCB0byBlbnN1cmUgdGhhdCBiYW5rcyBjYW4gYWJzb3JiIGxvc3NlcyBkdXJpbmcgZWNvbm9taWMgc3RyZXNzLiBUaGVyZWZvcmUsIGV4Y2VzcyBjYXBpdGFsIGFib3ZlIHRoZXNlIGxldmVscyBwcm92aWRlcyBhIGN1c2hpb24gZm9yIHVuZXhwZWN0ZWQgcmlza3MuIEFzIGEgcmVzdWx0LCBEZXV0c2NoZSBCYW5r4oCZcyBoaWdoZXIgQ0VUMSByYXRpbyBhbmQgcmVkdWN0aW9uIG9mIOKCrDEzIGJpbGxpb24gaW4gcmlzay13ZWlnaHRlZCBhc3NldHMsIHN1Z2dlc3QgaXQgaGFzIGEgcmVsYXRpdmVseSBzdHJvbmdlciBidWZmZXIgYWdhaW5zdCBwb3RlbnRpYWwgbG9zc2VzLCBlbmhhbmNpbmcgaXRzIGZpbmFuY2lhbCBzdGFiaWxpdHkgb3ZlciBCYW5rIG9mIEFtZXJpY2EuCgojIF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f