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.

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.

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.

library(tidyr)
Warning: package ‘tidyr’ was built under R version 4.0.5

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.

LS0tDQp0aXRsZTogIldlZWsgMyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KDQotLS0NClRvZGF5IHdlIGFyZSBnb2luZyB0byBsZWFybiBob3cgdG8gcGxvdCBkYXRhIGluIFIhIFdoaWxlIHRoZXJlIGFyZSBzb21lIHNpbXBsZSBwbG90dGluZyBmdW5jdGlvbnMgYnVpbHQgaW50byBiYXNlIFIgKHlvdSB3aWxsIG9mdGVuIHNlZSB0dXRvcmlhbHMgdGhhdCB1c2UgdGhlIHBsb3QoKSBjb21tYW5kKSwgSSBlbmNvdXJhZ2UgeW91IHRvIHByb2R1Y2UgeW91ciBwbG90cyBhbmQgZGF0YSB2aXN1YWxpemF0aW9ucyB1aXNuZyB0aGUgZ2dwbG90MiBwYWNrYWdlIGluIFIuIFRoaXMgcGFja2FnZSB0YWtlcyBhIGxpdHRsZSBnZXR0aW5nIHVzZWQgdG8sIGJ1dCBvbmNlIHlvdSB1bmRlcnN0YW5kIHRoZSBzeW50YXggeW91IHdpbGwgYmUgbWFraW5nIGVmZmVjdGl2ZSBncmFwaHMgYW5kIHZpc3VhbGl6YXRpb25zIGluIG5vIHRpbWUhIFZpc3VhbGl6aW5nIGRhdGEgaXMgc3VjaCBhbiBpbXBvcnRhbnQgcGFydCBvZiB0aGUgZGF0YSBhbmFseXNpcyBwcm9jZXNzOiBpdCBoZWxwcyB1cyB0byBiZXR0ZXIgdW5kZXJzdGFuZCB0aGUgZGF0YSBhbmQgaXRzIGRpc3RyaWJ1dGlvbiwgaXQgYWxsb3dzIHVzIHRvIGlkZW50aWZ5IGFuZCBjb21tdW5pY2F0ZSBwYXR0ZXJucyBpbiBzaW1wbGUgYW5kIHZpc3VhbGx5IGFwcGVhbGluZyB3YXlzLCBhbmQgaXQgZW5hYmxlcyB1cyB0byBjb25kZW5zZSBhIGxhcmdlIGFtb3VudCBvZiB0ZWNobmljYWwgaW5mb3JtYXRpb24gaW50byBhIGRpYWdyYW0gb3IgdmlzdWFsLiANCg0KDQpgYGB7cn0NCg0KI01ha2Ugc3VyZSB5b3UgZG93bmxvYWQgZ2dwbG90MiBmaXJzdCEgTGV0J3MgbG9hZCBpbiBwYWNrYWdlIGFuZCBzZXQgdGhlIHdvcmtpbmcgZGlyZWN0b3J5Lg0Kc2V0d2QoIkM6L1VzZXJzL21lbGhhL09uZURyaXZlL0RvY3VtZW50cy9CaW5naGFtdG9uL2hhcnAxMzAiKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGdncGxvdDIpDQoNCiN3ZSdsbCBzdGFydCBieSBsb2FkaW5nIGluIHNvbWUgZGF0YSB0byBwbGF5IHdpdGghIFdlJ2xsIHVzZSBOWUMgdGVtcGVyYXR1cmUgZGF0YSBmb3IgdGhpcyB0dXRvcmlhbC4gDQoNCnRlbXBzIDwtIHJlYWQuY3N2KCJ0ZW1wc19ueWMuY3N2IikNCg0KI1Rha2UgYSBsb29rIGF0IHRoaXMgZGF0YXNldCEgSXQgY29udGFpbnMgbWVhbiwgbWluLCBhbmQgbWF4IHRlbXBlcmF0dXJlcyBpbiBOWUMgZm9yIGFuIGVudGlyZSB5ZWFyICgyMDE0KS4NCiNXaGF0IGlmIHdlIHdhbnRlZCB0byBwbG90IHRoZSB0ZW1wZXJhdHVyZXMgb3ZlciB0aW1lPyBXZSBjb3VsZCBwbG90IGl0IHVzaW5nIGJhc2UgUiBsaWtlIHNvOg0KDQpwbG90KHRlbXBzJGRheSwgdGVtcHMkYWN0dWFsX21lYW5fdGVtcCkNCg0KI2ZvciBhbGwgcGxvdHMsIHRoZSBzeW50YXggaXMgdXN1YWxseSAoeCA9ICwgeSA9ICkgLSB3ZSdsbCBwdXQgdGltZSAoZGF5cykgb24gdGhlIGhvcml6b250YWwgYXhpcywgYW5kIHRlbXBlcmF0dXJlcyBvbiB0aGUgdmVydGljYWwgYXhpcy4gUHV0dGluZyB0aGUgdGltZSB2YXJpYWJsZSBvbiB0aGUgeC1heGlzIGlzIHByZXR0eSBzdGFuZGFyZC4gDQpgYGANClRoaXMgcGxvdCBpc24ndCBiYWQsIGJ1dCBpdCBpc24ndCB2ZXJ5IG5pY2UgbG9va2luZyBlaXRoZXIuIFRoZSBnZ3Bsb3QyIHBhY2thZ2UgZ2l2ZXMgdXMgc28gbXVjaCBmbGV4aWJpbGl0eSB0byBjdXN0b21pemUgb3VyIHBsb3RzIC0gd2UnbGwgbWFrZSBhIG11Y2ggbmljZXIgdmVyc2lvbiBvZiB0aGlzIHNvb24uIEJlZm9yZSB3ZSBnZXQgdG8gdGhhdCwgd2UgZmlyc3QgbmVlZCB0byBsZWFybiBhIGJpdCBhYm91dCB0aGUgc3ludGF4IG9mIGdncGxvdDIuIA0KDQpgYGB7cn0NCiNMZXQncyBsb29rIGF0IHRoZSBmaXJzdCBsaW5lIG9mIGEgYmFzaWMgZ2dwbG90IGdyYXBoOg0KDQpnZ3Bsb3QodGVtcHMsIGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21lYW5fdGVtcCkpDQoNCiNXaGVuIHlvdSB1c2UgdGhlIGdncGxvdCgpIGNvbW1hbmQsIHlvdSBuZWVkIHRvIHN1cHBseSBhIGZldyBrZXkgYXJndW1lbnRzLiBUaGUgZmlyc3QgaXMgdGhlIGRhdGFzZXQgLSBpbiB0aGlzIGNhc2UsIHdlIHdpbGwgYmUgdXNpbmcgdGhlIHRlbXBzIGRhdGEgKGFzIHNob3duKS4gVGhlIG5leHQgcGFydCwgY2FsbGVkIHRoZSBhZXN0aGV0aWMgbWFwcGluZyBvciBhZXMgb2YgdGhlIHBsb3QsIHRlbGxzIHVzIHdoYXQgd2Ugd2lsbCBiZSBwbG90dGluZyBmcm9tIHRoZSBkYXRhc2V0LiBMYXRlciwgd2Ugd2lsbCBhbHNvIGluY2x1ZGUgc29tZSBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGhlIHBsb3QgaW4gdGhlIGFlcygpIHNlY3Rpb24uIENhbiB3ZSBwbG90IHRoZSBncmFwaCBub3c/IE5vdCBqdXN0IHlldCEgV2UgbmVlZCB0byBhZGQgYSBnZW9tIGxheWVyIC0gdGhlIGdlb20gbGF5ZXIgdGVsbHMgZ2dwbG90MiB3aGF0IGtpbmQgb2YgdmlzdWFsaXphdGlvbiB0byBwcm9kdWNlIHdpdGggdGhlIGRhdGEuIFdlIHVzZSBhICsgc2lnbiB0byBpbmRpY2F0ZSBhIG5ldyBsYXllciBpbiB0aGUgcGxvdCBsaWtlIHRoaXMgKGhlcmUgSSdtIHVzaW5nIGdlb21fcG9pbnQgdG8gdGVsbCBnZ3Bsb3QyIHRvIGRyYXcgYSBzY2F0dGVyIHBsb3QpOg0KDQpnZ3Bsb3QodGVtcHMsIGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21lYW5fdGVtcCkpICsNCiAgZ2VvbV9wb2ludCgpDQpgYGANCmBgYHtyfQ0KI09uZSBvZiB0aGUgbmljZSB0aGluZ3MgYWJvdXQgZ2dwbG90MiBpcyBpdHMgZmxleGliaWxpdHkuIFdlIGNhbiBlYXNpbHkgY3VzdG9taXplIHRoZSBwbG90LiBPbmNlIHlvdSBnZXQgdXNlZCB0byB0aGUgc3ludGF4IG9mIGdncGxvdDIsIGN1c3RvbWl6YXRpb24gaXMgdmVyeSBzaW1wbGUuIEZvciBleGFtcGxlLCBsZXQncyBzdGFydCBieSBjaGFuZ2luZyB0aGUgY29sb3Igb2YgdGhlIHBvaW50czoNCg0KZ2dwbG90KHRlbXBzLCBhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tZWFuX3RlbXApKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAibWVkaXVtcHVycGxlIikNCmBgYA0KVGhlcmUncyBhIGZldyBpbXBvcnRhbnQgdGhpbmdzIHRvIHBvaW50IG91dCBhYm91dCB0aGUgY29kZSBhYm92ZS4gSSBoYXZlIHB1dCB0aGUgY29sb3IgPSBhcmd1bWVudCBpbiB0aGUgZ2VvbV9wb2ludCBsYXllci4gVGhpcyB0ZWxscyBSIHRvIHVzZSB0aGUgY29sb3IgYmx1ZSBmb3IgdGhlIHBvaW50cyAtIHdoZW4gd2UgY3JlYXRlIG1vcmUgY29tcGxleCBncmFwaHMsIGJlaW5nIGFibGUgdG8gY3VzdG9taXplIGVhY2ggZ2VvbSBsYXllciBpbmRpdmlkdWFsbHkgYmVjb21lcyByZWFsbHkgaW1wb3J0YW50LiBTZWNvbmQsIHRoZSBjb2xvciB0aGF0IEkgY2hvb3NlIGNvbWVzIG5leHQgaW4gcXVvdGF0aW9uIG1hcmtzLiBXaGF0IGhhcHBlbnMgaWYgd2UgbGVhdmUgdGhlbSBvdXQ/DQoNCmBgYHtyfQ0KYmx1ZSA8LSAiYmx1ZSINCg0KZ2dwbG90KHRlbXBzLCBhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tZWFuX3RlbXApKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSBibHVlKQ0KDQpgYGANCkFzIHlvdSBjYW4gc2VlLCB3aXRob3V0IHRoZSBxdW90ZXMsIFIgdGhpbmtzIHRoYXQgd2UgYXJlIHVzaW5nIGFuIG9iamVjdCBjYWxsIGJsdWUgdG8gc2V0IHRoZSBjb2xvciBvZiB0aGUgZ3JhcGghIFlvdSBjb3VsZCBhY3R1YWxseSBkbyB0aGF0LCBsaWtlIHRoaXM6DQoNCmBgYHtyfQ0KYmx1ZSA8LSAiYmx1ZSINCg0KZ2dwbG90KHRlbXBzLCBhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tZWFuX3RlbXApKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSBibHVlKQ0KYGBgDQpCZWluZyBhYmxlIHRvIHNldCB0aGUgY29sb3Igc2NoZW1lIG9mIGEgZ3JhcGggdXNpbmcgYW4gb2JqZWN0IGlzIG11Y2ggbW9yZSB1c2VmdWwgd2hlbiB5b3UgYXJlIHdvcmtpbmcgd2l0aCBhIGNvbG9yIHBhbGV0dGUgKHRoYXQgaXMsIHdoZW4geW91IG5lZWQgdG8gdXNlIG11bHRpcGxlIGNvbG9ycyB0byBzeW1ib2xpemUgYSBncmFwaCkuIFdlIHdpbGwgc2VlIGFuIGV4YW1wbGUgbGlrZSB0aGF0IHNvb24uIExldCdzIGxvb2sgYXQgc29tZSBvdGhlciBjdXN0b21pemF0aW9uIGZlYXR1cmVzIQ0KDQpgYGB7cn0NCiNXaGF0IGlmIHdlIHdhbnQgdG8gYWRkIGxhYmVscyB0byBvdXIgcGxvdD8gVGhpcyBpcyB2ZXJ5IGVhc3kgdG8gZG8gd2l0aCB0aGUgbGFicyBhcmd1bWVudCwgbGlrZSBzbyAocmVtZW1iZXIgdGhhdCB0aGUgeC1heGlzIGlzIHRoZSBob3Jpem9udGFsIGF4aXMsIHdoaWxlIHRoZSB5LWF4aXMgaXMgdGhlIHZlcnRpY2xlIGF4aXMpOg0KDQpnZ3Bsb3QodGVtcHMsIGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21lYW5fdGVtcCkpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibHVlIikgKw0KICBsYWJzKHkgPSAiTWVhbiBUZW1wZXJhdHVyZSIsIHggPSAiRGF5IikNCmBgYA0KYGBge3J9DQojVGhpcyBpcyBzdGFydGluZyB0byBsb29rIHByZXR0eSBuaWNlISBXaGF0IGlmIHdlIHdhbnRlZCB0byBhZGQgYSB0aXRsZSB0b28/DQoNCmdncGxvdCh0ZW1wcywgYWVzKHggPSBkYXksIHkgPSBhY3R1YWxfbWVhbl90ZW1wKSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gImJsdWUiKSArDQogIGxhYnMoeSA9ICJNZWFuIFRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJNZWFuIERhaWx5IFRlbXBlcmF0dXJlIGluIE5ldyBZb3JrIENpdHksIDIwMTQiKQ0KDQojWW91J2xsIG5vdGljZSB0aGF0IEkgbGlrZSB0byBwdXQgZWFjaCBuZXcgYXJndW1lbnQgYWZ0ZXIgYSAiKyIgb24gYSBuZXcgbGluZSAtIHlvdSBkb24ndCBoYXZlIHRvIGRvIHRoaXMsIGJ1dCBJIHByZWZlciB0byBiZWNhdXNlIGl0IG1ha2VzIG15IGNvZGUgbXVjaCBlYXNpZXIgdG8gZm9sbG93LiBJIGFsc28gbGlrZSB0byBwdXQgbG9uZ2VyIGxhYmVsIG5hbWVzIG9uIGEgbmV3IGxpbmUgLSBhZ2FpbiwgdGhpcyB3b24ndCBhZmZlY3QgaG93IHRoZSBjb2RlIHJ1bnMsIGl0IGp1c3QgbWFrZXMgaXQgbW9yZSByZWFkYWJsZS4gDQoNCmBgYA0KYGBge3J9DQojQnV0IHdoYXQgaWYgd2Ugd2FudGVkIHRvIGFsc28gZ3JhcGggdGhlIG1pbmltdW0gYW5kIG1heGltdW0gdGVtcGVyYXR1cmVzIG9uIHRoZSBzYW1lIHBsb3Q/IHRoaXMgaXMgYWxzbyB2ZXJ5IGVhc3kgdG8gZG8hIFdlIGp1c3QgbmVlZCB0byB1c2UgYSBnZW9tX3BvaW50IGxheWVyIGZvciBlYWNoIHZhcmlhYmxlIHdlIHdhbnQgdG8gcGxvdC4gDQoNCiNoZXJlIHdlIHN0YXJ0IGJ5IHRlbGxpbmcgUiB0aGF0IHdlIHdhbnQgdG8gdXNlIHRoZSB0ZW1wcyBkYXRhIGZvciBvdXIgcGxvdA0KZ2dwbG90KHRlbXBzKSArDQogICNmb3IgZWFjaCBuZXcgZ2VvbV9wb2ludCBsYXllciwgSSBuZWVkIHRvIGluY2x1ZGUgYSBuZXcgYWVzdGhldGljIG1hcHBpbmcNCiAgI3RoaXMgdGVsbHMgUiB3aGljaCB2YXJpYWJsZSB0byB1c2UgaW4gdGhlIHBsb3QNCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tZWFuX3RlbXApLCBjb2xvciA9ICJncmF5IikgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21pbl90ZW1wKSwgY29sb3IgPSAiYmx1ZSIpICsNCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tYXhfdGVtcCksIGNvbG9yID0gInJlZCIpICsNCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IikNCg0KI05vdGljZSBoZXJlIHRoYXQgdGhlIGNvbG9yIGFyZ3VtZW50cyBhcmUgb3V0c2lkZSBvZiB0aGUgYWVzKCkgYXJndW1lbnQuIFRoaXMgaXMgaW50ZW50aW9uYWwgLSBvbmx5IGFyZ3VtZW50cyB0aGF0IGRlcGVuZCBvbiB2YXJpYWJsZXMgaW4gdGhlIGRhdGFzZXQgc2hvdWxkIGJlIGluIHRoZSBhZXMoKSBhcmd1bWVudC4gV2hhdCBkb2VzIHRoYXQgbWVhbj8gSW4gdGhpcyBjYXNlLCB0aGUgY29sb3IgImdyYXkiIGRvZXNuJ3QgZGVwZW5kIG9uIGFueXRoaW5nIGluIHRoZSBkYXRhIC0gZm9yIGV4YW1wbGUsIHRoZSBjb2xvciBkb2Vzbid0IGNoYW5nZSBmb3IgbG93ZXIgb3IgaGlnaGVyIHZhbHVlcy4gVGhlIGVudGlyZSBnZW9tX3BvaW50IGxheWVyIGlzIGp1c3QgZ3JheS4gSWYgd2UgaGFkIGEgdmFyaWFibGUgY2FsbGVkICJjb2xvciIgaW4gdGhlIGRhdGFzZXQsIG9yIGlmIHdlIHdhbnRlZCB0aGUgY29sb3JzIHRvIGNoYW5nZSBiYXNlZCBvbiB0ZW1wZXJhdHVyZSB2YWx1ZXMsIHdlIGNvdWxkIHB1dCBjb2xvciBpbnNpZGUgdGhlIGFlcygpLiBJJ2xsIHNob3cgYW4gZXhhbXBsZSBuZXh0Lg0KDQpgYGANCmBgYHtyfQ0KZ2dwbG90KHRlbXBzKSArDQogIGdlb21fcG9pbnQoYWVzKHggPSBkYXksIHkgPSBhY3R1YWxfbWVhbl90ZW1wLCBjb2xvciA9IGFjdHVhbF9tZWFuX3RlbXApKSArDQogIGxhYnMoeSA9ICJNZWFuIFRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJNZWFuIERhaWx5IFRlbXBlcmF0dXJlIGluIE5ldyBZb3JrIENpdHksIDIwMTQiLA0KICAgICAgIGNvbG9yID0gIk1lYW4gVGVtcGVyYXR1cmUgKEYpIikNCmBgYA0KDQpIb3BlZnVsbHkgdGhhdCBtYWtlcyBzZW5zZSBub3chIFNvLCB0aGUgZ3JhcGggb2YgbXVsdGlwbGUgdmFyaWFibGVzIGxvb2tzIHByZXR0eSBuaWNlISBCdXQsIHRoZXJlIG5vIGxlZ2VuZCBvbiBvdXIgZ3JhcGghIEhvdyB3aWxsIHBlb3BsZSBrbm93IHdoYXQgZWFjaCBjb2xvciByZXByZXNlbnRzPyBUaGlzIGlzIGEgc29tZXdoYXQgYW5ub3lpbmcgbGltaXRhdGlvbiBvZiBnZ3Bsb3QyLCBhbmQgaXQncyBhIHByb2JsZW0gdGhhdCB5b3UnbGwgY29tZSBhY3Jvc3Mgc29tZXdoYXQgZnJlcXVlbnRseS4gVGhlcmUgYXJlIHR3byB3YXlzIHRvIGZpeCBpdDogZmlyc3QsIHdlIGNhbiBhZGQgYSBsZWdlbmQgbWFudWFsbHkuIEknbGwgc2hvdyB5b3UgaG93IHRvIGRvIHRoYXQgZmlyc3QuIFNlY29uZCwgd2UgY2FuIHJlc2hhcGUgdGhlIGRhdGEgLSB0aGlzIGlzIGEgc29tZXdoYXQgbW9yZSBjb21wbGljYXRlZCBtZXRob2QsIGJ1dCBpdCBlbmRzIHVwIGJlaW5nIGV4dHJlbWVseSB1c2VmdWwgd2hlbiB5b3UgaGF2ZSBtb3JlIHRoYW4gYSBmZXcgdmFyaWFibGVzIHRvIGdyYXBoLiBJJ2xsIGV4cGxhaW4gdGhhdCBtZXRob2Qgc2Vjb25kLiANCg0KYGBge3J9DQoNCiNXZSdsbCBmaXJzdCBtYW51YWxseSBzZXQgdGhlIGNvbG9ycyBpbiB0aGUgbGVnZW5kIHVzaW5nIHNjYWxlX2NvbG9yX21hbnVhbC5Gb3Igc29tZSByZWFzb24sIGlmIHlvdSBzZXQgdGhlIGNvbG9ycyBhbGwgYXQgb25jZSwgUiB3aWxsIGdlbmVyYXRlIGEgbGVnZW5kOyBpZiB5b3Ugc2V0IGVhY2ggY29sb3IgaW5kaXZpZHVhbGx5IGluIHRoZSBnZW9tX3BvaW50IGxheWVyLCBpdCB3b24ndC4gSSBkb24ndCBtYWtlIHRoZSBydWxlcywgSSBqdXN0IGZvbGxvdyB0aGVtISBXaGVuIHlvdSBzZXQgdGhlIGNvbG9ycyBtYW51YWxseSwgeW91IGhhdmUgdG8gdGVsbCBSIHdoYXQgbGFiZWwgeW91J2QgbGlrZSB0byB1c2UgZm9yIGVhY2ggZ2VvbSBsYXllci4gSGVyZSwgSSd2ZSBzZXQgdGhlIGxhYmVsIG5hbWVzIHVzaW5nIGNvbG9yID0gIiIgaW5zaWRlIHRoZSBhZXN0aGV0aWMgbWFwcGluZyBpbiB0aGUgZ2VvbSBsYXllci4gDQoNCmdncGxvdCh0ZW1wcykgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21lYW5fdGVtcCwgY29sb3IgPSAiTWVhbiIpKSArDQogIGdlb21fcG9pbnQoYWVzKHggPSBkYXksIHkgPSBhY3R1YWxfbWluX3RlbXAsIGNvbG9yID0gIk1pbiIpKSArDQogIGdlb21fcG9pbnQoYWVzKHggPSBkYXksIHkgPSBhY3R1YWxfbWF4X3RlbXAsIGNvbG9yID0gIk1heCIpKSArDQogIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSIsIHggPSAiRGF5IiwgDQogICAgICAgdGl0bGUgPSAiRGFpbHkgVGVtcGVyYXR1cmUgaW4gTmV3IFlvcmsgQ2l0eSwgMjAxNCIsDQogICAgICAgI3NpbmNlIHRoZSBsZWdlbmQgaXMgYmFzZWQgb24gdGhlIGNvbG9yIG1hcHBpbmcsIHVzZSBjb2xvciA9IHRvIHNldCB0aGUgbGVnZW5kIHRpdGxlDQogICAgICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgVmFsdWVzIikrDQogIHNjYWxlX2NvbG9yX21hbnVhbChsYWJlbHMgPSBjKCJNZWFuIiwgIk1pbiIsICJNYXgiKSwgdmFsdWVzID0gYygiZ3JheSIsICJibHVlIiwgInJlZCIpKQ0KDQojSW4gc2NhbGVfY29sb3JfbWFudWFsLCB3ZSBzdGFydCBieSB0ZWxsaW5nIFIgd2hpY2ggbGFiZWxzIHRvIHVzZSB0byBnZW5lcmF0ZSB0aGUgY29sb3Igc2NoZW1lOyBpbiB0aGlzIGNhc2UsIGl0J3MgdGhlIHNhbWUgbGFiZWxzIHdlIGp1c3Qgc2V0IGFib3ZlLiBUaGVuLCB3ZSBoYXZlIHRvIHRlbGwgUiB3aGljaCBjb2xvcnMgdG8gdXNlIGZvciBlYWNoIGxhYmVsLiBCZWNhdXNlIHRoZXJlIGFyZSB0aHJlZSBjb2xvciB2YWx1ZXMgdG8gc2V0LCBub3RlIHRoYXQgd2UgaGF2ZSB0byB1c2UgYygpIGFyb3VuZCB0aGUgbGlzdCBvZiB2YXJpYWJsZSBuYW1lcyBhbmQgY29sb3JzLiANCg0KI1NjYWxlX2NvbG9yX21hbnVhbCBvZnRlbiBpbnZvbHZlcyBzb21lIGd1ZXNzaW5nIGFuZCBjaGVja2luZyB3aXRoIHRoZSBvcmRlciBvZiB0aGUgY29sb3JzIC0gZm9yIHNvbWUgcmVhc29uLCBSIHdhbnRlZCB0byB1c2UgdGhlIGZpcnN0IGNvbG9yIGZvciB0aGUgbWF4IHRlbXBlcmF0dXJlLCB0aGUgc2Vjb25kIGZvciB0aGUgbWVhbiwgYW5kIHRoZSB0aGlyZCBmb3IgdGhlIG1pbi4gVGhpcyBvcmRlciBtYWtlcyBubyBzZW5zZSwgYnV0IGl0IGlzIGFsc28gbm90IGVhc3kgdG8gY2hhbmdlLiBJZiB5b3Ugbm90aWNlIHRoYXQgdGhlIGNvbG9ycyBpbiB5b3VyIGdyYXBoIGRvbid0IG1hdGNoIHVwLCB0aGUgZWFzaWVzdCBmaXggaXMgdG8ganVzdCBjaGFuZ2UgdGhlIG9yZGVyIHRoYXQgeW91IGxpc3RlZCB0aGUgY29sb3JzIGFuZCB2YXJpYWJsZSBuYW1lcyBzbyB0aGF0IGl0IG1hdGNoZXMgUidzIGRlZmF1bHQgb3JkZXJpbmcuIFRoYXQncyB3aGF0IEkgZGlkIGJlbG93LiANCmBgYA0KYGBge3J9DQojSGVyZSdzIHRoZSBjb3JyZWN0IHBsb3QhDQpnZ3Bsb3QodGVtcHMpICsNCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tZWFuX3RlbXAsIGNvbG9yID0gIk1lYW4iKSkgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21pbl90ZW1wLCBjb2xvciA9ICJNaW4iKSkgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21heF90ZW1wLCBjb2xvciA9ICJNYXgiKSkgKw0KICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUiLCB4ID0gIkRheSIsIA0KICAgICAgIHRpdGxlID0gIkRhaWx5IFRlbXBlcmF0dXJlIGluIE5ldyBZb3JrIENpdHksIDIwMTQiLA0KICAgICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFZhbHVlcyIpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwobGFiZWxzID0gYygiTWF4IiwgIk1lYW4iLCAiTWluIiksIHZhbHVlcyA9IGMoInJlZCIsICJncmF5IiwgImJsdWUiKSkNCmBgYA0KRG9lc24ndCB0aGF0IGxvb2sgbmljZT8gTGV0J3MgdGFsayBhYm91dCByZXNoYXBpbmcgeW91ciBkYXRhIG5vdy4gVGhpcyBpcyBhIHZlcnkgaGVscGZ1bCBza2lsbCB0byBoYXZlLCBhbmQgeW91IHdpbGwgZmluZCB5b3Vyc2VsZiBoYXZpbmcgdG8gcmVzaGFwZSBkYXRhIGZyZXF1ZW50bHkuU28gcmlnaHQgbm93LCBlYWNoIHZhcmlhYmxlIGhhcyBpdHMgb3duIGNvbHVtbiBpbiB0aGUgZGF0YWZyYW1lIGluIG91ciBjYXNlLCB3ZSdyZSB3b3JraW5nIHdpdGggZm91ciBjb2x1bW5zIG9mIGRhdGEuIFNpbmNlIHRocmVlIG9mIHRoZSB2YXJpYWJsZXMgYXJlIHRlbXBlcmF0dXJlIGRhdGEsIHdvdWxkbid0IGl0IG1ha2Ugc2Vuc2UgdG8gcHV0IHRoZW0gYWxsIGluIG9uZSBjb2x1bW4gaW5zdGVhZD8gVGhpcyBpcyB3aGF0IHdlIGNhbGwgdHJhbnNmb3JtaW5nIGRhdGEgZnJvbSB3aWRlIHRvIGxvbmcgZm9ybWF0IC0gd2lkZSBkYXRhIGhhcyBtb3JlIGNvbHVtbnMsIHdoaWxlIGxvbmcgZGF0YSB3aWxsIHVzdWFsbHkgaGF2ZSBtb3JlIHJvd3MgaW5zdGVhZC4gSGVyZSdzIGEgZGlhZ3JhbSBvZiB3aGF0IGl0IGxvb2tzIGxpa2UgdG8gdHJhbnNmb3JtIGZyb20gbG9uZyB0byB3aWRlOiBodHRwczovL2kuc3RhY2suaW1ndXIuY29tL2kxRG5lLmpwZy4gWW91IGNhbiBsb29rIGF0IHRoaXMgZGlhZ3JhbSBsYXRlciBpZiB5b3UncmUgY29uZnVzZWQgYWJvdXQgd2hhdCB3aWRlIGFuZCBsb25nIGZvcm1hdCBsb29rIGxpa2UuIEZvciB3aGF0ZXZlciByZWFzb24sIHRoZSBnZ3Bsb3QyIHBhY2thZ2UgdGVuZHMgdG8gd29yayBiZXR0ZXIgd2l0aCBsb25nIGRhdGEuIFdlJ2xsIHJlc2hhcGUgdGhlIGRhdGEgdXNpbmcgYSBjb21tYW5kIGZyb20gdGhlIHRpZHlyIHBhY2thZ2UsIHBpdm90X2xvbmdlci4gDQoNCmBgYHtyfQ0Kd2lkZV9kYXRhIDwtIHRlbXBzICU+JSANCiAgI3dlJ2xsIG9ubHkgc2VsZWN0IHRoZSB2YXJpYWJsZXMgb2YgaW50ZXJlc3QgdG8gZG8gdGhpcw0KICBzZWxlY3QoYyhkYXksIGFjdHVhbF9tZWFuX3RlbXAsIGFjdHVhbF9taW5fdGVtcCwgYWN0dWFsX21heF90ZW1wKSkNCg0KI2xldCdzIGNoYW5nZSB0aGUgY29sdW1uIG5hbWVzIHRvIG1ha2UgdGhlbSBhIGJpdCBuaWNlcjoNCiNJJ2xsIHNob3cgeW91IHdoeSB0aGlzIG1hdHRlcnMgc29vbi4gDQpjb2xuYW1lcyh3aWRlX2RhdGEpIDwtIGMoIkRheSIsICJNZWFuIiwgIk1pbiIsICJNYXgiKQ0KDQpoZWFkKHdpZGVfZGF0YSkNCmBgYA0KYGBge3J9DQojTm93IHdlJ2xsIHJlc2hhcGUgaXQhDQoNCmxvbmdfZGF0YSA8LSB3aWRlX2RhdGEgJT4lIA0KICAjVGhlIGNvbHVtbiB0aXRsZXMgYmVjb21lIHRoZSBjYXRlZ29yaWVzIGluIGEgbmV3IGNvbHVtbiBhZnRlciB0aGUgcmVzaGFwaW5nDQogICNJJ20gbmFtaW5nIHRoaXMgbmV3IGNvbHVtbiB0ZW1wX3R5cGUNCiAgI1RoZSB0ZW1wZXJhdHVyZSB2YWx1ZXMgYXJlIHB1dCBpbiBhIG5ldyB2YWx1ZXMgY29sdW1uLCB3aGljaCBJJ20gY2FsbGluZyB0ZW1wDQogIHBpdm90X2xvbmdlcighRGF5LCBuYW1lc190byA9ICJ0ZW1wX3R5cGUiLCB2YWx1ZXNfdG8gPSAidGVtcCIpDQoNCmhlYWQobG9uZ19kYXRhKQ0KYGBgDQpgYGB7cn0NCiNXaGF0IGlmIEkgd2FudGVkIHRvIGdvIGZyb20gbG9uZyB0byB3aWRlIGRhdGE/IEhlcmUncyB3aGF0IHRoYXQgbG9va3MgbGlrZSwgZm9yIHlvdXIgcmVmZXJlbmNlOg0KDQp3aWRlX2RhdGExIDwtIGxvbmdfZGF0YSAlPiUgDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSB0ZW1wX3R5cGUsIHZhbHVlc19mcm9tID0gdGVtcCkNCg0KI1J1biB0aGlzIGNvZGUgdG8gdmVyaWZ5IHRoYXQgdGhlIG9yaWdpbmFsIHdpZGVfZGF0YSBhbmQgb3VyIG5ldyB3aWRlX2RhdGExIGRhdGFmcmFtZSBhcmUgdGhlIHNhbWUuIExvZ2ljYWwgZGF0YSBpcyBoZWxwZnVsIGluIHRoaXMgY2FzZSENCiNJJ20gc2V0dGluZyB0aGUgbnVtYmVyIG9mIHZhbHVlcyB0aGF0IFIgcHJpbnRzIG91dCB0byAyMCAtIG90aGVyd2lzZSwgUiB3b3VsZCBwcmludCB0aGUgd2hvbGUgZGF0YXNldCBvbiB0aGUgc2NyZWVuLCBhbmQgaXQgd291bGQgdGFrZSB1cCBhIGxvdCBvZiBzcGFjZSENCm9wdGlvbnMobWF4LnByaW50ID0gMjApDQp3aWRlX2RhdGExID09IHdpZGVfZGF0YQ0KYGBgDQoNCg0KRG8geW91IHNlZSB0aGUgZGlmZmVyZW5jZT8gTm93LCB0aGUgY2F0ZWdvcnkgKHRlbXBfdHlwZSwgb3IgbWVhbiwgbWluLCBhbmQgbWF4KSBpcyBpbiBvbmUgY29sdW1uLCB3aGlsZSBlYWNoIHRlbXBlcmF0dXJlIHRoYXQgY29ycmVzcG9uZHMgdG8gdGhlIHRlbXBfdHlwZSBhbmQgZGF5IGlzIGluIHRoZSB0ZW1wIGNvbHVtbi4gVGhlIHdpZGUgYW5kIGxvbmcgZGF0YSBzZXRzIGFyZSBqdXN0IGRpZmZlcmVudCB3YXlzIG9mIHN0b3JpbmcgdGhlIHNhbWUgZGF0YSEgTm93IGxldCdzIHNlZSBob3cgdGhpcyB3b3JrcyBpbiBnZ3Bsb3QyLiANCg0KYGBge3J9DQoNCiNOb3csIGluc3RlYWQgb2YgdGhyZWUgZ2VvbSBsYXllcnMsIHdlIHdpbGwgbmVlZCB0byBwbG90IHRoZSBkYXRhIGJ5IHRocmVlIGdyb3VwczogbWVhbiwgbWluLCBhbmQgbWF4LiBCZWNhdXNlIHdlIGFyZSBncm91cGluZyB0aGUgZGF0YSBpbiB0aGUgZGF0YWZyYW1lIGJ5IHRoZSB0eXBlIG9mIHRlbXBlcmF0dXJlIHJlY29yZGVkLCB3ZSBuZWVkIHRvIGFzc2lnbiB0aGUgdGVtcF90eXBlIGNvbHVtbiB0byB0aGUgZ3JvdXAgYXJndW1lbnQuIEJlY2F1c2UgZWFjaCB0eXBlIG9mIHRlbXBlcmF0dXJlIHdpbGwgYWxzbyBoYXZlIGEgZGlmZmVyZW50IGNvbG9yLCB3ZSB3aWxsIGFzc2lnbiB0ZW1wX3R5cGUgdG8gdGhlIGNvbG9yIGFyZ3VtZW50IGFzIHdlbGwuIExldCdzIHNlZSB3aGF0IHRoaXMgbG9va3MgbGlrZSENCg0KZ2dwbG90KGxvbmdfZGF0YSwgYWVzKHggPSBEYXksIHkgPSB0ZW1wLCBncm91cCA9IHRlbXBfdHlwZSwgY29sb3IgPSB0ZW1wX3R5cGUpKSArDQogIGdlb21fcG9pbnQoKSArDQogIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSIsIHggPSAiRGF5IiwgDQogICAgICAgdGl0bGUgPSAiRGFpbHkgVGVtcGVyYXR1cmUgaW4gTmV3IFlvcmsgQ2l0eSwgMjAxNCIsDQogICAgICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgKEYpIikNCmBgYA0KDQpEbyB5b3Ugc2VlIHdoeSBJIGNoYW5nZWQgdGhlIGNvbHVtbiBuYW1lcz8gUiB1c2VzIHRoZSBjYXRlZ29yaWVzIGluIHRoZSB0ZW1wX3R5cGUgY29sdW1uIHRvIGFkZCBuYW1lcyB0byB0aGUgbGVnZW5kLiBLZWVwaW5nIHRoZSAiYWN0dWFsX21lYW5fdGVtcCIgKGFuZCBzbyBvbikgbGFiZWxzIHdvdWxkIG5vdCBoYXZlIGJlZW4gbmVhcmx5IGFzIGNsZWFyIGluIGEgbGVnZW5kLiBJbiBvdXIgZ3JhcGhzLCB3ZSBzaG91bGQgYWltIHRvIHNob3cgY29tcGxleCBpbmZvcm1hdGlvbiBpbiB0aGUgc2ltcGxlc3Qgd2F5IHBvc3NpYmxlIC0gaGF2aW5nIGNsZWFyIGxlZ2VuZCBhbmQgYXhpcyB0aXRsZXMgaXMga2V5IHRvIHRoYXQuIE5vdywgaW4gdGhpcyBjYXNlLCB0aGUgY29sb3JzIGFyZW4ndCBxdWl0ZSByaWdodCEgTGV0J3Mgc2V0IHRoZW0gbWFudWFsbHkuIA0KDQpgYGB7cn0NCiNjcmVhdGUgdGhlIGNvbG9yIHBhbGV0dGUgZm9yIHRoZSBkYXRhDQojUmVtZW1iZXIsIG9yZGVyIG1hdHRlcnMhIEJhc2VkIG9uIHRoZSBvcmRlciBvZiB0aGUgbGVnZW5kIGluIHRoZSBsYXN0IGdyYXBoLCBJIHdpbGwgaW5jbHVkZSB0aGUgY29sb3IgZm9yIHRoZSBtYXggdGVtcCwgdGhlbiB0aGUgbWVhbiwgdGhlbiB0aGUgbWluLiANCg0KY29sb3JzIDwtIGMoInJlZCIsICJncmF5IiwgImJsdWUiKQ0KDQpnZ3Bsb3QobG9uZ19kYXRhLCBhZXMoeCA9IERheSwgeSA9IHRlbXAsIGdyb3VwID0gdGVtcF90eXBlLCBjb2xvciA9IHRlbXBfdHlwZSkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IiwNCiAgICAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSAoRikiKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9ycykNCmBgYA0KDQpEbyB5b3Ugc2VlIGhvdyBtdWNoIHNpbXBsZXIgYW5kIHNob3J0ZXIgdGhlIGdncGxvdDIgY29kZSBpcyBub3c/IFJlc2hhcGluZyBkYXRhIGRlZmluaXRlbHkgdGFrZXMgc29tZSBnZXR0aW5nIHVzZWQgdG8sIGJ1dCBpdCdsbCBzYXZlIHlvdSB0aW1lIGluIHRoZSBmdXR1cmUuIEJlZm9yZSB3ZSBtb3ZlIG9uLCBJJ2xsIHNob3cgeW91IG9uZSBtb3JlIHdheSB0byBzZXQgdGhlIGNvbG9ycywgbm93IHRoYXQgd2UgaGF2ZSB0aGUgZGF0YSBpbiBsb25nIGZvcm1hdC4gVGhpcyB0aGlyZCB2ZXJzaW9uIHdpbGwgaW50cm9kdWNlIHlvdSB0byBhIGZ1bmN0aW9uIHRoYXQgaXMgaGVscGZ1bCB3aXRoaW4gZHBseXIgZnVuY3Rpb25zLCBpZmVsc2UuIA0KDQpgYGB7cn0NCiNUaGlzIHZlcnNpb24gaW52b2x2ZXMgY3JlYXRpbmcgYSBuZXcgY29sdW1uIGluIHRoZSBsb25nIGRhdGFmcmFtZSB3aXRoIHRoZSBjb2xvciB2YWx1ZXMgaW4gaXQuIEVhY2ggY29sb3Igd2lsbCBjb3JyZXNwb25kIHRvIHRoZSBjb3JyZWN0IHRlbXBfdHlwZS4gDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5cikNCmxvbmdfZGF0YSA8LSBsb25nX2RhdGEgJT4lIA0KICBtdXRhdGUoY29sb3JzID0gaWZlbHNlKHRlbXBfdHlwZSA9PSAiTWF4IiwgInJlZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRlbXBfdHlwZSA9PSAiTWVhbiIsICJncmF5IiwgImJsdWUiKSkpDQoNCiNMZXQncyB3YWxrIHRocm91Z2ggdGhlIHN5bnRheCBvZiB0aGUgaWZlbHNlIGZ1bmN0aW9uIChub3RlIHRoYXQgaXQgc3RhbmQgZm9yICJpZiBlbHNlIikNCiNZb3UgY2FuIHJlYWQgdGhlIGNvZGUgbGlrZSB0aGlzOiBpZiB0ZW1wX3R5cGUgaXMgZXF1YWwgdG8gTWF4LCBzZXQgdGhlIHZhbHVlIHRvIHJlZA0KI2lmIHRlbXAgdHlwZSBpcyBlcXVhbCB0byBNZWFuLCBzZXQgdGhlIGNvbG9yIHRvIGdyYXkuIA0KI0ZvciBhbGwgb3RoZXJzLCBzZXQgdGhlIGNvbG9yIHRvIGJsdWUuIA0KI0lmIHlvdSBsb29rIHVwIHRoZSBkb2N1bWVudGF0aW9uIHRvIGlmZWxzZSwgeW91J2xsIHNlZSBqdXN0IGhvdyBzaW1wbGUgaXQgaXM6DQojaWZlbHNlKHRlc3QsIHllcywgbm8pDQojeW91IGdpdmUgdGhlIGZ1bmN0aW9uIHRoZSB0ZXN0LCBhbmQgc2V0IGEgdmFsdWUgdG8gY29ycmVzcG9uZCB0byB5ZXMgKFRydWUpIGFuZCBubyAoRmFsc2UpIGFuc3dlcnMuIEluIHRoaXMgY29kZSwgSSBoYXZlIG5lc3RlZCBhbiBpZmVsc2UgZnVuY3Rpb24gaW5zaWRlIG9mIGFub3RoZXIgb25lLCBiYXNpY2FsbHkgdGVsbGluZyBSIHRoYXQgbm8gb3IgZmFsc2UgdmFsdWVzIGJhc2VkIG9uIHRoZSBmaXJzdCBjYWxsIHRvIGlmZWxzZSBhcmUgc3ViamVjdCB0byBhbm90aGVyIGlmZWxzZSBzdGF0ZW1lbnQuIFZhbHVlcyB0aGF0IGFyZSBubyBvciBmYWxzZSBpbiBib3RoIGNhbGxzIG90IGlmZWxzZSB3aWxsIGJlIGJsdWUgKG5vdGUgdGhhdCB0aGVzZSBhcmUgdGhlIG1pbmltdW0gdmFsdWVzKS4NCiNMZXQncyBncmFwaCB0aGlzIQ0KDQpnZ3Bsb3QobG9uZ19kYXRhLCBhZXMoeCA9IERheSwgeSA9IHRlbXAsIGdyb3VwID0gdGVtcF90eXBlLCBjb2xvciA9IGNvbG9ycykpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IiwNCiAgICAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSAoRikiKSsNCiAgc2NhbGVfY29sb3JfaWRlbnRpdHkoZ3VpZGUgPSAibGVnZW5kIiwgbGFiZWxzID0gYygiTWluIiwgIk1lYW4iLCAiTWF4IikpDQoNCiNJZiB5b3Ugd2FudCB0byB1c2UgdGhpcyBtZXRob2QsIHlvdSBuZWVkIHRvIGFsc28gaW5jbHVkZSB0aGUgc2NhbGVfY29sb3JfaWRlbnRpdHkgYXJndW1lbnQgLSB0aGlzIHRlbGxzIFIgdG8gdXNlIGNvbG9ycyBmcm9tIHRoZSBkYXRhLiBJIGFsc28gaGFkIHRvIHNwZWNpZnkgdGhlIGxlZ2VuZCBsYWJlbCBuYW1lcyB1c2luZyB0aGUgbGFiZWxzID0gYXJndW1lbnQgLSBhZ2FpbiwgUiBpcyB3ZWlyZCBhYm91dCB2YXJpYWJsZSBvcmRlciwgYW5kIEkgaGFkIHRvIGluY2x1ZGUgdGhlIGxhYmVsIG5hbWVzIGluIHRoZSBzYW1lIG9yZGVyIHRoYXQgUiB1c2VzIGluIHRoZSBsZWdlbmQuIEZvciB3aGF0ZXZlciByZWFzb24sIHRoaXMgb3JkZXIgaXMgYSBiaXQgcmFuZG9tLg0KYGBgDQpPdmVyYWxsLCB0aGUgc2Vjb25kIG1ldGhvZCBvZiBhZGRpbmcgY29sb3IgZm9yIG11bHRpcGxlIHZhcmlhYmxlcyAocmVzaGFwaW5nIHRoZSBkYXRhIGFuZCB1c2luZyBhIGNvbG9yIHBhbGV0dGUgb2JqZWN0IHRvIHNldCBjb2xvcnMpIGlzIHByb2JhYmx5IHRoZSBtb3N0IGZsZXhpYmxlIG1ldGhvZC4gT2Z0ZW4sIHlvdSdsbCBiZSBhYmxlIHRvIHNldCBwYWxldHRlcyB1c2luZyBmdW5jdGlvbnMsIHdoaWNoIG1ha2VzIHRoZSBwcm9jZXNzIGV2ZW4gZmFzdGVyOyBpdCdzIHVubGlrZWx5IHRoYXQgeW91J2xsIG5lZWQgdG8gbWFudWFsbHkgc3BlY2lmeSBjb2xvcnMuIEluIHRoZSBuZXh0IGNodW5rIG9mIGNvZGUsIEknbGwgZ2l2ZSBhbiBleGFtcGxlIHVzaW5nIGEgcGFja2FnZSB0aGF0IGNvbnRhaW5zIHNvbWUgcmVhbGx5IG5pY2UgY29sb3IgcGFsZXR0ZXMgaW5zcGlyZWQgYnkgVVMgbmF0aW9uYWwgcGFya3MuIE1vcmUgaW5mbyBvbiB0aGUgcGFsZXR0ZXMgYXJlIGhlcmU6IGh0dHBzOi8vZ2l0aHViLmNvbS9rYXRpZWpvbGx5L25hdGlvbmFscGFya2NvbG9ycy4gWW91IGNhbiB1c2UgdGhlIGNvZGUgZnJvbSB0aGUgZ2l0aHViIGxpbmsgdG8gaW5zdGFsbCB0aGUgcGFja2FnZSwgdG9vLiANCk90aGVyIHBhY2thZ2VzLCBsaWtlIFJDb2xvckJyZXdlciwgYWxzbyBwcm92aWRlIGEgcmFuZ2Ugb2YgcGFsZXR0ZXMgdG8gY2hvb3NlIGZyb20uIA0KDQpgYGB7cn0NCiNJIGFscmVhZHkgaGF2ZSB0aGlzIGluc3RhbGxlZCAtIEkgbGlrZSB1c2luZyB0aGVzZSBjb2xvcnMgZm9yIHByZXNlbnRhdGlvbnMuIA0KbGlicmFyeShuYXRpb25hbHBhcmtjb2xvcnMpDQoNCiNJJ3ZlIGp1c3QgcGlja2VkIGEgcmFuZG9tIHBhbGV0dGUsIHRoZXNlIGNvbG9ycyBhcmVuJ3QgbWVhbmluZ2Z1bC4gDQpwYWxldHRlIDwtIHBhcmtfcGFsZXR0ZSgiU21va3lNb3VudGFpbnMiLCBuID0gMykNCg0KbGlicmFyeShnZ3Bsb3QyKQ0KI05vdyBncmFwaCBpdCB3aXRoIHRoZSBwYWxldHRlIQ0KZ2dwbG90KGxvbmdfZGF0YSwgYWVzKHggPSBEYXksIHkgPSB0ZW1wLCBncm91cCA9IHRlbXBfdHlwZSwgY29sb3IgPSB0ZW1wX3R5cGUpKSArDQogIGdlb21fcG9pbnQoKSArDQogIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSIsIHggPSAiRGF5IiwgDQogICAgICAgdGl0bGUgPSAiRGFpbHkgVGVtcGVyYXR1cmUgaW4gTmV3IFlvcmsgQ2l0eSwgMjAxNCIsDQogICAgICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgKEYpIikrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBwYWxldHRlKQ0KYGBgDQpTbyBub3cgeW91IGtub3cgdGhlIGJhc2ljcyBvZiBncmFwaGluZyB3aXRoIGdncGxvdDIhIFRoZXJlIGFyZSBqdXN0IGEgZmV3IG1vcmUgdG9waWNzIHRvIGNvdmVyIHRoYXQgeW91IHdpbGwgZmluZCBoZWxwZnVsLiBGaXJzdCwgd2hhdCBpZiBJIGRvbid0IHdhbnQgdG8gdXNlIGEgc2NhdHRlciBwbG90PyBHZ3Bsb3QyIGNvbWVzIHdpdGggYSB3aWRlIHJhbmdlIG9mIGdlb20gcG9zc2liaWxpdGllcyEgSXQncyBzbyBlYXN5IHRvIHByb2R1Y2UgZGlmZmVyZW50IGtpbmRzIG9mIHBsb3RzIG9mIHlvdXIgZGF0YS4gTGV0J3MgbWFrZSBhIGxpbmUgcGxvdCB3aXRoIHRoZSBkYXRhIHdlIGFscmVhZHkgaGF2ZS4gDQoNCmBgYHtyfQ0KDQpnZ3Bsb3QobG9uZ19kYXRhLCBhZXMoeCA9IERheSwgeSA9IHRlbXAsIGdyb3VwID0gdGVtcF90eXBlLCBjb2xvciA9IHRlbXBfdHlwZSkpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUiLCB4ID0gIkRheSIsIA0KICAgICAgIHRpdGxlID0gIkRhaWx5IFRlbXBlcmF0dXJlIGluIE5ldyBZb3JrIENpdHksIDIwMTQiLA0KICAgICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIChGKSIpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gcGFsZXR0ZSkNCg0KYGBgDQpUaGUgbGluZSBwbG90IGRvZXNuJ3QgbG9vayBuaWNlIGFuZCBzbW9vdGggYmVjYXVzZSB3ZSdyZSB3b3JraW5nIHdpdGggZGFpbHkgZGF0YSAtIHRoZXJlIGFyZSBhIGxvdCBvZiBkYXRhIHBvaW50cywgYW5kIHRoZSB0ZW1wZXJhdHVyZXMgbW92ZSBhcm91bmQgYSBsb3QhIEJ1dCBhcyB5b3UgY2FuIHNlZSwgc3dpdGNoaW5nIHRvIGEgbGluZSBwbG90IHdhcyBzbyBlYXN5LiBOZXh0LCB3ZSBjYW4gbG9vayBhdCBhIGJhciBwbG90LiBMaW5lIHBsb3RzLCBzY2F0dGVyIHBsb3RzLCBhbmQgYmFyIHBsb3RzIHdpbGwgYmUgdGhlIG1vc3QgY29tbW9uIHBsb3RzIHlvdSdsbCB1c2UuIA0KDQpgYGB7cn0NCiNSZW1lbWJlciB0aGF0IGJhciBwbG90cyBkb24ndCByZXF1aXJlIHggYW5kIHkgdmFyaWFibGVzIC0gd2UganVzdCBuZWVkIG9uZSB5IHZhcmlhYmxlIChpbiB0aGlzIGNhc2UsIHRlbXBlcmF0dXJlKSBhbmQgY2F0ZWdvcmllcyBmb3IgdGhlIHgtYXhpcyAoaW4gdGhpcyBjYXNlLCB0ZW1wX3R5cGUpLiBMZXQncyBtYWtlIGEgc2ltcGxlIGJhciBwbG90IGZvciBvbmUgZGF5Og0KDQpkYXkxIDwtIGxvbmdfZGF0YSAlPiUgZmlsdGVyKERheSA9PSAxKQ0KDQpnZ3Bsb3QoZGF5MSwgYWVzKHkgPSB0ZW1wLCB4ID0gdGVtcF90eXBlLCBncm91cCA9IHRlbXBfdHlwZSwgZmlsbCA9IHRlbXBfdHlwZSkpKw0KICBnZW9tX2JhcihzdGF0ID0gIklkZW50aXR5IikrDQogIGxhYnMoeCA9ICJUZW1wZXJhdHVyZSBUeXBlIiwgeSA9ICJUZW1wZXJhdHVyZSIsDQogICAgICAgdGl0bGUgPSAiVGVtcGVyYXR1cmVzIGluIE9uZSBEYXkgaW4gTllDIikgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsZXR0ZSkNCg0KI1NvbWUgdGhpbmdzIHRvIG5vdGUgYWJvdXQgdGhpcyBjb2RlOiBiZWNhdXNlIEkgaGF2ZSBpbmNsdWRlZCB0aGUgY2F0ZWdvcmllcyBhcyB4LXZhbHVlcywgSSBuZWVkIHRvIGluY2x1ZGUgdGhlIGFyZ3VtZW50IHN0YXQgPSAiSWRlbnRpdHkiIGluIHRoZSBnZW9tX2JhciBsYXllci4gV2l0aG91dCBnb2luZyBpbnRvIHRvbyBtdWNoIGRldGFpbCwgdGhpcyBhcmd1bWVudCB0ZWxscyBSIHRoYXQgdGhlIGhlaWdodCBvZiB0aGUgY29sdW1ucyBzaG91bGQgYmUgZXF1YWwgdG8gdGhlIHRlbXAgdmFsdWVzLiBOb3RlIGFsc28gdGhhdCBpbnN0ZWFkIG9mIGNvbG9yLCB3ZSB1c2UgdGhlIGZpbGw9IGFyZ3VtZW50IGhlcmUgLSB0aGUgY29sb3IgYXJndW1lbnQgaXMgZm9yIGxpbmVzIGFuZCBwb2ludHMsIHdoaWxlIHNvbGlkIHBvbHlnb25zIG5lZWQgdG8gYmUgYXNzaWduZWQgY29sb3JzIHVzaW5nIHRoZSBmaWxsIGFyZ3VtZW50LiBBcyBhbiBleGVyY2lzZSwgdHJ5IHNlZWluZyB3aGF0IGhhcHBlbnMgd2hlbiB5b3UgdXNlIGNvbG9yID0gaW5zdGVhZCEgV2hlbiB5b3UgdXNlIGZpbGwsIHRoZSBzY2FsZV9jb2xvcl9tYW51YWwgYXJndW1lbnQgYWxzbyBjaGFuZ2VzIHRvIHNjYWxlX2ZpbGxfbWFudWFsIHRvIHNldCB0aGUgY29sb3IgcGFsZXR0ZS4gRmluYWxseSwgUiB3aWxsIGF1dG9tYXRpY2FsbHkgZ2VuZXJhdGUgYSBsZWdlbmQgd2hlbiB5b3UgYXNzaWduIGNvbG9ycyB1c2luZyB0aGUgZ3JvdXAgYWVzdGhldGljIC0gSSBkaWRuJ3QgbmVlZCBhIGxlZ2VuZCBpbiB0aGlzIGdyYXBoLCBzbyBJIHVzZWQgdGhlIHRoZW1lKCkgYXJndW1lbnQgdG8gc2V0IHRoZSBsZWdlbmQgcG9zaXRpb24gdG8gIm5vbmUiLiBUaGlzIGRlbGV0ZXMgdGhlIGxlZ2VuZCBmcm9tIHRoZSBwbG90LCBhbmQgaXMgd29ydGggcmVtZW1iZXJpbmcuIA0KYGBgDQpMZXQncyB0aGluayBhYm91dCBzb21lIG90aGVyIHdheXMgeW91IGNhbiBjdXN0b21pemUgeW91ciBwbG90cy4gT25lIHdheSB0aGF0IHdlIGNhbiBtYWtlIG91ciBwbG90IGxvb2sgbmljZSBpcyBieSBhZGRpbmcgYSB2aXN1YWwgdGhlbWUuIFRoZXJlIGFyZSBhIG51bWJlciBvZiB0aGVtZXMgeW91IGNhbiBhZGQgdG8geW91ciBwbG90IC0gd2UnbGwgZG93bmxvYWQgYSBuZXcgcGFja2FnZSBub3cgdGhhdCBjb250YWlucyBzb21lIGFkZGl0aW9uYWwgdGhlbWVzIGFzIHdlbGwuIA0KDQpgYGB7cn0NCmxpYnJhcnkoZ2d0aGVtZXMpDQoNCiNJIHByZWZlciB0aGUgbWluaW1hbCB0aGVtZSB0aGF0IGNvbWVzIGxvYWRlZCB3aXRoIGdncGxvdDIgLSBpdCBtYWtlcyBwbG90cyBsb29rIHZlcnkgc2xlZWsgDQpnZ3Bsb3QobG9uZ19kYXRhLCBhZXMoeCA9IERheSwgeSA9IHRlbXAsIGdyb3VwID0gdGVtcF90eXBlLCBjb2xvciA9IHRlbXBfdHlwZSkpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUiLCB4ID0gIkRheSIsIA0KICAgICAgIHRpdGxlID0gIkRhaWx5IFRlbXBlcmF0dXJlIGluIE5ldyBZb3JrIENpdHksIDIwMTQiLA0KICAgICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIChGKSIpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gcGFsZXR0ZSkgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQpgYGB7cn0NCiNUaGUgZ2d0aGVtZXMgcGFja2FnZSBjb21lcyB3aXRoIHNvbWUgb3RoZXIgdXNlZnVsIHRoZW1lcy4gTGV0J3MgdHJ5IGEgZmV3IG1vcmU6DQojSWYgeW91IHdhbnQgeW91ciBwbG90IHRvIGxvb2sgbGlrZSB0aGUgcGxvdHMgaW4gdGhlIEVjb25vbWlzdCBtYWdhemluZSwgeW91IG1pZ2h0IHVzZSB0aGlzIHRoZW1lOg0KDQpnZ3Bsb3QobG9uZ19kYXRhLCBhZXMoeCA9IERheSwgeSA9IHRlbXAsIGdyb3VwID0gdGVtcF90eXBlLCBjb2xvciA9IHRlbXBfdHlwZSkpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUiLCB4ID0gIkRheSIsIA0KICAgICAgIHRpdGxlID0gIkRhaWx5IFRlbXBlcmF0dXJlIGluIE5ldyBZb3JrIENpdHksIDIwMTQiLA0KICAgICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIChGKSIpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gcGFsZXR0ZSkrDQogIHRoZW1lX2Vjb25vbWlzdCgpDQpgYGANCmBgYHtyfQ0KDQojVGhpcyB0aGVtZSBtaW1pY3MgcGxvdHMgZHJhd24gYnkgdGhlIFdhbGwgU3RyZWV0IEpvdXJuYWw6DQpnZ3Bsb3QobG9uZ19kYXRhLCBhZXMoeCA9IERheSwgeSA9IHRlbXAsIGdyb3VwID0gdGVtcF90eXBlLCBjb2xvciA9IHRlbXBfdHlwZSkpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUiLCB4ID0gIkRheSIsIA0KICAgICAgIHRpdGxlID0gIkRhaWx5IFRlbXBlcmF0dXJlIGluIE5ldyBZb3JrIENpdHksIDIwMTQiLA0KICAgICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIChGKSIpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gcGFsZXR0ZSkrDQogIHRoZW1lX3dzaigpDQpgYGANCg0KSWYgeW91IHR5cGUgdGhlbWVfIHlvdSBzaG91bGQgZ2V0IGEgZHJvcCBkb3duIG1lbnUgb2YgYWxsIG9mIHRoZSBwb3NzaWJsZSB0aGVtZXMgdG8gY2hvb3NlIGZyb20gLSBJIHdvdWxkIGVuY291cmFnZSB5b3UgdG8gcGxheSBhcm91bmQgd2l0aCB0aGVtLCBhbmQgc2VlIHdoaWNoIG9uZSB5b3UgbGlrZSBiZXN0ISANCg0KYGBge3J9DQojRmluYWxseSwgeW91IGNhbiB1c2UgdGhlIHRoZW1lIGZ1bmN0aW9uIHRvIGNoYW5nZSB0aGUgY2VudGVyaW5nIG9mIHRoZSB0aXRsZSBhbmQgb3RoZXIgdGV4dC4gQnkgdGhlIGRlZmF1bHQsIGV2ZXJ5dGhpbmcgaXMgbGVmdC1hbGlnbmVkLiANCg0KZ2dwbG90KGxvbmdfZGF0YSwgYWVzKHggPSBEYXksIHkgPSB0ZW1wLCBncm91cCA9IHRlbXBfdHlwZSwgY29sb3IgPSB0ZW1wX3R5cGUpKSArDQogIGdlb21fbGluZSgpICsNCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCANCiAgICAgICB0aXRsZSA9ICJEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IiwNCiAgICAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSAoRikiKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGUpICsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkNCg0KI05vdGUgdGhhdCB0aGUgZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSBhcmd1bWVudCBpcyB0ZWxsaW5nIFIgdG8gY2VudGVyLWFsaWduIHRoZSB0aXRsZSB0ZXh0DQojWW91IGNhbiBwbGF5IGFyb3VuZCB3aXRoIHRoZSBoanVzdCBhcmd1bWVudCB0byBtYW51YWxseSBjaGFuZ2UgdGhlIHRpdGxlIHBvc2l0aW9uIChhbHRob3VnaCBJIGRvbid0IHJlYWxseSBzZWUgYW55IHJlYXNvbiB0byBkbyB0aGlzKQ0KYGBgDQpGaW5hbGx5LCBjYW4geW91IHVzZSBtb3JlIHRoYW4gb25lIHBsb3QgdHlwZSBpbiB0aGUgc2FtZSBwbG90PyBZb3Ugc3VyZSBjYW4hIFRoZSBjb2RlIGJlbG93IHNob3dzIHdoYXQgdGhpcyBsb29rcyBsaWtlIGJ5IGFkZGluZyBhIHRyZW5kIGxpbmUgdG8gdGhlIGRhdGEgdXNpbmcgYSBzbW9vdGhpbmcgbWV0aG9kIChkb24ndCB3b3JyeSBhYm91dCBob3cgaXQgd29ya3MsIHRoaXMgaXMganVzdCBhbiBleGFtcGxlKS4gSW4gdGhpcyBleGFtcGxlLCBiZWNhdXNlIHdlIGFyZSB1c2luZyB0aGUgc21vb3RoaW5nIGZ1bmN0aW9uIHRvIGZpbmQgdGhlIGF2ZXJhZ2UgdmFsdWVzIG9mIGVhY2ggdGVtcGVyYXR1cmUgdHlwZSwgd2UgZG9uJ3QgbmVlZCB0byBjaGFuZ2UgdGhlIGFlc3RoZXRpY3MuIElmLCBmb3IgZXhhbXBsZSwgeW91IHdhbnRlZCB0byBtYWtlIGEgbGluZSBncmFwaCB3aXRoIG9uZSB2YXJpYWJsZSBvdmVyIHRpbWUgYW5kIGEgcG9pbnQgZ3JhcGggd2l0aCBhIGRpZmZlcmVudCB2YXJpYWJsZSBvdmVyIHRpbWUsIHlvdSB3b3VsZCBuZWVkIHRvIG1hbnVhbGx5IGluY2x1ZGUgdGhlIGFlc3RoZXRpY3MgaW4gZWFjaCBnZW9tIGxheWVyIChsaWtlIHdlIGRpZCB0aGUgZmlyc3QgdGltZSB3ZSBhZGRlZCBjb2xvciAtIGluIHRoYXQgZXhhbXBsZSwgZWFjaCB2YXJpYWJsZSBoYWQgaXRzIG93biBnZW9tIGxheWVyLCBhbmQgd2UgaGFkIHRvIG1hcCB0aGUgYWVzdGhldGljcyBmb3IgZWFjaCBvbmUpLiANCg0KYGBge3J9DQoNCmdncGxvdChsb25nX2RhdGEsIGFlcyh4ID0gRGF5LCB5ID0gdGVtcCwgZ3JvdXAgPSB0ZW1wX3R5cGUsIGNvbG9yID0gdGVtcF90eXBlKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3Ntb290aChjb2xvciA9ICJibGFjayIpKw0KICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUiLCB4ID0gIkRheSIsIA0KICAgICAgIHRpdGxlID0gIkRhaWx5IFRlbXBlcmF0dXJlIGluIE5ldyBZb3JrIENpdHksIDIwMTQiLA0KICAgICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIChGKSIpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gcGFsZXR0ZSkgKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQ0KDQpgYGANCkFuZCB0aGVyZSB5b3UgaGF2ZSBpdCEgWW91IGFyZSBub3cgYSBwcm8gYXQgdXNpbmcgZ2dwbG90Mi4gWW91IHNob3VsZCBoYXZlIGFsbCB0aGUgdG9vbHMgeW91IG5lZWQgdG8gbWFrZSBiZWF1dGlmdWwgYW5kIGVmZmVjdGl2ZSB2aXN1YWxpemF0aW9uIGluIFIuIElmIHlvdSB3YW50IG1vcmUgaW5mb3JtYXRpb24gb24gZGlmZmVyZW50IHR5cGVzIG9mIGdyYXBocywgb3IgeW91IGp1c3Qgd2FudCBhIGhlbHBmdWwgcmVmZXJlbmNlIHRvIHJlZmVyIHRvIGFzIHlvdSBwcm9ncmVzcyB0aHJvdWdoIHRoZSBjb3Vyc2UsIHlvdSBjYW4gZmluZCBhbiBleGNlbGxlbnQgZ2dwbG90MiBjaGVhdCBzaGVldCBoZXJlOiBodHRwczovL3d3dy5tYXRocy51c3lkLmVkdS5hdS91L1VHL1NNL1NUQVQzMDIyL3IvY3VycmVudC9NaXNjL2RhdGEtdmlzdWFsaXphdGlvbi0yLjEucGRmLiANCg0KDQpSZXNvdXJjZXMNCg0KRml2ZVRoaXJ0eUVpZ2h0ICgyMDE0KS4gVVMuIFdlYXRoZXIgSGlzdG9yeS4gW0RhdGEgU2V0XS4gUmV0cmlldmVkIGZyb206IGh0dHBzOi8vZ2l0aHViLmNvbS9maXZldGhpcnR5ZWlnaHQvZGF0YS90cmVlL21hc3Rlci91cy13ZWF0aGVyLWhpc3RvcnkuIA0KDQpQcmFiaGFrYXJhbiwgUy4gKDIwMTcpLiBUaGUgQ29tcGxldGUgZ2dwbG90MiBUdXRvcmlhbCAtIFBhcnQxIHwgSW50cm9kdWN0aW9uIFRvIGdncGxvdDIuIFJldHJpZXZlZCBmcm9tOiBodHRwOi8vci1zdGF0aXN0aWNzLmNvL0NvbXBsZXRlLUdncGxvdDItVHV0b3JpYWwtUGFydDEtV2l0aC1SLUNvZGUuaHRtbC4g