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