Today we are going to learn how to plot data in R! While there are
some simple plotting functions built into base R (you will often see
tutorials that use the plot() command), I encourage you to produce your
plots and data visualizations uisng the ggplot2 package in R. This
package takes a little getting used to, but once you understand the
syntax you will be making effective graphs and visualizations in no
time! Visualizing data is such an important part of the data analysis
process: it helps us to better understand the data and its distribution,
it allows us to identify and communicate patterns in simple and visually
appealing ways, and it enables us to condense a large amount of
technical information into a diagram or visual.
#Make sure you download ggplot2 first! Let's load in package and set the working directory.
setwd("C:/Users/melha/OneDrive/Documents/Binghamton/geog380")
Warning: The working directory was changed to C:/Users/melha/OneDrive/Documents/Binghamton/geog380 inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
library(dplyr)
library(tidyr)
Warning: package ‘tidyr’ was built under R version 4.0.5
library(ggplot2)
#we'll start by loading in some data to play with! We'll use NYC temperature data for this tutorial.
temps <- read.csv("temps_nyc.csv")
#Take a look at this dataset! It contains mean, min, and max temperatures in NYC for an entire year (2014).
#What if we wanted to plot the temperatures over time? We could plot it using base R like so:
plot(temps$day, temps$actual_mean_temp)

#for all plots, the syntax is usually (x = , y = ) - we'll put time (days) on the horizontal axis, and temperatures on the vertical axis. Putting the time variable on the x-axis is pretty standard.
This plot isn’t bad, but it isn’t very nice looking either. The
ggplot2 package gives us so much flexibility to customize our plots -
we’ll make a much nicer version of this soon. Before we get to that, we
first need to learn a bit about the syntax of ggplot2.
#Let's look at the first line of a basic ggplot graph:
ggplot(temps, aes(x = day, y = actual_mean_temp))

#When you use the ggplot() command, you need to supply a few key arguments. The first is the dataset - in this case, we will be using the temps data (as shown). The next part, called the aesthetic mapping or aes of the plot, tells us what we will be plotting from the dataset. Later, we will also include some characteristics of the plot in the aes() section. Can we plot the graph now? Not just yet! We need to add a geom layer - the geom layer tells ggplot2 what kind of visualization to produce with the data. We use a + sign to indicate a new layer in the plot like this (here I'm using geom_point to tell ggplot2 to draw a scatter plot):
ggplot(temps, aes(x = day, y = actual_mean_temp)) +
geom_point()


There’s a few important things to point out about the code above. I
have put the color = argument in the geom_point layer. This tells R to
use the color blue for the points - when we create more complex graphs,
being able to customize each geom layer individually becomes really
important. Second, the color that I choose comes next in quotation
marks. What happens if we leave them out?

As you can see, without the quotes, R thinks that we are using an
object call blue to set the color of the graph! You could actually do
that, like this:

Being able to set the color scheme of a graph using an object is much
more useful when you are working with a color palette (that is, when you
need to use multiple colors to symbolize a graph). We will see an
example like that soon. Let’s look at some other customization
features!




Hopefully that makes sense now! So, the graph of multiple variables
looks pretty nice! But, there no legend on our graph! How will people
know what each color represents? This is a somewhat annoying limitation
of ggplot2, and it’s a problem that you’ll come across somewhat
frequently. There are two ways to fix it: first, we can add a legend
manually. I’ll show you how to do that first. Second, we can reshape the
data - this is a somewhat more complicated method, but it ends up being
extremely useful when you have more than a few variables to graph. I’ll
explain that method second.


Doesn’t that look nice? Let’s talk about reshaping your data now.
This is a very helpful skill to have, and you will find yourself having
to reshape data frequently.So right now, each variable has its own
column in the dataframe in our case, we’re working with four columns of
data. Since three of the variables are temperature data, wouldn’t it
make sense to put them all in one column instead? This is what we call
transforming data from wide to long format - wide data has more columns,
while long data will usually have more rows instead. Here’s a diagram of
what it looks like to transform from long to wide: https://i.stack.imgur.com/i1Dne.jpg. You can look at
this diagram later if you’re confused about what wide and long format
look like. For whatever reason, the ggplot2 package tends to work better
with long data. We’ll reshape the data using a command from the tidyr
package, pivot_longer.
#What if I wanted to go from long to wide data? Here's what that looks like, for your reference:
wide_data1 <- long_data %>%
pivot_wider(names_from = temp_type, values_from = temp)
#Run this code to verify that the original wide_data and our new wide_data1 dataframe are the same. Logical data is helpful in this case!
#I'm setting the number of values that R prints out to 20 - otherwise, R would print the whole dataset on the screen, and it would take up a lot of space!
options(max.print = 20)
wide_data1 == wide_data
Do you see the difference? Now, the category (temp_type, or mean,
min, and max) is in one column, while each temperature that corresponds
to the temp_type and day is in the temp column. The wide and long data
sets are just different ways of storing the same data! Now let’s see how
this works in ggplot2.

Do you see why I changed the column names? R uses the categories in
the temp_type column to add names to the legend. Keeping the
“actual_mean_temp” (and so on) labels would not have been nearly as
clear in a legend. In our graphs, we should aim to show complex
information in the simplest way possible - having clear legend and axis
titles is key to that. Now, in this case, the colors aren’t quite right!
Let’s set them manually.

Do you see how much simpler and shorter the ggplot2 code is now?
Reshaping data definitely takes some getting used to, but it’ll save you
time in the future. Before we move on, I’ll show you one more way to set
the colors, now that we have the data in long format. This third version
will introduce you to a function that is helpful within dplyr functions,
ifelse.

Overall, the second method of adding color for multiple variables
(reshaping the data and using a color palette object to set colors) is
probably the most flexible method. Often, you’ll be able to set palettes
using functions, which makes the process even faster; it’s unlikely that
you’ll need to manually specify colors. In the next chunk of code, I’ll
give an example using a package that contains some really nice color
palettes inspired by US national parks. More info on the palettes are
here: https://github.com/katiejolly/nationalparkcolors. You
can use the code from the github link to install the package, too. Other
packages, like RColorBrewer, also provide a range of palettes to choose
from.

So now you know the basics of graphing with ggplot2! There are just a
few more topics to cover that you will find helpful. First, what if I
don’t want to use a scatter plot? Ggplot2 comes with a wide range of
geom possibilities! It’s so easy to produce different kinds of plots of
your data. Let’s make a line plot with the data we already have.

The line plot doesn’t look nice and smooth because we’re working with
daily data - there are a lot of data points, and the temperatures move
around a lot! But as you can see, switching to a line plot was so easy.
Next, we can look at a bar plot. Line plots, scatter plots, and bar
plots will be the most common plots you’ll use.

Let’s think about some other ways you can customize your plots. One
way that we can make our plot look nice is by adding a visual theme.
There are a number of themes you can add to your plot - we’ll download a
new package now that contains some additional themes as well.



If you type theme_ you should get a drop down menu of all of the
possible themes to choose from - I would encourage you to play around
with them, and see which one you like best!

Finally, can you use more than one plot type in the same plot? You
sure can! The code below shows what this looks like by adding a trend
line to the data using a smoothing method (don’t worry about how it
works, this is just an example). In this example, because we are using
the smoothing function to find the average values of each temperature
type, we don’t need to change the aesthetics. If, for example, you
wanted to make a line graph with one variable over time and a point
graph with a different variable over time, you would need to manually
include the aesthetics in each geom layer (like we did the first time we
added color - in that example, each variable had its own geom layer, and
we had to map the aesthetics for each one).

And there you have it! You are now a pro at using ggplot2. You should
have all the tools you need to make beautiful and effective
visualization in R. If you want more information on different types of
graphs, or you just want a helpful reference to refer to as you progress
through the course, you can find an excellent ggplot2 cheat sheet here:
https://www.maths.usyd.edu.au/u/UG/SM/STAT3022/r/current/Misc/data-visualization-2.1.pdf.
Resources
FiveThirtyEight (2014). US. Weather History. [Data Set]. Retrieved
from: https://github.com/fivethirtyeight/data/tree/master/us-weather-history.
Prabhakaran, S. (2017). The Complete ggplot2 Tutorial - Part1 |
Introduction To ggplot2. Retrieved from: http://r-statistics.co/Complete-Ggplot2-Tutorial-Part1-With-R-Code.html.
LS0tDQp0aXRsZTogIldlZWsgMyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KDQotLS0NClRvZGF5IHdlIGFyZSBnb2luZyB0byBsZWFybiBob3cgdG8gcGxvdCBkYXRhIGluIFIhIFdoaWxlIHRoZXJlIGFyZSBzb21lIHNpbXBsZSBwbG90dGluZyBmdW5jdGlvbnMgYnVpbHQgaW50byBiYXNlIFIgKHlvdSB3aWxsIG9mdGVuIHNlZSB0dXRvcmlhbHMgdGhhdCB1c2UgdGhlIHBsb3QoKSBjb21tYW5kKSwgSSBlbmNvdXJhZ2UgeW91IHRvIHByb2R1Y2UgeW91ciBwbG90cyBhbmQgZGF0YSB2aXN1YWxpemF0aW9ucyB1aXNuZyB0aGUgZ2dwbG90MiBwYWNrYWdlIGluIFIuIFRoaXMgcGFja2FnZSB0YWtlcyBhIGxpdHRsZSBnZXR0aW5nIHVzZWQgdG8sIGJ1dCBvbmNlIHlvdSB1bmRlcnN0YW5kIHRoZSBzeW50YXggeW91IHdpbGwgYmUgbWFraW5nIGVmZmVjdGl2ZSBncmFwaHMgYW5kIHZpc3VhbGl6YXRpb25zIGluIG5vIHRpbWUhIFZpc3VhbGl6aW5nIGRhdGEgaXMgc3VjaCBhbiBpbXBvcnRhbnQgcGFydCBvZiB0aGUgZGF0YSBhbmFseXNpcyBwcm9jZXNzOiBpdCBoZWxwcyB1cyB0byBiZXR0ZXIgdW5kZXJzdGFuZCB0aGUgZGF0YSBhbmQgaXRzIGRpc3RyaWJ1dGlvbiwgaXQgYWxsb3dzIHVzIHRvIGlkZW50aWZ5IGFuZCBjb21tdW5pY2F0ZSBwYXR0ZXJucyBpbiBzaW1wbGUgYW5kIHZpc3VhbGx5IGFwcGVhbGluZyB3YXlzLCBhbmQgaXQgZW5hYmxlcyB1cyB0byBjb25kZW5zZSBhIGxhcmdlIGFtb3VudCBvZiB0ZWNobmljYWwgaW5mb3JtYXRpb24gaW50byBhIGRpYWdyYW0gb3IgdmlzdWFsLiANCg0KDQpgYGB7cn0NCg0KI01ha2Ugc3VyZSB5b3UgZG93bmxvYWQgZ2dwbG90MiBmaXJzdCEgTGV0J3MgbG9hZCBpbiBwYWNrYWdlIGFuZCBzZXQgdGhlIHdvcmtpbmcgZGlyZWN0b3J5Lg0Kc2V0d2QoIkM6L1VzZXJzL21lbGhhL09uZURyaXZlL0RvY3VtZW50cy9CaW5naGFtdG9uL2dlb2czODAiKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGdncGxvdDIpDQoNCiN3ZSdsbCBzdGFydCBieSBsb2FkaW5nIGluIHNvbWUgZGF0YSB0byBwbGF5IHdpdGghIFdlJ2xsIHVzZSBOWUMgdGVtcGVyYXR1cmUgZGF0YSBmb3IgdGhpcyB0dXRvcmlhbC4gDQoNCnRlbXBzIDwtIHJlYWQuY3N2KCJ0ZW1wc19ueWMuY3N2IikNCg0KI1Rha2UgYSBsb29rIGF0IHRoaXMgZGF0YXNldCEgSXQgY29udGFpbnMgbWVhbiwgbWluLCBhbmQgbWF4IHRlbXBlcmF0dXJlcyBpbiBOWUMgZm9yIGFuIGVudGlyZSB5ZWFyICgyMDE0KS4NCiNXaGF0IGlmIHdlIHdhbnRlZCB0byBwbG90IHRoZSB0ZW1wZXJhdHVyZXMgb3ZlciB0aW1lPyBXZSBjb3VsZCBwbG90IGl0IHVzaW5nIGJhc2UgUiBsaWtlIHNvOg0KDQpwbG90KHRlbXBzJGRheSwgdGVtcHMkYWN0dWFsX21lYW5fdGVtcCkNCg0KI2ZvciBhbGwgcGxvdHMsIHRoZSBzeW50YXggaXMgdXN1YWxseSAoeCA9ICwgeSA9ICkgLSB3ZSdsbCBwdXQgdGltZSAoZGF5cykgb24gdGhlIGhvcml6b250YWwgYXhpcywgYW5kIHRlbXBlcmF0dXJlcyBvbiB0aGUgdmVydGljYWwgYXhpcy4gUHV0dGluZyB0aGUgdGltZSB2YXJpYWJsZSBvbiB0aGUgeC1heGlzIGlzIHByZXR0eSBzdGFuZGFyZC4gDQpgYGANClRoaXMgcGxvdCBpc24ndCBiYWQsIGJ1dCBpdCBpc24ndCB2ZXJ5IG5pY2UgbG9va2luZyBlaXRoZXIuIFRoZSBnZ3Bsb3QyIHBhY2thZ2UgZ2l2ZXMgdXMgc28gbXVjaCBmbGV4aWJpbGl0eSB0byBjdXN0b21pemUgb3VyIHBsb3RzIC0gd2UnbGwgbWFrZSBhIG11Y2ggbmljZXIgdmVyc2lvbiBvZiB0aGlzIHNvb24uIEJlZm9yZSB3ZSBnZXQgdG8gdGhhdCwgd2UgZmlyc3QgbmVlZCB0byBsZWFybiBhIGJpdCBhYm91dCB0aGUgc3ludGF4IG9mIGdncGxvdDIuIA0KDQpgYGB7cn0NCiNMZXQncyBsb29rIGF0IHRoZSBmaXJzdCBsaW5lIG9mIGEgYmFzaWMgZ2dwbG90IGdyYXBoOg0KDQpnZ3Bsb3QodGVtcHMsIGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21lYW5fdGVtcCkpDQoNCiNXaGVuIHlvdSB1c2UgdGhlIGdncGxvdCgpIGNvbW1hbmQsIHlvdSBuZWVkIHRvIHN1cHBseSBhIGZldyBrZXkgYXJndW1lbnRzLiBUaGUgZmlyc3QgaXMgdGhlIGRhdGFzZXQgLSBpbiB0aGlzIGNhc2UsIHdlIHdpbGwgYmUgdXNpbmcgdGhlIHRlbXBzIGRhdGEgKGFzIHNob3duKS4gVGhlIG5leHQgcGFydCwgY2FsbGVkIHRoZSBhZXN0aGV0aWMgbWFwcGluZyBvciBhZXMgb2YgdGhlIHBsb3QsIHRlbGxzIHVzIHdoYXQgd2Ugd2lsbCBiZSBwbG90dGluZyBmcm9tIHRoZSBkYXRhc2V0LiBMYXRlciwgd2Ugd2lsbCBhbHNvIGluY2x1ZGUgc29tZSBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGhlIHBsb3QgaW4gdGhlIGFlcygpIHNlY3Rpb24uIENhbiB3ZSBwbG90IHRoZSBncmFwaCBub3c/IE5vdCBqdXN0IHlldCEgV2UgbmVlZCB0byBhZGQgYSBnZW9tIGxheWVyIC0gdGhlIGdlb20gbGF5ZXIgdGVsbHMgZ2dwbG90MiB3aGF0IGtpbmQgb2YgdmlzdWFsaXphdGlvbiB0byBwcm9kdWNlIHdpdGggdGhlIGRhdGEuIFdlIHVzZSBhICsgc2lnbiB0byBpbmRpY2F0ZSBhIG5ldyBsYXllciBpbiB0aGUgcGxvdCBsaWtlIHRoaXMgKGhlcmUgSSdtIHVzaW5nIGdlb21fcG9pbnQgdG8gdGVsbCBnZ3Bsb3QyIHRvIGRyYXcgYSBzY2F0dGVyIHBsb3QpOg0KDQpnZ3Bsb3QodGVtcHMsIGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21lYW5fdGVtcCkpICsNCiAgZ2VvbV9wb2ludCgpDQpgYGANCmBgYHtyfQ0KI09uZSBvZiB0aGUgbmljZSB0aGluZ3MgYWJvdXQgZ2dwbG90MiBpcyBpdHMgZmxleGliaWxpdHkuIFdlIGNhbiBlYXNpbHkgY3VzdG9taXplIHRoZSBwbG90LiBPbmNlIHlvdSBnZXQgdXNlZCB0byB0aGUgc3ludGF4IG9mIGdncGxvdDIsIGN1c3RvbWl6YXRpb24gaXMgdmVyeSBzaW1wbGUuIEZvciBleGFtcGxlLCBsZXQncyBzdGFydCBieSBjaGFuZ2luZyB0aGUgY29sb3Igb2YgdGhlIHBvaW50czoNCg0KZ2dwbG90KHRlbXBzLCBhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tZWFuX3RlbXApKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAibWVkaXVtcHVycGxlIikNCmBgYA0KVGhlcmUncyBhIGZldyBpbXBvcnRhbnQgdGhpbmdzIHRvIHBvaW50IG91dCBhYm91dCB0aGUgY29kZSBhYm92ZS4gSSBoYXZlIHB1dCB0aGUgY29sb3IgPSBhcmd1bWVudCBpbiB0aGUgZ2VvbV9wb2ludCBsYXllci4gVGhpcyB0ZWxscyBSIHRvIHVzZSB0aGUgY29sb3IgYmx1ZSBmb3IgdGhlIHBvaW50cyAtIHdoZW4gd2UgY3JlYXRlIG1vcmUgY29tcGxleCBncmFwaHMsIGJlaW5nIGFibGUgdG8gY3VzdG9taXplIGVhY2ggZ2VvbSBsYXllciBpbmRpdmlkdWFsbHkgYmVjb21lcyByZWFsbHkgaW1wb3J0YW50LiBTZWNvbmQsIHRoZSBjb2xvciB0aGF0IEkgY2hvb3NlIGNvbWVzIG5leHQgaW4gcXVvdGF0aW9uIG1hcmtzLiBXaGF0IGhhcHBlbnMgaWYgd2UgbGVhdmUgdGhlbSBvdXQ/DQoNCmBgYHtyfQ0KYmx1ZSA8LSAiYmx1ZSINCg0KZ2dwbG90KHRlbXBzLCBhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tZWFuX3RlbXApKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSBibHVlKQ0KDQpgYGANCkFzIHlvdSBjYW4gc2VlLCB3aXRob3V0IHRoZSBxdW90ZXMsIFIgdGhpbmtzIHRoYXQgd2UgYXJlIHVzaW5nIGFuIG9iamVjdCBjYWxsIGJsdWUgdG8gc2V0IHRoZSBjb2xvciBvZiB0aGUgZ3JhcGghIFlvdSBjb3VsZCBhY3R1YWxseSBkbyB0aGF0LCBsaWtlIHRoaXM6DQoNCmBgYHtyfQ0KYmx1ZSA8LSAiYmx1ZSINCg0KZ2dwbG90KHRlbXBzLCBhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tZWFuX3RlbXApKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSBibHVlKQ0KYGBgDQpCZWluZyBhYmxlIHRvIHNldCB0aGUgY29sb3Igc2NoZW1lIG9mIGEgZ3JhcGggdXNpbmcgYW4gb2JqZWN0IGlzIG11Y2ggbW9yZSB1c2VmdWwgd2hlbiB5b3UgYXJlIHdvcmtpbmcgd2l0aCBhIGNvbG9yIHBhbGV0dGUgKHRoYXQgaXMsIHdoZW4geW91IG5lZWQgdG8gdXNlIG11bHRpcGxlIGNvbG9ycyB0byBzeW1ib2xpemUgYSBncmFwaCkuIFdlIHdpbGwgc2VlIGFuIGV4YW1wbGUgbGlrZSB0aGF0IHNvb24uIExldCdzIGxvb2sgYXQgc29tZSBvdGhlciBjdXN0b21pemF0aW9uIGZlYXR1cmVzIQ0KDQpgYGB7cn0NCiNXaGF0IGlmIHdlIHdhbnQgdG8gYWRkIGxhYmVscyB0byBvdXIgcGxvdD8gVGhpcyBpcyB2ZXJ5IGVhc3kgdG8gZG8gd2l0aCB0aGUgbGFicyBhcmd1bWVudCwgbGlrZSBzbyAocmVtZW1iZXIgdGhhdCB0aGUgeC1heGlzIGlzIHRoZSBob3Jpem9udGFsIGF4aXMsIHdoaWxlIHRoZSB5LWF4aXMgaXMgdGhlIHZlcnRpY2xlIGF4aXMpOg0KDQpnZ3Bsb3QodGVtcHMsIGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21lYW5fdGVtcCkpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibHVlIikgKw0KICBsYWJzKHkgPSAiTWVhbiBUZW1wZXJhdHVyZSIsIHggPSAiRGF5IikNCmBgYA0KYGBge3J9DQojVGhpcyBpcyBzdGFydGluZyB0byBsb29rIHByZXR0eSBuaWNlISBXaGF0IGlmIHdlIHdhbnRlZCB0byBhZGQgYSB0aXRsZSB0b28/DQoNCmdncGxvdCh0ZW1wcywgYWVzKHggPSBkYXksIHkgPSBhY3R1YWxfbWVhbl90ZW1wKSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gImJsdWUiKSArDQogIGxhYnMoeSA9ICJNZWFuIFRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJNZWFuIERhaWx5IFRlbXBlcmF0dXJlIGluIE5ldyBZb3JrIENpdHksIDIwMTQiKQ0KDQojWW91J2xsIG5vdGljZSB0aGF0IEkgbGlrZSB0byBwdXQgZWFjaCBuZXcgYXJndW1lbnQgYWZ0ZXIgYSAiKyIgb24gYSBuZXcgbGluZSAtIHlvdSBkb24ndCBoYXZlIHRvIGRvIHRoaXMsIGJ1dCBJIHByZWZlciB0byBiZWNhdXNlIGl0IG1ha2VzIG15IGNvZGUgbXVjaCBlYXNpZXIgdG8gZm9sbG93LiBJIGFsc28gbGlrZSB0byBwdXQgbG9uZ2VyIGxhYmVsIG5hbWVzIG9uIGEgbmV3IGxpbmUgLSBhZ2FpbiwgdGhpcyB3b24ndCBhZmZlY3QgaG93IHRoZSBjb2RlIHJ1bnMsIGl0IGp1c3QgbWFrZXMgaXQgbW9yZSByZWFkYWJsZS4gDQoNCmBgYA0KYGBge3J9DQojQnV0IHdoYXQgaWYgd2Ugd2FudGVkIHRvIGFsc28gZ3JhcGggdGhlIG1pbmltdW0gYW5kIG1heGltdW0gdGVtcGVyYXR1cmVzIG9uIHRoZSBzYW1lIHBsb3Q/IHRoaXMgaXMgYWxzbyB2ZXJ5IGVhc3kgdG8gZG8hIFdlIGp1c3QgbmVlZCB0byB1c2UgYSBnZW9tX3BvaW50IGxheWVyIGZvciBlYWNoIHZhcmlhYmxlIHdlIHdhbnQgdG8gcGxvdC4gDQoNCiNoZXJlIHdlIHN0YXJ0IGJ5IHRlbGxpbmcgUiB0aGF0IHdlIHdhbnQgdG8gdXNlIHRoZSB0ZW1wcyBkYXRhIGZvciBvdXIgcGxvdA0KZ2dwbG90KHRlbXBzKSArDQogICNmb3IgZWFjaCBuZXcgZ2VvbV9wb2ludCBsYXllciwgSSBuZWVkIHRvIGluY2x1ZGUgYSBuZXcgYWVzdGhldGljIG1hcHBpbmcNCiAgI3RoaXMgdGVsbHMgUiB3aGljaCB2YXJpYWJsZSB0byB1c2UgaW4gdGhlIHBsb3QNCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tZWFuX3RlbXApLCBjb2xvciA9ICJncmF5IikgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21pbl90ZW1wKSwgY29sb3IgPSAiYmx1ZSIpICsNCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tYXhfdGVtcCksIGNvbG9yID0gInJlZCIpICsNCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IikNCg0KI05vdGljZSBoZXJlIHRoYXQgdGhlIGNvbG9yIGFyZ3VtZW50cyBhcmUgb3V0c2lkZSBvZiB0aGUgYWVzKCkgYXJndW1lbnQuIFRoaXMgaXMgaW50ZW50aW9uYWwgLSBvbmx5IGFyZ3VtZW50cyB0aGF0IGRlcGVuZCBvbiB2YXJpYWJsZXMgaW4gdGhlIGRhdGFzZXQgc2hvdWxkIGJlIGluIHRoZSBhZXMoKSBhcmd1bWVudC4gV2hhdCBkb2VzIHRoYXQgbWVhbj8gSW4gdGhpcyBjYXNlLCB0aGUgY29sb3IgImdyYXkiIGRvZXNuJ3QgZGVwZW5kIG9uIGFueXRoaW5nIGluIHRoZSBkYXRhIC0gZm9yIGV4YW1wbGUsIHRoZSBjb2xvciBkb2Vzbid0IGNoYW5nZSBmb3IgbG93ZXIgb3IgaGlnaGVyIHZhbHVlcy4gVGhlIGVudGlyZSBnZW9tX3BvaW50IGxheWVyIGlzIGp1c3QgZ3JheS4gSWYgd2UgaGFkIGEgdmFyaWFibGUgY2FsbGVkICJjb2xvciIgaW4gdGhlIGRhdGFzZXQsIG9yIGlmIHdlIHdhbnRlZCB0aGUgY29sb3JzIHRvIGNoYW5nZSBiYXNlZCBvbiB0ZW1wZXJhdHVyZSB2YWx1ZXMsIHdlIGNvdWxkIHB1dCBjb2xvciBpbnNpZGUgdGhlIGFlcygpLiBJJ2xsIHNob3cgYW4gZXhhbXBsZSBuZXh0Lg0KDQpgYGANCmBgYHtyfQ0KZ2dwbG90KHRlbXBzKSArDQogIGdlb21fcG9pbnQoYWVzKHggPSBkYXksIHkgPSBhY3R1YWxfbWVhbl90ZW1wLCBjb2xvciA9IGFjdHVhbF9tZWFuX3RlbXApKSArDQogIGxhYnMoeSA9ICJNZWFuIFRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJNZWFuIERhaWx5IFRlbXBlcmF0dXJlIGluIE5ldyBZb3JrIENpdHksIDIwMTQiLA0KICAgICAgIGNvbG9yID0gIk1lYW4gVGVtcGVyYXR1cmUgKEYpIikNCmBgYA0KDQpIb3BlZnVsbHkgdGhhdCBtYWtlcyBzZW5zZSBub3chIFNvLCB0aGUgZ3JhcGggb2YgbXVsdGlwbGUgdmFyaWFibGVzIGxvb2tzIHByZXR0eSBuaWNlISBCdXQsIHRoZXJlIG5vIGxlZ2VuZCBvbiBvdXIgZ3JhcGghIEhvdyB3aWxsIHBlb3BsZSBrbm93IHdoYXQgZWFjaCBjb2xvciByZXByZXNlbnRzPyBUaGlzIGlzIGEgc29tZXdoYXQgYW5ub3lpbmcgbGltaXRhdGlvbiBvZiBnZ3Bsb3QyLCBhbmQgaXQncyBhIHByb2JsZW0gdGhhdCB5b3UnbGwgY29tZSBhY3Jvc3Mgc29tZXdoYXQgZnJlcXVlbnRseS4gVGhlcmUgYXJlIHR3byB3YXlzIHRvIGZpeCBpdDogZmlyc3QsIHdlIGNhbiBhZGQgYSBsZWdlbmQgbWFudWFsbHkuIEknbGwgc2hvdyB5b3UgaG93IHRvIGRvIHRoYXQgZmlyc3QuIFNlY29uZCwgd2UgY2FuIHJlc2hhcGUgdGhlIGRhdGEgLSB0aGlzIGlzIGEgc29tZXdoYXQgbW9yZSBjb21wbGljYXRlZCBtZXRob2QsIGJ1dCBpdCBlbmRzIHVwIGJlaW5nIGV4dHJlbWVseSB1c2VmdWwgd2hlbiB5b3UgaGF2ZSBtb3JlIHRoYW4gYSBmZXcgdmFyaWFibGVzIHRvIGdyYXBoLiBJJ2xsIGV4cGxhaW4gdGhhdCBtZXRob2Qgc2Vjb25kLiANCg0KYGBge3J9DQoNCiNXZSdsbCBmaXJzdCBtYW51YWxseSBzZXQgdGhlIGNvbG9ycyBpbiB0aGUgbGVnZW5kIHVzaW5nIHNjYWxlX2NvbG9yX21hbnVhbC5Gb3Igc29tZSByZWFzb24sIGlmIHlvdSBzZXQgdGhlIGNvbG9ycyBhbGwgYXQgb25jZSwgUiB3aWxsIGdlbmVyYXRlIGEgbGVnZW5kOyBpZiB5b3Ugc2V0IGVhY2ggY29sb3IgaW5kaXZpZHVhbGx5IGluIHRoZSBnZW9tX3BvaW50IGxheWVyLCBpdCB3b24ndC4gSSBkb24ndCBtYWtlIHRoZSBydWxlcywgSSBqdXN0IGZvbGxvdyB0aGVtISBXaGVuIHlvdSBzZXQgdGhlIGNvbG9ycyBtYW51YWxseSwgeW91IGhhdmUgdG8gdGVsbCBSIHdoYXQgbGFiZWwgeW91J2QgbGlrZSB0byB1c2UgZm9yIGVhY2ggZ2VvbSBsYXllci4gSGVyZSwgSSd2ZSBzZXQgdGhlIGxhYmVsIG5hbWVzIHVzaW5nIGNvbG9yID0gIiIgaW5zaWRlIHRoZSBhZXN0aGV0aWMgbWFwcGluZyBpbiB0aGUgZ2VvbSBsYXllci4gDQoNCmdncGxvdCh0ZW1wcykgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21lYW5fdGVtcCwgY29sb3IgPSAiTWVhbiIpKSArDQogIGdlb21fcG9pbnQoYWVzKHggPSBkYXksIHkgPSBhY3R1YWxfbWluX3RlbXAsIGNvbG9yID0gIk1pbiIpKSArDQogIGdlb21fcG9pbnQoYWVzKHggPSBkYXksIHkgPSBhY3R1YWxfbWF4X3RlbXAsIGNvbG9yID0gIk1heCIpKSArDQogIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSIsIHggPSAiRGF5IiwgDQogICAgICAgdGl0bGUgPSAiRGFpbHkgVGVtcGVyYXR1cmUgaW4gTmV3IFlvcmsgQ2l0eSwgMjAxNCIsDQogICAgICAgI3NpbmNlIHRoZSBsZWdlbmQgaXMgYmFzZWQgb24gdGhlIGNvbG9yIG1hcHBpbmcsIHVzZSBjb2xvciA9IHRvIHNldCB0aGUgbGVnZW5kIHRpdGxlDQogICAgICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgVmFsdWVzIikrDQogIHNjYWxlX2NvbG9yX21hbnVhbChsYWJlbHMgPSBjKCJNZWFuIiwgIk1pbiIsICJNYXgiKSwgdmFsdWVzID0gYygiZ3JheSIsICJibHVlIiwgInJlZCIpKQ0KDQojSW4gc2NhbGVfY29sb3JfbWFudWFsLCB3ZSBzdGFydCBieSB0ZWxsaW5nIFIgd2hpY2ggbGFiZWxzIHRvIHVzZSB0byBnZW5lcmF0ZSB0aGUgY29sb3Igc2NoZW1lOyBpbiB0aGlzIGNhc2UsIGl0J3MgdGhlIHNhbWUgbGFiZWxzIHdlIGp1c3Qgc2V0IGFib3ZlLiBUaGVuLCB3ZSBoYXZlIHRvIHRlbGwgUiB3aGljaCBjb2xvcnMgdG8gdXNlIGZvciBlYWNoIGxhYmVsLiBCZWNhdXNlIHRoZXJlIGFyZSB0aHJlZSBjb2xvciB2YWx1ZXMgdG8gc2V0LCBub3RlIHRoYXQgd2UgaGF2ZSB0byB1c2UgYygpIGFyb3VuZCB0aGUgbGlzdCBvZiB2YXJpYWJsZSBuYW1lcyBhbmQgY29sb3JzLiANCg0KI1NjYWxlX2NvbG9yX21hbnVhbCBvZnRlbiBpbnZvbHZlcyBzb21lIGd1ZXNzaW5nIGFuZCBjaGVja2luZyB3aXRoIHRoZSBvcmRlciBvZiB0aGUgY29sb3JzIC0gZm9yIHNvbWUgcmVhc29uLCBSIHdhbnRlZCB0byB1c2UgdGhlIGZpcnN0IGNvbG9yIGZvciB0aGUgbWF4IHRlbXBlcmF0dXJlLCB0aGUgc2Vjb25kIGZvciB0aGUgbWVhbiwgYW5kIHRoZSB0aGlyZCBmb3IgdGhlIG1pbi4gVGhpcyBvcmRlciBtYWtlcyBubyBzZW5zZSwgYnV0IGl0IGlzIGFsc28gbm90IGVhc3kgdG8gY2hhbmdlLiBJZiB5b3Ugbm90aWNlIHRoYXQgdGhlIGNvbG9ycyBpbiB5b3VyIGdyYXBoIGRvbid0IG1hdGNoIHVwLCB0aGUgZWFzaWVzdCBmaXggaXMgdG8ganVzdCBjaGFuZ2UgdGhlIG9yZGVyIHRoYXQgeW91IGxpc3RlZCB0aGUgY29sb3JzIGFuZCB2YXJpYWJsZSBuYW1lcyBzbyB0aGF0IGl0IG1hdGNoZXMgUidzIGRlZmF1bHQgb3JkZXJpbmcuIFRoYXQncyB3aGF0IEkgZGlkIGJlbG93LiANCmBgYA0KYGBge3J9DQojSGVyZSdzIHRoZSBjb3JyZWN0IHBsb3QhDQpnZ3Bsb3QodGVtcHMpICsNCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tZWFuX3RlbXAsIGNvbG9yID0gIk1lYW4iKSkgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21pbl90ZW1wLCBjb2xvciA9ICJNaW4iKSkgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21heF90ZW1wLCBjb2xvciA9ICJNYXgiKSkgKw0KICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUiLCB4ID0gIkRheSIsIA0KICAgICAgIHRpdGxlID0gIkRhaWx5IFRlbXBlcmF0dXJlIGluIE5ldyBZb3JrIENpdHksIDIwMTQiLA0KICAgICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFZhbHVlcyIpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwobGFiZWxzID0gYygiTWF4IiwgIk1lYW4iLCAiTWluIiksIHZhbHVlcyA9IGMoInJlZCIsICJncmF5IiwgImJsdWUiKSkNCmBgYA0KRG9lc24ndCB0aGF0IGxvb2sgbmljZT8gTGV0J3MgdGFsayBhYm91dCByZXNoYXBpbmcgeW91ciBkYXRhIG5vdy4gVGhpcyBpcyBhIHZlcnkgaGVscGZ1bCBza2lsbCB0byBoYXZlLCBhbmQgeW91IHdpbGwgZmluZCB5b3Vyc2VsZiBoYXZpbmcgdG8gcmVzaGFwZSBkYXRhIGZyZXF1ZW50bHkuU28gcmlnaHQgbm93LCBlYWNoIHZhcmlhYmxlIGhhcyBpdHMgb3duIGNvbHVtbiBpbiB0aGUgZGF0YWZyYW1lIGluIG91ciBjYXNlLCB3ZSdyZSB3b3JraW5nIHdpdGggZm91ciBjb2x1bW5zIG9mIGRhdGEuIFNpbmNlIHRocmVlIG9mIHRoZSB2YXJpYWJsZXMgYXJlIHRlbXBlcmF0dXJlIGRhdGEsIHdvdWxkbid0IGl0IG1ha2Ugc2Vuc2UgdG8gcHV0IHRoZW0gYWxsIGluIG9uZSBjb2x1bW4gaW5zdGVhZD8gVGhpcyBpcyB3aGF0IHdlIGNhbGwgdHJhbnNmb3JtaW5nIGRhdGEgZnJvbSB3aWRlIHRvIGxvbmcgZm9ybWF0IC0gd2lkZSBkYXRhIGhhcyBtb3JlIGNvbHVtbnMsIHdoaWxlIGxvbmcgZGF0YSB3aWxsIHVzdWFsbHkgaGF2ZSBtb3JlIHJvd3MgaW5zdGVhZC4gSGVyZSdzIGEgZGlhZ3JhbSBvZiB3aGF0IGl0IGxvb2tzIGxpa2UgdG8gdHJhbnNmb3JtIGZyb20gbG9uZyB0byB3aWRlOiBodHRwczovL2kuc3RhY2suaW1ndXIuY29tL2kxRG5lLmpwZy4gWW91IGNhbiBsb29rIGF0IHRoaXMgZGlhZ3JhbSBsYXRlciBpZiB5b3UncmUgY29uZnVzZWQgYWJvdXQgd2hhdCB3aWRlIGFuZCBsb25nIGZvcm1hdCBsb29rIGxpa2UuIEZvciB3aGF0ZXZlciByZWFzb24sIHRoZSBnZ3Bsb3QyIHBhY2thZ2UgdGVuZHMgdG8gd29yayBiZXR0ZXIgd2l0aCBsb25nIGRhdGEuIFdlJ2xsIHJlc2hhcGUgdGhlIGRhdGEgdXNpbmcgYSBjb21tYW5kIGZyb20gdGhlIHRpZHlyIHBhY2thZ2UsIHBpdm90X2xvbmdlci4gDQoNCmBgYHtyfQ0Kd2lkZV9kYXRhIDwtIHRlbXBzICU+JSANCiAgI3dlJ2xsIG9ubHkgc2VsZWN0IHRoZSB2YXJpYWJsZXMgb2YgaW50ZXJlc3QgdG8gZG8gdGhpcw0KICBzZWxlY3QoYyhkYXksIGFjdHVhbF9tZWFuX3RlbXAsIGFjdHVhbF9taW5fdGVtcCwgYWN0dWFsX21heF90ZW1wKSkNCg0KI2xldCdzIGNoYW5nZSB0aGUgY29sdW1uIG5hbWVzIHRvIG1ha2UgdGhlbSBhIGJpdCBuaWNlcjoNCiNJJ2xsIHNob3cgeW91IHdoeSB0aGlzIG1hdHRlcnMgc29vbi4gDQpjb2xuYW1lcyh3aWRlX2RhdGEpIDwtIGMoIkRheSIsICJNZWFuIiwgIk1pbiIsICJNYXgiKQ0KDQpoZWFkKHdpZGVfZGF0YSkNCmBgYA0KYGBge3J9DQojTm93IHdlJ2xsIHJlc2hhcGUgaXQhDQoNCmxvbmdfZGF0YSA8LSB3aWRlX2RhdGEgJT4lIA0KICAjVGhlIGNvbHVtbiB0aXRsZXMgYmVjb21lIHRoZSBjYXRlZ29yaWVzIGluIGEgbmV3IGNvbHVtbiBhZnRlciB0aGUgcmVzaGFwaW5nDQogICNJJ20gbmFtaW5nIHRoaXMgbmV3IGNvbHVtbiB0ZW1wX3R5cGUNCiAgI1RoZSB0ZW1wZXJhdHVyZSB2YWx1ZXMgYXJlIHB1dCBpbiBhIG5ldyB2YWx1ZXMgY29sdW1uLCB3aGljaCBJJ20gY2FsbGluZyB0ZW1wDQogIHBpdm90X2xvbmdlcighRGF5LCBuYW1lc190byA9ICJ0ZW1wX3R5cGUiLCB2YWx1ZXNfdG8gPSAidGVtcCIpDQoNCmhlYWQobG9uZ19kYXRhKQ0KYGBgDQpgYGB7cn0NCiNXaGF0IGlmIEkgd2FudGVkIHRvIGdvIGZyb20gbG9uZyB0byB3aWRlIGRhdGE/IEhlcmUncyB3aGF0IHRoYXQgbG9va3MgbGlrZSwgZm9yIHlvdXIgcmVmZXJlbmNlOg0KDQp3aWRlX2RhdGExIDwtIGxvbmdfZGF0YSAlPiUgDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSB0ZW1wX3R5cGUsIHZhbHVlc19mcm9tID0gdGVtcCkNCg0KI1J1biB0aGlzIGNvZGUgdG8gdmVyaWZ5IHRoYXQgdGhlIG9yaWdpbmFsIHdpZGVfZGF0YSBhbmQgb3VyIG5ldyB3aWRlX2RhdGExIGRhdGFmcmFtZSBhcmUgdGhlIHNhbWUuIExvZ2ljYWwgZGF0YSBpcyBoZWxwZnVsIGluIHRoaXMgY2FzZSENCiNJJ20gc2V0dGluZyB0aGUgbnVtYmVyIG9mIHZhbHVlcyB0aGF0IFIgcHJpbnRzIG91dCB0byAyMCAtIG90aGVyd2lzZSwgUiB3b3VsZCBwcmludCB0aGUgd2hvbGUgZGF0YXNldCBvbiB0aGUgc2NyZWVuLCBhbmQgaXQgd291bGQgdGFrZSB1cCBhIGxvdCBvZiBzcGFjZSENCm9wdGlvbnMobWF4LnByaW50ID0gMjApDQp3aWRlX2RhdGExID09IHdpZGVfZGF0YQ0KYGBgDQoNCg0KRG8geW91IHNlZSB0aGUgZGlmZmVyZW5jZT8gTm93LCB0aGUgY2F0ZWdvcnkgKHRlbXBfdHlwZSwgb3IgbWVhbiwgbWluLCBhbmQgbWF4KSBpcyBpbiBvbmUgY29sdW1uLCB3aGlsZSBlYWNoIHRlbXBlcmF0dXJlIHRoYXQgY29ycmVzcG9uZHMgdG8gdGhlIHRlbXBfdHlwZSBhbmQgZGF5IGlzIGluIHRoZSB0ZW1wIGNvbHVtbi4gVGhlIHdpZGUgYW5kIGxvbmcgZGF0YSBzZXRzIGFyZSBqdXN0IGRpZmZlcmVudCB3YXlzIG9mIHN0b3JpbmcgdGhlIHNhbWUgZGF0YSEgTm93IGxldCdzIHNlZSBob3cgdGhpcyB3b3JrcyBpbiBnZ3Bsb3QyLiANCg0KYGBge3J9DQoNCiNOb3csIGluc3RlYWQgb2YgdGhyZWUgZ2VvbSBsYXllcnMsIHdlIHdpbGwgbmVlZCB0byBwbG90IHRoZSBkYXRhIGJ5IHRocmVlIGdyb3VwczogbWVhbiwgbWluLCBhbmQgbWF4LiBCZWNhdXNlIHdlIGFyZSBncm91cGluZyB0aGUgZGF0YSBpbiB0aGUgZGF0YWZyYW1lIGJ5IHRoZSB0eXBlIG9mIHRlbXBlcmF0dXJlIHJlY29yZGVkLCB3ZSBuZWVkIHRvIGFzc2lnbiB0aGUgdGVtcF90eXBlIGNvbHVtbiB0byB0aGUgZ3JvdXAgYXJndW1lbnQuIEJlY2F1c2UgZWFjaCB0eXBlIG9mIHRlbXBlcmF0dXJlIHdpbGwgYWxzbyBoYXZlIGEgZGlmZmVyZW50IGNvbG9yLCB3ZSB3aWxsIGFzc2lnbiB0ZW1wX3R5cGUgdG8gdGhlIGNvbG9yIGFyZ3VtZW50IGFzIHdlbGwuIExldCdzIHNlZSB3aGF0IHRoaXMgbG9va3MgbGlrZSENCg0KZ2dwbG90KGxvbmdfZGF0YSwgYWVzKHggPSBEYXksIHkgPSB0ZW1wLCBncm91cCA9IHRlbXBfdHlwZSwgY29sb3IgPSB0ZW1wX3R5cGUpKSArDQogIGdlb21fcG9pbnQoKSArDQogIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSIsIHggPSAiRGF5IiwgDQogICAgICAgdGl0bGUgPSAiRGFpbHkgVGVtcGVyYXR1cmUgaW4gTmV3IFlvcmsgQ2l0eSwgMjAxNCIsDQogICAgICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgKEYpIikNCmBgYA0KDQpEbyB5b3Ugc2VlIHdoeSBJIGNoYW5nZWQgdGhlIGNvbHVtbiBuYW1lcz8gUiB1c2VzIHRoZSBjYXRlZ29yaWVzIGluIHRoZSB0ZW1wX3R5cGUgY29sdW1uIHRvIGFkZCBuYW1lcyB0byB0aGUgbGVnZW5kLiBLZWVwaW5nIHRoZSAiYWN0dWFsX21lYW5fdGVtcCIgKGFuZCBzbyBvbikgbGFiZWxzIHdvdWxkIG5vdCBoYXZlIGJlZW4gbmVhcmx5IGFzIGNsZWFyIGluIGEgbGVnZW5kLiBJbiBvdXIgZ3JhcGhzLCB3ZSBzaG91bGQgYWltIHRvIHNob3cgY29tcGxleCBpbmZvcm1hdGlvbiBpbiB0aGUgc2ltcGxlc3Qgd2F5IHBvc3NpYmxlIC0gaGF2aW5nIGNsZWFyIGxlZ2VuZCBhbmQgYXhpcyB0aXRsZXMgaXMga2V5IHRvIHRoYXQuIE5vdywgaW4gdGhpcyBjYXNlLCB0aGUgY29sb3JzIGFyZW4ndCBxdWl0ZSByaWdodCEgTGV0J3Mgc2V0IHRoZW0gbWFudWFsbHkuIA0KDQpgYGB7cn0NCiNjcmVhdGUgdGhlIGNvbG9yIHBhbGV0dGUgZm9yIHRoZSBkYXRhDQojUmVtZW1iZXIsIG9yZGVyIG1hdHRlcnMhIEJhc2VkIG9uIHRoZSBvcmRlciBvZiB0aGUgbGVnZW5kIGluIHRoZSBsYXN0IGdyYXBoLCBJIHdpbGwgaW5jbHVkZSB0aGUgY29sb3IgZm9yIHRoZSBtYXggdGVtcCwgdGhlbiB0aGUgbWVhbiwgdGhlbiB0aGUgbWluLiANCg0KY29sb3JzIDwtIGMoInJlZCIsICJncmF5IiwgImJsdWUiKQ0KDQpnZ3Bsb3QobG9uZ19kYXRhLCBhZXMoeCA9IERheSwgeSA9IHRlbXAsIGdyb3VwID0gdGVtcF90eXBlLCBjb2xvciA9IHRlbXBfdHlwZSkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IiwNCiAgICAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSAoRikiKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9ycykNCmBgYA0KDQpEbyB5b3Ugc2VlIGhvdyBtdWNoIHNpbXBsZXIgYW5kIHNob3J0ZXIgdGhlIGdncGxvdDIgY29kZSBpcyBub3c/IFJlc2hhcGluZyBkYXRhIGRlZmluaXRlbHkgdGFrZXMgc29tZSBnZXR0aW5nIHVzZWQgdG8sIGJ1dCBpdCdsbCBzYXZlIHlvdSB0aW1lIGluIHRoZSBmdXR1cmUuIEJlZm9yZSB3ZSBtb3ZlIG9uLCBJJ2xsIHNob3cgeW91IG9uZSBtb3JlIHdheSB0byBzZXQgdGhlIGNvbG9ycywgbm93IHRoYXQgd2UgaGF2ZSB0aGUgZGF0YSBpbiBsb25nIGZvcm1hdC4gVGhpcyB0aGlyZCB2ZXJzaW9uIHdpbGwgaW50cm9kdWNlIHlvdSB0byBhIGZ1bmN0aW9uIHRoYXQgaXMgaGVscGZ1bCB3aXRoaW4gZHBseXIgZnVuY3Rpb25zLCBpZmVsc2UuIA0KDQpgYGB7cn0NCiNUaGlzIHZlcnNpb24gaW52b2x2ZXMgY3JlYXRpbmcgYSBuZXcgY29sdW1uIGluIHRoZSBsb25nIGRhdGFmcmFtZSB3aXRoIHRoZSBjb2xvciB2YWx1ZXMgaW4gaXQuIEVhY2ggY29sb3Igd2lsbCBjb3JyZXNwb25kIHRvIHRoZSBjb3JyZWN0IHRlbXBfdHlwZS4gDQoNCmxvbmdfZGF0YSA8LSBsb25nX2RhdGEgJT4lIA0KICBtdXRhdGUoY29sb3JzID0gaWZlbHNlKHRlbXBfdHlwZSA9PSAiTWF4IiwgInJlZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRlbXBfdHlwZSA9PSAiTWVhbiIsICJncmF5IiwgImJsdWUiKSkpDQoNCiNMZXQncyB3YWxrIHRocm91Z2ggdGhlIHN5bnRheCBvZiB0aGUgaWZlbHNlIGZ1bmN0aW9uIChub3RlIHRoYXQgaXQgc3RhbmQgZm9yICJpZiBlbHNlIikNCiNZb3UgY2FuIHJlYWQgdGhlIGNvZGUgbGlrZSB0aGlzOiBpZiB0ZW1wX3R5cGUgaXMgZXF1YWwgdG8gTWF4LCBzZXQgdGhlIHZhbHVlIHRvIHJlZA0KI2lmIHRlbXAgdHlwZSBpcyBlcXVhbCB0byBNZWFuLCBzZXQgdGhlIGNvbG9yIHRvIGdyYXkuIA0KI0ZvciBhbGwgb3RoZXJzLCBzZXQgdGhlIGNvbG9yIHRvIGJsdWUuIA0KI0lmIHlvdSBsb29rIHVwIHRoZSBkb2N1bWVudGF0aW9uIHRvIGlmZWxzZSwgeW91J2xsIHNlZSBqdXN0IGhvdyBzaW1wbGUgaXQgaXM6DQojaWZlbHNlKHRlc3QsIHllcywgbm8pDQojeW91IGdpdmUgdGhlIGZ1bmN0aW9uIHRoZSB0ZXN0LCBhbmQgc2V0IGEgdmFsdWUgdG8gY29ycmVzcG9uZCB0byB5ZXMgKFRydWUpIGFuZCBubyAoRmFsc2UpIGFuc3dlcnMuIEluIHRoaXMgY29kZSwgSSBoYXZlIG5lc3RlZCBhbiBpZmVsc2UgZnVuY3Rpb24gaW5zaWRlIG9mIGFub3RoZXIgb25lLCBiYXNpY2FsbHkgdGVsbGluZyBSIHRoYXQgbm8gb3IgZmFsc2UgdmFsdWVzIGJhc2VkIG9uIHRoZSBmaXJzdCBjYWxsIHRvIGlmZWxzZSBhcmUgc3ViamVjdCB0byBhbm90aGVyIGlmZWxzZSBzdGF0ZW1lbnQuIFZhbHVlcyB0aGF0IGFyZSBubyBvciBmYWxzZSBpbiBib3RoIGNhbGxzIG90IGlmZWxzZSB3aWxsIGJlIGJsdWUgKG5vdGUgdGhhdCB0aGVzZSBhcmUgdGhlIG1pbmltdW0gdmFsdWVzKS4NCiNMZXQncyBncmFwaCB0aGlzIQ0KDQpnZ3Bsb3QobG9uZ19kYXRhLCBhZXMoeCA9IERheSwgeSA9IHRlbXAsIGdyb3VwID0gdGVtcF90eXBlLCBjb2xvciA9IGNvbG9ycykpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IiwNCiAgICAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSAoRikiKSsNCiAgc2NhbGVfY29sb3JfaWRlbnRpdHkoZ3VpZGUgPSAibGVnZW5kIiwgbGFiZWxzID0gYygiTWluIiwgIk1lYW4iLCAiTWF4IikpDQoNCiNJZiB5b3Ugd2FudCB0byB1c2UgdGhpcyBtZXRob2QsIHlvdSBuZWVkIHRvIGFsc28gaW5jbHVkZSB0aGUgc2NhbGVfY29sb3JfaWRlbnRpdHkgYXJndW1lbnQgLSB0aGlzIHRlbGxzIFIgdG8gdXNlIGNvbG9ycyBmcm9tIHRoZSBkYXRhLiBJIGFsc28gaGFkIHRvIHNwZWNpZnkgdGhlIGxlZ2VuZCBsYWJlbCBuYW1lcyB1c2luZyB0aGUgbGFiZWxzID0gYXJndW1lbnQgLSBhZ2FpbiwgUiBpcyB3ZWlyZCBhYm91dCB2YXJpYWJsZSBvcmRlciwgYW5kIEkgaGFkIHRvIGluY2x1ZGUgdGhlIGxhYmVsIG5hbWVzIGluIHRoZSBzYW1lIG9yZGVyIHRoYXQgUiB1c2VzIGluIHRoZSBsZWdlbmQuIEZvciB3aGF0ZXZlciByZWFzb24sIHRoaXMgb3JkZXIgaXMgYSBiaXQgcmFuZG9tLg0KYGBgDQpPdmVyYWxsLCB0aGUgc2Vjb25kIG1ldGhvZCBvZiBhZGRpbmcgY29sb3IgZm9yIG11bHRpcGxlIHZhcmlhYmxlcyAocmVzaGFwaW5nIHRoZSBkYXRhIGFuZCB1c2luZyBhIGNvbG9yIHBhbGV0dGUgb2JqZWN0IHRvIHNldCBjb2xvcnMpIGlzIHByb2JhYmx5IHRoZSBtb3N0IGZsZXhpYmxlIG1ldGhvZC4gT2Z0ZW4sIHlvdSdsbCBiZSBhYmxlIHRvIHNldCBwYWxldHRlcyB1c2luZyBmdW5jdGlvbnMsIHdoaWNoIG1ha2VzIHRoZSBwcm9jZXNzIGV2ZW4gZmFzdGVyOyBpdCdzIHVubGlrZWx5IHRoYXQgeW91J2xsIG5lZWQgdG8gbWFudWFsbHkgc3BlY2lmeSBjb2xvcnMuIEluIHRoZSBuZXh0IGNodW5rIG9mIGNvZGUsIEknbGwgZ2l2ZSBhbiBleGFtcGxlIHVzaW5nIGEgcGFja2FnZSB0aGF0IGNvbnRhaW5zIHNvbWUgcmVhbGx5IG5pY2UgY29sb3IgcGFsZXR0ZXMgaW5zcGlyZWQgYnkgVVMgbmF0aW9uYWwgcGFya3MuIE1vcmUgaW5mbyBvbiB0aGUgcGFsZXR0ZXMgYXJlIGhlcmU6IGh0dHBzOi8vZ2l0aHViLmNvbS9rYXRpZWpvbGx5L25hdGlvbmFscGFya2NvbG9ycy4gWW91IGNhbiB1c2UgdGhlIGNvZGUgZnJvbSB0aGUgZ2l0aHViIGxpbmsgdG8gaW5zdGFsbCB0aGUgcGFja2FnZSwgdG9vLiANCk90aGVyIHBhY2thZ2VzLCBsaWtlIFJDb2xvckJyZXdlciwgYWxzbyBwcm92aWRlIGEgcmFuZ2Ugb2YgcGFsZXR0ZXMgdG8gY2hvb3NlIGZyb20uIA0KDQpgYGB7cn0NCiNJIGFscmVhZHkgaGF2ZSB0aGlzIGluc3RhbGxlZCAtIEkgbGlrZSB1c2luZyB0aGVzZSBjb2xvcnMgZm9yIHByZXNlbnRhdGlvbnMuIA0KbGlicmFyeShuYXRpb25hbHBhcmtjb2xvcnMpDQoNCiNJJ3ZlIGp1c3QgcGlja2VkIGEgcmFuZG9tIHBhbGV0dGUsIHRoZXNlIGNvbG9ycyBhcmVuJ3QgbWVhbmluZ2Z1bC4gDQpwYWxldHRlIDwtIHBhcmtfcGFsZXR0ZSgiWmlvbiIsIG4gPSAzKQ0KDQoNCiNOb3cgZ3JhcGggaXQgd2l0aCB0aGUgcGFsZXR0ZSENCmdncGxvdChsb25nX2RhdGEsIGFlcyh4ID0gRGF5LCB5ID0gdGVtcCwgZ3JvdXAgPSB0ZW1wX3R5cGUsIGNvbG9yID0gdGVtcF90eXBlKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUiLCB4ID0gIkRheSIsIA0KICAgICAgIHRpdGxlID0gIkRhaWx5IFRlbXBlcmF0dXJlIGluIE5ldyBZb3JrIENpdHksIDIwMTQiLA0KICAgICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIChGKSIpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gcGFsZXR0ZSkNCmBgYA0KU28gbm93IHlvdSBrbm93IHRoZSBiYXNpY3Mgb2YgZ3JhcGhpbmcgd2l0aCBnZ3Bsb3QyISBUaGVyZSBhcmUganVzdCBhIGZldyBtb3JlIHRvcGljcyB0byBjb3ZlciB0aGF0IHlvdSB3aWxsIGZpbmQgaGVscGZ1bC4gRmlyc3QsIHdoYXQgaWYgSSBkb24ndCB3YW50IHRvIHVzZSBhIHNjYXR0ZXIgcGxvdD8gR2dwbG90MiBjb21lcyB3aXRoIGEgd2lkZSByYW5nZSBvZiBnZW9tIHBvc3NpYmlsaXRpZXMhIEl0J3Mgc28gZWFzeSB0byBwcm9kdWNlIGRpZmZlcmVudCBraW5kcyBvZiBwbG90cyBvZiB5b3VyIGRhdGEuIExldCdzIG1ha2UgYSBsaW5lIHBsb3Qgd2l0aCB0aGUgZGF0YSB3ZSBhbHJlYWR5IGhhdmUuIA0KDQpgYGB7cn0NCg0KZ2dwbG90KGxvbmdfZGF0YSwgYWVzKHggPSBEYXksIHkgPSB0ZW1wLCBncm91cCA9IHRlbXBfdHlwZSwgY29sb3IgPSB0ZW1wX3R5cGUpKSArDQogIGdlb21fbGluZSgpICsNCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IiwNCiAgICAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSAoRikiKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGUpDQoNCmBgYA0KVGhlIGxpbmUgcGxvdCBkb2Vzbid0IGxvb2sgbmljZSBhbmQgc21vb3RoIGJlY2F1c2Ugd2UncmUgd29ya2luZyB3aXRoIGRhaWx5IGRhdGEgLSB0aGVyZSBhcmUgYSBsb3Qgb2YgZGF0YSBwb2ludHMsIGFuZCB0aGUgdGVtcGVyYXR1cmVzIG1vdmUgYXJvdW5kIGEgbG90ISBCdXQgYXMgeW91IGNhbiBzZWUsIHN3aXRjaGluZyB0byBhIGxpbmUgcGxvdCB3YXMgc28gZWFzeS4gTmV4dCwgd2UgY2FuIGxvb2sgYXQgYSBiYXIgcGxvdC4gTGluZSBwbG90cywgc2NhdHRlciBwbG90cywgYW5kIGJhciBwbG90cyB3aWxsIGJlIHRoZSBtb3N0IGNvbW1vbiBwbG90cyB5b3UnbGwgdXNlLiANCg0KYGBge3J9DQojUmVtZW1iZXIgdGhhdCBiYXIgcGxvdHMgZG9uJ3QgcmVxdWlyZSB4IGFuZCB5IHZhcmlhYmxlcyAtIHdlIGp1c3QgbmVlZCBvbmUgeSB2YXJpYWJsZSAoaW4gdGhpcyBjYXNlLCB0ZW1wZXJhdHVyZSkgYW5kIGNhdGVnb3JpZXMgZm9yIHRoZSB4LWF4aXMgKGluIHRoaXMgY2FzZSwgdGVtcF90eXBlKS4gTGV0J3MgbWFrZSBhIHNpbXBsZSBiYXIgcGxvdCBmb3Igb25lIGRheToNCg0KZGF5MSA8LSBsb25nX2RhdGEgJT4lIGZpbHRlcihEYXkgPT0gMSkNCg0KZ2dwbG90KGRheTEsIGFlcyh5ID0gdGVtcCwgeCA9IHRlbXBfdHlwZSwgZ3JvdXAgPSB0ZW1wX3R5cGUsIGZpbGwgPSB0ZW1wX3R5cGUpKSsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJJZGVudGl0eSIpKw0KICBsYWJzKHggPSAiVGVtcGVyYXR1cmUgVHlwZSIsIHkgPSAiVGVtcGVyYXR1cmUiLA0KICAgICAgIHRpdGxlID0gIlRlbXBlcmF0dXJlcyBpbiBPbmUgRGF5IGluIE5ZQyIpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGUpDQoNCiNTb21lIHRoaW5ncyB0byBub3RlIGFib3V0IHRoaXMgY29kZTogYmVjYXVzZSBJIGhhdmUgaW5jbHVkZWQgdGhlIGNhdGVnb3JpZXMgYXMgeC12YWx1ZXMsIEkgbmVlZCB0byBpbmNsdWRlIHRoZSBhcmd1bWVudCBzdGF0ID0gIklkZW50aXR5IiBpbiB0aGUgZ2VvbV9iYXIgbGF5ZXIuIFdpdGhvdXQgZ29pbmcgaW50byB0b28gbXVjaCBkZXRhaWwsIHRoaXMgYXJndW1lbnQgdGVsbHMgUiB0aGF0IHRoZSBoZWlnaHQgb2YgdGhlIGNvbHVtbnMgc2hvdWxkIGJlIGVxdWFsIHRvIHRoZSB0ZW1wIHZhbHVlcy4gTm90ZSBhbHNvIHRoYXQgaW5zdGVhZCBvZiBjb2xvciwgd2UgdXNlIHRoZSBmaWxsPSBhcmd1bWVudCBoZXJlIC0gdGhlIGNvbG9yIGFyZ3VtZW50IGlzIGZvciBsaW5lcyBhbmQgcG9pbnRzLCB3aGlsZSBzb2xpZCBwb2x5Z29ucyBuZWVkIHRvIGJlIGFzc2lnbmVkIGNvbG9ycyB1c2luZyB0aGUgZmlsbCBhcmd1bWVudC4gQXMgYW4gZXhlcmNpc2UsIHRyeSBzZWVpbmcgd2hhdCBoYXBwZW5zIHdoZW4geW91IHVzZSBjb2xvciA9IGluc3RlYWQhIFdoZW4geW91IHVzZSBmaWxsLCB0aGUgc2NhbGVfY29sb3JfbWFudWFsIGFyZ3VtZW50IGFsc28gY2hhbmdlcyB0byBzY2FsZV9maWxsX21hbnVhbCB0byBzZXQgdGhlIGNvbG9yIHBhbGV0dGUuIEZpbmFsbHksIFIgd2lsbCBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlIGEgbGVnZW5kIHdoZW4geW91IGFzc2lnbiBjb2xvcnMgdXNpbmcgdGhlIGdyb3VwIGFlc3RoZXRpYyAtIEkgZGlkbid0IG5lZWQgYSBsZWdlbmQgaW4gdGhpcyBncmFwaCwgc28gSSB1c2VkIHRoZSB0aGVtZSgpIGFyZ3VtZW50IHRvIHNldCB0aGUgbGVnZW5kIHBvc2l0aW9uIHRvICJub25lIi4gVGhpcyBkZWxldGVzIHRoZSBsZWdlbmQgZnJvbSB0aGUgcGxvdCwgYW5kIGlzIHdvcnRoIHJlbWVtYmVyaW5nLiANCmBgYA0KTGV0J3MgdGhpbmsgYWJvdXQgc29tZSBvdGhlciB3YXlzIHlvdSBjYW4gY3VzdG9taXplIHlvdXIgcGxvdHMuIE9uZSB3YXkgdGhhdCB3ZSBjYW4gbWFrZSBvdXIgcGxvdCBsb29rIG5pY2UgaXMgYnkgYWRkaW5nIGEgdmlzdWFsIHRoZW1lLiBUaGVyZSBhcmUgYSBudW1iZXIgb2YgdGhlbWVzIHlvdSBjYW4gYWRkIHRvIHlvdXIgcGxvdCAtIHdlJ2xsIGRvd25sb2FkIGEgbmV3IHBhY2thZ2Ugbm93IHRoYXQgY29udGFpbnMgc29tZSBhZGRpdGlvbmFsIHRoZW1lcyBhcyB3ZWxsLiANCg0KYGBge3J9DQpsaWJyYXJ5KGdndGhlbWVzKQ0KDQojSSBwcmVmZXIgdGhlIG1pbmltYWwgdGhlbWUgdGhhdCBjb21lcyBsb2FkZWQgd2l0aCBnZ3Bsb3QyIC0gaXQgbWFrZXMgcGxvdHMgbG9vayB2ZXJ5IHNsZWVrIA0KZ2dwbG90KGxvbmdfZGF0YSwgYWVzKHggPSBEYXksIHkgPSB0ZW1wLCBncm91cCA9IHRlbXBfdHlwZSwgY29sb3IgPSB0ZW1wX3R5cGUpKSArDQogIGdlb21fbGluZSgpICsNCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IiwNCiAgICAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSAoRikiKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGUpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KYGBge3J9DQojVGhlIGdndGhlbWVzIHBhY2thZ2UgY29tZXMgd2l0aCBzb21lIG90aGVyIHVzZWZ1bCB0aGVtZXMuIExldCdzIHRyeSBhIGZldyBtb3JlOg0KI0lmIHlvdSB3YW50IHlvdXIgcGxvdCB0byBsb29rIGxpa2UgdGhlIHBsb3RzIGluIHRoZSBFY29ub21pc3QgbWFnYXppbmUsIHlvdSBtaWdodCB1c2UgdGhpcyB0aGVtZToNCg0KZ2dwbG90KGxvbmdfZGF0YSwgYWVzKHggPSBEYXksIHkgPSB0ZW1wLCBncm91cCA9IHRlbXBfdHlwZSwgY29sb3IgPSB0ZW1wX3R5cGUpKSArDQogIGdlb21fbGluZSgpICsNCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IiwNCiAgICAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSAoRikiKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGUpKw0KICB0aGVtZV9lY29ub21pc3QoKQ0KYGBgDQpgYGB7cn0NCg0KI1RoaXMgdGhlbWUgbWltaWNzIHBsb3RzIGRyYXduIGJ5IHRoZSBXYWxsIFN0cmVldCBKb3VybmFsOg0KZ2dwbG90KGxvbmdfZGF0YSwgYWVzKHggPSBEYXksIHkgPSB0ZW1wLCBncm91cCA9IHRlbXBfdHlwZSwgY29sb3IgPSB0ZW1wX3R5cGUpKSArDQogIGdlb21fbGluZSgpICsNCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IiwNCiAgICAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSAoRikiKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGUpKw0KICB0aGVtZV93c2ooKQ0KYGBgDQoNCklmIHlvdSB0eXBlIHRoZW1lXyB5b3Ugc2hvdWxkIGdldCBhIGRyb3AgZG93biBtZW51IG9mIGFsbCBvZiB0aGUgcG9zc2libGUgdGhlbWVzIHRvIGNob29zZSBmcm9tIC0gSSB3b3VsZCBlbmNvdXJhZ2UgeW91IHRvIHBsYXkgYXJvdW5kIHdpdGggdGhlbSwgYW5kIHNlZSB3aGljaCBvbmUgeW91IGxpa2UgYmVzdCEgDQoNCmBgYHtyfQ0KI0ZpbmFsbHksIHlvdSBjYW4gdXNlIHRoZSB0aGVtZSBmdW5jdGlvbiB0byBjaGFuZ2UgdGhlIGNlbnRlcmluZyBvZiB0aGUgdGl0bGUgYW5kIG90aGVyIHRleHQuIEJ5IHRoZSBkZWZhdWx0LCBldmVyeXRoaW5nIGlzIGxlZnQtYWxpZ25lZC4gDQoNCmdncGxvdChsb25nX2RhdGEsIGFlcyh4ID0gRGF5LCB5ID0gdGVtcCwgZ3JvdXAgPSB0ZW1wX3R5cGUsIGNvbG9yID0gdGVtcF90eXBlKSkgKw0KICBnZW9tX2xpbmUoKSArDQogIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSIsIHggPSAiRGF5IiwgDQogICAgICAgdGl0bGUgPSAiRGFpbHkgVGVtcGVyYXR1cmUgaW4gTmV3IFlvcmsgQ2l0eSwgMjAxNCIsDQogICAgICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgKEYpIikrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBwYWxldHRlKSArDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpDQoNCiNOb3RlIHRoYXQgdGhlIGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkgYXJndW1lbnQgaXMgdGVsbGluZyBSIHRvIGNlbnRlci1hbGlnbiB0aGUgdGl0bGUgdGV4dA0KI1lvdSBjYW4gcGxheSBhcm91bmQgd2l0aCB0aGUgaGp1c3QgYXJndW1lbnQgdG8gbWFudWFsbHkgY2hhbmdlIHRoZSB0aXRsZSBwb3NpdGlvbiAoYWx0aG91Z2ggSSBkb24ndCByZWFsbHkgc2VlIGFueSByZWFzb24gdG8gZG8gdGhpcykNCmBgYA0KRmluYWxseSwgY2FuIHlvdSB1c2UgbW9yZSB0aGFuIG9uZSBwbG90IHR5cGUgaW4gdGhlIHNhbWUgcGxvdD8gWW91IHN1cmUgY2FuISBUaGUgY29kZSBiZWxvdyBzaG93cyB3aGF0IHRoaXMgbG9va3MgbGlrZSBieSBhZGRpbmcgYSB0cmVuZCBsaW5lIHRvIHRoZSBkYXRhIHVzaW5nIGEgc21vb3RoaW5nIG1ldGhvZCAoZG9uJ3Qgd29ycnkgYWJvdXQgaG93IGl0IHdvcmtzLCB0aGlzIGlzIGp1c3QgYW4gZXhhbXBsZSkuIEluIHRoaXMgZXhhbXBsZSwgYmVjYXVzZSB3ZSBhcmUgdXNpbmcgdGhlIHNtb290aGluZyBmdW5jdGlvbiB0byBmaW5kIHRoZSBhdmVyYWdlIHZhbHVlcyBvZiBlYWNoIHRlbXBlcmF0dXJlIHR5cGUsIHdlIGRvbid0IG5lZWQgdG8gY2hhbmdlIHRoZSBhZXN0aGV0aWNzLiBJZiwgZm9yIGV4YW1wbGUsIHlvdSB3YW50ZWQgdG8gbWFrZSBhIGxpbmUgZ3JhcGggd2l0aCBvbmUgdmFyaWFibGUgb3ZlciB0aW1lIGFuZCBhIHBvaW50IGdyYXBoIHdpdGggYSBkaWZmZXJlbnQgdmFyaWFibGUgb3ZlciB0aW1lLCB5b3Ugd291bGQgbmVlZCB0byBtYW51YWxseSBpbmNsdWRlIHRoZSBhZXN0aGV0aWNzIGluIGVhY2ggZ2VvbSBsYXllciAobGlrZSB3ZSBkaWQgdGhlIGZpcnN0IHRpbWUgd2UgYWRkZWQgY29sb3IgLSBpbiB0aGF0IGV4YW1wbGUsIGVhY2ggdmFyaWFibGUgaGFkIGl0cyBvd24gZ2VvbSBsYXllciwgYW5kIHdlIGhhZCB0byBtYXAgdGhlIGFlc3RoZXRpY3MgZm9yIGVhY2ggb25lKS4gDQoNCmBgYHtyfQ0KDQpnZ3Bsb3QobG9uZ19kYXRhLCBhZXMoeCA9IERheSwgeSA9IHRlbXAsIGdyb3VwID0gdGVtcF90eXBlLCBjb2xvciA9IHRlbXBfdHlwZSkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9zbW9vdGgoY29sb3IgPSAiYmxhY2siKSsNCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IiwNCiAgICAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSAoRikiKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGUpICsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkNCg0KYGBgDQpBbmQgdGhlcmUgeW91IGhhdmUgaXQhIFlvdSBhcmUgbm93IGEgcHJvIGF0IHVzaW5nIGdncGxvdDIuIFlvdSBzaG91bGQgaGF2ZSBhbGwgdGhlIHRvb2xzIHlvdSBuZWVkIHRvIG1ha2UgYmVhdXRpZnVsIGFuZCBlZmZlY3RpdmUgdmlzdWFsaXphdGlvbiBpbiBSLiBJZiB5b3Ugd2FudCBtb3JlIGluZm9ybWF0aW9uIG9uIGRpZmZlcmVudCB0eXBlcyBvZiBncmFwaHMsIG9yIHlvdSBqdXN0IHdhbnQgYSBoZWxwZnVsIHJlZmVyZW5jZSB0byByZWZlciB0byBhcyB5b3UgcHJvZ3Jlc3MgdGhyb3VnaCB0aGUgY291cnNlLCB5b3UgY2FuIGZpbmQgYW4gZXhjZWxsZW50IGdncGxvdDIgY2hlYXQgc2hlZXQgaGVyZTogaHR0cHM6Ly93d3cubWF0aHMudXN5ZC5lZHUuYXUvdS9VRy9TTS9TVEFUMzAyMi9yL2N1cnJlbnQvTWlzYy9kYXRhLXZpc3VhbGl6YXRpb24tMi4xLnBkZi4gDQoNCg0KUmVzb3VyY2VzDQoNCkZpdmVUaGlydHlFaWdodCAoMjAxNCkuIFVTLiBXZWF0aGVyIEhpc3RvcnkuIFtEYXRhIFNldF0uIFJldHJpZXZlZCBmcm9tOiBodHRwczovL2dpdGh1Yi5jb20vZml2ZXRoaXJ0eWVpZ2h0L2RhdGEvdHJlZS9tYXN0ZXIvdXMtd2VhdGhlci1oaXN0b3J5LiANCg0KUHJhYmhha2FyYW4sIFMuICgyMDE3KS4gVGhlIENvbXBsZXRlIGdncGxvdDIgVHV0b3JpYWwgLSBQYXJ0MSB8IEludHJvZHVjdGlvbiBUbyBnZ3Bsb3QyLiBSZXRyaWV2ZWQgZnJvbTogaHR0cDovL3Itc3RhdGlzdGljcy5jby9Db21wbGV0ZS1HZ3Bsb3QyLVR1dG9yaWFsLVBhcnQxLVdpdGgtUi1Db2RlLmh0bWwuIA==