Associated Material

Zoom Notes: Zoom Notes 09 - Repeating Code

Readings:


Introduction

In the previous module we learned to make our code more modular by organising it into functions, each of which encapsulates some logically distinct task. By repeatedly calling a function, we can execute the same code many times, while only having to type it out once. This is code reuse and is an important goal in efficient software development.

We can also achieve code reuse through iteration. Iterative constructs (more casually called loops) allow us to write a code block once, then instruct R to execute it a specified number of times. The number of iterations can be made to vary depending on the state. (Recall that state is the set of values of all the variables in the environment when a command is executed.) For example, we can write a loop that iterates as many times as there are rows in a data frame that we read from a file before the loop starts.

In R, as in most modern programming languages, there are different types of loops, with subtle differences in behaviour. We begin with the most general kind of loop – the for loop.

Syntax

In R a for loop has the following structure:

for (variable_name in some_kind_of_sequence)
{
    Code block to be repeated. Can be as long as required.
}


The keywords for and in are required, as are the round brackets in the loop header, and the curly brackets that delineate the code body.

The some_kind_of sequence is usually a vector. The code body is executed as many times as there are elements in the vector.

We will discuss the role of the variable_name element later in the module.

(It is also syntactically acceptable to place the opening curly bracket on the same line as the for loop header, after the closing round bracket, separated by a space.)

Basic for loop

A popular cheer in Australian sports is “Aussie!, Aussie!, Aussie!”. Assume that (for some inexplicable reason) you wished to print this cheer. That is, you want to print “Aussie!” to the console three times. Using only sequential code you would write:

print("Aussie!")
print("Aussie!")
print("Aussie!")

You are executing the identical line of code three times. Having to type the same line of code multiple times is boring, and increases the number of opportunities for typos and bugs to sneak in. (In this toy example, we are only repeating one line of code three times; in a real computational situation we might need to repeat dozens of lines of code hundreds of times.) Using a for loop, we can achieve the same output while only typing the command once.

for (cheer in c(1,2,3))
{
  print("Aussie")
}
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"

Match the parts of this loop to the schematic, noting the position of the keywords for and in, the round brackets, and the curly brackets. Note the some_kind_of_sequence element which, in this case, is the vector created by c(1,2,3). Since there are three elements in the vector, the code body is executed three times.

Vector sequences

If we wanted to print “Aussie!” 5 times, we could increase the length of the vector to 5. If we wanted to print it 100 times (could happen) we could increase the length of the vector to 100, but using function c() for this is too cumbersome. In R, we have an alternative for generating a sequence of numbers – the : operator.

small_seq <- 1:5
small_seq
#> [1] 1 2 3 4 5

big_seq <- 1:50
big_seq
#>  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
#> [26] 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

There are more powerful R functions for generating sequences (see, for example seq and rep) but for basic for loops, the : operator is sufficient. We can extend our cheer-printing for loop:

for (cheer in 1:10)
{
  print("Aussie")
}
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"


The Loop Driver

Recall the schematic for a for loop in R:

for (variable_name in some_kind_of_sequence)
{
    Code to be repeated. Can be as long as required.
}


The variable_name element can be any legal R variable name. This element is called the loop driver. Inside the code body of the for loop, the loop driver variable is always available. For example, in our “Aussie!, Aussie! Aussie!” example, our loop driver was called cheer. In our code body we could have referred to variable cheer.

As discussed above, the for loop code body is executed as many times as there are elements in the sequence in the header. At each pass through the loop, the loop driver variable automatically takes on the value of the corresponding element of the sequence. That is, in the first pass of the loop, the loop driver holds the value of the first element of the sequence; in the second pass of the loop, the loop driver holds the value of the second element of the sequence, and so on.

We illustrate this by extending our previous example to print the value of loop driver cheer inside the code body:

for (cheer in 1:3)
{
  print("Aussie")
  print(cheer)
}
#> [1] "Aussie"
#> [1] 1
#> [1] "Aussie"
#> [1] 2
#> [1] "Aussie"
#> [1] 3

Note that you never assign a value to the loop driver – it takes on its values automatically as the for loop runs.

In all our examples so far, the sequence in the for loop header has been numbers from 1 to n. In R, the sequence can be a vector of any type, and the loop driver will take on whatever values the sequence contains. For example, we can drive a for loop with a vector of string:

sports <- c("Rugby", "Cycling", "Ice Skating")
for (current_sport in sports)
{
  # Print the sport name
  print(current_sport)
  
  # Compute the number of characters in the sport name
  print(nchar(current_sport))
}
#> [1] "Rugby"
#> [1] 5
#> [1] "Cycling"
#> [1] 7
#> [1] "Ice Skating"
#> [1] 11


Loop driver as index

Throughout the course we have seen that R relies heavily on managing data in ordered collections (vectors, lists, and data frames). We select elements from those collections using the selection operator [], providing the ordinal position of the element of interest. Since loop driver variables take on each value in their sequence, we can use a for loop to step through each element of a collection in turn.

For example, assume you have a data frame containing one student’s internal and exam marks for the papers taken in one semester:

paper_codes <- c("HUBS192", "ECOL212", "STAT260")
internal_marks <- c(87, 85, 62)
exam_marks <- c(93, 84, 85)

marks_df <- data.frame(PaperCode = paper_codes,
                       InternalMark = as.numeric(internal_marks),
                       ExamMark = as.numeric(exam_marks))

marks_df
#>   PaperCode InternalMark ExamMark
#> 1   HUBS192           87       93
#> 2   ECOL212           85       84
#> 3   STAT260           62       85

We know that we can select all columns from a single row in that data frame using the syntax [row number, ]

# Select and print row 2
selected_row <- marks_df[2, ]
print(selected_row)
#>   PaperCode InternalMark ExamMark
#> 2   ECOL212           85       84

With a for loop, we can use the loop driver to iterate over all the rows, processing each in turn:

for (index in 1:3)
{
  # Use the loop driver to select a row from the data frame
  selected_row <- marks_df[index, ]
  
  # Process the row (just printing in this example)
  print(selected_row)
}
#>   PaperCode InternalMark ExamMark
#> 1   HUBS192           87       93
#>   PaperCode InternalMark ExamMark
#> 2   ECOL212           85       84
#>   PaperCode InternalMark ExamMark
#> 3   STAT260           62       85

Note that if we made our data frame longer than three rows by adding more papers to it, the preceding for loop would not print all the rows; the sequence in that example is always 1, 2, 3 so we see only rows 1, 2, and 3. We can make the loop more general by determining the for loop sequence dynamically using function nrow, which accepts a data frame as an argument, and returns the number of rows in the data frame:

# Display all rows
for (index in 1:nrow(marks_df))
{
  # Use the loop driver to index into the data frame
  selected_row <- marks_df[index, ]
  print(selected_row)
}
#>   PaperCode InternalMark ExamMark
#> 1   HUBS192           87       93
#>   PaperCode InternalMark ExamMark
#> 2   ECOL212           85       84
#>   PaperCode InternalMark ExamMark
#> 3   STAT260           62       85

# Add a row to the data frame
marks_df <- rbind(marks_df, data.frame(PaperCode = "ZOOL316", 
                                       InternalMark = 83, 
                                       ExamMark = 90))


# Repeat the loop -- see four rows
for (index in 1:nrow(marks_df))
{
  # Use the loop driver to index into the data frame
  selected_row <- marks_df[index, ]
  print(selected_row)
}
#>   PaperCode InternalMark ExamMark
#> 1   HUBS192           87       93
#>   PaperCode InternalMark ExamMark
#> 2   ECOL212           85       84
#>   PaperCode InternalMark ExamMark
#> 3   STAT260           62       85
#>   PaperCode InternalMark ExamMark
#> 4   ZOOL316           83       90


Exercise

  1. Write a for loop that iterates over marks_df printing each column in turn.
  2. Your final mark in each paper is computed as 40% of your internal mark plus 60% of your exam mark. Using the technique of your choice, add a new column to data frame marks_df which contains the computed final mark for each paper.
  3. Run your for loop again and confirm that it displays all the columns, including the new one.
# Display all columns
for (index in 1:ncol(marks_df))
{
  # Use the loop driver to index into the data frame
  selected_col <- marks_df[ , index]
  print(selected_col)
}
#> [1] "HUBS192" "ECOL212" "STAT260" "ZOOL316"
#> [1] 87 85 62 83
#> [1] 93 84 85 90


# Add a new column
marks_df$TotalMark <- (0.40 * marks_df$InternalMark) + (0.60 * marks_df$ExamMark) 


# Confirm that we display all four columns
for (index in 1:ncol(marks_df))
{
  # Use the loop driver to index into the data frame
  selected_col <- marks_df[ , index]
  print(selected_col)
}
#> [1] "HUBS192" "ECOL212" "STAT260" "ZOOL316"
#> [1] 87 85 62 83
#> [1] 93 84 85 90
#> [1] 90.6 84.4 75.8 87.2


Nested for loops

In the preceding examples, we have iterated over a data frame processing complete rows, or complete columns. Frequently, it is necessary to iterate over a data frame (or matrix) processing each individual cell in turn. That is, instead of using the [, col] or [row, ] forms of selection, we need to specify both a row index and a column index (i.e. [row, col]). This is very common processing technique in simulation, computer graphics, artificial intelligence, and computational problems requiring matrix algebra.

We iterate over tabular date in an orderly fashion. For example, if we have a 3x3 matrix or data frame we would process the cells in the first row from left to right ([1,1], [1,2], [1,3]), then the cells in the second row ([2,1], [2,2], [2,3]), and finally the cells in the third row ([3,1], [3,1], [3,3]). You can view this pattern as using two loop drivers, one for the row index and one for the column index. While the row driver is 1, we want the column driver to loop through values 1, 2, and 3. Then, we want the row driver to take on 2, and again want the column driver to loop through 1, 2, and 3. Finally we want the row driver to be 3, and the column driver to loop again. We can achieve this by nesting a for loop for columns inside a for loop for rows, as shown below. Note that each for loop has its own loop driver, its own sequence and its own round and curly brackets. The style of indenting the inner for loop is important for maintaining code readability.

# Outer loop.
for (row_index in 1:nrow(marks_df))
{
  # Inner loop -- makes all iterations for each pass through outer loop
  for (col_index in 1:ncol(marks_df))
  {
    # Use both loop drivers to select
    cell_value <- marks_df[row_index, col_index]
    print(cell_value)
  }
}
#> [1] "HUBS192"
#> [1] 87
#> [1] 93
#> [1] 90.6
#> [1] "ECOL212"
#> [1] 85
#> [1] 84
#> [1] 84.4
#> [1] "STAT260"
#> [1] 62
#> [1] 85
#> [1] 75.8
#> [1] "ZOOL316"
#> [1] 83
#> [1] 90
#> [1] 87.2


Exercise

The preceding example prints row-wise. That is, it prints all the values for each row (i.e. for a single paper) before moving to the next row (paper). Modify the code to print column-wise. That is, print down the columns: all the paper names, then all the internal marks, then all the exam marks, then all the final marks.

# Outer loop.
for (col_index in 1:ncol(marks_df))
{
  # Inner loop -- makes all iterations for each pass through outer loop
  for (row_index in 1:nrow(marks_df))
  {
    # Use both loop drivers to select
    cell_value <- marks_df[row_index, col_index]
    print(cell_value)
  }
}
#> [1] "HUBS192"
#> [1] "ECOL212"
#> [1] "STAT260"
#> [1] "ZOOL316"
#> [1] 87
#> [1] 85
#> [1] 62
#> [1] 83
#> [1] 93
#> [1] 84
#> [1] 85
#> [1] 90
#> [1] 90.6
#> [1] 84.4
#> [1] 75.8
#> [1] 87.2


CAUTION

Using a nested for loop to visit every cell in a table is a very common, and very powerful code pattern. However, be aware that it can be computationally expensive (i.e. it can take a long time to run). If your outer loop runs n passes and your inner loop runs m passes, you make a total of n * m passes. When processing a 1000 row x 1000 column table with a nested for loop, the code body of the inner loop is executed one million times, which may be intractable. If you have large tabular data sets that take a long time to process, you should consider leveraging R’s advanced vector processing techniques that can be more efficient than an interior for loop. See, for example, https://rstudio-pubs-static.s3.amazonaws.com/72295_692737b667614d369bd87cb0f51c9a4b.html or http://www.john-ros.com/Rcourse/memory.html for discussions.

While loop

The for loop is used when you want to execute a code body a specific number of times, or iterate over a specific sequence of values. An alternative loop structure – the while loop repeats as long as a given condition evaluates to true.

The schematic for a while loop is as follows:

while (condition) 
{
  # Loop body
}

In an earlier module, we used function rnorm to randomly select a value from a normal distribution with a known mean and standard deviation. Imagine that you want to explore the probability of randomly selecting a number from such a distribution that is more than two standard deviations above the mean (i.e. has a z-score of 2 or more). You could estimate this by repeatedly selecting a number until you achieved the criterion, and counting the number of times you had to select. We wish to loop repeatedly over some logic (selecting and counting), but we don’t know exactly how many times the loop should run, so a for loop is not appropriate. In this situation, we use a while loop.

Before looking at the code sample below, try to work out what the while loop condition will be.

# Define the parameters
distribution_mean <- 100
distribution_sd <- 10

# Prepare a variable to count the passes
count <- 0

# Make your first selection so the loop condition to be evaluated 
# on the first pass
rand_value <- rnorm(1, distribution_mean, distribution_sd)

# The loop. Note the condition. We continue running the loop
# as long as our selected value is less than mean + 2*sd.
# While loops run as long as the loop condition is true.
while (rand_value < distribution_mean + (2 * distribution_sd))
{
  # increment the count because the loop condition was true
  count <- count + 1
  
  # Select again
  rand_value <- rnorm(1, distribution_mean, distribution_sd)
  
} # end of while loop

# Display the result
output <- paste(count, "values were chosen before z-score > 1")
print(output)
#> [1] "8 values were chosen before z-score > 1"

Here is an example of a while loop to count how many iterations it takes to obtain 3 heads in a row:

## Example from R for Data Science - 21.3.4 ##

# Function to simulate head or tail as the result of a coin flip
flip <- function(){
  sample(c("T", "H"), 1)
}

# variables to keep track of key results
flips <- 0
nheads <- 0

# flip a coin until there are three heads and count how many flips were performed.
while (nheads < 3) {
  if (flip() == "H") {
    nheads <- nheads + 1
  } else {
    nheads <- 0
  }
  flips <- flips + 1
}
flips
#> [1] 15


Infinite while loops

NB: It is essential that your while loop condition will eventually evaluate to false. Consider the following code sample (which we will not run).

# Set a starting value so we can check the condition on the first pass
x <- 10

# The loop
while (x > 0)
{
  # The code body
  x <- x + 1
}

The variable x is initialised to 10, and incremented at each pass through the code body. Its value will therefore always be greater than or equal to 10. The loop condition is x > 0. Since x starts at 10 and increases at each pass, it will always be greater than 0, so the loop condition will always be true, and the loop will never stop. This is an infinite loop. When your code is in an infinite loop, the only way to stop it is to forcibly terminate the program (assuming you recognise what has occurred). In R you can usually do this by clicking the red stop sign in the top right corner of the console window. An infinite loop that produces a lot of variables can consume memory to the point where the machine will crash. This is bad. Always check that your loop condition is guaranteed to eventually evaluate to false before running code with a while loop.

Map

In the package purrr (part of package tidyverse), there are a collection of map functions which iterate over a vector or list, applying a function to each element. This is a very succinct syntax, which achieves the same result as calling the function inside a for loop, without the overhead of writing out the loop structure.

library(purrr)

farenheit_to_celcius <- function(temp_f){
  temp_c <- (temp_f - 32) * 5/9
  return(temp_c)
}

my_temps_f <- c(90, 78, 88, 89, 77)

# map applies the function (2nd argument) to each element of the vector (1st argument) 
# and returns the results as a list. 
my_temps_c_list <- map(my_temps_f, farenheit_to_celcius)
my_temps_c_list
#> [[1]]
#> [1] 32.22222
#> 
#> [[2]]
#> [1] 25.55556
#> 
#> [[3]]
#> [1] 31.11111
#> 
#> [[4]]
#> [1] 31.66667
#> 
#> [[5]]
#> [1] 25

The map argument names are .x and .f, so the call to map above could also be written as my_temps_c_list <- map(.x = my_temps_f, .f = farenheit_to_celcius)

Note that when providing a function as an argument, give only the function name. Do not follow the function name with () as for a function call.

Map and friends

The basic form of map above, returns the results in a list. There are suffix versions of map that return the results as a specific data type.

  • map() makes a list.
  • map_lgl() makes a logical vector.
  • map_int() makes an integer vector.
  • map_dbl() makes a double vector.
  • map_chr() makes a character vector.

These suffix versions will give an error if the data type of the results doesn’t match the intended return type. This is useful because you can write code to process the results further, confident that they are of a specific data type.

Apply

Base R has a set of built in functions that duplicate the behaviour of purrr::map and its suffix functions. These are the apply family: apply, lapply, sapply, mapply, and tapply. The functions differ primarily in the structure of the data they return. See, for example, http://adv-r.had.co.nz/Functionals.html for more detail.

Function lapply is analogous to purrr::map():

farenheit_to_celcius <- function(temp_f){
  temp_c <- (temp_f -32) * 5/9
  return(temp_c)
}

my_temps_f <- c(90, 78, 88, 89, 77)

# lapply example
lapply_my_temps_c <- lapply(X = my_temps_f, FUN = farenheit_to_celcius)
lapply_my_temps_c
#> [[1]]
#> [1] 32.22222
#> 
#> [[2]]
#> [1] 25.55556
#> 
#> [[3]]
#> [1] 31.11111
#> 
#> [[4]]
#> [1] 31.66667
#> 
#> [[5]]
#> [1] 25

Note that some of the apply family return different data structures depending on the type of the input data. This can make it challenging to know beforehand what the output is going to look like - unlike the suffix versions of purrr::map

Conclusion

In this module we covered using for and while loops to repeat code fragments efficiently. We saw that functions in the map and apply families provide an equivalent, yet more succinct syntax, when the repeated code is a single function. Combining loops with functions and conditional flow of control from last week’s session, you can create code that is modular, reusable, and maintainable.

What’s Next

Next week we conclude the formal content of R4SSP with a discussion of R workflows, including project structure, incremental development, and effective debugging techniques.

LS0tCnRpdGxlOiAiUmVwZWF0aW5nIENvZGUiCmRhdGU6ICJTZW1lc3RlciAyLCAyMDIzIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfZGVwdGg6IDMKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGNvbW1lbnQgPSAiIz4iLAogIGZpZy5wYXRoID0gImZpZ3VyZXMvMDkvIiwgIyB1c2Ugb25seSBmb3Igc2luZ2xlIFJtZCBmaWxlcwogIGNvbGxhcHNlID0gVFJVRSwKICBlY2hvID0gVFJVRQopCgojIGtlZXAgdGhlIHJlc3VsdGluZyBodG1sIHRoZSBzYW1lIHNpbmNlIHNhbXBsaW5nIGlzIHVzZWQgbGF0ZXIgb24gaW4gdGhlIGxlc3NvbgpzZXQuc2VlZCg0MikKCmBgYAoKPiAjIyMjIEFzc29jaWF0ZWQgTWF0ZXJpYWwKPgo+IFpvb20gTm90ZXM6IFtab29tIE5vdGVzIDA5IC0gUmVwZWF0aW5nIENvZGVdKHpvb21fbm90ZXNfMDlfaXRlcmF0ZS5odG1sKQo+Cj4gUmVhZGluZ3M6Cj4KPiAtIFtSIGZvciBEYXRhIFNjaWVuY2UgLSBDaGFwdGVyIDIxXShodHRwczovL3I0ZHMuaGFkLmNvLm56L2l0ZXJhdGlvbi5odG1sKQoKXAoKIyBJbnRyb2R1Y3Rpb24KCkluIHRoZSBwcmV2aW91cyBtb2R1bGUgd2UgbGVhcm5lZCB0byBtYWtlIG91ciBjb2RlIG1vcmUgKiptb2R1bGFyKiogYnkgb3JnYW5pc2luZyBpdCBpbnRvIGZ1bmN0aW9ucywgZWFjaCBvZiB3aGljaCBlbmNhcHN1bGF0ZXMgc29tZSBsb2dpY2FsbHkgZGlzdGluY3QgdGFzay4gQnkgcmVwZWF0ZWRseSBjYWxsaW5nIGEgZnVuY3Rpb24sIHdlIGNhbiBleGVjdXRlIHRoZSBzYW1lIGNvZGUgbWFueSB0aW1lcywgd2hpbGUgb25seSBoYXZpbmcgdG8gdHlwZSBpdCBvdXQgb25jZS4gVGhpcyBpcyAqKmNvZGUgcmV1c2UqKiBhbmQgaXMgYW4gaW1wb3J0YW50IGdvYWwgaW4gZWZmaWNpZW50IHNvZnR3YXJlIGRldmVsb3BtZW50LgoKV2UgY2FuIGFsc28gYWNoaWV2ZSBjb2RlIHJldXNlIHRocm91Z2ggKippdGVyYXRpb24qKi4gSXRlcmF0aXZlIGNvbnN0cnVjdHMgKG1vcmUgY2FzdWFsbHkgY2FsbGVkICoqbG9vcHMqKikgYWxsb3cgdXMgdG8gd3JpdGUgYSBjb2RlIGJsb2NrIG9uY2UsIHRoZW4gaW5zdHJ1Y3QgUiB0byBleGVjdXRlIGl0IGEgc3BlY2lmaWVkIG51bWJlciBvZiB0aW1lcy4gVGhlIG51bWJlciBvZiBpdGVyYXRpb25zIGNhbiBiZSBtYWRlIHRvIHZhcnkgZGVwZW5kaW5nIG9uIHRoZSAqKnN0YXRlKiouIChSZWNhbGwgdGhhdCAqKnN0YXRlKiogaXMgdGhlIHNldCBvZiB2YWx1ZXMgb2YgYWxsIHRoZSB2YXJpYWJsZXMgaW4gdGhlIGVudmlyb25tZW50IHdoZW4gYSBjb21tYW5kIGlzIGV4ZWN1dGVkLikgRm9yIGV4YW1wbGUsIHdlIGNhbiB3cml0ZSBhIGxvb3AgdGhhdCBpdGVyYXRlcyBhcyBtYW55IHRpbWVzIGFzIHRoZXJlIGFyZSByb3dzIGluIGEgZGF0YSBmcmFtZSB0aGF0IHdlIHJlYWQgZnJvbSBhIGZpbGUgYmVmb3JlIHRoZSBsb29wIHN0YXJ0cy4KCkluIFIsIGFzIGluIG1vc3QgbW9kZXJuIHByb2dyYW1taW5nIGxhbmd1YWdlcywgdGhlcmUgYXJlIGRpZmZlcmVudCB0eXBlcyBvZiBsb29wcywgd2l0aCBzdWJ0bGUgZGlmZmVyZW5jZXMgaW4gYmVoYXZpb3VyLiBXZSBiZWdpbiB3aXRoIHRoZSBtb3N0IGdlbmVyYWwga2luZCBvZiBsb29wIC0tIHRoZSAqKmZvciBsb29wKiouCgoKIyBTeW50YXgKCkluIFIgYSAqKmZvciBsb29wKiogaGFzIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlOgoKCnwgKipmb3IqKiAoKnZhcmlhYmxlX25hbWUqICoqaW4qKiAqc29tZV9raW5kX29mX3NlcXVlbmNlKikKfCB7CnwgICAgICpDb2RlIGJsb2NrIHRvIGJlIHJlcGVhdGVkLiBDYW4gYmUgYXMgbG9uZyBhcyByZXF1aXJlZC4qCnwgfQoKXAoKVGhlIGtleXdvcmRzICoqZm9yKiogYW5kICoqaW4qKiBhcmUgcmVxdWlyZWQsIGFzIGFyZSB0aGUgcm91bmQgYnJhY2tldHMgaW4gdGhlICoqbG9vcCBoZWFkZXIqKiwgYW5kIHRoZSBjdXJseSBicmFja2V0cyB0aGF0IGRlbGluZWF0ZSB0aGUgY29kZSBib2R5LgoKVGhlICpzb21lX2tpbmRfb2Ygc2VxdWVuY2UqIGlzIHVzdWFsbHkgYSB2ZWN0b3IuIFRoZSBjb2RlIGJvZHkgaXMgZXhlY3V0ZWQgYXMgbWFueSB0aW1lcyBhcyB0aGVyZSBhcmUgZWxlbWVudHMgaW4gdGhlIHZlY3Rvci4KCldlIHdpbGwgZGlzY3VzcyB0aGUgcm9sZSBvZiB0aGUgKnZhcmlhYmxlX25hbWUqIGVsZW1lbnQgbGF0ZXIgaW4gdGhlIG1vZHVsZS4KCihJdCBpcyBhbHNvIHN5bnRhY3RpY2FsbHkgYWNjZXB0YWJsZSB0byBwbGFjZSB0aGUgb3BlbmluZyBjdXJseSBicmFja2V0IG9uIHRoZSBzYW1lIGxpbmUgYXMgdGhlIGZvciBsb29wIGhlYWRlciwgYWZ0ZXIgdGhlIGNsb3Npbmcgcm91bmQgYnJhY2tldCwgc2VwYXJhdGVkIGJ5IGEgc3BhY2UuKQoKCiMgQmFzaWMgZm9yIGxvb3AKCkEgcG9wdWxhciBjaGVlciBpbiBBdXN0cmFsaWFuIHNwb3J0cyBpcyAiQXVzc2llISwgQXVzc2llISwgQXVzc2llISIuIEFzc3VtZSB0aGF0IChmb3Igc29tZSBpbmV4cGxpY2FibGUgcmVhc29uKSB5b3Ugd2lzaGVkIHRvIHByaW50IHRoaXMgY2hlZXIuIFRoYXQgaXMsIHlvdSB3YW50IHRvIHByaW50ICJBdXNzaWUhIiB0byB0aGUgY29uc29sZSB0aHJlZSB0aW1lcy4gVXNpbmcgb25seSBzZXF1ZW50aWFsIGNvZGUgeW91IHdvdWxkIHdyaXRlOgoKYGBge3Igc2VxdWVudGlhbCwgZXZhbD1GQUxTRX0KcHJpbnQoIkF1c3NpZSEiKQpwcmludCgiQXVzc2llISIpCnByaW50KCJBdXNzaWUhIikKYGBgCgpZb3UgYXJlIGV4ZWN1dGluZyB0aGUgaWRlbnRpY2FsIGxpbmUgb2YgY29kZSB0aHJlZSB0aW1lcy4gSGF2aW5nIHRvIHR5cGUgdGhlIHNhbWUgbGluZSBvZiBjb2RlIG11bHRpcGxlIHRpbWVzIGlzIGJvcmluZywgYW5kIGluY3JlYXNlcyB0aGUgbnVtYmVyIG9mIG9wcG9ydHVuaXRpZXMgZm9yIHR5cG9zIGFuZCBidWdzIHRvIHNuZWFrIGluLiAoSW4gdGhpcyB0b3kgZXhhbXBsZSwgd2UgYXJlIG9ubHkgcmVwZWF0aW5nIG9uZSBsaW5lIG9mIGNvZGUgdGhyZWUgdGltZXM7IGluIGEgcmVhbCBjb21wdXRhdGlvbmFsIHNpdHVhdGlvbiB3ZSBtaWdodCBuZWVkIHRvIHJlcGVhdCBkb3plbnMgb2YgbGluZXMgb2YgY29kZSBodW5kcmVkcyBvZiB0aW1lcy4pIFVzaW5nIGEgKipmb3IgbG9vcCoqLCB3ZSBjYW4gYWNoaWV2ZSB0aGUgc2FtZSBvdXRwdXQgd2hpbGUgb25seSB0eXBpbmcgdGhlIGNvbW1hbmQgb25jZS4KCmBgYHtyIGJhc2ljIGxvb3B9CmZvciAoY2hlZXIgaW4gYygxLDIsMykpCnsKICBwcmludCgiQXVzc2llIikKfQpgYGAKCk1hdGNoIHRoZSBwYXJ0cyBvZiB0aGlzIGxvb3AgdG8gdGhlIHNjaGVtYXRpYywgbm90aW5nIHRoZSBwb3NpdGlvbiBvZiB0aGUga2V5d29yZHMgKipmb3IqKiBhbmQgKippbioqLCB0aGUgcm91bmQgYnJhY2tldHMsIGFuZCB0aGUgY3VybHkgYnJhY2tldHMuIE5vdGUgdGhlICpzb21lX2tpbmRfb2Zfc2VxdWVuY2UqIGVsZW1lbnQgd2hpY2gsIGluIHRoaXMgY2FzZSwgaXMgdGhlIHZlY3RvciBjcmVhdGVkIGJ5IGBjKDEsMiwzKWAuIFNpbmNlIHRoZXJlIGFyZSB0aHJlZSBlbGVtZW50cyBpbiB0aGUgdmVjdG9yLCB0aGUgY29kZSBib2R5IGlzIGV4ZWN1dGVkIHRocmVlIHRpbWVzLiAKCiMjIFZlY3RvciBzZXF1ZW5jZXMKCklmIHdlIHdhbnRlZCB0byBwcmludCAiQXVzc2llISIgNSB0aW1lcywgd2UgY291bGQgaW5jcmVhc2UgdGhlIGxlbmd0aCBvZiB0aGUgdmVjdG9yIHRvIDUuIElmIHdlIHdhbnRlZCB0byBwcmludCBpdCAxMDAgdGltZXMgKGNvdWxkIGhhcHBlbikgd2UgY291bGQgaW5jcmVhc2UgdGhlIGxlbmd0aCBvZiB0aGUgdmVjdG9yIHRvIDEwMCwgYnV0IHVzaW5nIGZ1bmN0aW9uIGBjKClgIGZvciB0aGlzIGlzIHRvbyBjdW1iZXJzb21lLiBJbiBSLCB3ZSBoYXZlIGFuIGFsdGVybmF0aXZlIGZvciBnZW5lcmF0aW5nIGEgc2VxdWVuY2Ugb2YgbnVtYmVycyAtLSB0aGUgYDpgIG9wZXJhdG9yLgoKYGBge3Igc2VxIH0Kc21hbGxfc2VxIDwtIDE6NQpzbWFsbF9zZXEKCmJpZ19zZXEgPC0gMTo1MApiaWdfc2VxCmBgYAoKVGhlcmUgYXJlIG1vcmUgcG93ZXJmdWwgUiBmdW5jdGlvbnMgZm9yIGdlbmVyYXRpbmcgc2VxdWVuY2VzIChzZWUsIGZvciBleGFtcGxlIGBzZXFgIGFuZCBgcmVwYCkgYnV0IGZvciBiYXNpYyBmb3IgbG9vcHMsIHRoZSBgOmAgb3BlcmF0b3IgaXMgc3VmZmljaWVudC4gV2UgY2FuIGV4dGVuZCBvdXIgY2hlZXItcHJpbnRpbmcgZm9yIGxvb3A6CgpgYGB7ciBsb25nIGNoZWVyfQpmb3IgKGNoZWVyIGluIDE6MTApCnsKICBwcmludCgiQXVzc2llIikKfQpgYGAKClwKCiMgVGhlIExvb3AgRHJpdmVyCgpSZWNhbGwgdGhlIHNjaGVtYXRpYyBmb3IgYSBmb3IgbG9vcCBpbiBSOgoKfCAqKmZvcioqICgqdmFyaWFibGVfbmFtZSogKippbioqICpzb21lX2tpbmRfb2Zfc2VxdWVuY2UqKQp8IHsKfCAgICAgKkNvZGUgdG8gYmUgcmVwZWF0ZWQuIENhbiBiZSBhcyBsb25nIGFzIHJlcXVpcmVkLioKfCB9CgpcClRoZSAqdmFyaWFibGVfbmFtZSogZWxlbWVudCBjYW4gYmUgYW55IGxlZ2FsIFIgdmFyaWFibGUgbmFtZS4gVGhpcyBlbGVtZW50IGlzIGNhbGxlZCB0aGUgKipsb29wIGRyaXZlcioqLiBJbnNpZGUgdGhlIGNvZGUgYm9keSBvZiB0aGUgZm9yIGxvb3AsIHRoZSBsb29wIGRyaXZlciB2YXJpYWJsZSAqKmlzIGFsd2F5cyBhdmFpbGFibGUqKi4gRm9yIGV4YW1wbGUsIGluIG91ciAiQXVzc2llISwgQXVzc2llISBBdXNzaWUhIiBleGFtcGxlLCBvdXIgbG9vcCBkcml2ZXIgd2FzIGNhbGxlZCAqY2hlZXIqLiBJbiBvdXIgY29kZSBib2R5IHdlIGNvdWxkIGhhdmUgcmVmZXJyZWQgdG8gdmFyaWFibGUgYGNoZWVyYC4gCgpBcyBkaXNjdXNzZWQgYWJvdmUsIHRoZSBmb3IgbG9vcCBjb2RlIGJvZHkgaXMgZXhlY3V0ZWQgYXMgbWFueSB0aW1lcyBhcyB0aGVyZSBhcmUgZWxlbWVudHMgaW4gdGhlIHNlcXVlbmNlIGluIHRoZSBoZWFkZXIuIEF0IGVhY2ggcGFzcyB0aHJvdWdoIHRoZSBsb29wLCB0aGUgbG9vcCBkcml2ZXIgdmFyaWFibGUgYXV0b21hdGljYWxseSB0YWtlcyBvbiAqKnRoZSB2YWx1ZSBvZiB0aGUgY29ycmVzcG9uZGluZyBlbGVtZW50IG9mIHRoZSBzZXF1ZW5jZSoqLiBUaGF0IGlzLCBpbiB0aGUgZmlyc3QgcGFzcyBvZiB0aGUgbG9vcCwgdGhlIGxvb3AgZHJpdmVyIGhvbGRzIHRoZSB2YWx1ZSBvZiB0aGUgZmlyc3QgZWxlbWVudCBvZiB0aGUgc2VxdWVuY2U7IGluIHRoZSBzZWNvbmQgcGFzcyBvZiB0aGUgbG9vcCwgdGhlIGxvb3AgZHJpdmVyIGhvbGRzIHRoZSB2YWx1ZSBvZiB0aGUgc2Vjb25kIGVsZW1lbnQgb2YgdGhlIHNlcXVlbmNlLCBhbmQgc28gb24uCgpXZSBpbGx1c3RyYXRlIHRoaXMgYnkgZXh0ZW5kaW5nIG91ciBwcmV2aW91cyBleGFtcGxlIHRvIHByaW50IHRoZSB2YWx1ZSBvZiBsb29wIGRyaXZlciBgY2hlZXJgIGluc2lkZSB0aGUgY29kZSBib2R5OgoKYGBge3IgbG9uZyBjaGVlciAyfQpmb3IgKGNoZWVyIGluIDE6MykKewogIHByaW50KCJBdXNzaWUiKQogIHByaW50KGNoZWVyKQp9CmBgYAoKTm90ZSB0aGF0IHlvdSAqKm5ldmVyIGFzc2lnbiBhIHZhbHVlIHRvIHRoZSBsb29wIGRyaXZlcioqIC0tIGl0IHRha2VzIG9uIGl0cyB2YWx1ZXMgYXV0b21hdGljYWxseSBhcyB0aGUgZm9yIGxvb3AgcnVucy4KCkluIGFsbCBvdXIgZXhhbXBsZXMgc28gZmFyLCB0aGUgc2VxdWVuY2UgaW4gdGhlIGZvciBsb29wIGhlYWRlciBoYXMgYmVlbiBudW1iZXJzIGZyb20gMSB0byAqbiouIEluIFIsIHRoZSBzZXF1ZW5jZSBjYW4gYmUgYSB2ZWN0b3Igb2YgYW55IHR5cGUsIGFuZCB0aGUgbG9vcCBkcml2ZXIgd2lsbCB0YWtlIG9uIHdoYXRldmVyIHZhbHVlcyB0aGUgc2VxdWVuY2UgY29udGFpbnMuIEZvciBleGFtcGxlLCB3ZSBjYW4gZHJpdmUgYSBmb3IgbG9vcCB3aXRoIGEgdmVjdG9yIG9mIHN0cmluZzoKCmBgYHtyIHNlcSBvZiBzdHJpbmd9CnNwb3J0cyA8LSBjKCJSdWdieSIsICJDeWNsaW5nIiwgIkljZSBTa2F0aW5nIikKZm9yIChjdXJyZW50X3Nwb3J0IGluIHNwb3J0cykKewogICMgUHJpbnQgdGhlIHNwb3J0IG5hbWUKICBwcmludChjdXJyZW50X3Nwb3J0KQogIAogICMgQ29tcHV0ZSB0aGUgbnVtYmVyIG9mIGNoYXJhY3RlcnMgaW4gdGhlIHNwb3J0IG5hbWUKICBwcmludChuY2hhcihjdXJyZW50X3Nwb3J0KSkKfQogIApgYGAKClwKCiMjIExvb3AgZHJpdmVyIGFzIGluZGV4CgpUaHJvdWdob3V0IHRoZSBjb3Vyc2Ugd2UgaGF2ZSBzZWVuIHRoYXQgUiByZWxpZXMgaGVhdmlseSBvbiBtYW5hZ2luZyBkYXRhIGluIG9yZGVyZWQgY29sbGVjdGlvbnMgKHZlY3RvcnMsIGxpc3RzLCBhbmQgZGF0YSBmcmFtZXMpLiBXZSBzZWxlY3QgZWxlbWVudHMgZnJvbSB0aG9zZSBjb2xsZWN0aW9ucyB1c2luZyB0aGUgc2VsZWN0aW9uIG9wZXJhdG9yIGBbXWAsIHByb3ZpZGluZyB0aGUgb3JkaW5hbCBwb3NpdGlvbiBvZiB0aGUgZWxlbWVudCBvZiBpbnRlcmVzdC4gU2luY2UgbG9vcCBkcml2ZXIgdmFyaWFibGVzIHRha2Ugb24gZWFjaCB2YWx1ZSBpbiB0aGVpciBzZXF1ZW5jZSwgd2UgY2FuIHVzZSBhIGZvciBsb29wIHRvIHN0ZXAgdGhyb3VnaCBlYWNoIGVsZW1lbnQgb2YgYSBjb2xsZWN0aW9uIGluIHR1cm4uCgpGb3IgZXhhbXBsZSwgYXNzdW1lIHlvdSBoYXZlIGEgZGF0YSBmcmFtZSBjb250YWluaW5nIG9uZSBzdHVkZW50J3MgaW50ZXJuYWwgYW5kIGV4YW0gbWFya3MgZm9yIHRoZSBwYXBlcnMgdGFrZW4gaW4gb25lIHNlbWVzdGVyOiAKCmBgYHtyIG1ha2UgZGF0YSBmcmFtZX0KcGFwZXJfY29kZXMgPC0gYygiSFVCUzE5MiIsICJFQ09MMjEyIiwgIlNUQVQyNjAiKQppbnRlcm5hbF9tYXJrcyA8LSBjKDg3LCA4NSwgNjIpCmV4YW1fbWFya3MgPC0gYyg5MywgODQsIDg1KQoKbWFya3NfZGYgPC0gZGF0YS5mcmFtZShQYXBlckNvZGUgPSBwYXBlcl9jb2RlcywKICAgICAgICAgICAgICAgICAgICAgICBJbnRlcm5hbE1hcmsgPSBhcy5udW1lcmljKGludGVybmFsX21hcmtzKSwKICAgICAgICAgICAgICAgICAgICAgICBFeGFtTWFyayA9IGFzLm51bWVyaWMoZXhhbV9tYXJrcykpCgptYXJrc19kZgoKYGBgCgpXZSBrbm93IHRoYXQgd2UgY2FuIHNlbGVjdCBhbGwgY29sdW1ucyBmcm9tIGEgc2luZ2xlIHJvdyBpbiB0aGF0IGRhdGEgZnJhbWUgdXNpbmcgdGhlIHN5bnRheCBbKnJvdyBudW1iZXIqLCAgXQoKYGBge3Igc2VsZWN0IHJvd30KIyBTZWxlY3QgYW5kIHByaW50IHJvdyAyCnNlbGVjdGVkX3JvdyA8LSBtYXJrc19kZlsyLCBdCnByaW50KHNlbGVjdGVkX3JvdykKCmBgYAoKV2l0aCBhIGZvciBsb29wLCB3ZSBjYW4gdXNlIHRoZSBsb29wIGRyaXZlciB0byBpdGVyYXRlIG92ZXIgYWxsIHRoZSByb3dzLCBwcm9jZXNzaW5nIGVhY2ggaW4gdHVybjoKCmBgYHtyIHNpbXBsZSBkcml2ZXIgYXMgaW5kZXh9CmZvciAoaW5kZXggaW4gMTozKQp7CiAgIyBVc2UgdGhlIGxvb3AgZHJpdmVyIHRvIHNlbGVjdCBhIHJvdyBmcm9tIHRoZSBkYXRhIGZyYW1lCiAgc2VsZWN0ZWRfcm93IDwtIG1hcmtzX2RmW2luZGV4LCBdCiAgCiAgIyBQcm9jZXNzIHRoZSByb3cgKGp1c3QgcHJpbnRpbmcgaW4gdGhpcyBleGFtcGxlKQogIHByaW50KHNlbGVjdGVkX3JvdykKfQoKYGBgCgpOb3RlIHRoYXQgaWYgd2UgbWFkZSBvdXIgZGF0YSBmcmFtZSBsb25nZXIgdGhhbiB0aHJlZSByb3dzIGJ5IGFkZGluZyBtb3JlIHBhcGVycyB0byBpdCwgdGhlIHByZWNlZGluZyBmb3IgbG9vcCAqKndvdWxkIG5vdCoqIHByaW50IGFsbCB0aGUgcm93czsgdGhlIHNlcXVlbmNlIGluIHRoYXQgZXhhbXBsZSBpcyBhbHdheXMgYDEsIDIsIDNgIHNvIHdlIHNlZSBvbmx5IHJvd3MgMSwgMiwgYW5kIDMuIFdlIGNhbiBtYWtlIHRoZSBsb29wIG1vcmUgZ2VuZXJhbCBieSBkZXRlcm1pbmluZyB0aGUgZm9yIGxvb3Agc2VxdWVuY2UgKipkeW5hbWljYWxseSoqIHVzaW5nIGZ1bmN0aW9uIGBucm93YCwgd2hpY2ggYWNjZXB0cyBhIGRhdGEgZnJhbWUgYXMgYW4gYXJndW1lbnQsIGFuZCByZXR1cm5zIHRoZSBudW1iZXIgb2Ygcm93cyBpbiB0aGUgZGF0YSBmcmFtZToKCmBgYHtyIHVzaW5nIG5yb3d9CiMgRGlzcGxheSBhbGwgcm93cwpmb3IgKGluZGV4IGluIDE6bnJvdyhtYXJrc19kZikpCnsKICAjIFVzZSB0aGUgbG9vcCBkcml2ZXIgdG8gaW5kZXggaW50byB0aGUgZGF0YSBmcmFtZQogIHNlbGVjdGVkX3JvdyA8LSBtYXJrc19kZltpbmRleCwgXQogIHByaW50KHNlbGVjdGVkX3JvdykKfQoKIyBBZGQgYSByb3cgdG8gdGhlIGRhdGEgZnJhbWUKbWFya3NfZGYgPC0gcmJpbmQobWFya3NfZGYsIGRhdGEuZnJhbWUoUGFwZXJDb2RlID0gIlpPT0wzMTYiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSW50ZXJuYWxNYXJrID0gODMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFeGFtTWFyayA9IDkwKSkKCgojIFJlcGVhdCB0aGUgbG9vcCAtLSBzZWUgZm91ciByb3dzCmZvciAoaW5kZXggaW4gMTpucm93KG1hcmtzX2RmKSkKewogICMgVXNlIHRoZSBsb29wIGRyaXZlciB0byBpbmRleCBpbnRvIHRoZSBkYXRhIGZyYW1lCiAgc2VsZWN0ZWRfcm93IDwtIG1hcmtzX2RmW2luZGV4LCBdCiAgcHJpbnQoc2VsZWN0ZWRfcm93KQp9CmBgYAoKXAoKIyBFeGVyY2lzZQoKMS4gV3JpdGUgYSBmb3IgbG9vcCB0aGF0IGl0ZXJhdGVzIG92ZXIgbWFya3NfZGYgcHJpbnRpbmcgKiplYWNoIGNvbHVtbioqIGluIHR1cm4uCjIuIFlvdXIgZmluYWwgbWFyayBpbiBlYWNoIHBhcGVyIGlzIGNvbXB1dGVkIGFzIDQwJSBvZiB5b3VyIGludGVybmFsIG1hcmsgcGx1cyA2MCUgb2YgeW91ciBleGFtIG1hcmsuIFVzaW5nIHRoZSB0ZWNobmlxdWUgb2YgeW91ciBjaG9pY2UsIGFkZCBhIG5ldyBjb2x1bW4gdG8gZGF0YSBmcmFtZSBtYXJrc19kZiB3aGljaCBjb250YWlucyB0aGUgY29tcHV0ZWQgZmluYWwgbWFyayBmb3IgZWFjaCBwYXBlci4KMy4gUnVuIHlvdXIgZm9yIGxvb3AgYWdhaW4gYW5kIGNvbmZpcm0gdGhhdCBpdCBkaXNwbGF5cyAqYWxsKiB0aGUgY29sdW1ucywgaW5jbHVkaW5nIHRoZSBuZXcgb25lLgoKYGBge3IgZXggMSBzb2x1dGlvbn0KIyBEaXNwbGF5IGFsbCBjb2x1bW5zCmZvciAoaW5kZXggaW4gMTpuY29sKG1hcmtzX2RmKSkKewogICMgVXNlIHRoZSBsb29wIGRyaXZlciB0byBpbmRleCBpbnRvIHRoZSBkYXRhIGZyYW1lCiAgc2VsZWN0ZWRfY29sIDwtIG1hcmtzX2RmWyAsIGluZGV4XQogIHByaW50KHNlbGVjdGVkX2NvbCkKfQoKCiMgQWRkIGEgbmV3IGNvbHVtbgptYXJrc19kZiRUb3RhbE1hcmsgPC0gKDAuNDAgKiBtYXJrc19kZiRJbnRlcm5hbE1hcmspICsgKDAuNjAgKiBtYXJrc19kZiRFeGFtTWFyaykgCgoKIyBDb25maXJtIHRoYXQgd2UgZGlzcGxheSBhbGwgZm91ciBjb2x1bW5zCmZvciAoaW5kZXggaW4gMTpuY29sKG1hcmtzX2RmKSkKewogICMgVXNlIHRoZSBsb29wIGRyaXZlciB0byBpbmRleCBpbnRvIHRoZSBkYXRhIGZyYW1lCiAgc2VsZWN0ZWRfY29sIDwtIG1hcmtzX2RmWyAsIGluZGV4XQogIHByaW50KHNlbGVjdGVkX2NvbCkKfQpgYGAKClwKCiMgTmVzdGVkIGZvciBsb29wcwoKSW4gdGhlIHByZWNlZGluZyBleGFtcGxlcywgd2UgaGF2ZSBpdGVyYXRlZCBvdmVyIGEgZGF0YSBmcmFtZSBwcm9jZXNzaW5nIGNvbXBsZXRlIHJvd3MsIG9yIGNvbXBsZXRlIGNvbHVtbnMuIEZyZXF1ZW50bHksIGl0IGlzIG5lY2Vzc2FyeSB0byBpdGVyYXRlIG92ZXIgYSBkYXRhIGZyYW1lIChvciBtYXRyaXgpIHByb2Nlc3NpbmcgZWFjaCAqaW5kaXZpZHVhbCBjZWxsKiBpbiB0dXJuLiBUaGF0IGlzLCBpbnN0ZWFkIG9mIHVzaW5nIHRoZSBgWywgY29sXWAgb3IgYFtyb3csIF1gIGZvcm1zIG9mIHNlbGVjdGlvbiwgd2UgbmVlZCB0byBzcGVjaWZ5IGJvdGggYSByb3cgaW5kZXggYW5kIGEgY29sdW1uIGluZGV4IChpLmUuIGBbcm93LCBjb2xdYCkuIFRoaXMgaXMgdmVyeSBjb21tb24gcHJvY2Vzc2luZyB0ZWNobmlxdWUgaW4gc2ltdWxhdGlvbiwgY29tcHV0ZXIgZ3JhcGhpY3MsIGFydGlmaWNpYWwgaW50ZWxsaWdlbmNlLCBhbmQgY29tcHV0YXRpb25hbCBwcm9ibGVtcyByZXF1aXJpbmcgbWF0cml4IGFsZ2VicmEuCgpXZSBpdGVyYXRlIG92ZXIgdGFidWxhciBkYXRlIGluIGFuIG9yZGVybHkgZmFzaGlvbi4gRm9yIGV4YW1wbGUsIGlmIHdlIGhhdmUgYSAzeDMgbWF0cml4IG9yIGRhdGEgZnJhbWUgd2Ugd291bGQgcHJvY2VzcyB0aGUgY2VsbHMgaW4gdGhlIGZpcnN0IHJvdyBmcm9tIGxlZnQgdG8gcmlnaHQgKFsxLDFdLCBbMSwyXSwgWzEsM10pLCB0aGVuIHRoZSBjZWxscyBpbiB0aGUgc2Vjb25kIHJvdyAoWzIsMV0sIFsyLDJdLCBbMiwzXSksIGFuZCBmaW5hbGx5IHRoZSBjZWxscyBpbiB0aGUgdGhpcmQgcm93IChbMywxXSwgWzMsMV0sIFszLDNdKS4gWW91IGNhbiB2aWV3IHRoaXMgcGF0dGVybiBhcyB1c2luZyAqKnR3byBsb29wIGRyaXZlcnMqKiwgb25lIGZvciB0aGUgcm93IGluZGV4IGFuZCBvbmUgZm9yIHRoZSBjb2x1bW4gaW5kZXguIFdoaWxlIHRoZSByb3cgZHJpdmVyIGlzIDEsIHdlIHdhbnQgdGhlIGNvbHVtbiBkcml2ZXIgdG8gbG9vcCB0aHJvdWdoIHZhbHVlcyAxLCAyLCBhbmQgMy4gVGhlbiwgd2Ugd2FudCB0aGUgcm93IGRyaXZlciB0byB0YWtlIG9uIDIsIGFuZCBhZ2FpbiB3YW50IHRoZSBjb2x1bW4gZHJpdmVyIHRvIGxvb3AgdGhyb3VnaCAxLCAyLCBhbmQgMy4gRmluYWxseSB3ZSB3YW50IHRoZSByb3cgZHJpdmVyIHRvIGJlIDMsIGFuZCB0aGUgY29sdW1uIGRyaXZlciB0byBsb29wIGFnYWluLiBXZSBjYW4gYWNoaWV2ZSB0aGlzIGJ5ICoqbmVzdGluZyoqIGEgZm9yIGxvb3AgZm9yIGNvbHVtbnMgKippbnNpZGUqKiBhIGZvciBsb29wIGZvciByb3dzLCBhcyBzaG93biBiZWxvdy4gTm90ZSB0aGF0IGVhY2ggZm9yIGxvb3AgaGFzIGl0cyBvd24gbG9vcCBkcml2ZXIsIGl0cyBvd24gc2VxdWVuY2UgYW5kIGl0cyBvd24gcm91bmQgYW5kIGN1cmx5IGJyYWNrZXRzLiBUaGUgc3R5bGUgb2YgaW5kZW50aW5nIHRoZSAqKmlubmVyIGZvciBsb29wKiogaXMgaW1wb3J0YW50IGZvciBtYWludGFpbmluZyBjb2RlIHJlYWRhYmlsaXR5LgoKYGBge3IgbmVzdGVkIGZvciByb3ctd2lzZX0KIyBPdXRlciBsb29wLgpmb3IgKHJvd19pbmRleCBpbiAxOm5yb3cobWFya3NfZGYpKQp7CiAgIyBJbm5lciBsb29wIC0tIG1ha2VzIGFsbCBpdGVyYXRpb25zIGZvciBlYWNoIHBhc3MgdGhyb3VnaCBvdXRlciBsb29wCiAgZm9yIChjb2xfaW5kZXggaW4gMTpuY29sKG1hcmtzX2RmKSkKICB7CiAgICAjIFVzZSBib3RoIGxvb3AgZHJpdmVycyB0byBzZWxlY3QKICAgIGNlbGxfdmFsdWUgPC0gbWFya3NfZGZbcm93X2luZGV4LCBjb2xfaW5kZXhdCiAgICBwcmludChjZWxsX3ZhbHVlKQogIH0KfQpgYGAKClwKCiMjIEV4ZXJjaXNlClRoZSBwcmVjZWRpbmcgZXhhbXBsZSBwcmludHMgKnJvdy13aXNlKi4gVGhhdCBpcywgaXQgcHJpbnRzIGFsbCB0aGUgdmFsdWVzIGZvciBlYWNoIHJvdyAoaS5lLiBmb3IgYSBzaW5nbGUgcGFwZXIpIGJlZm9yZSBtb3ZpbmcgdG8gdGhlIG5leHQgcm93IChwYXBlcikuIE1vZGlmeSB0aGUgY29kZSB0byBwcmludCAqY29sdW1uLXdpc2UqLiBUaGF0IGlzLCBwcmludCBkb3duIHRoZSBjb2x1bW5zOiBhbGwgdGhlIHBhcGVyIG5hbWVzLCB0aGVuIGFsbCB0aGUgaW50ZXJuYWwgbWFya3MsIHRoZW4gYWxsIHRoZSBleGFtIG1hcmtzLCB0aGVuIGFsbCB0aGUgZmluYWwgbWFya3MuCgpgYGB7ciBuZXN0ZWQgZm9yIGNvbC13aXNlfQojIE91dGVyIGxvb3AuCmZvciAoY29sX2luZGV4IGluIDE6bmNvbChtYXJrc19kZikpCnsKICAjIElubmVyIGxvb3AgLS0gbWFrZXMgYWxsIGl0ZXJhdGlvbnMgZm9yIGVhY2ggcGFzcyB0aHJvdWdoIG91dGVyIGxvb3AKICBmb3IgKHJvd19pbmRleCBpbiAxOm5yb3cobWFya3NfZGYpKQogIHsKICAgICMgVXNlIGJvdGggbG9vcCBkcml2ZXJzIHRvIHNlbGVjdAogICAgY2VsbF92YWx1ZSA8LSBtYXJrc19kZltyb3dfaW5kZXgsIGNvbF9pbmRleF0KICAgIHByaW50KGNlbGxfdmFsdWUpCiAgfQp9CmBgYAoKXAoKIyMjIENBVVRJT04KClVzaW5nIGEgbmVzdGVkIGZvciBsb29wIHRvIHZpc2l0IGV2ZXJ5IGNlbGwgaW4gYSB0YWJsZSBpcyBhIHZlcnkgY29tbW9uLCBhbmQgdmVyeSBwb3dlcmZ1bCBjb2RlIHBhdHRlcm4uIEhvd2V2ZXIsIGJlIGF3YXJlIHRoYXQgaXQgY2FuIGJlIGNvbXB1dGF0aW9uYWxseSBleHBlbnNpdmUgKGkuZS4gaXQgY2FuIHRha2UgYSBsb25nIHRpbWUgdG8gcnVuKS4gSWYgeW91ciBvdXRlciBsb29wIHJ1bnMgYG5gIHBhc3NlcyBhbmQgeW91ciBpbm5lciBsb29wIHJ1bnMgYG1gIHBhc3NlcywgeW91IG1ha2UgYSB0b3RhbCBvZiBgbiAqIG1gIHBhc3Nlcy4gV2hlbiBwcm9jZXNzaW5nIGEgMTAwMCByb3cgeCAxMDAwIGNvbHVtbiB0YWJsZSB3aXRoIGEgbmVzdGVkIGZvciBsb29wLCB0aGUgY29kZSBib2R5IG9mIHRoZSBpbm5lciBsb29wIGlzIGV4ZWN1dGVkIG9uZSBtaWxsaW9uIHRpbWVzLCB3aGljaCBtYXkgYmUgaW50cmFjdGFibGUuIElmIHlvdSBoYXZlIGxhcmdlIHRhYnVsYXIgZGF0YSBzZXRzIHRoYXQgdGFrZSBhIGxvbmcgdGltZSB0byBwcm9jZXNzLCB5b3Ugc2hvdWxkIGNvbnNpZGVyIGxldmVyYWdpbmcgUidzIGFkdmFuY2VkIHZlY3RvciBwcm9jZXNzaW5nIHRlY2huaXF1ZXMgdGhhdCBjYW4gYmUgbW9yZSBlZmZpY2llbnQgdGhhbiBhbiBpbnRlcmlvciBmb3IgbG9vcC4gU2VlLCBmb3IgZXhhbXBsZSwgaHR0cHM6Ly9yc3R1ZGlvLXB1YnMtc3RhdGljLnMzLmFtYXpvbmF3cy5jb20vNzIyOTVfNjkyNzM3YjY2NzYxNGQzNjliZDg3Y2IwZjUxYzlhNGIuaHRtbCBvciBodHRwOi8vd3d3LmpvaG4tcm9zLmNvbS9SY291cnNlL21lbW9yeS5odG1sIGZvciBkaXNjdXNzaW9ucy4KCiMgV2hpbGUgbG9vcAoKVGhlICoqZm9yIGxvb3AqKiBpcyB1c2VkIHdoZW4geW91IHdhbnQgdG8gZXhlY3V0ZSBhIGNvZGUgYm9keSBhIHNwZWNpZmljIG51bWJlciBvZiB0aW1lcywgb3IgaXRlcmF0ZSBvdmVyIGEgc3BlY2lmaWMgc2VxdWVuY2Ugb2YgdmFsdWVzLiBBbiBhbHRlcm5hdGl2ZSBsb29wIHN0cnVjdHVyZSAtLSB0aGUgKip3aGlsZSBsb29wKiogcmVwZWF0cyBhcyBsb25nIGFzIGEgZ2l2ZW4gY29uZGl0aW9uIGV2YWx1YXRlcyB0byB0cnVlLgoKVGhlIHNjaGVtYXRpYyBmb3IgYSBgd2hpbGVgIGxvb3AgaXMgYXMgZm9sbG93czoKCmBgYHtyLCBldmFsID0gRkFMU0V9CndoaWxlIChjb25kaXRpb24pIAp7CiAgIyBMb29wIGJvZHkKfQpgYGAKCkluIGFuIGVhcmxpZXIgbW9kdWxlLCB3ZSB1c2VkIGZ1bmN0aW9uIGBybm9ybWAgdG8gcmFuZG9tbHkgc2VsZWN0IGEgdmFsdWUgZnJvbSBhIG5vcm1hbCBkaXN0cmlidXRpb24gd2l0aCBhIGtub3duIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbi4gSW1hZ2luZSB0aGF0IHlvdSB3YW50IHRvIGV4cGxvcmUgdGhlIHByb2JhYmlsaXR5IG9mIHJhbmRvbWx5IHNlbGVjdGluZyBhIG51bWJlciBmcm9tIHN1Y2ggYSBkaXN0cmlidXRpb24gdGhhdCBpcyBtb3JlIHRoYW4gdHdvIHN0YW5kYXJkIGRldmlhdGlvbnMgYWJvdmUgdGhlIG1lYW4gKGkuZS4gaGFzIGEgei1zY29yZSBvZiAyIG9yIG1vcmUpLiBZb3UgY291bGQgZXN0aW1hdGUgdGhpcyBieSByZXBlYXRlZGx5IHNlbGVjdGluZyBhIG51bWJlciB1bnRpbCB5b3UgYWNoaWV2ZWQgdGhlIGNyaXRlcmlvbiwgYW5kIGNvdW50aW5nIHRoZSBudW1iZXIgb2YgdGltZXMgeW91IGhhZCB0byBzZWxlY3QuIFdlIHdpc2ggdG8gbG9vcCByZXBlYXRlZGx5IG92ZXIgc29tZSBsb2dpYyAoc2VsZWN0aW5nIGFuZCBjb3VudGluZyksIGJ1dCB3ZSBkb24ndCBrbm93IGV4YWN0bHkgaG93IG1hbnkgdGltZXMgdGhlIGxvb3Agc2hvdWxkIHJ1biwgc28gYSBmb3IgbG9vcCBpcyBub3QgYXBwcm9wcmlhdGUuIEluIHRoaXMgc2l0dWF0aW9uLCB3ZSB1c2UgYSAqKndoaWxlIGxvb3AqKi4KCioqQmVmb3JlIGxvb2tpbmcgYXQgdGhlIGNvZGUgc2FtcGxlIGJlbG93LCB0cnkgdG8gd29yayBvdXQgd2hhdCB0aGUgd2hpbGUgbG9vcCBjb25kaXRpb24gd2lsbCBiZS4qKgoKCmBgYHtyIHdoaWxlIGxvb29wIHdpdGggcm5vcm19CiMgRGVmaW5lIHRoZSBwYXJhbWV0ZXJzCmRpc3RyaWJ1dGlvbl9tZWFuIDwtIDEwMApkaXN0cmlidXRpb25fc2QgPC0gMTAKCiMgUHJlcGFyZSBhIHZhcmlhYmxlIHRvIGNvdW50IHRoZSBwYXNzZXMKY291bnQgPC0gMAoKIyBNYWtlIHlvdXIgZmlyc3Qgc2VsZWN0aW9uIHNvIHRoZSBsb29wIGNvbmRpdGlvbiB0byBiZSBldmFsdWF0ZWQgCiMgb24gdGhlIGZpcnN0IHBhc3MKcmFuZF92YWx1ZSA8LSBybm9ybSgxLCBkaXN0cmlidXRpb25fbWVhbiwgZGlzdHJpYnV0aW9uX3NkKQoKIyBUaGUgbG9vcC4gTm90ZSB0aGUgY29uZGl0aW9uLiBXZSBjb250aW51ZSBydW5uaW5nIHRoZSBsb29wCiMgYXMgbG9uZyBhcyBvdXIgc2VsZWN0ZWQgdmFsdWUgaXMgbGVzcyB0aGFuIG1lYW4gKyAyKnNkLgojIFdoaWxlIGxvb3BzIHJ1biBhcyBsb25nIGFzIHRoZSBsb29wIGNvbmRpdGlvbiBpcyB0cnVlLgp3aGlsZSAocmFuZF92YWx1ZSA8IGRpc3RyaWJ1dGlvbl9tZWFuICsgKDIgKiBkaXN0cmlidXRpb25fc2QpKQp7CiAgIyBpbmNyZW1lbnQgdGhlIGNvdW50IGJlY2F1c2UgdGhlIGxvb3AgY29uZGl0aW9uIHdhcyB0cnVlCiAgY291bnQgPC0gY291bnQgKyAxCiAgCiAgIyBTZWxlY3QgYWdhaW4KICByYW5kX3ZhbHVlIDwtIHJub3JtKDEsIGRpc3RyaWJ1dGlvbl9tZWFuLCBkaXN0cmlidXRpb25fc2QpCiAgCn0gIyBlbmQgb2Ygd2hpbGUgbG9vcAoKIyBEaXNwbGF5IHRoZSByZXN1bHQKb3V0cHV0IDwtIHBhc3RlKGNvdW50LCAidmFsdWVzIHdlcmUgY2hvc2VuIGJlZm9yZSB6LXNjb3JlID4gMSIpCnByaW50KG91dHB1dCkKCmBgYAoKSGVyZSBpcyBhbiBleGFtcGxlIG9mIGEgYHdoaWxlYCBsb29wIHRvIGNvdW50IGhvdyBtYW55IGl0ZXJhdGlvbnMgaXQgdGFrZXMgdG8gb2J0YWluIDMgaGVhZHMgaW4gYSByb3c6CgpgYGB7ciwgZWNobyA9IFRSVUUsIGV2YWwgPSBUUlVFfQojIyBFeGFtcGxlIGZyb20gUiBmb3IgRGF0YSBTY2llbmNlIC0gMjEuMy40ICMjCgojIEZ1bmN0aW9uIHRvIHNpbXVsYXRlIGhlYWQgb3IgdGFpbCBhcyB0aGUgcmVzdWx0IG9mIGEgY29pbiBmbGlwCmZsaXAgPC0gZnVuY3Rpb24oKXsKICBzYW1wbGUoYygiVCIsICJIIiksIDEpCn0KCiMgdmFyaWFibGVzIHRvIGtlZXAgdHJhY2sgb2Yga2V5IHJlc3VsdHMKZmxpcHMgPC0gMApuaGVhZHMgPC0gMAoKIyBmbGlwIGEgY29pbiB1bnRpbCB0aGVyZSBhcmUgdGhyZWUgaGVhZHMgYW5kIGNvdW50IGhvdyBtYW55IGZsaXBzIHdlcmUgcGVyZm9ybWVkLgp3aGlsZSAobmhlYWRzIDwgMykgewogIGlmIChmbGlwKCkgPT0gIkgiKSB7CiAgICBuaGVhZHMgPC0gbmhlYWRzICsgMQogIH0gZWxzZSB7CiAgICBuaGVhZHMgPC0gMAogIH0KICBmbGlwcyA8LSBmbGlwcyArIDEKfQpmbGlwcwoKYGBgCgpcCgojIyBJbmZpbml0ZSB3aGlsZSBsb29wcwoKTkI6IEl0IGlzIGVzc2VudGlhbCB0aGF0IHlvdXIgd2hpbGUgbG9vcCBjb25kaXRpb24gd2lsbCAqKmV2ZW50dWFsbHkgZXZhbHVhdGUgdG8gZmFsc2UqKi4gQ29uc2lkZXIgdGhlIGZvbGxvd2luZyBjb2RlIHNhbXBsZSAod2hpY2ggd2Ugd2lsbCAqbm90KiBydW4pLgoKYGBge3IgaW5maW5pdGUgbG9vcCwgZXZhbCA9IEZBTFNFfQojIFNldCBhIHN0YXJ0aW5nIHZhbHVlIHNvIHdlIGNhbiBjaGVjayB0aGUgY29uZGl0aW9uIG9uIHRoZSBmaXJzdCBwYXNzCnggPC0gMTAKCiMgVGhlIGxvb3AKd2hpbGUgKHggPiAwKQp7CiAgIyBUaGUgY29kZSBib2R5CiAgeCA8LSB4ICsgMQp9CgpgYGAKClRoZSB2YXJpYWJsZSB4IGlzIGluaXRpYWxpc2VkIHRvIDEwLCBhbmQgaW5jcmVtZW50ZWQgYXQgZWFjaCBwYXNzIHRocm91Z2ggdGhlIGNvZGUgYm9keS4gSXRzIHZhbHVlIHdpbGwgdGhlcmVmb3JlIGFsd2F5cyBiZSBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gMTAuIFRoZSBsb29wIGNvbmRpdGlvbiBpcyBgeCA+IDBgLiBTaW5jZSB4IHN0YXJ0cyBhdCAxMCBhbmQgaW5jcmVhc2VzIGF0IGVhY2ggcGFzcywgaXQgd2lsbCBhbHdheXMgYmUgZ3JlYXRlciB0aGFuIDAsIHNvIHRoZSBsb29wIGNvbmRpdGlvbiB3aWxsIGFsd2F5cyBiZSB0cnVlLCBhbmQgdGhlIGxvb3Agd2lsbCBuZXZlciBzdG9wLiBUaGlzIGlzIGFuICoqaW5maW5pdGUgbG9vcCoqLiBXaGVuIHlvdXIgY29kZSBpcyBpbiBhbiBpbmZpbml0ZSBsb29wLCB0aGUgb25seSB3YXkgdG8gc3RvcCBpdCBpcyB0byBmb3JjaWJseSB0ZXJtaW5hdGUgdGhlIHByb2dyYW0gKGFzc3VtaW5nIHlvdSByZWNvZ25pc2Ugd2hhdCBoYXMgb2NjdXJyZWQpLiBJbiBSIHlvdSBjYW4gdXN1YWxseSBkbyB0aGlzIGJ5IGNsaWNraW5nIHRoZSByZWQgc3RvcCBzaWduIGluIHRoZSB0b3AgcmlnaHQgY29ybmVyIG9mIHRoZSBjb25zb2xlIHdpbmRvdy4gQW4gaW5maW5pdGUgbG9vcCB0aGF0IHByb2R1Y2VzIGEgbG90IG9mIHZhcmlhYmxlcyBjYW4gY29uc3VtZSBtZW1vcnkgdG8gdGhlIHBvaW50IHdoZXJlIHRoZSBtYWNoaW5lIHdpbGwgY3Jhc2guIFRoaXMgaXMgYmFkLiBBbHdheXMgY2hlY2sgdGhhdCB5b3VyIGxvb3AgY29uZGl0aW9uIGlzIGd1YXJhbnRlZWQgdG8gZXZlbnR1YWxseSBldmFsdWF0ZSB0byBmYWxzZSBiZWZvcmUgcnVubmluZyBjb2RlIHdpdGggYSB3aGlsZSBsb29wLgoKIyBNYXAKCkluIHRoZSBwYWNrYWdlIGBwdXJycmAgKHBhcnQgb2YgcGFja2FnZSB0aWR5dmVyc2UpLCB0aGVyZSBhcmUgYSBjb2xsZWN0aW9uIG9mIGBtYXBgIGZ1bmN0aW9ucyB3aGljaCBpdGVyYXRlIG92ZXIgYSB2ZWN0b3Igb3IgbGlzdCwgYXBwbHlpbmcgYSBmdW5jdGlvbiB0byBlYWNoIGVsZW1lbnQuIFRoaXMgaXMgYSB2ZXJ5IHN1Y2NpbmN0IHN5bnRheCwgd2hpY2ggYWNoaWV2ZXMgdGhlIHNhbWUgcmVzdWx0IGFzIGNhbGxpbmcgdGhlIGZ1bmN0aW9uIGluc2lkZSBhIGZvciBsb29wLCB3aXRob3V0IHRoZSBvdmVyaGVhZCBvZiB3cml0aW5nIG91dCB0aGUgbG9vcCBzdHJ1Y3R1cmUuCgpgYGB7ciBzaW1wbGUgbWFwfQpsaWJyYXJ5KHB1cnJyKQoKZmFyZW5oZWl0X3RvX2NlbGNpdXMgPC0gZnVuY3Rpb24odGVtcF9mKXsKICB0ZW1wX2MgPC0gKHRlbXBfZiAtIDMyKSAqIDUvOQogIHJldHVybih0ZW1wX2MpCn0KCm15X3RlbXBzX2YgPC0gYyg5MCwgNzgsIDg4LCA4OSwgNzcpCgojIG1hcCBhcHBsaWVzIHRoZSBmdW5jdGlvbiAoMm5kIGFyZ3VtZW50KSB0byBlYWNoIGVsZW1lbnQgb2YgdGhlIHZlY3RvciAoMXN0IGFyZ3VtZW50KSAKIyBhbmQgcmV0dXJucyB0aGUgcmVzdWx0cyBhcyBhIGxpc3QuIApteV90ZW1wc19jX2xpc3QgPC0gbWFwKG15X3RlbXBzX2YsIGZhcmVuaGVpdF90b19jZWxjaXVzKQpteV90ZW1wc19jX2xpc3QKCmBgYAoKVGhlIGBtYXBgIGFyZ3VtZW50IG5hbWVzIGFyZSBgLnhgIGFuZCBgLmZgLCBzbyB0aGUgY2FsbCB0byBgbWFwYCBhYm92ZSBjb3VsZCBhbHNvIGJlIHdyaXR0ZW4gYXMgYG15X3RlbXBzX2NfbGlzdCA8LSBtYXAoLnggPSBteV90ZW1wc19mLCAuZiA9IGZhcmVuaGVpdF90b19jZWxjaXVzKWAKCk5vdGUgdGhhdCB3aGVuIHByb3ZpZGluZyBhIGZ1bmN0aW9uIGFzIGFuIGFyZ3VtZW50LCBnaXZlICoqb25seSB0aGUgZnVuY3Rpb24gbmFtZSoqLiBEbyBub3QgZm9sbG93IHRoZSBmdW5jdGlvbiBuYW1lIHdpdGggKCkgYXMgZm9yIGEgZnVuY3Rpb24gY2FsbC4KCgojIyBNYXAgYW5kIGZyaWVuZHMKClRoZSBiYXNpYyBmb3JtIG9mIGBtYXBgIGFib3ZlLCByZXR1cm5zIHRoZSByZXN1bHRzIGluIGEgbGlzdC4gVGhlcmUgYXJlIHN1ZmZpeCB2ZXJzaW9ucyBvZiBgbWFwYCB0aGF0IHJldHVybiB0aGUgcmVzdWx0cyBhcyBhIHNwZWNpZmljIGRhdGEgdHlwZS4KCi0gYG1hcCgpYCBtYWtlcyBhIGxpc3QuCi0gYG1hcF9sZ2woKWAgbWFrZXMgYSBsb2dpY2FsIHZlY3Rvci4KLSBgbWFwX2ludCgpYCBtYWtlcyBhbiBpbnRlZ2VyIHZlY3Rvci4KLSBgbWFwX2RibCgpYCBtYWtlcyBhIGRvdWJsZSB2ZWN0b3IuCi0gYG1hcF9jaHIoKWAgbWFrZXMgYSBjaGFyYWN0ZXIgdmVjdG9yLgoKVGhlc2Ugc3VmZml4IHZlcnNpb25zIHdpbGwgZ2l2ZSBhbiBlcnJvciBpZiB0aGUgZGF0YSB0eXBlIG9mIHRoZSByZXN1bHRzIGRvZXNuJ3QgbWF0Y2ggdGhlIGludGVuZGVkIHJldHVybiB0eXBlLiBUaGlzIGlzIHVzZWZ1bCBiZWNhdXNlIHlvdSBjYW4gd3JpdGUgY29kZSB0byBwcm9jZXNzIHRoZSByZXN1bHRzIGZ1cnRoZXIsIGNvbmZpZGVudCB0aGF0IHRoZXkgYXJlIG9mIGEgc3BlY2lmaWMgZGF0YSB0eXBlLiAKCiMgQXBwbHkKCkJhc2UgUiBoYXMgYSBzZXQgb2YgYnVpbHQgaW4gZnVuY3Rpb25zIHRoYXQgZHVwbGljYXRlIHRoZSBiZWhhdmlvdXIgb2YgYHB1cnJyOjptYXBgIGFuZCBpdHMgc3VmZml4IGZ1bmN0aW9ucy4gVGhlc2UgYXJlIHRoZSAqKmFwcGx5IGZhbWlseSoqOiBgYXBwbHlgLCBgbGFwcGx5YCwgYHNhcHBseWAsIGBtYXBwbHlgLCBhbmQgYHRhcHBseWAuIFRoZSBmdW5jdGlvbnMgZGlmZmVyIHByaW1hcmlseSBpbiB0aGUgc3RydWN0dXJlIG9mIHRoZSBkYXRhIHRoZXkgcmV0dXJuLiBTZWUsIGZvciBleGFtcGxlLCBodHRwOi8vYWR2LXIuaGFkLmNvLm56L0Z1bmN0aW9uYWxzLmh0bWwgZm9yIG1vcmUgZGV0YWlsLgoKRnVuY3Rpb24gYGxhcHBseWAgaXMgYW5hbG9nb3VzIHRvIGBwdXJycjo6bWFwKClgOgoKYGBge3J9CmZhcmVuaGVpdF90b19jZWxjaXVzIDwtIGZ1bmN0aW9uKHRlbXBfZil7CiAgdGVtcF9jIDwtICh0ZW1wX2YgLTMyKSAqIDUvOQogIHJldHVybih0ZW1wX2MpCn0KCm15X3RlbXBzX2YgPC0gYyg5MCwgNzgsIDg4LCA4OSwgNzcpCgojIGxhcHBseSBleGFtcGxlCmxhcHBseV9teV90ZW1wc19jIDwtIGxhcHBseShYID0gbXlfdGVtcHNfZiwgRlVOID0gZmFyZW5oZWl0X3RvX2NlbGNpdXMpCmxhcHBseV9teV90ZW1wc19jCgpgYGAKCk5vdGUgdGhhdCBzb21lIG9mIHRoZSBhcHBseSBmYW1pbHkgcmV0dXJuIGRpZmZlcmVudCBkYXRhIHN0cnVjdHVyZXMgZGVwZW5kaW5nIG9uIHRoZSB0eXBlIG9mIHRoZSBpbnB1dCBkYXRhLiBUaGlzIGNhbiBtYWtlIGl0IGNoYWxsZW5naW5nIHRvIGtub3cgYmVmb3JlaGFuZCB3aGF0IHRoZSBvdXRwdXQgaXMgZ29pbmcgdG8gbG9vayBsaWtlIC0gdW5saWtlIHRoZSBzdWZmaXggdmVyc2lvbnMgb2YgYHB1cnJyOjptYXBgCgojIENvbmNsdXNpb24KCkluIHRoaXMgbW9kdWxlIHdlIGNvdmVyZWQgdXNpbmcgZm9yIGFuZCB3aGlsZSBsb29wcyB0byByZXBlYXQgY29kZSBmcmFnbWVudHMgZWZmaWNpZW50bHkuIFdlIHNhdyB0aGF0IGZ1bmN0aW9ucyBpbiB0aGUgbWFwIGFuZCBhcHBseSBmYW1pbGllcyBwcm92aWRlIGFuIGVxdWl2YWxlbnQsIHlldCBtb3JlIHN1Y2NpbmN0IHN5bnRheCwgd2hlbiB0aGUgcmVwZWF0ZWQgY29kZSBpcyBhIHNpbmdsZSBmdW5jdGlvbi4gQ29tYmluaW5nIGxvb3BzIHdpdGggZnVuY3Rpb25zIGFuZCBjb25kaXRpb25hbCBmbG93IG9mIGNvbnRyb2wgZnJvbSBsYXN0IHdlZWsncyBzZXNzaW9uLCB5b3UgY2FuIGNyZWF0ZSBjb2RlIHRoYXQgaXMgbW9kdWxhciwgcmV1c2FibGUsIGFuZCBtYWludGFpbmFibGUuIAoKIyBXaGF0J3MgTmV4dApOZXh0IHdlZWsgd2UgY29uY2x1ZGUgdGhlIGZvcm1hbCBjb250ZW50IG9mIFI0U1NQIHdpdGggYSBkaXNjdXNzaW9uIG9mIFIgd29ya2Zsb3dzLCBpbmNsdWRpbmcgcHJvamVjdCBzdHJ1Y3R1cmUsIGluY3JlbWVudGFsIGRldmVsb3BtZW50LCBhbmQgZWZmZWN0aXZlIGRlYnVnZ2luZyB0ZWNobmlxdWVzLgoKCgogCg==