Hello! Welcome to the first of the advanced R workshops on the LIFE4138 module. Our learning objectives for this session are:

What do we mean by “advanced”?

So, the previous sessions have all been designed to give you an overall grounding of the way that R works, and to try and understand the different approaches that R users take to the language (baseR versus the tidyverse approach for e.g.). For most R users, this is enough to get by. You’ll be able to do the majority of the stuff that you need to using only the skills that we’ve been through so far.

That being said, there are times, particularly when undertaking bioinformatic analysis, when perhaps you might like to have a script that will run independently without your input. Situations such as this really highlight the importance of the advanced techniques that we’re about to learn!

Taking it to the next step

The below will begin to give you a greater flexibilty and versatility with your R coding, and allow you to begin to make R work for you in exactly the way that you want it to. for loops for example are a great principle to learn in general with your code, and learning both the loops themselves as well as the alternatives available in R will be incredibly useful to you.

Another nice thing about moving on to more advanced coding principles in R is that they will help to deepen your understanding of how the basics work. For example, the way that we handle and access vectors will become clearer as we use more advanced techniques to work through them.

But how do I become an “advanced” R user?!

The above abilities and ideas will open up your coding abilities, and allow you to really get to grips with R as both a language and a tool for data wrangling, plotting, and downstream analysis.

Finally, the importance of your coding environment (I mean physical environment, not your R environment) cannot be understated. Find a way to get “in the zone”, and allow yourself to concentrate solely on what it is that you’re trying to achieve. Focus is important with code, it’s so easy to make mistakes and end up with analyses that hasn’t done what you think it has. For me, I make a giant cup of tea, grab some biscuits, get comfy with a warm jumper, and pop my headphones on. I listen to a playlist that I have personally curated for a mixture of concentration, positivity, and motivation. It sounds daft, but I promise, it works. If I really don’t want to be disturbed, I shut my office door, cover the window in the door, and turn the lights off (and put my lamp on - I’m aiming for ambient lighting rather than pitch black!).

I know I just said finally, but actually properly finally, don’t forget to take a break. If you’re tearing your hair out to debug a piece of code, or if you’re really stuck and just can’t make something work, put it down. Walk away, make yourself a cup of tea, have some cake, go for a run, do whatever you need to for some mental space. Even sleep on it if you have to. When you come back to it, often the answer will present itself. If it doesn’t everything will at least feel a little easier than it did before. Coding can be frustrating, but learning to manage and harness that frustration is a real skill!

Right. Let’s get to the meat of it.

Control flow

The first concept that we’ll cover today is control flow. You may well have come across control flow in your forrays with Python and Unix, and the basic idea of how it works is largely similar in R. Control flow is a fundemental part of the way that any programming language works, not just R. It essentially provides a way to control the order that a set of functions are performed on your dataset.

There are several examples of control flow functions, but the ones we will concentrate on today are for loops, if and else statements, and the ifelse() function. ifelse() isn’t strictly a control flow statement, but a function from the baseR set of functions.

Before we get started, the way that control flows work are as follows. Say, for example, you have a condition. You ask whether that condition is true or false. If the condition is true, you perform a function.

If it is false, you perform another function. This is easier to understand with an analogy. We can use if else statements to write a function to make ourselves a cup of tea. First, we perform the boil kettle function. Then, we periodically check to see if the water has boiled. If the outcome of “Has the water boiled” is FALSE, we perform the wait a bit longer function. We check again. If the outcome is TRUE, we perform the pour water function, which then allows us to perform the drink tea function. Admittedly, this analogy is flawed - it’s missing some vital steps including adding a tea bag, adding any milk, waiting for the tea to cool, and cutting yourself a slice of cake! That being said, it demonstrates the basic concept of control flow nicely.

A note on brackets

Before we go any further, you may have noticed that we often use different types of brackets for various purposes in R. This is vitally important to the language, and your code will not function in the way that you expect it to if you get this wrong.

() - rounded brackets are used exclusively to perform functions, or denote the order of mathematical calculations [] - square brackets are used for indexing and subsetting {} - curly brackets are used to define blocks of code in functions and statements. What I mean by this will become increasingly apparent as we work through the below.

For loops

Despite if else statements being perhaps easier to wrap our heads around, we’re going to start with for loops. Essentially, a for loop is a way of iterating through a set of values, performing a function on each in turn. These loops are relatively straightforward and intuitive in R, once you get used to using them.

The syntax is, of course, slightly different to Python, but the basic concept is the same. Typically, for loops in R are a little slow. There’s a much quicker way of performing these functions, but we wont go into that here - it’s important to understand how the loops work first.

Let’s try one. We want to create a basic for loop which will print all of the numbers from 1 to 10. We could of course do this without a loop, by assigning an individual value to x, and printing them in turn:

x <- 1
print(x)
[1] 1
x <- 2
print(x)
[1] 2
x <- 3
print(x)
[1] 3

What if we wanted to automate this? Let’s build that basic for loop…

for (x in 1:10){
  print(x)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10

Brilliant, but let’s go through just how that works.

  • for - we start with the for statement. If you are using an IDE, you might notice that this statment changes colour to denote that it is one of R’s protected control statements.
  • x in 1:10 - we know that 1:10 produces a vector of all of the numbers in sequence from 1 to 10. the x in bit just means “for every value in the vector of”. The x could be anything you want it to be. e.g. for numbers in 1:10 would yeild the name result. Note here that different programming languages follow different conventions- in python you’ll often see for loops written as for i in 1:10.
  • {} - the curly brackets contain the body of the loop. What that means is that all of the values we have just specified above will have the contents of the {} performed on them. Here, we’ve used the print() function, which just prints our values to the console.

So, this loop assigns x a value of 1 - 10 in a sequence, and prints it to the console.

This is an example of a super simple and straightforward control statement. We could replace the 1:10 with anything we liked, and the loop would cycle through the values presented it in turn until it reached the final one.

Now, printing the numbers 1 to 10 doesn’t seem overly useful. What if we want to perform a mathematical operation on all of the numbers in a sequence quickly? Let’s expand our for loop so that it adds 10 to every number in the sequence, and prints the result to the console:

for (x in 1:10){
  print(x + 10)
}
[1] 11
[1] 12
[1] 13
[1] 14
[1] 15
[1] 16
[1] 17
[1] 18
[1] 19
[1] 20

Easy as that. Again, this is a really basic example of a for loop, just so you can get to grips with the principle of how they work in R.

We can also create for loops with vectors consisting of character strings - let’s create one with 4 components:

years <- c("2019", "2020", "2021", "2022")

Remember what when we create character string vectors, we have to include the c() function

Let’s pop these in a loop that will print the sentence “The year is” followed by each of the levels of the vector in turn

years <- c("2019", "2020", "2021", "2022")

for (x in years){
  y <- paste("The year is", x)
  print(y)
}
[1] "The year is 2019"
[1] "The year is 2020"
[1] "The year is 2021"
[1] "The year is 2022"

This loops through the four years we have given in the vector, and uses the paste() function to stick two character strings together, printing each of the vector elements in turn. Notice that we’ve created a new object within the loop, y - if you look in your R environment window, or try and print y to the console with print(y), you’ll see that y is stored as “The year is 2022”, which is the final iteration of the loop. It’s important to note that the other iterations are not stored in the wider R environment, as the loop overwrites itself every time it performs an iteration.

Just to recap,a for loop runs through values in a vector (and is quick in these small toy examples!), and does some work for you inside the statement. Curly brackets {} denote the body of the loop, which is where we tell R what we want it to do with our input. Whilst for loops are great, every example that we’ve just run through can actually be acheived with simpler, and more computationally efficient code (sorry). Remember to think about your code, and consider whether there might be easier solutions to a problem!

Vectorisation as a more efficient mechanism?

For our first example, printing 1 - 10 to the screen with a loop, we could save a lot of time by explicitly popping x into it’s own vector (rather than adding this to the conditions of a for loop), and dealing with it that way:

x <- 1:10
print(x)
 [1]  1  2  3  4  5  6  7  8  9 10

As you can see, this ultimately yields the same result, with considerably less faffing. In these small toy examples, there isn’t a whole lot of difference in computation time, but in much larger datasets, this is certainly something worth considering. Generally, vectorisation is much speedier than for loops.

For the example where we added 10 to x, we can use the same vectorisation principle. This is where R differs in it’s fundemental dev makeup to, for example, bash, where you would have to do a for loop to perform the following:

x <- 1:10 # recreate our 1:10 vector
print(x + 10)
 [1] 11 12 13 14 15 16 17 18 19 20

Here, you don’t even need the print() function, just typing x + 10 would be sufficient!

You don’t even really need to use loops on character vectors in R! Let’s go back to our “the year is” example. We can avoid a loop by using the paste() function on the vector explicitly, rather than having to force it through a loop:

years <- c("2019", "2020", "2021", "2022")
paste("The year is", years)
[1] "The year is 2019" "The year is 2020" "The year is 2021" "The year is 2022"

So why bother with for loops in the first place?

All of this is not to say that for loops are rubbish and useless in R - in fact there will likely be times where they are unavoidable, and a vector based solution just won’t cut it. It is however worth hammering home the point that they are really worth thinking about quite carefully. There will often be a better way to do whatever you’re trying to do - slow down when you’re coding. Stop and think about what it is you’re trying to achieve. Beginners in particular tend to learn how to create for loops, and then use them for everything, when often, a vector based solution would be much quicker and simpler!

If statements

Now, on to if statements. These are another control flow coding mechanism you can use in R and further afield to customise the order that commands are run in, depending on conditions of your data. Think about the kettle example - IF your water boiled, then you perform the task. if statements ask whether a condition has been met, before they perform a function. The best way to explain this is, as always, with an example:

z <- 1
if (z < 10){
  print("z is less than 10")
}

We can see that because we’ve given z the value of 1, which is less than 10, we get an output telling us so (R is performing the function!). What happens if we change the assignment of z and try again?

z <- 45
if (z < 10){
  print("z is less than 10")
}

We don’t get an output. Because the condition was not met, no function was performed on our data.

The way that this is coded in R is that the provided condition (in ()) is run, to give a logical output. If that output is TRUE, the body of the function (in {}) is run. If the output is FALSE, nothing will happen.

else statements

It isn’t a huge leap to ask whether we could take the above and perform a different function if the condition was not met, and the logical output was FALSE. We can achieve this by pairing our if statement with an else statement. The syntax of this can take a little getting used to, because it pairs two sets of {} separated by an else statement. Let’s demonstrate:

z <- 1

if (z < 10){
  print("z is less than 10")
} else {
  print("z is more than 10")
}
[1] "z is less than 10"

With an input of 1, we get a printed message telling us that z is less than 10. What if we change z to be greater than 10?

z <- 20

if (z < 10){
  print("z is less than 10")
} else {
  print("z is more than 10")
}
[1] "z is more than 10"

As expected, R tells us that z is more than 10. This combination of if and else statements runs a control flow that takes an input, and if a condition is met, runs function a. If the condition is not met, it runs function b. This basic principle allows you to perform slightly more complex functions or analyses, based on the input that you give.

The ifelse() function

There is an alternative to if and else control flow functions in R - the ifelse() function. This doesn’t always perform in quite the way that you might expect, but it’s certainly an option to consider. The syntax is perhaps a little more familiar than the control flow statements… Let’s perform the same thing we just did, but this time using an ifelse() function:

z <- 1
ifelse(z < 10, "less than 10", "more than 10")
[1] "less than 10"
z <- 20
ifelse(z < 10, "less than 10", "more than 10")
[1] "more than 10"

Great. All works the same so far! The ifelse() function takes an input, evaluates it against a condition (here that it is < 10). If the condition is TRUE, it performs the first option, if FALSE, does the 2nd.

Helpfully, we can also perform the ifelse() functions on a vector. Let’s create a numeric vector from 1 - 60 in steps of 6 and run our function again

z <- seq(from = 1, to = 60, by = 6)
ifelse(z < 10, "less than 10", "more than 10")
 [1] "less than 10" "less than 10" "more than 10" "more than 10" "more than 10" "more than 10" "more than 10"
 [8] "more than 10" "more than 10" "more than 10"

We end up with 10 outputs, each telling us whether a result is less or more than 10!

z <- seq(from = 1, to = 60, by = 6)

if (z < 10){
  print("z is less than 10")
} else {
  print("z is more than 10")
}
Error in if (z < 10) { : the condition has length > 1

You can see from the error above, that you can’t perform if else statements on a vector - the condition is only expecting something with a length of 1, rather than, in this case, 10.

We can use ifelse() on character vectors too. Let’s create one and try it out:

countries <- c("UK", "USA", "France", "Spain")
ifelse(countries == "UK", "UK", "Elsewhere")
[1] "UK"        "Elsewhere" "Elsewhere" "Elsewhere"

The function is evaluating to see if the input matches the string “UK”, and if it does, will print “UK”, otherwise, prints “Elsewhere”. Fairly straightforward stuff!

Writing your own functions:

Writing your own functions is an important part of programming. It keeps code simple and readable, and allows you to perform a set of tasks multiple times without loads of duplication in your code. If you wanted to develop your own package, custom function creation would be a huge part of this - a package is essentially just a collection of functions!

The process of creating functions is quite straightforward - I do it loads to make my life quick and easy. Let’s start by creating a simple function that adds 10 to any numeric input:

add_ten <- function(x){
  y <- x + 10
  return(y)
}

add_ten(1)
[1] 11

So, here, we’ve created and tested a basic function. Let’s dissect it a little:

Notice here that the new y object is treated a little differently in functions than loops. If we remove y from our environment and run the function again, you’ll notice that it does not re-appear. Whatever objects you create within the body of the function exist only within that function - they are not callable to the wider R environment.

Functions can also take a vector input - let’s run our add_ten() function with a vector and see what happens

add_ten <- function(x){
  y <- x + 10
  return(y)
}

z <- 1:10
add_ten(z)
 [1] 11 12 13 14 15 16 17 18 19 20

Of course, we could perform this function manually, as it is a really straightforward example. I’d be unlikely to bother creating a function to do this in practice, but it’s a useful demonstration.

The anatomy of a function

Let’s quickly recap the anatomy of how a function works

function(x) declares a function. It creates the function within the R environment, and defines the arguments that the function requires. In our example above, whenever you run add_ten, you must have an x argument, otherwise the function will not run.

{} define the block of code within which the work that the function does takes place. Here, y is only defined within the function.

return(y) tells R to give us an output, and display what the function has done.

Functions with multiple arguments

We can extend our functions to take multiple arguments, or inputs, using the basics that we’ve just learned. Functions that we have used throughout the course so far have taken multiple arguments, so let’s try and also create one. We’ll write a function that multiplies two numbers together:

multiply <- function(x, y){
  z <- x * y
  return(z)
}

multiply(3,2)
[1] 6

In our R environment window, we can see a new section has been created called ‘Functions’. Within that, we can see both our add_ten and our multiply functions, and the number of arguments that each takes.

Functions with default arguments

You’ll find often that several arguments in functions that you’re running in R have default settngs that you do not have to explicitly code in order for R to perform them. For example, in the sum() and mean() functions, the default for the na.rm argument is FALSE. We can edit our multiply() function to have a default y value of 10:

multiply <- function(x, y = 10){
  z <- x * y
  return(z)
}

multiply(3)
[1] 30
multiply(3, 2)
[1] 6

Here, we can see that if we include only 1 argument to the function now, it will run and use the default of y = 10. If we include two arguments ourselves, we override the default and the function performs on both of the arguments that we have specified. You can hopefully see how writing functions with multiple arguments and defaults isn’t too much of a stretch from writing a function with a single argument, and see how useful that might be in your coding!

Combining functions and conditionals:

Now, we can combine all of the skills that we’ve learned today and create complex functions with some control flow statements inside of them. Let’s start by wtiting a function that evaluates whether a numerical input is greater than or less than 10.

eval10 <- function(x){
  y <- ifelse(x < 10, "less than 10", "greater than 10")
  return(y)
}

eval10(1)
[1] "less than 10"
eval10(15)
[1] "greater than 10"

We’ve included a simple ifelse function within our eval10 function, which takes a new object, y, and performs an ifelse() function upon it, and returns the output. We could do the same with the explicit if and else control flow statements

eval10_2 <- function(x){
  y <- if (x < 10){
    print("less than 10")
    } else {
      print("greater than 10")
    }
}

eval10_2(1)
[1] "less than 10"
eval10_2(15)
[1] "greater than 10"

Whilst this is a simple example, we could build up to creating some incredibly complex functions with custom control flows to efficiently handle our data and downstream analysis in R. It may well be useful for things such as looking at data to see if it contains headers before removing them, or assessing the length of a data set before performing a function on it.

Lists in R

Now, we’ve had a whistle stop tour of functions, obviously this is not the full extent of their functionality, but it’s time to move on to lists. We’ve not really mentioned lists so far, other than very briefly in some of the beginner sessions. To recap, there are 4 main data structures in R - vectors, matricies, data.frames, and lists.

A list is a special form of data structure which allows you to contain objects of different lengths within it. They are a little more complicated than the other data structures we covered before - partly because a data.frame is both a special type of list, and can be contained within a list! In a data.frame, each component part (or column) must be the same length - this is not true of a list.

They are quite complicated on first glance, and often are not taught at all in R courses - I was never formally taught what a list was or how on earth to use one, and I had to try and work it out for myself. Lists are probably the form od data structure that I use the least in R, simply because I never got into the habit of using them. Now, let’s make a list and see how they work, and figure out how to access stuff within them. First, we’ll create three vectors (one character, one numeric, and one logical), and combine them with the list() function.

nintendo <- c("Mario", "Luigi", "Peach")
numbers <- 1:100
logic <- c(TRUE, FALSE, FALSE, TRUE)

my_list <- list(nintendo, numbers, logic)

Now, we have our list. We can print it to the screen by typing the name of our list, and it’ll print everything out.

my_list
[[1]]
[1] "Mario" "Luigi" "Peach"

[[2]]
  [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
 [27]  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52
 [53]  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78
 [79]  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100

[[3]]
[1]  TRUE FALSE FALSE  TRUE

From this, we can clearly see that the objects contained within the list are of different lengths - nintendo has a length of 3, numbers has a length of 100, and logic has a length of 4.

So, how do we access the list? It can seem complicated, but actually printing it to the screen has given us lots of information. We can use square brackets [] to choose objects. We can also access elements with their names, provided we have given them names, but we will come back to that.

Let’s try and select the first vector element of our list. We might try and access it with:

my_list[1]
[[1]]
[1] "Mario" "Luigi" "Peach"

Whilst this does return what we want it to, this actually isn’t in the vector class that we created the list with. We can check with the class() function:

class(my_list[1])
[1] "list"

We can see here that the object has retained it’s list class, and has taken the first part of the list, but not the vector itself. We can access the vector within the list with double square brackets [[]], the clue is in the display of the list!

my_list[[1]]
[1] "Mario" "Luigi" "Peach"
class(my_list[[1]])
[1] "character"

When we verify what we’re doing with class(), we can see that we’re getting the original character vector stored within the list. This is a bit complex and hand-wavy, but basically remember that [[]] allows you to access the element from within the list in its native form, whereas [] gives you the element of the list, whilst retaining it’s list class.

Be aware that the way we access lists with [] is different than vectors. For example, if we were to type my_list[1:2] we get the first two elements of the list, but my_list[[1:2]] gives you the second element of the first bit of the list:

my_list[1:2]
[[1]]
[1] "Mario" "Luigi" "Peach"

[[2]]
  [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
 [27]  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52
 [53]  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78
 [79]  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100
my_list[[1:2]]
[1] "Luigi"

You can access bits of lists as above, or perhaps more intuitively and less confusingly, by combining double and single square brackets

my_list[[1]][2] # This accesses the 2nd item of the 1st list element.

You can also use names to access list elements in a way that is equivalent to how a dataframe would work. In order to do this, however, you must specify the names when you’re creating the list, like this:

my_list <- list(nintendo = nintendo, numbers = numbers, logic = logic)

If we print the list again, you’ll see that the [[1]], [[2]], and [[3]] have been replaced by $nintendo, $numbers, and $logic:

my_list
$nintendo
[1] "Mario" "Luigi" "Peach"

$numbers
  [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
 [27]  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52
 [53]  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78
 [79]  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100

$logic
[1]  TRUE FALSE FALSE  TRUE

Now you can access your list using the names, but note that just like a dataframe, my_list[[1]] will still work

my_list$nintendo
[1] "Mario" "Luigi" "Peach"
my_list[[1]]
[1] "Mario" "Luigi" "Peach"

Why are lists important?

It perhaps isn’t immediately obvious why lists are important, but we will talk more about this in the next session. It’s useful for you to know how to use them, as they will make R more useful to you.

Briefly, lists can be helpful if you are working on lots of dataframes/tibbles at the same time, as you can store them within a list. The versatility of this will become clearer next time when we’re talking about the apply family of functions, sapply(), lapply(), and apply().

Summary

So, today we have learned about control flow with for, if, else, and ifelse(), and how these are used to control the flow of data through a set of functions, depending on whether conditions are met.

We’ve learned how to write our own functions, including with multiple arguments and defaults, and have combined this with our new knowledge of control flow.

Finally, we touched on lists which feeds nicely into the apply set of functions that we’ll look at in more detail on Thursday. We can use sapply(), lapply() and apply() to efficiently process vectors in R, and we’ll learn more about the principles of proper scripting.

LS0tCnRpdGxlOiAiTElGRTQxMzggLSBBZHZhbmNlZCBSIHdvcmtzaG9wIDEiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCkhlbGxvISBXZWxjb21lIHRvIHRoZSBmaXJzdCBvZiB0aGUgYWR2YW5jZWQgUiB3b3Jrc2hvcHMgb24gdGhlIExJRkU0MTM4IG1vZHVsZS4gT3VyIGxlYXJuaW5nIG9iamVjdGl2ZXMgZm9yIHRoaXMgc2Vzc2lvbiBhcmU6CgoqIExlYXJuIHNvbWUgYWR2YW5jZWQgcHJvZ3JhbW1pbmcgc2tpbGxzIGluIFIsIGFuZCB1bmRlcnN0YW5kIHRoYXQgdGhlIGxhbmd1YWdlIGNhbiBiZSB1c2VkIGFzIGEgInN0cmljdCIgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2Ugc2ltaWxhciB0byBQeXRob24gZXRjLgoqIFRoaW5rIGFib3V0IGNvbnRyb2wgZmxvdyAtIHdlJ2xsIGludHJvZHVjZSB0aGUgY29uY2VwdHMgb2YgY29udHJvbCBmbG93LCBpbmNsdWRpbmcgYGZvcmAgbG9vcHMsIGBpZmAgYW5kIGBlbHNlYCBzdGF0ZW1lbnRzLCBhbmQgdGhlIGBpZmVsc2UoKWAgZnVuY3Rpb24uCiogV2Ugd2lsbCBsZWFybiB0byB3cml0ZSBvdXIgb3duIGZ1bmN0aW9ucywgYSB2aXRhbCB0b29sIHdoZW4gd2UgYXJlIGJ1aWxkaW5nIHNjcmlwdHMuIFdlIHdpbGwgZGlzY3VzcyB0aGUgdXNhYmlsaXR5IG9mIGN1c3RvbSBmdW5jdGlvbnMgdG8gYXZvaWQgcmVwbGljYXRpb24gaW4geW91ciBjb2RlLgoqIEZpbmFsbHksIHdlIHdpbGwgYmVnaW4gdG8gaGF2ZSBhIGxvb2sgYXQgb3VyIDR0aCBkYXRhIHN0cnVjdHVyZSBpbiBSIC0gbGlzdHMuCgojIFdoYXQgZG8gd2UgbWVhbiBieSAiYWR2YW5jZWQiPwoKU28sIHRoZSBwcmV2aW91cyBzZXNzaW9ucyBoYXZlIGFsbCBiZWVuIGRlc2lnbmVkIHRvIGdpdmUgeW91IGFuIG92ZXJhbGwgZ3JvdW5kaW5nIG9mIHRoZSB3YXkgdGhhdCBSIHdvcmtzLCBhbmQgdG8gdHJ5IGFuZCB1bmRlcnN0YW5kIHRoZSBkaWZmZXJlbnQgYXBwcm9hY2hlcyB0aGF0IFIgdXNlcnMgdGFrZSB0byB0aGUgbGFuZ3VhZ2UgKGJhc2VSIHZlcnN1cyB0aGUgdGlkeXZlcnNlIGFwcHJvYWNoIGZvciBlLmcuKS4gRm9yIG1vc3QgUiB1c2VycywgdGhpcyBpcyBlbm91Z2ggdG8gZ2V0IGJ5LiBZb3UnbGwgYmUgYWJsZSB0byBkbyB0aGUgbWFqb3JpdHkgb2YgdGhlIHN0dWZmIHRoYXQgeW91IG5lZWQgdG8gdXNpbmcgb25seSB0aGUgc2tpbGxzIHRoYXQgd2UndmUgYmVlbiB0aHJvdWdoIHNvIGZhci4KClRoYXQgYmVpbmcgc2FpZCwgdGhlcmUgYXJlIHRpbWVzLCBwYXJ0aWN1bGFybHkgd2hlbiB1bmRlcnRha2luZyBiaW9pbmZvcm1hdGljIGFuYWx5c2lzLCB3aGVuIHBlcmhhcHMgeW91IG1pZ2h0IGxpa2UgdG8gaGF2ZSBhIHNjcmlwdCB0aGF0IHdpbGwgcnVuIGluZGVwZW5kZW50bHkgd2l0aG91dCB5b3VyIGlucHV0LiBTaXR1YXRpb25zIHN1Y2ggYXMgdGhpcyByZWFsbHkgaGlnaGxpZ2h0IHRoZSBpbXBvcnRhbmNlIG9mIHRoZSBhZHZhbmNlZCB0ZWNobmlxdWVzIHRoYXQgd2UncmUgYWJvdXQgdG8gbGVhcm4hCgojIFRha2luZyBpdCB0byB0aGUgbmV4dCBzdGVwCgpUaGUgYmVsb3cgd2lsbCBiZWdpbiB0byBnaXZlIHlvdSBhIGdyZWF0ZXIgZmxleGliaWx0eSBhbmQgdmVyc2F0aWxpdHkgd2l0aCB5b3VyIFIgY29kaW5nLCBhbmQgYWxsb3cgeW91IHRvIGJlZ2luIHRvIG1ha2UgUiB3b3JrIGZvciB5b3UgaW4gZXhhY3RseSB0aGUgd2F5IHRoYXQgeW91IHdhbnQgaXQgdG8uIGBmb3JgIGxvb3BzIGZvciBleGFtcGxlIGFyZSBhIGdyZWF0IHByaW5jaXBsZSB0byBsZWFybiBpbiBnZW5lcmFsIHdpdGggeW91ciBjb2RlLCBhbmQgbGVhcm5pbmcgYm90aCB0aGUgbG9vcHMgdGhlbXNlbHZlcyBhcyB3ZWxsIGFzIHRoZSBhbHRlcm5hdGl2ZXMgYXZhaWxhYmxlIGluIFIgd2lsbCBiZSBpbmNyZWRpYmx5IHVzZWZ1bCB0byB5b3UuIAoKQW5vdGhlciBuaWNlIHRoaW5nIGFib3V0IG1vdmluZyBvbiB0byBtb3JlIGFkdmFuY2VkIGNvZGluZyBwcmluY2lwbGVzIGluIFIgaXMgdGhhdCB0aGV5IHdpbGwgaGVscCB0byBkZWVwZW4geW91ciB1bmRlcnN0YW5kaW5nIG9mIGhvdyB0aGUgYmFzaWNzIHdvcmsuICBGb3IgZXhhbXBsZSwgdGhlIHdheSB0aGF0IHdlIGhhbmRsZSBhbmQgYWNjZXNzIHZlY3RvcnMgd2lsbCBiZWNvbWUgY2xlYXJlciBhcyB3ZSB1c2UgbW9yZSBhZHZhbmNlZCB0ZWNobmlxdWVzIHRvIHdvcmsgdGhyb3VnaCB0aGVtLgoKIyBCdXQgaG93IGRvIEkgYmVjb21lIGFuICJhZHZhbmNlZCIgUiB1c2VyPyEKCiogSnVzdCBmb2xsb3dpbmcgdHV0b3JpYWxzIHN1Y2ggYXMgdGhpcyB3aWxsIG5vdCBtYWtlIHlvdSBpbnRvIGFuIGFkdmFuY2VkIFIgdXNlci4gVGhlc2UgdHV0b3JpYWxzIGNhbiBvbmx5IGdvIHNvIGZhciAtIEkgY2FuIGludHJvZHVjZSB5b3UgdG8gYSBjb25jZXB0LCBidXQgcmVhbGx5IHdoYXQgd2lsbCBkZWVwZW4gYW5kIHN0cmVuZ3RoZW4geW91ciB1bmRlcnN0YW5kaW5nIGlzIGJ5IHVzaW5nIHRoZSB0ZWNobmlxdWVzIHdpdGggcmVhbC13b3JsZCBkYXRhLCBiZXlvbmQgdGhlIHN0cnVjdHVyZWQgZm9ybWF0IG9mIHRoaXMgdHV0b3JpYWwuCgoqIFRoZSBiZXN0IHdheSB0byBsZWFybiBSIChvciBhbnkgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UpLCBpcyBieSBkb2luZywgcGxheWluZywgYW5kIGV4cGVyaW1lbnRpbmcuCgoqIENyaXRpY2FsbHksIHlvdSBhbHNvIG5lZWQgdG8gbGVhcm4gaG93IGFuZCB3aGVyZSB0byBhY2Nlc3MgaGVscC4gRG9uJ3QgYmUgYWZyYWlkIHRvIHVzZSBnb29nbGUsIHN0YWNrIG92ZXJmbG93LCBvciB0byBhc2sgeW91ciBmcmllbmRzIG9yIGNvbGxlYWd1ZXMgZm9yIGFkdmljZS4gQSBmcmVzaCBwYWlyIG9mIGV5ZXMgaXMgbXVjaCBtb3JlIGxpa2VseSB0byBzcG90IGEgcm9ndWUgY29tbWEgdGhhbiB5b3UgYXJlIGFmdGVyIHlvdSd2ZSBiZWVuIHN0YXJpbmcgYXQgeW91ciBzY3JlZW4gZm9yIGhvdXJzLiBUaGlzIG1pZ2h0IHNlZW0gYSBsaXR0bGUgYmFzaWMgZm9yIGFuIGFkdmFuY2VkIFIgdHV0b3JpYWwsIGJ1dCBsb29raW5nIGZvciBhbnN3ZXJzIG9ubGluZSBpcyBhIGdyZWF0IHdheSB0byBzZWUgb3RoZXIgZXhhbXBsZXMsIGxvb2sgYXQgb3RoZXIgcGVvcGxlcyBjb2Rpbmcgc3R5bGVzLCBnZXQgaGVscCwgYW5kIGltcG9ydGFudGx5LCBsZWFybiB0byBhdm9pZCBmdXR1cmUgbWlzdGFrZXMuIFRoZXJlIGFyZSBsb2FkcyBvZiB3b25kZXJmdWwgUiByZXNvdXJjZXMgb3V0IHRoZXJlIGZvciB5b3UgdG8gdXNlLCBhbmQgdGhleSBhcmUgZ2V0dGluZyBpbmNyZWFzaW5nbHkgYmV0dGVyIHdpdGggdGltZS4KCiogQW5vdGhlciB0aGluZyB5b3Ugc2hvdWxkIGRldmVsb3AgYXMgeW91IGJlY29tZSBhIG1vcmUgYWR2YW5jZWQgUiB1c2VyLCBpcyB5b3VyIG93biBjb2RpbmcgcGhpbG9zb3BoeS4gTXkgYXBwcm9hY2ggaXMgdG8gZG8gd2hhdCB3b3Jrcy4gVGhpcyBzb3VuZHMgZGFmdCBhdCBmaXJzdCwgYnV0IHRoZXJlIGFyZSBzZXZlcmFsIHBlb3BsZSB3aG9zIHBoaWxvc29waHkgaXQgaXMgdG8gYWNoaWV2ZSBhbmQgZW5kIHJlc3VsdCB1c2luZyBhcyBmZXcgbGluZXMgb2YgY29kZSBhcyBwb3NzaWJsZS4gSSBsaWtlIHRvIGRvIHdoYXQgd29ya3MgZm9yIG1lLCB3aGlsc3QgcmV0YWluaW5nIGFuIG9wZW4gbWluZCB0byBuZXcgc29sdXRpb25zLiBJdCBpcyB2ZXJ5IGVhc3kgdG8gZ2V0IHN0dWNrIGluIGEgY29kaW5nIHJ1dCB3aXRoIFIsIGFuZCBjb250aW51ZSB0byB1c2UgYSBzb2x1dGlvbiB0aGF0IG1pZ2h0IHF1aWNrbHkgYmVjb21lIG91dCBvZiBkYXRlIG9yIGltcHJhY3RpY2FsL3VuZWNjZXNhcmlseSBkaWZmaWN1bHQgKHRoaW5rIGFib3V0IHRoZSBpbnRyb2R1Y3Rpb24gb2YgdGhlIHRpZHl2ZXJzZSBpbiB0aGUgMjAxMHMgZm9yIGV4YW1wbGUhKS4gCgpUaGUgYWJvdmUgYWJpbGl0aWVzIGFuZCBpZGVhcyB3aWxsIG9wZW4gdXAgeW91ciBjb2RpbmcgYWJpbGl0aWVzLCBhbmQgYWxsb3cgeW91IHRvIHJlYWxseSBnZXQgdG8gZ3JpcHMgd2l0aCBSIGFzIGJvdGggYSBsYW5ndWFnZSBhbmQgYSB0b29sIGZvciBkYXRhIHdyYW5nbGluZywgcGxvdHRpbmcsIGFuZCBkb3duc3RyZWFtIGFuYWx5c2lzLiAKCkZpbmFsbHksIHRoZSBpbXBvcnRhbmNlIG9mIHlvdXIgY29kaW5nIGVudmlyb25tZW50IChJIG1lYW4gcGh5c2ljYWwgZW52aXJvbm1lbnQsIG5vdCB5b3VyIFIgZW52aXJvbm1lbnQpIGNhbm5vdCBiZSB1bmRlcnN0YXRlZC4gRmluZCBhIHdheSB0byBnZXQgImluIHRoZSB6b25lIiwgYW5kIGFsbG93IHlvdXJzZWxmIHRvIGNvbmNlbnRyYXRlIHNvbGVseSBvbiB3aGF0IGl0IGlzIHRoYXQgeW91J3JlIHRyeWluZyB0byBhY2hpZXZlLiBGb2N1cyBpcyBpbXBvcnRhbnQgd2l0aCBjb2RlLCBpdCdzIHNvIGVhc3kgdG8gbWFrZSBtaXN0YWtlcyBhbmQgZW5kIHVwIHdpdGggYW5hbHlzZXMgdGhhdCBoYXNuJ3QgZG9uZSB3aGF0IHlvdSB0aGluayBpdCBoYXMuIEZvciBtZSwgSSBtYWtlIGEgZ2lhbnQgY3VwIG9mIHRlYSwgZ3JhYiBzb21lIGJpc2N1aXRzLCBnZXQgY29tZnkgd2l0aCBhIHdhcm0ganVtcGVyLCBhbmQgcG9wIG15IGhlYWRwaG9uZXMgb24uIEkgbGlzdGVuIHRvIGEgcGxheWxpc3QgdGhhdCBJIGhhdmUgcGVyc29uYWxseSBjdXJhdGVkIGZvciBhIG1peHR1cmUgb2YgY29uY2VudHJhdGlvbiwgcG9zaXRpdml0eSwgYW5kIG1vdGl2YXRpb24uIEl0IHNvdW5kcyBkYWZ0LCBidXQgSSBwcm9taXNlLCBpdCB3b3Jrcy4gSWYgSSByZWFsbHkgZG9uJ3Qgd2FudCB0byBiZSBkaXN0dXJiZWQsIEkgc2h1dCBteSBvZmZpY2UgZG9vciwgY292ZXIgdGhlIHdpbmRvdyBpbiB0aGUgZG9vciwgYW5kIHR1cm4gdGhlIGxpZ2h0cyBvZmYgKGFuZCBwdXQgbXkgbGFtcCBvbiAtIEknbSBhaW1pbmcgZm9yIGFtYmllbnQgbGlnaHRpbmcgcmF0aGVyIHRoYW4gcGl0Y2ggYmxhY2shKS4KCkkga25vdyBJIGp1c3Qgc2FpZCBmaW5hbGx5LCBidXQgYWN0dWFsbHkgcHJvcGVybHkgZmluYWxseSwgZG9uJ3QgZm9yZ2V0IHRvIHRha2UgYSBicmVhay4gSWYgeW91J3JlIHRlYXJpbmcgeW91ciBoYWlyIG91dCB0byBkZWJ1ZyBhIHBpZWNlIG9mIGNvZGUsIG9yIGlmIHlvdSdyZSByZWFsbHkgc3R1Y2sgYW5kIGp1c3QgY2FuJ3QgbWFrZSBzb21ldGhpbmcgd29yaywgcHV0IGl0IGRvd24uIFdhbGsgYXdheSwgbWFrZSB5b3Vyc2VsZiBhIGN1cCBvZiB0ZWEsIGhhdmUgc29tZSBjYWtlLCBnbyBmb3IgYSBydW4sIGRvIHdoYXRldmVyIHlvdSBuZWVkIHRvIGZvciBzb21lIG1lbnRhbCBzcGFjZS4gRXZlbiBzbGVlcCBvbiBpdCBpZiB5b3UgaGF2ZSB0by4gV2hlbiB5b3UgY29tZSBiYWNrIHRvIGl0LCBvZnRlbiB0aGUgYW5zd2VyIHdpbGwgcHJlc2VudCBpdHNlbGYuIElmIGl0IGRvZXNuJ3QgZXZlcnl0aGluZyB3aWxsIGF0IGxlYXN0IGZlZWwgYSBsaXR0bGUgZWFzaWVyIHRoYW4gaXQgZGlkIGJlZm9yZS4gQ29kaW5nIGNhbiBiZSBmcnVzdHJhdGluZywgYnV0IGxlYXJuaW5nIHRvIG1hbmFnZSBhbmQgaGFybmVzcyB0aGF0IGZydXN0cmF0aW9uIGlzIGEgcmVhbCBza2lsbCEKClJpZ2h0LiBMZXQncyBnZXQgdG8gdGhlIG1lYXQgb2YgaXQuCgojIENvbnRyb2wgZmxvdwoKVGhlIGZpcnN0IGNvbmNlcHQgdGhhdCB3ZSdsbCBjb3ZlciB0b2RheSBpcyBjb250cm9sIGZsb3cuIFlvdSBtYXkgd2VsbCBoYXZlIGNvbWUgYWNyb3NzIGNvbnRyb2wgZmxvdyBpbiB5b3VyIGZvcnJheXMgd2l0aCBQeXRob24gYW5kIFVuaXgsIGFuZCB0aGUgYmFzaWMgaWRlYSBvZiBob3cgaXQgd29ya3MgaXMgbGFyZ2VseSBzaW1pbGFyIGluIFIuIENvbnRyb2wgZmxvdyBpcyBhIGZ1bmRlbWVudGFsIHBhcnQgb2YgdGhlIHdheSB0aGF0IGFueSBwcm9ncmFtbWluZyBsYW5ndWFnZSB3b3Jrcywgbm90IGp1c3QgUi4gSXQgZXNzZW50aWFsbHkgcHJvdmlkZXMgYSB3YXkgdG8gY29udHJvbCB0aGUgb3JkZXIgdGhhdCBhIHNldCBvZiBmdW5jdGlvbnMgYXJlIHBlcmZvcm1lZCBvbiB5b3VyIGRhdGFzZXQuCgpUaGVyZSBhcmUgc2V2ZXJhbCBleGFtcGxlcyBvZiBjb250cm9sIGZsb3cgZnVuY3Rpb25zLCBidXQgdGhlIG9uZXMgd2Ugd2lsbCBjb25jZW50cmF0ZSBvbiB0b2RheSBhcmUgYGZvcmAgbG9vcHMsIGBpZmAgYW5kIGBlbHNlYCBzdGF0ZW1lbnRzLCBhbmQgdGhlIGBpZmVsc2UoKWAgZnVuY3Rpb24uIGBpZmVsc2UoKWAgaXNuJ3Qgc3RyaWN0bHkgYSBjb250cm9sIGZsb3cgc3RhdGVtZW50LCBidXQgYSBmdW5jdGlvbiBmcm9tIHRoZSBiYXNlUiBzZXQgb2YgZnVuY3Rpb25zLgoKQmVmb3JlIHdlIGdldCBzdGFydGVkLCB0aGUgd2F5IHRoYXQgY29udHJvbCBmbG93cyB3b3JrIGFyZSBhcyBmb2xsb3dzLiBTYXksIGZvciBleGFtcGxlLCB5b3UgaGF2ZSBhIGNvbmRpdGlvbi4gWW91IGFzayB3aGV0aGVyIHRoYXQgY29uZGl0aW9uIGlzIHRydWUgb3IgZmFsc2UuIElmIHRoZSBjb25kaXRpb24gaXMgdHJ1ZSwgeW91IHBlcmZvcm0gYSBmdW5jdGlvbi4gCgohW10oY29udHJvbF9mbG93LnBuZykKCklmIGl0IGlzIGZhbHNlLCB5b3UgcGVyZm9ybSBhbm90aGVyIGZ1bmN0aW9uLiBUaGlzIGlzIGVhc2llciB0byB1bmRlcnN0YW5kIHdpdGggYW4gYW5hbG9neS4gV2UgY2FuIHVzZSBgaWZgIGBlbHNlYCBzdGF0ZW1lbnRzIHRvIHdyaXRlIGEgZnVuY3Rpb24gdG8gbWFrZSBvdXJzZWx2ZXMgYSBjdXAgb2YgdGVhLiBGaXJzdCwgd2UgcGVyZm9ybSB0aGUgYm9pbCBrZXR0bGUgZnVuY3Rpb24uIFRoZW4sIHdlIHBlcmlvZGljYWxseSBjaGVjayB0byBzZWUgaWYgdGhlIHdhdGVyIGhhcyBib2lsZWQuIElmIHRoZSBvdXRjb21lIG9mICJIYXMgdGhlIHdhdGVyIGJvaWxlZCIgaXMgYEZBTFNFYCwgd2UgcGVyZm9ybSB0aGUgd2FpdCBhIGJpdCBsb25nZXIgZnVuY3Rpb24uIFdlIGNoZWNrIGFnYWluLiBJZiB0aGUgb3V0Y29tZSBpcyBgVFJVRWAsIHdlIHBlcmZvcm0gdGhlIHBvdXIgd2F0ZXIgZnVuY3Rpb24sIHdoaWNoIHRoZW4gYWxsb3dzIHVzIHRvIHBlcmZvcm0gdGhlIGRyaW5rIHRlYSBmdW5jdGlvbi4gQWRtaXR0ZWRseSwgdGhpcyBhbmFsb2d5IGlzIGZsYXdlZCAtIGl0J3MgbWlzc2luZyBzb21lIHZpdGFsIHN0ZXBzIGluY2x1ZGluZyBhZGRpbmcgYSB0ZWEgYmFnLCBhZGRpbmcgYW55IG1pbGssIHdhaXRpbmcgZm9yIHRoZSB0ZWEgdG8gY29vbCwgYW5kIGN1dHRpbmcgeW91cnNlbGYgYSBzbGljZSBvZiBjYWtlISBUaGF0IGJlaW5nIHNhaWQsIGl0IGRlbW9uc3RyYXRlcyB0aGUgYmFzaWMgY29uY2VwdCBvZiBjb250cm9sIGZsb3cgbmljZWx5LgoKIVtdKGNvbnRyb2xfZmxvdzIucG5nKQoKIyMgQSBub3RlIG9uIGJyYWNrZXRzCgpCZWZvcmUgd2UgZ28gYW55IGZ1cnRoZXIsIHlvdSBtYXkgaGF2ZSBub3RpY2VkIHRoYXQgd2Ugb2Z0ZW4gdXNlIGRpZmZlcmVudCB0eXBlcyBvZiBicmFja2V0cyBmb3IgdmFyaW91cyBwdXJwb3NlcyBpbiBSLiBUaGlzIGlzIHZpdGFsbHkgaW1wb3J0YW50IHRvIHRoZSBsYW5ndWFnZSwgYW5kIHlvdXIgY29kZSB3aWxsIG5vdCBmdW5jdGlvbiBpbiB0aGUgd2F5IHRoYXQgeW91IGV4cGVjdCBpdCB0byBpZiB5b3UgZ2V0IHRoaXMgd3JvbmcuCgpgKClgIC0gcm91bmRlZCBicmFja2V0cyBhcmUgdXNlZCBleGNsdXNpdmVseSB0byBwZXJmb3JtIGZ1bmN0aW9ucywgb3IgZGVub3RlIHRoZSBvcmRlciBvZiBtYXRoZW1hdGljYWwgY2FsY3VsYXRpb25zCmBbXWAgLSBzcXVhcmUgYnJhY2tldHMgYXJlIHVzZWQgZm9yIGluZGV4aW5nIGFuZCBzdWJzZXR0aW5nCmB7fWAgLSBjdXJseSBicmFja2V0cyBhcmUgdXNlZCB0byBkZWZpbmUgYmxvY2tzIG9mIGNvZGUgaW4gZnVuY3Rpb25zIGFuZCBzdGF0ZW1lbnRzLiBXaGF0IEkgbWVhbiBieSB0aGlzIHdpbGwgYmVjb21lIGluY3JlYXNpbmdseSBhcHBhcmVudCBhcyB3ZSB3b3JrIHRocm91Z2ggdGhlIGJlbG93LgoKCiMjIEZvciBsb29wcwoKRGVzcGl0ZSBgaWYgZWxzZWAgc3RhdGVtZW50cyBiZWluZyBwZXJoYXBzIGVhc2llciB0byB3cmFwIG91ciBoZWFkcyBhcm91bmQsIHdlJ3JlIGdvaW5nIHRvIHN0YXJ0IHdpdGggYGZvcmAgbG9vcHMuIEVzc2VudGlhbGx5LCBhIGBmb3JgIGxvb3AgaXMgYSB3YXkgb2YgaXRlcmF0aW5nIHRocm91Z2ggYSBzZXQgb2YgdmFsdWVzLCBwZXJmb3JtaW5nIGEgZnVuY3Rpb24gb24gZWFjaCBpbiB0dXJuLiBUaGVzZSBsb29wcyBhcmUgcmVsYXRpdmVseSBzdHJhaWdodGZvcndhcmQgYW5kIGludHVpdGl2ZSBpbiBSLCBvbmNlIHlvdSBnZXQgdXNlZCB0byB1c2luZyB0aGVtLiAKClRoZSBzeW50YXggaXMsIG9mIGNvdXJzZSwgc2xpZ2h0bHkgZGlmZmVyZW50IHRvIFB5dGhvbiwgYnV0IHRoZSBiYXNpYyBjb25jZXB0IGlzIHRoZSBzYW1lLiBUeXBpY2FsbHksIGBmb3JgIGxvb3BzIGluIFIgYXJlIGEgbGl0dGxlIHNsb3cuIFRoZXJlJ3MgYSBtdWNoIHF1aWNrZXIgd2F5IG9mIHBlcmZvcm1pbmcgdGhlc2UgZnVuY3Rpb25zLCBidXQgd2Ugd29udCBnbyBpbnRvIHRoYXQgaGVyZSAtIGl0J3MgaW1wb3J0YW50IHRvIHVuZGVyc3RhbmQgaG93IHRoZSBsb29wcyB3b3JrIGZpcnN0LiAKCkxldCdzIHRyeSBvbmUuIFdlIHdhbnQgdG8gY3JlYXRlIGEgYmFzaWMgYGZvcmAgbG9vcCB3aGljaCB3aWxsIHByaW50IGFsbCBvZiB0aGUgbnVtYmVycyBmcm9tIDEgdG8gMTAuIFdlIGNvdWxkIG9mIGNvdXJzZSBkbyB0aGlzIHdpdGhvdXQgYSBsb29wLCBieSBhc3NpZ25pbmcgYW4gaW5kaXZpZHVhbCB2YWx1ZSB0byB4LCBhbmQgcHJpbnRpbmcgdGhlbSBpbiB0dXJuOgoKYGBge3J9CnggPC0gMQpwcmludCh4KQoKeCA8LSAyCnByaW50KHgpCgp4IDwtIDMKcHJpbnQoeCkKCiMgYW5kIHNvIG9uLi4uCmBgYAoKV2hhdCBpZiB3ZSB3YW50ZWQgdG8gYXV0b21hdGUgdGhpcz8gTGV0J3MgYnVpbGQgdGhhdCBiYXNpYyBgZm9yYCBsb29wLi4uCgpgYGB7cn0KZm9yICh4IGluIDE6MTApewogIHByaW50KHgpCn0KYGBgCgpCcmlsbGlhbnQsIGJ1dCBsZXQncyBnbyB0aHJvdWdoIGp1c3QgaG93IHRoYXQgd29ya3MuCgoqIGBmb3JgIC0gd2Ugc3RhcnQgd2l0aCB0aGUgYGZvcmAgc3RhdGVtZW50LiBJZiB5b3UgYXJlIHVzaW5nIGFuIElERSwgeW91IG1pZ2h0IG5vdGljZSB0aGF0IHRoaXMgc3RhdG1lbnQgY2hhbmdlcyBjb2xvdXIgdG8gZGVub3RlIHRoYXQgaXQgaXMgb25lIG9mIFIncyBwcm90ZWN0ZWQgY29udHJvbCBzdGF0ZW1lbnRzLgoqIGB4IGluIDE6MTBgIC0gd2Uga25vdyB0aGF0IDE6MTAgcHJvZHVjZXMgYSB2ZWN0b3Igb2YgYWxsIG9mIHRoZSBudW1iZXJzIGluIHNlcXVlbmNlIGZyb20gMSB0byAxMC4gdGhlIGB4IGluYCBiaXQganVzdCBtZWFucyAiZm9yIGV2ZXJ5IHZhbHVlIGluIHRoZSB2ZWN0b3Igb2YiLiBUaGUgeCBjb3VsZCBiZSBhbnl0aGluZyB5b3Ugd2FudCBpdCB0byBiZS4gZS5nLiBgZm9yIG51bWJlcnMgaW4gMToxMGAgd291bGQgeWVpbGQgdGhlIG5hbWUgcmVzdWx0LiBOb3RlIGhlcmUgdGhhdCBkaWZmZXJlbnQgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzIGZvbGxvdyBkaWZmZXJlbnQgY29udmVudGlvbnMtIGluIHB5dGhvbiB5b3UnbGwgb2Z0ZW4gc2VlIGBmb3JgIGxvb3BzIHdyaXR0ZW4gYXMgYGZvciBpIGluIDE6MTBgLiAKKiBge31gIC0gdGhlIGN1cmx5IGJyYWNrZXRzIGNvbnRhaW4gdGhlIGJvZHkgb2YgdGhlIGxvb3AuIFdoYXQgdGhhdCBtZWFucyBpcyB0aGF0IGFsbCBvZiB0aGUgdmFsdWVzIHdlIGhhdmUganVzdCBzcGVjaWZpZWQgYWJvdmUgd2lsbCBoYXZlIHRoZSBjb250ZW50cyBvZiB0aGUgYHt9YCBwZXJmb3JtZWQgb24gdGhlbS4gSGVyZSwgd2UndmUgdXNlZCB0aGUgYHByaW50KClgIGZ1bmN0aW9uLCB3aGljaCBqdXN0IHByaW50cyBvdXIgdmFsdWVzIHRvIHRoZSBjb25zb2xlLgoKU28sIHRoaXMgbG9vcCBhc3NpZ25zIHggYSB2YWx1ZSBvZiAxIC0gMTAgaW4gYSBzZXF1ZW5jZSwgYW5kIHByaW50cyBpdCB0byB0aGUgY29uc29sZS4KClRoaXMgaXMgYW4gZXhhbXBsZSBvZiBhIHN1cGVyIHNpbXBsZSBhbmQgc3RyYWlnaHRmb3J3YXJkIGNvbnRyb2wgc3RhdGVtZW50LiBXZSBjb3VsZCByZXBsYWNlIHRoZSAxOjEwIHdpdGggYW55dGhpbmcgd2UgbGlrZWQsIGFuZCB0aGUgbG9vcCB3b3VsZCBjeWNsZSB0aHJvdWdoIHRoZSB2YWx1ZXMgcHJlc2VudGVkIGl0IGluIHR1cm4gdW50aWwgaXQgcmVhY2hlZCB0aGUgZmluYWwgb25lLgoKTm93LCBwcmludGluZyB0aGUgbnVtYmVycyAxIHRvIDEwIGRvZXNuJ3Qgc2VlbSBvdmVybHkgdXNlZnVsLiBXaGF0IGlmIHdlIHdhbnQgdG8gcGVyZm9ybSBhIG1hdGhlbWF0aWNhbCBvcGVyYXRpb24gb24gYWxsIG9mIHRoZSBudW1iZXJzIGluIGEgc2VxdWVuY2UgcXVpY2tseT8gTGV0J3MgZXhwYW5kIG91ciBgZm9yYCBsb29wIHNvIHRoYXQgaXQgYWRkcyAxMCB0byBldmVyeSBudW1iZXIgaW4gdGhlIHNlcXVlbmNlLCBhbmQgcHJpbnRzIHRoZSByZXN1bHQgdG8gdGhlIGNvbnNvbGU6CgpgYGB7cn0KZm9yICh4IGluIDE6MTApewogIHByaW50KHggKyAxMCkKfQpgYGAKCkVhc3kgYXMgdGhhdC4gQWdhaW4sIHRoaXMgaXMgYSByZWFsbHkgYmFzaWMgZXhhbXBsZSBvZiBhIGBmb3JgIGxvb3AsIGp1c3Qgc28geW91IGNhbiBnZXQgdG8gZ3JpcHMgd2l0aCB0aGUgcHJpbmNpcGxlIG9mIGhvdyB0aGV5IHdvcmsgaW4gUi4gCgpXZSBjYW4gYWxzbyBjcmVhdGUgYGZvcmAgbG9vcHMgd2l0aCB2ZWN0b3JzIGNvbnNpc3Rpbmcgb2YgY2hhcmFjdGVyIHN0cmluZ3MgLSBsZXQncyBjcmVhdGUgb25lIHdpdGggNCBjb21wb25lbnRzOgpgYGB7cn0KeWVhcnMgPC0gYygiMjAxOSIsICIyMDIwIiwgIjIwMjEiLCAiMjAyMiIpCmBgYAoqUmVtZW1iZXIgd2hhdCB3aGVuIHdlIGNyZWF0ZSBjaGFyYWN0ZXIgc3RyaW5nIHZlY3RvcnMsIHdlIGhhdmUgdG8gaW5jbHVkZSB0aGUgYGMoKWAgZnVuY3Rpb24qCgpMZXQncyBwb3AgdGhlc2UgaW4gYSBsb29wIHRoYXQgd2lsbCBwcmludCB0aGUgc2VudGVuY2UgIlRoZSB5ZWFyIGlzIiBmb2xsb3dlZCBieSBlYWNoIG9mIHRoZSBsZXZlbHMgb2YgdGhlIHZlY3RvciBpbiB0dXJuCgpgYGB7cn0KeWVhcnMgPC0gYygiMjAxOSIsICIyMDIwIiwgIjIwMjEiLCAiMjAyMiIpCgpmb3IgKHggaW4geWVhcnMpewogIHkgPC0gcGFzdGUoIlRoZSB5ZWFyIGlzIiwgeCkKICBwcmludCh5KQp9CmBgYAoKVGhpcyBsb29wcyB0aHJvdWdoIHRoZSBmb3VyIHllYXJzIHdlIGhhdmUgZ2l2ZW4gaW4gdGhlIHZlY3RvciwgYW5kIHVzZXMgdGhlIGBwYXN0ZSgpYCBmdW5jdGlvbiB0byBzdGljayB0d28gY2hhcmFjdGVyIHN0cmluZ3MgdG9nZXRoZXIsIHByaW50aW5nIGVhY2ggb2YgdGhlIHZlY3RvciBlbGVtZW50cyBpbiB0dXJuLiBOb3RpY2UgdGhhdCB3ZSd2ZSBjcmVhdGVkIGEgbmV3IG9iamVjdCB3aXRoaW4gdGhlIGxvb3AsIGB5YCAtIGlmIHlvdSBsb29rIGluIHlvdXIgUiBlbnZpcm9ubWVudCB3aW5kb3csIG9yIHRyeSBhbmQgcHJpbnQgeSB0byB0aGUgY29uc29sZSB3aXRoIGBwcmludCh5KWAsIHlvdSdsbCBzZWUgdGhhdCB5IGlzIHN0b3JlZCBhcyAiVGhlIHllYXIgaXMgMjAyMiIsIHdoaWNoIGlzIHRoZSBmaW5hbCBpdGVyYXRpb24gb2YgdGhlIGxvb3AuIEl0J3MgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCB0aGUgb3RoZXIgaXRlcmF0aW9ucyBhcmUgbm90IHN0b3JlZCBpbiB0aGUgd2lkZXIgUiBlbnZpcm9ubWVudCwgYXMgdGhlIGxvb3Agb3ZlcndyaXRlcyBpdHNlbGYgZXZlcnkgdGltZSBpdCBwZXJmb3JtcyBhbiBpdGVyYXRpb24uCgpKdXN0IHRvIHJlY2FwLGEgYGZvcmAgbG9vcCBydW5zIHRocm91Z2ggdmFsdWVzIGluIGEgdmVjdG9yIChhbmQgaXMgcXVpY2sgaW4gdGhlc2Ugc21hbGwgdG95IGV4YW1wbGVzISksIGFuZCBkb2VzIHNvbWUgd29yayBmb3IgeW91IGluc2lkZSB0aGUgc3RhdGVtZW50LiBDdXJseSBicmFja2V0cyBge31gIGRlbm90ZSB0aGUgYm9keSBvZiB0aGUgbG9vcCwgd2hpY2ggaXMgd2hlcmUgd2UgdGVsbCBSIHdoYXQgd2Ugd2FudCBpdCB0byBkbyB3aXRoIG91ciBpbnB1dC4gV2hpbHN0IGZvciBsb29wcyBhcmUgZ3JlYXQsIGV2ZXJ5IGV4YW1wbGUgdGhhdCB3ZSd2ZSBqdXN0IHJ1biB0aHJvdWdoIGNhbiBhY3R1YWxseSBiZSBhY2hlaXZlZCB3aXRoIHNpbXBsZXIsIGFuZCBtb3JlIGNvbXB1dGF0aW9uYWxseSBlZmZpY2llbnQgY29kZSAoc29ycnkpLiBSZW1lbWJlciB0byB0aGluayBhYm91dCB5b3VyIGNvZGUsIGFuZCBjb25zaWRlciB3aGV0aGVyIHRoZXJlIG1pZ2h0IGJlIGVhc2llciBzb2x1dGlvbnMgdG8gYSBwcm9ibGVtIQoKIyMgVmVjdG9yaXNhdGlvbiBhcyBhIG1vcmUgZWZmaWNpZW50IG1lY2hhbmlzbT8KCkZvciBvdXIgZmlyc3QgZXhhbXBsZSwgcHJpbnRpbmcgMSAtIDEwIHRvIHRoZSBzY3JlZW4gd2l0aCBhIGxvb3AsIHdlIGNvdWxkIHNhdmUgYSBsb3Qgb2YgdGltZSBieSBleHBsaWNpdGx5IHBvcHBpbmcgeCBpbnRvIGl0J3Mgb3duIHZlY3RvciAocmF0aGVyIHRoYW4gYWRkaW5nIHRoaXMgdG8gdGhlIGNvbmRpdGlvbnMgb2YgYSBgZm9yYCBsb29wKSwgYW5kIGRlYWxpbmcgd2l0aCBpdCB0aGF0IHdheToKCmBgYHtyfQp4IDwtIDE6MTAKcHJpbnQoeCkKYGBgCgpBcyB5b3UgY2FuIHNlZSwgdGhpcyB1bHRpbWF0ZWx5IHlpZWxkcyB0aGUgc2FtZSByZXN1bHQsIHdpdGggY29uc2lkZXJhYmx5IGxlc3MgZmFmZmluZy4gSW4gdGhlc2Ugc21hbGwgdG95IGV4YW1wbGVzLCB0aGVyZSBpc24ndCBhIHdob2xlIGxvdCBvZiBkaWZmZXJlbmNlIGluIGNvbXB1dGF0aW9uIHRpbWUsIGJ1dCBpbiBtdWNoIGxhcmdlciBkYXRhc2V0cywgdGhpcyBpcyBjZXJ0YWlubHkgc29tZXRoaW5nIHdvcnRoIGNvbnNpZGVyaW5nLiBHZW5lcmFsbHksIHZlY3RvcmlzYXRpb24gaXMgbXVjaCBzcGVlZGllciB0aGFuIGZvciBsb29wcy4KCkZvciB0aGUgZXhhbXBsZSB3aGVyZSB3ZSBhZGRlZCAxMCB0byB4LCB3ZSBjYW4gdXNlIHRoZSBzYW1lIHZlY3RvcmlzYXRpb24gcHJpbmNpcGxlLiBUaGlzIGlzIHdoZXJlIFIgZGlmZmVycyBpbiBpdCdzIGZ1bmRlbWVudGFsIGRldiBtYWtldXAgdG8sIGZvciBleGFtcGxlLCBiYXNoLCB3aGVyZSB5b3Ugd291bGQgKipoYXZlKiogdG8gZG8gYSBgZm9yYCBsb29wIHRvIHBlcmZvcm0gdGhlIGZvbGxvd2luZzoKCmBgYHtyfQp4IDwtIDE6MTAgIyByZWNyZWF0ZSBvdXIgMToxMCB2ZWN0b3IKcHJpbnQoeCArIDEwKQpgYGAKCkhlcmUsIHlvdSBkb24ndCBldmVuIG5lZWQgdGhlIGBwcmludCgpYCBmdW5jdGlvbiwganVzdCB0eXBpbmcgYHggKyAxMGAgd291bGQgYmUgc3VmZmljaWVudCEKCllvdSBkb24ndCBldmVuIHJlYWxseSBuZWVkIHRvIHVzZSBsb29wcyBvbiBjaGFyYWN0ZXIgdmVjdG9ycyBpbiBSISBMZXQncyBnbyBiYWNrIHRvIG91ciAidGhlIHllYXIgaXMiIGV4YW1wbGUuIFdlIGNhbiBhdm9pZCBhIGxvb3AgYnkgdXNpbmcgdGhlIGBwYXN0ZSgpYCBmdW5jdGlvbiBvbiB0aGUgdmVjdG9yIGV4cGxpY2l0bHksIHJhdGhlciB0aGFuIGhhdmluZyB0byBmb3JjZSBpdCB0aHJvdWdoIGEgbG9vcDoKCmBgYHtyfQp5ZWFycyA8LSBjKCIyMDE5IiwgIjIwMjAiLCAiMjAyMSIsICIyMDIyIikKcGFzdGUoIlRoZSB5ZWFyIGlzIiwgeWVhcnMpCmBgYAoKIyMgU28gd2h5IGJvdGhlciB3aXRoIGZvciBsb29wcyBpbiB0aGUgZmlyc3QgcGxhY2U/CgpBbGwgb2YgdGhpcyBpcyBub3QgdG8gc2F5IHRoYXQgYGZvcmAgbG9vcHMgYXJlIHJ1YmJpc2ggYW5kIHVzZWxlc3MgaW4gUiAtIGluIGZhY3QgdGhlcmUgd2lsbCBsaWtlbHkgYmUgdGltZXMgd2hlcmUgdGhleSBhcmUgdW5hdm9pZGFibGUsIGFuZCBhIHZlY3RvciBiYXNlZCBzb2x1dGlvbiBqdXN0IHdvbid0IGN1dCBpdC4gSXQgaXMgaG93ZXZlciB3b3J0aCBoYW1tZXJpbmcgaG9tZSB0aGUgcG9pbnQgdGhhdCB0aGV5IGFyZSByZWFsbHkgd29ydGggdGhpbmtpbmcgYWJvdXQgcXVpdGUgY2FyZWZ1bGx5LiBUaGVyZSB3aWxsIG9mdGVuIGJlIGEgYmV0dGVyIHdheSB0byBkbyB3aGF0ZXZlciB5b3UncmUgdHJ5aW5nIHRvIGRvIC0gc2xvdyBkb3duIHdoZW4geW91J3JlIGNvZGluZy4gU3RvcCBhbmQgdGhpbmsgYWJvdXQgd2hhdCBpdCBpcyB5b3UncmUgdHJ5aW5nIHRvIGFjaGlldmUuIEJlZ2lubmVycyBpbiBwYXJ0aWN1bGFyIHRlbmQgdG8gbGVhcm4gaG93IHRvIGNyZWF0ZSBgZm9yYCBsb29wcywgYW5kIHRoZW4gdXNlIHRoZW0gZm9yIGV2ZXJ5dGhpbmcsIHdoZW4gb2Z0ZW4sIGEgdmVjdG9yIGJhc2VkIHNvbHV0aW9uIHdvdWxkIGJlIG11Y2ggcXVpY2tlciBhbmQgc2ltcGxlciEKCgojIGBJZmAgc3RhdGVtZW50cwoKTm93LCBvbiB0byBgaWZgIHN0YXRlbWVudHMuIFRoZXNlIGFyZSBhbm90aGVyIGNvbnRyb2wgZmxvdyBjb2RpbmcgbWVjaGFuaXNtIHlvdSBjYW4gdXNlIGluIFIgYW5kIGZ1cnRoZXIgYWZpZWxkIHRvIGN1c3RvbWlzZSB0aGUgb3JkZXIgdGhhdCBjb21tYW5kcyBhcmUgcnVuIGluLCBkZXBlbmRpbmcgb24gY29uZGl0aW9ucyBvZiB5b3VyIGRhdGEuIFRoaW5rIGFib3V0IHRoZSBrZXR0bGUgZXhhbXBsZSAtICoqSUYqKiB5b3VyIHdhdGVyIGJvaWxlZCwgdGhlbiB5b3UgcGVyZm9ybSB0aGUgdGFzay4gYGlmYCBzdGF0ZW1lbnRzIGFzayB3aGV0aGVyIGEgY29uZGl0aW9uIGhhcyBiZWVuIG1ldCwgYmVmb3JlIHRoZXkgcGVyZm9ybSBhIGZ1bmN0aW9uLiBUaGUgYmVzdCB3YXkgdG8gZXhwbGFpbiB0aGlzIGlzLCBhcyBhbHdheXMsIHdpdGggYW4gZXhhbXBsZToKYGBge3J9CnogPC0gMQppZiAoeiA8IDEwKXsKICBwcmludCgieiBpcyBsZXNzIHRoYW4gMTAiKQp9CmBgYAoKV2UgY2FuIHNlZSB0aGF0IGJlY2F1c2Ugd2UndmUgZ2l2ZW4gYHpgIHRoZSB2YWx1ZSBvZiAxLCB3aGljaCBpcyBsZXNzIHRoYW4gMTAsIHdlIGdldCBhbiBvdXRwdXQgdGVsbGluZyB1cyBzbyAoUiBpcyBwZXJmb3JtaW5nIHRoZSBmdW5jdGlvbiEpLiBXaGF0IGhhcHBlbnMgaWYgd2UgY2hhbmdlIHRoZSBhc3NpZ25tZW50IG9mIGB6YCBhbmQgdHJ5IGFnYWluPwoKYGBge3J9CnogPC0gNDUKaWYgKHogPCAxMCl7CiAgcHJpbnQoInogaXMgbGVzcyB0aGFuIDEwIikKfQpgYGAKCldlIGRvbid0IGdldCBhbiBvdXRwdXQuIEJlY2F1c2UgdGhlIGNvbmRpdGlvbiB3YXMgbm90IG1ldCwgbm8gZnVuY3Rpb24gd2FzIHBlcmZvcm1lZCBvbiBvdXIgZGF0YS4KClRoZSB3YXkgdGhhdCB0aGlzIGlzIGNvZGVkIGluIFIgaXMgdGhhdCB0aGUgcHJvdmlkZWQgY29uZGl0aW9uIChpbiBgKClgKSBpcyBydW4sIHRvIGdpdmUgYSBsb2dpY2FsIG91dHB1dC4gSWYgdGhhdCBvdXRwdXQgaXMgYFRSVUVgLCB0aGUgYm9keSBvZiB0aGUgZnVuY3Rpb24gKGluIGB7fWApIGlzIHJ1bi4gSWYgdGhlIG91dHB1dCBpcyBgRkFMU0VgLCBub3RoaW5nIHdpbGwgaGFwcGVuLiAKCiMgYGVsc2VgIHN0YXRlbWVudHMKCkl0IGlzbid0IGEgaHVnZSBsZWFwIHRvIGFzayB3aGV0aGVyIHdlIGNvdWxkIHRha2UgdGhlIGFib3ZlIGFuZCBwZXJmb3JtIGEgZGlmZmVyZW50IGZ1bmN0aW9uIGlmIHRoZSBjb25kaXRpb24gd2FzIG5vdCBtZXQsIGFuZCB0aGUgbG9naWNhbCBvdXRwdXQgd2FzIGBGQUxTRWAuIFdlIGNhbiBhY2hpZXZlIHRoaXMgYnkgcGFpcmluZyBvdXIgYGlmYCBzdGF0ZW1lbnQgd2l0aCBhbiBgZWxzZWAgc3RhdGVtZW50LiBUaGUgc3ludGF4IG9mIHRoaXMgY2FuIHRha2UgYSBsaXR0bGUgZ2V0dGluZyB1c2VkIHRvLCBiZWNhdXNlIGl0IHBhaXJzIHR3byBzZXRzIG9mIGB7fWAgc2VwYXJhdGVkIGJ5IGFuIGBlbHNlYCBzdGF0ZW1lbnQuIExldCdzIGRlbW9uc3RyYXRlOgoKYGBge3J9CnogPC0gMQoKaWYgKHogPCAxMCl7CiAgcHJpbnQoInogaXMgbGVzcyB0aGFuIDEwIikKfSBlbHNlIHsKICBwcmludCgieiBpcyBtb3JlIHRoYW4gMTAiKQp9CmBgYAoKV2l0aCBhbiBpbnB1dCBvZiAxLCB3ZSBnZXQgYSBwcmludGVkIG1lc3NhZ2UgdGVsbGluZyB1cyB0aGF0IHogaXMgbGVzcyB0aGFuIDEwLiBXaGF0IGlmIHdlIGNoYW5nZSB6IHRvIGJlIGdyZWF0ZXIgdGhhbiAxMD8KCmBgYHtyfQp6IDwtIDIwCgppZiAoeiA8IDEwKXsKICBwcmludCgieiBpcyBsZXNzIHRoYW4gMTAiKQp9IGVsc2UgewogIHByaW50KCJ6IGlzIG1vcmUgdGhhbiAxMCIpCn0KYGBgCgpBcyBleHBlY3RlZCwgUiB0ZWxscyB1cyB0aGF0IHogaXMgbW9yZSB0aGFuIDEwLiBUaGlzIGNvbWJpbmF0aW9uIG9mIGBpZmAgYW5kIGBlbHNlYCBzdGF0ZW1lbnRzIHJ1bnMgYSBjb250cm9sIGZsb3cgdGhhdCB0YWtlcyBhbiBpbnB1dCwgYW5kIGlmIGEgY29uZGl0aW9uIGlzIG1ldCwgcnVucyBmdW5jdGlvbiBhLiBJZiB0aGUgY29uZGl0aW9uIGlzIG5vdCBtZXQsIGl0IHJ1bnMgZnVuY3Rpb24gYi4gVGhpcyBiYXNpYyBwcmluY2lwbGUgYWxsb3dzIHlvdSB0byBwZXJmb3JtIHNsaWdodGx5IG1vcmUgY29tcGxleCBmdW5jdGlvbnMgb3IgYW5hbHlzZXMsIGJhc2VkIG9uIHRoZSBpbnB1dCB0aGF0IHlvdSBnaXZlLgoKIyBUaGUgYGlmZWxzZSgpYCBmdW5jdGlvbgoKVGhlcmUgaXMgYW4gYWx0ZXJuYXRpdmUgdG8gYGlmYCBhbmQgYGVsc2VgIGNvbnRyb2wgZmxvdyBmdW5jdGlvbnMgaW4gUiAtIHRoZSBgaWZlbHNlKClgIGZ1bmN0aW9uLiBUaGlzIGRvZXNuJ3QgYWx3YXlzIHBlcmZvcm0gaW4gcXVpdGUgdGhlIHdheSB0aGF0IHlvdSBtaWdodCBleHBlY3QsIGJ1dCBpdCdzIGNlcnRhaW5seSBhbiBvcHRpb24gdG8gY29uc2lkZXIuIFRoZSBzeW50YXggaXMgcGVyaGFwcyBhIGxpdHRsZSBtb3JlIGZhbWlsaWFyIHRoYW4gdGhlIGNvbnRyb2wgZmxvdyBzdGF0ZW1lbnRzLi4uIExldCdzIHBlcmZvcm0gdGhlIHNhbWUgdGhpbmcgd2UganVzdCBkaWQsIGJ1dCB0aGlzIHRpbWUgdXNpbmcgYW4gYGlmZWxzZSgpYCBmdW5jdGlvbjoKCmBgYHtyfQp6IDwtIDEKaWZlbHNlKHogPCAxMCwgImxlc3MgdGhhbiAxMCIsICJtb3JlIHRoYW4gMTAiKQpgYGAKCgpgYGB7cn0KeiA8LSAyMAppZmVsc2UoeiA8IDEwLCAibGVzcyB0aGFuIDEwIiwgIm1vcmUgdGhhbiAxMCIpCmBgYAoKR3JlYXQuIEFsbCB3b3JrcyB0aGUgc2FtZSBzbyBmYXIhIFRoZSBgaWZlbHNlKClgIGZ1bmN0aW9uIHRha2VzIGFuIGlucHV0LCBldmFsdWF0ZXMgaXQgYWdhaW5zdCBhIGNvbmRpdGlvbiAoaGVyZSB0aGF0IGl0IGlzIDwgMTApLiBJZiB0aGUgY29uZGl0aW9uIGlzIGBUUlVFYCwgaXQgcGVyZm9ybXMgdGhlIGZpcnN0IG9wdGlvbiwgaWYgYEZBTFNFYCwgZG9lcyB0aGUgMm5kLiAKCkhlbHBmdWxseSwgd2UgY2FuIGFsc28gcGVyZm9ybSB0aGUgYGlmZWxzZSgpYCBmdW5jdGlvbnMgb24gYSB2ZWN0b3IuIExldCdzIGNyZWF0ZSBhIG51bWVyaWMgdmVjdG9yIGZyb20gMSAtIDYwIGluIHN0ZXBzIG9mIDYgYW5kIHJ1biBvdXIgZnVuY3Rpb24gYWdhaW4KCmBgYHtyfQp6IDwtIHNlcShmcm9tID0gMSwgdG8gPSA2MCwgYnkgPSA2KQppZmVsc2UoeiA8IDEwLCAibGVzcyB0aGFuIDEwIiwgIm1vcmUgdGhhbiAxMCIpCmBgYAoKV2UgZW5kIHVwIHdpdGggMTAgb3V0cHV0cywgZWFjaCB0ZWxsaW5nIHVzIHdoZXRoZXIgYSByZXN1bHQgaXMgbGVzcyBvciBtb3JlIHRoYW4gMTAhCgpgYGB7cn0KeiA8LSBzZXEoZnJvbSA9IDEsIHRvID0gNjAsIGJ5ID0gNikKCmlmICh6IDwgMTApewogIHByaW50KCJ6IGlzIGxlc3MgdGhhbiAxMCIpCn0gZWxzZSB7CiAgcHJpbnQoInogaXMgbW9yZSB0aGFuIDEwIikKfQpgYGAKCllvdSBjYW4gc2VlIGZyb20gdGhlIGVycm9yIGFib3ZlLCB0aGF0IHlvdSBjYW4ndCBwZXJmb3JtIGBpZmAgYGVsc2VgIHN0YXRlbWVudHMgb24gYSB2ZWN0b3IgLSB0aGUgY29uZGl0aW9uIGlzIG9ubHkgZXhwZWN0aW5nIHNvbWV0aGluZyB3aXRoIGEgbGVuZ3RoIG9mIDEsIHJhdGhlciB0aGFuLCBpbiB0aGlzIGNhc2UsIDEwLgoKCldlIGNhbiB1c2UgYGlmZWxzZSgpYCBvbiBjaGFyYWN0ZXIgdmVjdG9ycyB0b28uIExldCdzIGNyZWF0ZSBvbmUgYW5kIHRyeSBpdCBvdXQ6CgpgYGB7cn0KY291bnRyaWVzIDwtIGMoIlVLIiwgIlVTQSIsICJGcmFuY2UiLCAiU3BhaW4iKQppZmVsc2UoY291bnRyaWVzID09ICJVSyIsICJVSyIsICJFbHNld2hlcmUiKQoKYGBgCgpUaGUgZnVuY3Rpb24gaXMgZXZhbHVhdGluZyB0byBzZWUgaWYgdGhlIGlucHV0IG1hdGNoZXMgdGhlIHN0cmluZyAiVUsiLCBhbmQgaWYgaXQgZG9lcywgd2lsbCBwcmludCAiVUsiLCBvdGhlcndpc2UsIHByaW50cyAiRWxzZXdoZXJlIi4gRmFpcmx5IHN0cmFpZ2h0Zm9yd2FyZCBzdHVmZiEKCgojIFdyaXRpbmcgeW91ciBvd24gZnVuY3Rpb25zOgoKV3JpdGluZyB5b3VyIG93biBmdW5jdGlvbnMgaXMgYW4gaW1wb3J0YW50IHBhcnQgb2YgcHJvZ3JhbW1pbmcuIEl0IGtlZXBzIGNvZGUgc2ltcGxlIGFuZCByZWFkYWJsZSwgYW5kIGFsbG93cyB5b3UgdG8gcGVyZm9ybSBhIHNldCBvZiB0YXNrcyBtdWx0aXBsZSB0aW1lcyB3aXRob3V0IGxvYWRzIG9mIGR1cGxpY2F0aW9uIGluIHlvdXIgY29kZS4gSWYgeW91IHdhbnRlZCB0byBkZXZlbG9wIHlvdXIgb3duIHBhY2thZ2UsIGN1c3RvbSBmdW5jdGlvbiBjcmVhdGlvbiB3b3VsZCBiZSBhIGh1Z2UgcGFydCBvZiB0aGlzIC0gYSBwYWNrYWdlIGlzIGVzc2VudGlhbGx5IGp1c3QgYSBjb2xsZWN0aW9uIG9mIGZ1bmN0aW9ucyEKClRoZSBwcm9jZXNzIG9mIGNyZWF0aW5nIGZ1bmN0aW9ucyBpcyBxdWl0ZSBzdHJhaWdodGZvcndhcmQgLSBJIGRvIGl0IGxvYWRzIHRvIG1ha2UgbXkgbGlmZSBxdWljayBhbmQgZWFzeS4gTGV0J3Mgc3RhcnQgYnkgY3JlYXRpbmcgYSBzaW1wbGUgZnVuY3Rpb24gdGhhdCBhZGRzIDEwIHRvIGFueSBudW1lcmljIGlucHV0OgoKYGBge3J9CmFkZF90ZW4gPC0gZnVuY3Rpb24oeCl7CiAgeSA8LSB4ICsgMTAKICByZXR1cm4oeSkKfQoKYWRkX3RlbigxKQpgYGAKClNvLCBoZXJlLCB3ZSd2ZSBjcmVhdGVkIGFuZCB0ZXN0ZWQgYSBiYXNpYyBmdW5jdGlvbi4gTGV0J3MgZGlzc2VjdCBpdCBhIGxpdHRsZToKCiogYGFkZF90ZW5gIC0gZmlyc3QsIHdlIGhhdmUgdG8gZ2l2ZSBvdXIgbmV3IGZ1bmN0aW9uIGEgbmFtZS4gSSd2ZSBpbWFnaW5hdGl2ZWx5IGNhbGxlZCB0aGlzIG9uZSBhZGRfdGVuLiAKKiBUaGVuLCB3ZSBhc3NpZ24gdGhlIHJlc3Qgb2YgdGhlIGNvZGUgdG8gdGhlIG5ldyBmdW5jdGlvbiBuYW1lIHdpdGggb3VyIGFzc2lnbm1lbnQgYXJyb3cgYDwtYAoqIE5leHQgdXAsIHdlIGhhdmUgdGhlIGBmdW5jdGlvbmAgZnVuY3Rpb24uIFRoaXMgdGVsbHMgUiB0aGF0IHdlIHdhbnQgdG8gdHVybiBvdXIgZnVuY3Rpb24gbmFtZSBpbnRvIGEgbmV3IGZ1bmN0aW9uCiogYGZ1bmN0aW9uKHgpYCAtIHRoaXMgdGVsbHMgUiB0aGF0IHdlIGFyZSBjcmVhdGluZyBhIGZ1bmN0aW9uIHdpdGggYSBzaW5nbGUgYXJndW1lbnQgKG9yIGlucHV0KSwgeC4KKiBge31gIHRoaXMgZGVub3RlcyB0aGUgYm9keSBvZiB0aGUgZnVuY3Rpb24gLSB3aGF0ZXZlciBjb2RlIGlzIGluIGhlcmUgaXMgd2hhdCB3aWxsIGJlIGFwcGxpZWQgdG8gYW4gaW5wdXQKKiBgeSA8LSB4ICsgMTBgIC0gdGhpcyBiaXRzIG9idmlvdXMgLSBhZGQgMTAgdG8gb3VyIGlucHV0IG9mIHggYW5kIGFzc2lnbiBpdCBhIG5ldyBuYW1lLCBgeWAuCiogYHJldHVybih5KWAgLSBnaXZlIHVzIGFuIG91dHB1dCEgV2l0aG91dCB0aGlzLCBSIHdvdWxkbid0IGF1dG9tYXRpY2FsbHkgdGVsbCB1cyB3aGF0IHRoZSBvdXRwdXQgb2Ygd2hhdGV2ZXIgd2UndmUganVzdCBhc2tlZCBpdCB0byBkbyBpcyEKCk5vdGljZSBoZXJlIHRoYXQgdGhlIG5ldyBgeWAgb2JqZWN0IGlzIHRyZWF0ZWQgYSBsaXR0bGUgZGlmZmVyZW50bHkgaW4gZnVuY3Rpb25zIHRoYW4gbG9vcHMuIElmIHdlIHJlbW92ZSBgeWAgZnJvbSBvdXIgZW52aXJvbm1lbnQgYW5kIHJ1biB0aGUgZnVuY3Rpb24gYWdhaW4sIHlvdSdsbCBub3RpY2UgdGhhdCBpdCBkb2VzIG5vdCByZS1hcHBlYXIuIFdoYXRldmVyIG9iamVjdHMgeW91IGNyZWF0ZSB3aXRoaW4gdGhlIGJvZHkgb2YgdGhlIGZ1bmN0aW9uIGV4aXN0IG9ubHkgd2l0aGluIHRoYXQgZnVuY3Rpb24gLSB0aGV5IGFyZSBub3QgY2FsbGFibGUgdG8gdGhlIHdpZGVyIFIgZW52aXJvbm1lbnQuCgpGdW5jdGlvbnMgY2FuIGFsc28gdGFrZSBhIHZlY3RvciBpbnB1dCAtIGxldCdzIHJ1biBvdXIgYGFkZF90ZW4oKWAgZnVuY3Rpb24gd2l0aCBhIHZlY3RvciBhbmQgc2VlIHdoYXQgaGFwcGVucwoKYGBge3J9CmFkZF90ZW4gPC0gZnVuY3Rpb24oeCl7CiAgeSA8LSB4ICsgMTAKICByZXR1cm4oeSkKfQoKeiA8LSAxOjEwCmFkZF90ZW4oeikKYGBgCgpPZiBjb3Vyc2UsIHdlIGNvdWxkIHBlcmZvcm0gdGhpcyBmdW5jdGlvbiBtYW51YWxseSwgYXMgaXQgaXMgYSByZWFsbHkgc3RyYWlnaHRmb3J3YXJkIGV4YW1wbGUuIEknZCBiZSB1bmxpa2VseSB0byBib3RoZXIgY3JlYXRpbmcgYSBmdW5jdGlvbiB0byBkbyB0aGlzIGluIHByYWN0aWNlLCBidXQgaXQncyBhIHVzZWZ1bCBkZW1vbnN0cmF0aW9uLiAKCgojIFRoZSBhbmF0b215IG9mIGEgZnVuY3Rpb24KCkxldCdzIHF1aWNrbHkgcmVjYXAgdGhlIGFuYXRvbXkgb2YgaG93IGEgZnVuY3Rpb24gd29ya3MKCmBmdW5jdGlvbih4KWAgZGVjbGFyZXMgYSBmdW5jdGlvbi4gSXQgY3JlYXRlcyB0aGUgZnVuY3Rpb24gd2l0aGluIHRoZSBSIGVudmlyb25tZW50LCBhbmQgZGVmaW5lcyB0aGUgYXJndW1lbnRzIHRoYXQgdGhlIGZ1bmN0aW9uIHJlcXVpcmVzLiBJbiBvdXIgZXhhbXBsZSBhYm92ZSwgd2hlbmV2ZXIgeW91IHJ1biBgYWRkX3RlbmAsIHlvdSAqbXVzdCogaGF2ZSBhbiB4IGFyZ3VtZW50LCBvdGhlcndpc2UgdGhlIGZ1bmN0aW9uIHdpbGwgbm90IHJ1bi4KCmB7fWAgZGVmaW5lIHRoZSBibG9jayBvZiBjb2RlIHdpdGhpbiB3aGljaCB0aGUgd29yayB0aGF0IHRoZSBmdW5jdGlvbiBkb2VzIHRha2VzIHBsYWNlLiBIZXJlLCBgeWAgaXMgb25seSBkZWZpbmVkIHdpdGhpbiB0aGUgZnVuY3Rpb24uCgpgcmV0dXJuKHkpYCB0ZWxscyBSIHRvIGdpdmUgdXMgYW4gb3V0cHV0LCBhbmQgZGlzcGxheSB3aGF0IHRoZSBmdW5jdGlvbiBoYXMgZG9uZS4KCgojIEZ1bmN0aW9ucyB3aXRoIG11bHRpcGxlIGFyZ3VtZW50cwoKV2UgY2FuIGV4dGVuZCBvdXIgZnVuY3Rpb25zIHRvIHRha2UgbXVsdGlwbGUgYXJndW1lbnRzLCBvciBpbnB1dHMsIHVzaW5nIHRoZSBiYXNpY3MgdGhhdCB3ZSd2ZSBqdXN0IGxlYXJuZWQuIEZ1bmN0aW9ucyB0aGF0IHdlIGhhdmUgdXNlZCB0aHJvdWdob3V0IHRoZSBjb3Vyc2Ugc28gZmFyIGhhdmUgdGFrZW4gbXVsdGlwbGUgYXJndW1lbnRzLCBzbyBsZXQncyB0cnkgYW5kIGFsc28gY3JlYXRlIG9uZS4gV2UnbGwgd3JpdGUgYSBmdW5jdGlvbiB0aGF0IG11bHRpcGxpZXMgdHdvIG51bWJlcnMgdG9nZXRoZXI6CmBgYHtyfQptdWx0aXBseSA8LSBmdW5jdGlvbih4LCB5KXsKICB6IDwtIHggKiB5CiAgcmV0dXJuKHopCn0KCm11bHRpcGx5KDMsMikKYGBgCgpJbiBvdXIgUiBlbnZpcm9ubWVudCB3aW5kb3csIHdlIGNhbiBzZWUgYSBuZXcgc2VjdGlvbiBoYXMgYmVlbiBjcmVhdGVkIGNhbGxlZCAnRnVuY3Rpb25zJy4gV2l0aGluIHRoYXQsIHdlIGNhbiBzZWUgYm90aCBvdXIgYGFkZF90ZW5gIGFuZCBvdXIgYG11bHRpcGx5YCBmdW5jdGlvbnMsIGFuZCB0aGUgbnVtYmVyIG9mIGFyZ3VtZW50cyB0aGF0IGVhY2ggdGFrZXMuIAoKIyBGdW5jdGlvbnMgd2l0aCBkZWZhdWx0IGFyZ3VtZW50cwoKWW91J2xsIGZpbmQgb2Z0ZW4gdGhhdCBzZXZlcmFsIGFyZ3VtZW50cyBpbiBmdW5jdGlvbnMgdGhhdCB5b3UncmUgcnVubmluZyBpbiBSIGhhdmUgZGVmYXVsdCBzZXR0bmdzIHRoYXQgeW91IGRvIG5vdCBoYXZlIHRvIGV4cGxpY2l0bHkgY29kZSBpbiBvcmRlciBmb3IgUiB0byBwZXJmb3JtIHRoZW0uIEZvciBleGFtcGxlLCBpbiB0aGUgYHN1bSgpYCBhbmQgYG1lYW4oKWAgZnVuY3Rpb25zLCB0aGUgZGVmYXVsdCBmb3IgdGhlIGBuYS5ybWAgYXJndW1lbnQgaXMgYEZBTFNFYC4gV2UgY2FuIGVkaXQgb3VyIGBtdWx0aXBseSgpYCBmdW5jdGlvbiB0byBoYXZlIGEgZGVmYXVsdCBgeWAgdmFsdWUgb2YgMTA6CgpgYGB7cn0KbXVsdGlwbHkgPC0gZnVuY3Rpb24oeCwgeSA9IDEwKXsKICB6IDwtIHggKiB5CiAgcmV0dXJuKHopCn0KCm11bHRpcGx5KDMpCm11bHRpcGx5KDMsIDIpCmBgYAoKSGVyZSwgd2UgY2FuIHNlZSB0aGF0IGlmIHdlIGluY2x1ZGUgb25seSAxIGFyZ3VtZW50IHRvIHRoZSBmdW5jdGlvbiBub3csIGl0IHdpbGwgcnVuIGFuZCB1c2UgdGhlIGRlZmF1bHQgb2YgeSA9IDEwLiBJZiB3ZSBpbmNsdWRlIHR3byBhcmd1bWVudHMgb3Vyc2VsdmVzLCB3ZSBvdmVycmlkZSB0aGUgZGVmYXVsdCBhbmQgdGhlIGZ1bmN0aW9uIHBlcmZvcm1zIG9uIGJvdGggb2YgdGhlIGFyZ3VtZW50cyB0aGF0IHdlIGhhdmUgc3BlY2lmaWVkLiBZb3UgY2FuIGhvcGVmdWxseSBzZWUgaG93IHdyaXRpbmcgZnVuY3Rpb25zIHdpdGggbXVsdGlwbGUgYXJndW1lbnRzIGFuZCBkZWZhdWx0cyBpc24ndCB0b28gbXVjaCBvZiBhIHN0cmV0Y2ggZnJvbSB3cml0aW5nIGEgZnVuY3Rpb24gd2l0aCBhIHNpbmdsZSBhcmd1bWVudCwgYW5kIHNlZSBob3cgdXNlZnVsIHRoYXQgbWlnaHQgYmUgaW4geW91ciBjb2RpbmchCgojIENvbWJpbmluZyBmdW5jdGlvbnMgYW5kIGNvbmRpdGlvbmFsczoKCk5vdywgd2UgY2FuIGNvbWJpbmUgYWxsIG9mIHRoZSBza2lsbHMgdGhhdCB3ZSd2ZSBsZWFybmVkIHRvZGF5IGFuZCBjcmVhdGUgY29tcGxleCBmdW5jdGlvbnMgd2l0aCBzb21lIGNvbnRyb2wgZmxvdyBzdGF0ZW1lbnRzIGluc2lkZSBvZiB0aGVtLiBMZXQncyBzdGFydCBieSB3dGl0aW5nIGEgZnVuY3Rpb24gdGhhdCBldmFsdWF0ZXMgd2hldGhlciBhIG51bWVyaWNhbCBpbnB1dCBpcyBncmVhdGVyIHRoYW4gb3IgbGVzcyB0aGFuIDEwLiAKCmBgYHtyfQpldmFsMTAgPC0gZnVuY3Rpb24oeCl7CiAgeSA8LSBpZmVsc2UoeCA8IDEwLCAibGVzcyB0aGFuIDEwIiwgImdyZWF0ZXIgdGhhbiAxMCIpCiAgcmV0dXJuKHkpCn0KCmV2YWwxMCgxKQpldmFsMTAoMTUpCgpgYGAKCldlJ3ZlIGluY2x1ZGVkIGEgc2ltcGxlIGlmZWxzZSBmdW5jdGlvbiB3aXRoaW4gb3VyIGV2YWwxMCBmdW5jdGlvbiwgd2hpY2ggdGFrZXMgYSBuZXcgb2JqZWN0LCB5LCBhbmQgcGVyZm9ybXMgYW4gaWZlbHNlKCkgZnVuY3Rpb24gdXBvbiBpdCwgYW5kIHJldHVybnMgdGhlIG91dHB1dC4gV2UgY291bGQgZG8gdGhlIHNhbWUgd2l0aCB0aGUgZXhwbGljaXQgYGlmYCBhbmQgYGVsc2VgIGNvbnRyb2wgZmxvdyBzdGF0ZW1lbnRzCgpgYGB7cn0KZXZhbDEwXzIgPC0gZnVuY3Rpb24oeCl7CiAgeSA8LSBpZiAoeCA8IDEwKXsKICAgIHByaW50KCJsZXNzIHRoYW4gMTAiKQogICAgfSBlbHNlIHsKICAgICAgcHJpbnQoImdyZWF0ZXIgdGhhbiAxMCIpCiAgICB9Cn0KCmV2YWwxMF8yKDEpCmV2YWwxMF8yKDE1KQpgYGAKCldoaWxzdCB0aGlzIGlzIGEgc2ltcGxlIGV4YW1wbGUsIHdlIGNvdWxkIGJ1aWxkIHVwIHRvIGNyZWF0aW5nIHNvbWUgaW5jcmVkaWJseSBjb21wbGV4IGZ1bmN0aW9ucyB3aXRoIGN1c3RvbSBjb250cm9sIGZsb3dzIHRvIGVmZmljaWVudGx5IGhhbmRsZSBvdXIgZGF0YSBhbmQgZG93bnN0cmVhbSBhbmFseXNpcyBpbiBSLiBJdCBtYXkgd2VsbCBiZSB1c2VmdWwgZm9yIHRoaW5ncyBzdWNoIGFzIGxvb2tpbmcgYXQgZGF0YSB0byBzZWUgaWYgaXQgY29udGFpbnMgaGVhZGVycyBiZWZvcmUgcmVtb3ZpbmcgdGhlbSwgb3IgYXNzZXNzaW5nIHRoZSBsZW5ndGggb2YgYSBkYXRhIHNldCBiZWZvcmUgcGVyZm9ybWluZyBhIGZ1bmN0aW9uIG9uIGl0LiAKCiMgTGlzdHMgaW4gUgoKTm93LCB3ZSd2ZSBoYWQgYSB3aGlzdGxlIHN0b3AgdG91ciBvZiBmdW5jdGlvbnMsIG9idmlvdXNseSB0aGlzIGlzIG5vdCB0aGUgZnVsbCBleHRlbnQgb2YgdGhlaXIgZnVuY3Rpb25hbGl0eSwgYnV0IGl0J3MgdGltZSB0byBtb3ZlIG9uIHRvIGxpc3RzLiBXZSd2ZSBub3QgcmVhbGx5IG1lbnRpb25lZCBsaXN0cyBzbyBmYXIsIG90aGVyIHRoYW4gdmVyeSBicmllZmx5IGluIHNvbWUgb2YgdGhlIGJlZ2lubmVyIHNlc3Npb25zLiBUbyByZWNhcCwgdGhlcmUgYXJlIDQgbWFpbiBkYXRhIHN0cnVjdHVyZXMgaW4gUiAtIHZlY3RvcnMsIG1hdHJpY2llcywgZGF0YS5mcmFtZXMsIGFuZCBsaXN0cy4gCgpBIGxpc3QgaXMgYSBzcGVjaWFsIGZvcm0gb2YgZGF0YSBzdHJ1Y3R1cmUgd2hpY2ggYWxsb3dzIHlvdSB0byBjb250YWluIG9iamVjdHMgb2YgZGlmZmVyZW50IGxlbmd0aHMgd2l0aGluIGl0LiBUaGV5IGFyZSBhIGxpdHRsZSBtb3JlIGNvbXBsaWNhdGVkIHRoYW4gdGhlIG90aGVyIGRhdGEgc3RydWN0dXJlcyB3ZSBjb3ZlcmVkIGJlZm9yZSAtIHBhcnRseSBiZWNhdXNlIGEgZGF0YS5mcmFtZSBpcyBib3RoIGEgc3BlY2lhbCB0eXBlIG9mIGxpc3QsIGFuZCBjYW4gYmUgY29udGFpbmVkIHdpdGhpbiBhIGxpc3QhIEluIGEgZGF0YS5mcmFtZSwgZWFjaCBjb21wb25lbnQgcGFydCAob3IgY29sdW1uKSBtdXN0IGJlIHRoZSBzYW1lIGxlbmd0aCAtIHRoaXMgaXMgbm90IHRydWUgb2YgYSBsaXN0LgoKVGhleSBhcmUgcXVpdGUgY29tcGxpY2F0ZWQgb24gZmlyc3QgZ2xhbmNlLCBhbmQgb2Z0ZW4gYXJlIG5vdCB0YXVnaHQgYXQgYWxsIGluIFIgY291cnNlcyAtIEkgd2FzIG5ldmVyIGZvcm1hbGx5IHRhdWdodCB3aGF0IGEgbGlzdCB3YXMgb3IgaG93IG9uIGVhcnRoIHRvIHVzZSBvbmUsIGFuZCBJIGhhZCB0byB0cnkgYW5kIHdvcmsgaXQgb3V0IGZvciBteXNlbGYuIExpc3RzIGFyZSBwcm9iYWJseSB0aGUgZm9ybSBvZCBkYXRhIHN0cnVjdHVyZSB0aGF0IEkgdXNlIHRoZSBsZWFzdCBpbiBSLCBzaW1wbHkgYmVjYXVzZSBJIG5ldmVyIGdvdCBpbnRvIHRoZSBoYWJpdCBvZiB1c2luZyB0aGVtLiBOb3csIGxldCdzIG1ha2UgYSBsaXN0IGFuZCBzZWUgaG93IHRoZXkgd29yaywgYW5kIGZpZ3VyZSBvdXQgaG93IHRvIGFjY2VzcyBzdHVmZiB3aXRoaW4gdGhlbS4gRmlyc3QsIHdlJ2xsIGNyZWF0ZSB0aHJlZSB2ZWN0b3JzIChvbmUgY2hhcmFjdGVyLCBvbmUgbnVtZXJpYywgYW5kIG9uZSBsb2dpY2FsKSwgYW5kIGNvbWJpbmUgdGhlbSB3aXRoIHRoZSBgbGlzdCgpYCBmdW5jdGlvbi4KCmBgYHtyfQpuaW50ZW5kbyA8LSBjKCJNYXJpbyIsICJMdWlnaSIsICJQZWFjaCIpCm51bWJlcnMgPC0gMToxMDAKbG9naWMgPC0gYyhUUlVFLCBGQUxTRSwgRkFMU0UsIFRSVUUpCgpteV9saXN0IDwtIGxpc3QobmludGVuZG8sIG51bWJlcnMsIGxvZ2ljKQpgYGAKTm93LCB3ZSBoYXZlIG91ciBsaXN0LiBXZSBjYW4gcHJpbnQgaXQgdG8gdGhlIHNjcmVlbiBieSB0eXBpbmcgdGhlIG5hbWUgb2Ygb3VyIGxpc3QsIGFuZCBpdCdsbCBwcmludCBldmVyeXRoaW5nIG91dC4KCmBgYHtyfQpteV9saXN0CmBgYApGcm9tIHRoaXMsIHdlIGNhbiBjbGVhcmx5IHNlZSB0aGF0IHRoZSBvYmplY3RzIGNvbnRhaW5lZCB3aXRoaW4gdGhlIGxpc3QgYXJlIG9mIGRpZmZlcmVudCBsZW5ndGhzIC0gbmludGVuZG8gaGFzIGEgbGVuZ3RoIG9mIDMsIG51bWJlcnMgaGFzIGEgbGVuZ3RoIG9mIDEwMCwgYW5kIGxvZ2ljIGhhcyBhIGxlbmd0aCBvZiA0LgoKU28sIGhvdyBkbyB3ZSBhY2Nlc3MgdGhlIGxpc3Q/IEl0IGNhbiBzZWVtIGNvbXBsaWNhdGVkLCBidXQgYWN0dWFsbHkgcHJpbnRpbmcgaXQgdG8gdGhlIHNjcmVlbiBoYXMgZ2l2ZW4gdXMgbG90cyBvZiBpbmZvcm1hdGlvbi4gV2UgY2FuIHVzZSBzcXVhcmUgYnJhY2tldHMgYFtdYCB0byBjaG9vc2Ugb2JqZWN0cy4gV2UgY2FuIGFsc28gYWNjZXNzIGVsZW1lbnRzIHdpdGggdGhlaXIgbmFtZXMsIHByb3ZpZGVkIHdlIGhhdmUgZ2l2ZW4gdGhlbSBuYW1lcywgYnV0IHdlIHdpbGwgY29tZSBiYWNrIHRvIHRoYXQuCgpMZXQncyB0cnkgYW5kIHNlbGVjdCB0aGUgZmlyc3QgdmVjdG9yIGVsZW1lbnQgb2Ygb3VyIGxpc3QuIFdlIG1pZ2h0IHRyeSBhbmQgYWNjZXNzIGl0IHdpdGg6CgpgYGB7cn0KbXlfbGlzdFsxXQpgYGAKCldoaWxzdCB0aGlzIGRvZXMgcmV0dXJuIHdoYXQgd2Ugd2FudCBpdCB0bywgdGhpcyBhY3R1YWxseSBpc24ndCBpbiB0aGUgdmVjdG9yIGNsYXNzIHRoYXQgd2UgY3JlYXRlZCB0aGUgbGlzdCB3aXRoLiBXZSBjYW4gY2hlY2sgd2l0aCB0aGUgYGNsYXNzKClgIGZ1bmN0aW9uOgoKYGBge3J9CmNsYXNzKG15X2xpc3RbMV0pCmBgYAoKV2UgY2FuIHNlZSBoZXJlIHRoYXQgdGhlIG9iamVjdCBoYXMgcmV0YWluZWQgaXQncyBsaXN0IGNsYXNzLCBhbmQgaGFzIHRha2VuIHRoZSBmaXJzdCBwYXJ0IG9mIHRoZSBsaXN0LCBidXQgbm90IHRoZSB2ZWN0b3IgaXRzZWxmLiBXZSBjYW4gYWNjZXNzIHRoZSB2ZWN0b3Igd2l0aGluIHRoZSBsaXN0IHdpdGggZG91YmxlIHNxdWFyZSBicmFja2V0cyBgW1tdXWAsIHRoZSBjbHVlIGlzIGluIHRoZSBkaXNwbGF5IG9mIHRoZSBsaXN0IQoKYGBge3J9Cm15X2xpc3RbWzFdXQoKY2xhc3MobXlfbGlzdFtbMV1dKQpgYGAKCldoZW4gd2UgdmVyaWZ5IHdoYXQgd2UncmUgZG9pbmcgd2l0aCBgY2xhc3MoKWAsIHdlIGNhbiBzZWUgdGhhdCB3ZSdyZSBnZXR0aW5nIHRoZSBvcmlnaW5hbCBjaGFyYWN0ZXIgdmVjdG9yIHN0b3JlZCB3aXRoaW4gdGhlIGxpc3QuIFRoaXMgaXMgYSBiaXQgY29tcGxleCBhbmQgaGFuZC13YXZ5LCBidXQgYmFzaWNhbGx5IHJlbWVtYmVyIHRoYXQgYFtbXV1gIGFsbG93cyB5b3UgdG8gYWNjZXNzIHRoZSBlbGVtZW50IGZyb20gd2l0aGluIHRoZSBsaXN0IGluIGl0cyBuYXRpdmUgZm9ybSwgd2hlcmVhcyBgW11gIGdpdmVzIHlvdSB0aGUgZWxlbWVudCBvZiB0aGUgbGlzdCwgd2hpbHN0IHJldGFpbmluZyBpdCdzIGxpc3QgY2xhc3MuCgpCZSBhd2FyZSB0aGF0IHRoZSB3YXkgd2UgYWNjZXNzIGxpc3RzIHdpdGggYFtdYCBpcyBkaWZmZXJlbnQgdGhhbiB2ZWN0b3JzLiBGb3IgZXhhbXBsZSwgaWYgd2Ugd2VyZSB0byB0eXBlIGBteV9saXN0WzE6Ml1gIHdlIGdldCB0aGUgZmlyc3QgdHdvIGVsZW1lbnRzIG9mIHRoZSBsaXN0LCBidXQgYG15X2xpc3RbWzE6Ml1dYCBnaXZlcyB5b3UgdGhlIHNlY29uZCBlbGVtZW50IG9mIHRoZSBmaXJzdCBiaXQgb2YgdGhlIGxpc3Q6CgpgYGB7cn0KbXlfbGlzdFsxOjJdCgpteV9saXN0W1sxOjJdXQpgYGAKWW91IGNhbiBhY2Nlc3MgYml0cyBvZiBsaXN0cyBhcyBhYm92ZSwgb3IgcGVyaGFwcyBtb3JlIGludHVpdGl2ZWx5IGFuZCBsZXNzIGNvbmZ1c2luZ2x5LCBieSBjb21iaW5pbmcgZG91YmxlIGFuZCBzaW5nbGUgc3F1YXJlIGJyYWNrZXRzCgpgYGB7cn0KbXlfbGlzdFtbMV1dWzJdICMgVGhpcyBhY2Nlc3NlcyB0aGUgMm5kIGl0ZW0gb2YgdGhlIDFzdCBsaXN0IGVsZW1lbnQuCmBgYAoKWW91IGNhbiBhbHNvIHVzZSBuYW1lcyB0byBhY2Nlc3MgbGlzdCBlbGVtZW50cyBpbiBhIHdheSB0aGF0IGlzIGVxdWl2YWxlbnQgdG8gaG93IGEgZGF0YWZyYW1lIHdvdWxkIHdvcmsuIEluIG9yZGVyIHRvIGRvIHRoaXMsIGhvd2V2ZXIsIHlvdSBtdXN0IHNwZWNpZnkgdGhlIG5hbWVzIHdoZW4geW91J3JlIGNyZWF0aW5nIHRoZSBsaXN0LCBsaWtlIHRoaXM6CgpgYGB7cn0KbXlfbGlzdCA8LSBsaXN0KG5pbnRlbmRvID0gbmludGVuZG8sIG51bWJlcnMgPSBudW1iZXJzLCBsb2dpYyA9IGxvZ2ljKQpgYGAKSWYgd2UgcHJpbnQgdGhlIGxpc3QgYWdhaW4sIHlvdSdsbCBzZWUgdGhhdCB0aGUgW1sxXV0sIFtbMl1dLCBhbmQgW1szXV0gaGF2ZSBiZWVuIHJlcGxhY2VkIGJ5ICRuaW50ZW5kbywgJG51bWJlcnMsIGFuZCAkbG9naWM6CmBgYHtyfQpteV9saXN0CmBgYApOb3cgeW91IGNhbiBhY2Nlc3MgeW91ciBsaXN0IHVzaW5nIHRoZSBuYW1lcywgYnV0IG5vdGUgdGhhdCBqdXN0IGxpa2UgYSBkYXRhZnJhbWUsIGBteV9saXN0W1sxXV1gIHdpbGwgc3RpbGwgd29yawoKYGBge3J9Cm15X2xpc3QkbmludGVuZG8KCm15X2xpc3RbWzFdXQpgYGAKCiMjIFdoeSBhcmUgbGlzdHMgaW1wb3J0YW50PwoKSXQgcGVyaGFwcyBpc24ndCBpbW1lZGlhdGVseSBvYnZpb3VzIHdoeSBsaXN0cyBhcmUgaW1wb3J0YW50LCBidXQgd2Ugd2lsbCB0YWxrIG1vcmUgYWJvdXQgdGhpcyBpbiB0aGUgbmV4dCBzZXNzaW9uLiBJdCdzIHVzZWZ1bCBmb3IgeW91IHRvIGtub3cgaG93IHRvIHVzZSB0aGVtLCBhcyB0aGV5IHdpbGwgbWFrZSBSIG1vcmUgdXNlZnVsIHRvIHlvdS4KCkJyaWVmbHksIGxpc3RzIGNhbiBiZSBoZWxwZnVsIGlmIHlvdSBhcmUgd29ya2luZyBvbiBsb3RzIG9mIGRhdGFmcmFtZXMvdGliYmxlcyBhdCB0aGUgc2FtZSB0aW1lLCBhcyB5b3UgY2FuIHN0b3JlIHRoZW0gd2l0aGluIGEgbGlzdC4gVGhlIHZlcnNhdGlsaXR5IG9mIHRoaXMgd2lsbCBiZWNvbWUgY2xlYXJlciBuZXh0IHRpbWUgd2hlbiB3ZSdyZSB0YWxraW5nIGFib3V0IHRoZSBhcHBseSBmYW1pbHkgb2YgZnVuY3Rpb25zLCBgc2FwcGx5KClgLCBgbGFwcGx5KClgLCBhbmQgYGFwcGx5KClgLgoKIyBTdW1tYXJ5CgpTbywgdG9kYXkgd2UgaGF2ZSBsZWFybmVkIGFib3V0IGNvbnRyb2wgZmxvdyB3aXRoIGBmb3JgLCBgaWZgLCBgZWxzZWAsIGFuZCBgaWZlbHNlKClgLCBhbmQgaG93IHRoZXNlIGFyZSB1c2VkIHRvIGNvbnRyb2wgdGhlIGZsb3cgb2YgZGF0YSB0aHJvdWdoIGEgc2V0IG9mIGZ1bmN0aW9ucywgZGVwZW5kaW5nIG9uIHdoZXRoZXIgY29uZGl0aW9ucyBhcmUgbWV0LiAKCldlJ3ZlIGxlYXJuZWQgaG93IHRvIHdyaXRlIG91ciBvd24gZnVuY3Rpb25zLCBpbmNsdWRpbmcgd2l0aCBtdWx0aXBsZSBhcmd1bWVudHMgYW5kIGRlZmF1bHRzLCBhbmQgaGF2ZSBjb21iaW5lZCB0aGlzIHdpdGggb3VyIG5ldyBrbm93bGVkZ2Ugb2YgY29udHJvbCBmbG93LgoKRmluYWxseSwgd2UgdG91Y2hlZCBvbiBsaXN0cyB3aGljaCBmZWVkcyBuaWNlbHkgaW50byB0aGUgYXBwbHkgc2V0IG9mIGZ1bmN0aW9ucyB0aGF0IHdlJ2xsIGxvb2sgYXQgaW4gbW9yZSBkZXRhaWwgb24gVGh1cnNkYXkuIFdlIGNhbiB1c2UgYHNhcHBseSgpYCwgYGxhcHBseSgpYCBhbmQgYGFwcGx5KClgIHRvIGVmZmljaWVudGx5IHByb2Nlc3MgdmVjdG9ycyBpbiBSLCBhbmQgd2UnbGwgbGVhcm4gbW9yZSBhYm91dCB0aGUgcHJpbmNpcGxlcyBvZiBwcm9wZXIgc2NyaXB0aW5nLgoKCgo=