Workshop 2, Finacial Programming

Data Structures

Lists

Lists are R objects that can store elements of different classes, oposite to vectors which can be used to store elements of the same class only. Each element of a list can be of any object class such as data frames, numeric vectors, matrices or even list. For example, we can create a list to store information of a financial portfolio.

I will create a list that represents information of a financial portfolio. I first create the elements of the portfolio:

# Create vectors for stock tickers and expected stock returns:
tickers <- c("AAPL","AMZN","WMT")
expected_stock_returns <- c(0.020,0.015,0.010)
expected_stock_risk <- c(0.04,0.045,0.02)
tickers
expected_stock_returns
expected_stock_risk

Now I will indicate how much (in %) I will allocate for each asset in my portfolio. I will assign 50% to Apple, and 25% to Amazon and Wal-Mart. I create a vector with these weights (in decimal):

stock_weights <- c(0.50,0.25,0.25)

Now I will calculate the expected portfolio return as a weighted average the stock expected returns:

weighted_returns <- expected_stock_returns*stock_weights
weighted_returns

When you multiply 2 vectors you get an element-by-element multiplication. This is called a “vectorization” operation. By default R “vectorizes” mathematical operations. This means the first element of the first vector is multiplied by the first element of the second vector. The same for the 2nd. and 3rd. elements of each vector.

Now I just sum all the elements of this vector that contains the weighted returns to get the expected return of my portfolio:

expected_portfolio_return <- sum(weighted_returns) 

I used the function sum to the weighted_returns vector, so each element of the vector is added to get the expected portfolio return.

I now create a list with all these pieces of information of my portfolio. I use the function list() to create the portfolio object as a list that contains the tickers vector, and the vectors for expected stock return, expected stock risk, stock weights and the expected portfolio return:

portfolio1 <- list(tickers, expected_stock_returns, expected_stock_risk, 
                   stock_weights, expected_portfolio_return)
# I assign names to each element of the portfolio:
names(portfolio1)<-c("Tickers","Stock_returns","Stock_risk","Stock_weights",
                     "Portfolio expected Return")
# I display the portfolio object:
portfolio1

I can access the elements of the portfolio1 list using either the name of each element, or the number of the element using double squared brackets[[]]:

# I display the expected stock tickers:
portfolio1$Tickers
# I can also display expected stock tickers using the element number and double
#  brackets:
portfolio1[[1]]
# I display the class and length of the first element:
class(portfolio1$Tickers)
length(portfolio1$Tickers)

The xts data class

R has different data classes (or R objects). Actually, you can create your own data class, which is a set one or more data structures. For time series datasets, which are very common in Finance, the most popular data classes are: ts, zoo and xts. xts stands for extensible time series class. An xts object contains a set of columns that can be of any type (alphabetic, numeric, boolean) and it has a time index. All xts objects are usually sorted chronologically.

The index of an xts object is like the first column of the object, but it is actually its index; it is not considered a column of the object. An xts object has the advantage that we can apply several functions to that object for data merging, sorting, selecting, etc.

Try the following example. Download a sample dataset called edhec, which comes with the PerformanceAnalytics package. In R, we can use thousands of available packages to do different types of calculations and operations. PerformanceAnalytics package is a package with many functions related to Financial analytics. We will use some of these functions later in the course.

we need the PerformanceAnalytics package, so you can install it from the Package menu (right-bottom of your RStudio).

Once the package is installed in my computer, I do not need to re-install it again. However, each time I need to use the package, I need to load it into memory:

library(PerformanceAnalytics)

I download the sample dataset edhec, which contains monthly returns of different hedge fund indexes created by the EDHEC Risk Institute.

data("edhec")

The edhec dataset will appear in my Global Environment.

edhec is an xts R object that contains historical monthly returns of different hedge fund indexes. We can easily do different calculations with specific functions that apply to xts objects. For now, we will learn how to do subsetting with xts objects.

If you want to know more functions for the xts R objects, you can check the xts CheatSheet at: https://s3.amazonaws.com/assets.datacamp.com/blog_assets/xts_Cheat_Sheet_R.pdf

Subsetting data

R has powerful indexing features for accessing object elements. These features can be used to select and exclude columns and rows (observations). In the next paragraphs we will learn how to extract the information we want from an xts object. Several of these functions also apply to data frames.

I see the structure of the edhec R dataset and the first and last rows:

str(edhec)
head(edhec)
tail(edhec)

From the results above, we see that this xts object has 13 columns, which are returns of different hedge fund indexes.

I can subset either rows, columns or both. For example I can select in which months the Emeging market fund has had negative returns:

 negative_returns_em <- edhec[edhec$`Emerging Markets`<0,4]
# I display the first rows of this new object, which has only negative returns for Emerging Markets:
head(negative_returns_em)
 negative_returns_em_all <- edhec[edhec$`Emerging Markets`<0,]
 head(negative_returns_em_all)

As you see, to do subsetting I use squared brackets afher the object, and the first number refers to the ROWS to be selected, and the second parameter refers to the COLUMNS to be selected. In this case, after the coma I wrote NOTHING, indicating that I want ALL COLUMNS!

If I want to do a subsetting of specific rows using a range of dates, I can do the following. Since this is an xts object, it is very easy to subset using dates. I select the returns of the 12 months of the year 2008:

 edhec2008<-edhec["2008-01-01/2008-12-31",]

I can also select those months where the Emerging Markets fund and the Convertible Arbitrage fund had positive returns in 2008:

 positive_edhec2008<-edhec2008[edhec2008$`Convertible Arbitrage`>0 & edhec2008$`Emerging Markets`>0,]
positive_edhec2008

We can see that only 2 months had positive returns in these funds in 2008.

There are several logical operators to be used for the subsetting condition of rows. These operators are:

== equal to != different to < less than <= less than or equal to > more than >= more than or equal to or & and

There are several logical operators to be used for the subsetting condition of rows. These operators are:

== equal to != different to < less than <= less than or equal to > more than >= more than or equal to or & and

##Control-flow commands Control-flow commands or constructs are used to program a series of tasks using conditions and/or loops.

There are 7 main control structures:

if/else: testing a condition for: execute a loop a fixed number of times repeat: execute an infinite loop while: execute a loop while a condition is true break: break the execution of a loop next: skip an interation of a loop return: exit a function

The most simple ones are the conditionals if() and if/else, which allow you to implement some basic algorithm logic in your analysis. We will start with the conditionals statements and then the loop statements.

Conditionals

If and if else

if(<condition1>) {
  ## do stuff
}

Here is a simple example, that is self-explanatory:

grade <- 70

if(grade > 69){cat("You have passed this course. Well done!")}

In this case the condition will be true, so the message will be displayed. You can try different values for grade and re-run this code to see what happens.

ELSE IF

Imagine that you have several conditions, not only one as the previous example. In this case, you need to use the else if statement. The structure looks like this:

if(<condition1>) {
  ## do something
} else if(<condition2>) {
  ## do something different
}

So our previous example can be upgraded as follows. Try chaging the values in the input variables.

gradePartial1 <- 80
gradePartial2 <- 60
gradeFinalExam <- 100

FinalGrade <- (gradePartial1*0.25 + gradePartial1*0.25 + gradeFinalExam*0.5)

if(FinalGrade > 90){
    "You did an Excellent job!"
  } else if(FinalGrade > 69){
    "You have passed this course. Well done."
  } else if(FinalGrade > 0){
    "Sorry you have failed the course."
  }

ELSE

Now imagine that we have several conditionals but we want to do something with the remaining variables that don’t fulfill the previous conditionals, then we use else. The structure looks like:

gradePartial1 <- -70
gradePartial2 <- 60
gradeFinalExam <- -60

FinalGrade <- (gradePartial1*0.25 + gradePartial1*0.25 + gradeFinalExam*0.5)

if(FinalGrade > 90){
    "You did awesome!"
  } else if(FinalGrade > 69){
    "You have passed this course. Well done."
  } else if(FinalGrade > 0){
    "Sorry you have failed the course."
  } else {
    "You have negative grades; it should be an error"
}

%in%

In the next example we use the operator %in%. This operator checks whether a value exists inside a vector. For each element of the vector it returns TRUE if the value is contained in the verctor and 0 otherwise:

# Both elements in the first vector appears in the second vector
c(1,2) %in% c(6,4,8,3,2,1)
# Only the last two elements of the first verctor appear in the second
c(6,4,8,3,2,1) %in% c(1,2)

For Loop

As you see, the result of using the %in% operator is a vector of Boolean values (TRUE OR FALSE). If the first element is TRUE, it means that the first number of the first vector is inside the second vector.

students<-c("Pedro","Laura","Bryan")

for(name in students){
  ##Instead of name you can write any variable just change it inside the loop
  cat("Hi, my name is",name)
}

In the next example we will use the quantmod library to download some financial data from online data sources such as Yahoo finance and Google Finance. Our initial vector indicate the tickers to download, in this case AAPL,JPM and GE.

You have to install the package in the Package tab of the bottom-right windows of RStudio.

Once you install the command, you have to load it with the library function. This quantmod library has the getSymbols function that is used to download online data from the web:

library(quantmod)

#Vector of tickers
tickers <-c("AAPL","JPM","GE")

for(i in tickers){
    getSymbols(i)
    cat("the prices of the ticker",i,"have been downloaded")
}

In the next example we do a similar process for a different ticker list. In the case of GE and AAPL we are going to download the data from yahoo, while INTGSTMXM193N from the FED. What happens with the remainning tickers?

tickers <- c("AAPL","GM","INTGSTMXM193N","GE","JPM")

for(i in tickers){
  if(i %in% c("AAPL","GE")){
    getSymbols(i,src = "yahoo")
    cat("the prices of the ticker",i,"have been downloaded from yahoo")
  }
  else if(i=="INTGSTMXM193N"){
    getSymbols(i,src = "FRED")
    #Note that the source for the FED is called FRED
    cat("the data of the ticker",i,"have been downloaded from the FED (Federal US Bank) ")
  }
}

We are going to use the previous example, but in this case we want also to add a condition to print the tickers that have NOT been downloaded.

tickers <- c("AAPL","GM","INTGSTMXM193N","GE","JPM")

for(i in tickers){
  
  if(i %in% c("AAPL","GE")){
    getSymbols(i,src = "yahoo")
    cat("the prices of the ticker",i,"have been downloaded from yahoo")
  }
  else if(i=="INTGSTMXM193N"){
    getSymbols(i,src = "FRED")
    cat("the data of the ticker",i,"have been downloaded from the FED (Federal US Bank) ")
  }
  else {
    cat("The ticker",i,"has not been downloaded")
  }
}

WHILE AND REPEAT TOOLS

In a similar manner than the for loop, it is possible to program a loop with while and repeat control-flow statements. The main difference is that in both you need to specify what is the exit condition, and it may be possible that NOT all the itereations has to be performed (like in the for case).

For the while you need to specify the condition at the beginning. Here an example. If you want to know how many years you need to keep an investment with a fixed interest rate in order to duplicate your initial investment:

 APR<-0.10
  # I define Annual Percentage Rate to be equal to 10%
  INV<-100
  # Initial investment equal to $100
  MULTIPLE<-2
  # Multiple = 2 to check when the investment double
  BALANCE<-INV
  # I start assigning the balance equal to the initial investment
  year<-0
  # I start with year equal to zero
  while (BALANCE<MULTIPLE*INV) {
    # the exit condition means that while the balance is less than the initial investment
    #    multiplied by the multiple, then continue with the iterations of the loop
    year<-year+1 
    # I increase the value of year by 1
    BALANCE<-BALANCE*(1+APR) 
    # I multiply the current balance times the growth factor (1+APR) using to the 
    #   Annual Percentage Rate
  }
  cat(
     "To multiply your investment times ", MULTIPLE, "you need ", year, " years.")
cat(
     "Your balance after ", year, " years will be $",BALANCE)

Unlike the while statement, you can use the repeat statement to do a loop, but in the case of repeat, you have to specify the exit condition using if and the break statement any place within the loop. Here is the same loop we did above but using repeat:

 APR<-0.10
  # I define Annual Percentage Rate to be equal to 10%
  INV<-100
  # Initial investment equal to $100
  MULTIPLE<-2
  # Multiple = 2 to check when the investment double
  BALANCE<-INV
  # I start assigning the balance equal to the initial investment
  year<-0
  # I start with year equal to zero
  repeat  {
    year<-year+1 
    # I increase the value of year by 1
    BALANCE<-BALANCE*(1+APR) 
    # I multiply the current balance times the growth factor (1+APR) using to the 
    #   Annual Percentage Rate
    if (BALANCE>=MULTIPLE*INV) {
      break
    }
    # If the balance is greater than the multiple times the investment, then
    #   the break statement is executed, so the program stops the interations
  }
  cat(
     "To multiply your investment times ", MULTIPLE, "you need ", year, " years.")
  cat(
     "Your balance after ", year, " years will be $",BALANCE)

5.4 Looping vs R-vectorization Most R programmers believe that loops must be AVOIDED! This is wierd since most of the time programming requires to do repetitive tasks. However, in R, unlike other traditional computer languages such as C, there is an alternative way to do loops without writing loops!

A <-c(3,3,4,6,8) 
  B <-c(-2,-3,-1,3,5)
  # A and B are vectors with the annual free cash flows of each product 
  sumcashflows<-vector(length=5)
  for (i in 1:length(A)) {
    sumcashflows[i]<-A[i] + B[i]
    # We sum the element i of both vectors and leave the result
    #   in the position i of the vector sumcashflows
  }
  sumcashflows
  A <-c(3,3,4,6,8) 
  B <-c(-2,-3,-1,3,5)
  sumcashflows<-A+B
  # We just sum both vectors as if they were numbers
  sumcashflows

5.5 Application: Present value of future cash flows Now, how can you calculate the Present Value of these cash flows? You have to remember the basics of time value of money. To calculate the present value (PV0) of a sequence of cash flows in the future, you just have to apply the following formula for the sequence of cash flows:

con loop

  # I assign 0 the the variable PV, present value
  PV <- 0
  # I defined the discount rate as R:
  R <- 0.15 
  for (i in 1:length(sumcashflows)) {
    # I calculate the present value of each cash flow i:
    PVCF <- sumcashflows[i] / (1 + R)^i
   # I sum each corresponding cash flow i to the cumulative variable PV    
    PV <- PV + PVCF
  }
 # The loop iterates 5 times, one for each cash flow and will ends with the sum of all 
  cat("The Present Value of all cash flows is ", PV)

sin loop

 # I assign a sequence from 1 to 5, for the exponents of the formula of present value 
  #   for each cash fow
  exponents <- seq(1,5)
  # The seq is a function that generates a sequence. Here I specified to start the 
  #   sequence in 1 and finish in 5
  # I calculate a vector with the present value for each cash flow. I use vectorization:
  PVvector <- sumcashflows / (1 + R)^exponents
  # Note that this mathematical expression applies to each of the element of the vector. 
  #   Also, each vector has the same dimension.
  # I finally sum all elements of the vector using the function sum:
  PV<-sum(PVvector)
  cat("The Present Value of all cash flows is ", PV)

##7 CHALLENGE 1 You have to write a program to calculate the number of months needed to finish paying a mortgage loan. The information about the loan is the following:

Loan amount = $3,000,000.00 pesos

APR (Annual % rate) = 11% (compounded monthly)

Monthly Fixed Payment = $40,000.00 (includes interests and capital)

Your program has to provide 2 results: the number of months needed to finish paying the loan, and the amount of the last payment if the payment is less than the fixed payment amount. Your program has to be able to run with any change in any of the values of the above variables.

This is a quite challenging exercise!

Hint: if you are familiar with Excel, start solving the problem in Excel, and then try to write your program in R.

##8 CHALLENGE 2 Write a program that calculates the price of the following bond issued by the company ABC. ABC needs to finance an important project to develop a new technological device.

To get the money, ABC issued a bond with the following characteristics:

Principal: $3,000,000 Time to maturity: 20 years Coupon rate: 11% (annual) coupons are payed each 6 months Calculate the price of this bond for each of the following annual interest rates:

8% 11% 13% You have to get the price for the bond for each of these 3 interest rates.

Remember that the price of a bond is the present value of its future cash flows.

CHALLENGE 1

You have to write a program to calculate the number of months needed to finish paying a mortgage loan. The information about the loan is the following:

Loan amount = $3,000,000.00 pesos

APR (Annual % rate) = 11% (compounded monthly)

Monthly Fixed Payment = $40,000.00 (includes interests and capital)

Your program has to provide 2 results: the number of months needed to finish paying the loan, and the amount of the last payment if the payment is less than the fixed payment amount. Your program has to be able to run with any change in any of the values of the above variables.

This is a quite challenging exercise!

Hint: if you are familiar with Excel, start solving the problem in Excel, and then try to write your program in R.

FinancialMath::amort.period(Loan = 3000000, pmt = 40000, i = .11, n = NA)
Error in FinancialMath::amort.period(Loan = 3e+06, pmt = 40000, i = 0.11,  : 
  Too small of pmt.

CHALLENGE 2

Write a program that calculates the price of the following bond issued by the company ABC. ABC needs to finance an important project to develop a new technological device.

To get the money, ABC issued a bond with the following characteristics:

Principal: $3,000,000 Time to maturity: 20 years Coupon rate: 11% (annual) coupons are payed each 6 months Calculate the price of this bond for each of the following annual interest rates:

8% 11% 13% You have to get the price for the bond for each of these 3 interest rates.

Remember that the price of a bond is the present value of its future cash flows.

FinancialMath::bond(t = NA, f = 3000000, r = 20, n = 11, i = .08, c = 1)
         Bond Summary
Price    4.283379e+08
Premium  4.283379e+08
Coupon   6.000000e+07
Eff Rate 8.000000e-02
Years    1.100000e+01
MAC D    5.239503e+00
MOD D    4.851392e+00
MAC C    3.710111e+01
MOD C    3.630025e+01

(I think?)

FinancialMath::bond(t = NA, f = 3000000, r = 20, n = 11, i = .11, c = 1)
         Bond Summary
Price    3.723909e+08
Premium  3.723909e+08
Coupon   6.000000e+07
Eff Rate 1.100000e-01
Years    1.100000e+01
MAC D    4.978808e+00
MOD D    4.485413e+00
MAC C    3.415739e+01
MOD C    3.176382e+01
FinancialMath::bond(t = NA, f = 3000000, r = 20, n = 13, i = .11, c = 1)
         Bond Summary
Price    4.049922e+08
Premium  4.049922e+08
Coupon   6.000000e+07
Eff Rate 1.100000e-01
Years    1.300000e+01
MAC D    5.582155e+00
MOD D    5.028969e+00
MAC C    4.395334e+01
MOD C    4.020412e+01
LS0tCnRpdGxlOiAiV29ya3Nob3AgMiwgRmluYW5jaWFsIFByb2dyYW1taW5nIgphdXRob3I6IFN0ZWZhbiBTY2h3ZWl0emVyIC0gQTAxMjA5NzU1Cm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMjICpXb3Jrc2hvcCAyLCBGaW5hY2lhbCBQcm9ncmFtbWluZyoKCiMgRGF0YSBTdHJ1Y3R1cmVzIAojIyBMaXN0cwoKTGlzdHMgYXJlIFIgb2JqZWN0cyB0aGF0IGNhbiBzdG9yZSBlbGVtZW50cyBvZiBkaWZmZXJlbnQgY2xhc3Nlcywgb3Bvc2l0ZSB0byB2ZWN0b3JzIHdoaWNoIGNhbiBiZSB1c2VkIHRvIHN0b3JlIGVsZW1lbnRzIG9mIHRoZSBzYW1lIGNsYXNzIG9ubHkuIEVhY2ggZWxlbWVudCBvZiBhIGxpc3QgY2FuIGJlIG9mIGFueSBvYmplY3QgY2xhc3Mgc3VjaCBhcyBkYXRhIGZyYW1lcywgbnVtZXJpYyB2ZWN0b3JzLCBtYXRyaWNlcyBvciBldmVuIGxpc3QuIEZvciBleGFtcGxlLCB3ZSBjYW4gY3JlYXRlIGEgbGlzdCB0byBzdG9yZSBpbmZvcm1hdGlvbiBvZiBhIGZpbmFuY2lhbCBwb3J0Zm9saW8uCgpJIHdpbGwgY3JlYXRlIGEgbGlzdCB0aGF0IHJlcHJlc2VudHMgaW5mb3JtYXRpb24gb2YgYSBmaW5hbmNpYWwgcG9ydGZvbGlvLiBJIGZpcnN0IGNyZWF0ZSB0aGUgZWxlbWVudHMgb2YgdGhlIHBvcnRmb2xpbzoKCmBgYHtyfQojIENyZWF0ZSB2ZWN0b3JzIGZvciBzdG9jayB0aWNrZXJzIGFuZCBleHBlY3RlZCBzdG9jayByZXR1cm5zOgp0aWNrZXJzIDwtIGMoIkFBUEwiLCJBTVpOIiwiV01UIikKZXhwZWN0ZWRfc3RvY2tfcmV0dXJucyA8LSBjKDAuMDIwLDAuMDE1LDAuMDEwKQpleHBlY3RlZF9zdG9ja19yaXNrIDwtIGMoMC4wNCwwLjA0NSwwLjAyKQp0aWNrZXJzCmV4cGVjdGVkX3N0b2NrX3JldHVybnMKZXhwZWN0ZWRfc3RvY2tfcmlzawpgYGAKCk5vdyBJIHdpbGwgaW5kaWNhdGUgaG93IG11Y2ggKGluICUpIEkgd2lsbCBhbGxvY2F0ZSBmb3IgZWFjaCBhc3NldCBpbiBteSBwb3J0Zm9saW8uIEkgd2lsbCBhc3NpZ24gNTAlIHRvIEFwcGxlLCBhbmQgMjUlIHRvIEFtYXpvbiBhbmQgV2FsLU1hcnQuIEkgY3JlYXRlIGEgdmVjdG9yIHdpdGggdGhlc2Ugd2VpZ2h0cyAoaW4gZGVjaW1hbCk6CgpgYGB7cn0Kc3RvY2tfd2VpZ2h0cyA8LSBjKDAuNTAsMC4yNSwwLjI1KQpgYGAKCk5vdyBJIHdpbGwgY2FsY3VsYXRlIHRoZSBleHBlY3RlZCBwb3J0Zm9saW8gcmV0dXJuIGFzIGEgd2VpZ2h0ZWQgYXZlcmFnZSB0aGUgc3RvY2sgZXhwZWN0ZWQgcmV0dXJuczoKCmBgYHtyfQp3ZWlnaHRlZF9yZXR1cm5zIDwtIGV4cGVjdGVkX3N0b2NrX3JldHVybnMqc3RvY2tfd2VpZ2h0cwp3ZWlnaHRlZF9yZXR1cm5zCmBgYAoKV2hlbiB5b3UgbXVsdGlwbHkgMiB2ZWN0b3JzIHlvdSBnZXQgYW4gZWxlbWVudC1ieS1lbGVtZW50IG11bHRpcGxpY2F0aW9uLiBUaGlzIGlzIGNhbGxlZCBhIOKAnHZlY3Rvcml6YXRpb27igJ0gb3BlcmF0aW9uLiBCeSBkZWZhdWx0IFIg4oCcdmVjdG9yaXplc+KAnSBtYXRoZW1hdGljYWwgb3BlcmF0aW9ucy4gVGhpcyBtZWFucyB0aGUgZmlyc3QgZWxlbWVudCBvZiB0aGUgZmlyc3QgdmVjdG9yIGlzIG11bHRpcGxpZWQgYnkgdGhlIGZpcnN0IGVsZW1lbnQgb2YgdGhlIHNlY29uZCB2ZWN0b3IuIFRoZSBzYW1lIGZvciB0aGUgMm5kLiBhbmQgM3JkLiBlbGVtZW50cyBvZiBlYWNoIHZlY3Rvci4KCk5vdyBJIGp1c3Qgc3VtIGFsbCB0aGUgZWxlbWVudHMgb2YgdGhpcyB2ZWN0b3IgdGhhdCBjb250YWlucyB0aGUgd2VpZ2h0ZWQgcmV0dXJucyB0byBnZXQgdGhlIGV4cGVjdGVkIHJldHVybiBvZiBteSBwb3J0Zm9saW86CmBgYHtyfQpleHBlY3RlZF9wb3J0Zm9saW9fcmV0dXJuIDwtIHN1bSh3ZWlnaHRlZF9yZXR1cm5zKSAKYGBgCkkgdXNlZCB0aGUgZnVuY3Rpb24gc3VtIHRvIHRoZSB3ZWlnaHRlZF9yZXR1cm5zIHZlY3Rvciwgc28gZWFjaCBlbGVtZW50IG9mIHRoZSB2ZWN0b3IgaXMgYWRkZWQgdG8gZ2V0IHRoZSBleHBlY3RlZCBwb3J0Zm9saW8gcmV0dXJuLgoKSSBub3cgY3JlYXRlIGEgbGlzdCB3aXRoIGFsbCB0aGVzZSBwaWVjZXMgb2YgaW5mb3JtYXRpb24gb2YgbXkgcG9ydGZvbGlvLiBJIHVzZSB0aGUgZnVuY3Rpb24gbGlzdCgpIHRvIGNyZWF0ZSB0aGUgcG9ydGZvbGlvIG9iamVjdCBhcyBhIGxpc3QgdGhhdCBjb250YWlucyB0aGUgdGlja2VycyB2ZWN0b3IsIGFuZCB0aGUgdmVjdG9ycyBmb3IgZXhwZWN0ZWQgc3RvY2sgcmV0dXJuLCBleHBlY3RlZCBzdG9jayByaXNrLCBzdG9jayB3ZWlnaHRzIGFuZCB0aGUgZXhwZWN0ZWQgcG9ydGZvbGlvIHJldHVybjoKCmBgYHtyfQpwb3J0Zm9saW8xIDwtIGxpc3QodGlja2VycywgZXhwZWN0ZWRfc3RvY2tfcmV0dXJucywgZXhwZWN0ZWRfc3RvY2tfcmlzaywgCiAgICAgICAgICAgICAgICAgICBzdG9ja193ZWlnaHRzLCBleHBlY3RlZF9wb3J0Zm9saW9fcmV0dXJuKQojIEkgYXNzaWduIG5hbWVzIHRvIGVhY2ggZWxlbWVudCBvZiB0aGUgcG9ydGZvbGlvOgpuYW1lcyhwb3J0Zm9saW8xKTwtYygiVGlja2VycyIsIlN0b2NrX3JldHVybnMiLCJTdG9ja19yaXNrIiwiU3RvY2tfd2VpZ2h0cyIsCiAgICAgICAgICAgICAgICAgICAgICJQb3J0Zm9saW8gZXhwZWN0ZWQgUmV0dXJuIikKIyBJIGRpc3BsYXkgdGhlIHBvcnRmb2xpbyBvYmplY3Q6CnBvcnRmb2xpbzEKYGBgCgpJIGNhbiBhY2Nlc3MgdGhlIGVsZW1lbnRzIG9mIHRoZSBwb3J0Zm9saW8xIGxpc3QgdXNpbmcgZWl0aGVyIHRoZSBuYW1lIG9mIGVhY2ggZWxlbWVudCwgb3IgdGhlIG51bWJlciBvZiB0aGUgZWxlbWVudCB1c2luZyBkb3VibGUgc3F1YXJlZCBicmFja2V0c1tbXV06CgpgYGB7cn0KIyBJIGRpc3BsYXkgdGhlIGV4cGVjdGVkIHN0b2NrIHRpY2tlcnM6CnBvcnRmb2xpbzEkVGlja2VycwpgYGAKCmBgYHtyfQojIEkgY2FuIGFsc28gZGlzcGxheSBleHBlY3RlZCBzdG9jayB0aWNrZXJzIHVzaW5nIHRoZSBlbGVtZW50IG51bWJlciBhbmQgZG91YmxlCiMgIGJyYWNrZXRzOgpwb3J0Zm9saW8xW1sxXV0KYGBgCgpgYGB7cn0KIyBJIGRpc3BsYXkgdGhlIGNsYXNzIGFuZCBsZW5ndGggb2YgdGhlIGZpcnN0IGVsZW1lbnQ6CmNsYXNzKHBvcnRmb2xpbzEkVGlja2VycykKYGBgCgpgYGB7cn0KbGVuZ3RoKHBvcnRmb2xpbzEkVGlja2VycykKYGBgCgojIyBUaGUgeHRzIGRhdGEgY2xhc3MKUiBoYXMgZGlmZmVyZW50IGRhdGEgY2xhc3NlcyAob3IgUiBvYmplY3RzKS4gQWN0dWFsbHksIHlvdSBjYW4gY3JlYXRlIHlvdXIgb3duIGRhdGEgY2xhc3MsIHdoaWNoIGlzIGEgc2V0IG9uZSBvciBtb3JlIGRhdGEgc3RydWN0dXJlcy4gRm9yIHRpbWUgc2VyaWVzIGRhdGFzZXRzLCB3aGljaCBhcmUgdmVyeSBjb21tb24gaW4gRmluYW5jZSwgdGhlIG1vc3QgcG9wdWxhciBkYXRhIGNsYXNzZXMgYXJlOiB0cywgem9vIGFuZCB4dHMuIHh0cyBzdGFuZHMgZm9yIGV4dGVuc2libGUgdGltZSBzZXJpZXMgY2xhc3MuIEFuIHh0cyBvYmplY3QgY29udGFpbnMgYSBzZXQgb2YgY29sdW1ucyB0aGF0IGNhbiBiZSBvZiBhbnkgdHlwZSAoYWxwaGFiZXRpYywgbnVtZXJpYywgYm9vbGVhbikgYW5kIGl0IGhhcyBhIHRpbWUgaW5kZXguIEFsbCB4dHMgb2JqZWN0cyBhcmUgdXN1YWxseSBzb3J0ZWQgY2hyb25vbG9naWNhbGx5LgoKVGhlIGluZGV4IG9mIGFuIHh0cyBvYmplY3QgaXMgbGlrZSB0aGUgZmlyc3QgY29sdW1uIG9mIHRoZSBvYmplY3QsIGJ1dCBpdCBpcyBhY3R1YWxseSBpdHMgaW5kZXg7IGl0IGlzIG5vdCBjb25zaWRlcmVkIGEgY29sdW1uIG9mIHRoZSBvYmplY3QuIEFuIHh0cyBvYmplY3QgaGFzIHRoZSBhZHZhbnRhZ2UgdGhhdCB3ZSBjYW4gYXBwbHkgc2V2ZXJhbCBmdW5jdGlvbnMgdG8gdGhhdCBvYmplY3QgZm9yIGRhdGEgbWVyZ2luZywgc29ydGluZywgc2VsZWN0aW5nLCBldGMuCgpUcnkgdGhlIGZvbGxvd2luZyBleGFtcGxlLiBEb3dubG9hZCBhIHNhbXBsZSBkYXRhc2V0IGNhbGxlZCBlZGhlYywgd2hpY2ggY29tZXMgd2l0aCB0aGUgUGVyZm9ybWFuY2VBbmFseXRpY3MgcGFja2FnZS4gSW4gUiwgd2UgY2FuIHVzZSB0aG91c2FuZHMgb2YgYXZhaWxhYmxlIHBhY2thZ2VzIHRvIGRvIGRpZmZlcmVudCB0eXBlcyBvZiBjYWxjdWxhdGlvbnMgYW5kIG9wZXJhdGlvbnMuIFBlcmZvcm1hbmNlQW5hbHl0aWNzIHBhY2thZ2UgaXMgYSBwYWNrYWdlIHdpdGggbWFueSBmdW5jdGlvbnMgcmVsYXRlZCB0byBGaW5hbmNpYWwgYW5hbHl0aWNzLiBXZSB3aWxsIHVzZSBzb21lIG9mIHRoZXNlIGZ1bmN0aW9ucyBsYXRlciBpbiB0aGUgY291cnNlLgoKd2UgbmVlZCB0aGUgUGVyZm9ybWFuY2VBbmFseXRpY3MgcGFja2FnZSwgc28geW91IGNhbiBpbnN0YWxsIGl0IGZyb20gdGhlIFBhY2thZ2UgbWVudSAocmlnaHQtYm90dG9tIG9mIHlvdXIgUlN0dWRpbykuCgpPbmNlIHRoZSBwYWNrYWdlIGlzIGluc3RhbGxlZCBpbiBteSBjb21wdXRlciwgSSBkbyBub3QgbmVlZCB0byByZS1pbnN0YWxsIGl0IGFnYWluLiBIb3dldmVyLCBlYWNoIHRpbWUgSSBuZWVkIHRvIHVzZSB0aGUgcGFja2FnZSwgSSBuZWVkIHRvIGxvYWQgaXQgaW50byBtZW1vcnk6CgoKYGBge3J9CmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpCmBgYAoKSSBkb3dubG9hZCB0aGUgc2FtcGxlIGRhdGFzZXQgZWRoZWMsIHdoaWNoIGNvbnRhaW5zIG1vbnRobHkgcmV0dXJucyBvZiBkaWZmZXJlbnQgaGVkZ2UgZnVuZCBpbmRleGVzIGNyZWF0ZWQgYnkgdGhlIEVESEVDIFJpc2sgSW5zdGl0dXRlLgoKYGBge3J9CmRhdGEoImVkaGVjIikKYGBgClRoZSBlZGhlYyBkYXRhc2V0IHdpbGwgYXBwZWFyIGluIG15IEdsb2JhbCBFbnZpcm9ubWVudC4KCmVkaGVjIGlzIGFuIHh0cyBSIG9iamVjdCB0aGF0IGNvbnRhaW5zIGhpc3RvcmljYWwgbW9udGhseSByZXR1cm5zIG9mIGRpZmZlcmVudCBoZWRnZSBmdW5kIGluZGV4ZXMuIFdlIGNhbiBlYXNpbHkgZG8gZGlmZmVyZW50IGNhbGN1bGF0aW9ucyB3aXRoIHNwZWNpZmljIGZ1bmN0aW9ucyB0aGF0IGFwcGx5IHRvIHh0cyBvYmplY3RzLiBGb3Igbm93LCB3ZSB3aWxsIGxlYXJuIGhvdyB0byBkbyBzdWJzZXR0aW5nIHdpdGggeHRzIG9iamVjdHMuCgpJZiB5b3Ugd2FudCB0byBrbm93IG1vcmUgZnVuY3Rpb25zIGZvciB0aGUgeHRzIFIgb2JqZWN0cywgeW91IGNhbiBjaGVjayB0aGUgeHRzIENoZWF0U2hlZXQgYXQ6IGh0dHBzOi8vczMuYW1hem9uYXdzLmNvbS9hc3NldHMuZGF0YWNhbXAuY29tL2Jsb2dfYXNzZXRzL3h0c19DaGVhdF9TaGVldF9SLnBkZgoKIyMgU3Vic2V0dGluZyBkYXRhCgpSIGhhcyBwb3dlcmZ1bCBpbmRleGluZyBmZWF0dXJlcyBmb3IgYWNjZXNzaW5nIG9iamVjdCBlbGVtZW50cy4gVGhlc2UgZmVhdHVyZXMgY2FuIGJlIHVzZWQgdG8gc2VsZWN0IGFuZCBleGNsdWRlIGNvbHVtbnMgYW5kIHJvd3MgKG9ic2VydmF0aW9ucykuIEluIHRoZSBuZXh0IHBhcmFncmFwaHMgd2Ugd2lsbCBsZWFybiBob3cgdG8gZXh0cmFjdCB0aGUgaW5mb3JtYXRpb24gd2Ugd2FudCBmcm9tIGFuIHh0cyBvYmplY3QuIFNldmVyYWwgb2YgdGhlc2UgZnVuY3Rpb25zIGFsc28gYXBwbHkgdG8gZGF0YSBmcmFtZXMuCgpJIHNlZSB0aGUgc3RydWN0dXJlIG9mIHRoZSBlZGhlYyBSIGRhdGFzZXQgYW5kIHRoZSBmaXJzdCBhbmQgbGFzdCByb3dzOgoKYGBge3J9CnN0cihlZGhlYykKYGBgCgpgYGB7cn0KaGVhZChlZGhlYykKYGBgCgpgYGB7cn0KdGFpbChlZGhlYykKYGBgCkZyb20gdGhlIHJlc3VsdHMgYWJvdmUsIHdlIHNlZSB0aGF0IHRoaXMgeHRzIG9iamVjdCBoYXMgMTMgY29sdW1ucywgd2hpY2ggYXJlIHJldHVybnMgb2YgZGlmZmVyZW50IGhlZGdlIGZ1bmQgaW5kZXhlcy4KCkkgY2FuIHN1YnNldCBlaXRoZXIgcm93cywgY29sdW1ucyBvciBib3RoLiBGb3IgZXhhbXBsZSBJIGNhbiBzZWxlY3QgaW4gd2hpY2ggbW9udGhzIHRoZSBFbWVnaW5nIG1hcmtldCBmdW5kIGhhcyBoYWQgbmVnYXRpdmUgcmV0dXJuczoKCmBgYHtyfQogbmVnYXRpdmVfcmV0dXJuc19lbSA8LSBlZGhlY1tlZGhlYyRgRW1lcmdpbmcgTWFya2V0c2A8MCw0XQojIEkgZGlzcGxheSB0aGUgZmlyc3Qgcm93cyBvZiB0aGlzIG5ldyBvYmplY3QsIHdoaWNoIGhhcyBvbmx5IG5lZ2F0aXZlIHJldHVybnMgZm9yIEVtZXJnaW5nIE1hcmtldHM6CmhlYWQobmVnYXRpdmVfcmV0dXJuc19lbSkKYGBgCgoKYGBge3J9CiBuZWdhdGl2ZV9yZXR1cm5zX2VtX2FsbCA8LSBlZGhlY1tlZGhlYyRgRW1lcmdpbmcgTWFya2V0c2A8MCxdCiBoZWFkKG5lZ2F0aXZlX3JldHVybnNfZW1fYWxsKQpgYGAKCkFzIHlvdSBzZWUsIHRvIGRvIHN1YnNldHRpbmcgSSB1c2Ugc3F1YXJlZCBicmFja2V0cyBhZmhlciB0aGUgb2JqZWN0LCBhbmQgdGhlIGZpcnN0IG51bWJlciByZWZlcnMgdG8gdGhlIFJPV1MgdG8gYmUgc2VsZWN0ZWQsIGFuZCB0aGUgc2Vjb25kIHBhcmFtZXRlciByZWZlcnMgdG8gdGhlIENPTFVNTlMgdG8gYmUgc2VsZWN0ZWQuIEluIHRoaXMgY2FzZSwgYWZ0ZXIgdGhlIGNvbWEgSSB3cm90ZSBOT1RISU5HLCBpbmRpY2F0aW5nIHRoYXQgSSB3YW50IEFMTCBDT0xVTU5TIQoKSWYgSSB3YW50IHRvIGRvIGEgc3Vic2V0dGluZyBvZiBzcGVjaWZpYyByb3dzIHVzaW5nIGEgcmFuZ2Ugb2YgZGF0ZXMsIEkgY2FuIGRvIHRoZSBmb2xsb3dpbmcuIFNpbmNlIHRoaXMgaXMgYW4geHRzIG9iamVjdCwgaXQgaXMgdmVyeSBlYXN5IHRvIHN1YnNldCB1c2luZyBkYXRlcy4gSSBzZWxlY3QgdGhlIHJldHVybnMgb2YgdGhlIDEyIG1vbnRocyBvZiB0aGUgeWVhciAyMDA4OgoKYGBge3J9CiBlZGhlYzIwMDg8LWVkaGVjWyIyMDA4LTAxLTAxLzIwMDgtMTItMzEiLF0KYGBgCgpJIGNhbiBhbHNvIHNlbGVjdCB0aG9zZSBtb250aHMgd2hlcmUgdGhlIEVtZXJnaW5nIE1hcmtldHMgZnVuZCBhbmQgdGhlIENvbnZlcnRpYmxlIEFyYml0cmFnZSBmdW5kIGhhZCBwb3NpdGl2ZSByZXR1cm5zIGluIDIwMDg6CgpgYGB7cn0KIHBvc2l0aXZlX2VkaGVjMjAwODwtZWRoZWMyMDA4W2VkaGVjMjAwOCRgQ29udmVydGlibGUgQXJiaXRyYWdlYD4wICYgZWRoZWMyMDA4JGBFbWVyZ2luZyBNYXJrZXRzYD4wLF0KcG9zaXRpdmVfZWRoZWMyMDA4CmBgYAoKV2UgY2FuIHNlZSB0aGF0IG9ubHkgMiBtb250aHMgaGFkIHBvc2l0aXZlIHJldHVybnMgaW4gdGhlc2UgZnVuZHMgaW4gMjAwOC4KClRoZXJlIGFyZSBzZXZlcmFsIGxvZ2ljYWwgb3BlcmF0b3JzIHRvIGJlIHVzZWQgZm9yIHRoZSBzdWJzZXR0aW5nIGNvbmRpdGlvbiBvZiByb3dzLiBUaGVzZSBvcGVyYXRvcnMgYXJlOgoKPT0gZXF1YWwgdG8KIT0gZGlmZmVyZW50IHRvCjwgbGVzcyB0aGFuCjw9IGxlc3MgdGhhbiBvciBlcXVhbCB0bwo+IG1vcmUgdGhhbgo+PSBtb3JlIHRoYW4gb3IgZXF1YWwgdG8Kb3IKJiBhbmQKClRoZXJlIGFyZSBzZXZlcmFsIGxvZ2ljYWwgb3BlcmF0b3JzIHRvIGJlIHVzZWQgZm9yIHRoZSBzdWJzZXR0aW5nIGNvbmRpdGlvbiBvZiByb3dzLiBUaGVzZSBvcGVyYXRvcnMgYXJlOgoKPT0gZXF1YWwgdG8KIT0gZGlmZmVyZW50IHRvCjwgbGVzcyB0aGFuCjw9IGxlc3MgdGhhbiBvciBlcXVhbCB0bwo+IG1vcmUgdGhhbgo+PSBtb3JlIHRoYW4gb3IgZXF1YWwgdG8Kb3IKJiBhbmQKCgojI0NvbnRyb2wtZmxvdyBjb21tYW5kcwpDb250cm9sLWZsb3cgY29tbWFuZHMgb3IgY29uc3RydWN0cyBhcmUgdXNlZCB0byBwcm9ncmFtIGEgc2VyaWVzIG9mIHRhc2tzIHVzaW5nIGNvbmRpdGlvbnMgYW5kL29yIGxvb3BzLgoKVGhlcmUgYXJlIDcgbWFpbiBjb250cm9sIHN0cnVjdHVyZXM6CgppZi9lbHNlOiB0ZXN0aW5nIGEgY29uZGl0aW9uCmZvcjogZXhlY3V0ZSBhIGxvb3AgYSBmaXhlZCBudW1iZXIgb2YgdGltZXMKcmVwZWF0OiBleGVjdXRlIGFuIGluZmluaXRlIGxvb3AKd2hpbGU6IGV4ZWN1dGUgYSBsb29wIHdoaWxlIGEgY29uZGl0aW9uIGlzIHRydWUKYnJlYWs6IGJyZWFrIHRoZSBleGVjdXRpb24gb2YgYSBsb29wCm5leHQ6IHNraXAgYW4gaW50ZXJhdGlvbiBvZiBhIGxvb3AKcmV0dXJuOiBleGl0IGEgZnVuY3Rpb24KClRoZSBtb3N0IHNpbXBsZSBvbmVzIGFyZSB0aGUgY29uZGl0aW9uYWxzIGlmKCkgYW5kIGlmL2Vsc2UsIHdoaWNoIGFsbG93IHlvdSB0byBpbXBsZW1lbnQgc29tZSBiYXNpYyBhbGdvcml0aG0gbG9naWMgaW4geW91ciBhbmFseXNpcy4gV2Ugd2lsbCBzdGFydCB3aXRoIHRoZSBjb25kaXRpb25hbHMgc3RhdGVtZW50cyBhbmQgdGhlbiB0aGUgbG9vcCBzdGF0ZW1lbnRzLgoKIyBDb25kaXRpb25hbHMKIyMgSWYgYW5kIGlmIGVsc2UKCmBgYHtyfQppZig8Y29uZGl0aW9uMT4pIHsKICAjIyBkbyBzdHVmZgp9CmBgYAoKSGVyZSBpcyBhIHNpbXBsZSBleGFtcGxlLCB0aGF0IGlzIHNlbGYtZXhwbGFuYXRvcnk6CgpgYGB7cn0KZ3JhZGUgPC0gNzAKCmlmKGdyYWRlID4gNjkpe2NhdCgiWW91IGhhdmUgcGFzc2VkIHRoaXMgY291cnNlLiBXZWxsIGRvbmUhIil9CmBgYApJbiB0aGlzIGNhc2UgdGhlIGNvbmRpdGlvbiB3aWxsIGJlIHRydWUsIHNvIHRoZSBtZXNzYWdlIHdpbGwgYmUgZGlzcGxheWVkLiBZb3UgY2FuIHRyeSBkaWZmZXJlbnQgdmFsdWVzIGZvciBncmFkZSBhbmQgcmUtcnVuIHRoaXMgY29kZSB0byBzZWUgd2hhdCBoYXBwZW5zLgoKIyMgRUxTRSBJRgpJbWFnaW5lIHRoYXQgeW91IGhhdmUgc2V2ZXJhbCBjb25kaXRpb25zLCBub3Qgb25seSBvbmUgYXMgdGhlIHByZXZpb3VzIGV4YW1wbGUuIEluIHRoaXMgY2FzZSwgeW91IG5lZWQgdG8gdXNlIHRoZSBlbHNlIGlmIHN0YXRlbWVudC4gVGhlIHN0cnVjdHVyZSBsb29rcyBsaWtlIHRoaXM6CmBgYHtyfQppZig8Y29uZGl0aW9uMT4pIHsKICAjIyBkbyBzb21ldGhpbmcKfSBlbHNlIGlmKDxjb25kaXRpb24yPikgewogICMjIGRvIHNvbWV0aGluZyBkaWZmZXJlbnQKfQpgYGAKClNvIG91ciBwcmV2aW91cyBleGFtcGxlIGNhbiBiZSB1cGdyYWRlZCBhcyBmb2xsb3dzLiBUcnkgY2hhZ2luZyB0aGUgdmFsdWVzIGluIHRoZSBpbnB1dCB2YXJpYWJsZXMuCgpgYGB7cn0KZ3JhZGVQYXJ0aWFsMSA8LSA4MApncmFkZVBhcnRpYWwyIDwtIDYwCmdyYWRlRmluYWxFeGFtIDwtIDEwMAoKRmluYWxHcmFkZSA8LSAoZ3JhZGVQYXJ0aWFsMSowLjI1ICsgZ3JhZGVQYXJ0aWFsMSowLjI1ICsgZ3JhZGVGaW5hbEV4YW0qMC41KQoKaWYoRmluYWxHcmFkZSA+IDkwKXsKICAgICJZb3UgZGlkIGFuIEV4Y2VsbGVudCBqb2IhIgogIH0gZWxzZSBpZihGaW5hbEdyYWRlID4gNjkpewogICAgIllvdSBoYXZlIHBhc3NlZCB0aGlzIGNvdXJzZS4gV2VsbCBkb25lLiIKICB9IGVsc2UgaWYoRmluYWxHcmFkZSA+IDApewogICAgIlNvcnJ5IHlvdSBoYXZlIGZhaWxlZCB0aGUgY291cnNlLiIKICB9CmBgYAoKIyMgRUxTRQoKTm93IGltYWdpbmUgdGhhdCB3ZSBoYXZlIHNldmVyYWwgY29uZGl0aW9uYWxzIGJ1dCB3ZSB3YW50IHRvIGRvIHNvbWV0aGluZyB3aXRoIHRoZSByZW1haW5pbmcgdmFyaWFibGVzIHRoYXQgZG9u4oCZdCBmdWxmaWxsIHRoZSBwcmV2aW91cyBjb25kaXRpb25hbHMsIHRoZW4gd2UgdXNlIGVsc2UuIFRoZSBzdHJ1Y3R1cmUgbG9va3MgbGlrZToKCmBgYHtyfQpncmFkZVBhcnRpYWwxIDwtIC03MApncmFkZVBhcnRpYWwyIDwtIDYwCmdyYWRlRmluYWxFeGFtIDwtIC02MAoKRmluYWxHcmFkZSA8LSAoZ3JhZGVQYXJ0aWFsMSowLjI1ICsgZ3JhZGVQYXJ0aWFsMSowLjI1ICsgZ3JhZGVGaW5hbEV4YW0qMC41KQoKaWYoRmluYWxHcmFkZSA+IDkwKXsKICAgICJZb3UgZGlkIGF3ZXNvbWUhIgogIH0gZWxzZSBpZihGaW5hbEdyYWRlID4gNjkpewogICAgIllvdSBoYXZlIHBhc3NlZCB0aGlzIGNvdXJzZS4gV2VsbCBkb25lLiIKICB9IGVsc2UgaWYoRmluYWxHcmFkZSA+IDApewogICAgIlNvcnJ5IHlvdSBoYXZlIGZhaWxlZCB0aGUgY291cnNlLiIKICB9IGVsc2UgewogICAgIllvdSBoYXZlIG5lZ2F0aXZlIGdyYWRlczsgaXQgc2hvdWxkIGJlIGFuIGVycm9yIgp9CmBgYAoKIyMgJWluJQpJbiB0aGUgbmV4dCBleGFtcGxlIHdlIHVzZSB0aGUgb3BlcmF0b3IgJWluJS4gVGhpcyBvcGVyYXRvciBjaGVja3Mgd2hldGhlciBhIHZhbHVlIGV4aXN0cyBpbnNpZGUgYSB2ZWN0b3IuIEZvciBlYWNoIGVsZW1lbnQgb2YgdGhlIHZlY3RvciBpdCByZXR1cm5zIFRSVUUgaWYgdGhlIHZhbHVlIGlzIGNvbnRhaW5lZCBpbiB0aGUgdmVyY3RvciBhbmQgMCBvdGhlcndpc2U6CgpgYGB7cn0KIyBCb3RoIGVsZW1lbnRzIGluIHRoZSBmaXJzdCB2ZWN0b3IgYXBwZWFycyBpbiB0aGUgc2Vjb25kIHZlY3RvcgpjKDEsMikgJWluJSBjKDYsNCw4LDMsMiwxKQpgYGAKCmBgYHtyfQojIE9ubHkgdGhlIGxhc3QgdHdvIGVsZW1lbnRzIG9mIHRoZSBmaXJzdCB2ZXJjdG9yIGFwcGVhciBpbiB0aGUgc2Vjb25kCmMoNiw0LDgsMywyLDEpICVpbiUgYygxLDIpCmBgYAoKIyMgRm9yIExvb3AKQXMgeW91IHNlZSwgdGhlIHJlc3VsdCBvZiB1c2luZyB0aGUgJWluJSBvcGVyYXRvciBpcyBhIHZlY3RvciBvZiBCb29sZWFuIHZhbHVlcyAoVFJVRSBPUiBGQUxTRSkuIElmIHRoZSBmaXJzdCBlbGVtZW50IGlzIFRSVUUsIGl0IG1lYW5zIHRoYXQgdGhlIGZpcnN0IG51bWJlciBvZiB0aGUgZmlyc3QgdmVjdG9yIGlzIGluc2lkZSB0aGUgc2Vjb25kIHZlY3Rvci4KCmBgYHtyfQpzdHVkZW50czwtYygiUGVkcm8iLCJMYXVyYSIsIkJyeWFuIikKCmZvcihuYW1lIGluIHN0dWRlbnRzKXsKICAjI0luc3RlYWQgb2YgbmFtZSB5b3UgY2FuIHdyaXRlIGFueSB2YXJpYWJsZSBqdXN0IGNoYW5nZSBpdCBpbnNpZGUgdGhlIGxvb3AKICBjYXQoIkhpLCBteSBuYW1lIGlzIixuYW1lKQp9CmBgYApJbiB0aGUgbmV4dCBleGFtcGxlIHdlIHdpbGwgdXNlIHRoZSBxdWFudG1vZCBsaWJyYXJ5IHRvIGRvd25sb2FkIHNvbWUgZmluYW5jaWFsIGRhdGEgZnJvbSBvbmxpbmUgZGF0YSBzb3VyY2VzIHN1Y2ggYXMgWWFob28gZmluYW5jZSBhbmQgR29vZ2xlIEZpbmFuY2UuIE91ciBpbml0aWFsIHZlY3RvciBpbmRpY2F0ZSB0aGUgdGlja2VycyB0byBkb3dubG9hZCwgaW4gdGhpcyBjYXNlIEFBUEwsSlBNIGFuZCBHRS4KCllvdSBoYXZlIHRvIGluc3RhbGwgdGhlIHBhY2thZ2UgaW4gdGhlIFBhY2thZ2UgdGFiIG9mIHRoZSBib3R0b20tcmlnaHQgd2luZG93cyBvZiBSU3R1ZGlvLgoKT25jZSB5b3UgaW5zdGFsbCB0aGUgY29tbWFuZCwgeW91IGhhdmUgdG8gbG9hZCBpdCB3aXRoIHRoZSBsaWJyYXJ5IGZ1bmN0aW9uLiBUaGlzIHF1YW50bW9kIGxpYnJhcnkgaGFzIHRoZSBnZXRTeW1ib2xzIGZ1bmN0aW9uIHRoYXQgaXMgdXNlZCB0byBkb3dubG9hZCBvbmxpbmUgZGF0YSBmcm9tIHRoZSB3ZWI6CgpgYGB7cn0KbGlicmFyeShxdWFudG1vZCkKCiNWZWN0b3Igb2YgdGlja2Vycwp0aWNrZXJzIDwtYygiQUFQTCIsIkpQTSIsIkdFIikKCmZvcihpIGluIHRpY2tlcnMpewogICAgZ2V0U3ltYm9scyhpKQogICAgY2F0KCJ0aGUgcHJpY2VzIG9mIHRoZSB0aWNrZXIiLGksImhhdmUgYmVlbiBkb3dubG9hZGVkIikKfQpgYGAKCkluIHRoZSBuZXh0IGV4YW1wbGUgd2UgZG8gYSBzaW1pbGFyIHByb2Nlc3MgZm9yIGEgZGlmZmVyZW50IHRpY2tlciBsaXN0LiBJbiB0aGUgY2FzZSBvZiBHRSBhbmQgQUFQTCB3ZSBhcmUgZ29pbmcgdG8gZG93bmxvYWQgdGhlIGRhdGEgZnJvbSB5YWhvbywgd2hpbGUgSU5UR1NUTVhNMTkzTiBmcm9tIHRoZSBGRUQuIFdoYXQgaGFwcGVucyB3aXRoIHRoZSByZW1haW5uaW5nIHRpY2tlcnM/CgpgYGB7cn0KdGlja2VycyA8LSBjKCJBQVBMIiwiR00iLCJJTlRHU1RNWE0xOTNOIiwiR0UiLCJKUE0iKQoKZm9yKGkgaW4gdGlja2Vycyl7CiAgaWYoaSAlaW4lIGMoIkFBUEwiLCJHRSIpKXsKICAgIGdldFN5bWJvbHMoaSxzcmMgPSAieWFob28iKQogICAgY2F0KCJ0aGUgcHJpY2VzIG9mIHRoZSB0aWNrZXIiLGksImhhdmUgYmVlbiBkb3dubG9hZGVkIGZyb20geWFob28iKQogIH0KICBlbHNlIGlmKGk9PSJJTlRHU1RNWE0xOTNOIil7CiAgICBnZXRTeW1ib2xzKGksc3JjID0gIkZSRUQiKQogICAgI05vdGUgdGhhdCB0aGUgc291cmNlIGZvciB0aGUgRkVEIGlzIGNhbGxlZCBGUkVECiAgICBjYXQoInRoZSBkYXRhIG9mIHRoZSB0aWNrZXIiLGksImhhdmUgYmVlbiBkb3dubG9hZGVkIGZyb20gdGhlIEZFRCAoRmVkZXJhbCBVUyBCYW5rKSAiKQogIH0KfQpgYGAKCgpXZSBhcmUgZ29pbmcgdG8gdXNlIHRoZSBwcmV2aW91cyBleGFtcGxlLCBidXQgaW4gdGhpcyBjYXNlIHdlIHdhbnQgYWxzbyB0byBhZGQgYSBjb25kaXRpb24gdG8gcHJpbnQgdGhlIHRpY2tlcnMgdGhhdCBoYXZlIE5PVCBiZWVuIGRvd25sb2FkZWQuCgoKYGBge3J9CnRpY2tlcnMgPC0gYygiQUFQTCIsIkdNIiwiSU5UR1NUTVhNMTkzTiIsIkdFIiwiSlBNIikKCmZvcihpIGluIHRpY2tlcnMpewogIAogIGlmKGkgJWluJSBjKCJBQVBMIiwiR0UiKSl7CiAgICBnZXRTeW1ib2xzKGksc3JjID0gInlhaG9vIikKICAgIGNhdCgidGhlIHByaWNlcyBvZiB0aGUgdGlja2VyIixpLCJoYXZlIGJlZW4gZG93bmxvYWRlZCBmcm9tIHlhaG9vIikKICB9CiAgZWxzZSBpZihpPT0iSU5UR1NUTVhNMTkzTiIpewogICAgZ2V0U3ltYm9scyhpLHNyYyA9ICJGUkVEIikKICAgIGNhdCgidGhlIGRhdGEgb2YgdGhlIHRpY2tlciIsaSwiaGF2ZSBiZWVuIGRvd25sb2FkZWQgZnJvbSB0aGUgRkVEIChGZWRlcmFsIFVTIEJhbmspICIpCiAgfQogIGVsc2UgewogICAgY2F0KCJUaGUgdGlja2VyIixpLCJoYXMgbm90IGJlZW4gZG93bmxvYWRlZCIpCiAgfQp9CmBgYAoKCiMjIFdISUxFIEFORCBSRVBFQVQgVE9PTFMKCkluIGEgc2ltaWxhciBtYW5uZXIgdGhhbiB0aGUgZm9yIGxvb3AsIGl0IGlzIHBvc3NpYmxlIHRvIHByb2dyYW0gYSBsb29wIHdpdGggd2hpbGUgYW5kIHJlcGVhdCBjb250cm9sLWZsb3cgc3RhdGVtZW50cy4gVGhlIG1haW4gZGlmZmVyZW5jZSBpcyB0aGF0IGluIGJvdGggeW91IG5lZWQgdG8gc3BlY2lmeSB3aGF0IGlzIHRoZSBleGl0IGNvbmRpdGlvbiwgYW5kIGl0IG1heSBiZSBwb3NzaWJsZSB0aGF0IE5PVCBhbGwgdGhlIGl0ZXJlYXRpb25zIGhhcyB0byBiZSBwZXJmb3JtZWQgKGxpa2UgaW4gdGhlIGZvciBjYXNlKS4KCkZvciB0aGUgd2hpbGUgeW91IG5lZWQgdG8gc3BlY2lmeSB0aGUgY29uZGl0aW9uIGF0IHRoZSBiZWdpbm5pbmcuIEhlcmUgYW4gZXhhbXBsZS4gSWYgeW91IHdhbnQgdG8ga25vdyBob3cgbWFueSB5ZWFycyB5b3UgbmVlZCB0byBrZWVwIGFuIGludmVzdG1lbnQgd2l0aCBhIGZpeGVkIGludGVyZXN0IHJhdGUgaW4gb3JkZXIgdG8gZHVwbGljYXRlIHlvdXIgaW5pdGlhbCBpbnZlc3RtZW50OgoKYGBge3J9CiBBUFI8LTAuMTAKICAjIEkgZGVmaW5lIEFubnVhbCBQZXJjZW50YWdlIFJhdGUgdG8gYmUgZXF1YWwgdG8gMTAlCiAgSU5WPC0xMDAKICAjIEluaXRpYWwgaW52ZXN0bWVudCBlcXVhbCB0byAkMTAwCiAgTVVMVElQTEU8LTIKICAjIE11bHRpcGxlID0gMiB0byBjaGVjayB3aGVuIHRoZSBpbnZlc3RtZW50IGRvdWJsZQogIEJBTEFOQ0U8LUlOVgogICMgSSBzdGFydCBhc3NpZ25pbmcgdGhlIGJhbGFuY2UgZXF1YWwgdG8gdGhlIGluaXRpYWwgaW52ZXN0bWVudAogIHllYXI8LTAKICAjIEkgc3RhcnQgd2l0aCB5ZWFyIGVxdWFsIHRvIHplcm8KICB3aGlsZSAoQkFMQU5DRTxNVUxUSVBMRSpJTlYpIHsKICAgICMgdGhlIGV4aXQgY29uZGl0aW9uIG1lYW5zIHRoYXQgd2hpbGUgdGhlIGJhbGFuY2UgaXMgbGVzcyB0aGFuIHRoZSBpbml0aWFsIGludmVzdG1lbnQKICAgICMgICAgbXVsdGlwbGllZCBieSB0aGUgbXVsdGlwbGUsIHRoZW4gY29udGludWUgd2l0aCB0aGUgaXRlcmF0aW9ucyBvZiB0aGUgbG9vcAogICAgeWVhcjwteWVhcisxIAogICAgIyBJIGluY3JlYXNlIHRoZSB2YWx1ZSBvZiB5ZWFyIGJ5IDEKICAgIEJBTEFOQ0U8LUJBTEFOQ0UqKDErQVBSKSAKICAgICMgSSBtdWx0aXBseSB0aGUgY3VycmVudCBiYWxhbmNlIHRpbWVzIHRoZSBncm93dGggZmFjdG9yICgxK0FQUikgdXNpbmcgdG8gdGhlIAogICAgIyAgIEFubnVhbCBQZXJjZW50YWdlIFJhdGUKICB9CiAgY2F0KAogICAgICJUbyBtdWx0aXBseSB5b3VyIGludmVzdG1lbnQgdGltZXMgIiwgTVVMVElQTEUsICJ5b3UgbmVlZCAiLCB5ZWFyLCAiIHllYXJzLiIpCmBgYAoKYGBge3J9CmNhdCgKICAgICAiWW91ciBiYWxhbmNlIGFmdGVyICIsIHllYXIsICIgeWVhcnMgd2lsbCBiZSAkIixCQUxBTkNFKQpgYGAKVW5saWtlIHRoZSB3aGlsZSBzdGF0ZW1lbnQsIHlvdSBjYW4gdXNlIHRoZSByZXBlYXQgc3RhdGVtZW50IHRvIGRvIGEgbG9vcCwgYnV0IGluIHRoZSBjYXNlIG9mIHJlcGVhdCwgeW91IGhhdmUgdG8gc3BlY2lmeSB0aGUgZXhpdCBjb25kaXRpb24gdXNpbmcgaWYgYW5kIHRoZSBicmVhayBzdGF0ZW1lbnQgYW55IHBsYWNlIHdpdGhpbiB0aGUgbG9vcC4gSGVyZSBpcyB0aGUgc2FtZSBsb29wIHdlIGRpZCBhYm92ZSBidXQgdXNpbmcgcmVwZWF0OgoKCmBgYHtyfQogQVBSPC0wLjEwCiAgIyBJIGRlZmluZSBBbm51YWwgUGVyY2VudGFnZSBSYXRlIHRvIGJlIGVxdWFsIHRvIDEwJQogIElOVjwtMTAwCiAgIyBJbml0aWFsIGludmVzdG1lbnQgZXF1YWwgdG8gJDEwMAogIE1VTFRJUExFPC0yCiAgIyBNdWx0aXBsZSA9IDIgdG8gY2hlY2sgd2hlbiB0aGUgaW52ZXN0bWVudCBkb3VibGUKICBCQUxBTkNFPC1JTlYKICAjIEkgc3RhcnQgYXNzaWduaW5nIHRoZSBiYWxhbmNlIGVxdWFsIHRvIHRoZSBpbml0aWFsIGludmVzdG1lbnQKICB5ZWFyPC0wCiAgIyBJIHN0YXJ0IHdpdGggeWVhciBlcXVhbCB0byB6ZXJvCiAgcmVwZWF0ICB7CiAgICB5ZWFyPC15ZWFyKzEgCiAgICAjIEkgaW5jcmVhc2UgdGhlIHZhbHVlIG9mIHllYXIgYnkgMQogICAgQkFMQU5DRTwtQkFMQU5DRSooMStBUFIpIAogICAgIyBJIG11bHRpcGx5IHRoZSBjdXJyZW50IGJhbGFuY2UgdGltZXMgdGhlIGdyb3d0aCBmYWN0b3IgKDErQVBSKSB1c2luZyB0byB0aGUgCiAgICAjICAgQW5udWFsIFBlcmNlbnRhZ2UgUmF0ZQogICAgaWYgKEJBTEFOQ0U+PU1VTFRJUExFKklOVikgewogICAgICBicmVhawogICAgfQogICAgIyBJZiB0aGUgYmFsYW5jZSBpcyBncmVhdGVyIHRoYW4gdGhlIG11bHRpcGxlIHRpbWVzIHRoZSBpbnZlc3RtZW50LCB0aGVuCiAgICAjICAgdGhlIGJyZWFrIHN0YXRlbWVudCBpcyBleGVjdXRlZCwgc28gdGhlIHByb2dyYW0gc3RvcHMgdGhlIGludGVyYXRpb25zCiAgfQogIGNhdCgKICAgICAiVG8gbXVsdGlwbHkgeW91ciBpbnZlc3RtZW50IHRpbWVzICIsIE1VTFRJUExFLCAieW91IG5lZWQgIiwgeWVhciwgIiB5ZWFycy4iKQpgYGAKCmBgYHtyfQogIGNhdCgKICAgICAiWW91ciBiYWxhbmNlIGFmdGVyICIsIHllYXIsICIgeWVhcnMgd2lsbCBiZSAkIixCQUxBTkNFKQpgYGAKNS40IExvb3BpbmcgdnMgUi12ZWN0b3JpemF0aW9uCk1vc3QgUiBwcm9ncmFtbWVycyBiZWxpZXZlIHRoYXQgbG9vcHMgbXVzdCBiZSBBVk9JREVEISBUaGlzIGlzIHdpZXJkIHNpbmNlIG1vc3Qgb2YgdGhlIHRpbWUgcHJvZ3JhbW1pbmcgcmVxdWlyZXMgdG8gZG8gcmVwZXRpdGl2ZSB0YXNrcy4gSG93ZXZlciwgaW4gUiwgdW5saWtlIG90aGVyIHRyYWRpdGlvbmFsIGNvbXB1dGVyIGxhbmd1YWdlcyBzdWNoIGFzIEMsIHRoZXJlIGlzIGFuIGFsdGVybmF0aXZlIHdheSB0byBkbyBsb29wcyB3aXRob3V0IHdyaXRpbmcgbG9vcHMhCgoKYGBge3J9CkEgPC1jKDMsMyw0LDYsOCkgCiAgQiA8LWMoLTIsLTMsLTEsMyw1KQogICMgQSBhbmQgQiBhcmUgdmVjdG9ycyB3aXRoIHRoZSBhbm51YWwgZnJlZSBjYXNoIGZsb3dzIG9mIGVhY2ggcHJvZHVjdCAKICBzdW1jYXNoZmxvd3M8LXZlY3RvcihsZW5ndGg9NSkKICBmb3IgKGkgaW4gMTpsZW5ndGgoQSkpIHsKICAgIHN1bWNhc2hmbG93c1tpXTwtQVtpXSArIEJbaV0KICAgICMgV2Ugc3VtIHRoZSBlbGVtZW50IGkgb2YgYm90aCB2ZWN0b3JzIGFuZCBsZWF2ZSB0aGUgcmVzdWx0CiAgICAjICAgaW4gdGhlIHBvc2l0aW9uIGkgb2YgdGhlIHZlY3RvciBzdW1jYXNoZmxvd3MKICB9CiAgc3VtY2FzaGZsb3dzCmBgYAoKYGBge3J9CiAgQSA8LWMoMywzLDQsNiw4KSAKICBCIDwtYygtMiwtMywtMSwzLDUpCiAgc3VtY2FzaGZsb3dzPC1BK0IKICAjIFdlIGp1c3Qgc3VtIGJvdGggdmVjdG9ycyBhcyBpZiB0aGV5IHdlcmUgbnVtYmVycwogIHN1bWNhc2hmbG93cwpgYGAKCjUuNSBBcHBsaWNhdGlvbjogUHJlc2VudCB2YWx1ZSBvZiBmdXR1cmUgY2FzaCBmbG93cwpOb3csIGhvdyBjYW4geW91IGNhbGN1bGF0ZSB0aGUgUHJlc2VudCBWYWx1ZSBvZiB0aGVzZSBjYXNoIGZsb3dzPyBZb3UgaGF2ZSB0byByZW1lbWJlciB0aGUgYmFzaWNzIG9mIHRpbWUgdmFsdWUgb2YgbW9uZXkuIFRvIGNhbGN1bGF0ZSB0aGUgcHJlc2VudCB2YWx1ZSAoUFYwKSBvZiBhIHNlcXVlbmNlIG9mIGNhc2ggZmxvd3MgaW4gdGhlIGZ1dHVyZSwgeW91IGp1c3QgaGF2ZSB0byBhcHBseSB0aGUgZm9sbG93aW5nIGZvcm11bGEgZm9yIHRoZSBzZXF1ZW5jZSBvZiBjYXNoIGZsb3dzOgoKY29uIGxvb3AKCmBgYHtyfQogICMgSSBhc3NpZ24gMCB0aGUgdGhlIHZhcmlhYmxlIFBWLCBwcmVzZW50IHZhbHVlCiAgUFYgPC0gMAogICMgSSBkZWZpbmVkIHRoZSBkaXNjb3VudCByYXRlIGFzIFI6CiAgUiA8LSAwLjE1IAogIGZvciAoaSBpbiAxOmxlbmd0aChzdW1jYXNoZmxvd3MpKSB7CiAgICAjIEkgY2FsY3VsYXRlIHRoZSBwcmVzZW50IHZhbHVlIG9mIGVhY2ggY2FzaCBmbG93IGk6CiAgICBQVkNGIDwtIHN1bWNhc2hmbG93c1tpXSAvICgxICsgUileaQogICAjIEkgc3VtIGVhY2ggY29ycmVzcG9uZGluZyBjYXNoIGZsb3cgaSB0byB0aGUgY3VtdWxhdGl2ZSB2YXJpYWJsZSBQViAgICAKICAgIFBWIDwtIFBWICsgUFZDRgogIH0KICMgVGhlIGxvb3AgaXRlcmF0ZXMgNSB0aW1lcywgb25lIGZvciBlYWNoIGNhc2ggZmxvdyBhbmQgd2lsbCBlbmRzIHdpdGggdGhlIHN1bSBvZiBhbGwgCiAgY2F0KCJUaGUgUHJlc2VudCBWYWx1ZSBvZiBhbGwgY2FzaCBmbG93cyBpcyAiLCBQVikKYGBgCgpzaW4gbG9vcAoKYGBge3J9CiAjIEkgYXNzaWduIGEgc2VxdWVuY2UgZnJvbSAxIHRvIDUsIGZvciB0aGUgZXhwb25lbnRzIG9mIHRoZSBmb3JtdWxhIG9mIHByZXNlbnQgdmFsdWUgCiAgIyAgIGZvciBlYWNoIGNhc2ggZm93CiAgZXhwb25lbnRzIDwtIHNlcSgxLDUpCiAgIyBUaGUgc2VxIGlzIGEgZnVuY3Rpb24gdGhhdCBnZW5lcmF0ZXMgYSBzZXF1ZW5jZS4gSGVyZSBJIHNwZWNpZmllZCB0byBzdGFydCB0aGUgCiAgIyAgIHNlcXVlbmNlIGluIDEgYW5kIGZpbmlzaCBpbiA1CiAgIyBJIGNhbGN1bGF0ZSBhIHZlY3RvciB3aXRoIHRoZSBwcmVzZW50IHZhbHVlIGZvciBlYWNoIGNhc2ggZmxvdy4gSSB1c2UgdmVjdG9yaXphdGlvbjoKICBQVnZlY3RvciA8LSBzdW1jYXNoZmxvd3MgLyAoMSArIFIpXmV4cG9uZW50cwogICMgTm90ZSB0aGF0IHRoaXMgbWF0aGVtYXRpY2FsIGV4cHJlc3Npb24gYXBwbGllcyB0byBlYWNoIG9mIHRoZSBlbGVtZW50IG9mIHRoZSB2ZWN0b3IuIAogICMgICBBbHNvLCBlYWNoIHZlY3RvciBoYXMgdGhlIHNhbWUgZGltZW5zaW9uLgogICMgSSBmaW5hbGx5IHN1bSBhbGwgZWxlbWVudHMgb2YgdGhlIHZlY3RvciB1c2luZyB0aGUgZnVuY3Rpb24gc3VtOgogIFBWPC1zdW0oUFZ2ZWN0b3IpCiAgY2F0KCJUaGUgUHJlc2VudCBWYWx1ZSBvZiBhbGwgY2FzaCBmbG93cyBpcyAiLCBQVikKYGBgCiMjNyBDSEFMTEVOR0UgMQpZb3UgaGF2ZSB0byB3cml0ZSBhIHByb2dyYW0gdG8gY2FsY3VsYXRlIHRoZSBudW1iZXIgb2YgbW9udGhzIG5lZWRlZCB0byBmaW5pc2ggcGF5aW5nIGEgbW9ydGdhZ2UgbG9hbi4gVGhlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBsb2FuIGlzIHRoZSBmb2xsb3dpbmc6CgpMb2FuIGFtb3VudCA9ICQzLDAwMCwwMDAuMDAgcGVzb3MKCkFQUiAoQW5udWFsICUgcmF0ZSkgPSAxMSUgKGNvbXBvdW5kZWQgbW9udGhseSkKCk1vbnRobHkgRml4ZWQgUGF5bWVudCA9ICQ0MCwwMDAuMDAgKGluY2x1ZGVzIGludGVyZXN0cyBhbmQgY2FwaXRhbCkKCllvdXIgcHJvZ3JhbSBoYXMgdG8gcHJvdmlkZSAyIHJlc3VsdHM6IHRoZSBudW1iZXIgb2YgbW9udGhzIG5lZWRlZCB0byBmaW5pc2ggcGF5aW5nIHRoZSBsb2FuLCBhbmQgdGhlIGFtb3VudCBvZiB0aGUgbGFzdCBwYXltZW50IGlmIHRoZSBwYXltZW50IGlzIGxlc3MgdGhhbiB0aGUgZml4ZWQgcGF5bWVudCBhbW91bnQuIFlvdXIgcHJvZ3JhbSBoYXMgdG8gYmUgYWJsZSB0byBydW4gd2l0aCBhbnkgY2hhbmdlIGluIGFueSBvZiB0aGUgdmFsdWVzIG9mIHRoZSBhYm92ZSB2YXJpYWJsZXMuCgpUaGlzIGlzIGEgcXVpdGUgY2hhbGxlbmdpbmcgZXhlcmNpc2UhCgpIaW50OiBpZiB5b3UgYXJlIGZhbWlsaWFyIHdpdGggRXhjZWwsIHN0YXJ0IHNvbHZpbmcgdGhlIHByb2JsZW0gaW4gRXhjZWwsIGFuZCB0aGVuIHRyeSB0byB3cml0ZSB5b3VyIHByb2dyYW0gaW4gUi4KCiMjOCBDSEFMTEVOR0UgMgpXcml0ZSBhIHByb2dyYW0gdGhhdCBjYWxjdWxhdGVzIHRoZSBwcmljZSBvZiB0aGUgZm9sbG93aW5nIGJvbmQgaXNzdWVkIGJ5IHRoZSBjb21wYW55IEFCQy4gQUJDIG5lZWRzIHRvIGZpbmFuY2UgYW4gaW1wb3J0YW50IHByb2plY3QgdG8gZGV2ZWxvcCBhIG5ldyB0ZWNobm9sb2dpY2FsIGRldmljZS4KClRvIGdldCB0aGUgbW9uZXksIEFCQyBpc3N1ZWQgYSBib25kIHdpdGggdGhlIGZvbGxvd2luZyBjaGFyYWN0ZXJpc3RpY3M6CgpQcmluY2lwYWw6ICQzLDAwMCwwMDAKVGltZSB0byBtYXR1cml0eTogMjAgeWVhcnMKQ291cG9uIHJhdGU6IDExJSAoYW5udWFsKQpjb3Vwb25zIGFyZSBwYXllZCBlYWNoIDYgbW9udGhzCkNhbGN1bGF0ZSB0aGUgcHJpY2Ugb2YgdGhpcyBib25kIGZvciBlYWNoIG9mIHRoZSBmb2xsb3dpbmcgYW5udWFsIGludGVyZXN0IHJhdGVzOgoKOCUKMTElCjEzJQpZb3UgaGF2ZSB0byBnZXQgdGhlIHByaWNlIGZvciB0aGUgYm9uZCBmb3IgZWFjaCBvZiB0aGVzZSAzIGludGVyZXN0IHJhdGVzLgoKUmVtZW1iZXIgdGhhdCB0aGUgcHJpY2Ugb2YgYSBib25kIGlzIHRoZSBwcmVzZW50IHZhbHVlIG9mIGl0cyBmdXR1cmUgY2FzaCBmbG93cy4KCgojIENIQUxMRU5HRSAxCgpZb3UgaGF2ZSB0byB3cml0ZSBhIHByb2dyYW0gdG8gY2FsY3VsYXRlIHRoZSBudW1iZXIgb2YgbW9udGhzIG5lZWRlZCB0byBmaW5pc2ggcGF5aW5nIGEgbW9ydGdhZ2UgbG9hbi4gVGhlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBsb2FuIGlzIHRoZSBmb2xsb3dpbmc6CgpMb2FuIGFtb3VudCA9ICQzLDAwMCwwMDAuMDAgcGVzb3MKCkFQUiAoQW5udWFsICUgcmF0ZSkgPSAxMSUgKGNvbXBvdW5kZWQgbW9udGhseSkKCk1vbnRobHkgRml4ZWQgUGF5bWVudCA9ICQ0MCwwMDAuMDAgKGluY2x1ZGVzIGludGVyZXN0cyBhbmQgY2FwaXRhbCkKCllvdXIgcHJvZ3JhbSBoYXMgdG8gcHJvdmlkZSAyIHJlc3VsdHM6IHRoZSBudW1iZXIgb2YgbW9udGhzIG5lZWRlZCB0byBmaW5pc2ggcGF5aW5nIHRoZSBsb2FuLCBhbmQgdGhlIGFtb3VudCBvZiB0aGUgbGFzdCBwYXltZW50IGlmIHRoZSBwYXltZW50IGlzIGxlc3MgdGhhbiB0aGUgZml4ZWQgcGF5bWVudCBhbW91bnQuIFlvdXIgcHJvZ3JhbSBoYXMgdG8gYmUgYWJsZSB0byBydW4gd2l0aCBhbnkgY2hhbmdlIGluIGFueSBvZiB0aGUgdmFsdWVzIG9mIHRoZSBhYm92ZSB2YXJpYWJsZXMuCgpUaGlzIGlzIGEgcXVpdGUgY2hhbGxlbmdpbmcgZXhlcmNpc2UhCgpIaW50OiBpZiB5b3UgYXJlIGZhbWlsaWFyIHdpdGggRXhjZWwsIHN0YXJ0IHNvbHZpbmcgdGhlIHByb2JsZW0gaW4gRXhjZWwsIGFuZCB0aGVuIHRyeSB0byB3cml0ZSB5b3VyIHByb2dyYW0gaW4gUi4KCmBgYHtyfQpGaW5hbmNpYWxNYXRoOjphbW9ydC5wZXJpb2QoTG9hbiA9IDMwMDAwMDAsIHBtdCA9IDQwMDAwLCBpID0gLjExLCBuID0gTkEpCmBgYAoKCgojIENIQUxMRU5HRSAyCgpXcml0ZSBhIHByb2dyYW0gdGhhdCBjYWxjdWxhdGVzIHRoZSBwcmljZSBvZiB0aGUgZm9sbG93aW5nIGJvbmQgaXNzdWVkIGJ5IHRoZSBjb21wYW55IEFCQy4gQUJDIG5lZWRzIHRvIGZpbmFuY2UgYW4gaW1wb3J0YW50IHByb2plY3QgdG8gZGV2ZWxvcCBhIG5ldyB0ZWNobm9sb2dpY2FsIGRldmljZS4KClRvIGdldCB0aGUgbW9uZXksIEFCQyBpc3N1ZWQgYSBib25kIHdpdGggdGhlIGZvbGxvd2luZyBjaGFyYWN0ZXJpc3RpY3M6CgpQcmluY2lwYWw6ICQzLDAwMCwwMDAKVGltZSB0byBtYXR1cml0eTogMjAgeWVhcnMKQ291cG9uIHJhdGU6IDExJSAoYW5udWFsKQpjb3Vwb25zIGFyZSBwYXllZCBlYWNoIDYgbW9udGhzCkNhbGN1bGF0ZSB0aGUgcHJpY2Ugb2YgdGhpcyBib25kIGZvciBlYWNoIG9mIHRoZSBmb2xsb3dpbmcgYW5udWFsIGludGVyZXN0IHJhdGVzOgoKOCUKMTElCjEzJQpZb3UgaGF2ZSB0byBnZXQgdGhlIHByaWNlIGZvciB0aGUgYm9uZCBmb3IgZWFjaCBvZiB0aGVzZSAzIGludGVyZXN0IHJhdGVzLgoKUmVtZW1iZXIgdGhhdCB0aGUgcHJpY2Ugb2YgYSBib25kIGlzIHRoZSBwcmVzZW50IHZhbHVlIG9mIGl0cyBmdXR1cmUgY2FzaCBmbG93cy4KCmBgYHtyfQpGaW5hbmNpYWxNYXRoOjpib25kKHQgPSBOQSwgZiA9IDMwMDAwMDAsIHIgPSAyMCwgbiA9IDExLCBpID0gLjA4LCBjID0gMSkKYGBgCihJIHRoaW5rPykKCmBgYHtyfQpGaW5hbmNpYWxNYXRoOjpib25kKHQgPSBOQSwgZiA9IDMwMDAwMDAsIHIgPSAyMCwgbiA9IDExLCBpID0gLjExLCBjID0gMSkKYGBgCgpgYGB7cn0KRmluYW5jaWFsTWF0aDo6Ym9uZCh0ID0gTkEsIGYgPSAzMDAwMDAwLCByID0gMjAsIG4gPSAxMywgaSA9IC4xMSwgYyA9IDEpCmBgYAoK