Welcome to Week 2 of Harp 130! This week, we will learn some
additional concepts and tools in R that will help you to better work
with, manage, and clean data for statistical analysis. Some of this
tutorial will follow along with the chapter in Learning Statistics with
R; in addition, I will introduce you to some techniques using the dplyr
package, which came out after the initial version of our textbook. Not
only is this package extremely useful for data managment tasks, but it
is also very popular in the R community and will be a very valuable tool
in your arsenal. Let’s get started!
#Let's start by continuing last week's discussion of variables
#When you work with a variable, there are some special values that you might see
#For example, do you remember what you get when you divide any number by 0? Try it!
1/0
[1] Inf
#The answer is infinity, or "Inf"
#Next, what happens if I try to perform an operation that results in an invalid number? For example:
0/0
[1] NaN
#Here, the result is "NaN" which stands for "Not a Number". This means that there is no meaningful numeric answer, or the answer may be undefined. This is distinct from the next two values because we know what the answer is, it just isn't meaningful
#By contrast, "NA" denotes missing data - we don't know what's supposed to be stored in this element. "NULL" on the other hand indicates that there is no value at all.
#In practice, you are more likely to see NaN or NA - it is very important to pay attention to these values. If they pop up, they can invalidate the results of your analysis or cause R to return an incorrect answer. For example, let's say we have this vector and there's accidentally a missing value in it:
obj <- c(1, 3, 5, NA, 2, 7)
#What if we want to take the sum of these values? What does R give us?
sum(obj)
[1] NA
#We get an NA! There are a number of ways to troubleshoot this; the most common way is to tell R to simply ignore missing values, by setting na.rm (short for NA Remove) to TRUE:
sum(obj, na.rm = T)
[1] 18
#As a reminder, you can always check the documentation for a function to see what arguments it takes; many functions will include some variation of the na.rm argument to allow you to ignore missing values. This may not always be the best option, but we don't need to worry about that right now.
#What if we want to add names to that vector that we just created? We can easily do that like so:
names(obj) <- c("E1", "E2", "E3", "E4", "E5", "E6")
#Here I've just used "E-" to generically name each element, but you can use any name that you want
#inspect our vector
obj
E1 E2 E3 E4 E5 E6
1 3 5 NA 2 7
#If I change my mind and don't want the names, I can always do the following to delete them:
names(obj) <- NULL
#We use "NULL" in this case to tell R that there is no value for the names - if we used NA instead, what would happen?
names(obj) <- NA
obj
<NA> <NA> <NA> <NA> <NA> <NA>
1 3 5 NA 2 7
#Finally, names are useful because we can index vectors using element names:
names(obj) <- c("E1", "E2", "E3", "E4", "E5", "E6")
obj["E2"]
E2
3
#Next, we'll talk about a data type that is specific to statistics. So far, we've learned about numeric and character data. The next data type is a Factor
#This becomes important when we want to distinguish between nominal, ordinal, interval and ratio scale data
#Numeric data makes a lot of sense for ratio data, and some sense for interval data (although note that this data does not have a natural zero value, so some operations wouldn't make sense to use)
#What about data types where performing numeric operations don't make a lot of sense? For example, let's think about nominal data. Say I've assigned you all to three groups: groups 1, 2, and 3. We can't say anything about these numbers! It wouldn't make sense to say that group 2 is 2x group 1, or that group 3 minus group 2 equals group 1, would it?
#But, if I store this as numeric data, what happens? Let's say I have this group data:
group <- c(1,2,3,2,1,3,2)
#Realistically, I shouldn't be able to perform any operations on this data, but R will let me:
group*3
[1] 3 6 9 6 3 9 6
group+2
[1] 3 4 5 4 3 5 4
#In order to ensure that our data is properly stored, we can transform this data into a different data type: Factor data.
group <- as.factor(group)
#did it work?
class(group)
[1] "factor"
#Can I perform any computations on this data?
group+1
Warning: ‘+’ not meaningful for factors
[1] NA NA NA NA NA NA NA
#No! This is what we wanted to see.
#What happens if we print out this data?
group
[1] 1 2 3 2 1 3 2
Levels: 1 2 3
#Levels will often refer to the categories in the data, while the data stores the values in our vector. We can also make the levels more meaningful here:
levels(group) <- c("group_1", "group_2", "group_3")
group
[1] group_1 group_2 group_3 group_2 group_1 group_3 group_2
Levels: group_1 group_2 group_3
#It's not necessarily pretty, but it's more meaningful than the previous version
So, you have now seen numeric, character, and factor data, and we’ll
use factors throughout the course to store nominal data. You have also
worked with different types of objects, including values and vectors.
Next, we will introduce a very important type of object: the data frame.
You may be familiar with this data type if you have ever worked in
Microsoft Excel before - a spreadsheet is one way to view a data frame.
At its simplest, a data frame is a way of organizing vectors of data
into a table.
#To start out, let's say we have some data on the students in this class
#We know everyone's major, their home state, and age
major <- c("math", "sociology", "psychology", "geography", "physics", "english")
state <- c("New York", "New York", "Pennsylvania", "New Jersey", "New York", "New York")
age <- c(21,18,19,20,18,19)
#we can view and work with each vector individually, but this doesn't tell us how the different variables relate to each other! Additionally, we know that each vector is the same size, and each element represents the same student in each vector (e.g element 1 is student 1 in each vector)
#In order to visualize this data in a more organized way, we can put it into a data frame!
students <- data.frame(age, major, state)
students
That is so much nicer! Notice now that, in the environment pane, the
“students” data frame is now listed under Data, while our vectors are
listed as Values - this is how R organizes this kind of data. When we
manipulate data, its also important to pay attention to how it is being
categorized - if you convert a dataframe to a vector or serveral vectors
to a data frame, always remember to check that it is being stored
correctly.
#What if we want to just inspect one variable in this data frame? We can do this using the '$' sign like this:
students$state
[1] "New York" "New York" "Pennsylvania" "New Jersey" "New York"
[6] "New York"
#This tells R to print the variable "state" within the data frame "student"
#What if I have a very large data frame, and I need to know what the variable names are? There are a few ways to do this:
names(students)
[1] "age" "major" "state"
colnames(students)
[1] "age" "major" "state"
#Sometimes, you will find that you have a very large data frame, and its time consuming to print out the whole thing. You can view just a few lines using the function head()
head(students)
#Let's look under the hood of this function:
?head
#Here we see that we can set the number of rows that are displayed using the n= argument like this:
head(students, n = 3)
#It can also be helpful to check the type of data that is stored in our data frame:
#Try this first - what type of data is it?
str(students)
'data.frame': 6 obs. of 3 variables:
$ age : num 21 18 19 20 18 19
$ major: chr "math" "sociology" "psychology" "geography" ...
$ state: chr "New York" "New York" "Pennsylvania" "New Jersey" ...
#The str() command gives us a lot of useful information about our data frame! We'll discuss data frame in more detail later; for now, it's just important for you to be familiar with this type of object
Finally, we will introduce one more type of object, the list. Lists
will not be used frequently throughout this course, but they are a
fundamental data structure to R and its helpful for you to at least be
familiar with them now. You will likely use lists quite a bit more as
you learn more advanced programming (I use lists constantly in my own
research). It is also helpful to know about lists in case you ever
accidentally transform a vector or a data frame into a list (which may
occasionally happen if you use a function incorrectly, although
hopefully we will avoid this!). What is a list? A list is a collection
of variables similarly to a data frame. A list, however, is not neat and
structured in the same way that a data frame is. Let’s look at an
example!
#I'll create a list containing some data on a hypothetical student:
student_a <- list( age = 21,
state = "New York",
major = c("Economics","Math")
)
#inspect the list:
student_a
$age
[1] 21
$state
[1] "New York"
$major
[1] "Economics" "Math"
#in our data frame, each student could only have exactly one major - in this list, the element "major" can contain as many values as we want! While all of the columns must be the same length in any data frame, a list is a nice way of storing data of different lengths. We can select an element from a list similarly to a data frame:
student_a$major
[1] "Economics" "Math"
When might you want to use a list? Again, in this class, we likely
won’t use them very often. But, think about a time when you might use a
large amount of data for a research problem. If I’m working with a bunch
of data frames and I need to use a function on each one, it might be
easier for me to create a list of dataframes and run the function on the
list instead - lists end up being very useful at helping you to save
time. But no need to think much more about that now! The purpose of this
section was just to introduce you to the concept.
In this next section, we’ll introduce a useful new R package: dplyr!
This package is part of a larger family of packages that are known as
the tidyverse. I use this package constantly in my own work; it’s very
helpful for working with data, and hopefully you’ll agree!
Before I introduce some functions from the package let’s first a)
download our first package and b) load in some data.
To download a package, you’ll go to tools > install packages >
then type in dplyr in the box
#We have to load in packages every time we start a new session in R
#When you start a new R document, it's often easiest to put all of the packages you'll be
#using at the top of the document
#Before we do that, usually I start by setting the working directory for my R session
#This tells R what folder I'll be using to access any files or data - I frequently work with excel files, so this is very important
#We set the working directory like this:
setwd("C:/Users/melha/OneDrive/Documents/Binghamton/Harp130")
#How can I find my file path? On a Windows machine, go to your file explorer
#It'll show the file path at the top; usually it says something like "> This PC > Documents >...." - if you click on this line, the full file path is shown, and you can copy and paste it right into R
#Note, however, that R is very picky about slashes in you're using a Windows machine - while Windows uses a backslash, you will need to change it to a forward slash manually (I'll show you what I mean)
#After you set the working directory, let's load in our first package! Dplyr
library(dplyr)
#Usually it'll show some text in red - this is generally not an issue, unless you get an error code that says the package won't load
Now, we’ll load in our first data frame, and then I will show you how
to clean it up using dplyr! We’re going to play around with some sample
data. The data in the folder is American Community Survey data from
2010-12 that was compiled by FiveThirtyEight. It has a breakdown of
survey respondents’ college majors, their gender, and the number of
respondents that were employed after graduation. Note that this data is
somewhat outdated (e.g. not every student is represented by only
including two genders), but it is good example data for the exercises
that follow. We will talk more about designing inclusive surveys later.
Make sure you’ve put the .csv file in your working directory!
Source: https://github.com/fivethirtyeight/data/blob/master/college-majors
#Let's read in the data using the read.csv command - this command is how we will load most data in the course
majors <- read.csv("college_majors.csv")
#How many observations are in this data? How many variables?
#Let's inspect the first few rows of the data to make sure it looks right
head(majors)
#Let's start learning how to use dplyr!
#First things first: the pipe symbol, or %>%
#The pipe is extremely useful and flexible, and it makes code very easy to follow
#Essentially, it allows us to perform multiple operations or functions in a logical order
#For example, I can write the following code to repeat the previous step:
majors %>% head()
#Here, I am telling R, "take the majors dataframe, then print the first six lines"
#The pipe is the "then" in the sentence - it tells R what to do next
#We can practice using it with other simple functions:
majors %>% str()
'data.frame': 173 obs. of 8 variables:
$ Major_code : int 2419 2416 2415 2417 2405 2418 6202 5001 2414 2408 ...
$ Major : chr "PETROLEUM ENGINEERING" "MINING AND MINERAL ENGINEERING" "METALLURGICAL ENGINEERING" "NAVAL ARCHITECTURE AND MARINE ENGINEERING" ...
$ Total : int 2339 756 856 1258 32260 2573 3777 1792 91227 81527 ...
$ Men : int 2057 679 725 1123 21239 2200 2110 832 80320 65511 ...
$ Women : int 282 77 131 135 11021 373 1667 960 10907 16016 ...
$ Major_category: chr "Engineering" "Engineering" "Engineering" "Engineering" ...
$ ShareWomen : num 0.121 0.102 0.153 0.107 0.342 ...
$ Employed : int 1976 640 648 758 25694 1857 2912 1526 76442 61928 ...
#Now we know the type of each variable in the data, which is very handy information
#Obviously, we could have just written str(majors) - right now, this doesn't look all that useful!
#Let's introduce some more functions from the dplyr package, and you'll see why the pipe is so versatile
#The first dplyr function we will learn is filter!
#Let's say I want to only look at engineering majors. I can use "filter" to select rows of a dataframe based on a logical condition like this:
majors %>% filter(Major_category == "Engineering") %>% head()
What did I do there? Let’s think through the steps. First, I told R
to use the dataframe, majors. Next, I told R to filter the dataframe and
only include rows where Major_category is equal to Engineering. Then, I
told R that I wanted to see the first six rows of this filtered data.
Note that, when using filter, strings are case sensitive. If I had typed
“engineering” the new data would have contained zero rows. In addition,
note that filtering is a logical operation - that is why I used two
equal signs. When I work with characters using “filter”, I can R that I
want to select rows where a variable is equal (==) or not equal (!=) to
a specified value. If I was filtering based on a numeric value, I can
also tell R to filter rows that are less than (<) or greater than
(>) a specified value. Let’s look at some additional examples:
#select majors that have more than 2,000 students:
majors %>% filter(Total > 2000) %>% head()
#What if I want to filter by multiple categories?
#First, how do I find out what all of the categories are without scrolling through the entire dataframe? We can use the base R function "unique()" to view the unique values of a variable like this:
unique(majors$Major_category)
[1] "Engineering" "Business"
[3] "Physical Sciences" "Law & Public Policy"
[5] "Computers & Mathematics" "Agriculture & Natural Resources"
[7] "Industrial Arts & Consumer Services" "Arts"
[9] "Health" "Social Science"
[11] "Biology & Life Science" "Education"
[13] "Humanities & Liberal Arts" "Psychology & Social Work"
[15] "Communications & Journalism" "Interdisciplinary"
#What if we want to know which category is the largest? We can use another base R function, table(), to look at this:
table(majors$Major_category)
Agriculture & Natural Resources Arts
10 8
Biology & Life Science Business
14 13
Communications & Journalism Computers & Mathematics
4 11
Education Engineering
16 29
Health Humanities & Liberal Arts
12 15
Industrial Arts & Consumer Services Interdisciplinary
7 1
Law & Public Policy Physical Sciences
5 10
Psychology & Social Work Social Science
9 9
#Which is the largest?
#What is we wanted to filter by the Health and Biology & Life Sciences categories? We can do that like so:
majors %>% filter(Major_category == c("Health", "Biology & Life Science")) %>% head()
Warning: longer object length is not a multiple of shorter object length
What did we actually just do? Let’s break it down. First, we told R
to use the majors data. Next, we use filter() to select rows that
contain either Health or Biology & Life Science in the variable
Major_category. Then we asked R to show us the first six rows of the
result. You use the c() that we learned before to tell R to filter by
multiple character values.
#Before we move on, it's important to note that we can save the filtered data to a new object! This comes in handy if we want to perform any analysis on a smaller version of the data. An example:
engineers <- majors %>% filter(Major_category == "Engineering")
#Now we have a new object, engineers, that we can easily work with
Let’s look at another function from dplyr. What if, instead of rows,
I want to select specific columns in a dataframe. This is also very
simple if we use the “select()” function. Let’s look at an example, and
then I’ll explain it in a bit more detail.
#What if we just want to look at enrollment in each major?
enroll <- majors %>% select(Major, Total)
#Using select, I just need to tell R the names of the columns that I am interested in selecting. If you look at my new dataframe, enroll, you'll see that I only have two columns.
#If I'm working with this data, I might want to know which majors have the largest enrollment. Here, we'll use another new dplyr function, arrange() to order the data
enroll <- majors %>% select(Major, Total) %>% arrange(desc(Total))
#When using arrange(), it's important to note that, by default, this function orders numeric data from smallest to largest (or in ascending order). If you wish to order your data from largest to smallest (in descending order), you must tell R this by putting the variable that you wish to order the dataframe by inside of the function desc(). If you check the help documentation for arrange(), it shows examples using desc() - if you ever forget, just check the help page! It will often have the information you're looking for. I'll show more complicated ways to use arrange() later in the course.
Let’s talk about another important function from the dplyr package:
mutate(). This function allows you to easily create a new variable in a
dataframe. It works like this: mutate(variable_name = x). X can be any
number of things - often, you will create a new variable based on a
formula or other variables in the dataframe. Let’s go back to the larger
majors and dataframe and look at some examples of this in practice!
#The simplest possible variable would just be a number or a letter for every row. I can create a variable like this as follows (I'll show you why this is useful in a bit):
majors1 <- majors %>% mutate(one = 1)
#Take a look at the dataframe to see what this looks like! I've stored this as a new dataframe, majors1.
#As I said earlier, often you will use a formula to create a new variable. Let's say, for instance, I want to create a new variable that shows the percentage of each major that are women. I can do this using two existing variables, Total and Women, as follows:
majors1 <- majors1 %>% mutate(women_frac = Women/Total)
#If we want to know which major has the largest percentage of women, we can add on arrange() at the end to find out:
majors1 <- majors1 %>% mutate(women_frac = Women/Total) %>% arrange(desc(women_frac))
#Which major has the largest percentage of women?
#What if I don't want these new variables anymore? I can easily remove them using select():
majors2 <- majors1 %>% select(-c(one, women_frac))
#Deleting two variables requires two things: a) I need to use a "-" to tell R that I am removing two variables rather than selecting them. b) I need to tell R that I am removing both, so I use c() to communicate that to R. What happens if I don't do that?
majors3 <- majors1 %>% select(-one, women_frac)
#alternatively, I can put a "-" in front of each variable to accomplish the same goal - using c() becomes very convenient, however, if you are removing a large number of variables at once.
majors1 <- majors1 %>% select(-one, -women_frac)
I have two more dplyr functions to introduce! The two are summarise()
and group_by(). Often, rather than work with raw data, we will want to
know information about groups within our data. In the majors data, we
might want to know more about each major_category, for example, the
number of students in each category. We don’t want to count up each one
by hand, that would be very tedious! Instead, we can tell R to do this
for us, using the two new functions.
#If I want R to perform an operation or function by group (in this case, by major_category), I have to tell it to do so using group_by(). This function doesn't change the dataframe in any way - it just instructs R to use the specified groups in any subsequent operations. Using it is as simple as:
majors %>% group_by(Major_category)
#Now, I want to create a new dataframe with the total number of students in each category. We can do this by summing the variable Total within each group. summarise() allows us to do just that - this function creates a new dataframe for a summary statistic of our choosing. Because it is a summary of the data, this function typically collapses the larger dataframe into one that has one value for each group. For example, if we use summarise to calculate the mean of the variable Total (without grouping it), this is what we get:
mean_total <- majors %>% summarise(mean = mean(Total, na.rm=T))
#In this line of code, the whole data frame is treated as a single group, so the output of summarise is one value. Let's see what happens when we group the data by category. Here, we'll get the total number of students in each category, so we'll use the sum() function as our summary statistic.
cat_total <- majors %>% group_by(Major_category) %>% summarise(total_cat = sum(Total))
#let's look at this new dataframe:
head(cat_total)
#Uh oh, one of the values is NA! Recall that, when we calculate any summary statistic, R doesn't know what to do with NA values - when it encounters an NA value within a group, it therefore returns NA as the final value. We need to tell it to ignore the NA values to avoid this.
cat_total <- majors %>%
group_by(Major_category) %>%
summarise(total_cat = sum(Total, na.rm=T))
#That should work now! Note that, when I write longer or more complicated code using dplyr, I like to put each additional function on its own line - this just makes the code cleaner and easier to follow.
#So, this does a really nice job producing one summary statistic for us! But what if we want to create a dataframe with a number of summary statistics about the major categories? This is easy to do with summarise() too! If you look up the help page for summarise(), it lists a number of suggested summary statistics that you can calculate using this function - if you are stuck and need ideas, it's helpful to return to the help page. Let's say I want to know the total students in each category, average enrollment for each department in the categories, as well as the largest and smallest enrollment values for the departments in each category. Here's how I do it, using the sum(), mean(), min(), and max() functions that are built into R:
summary_cat <- majors %>%
group_by(Major_category) %>%
summarise(total = sum(Total, na.rm = T), avg = mean(Total, na.rm = T),
smallest = min(Total, na.rm = T), largest = max(Total, na.rm = T))
#Now we have a nice summary table! Let's arrange the table in an order that makes sense, for example, alphabetically:
summary_cat <- summary_cat %>% arrange(Major_category)
That’s it for Week 2 - we’ve covered a lot of ground! In this week’s
tutorial, we’ve discussed missing data, how to work with data frames and
lists, and the basics of the dplyr package. Using this package, you will
be able to easily clean and manipulate data, create new variables, and
produce summary statistics. We learned about the pipe operator (
%>%), and some of the most common dplyr functions: filter(),
select(), mutate(), arrange(), group_by(), and summarise(). We also
learned some new base R functions that we will use to produce summary
statistics as we go: mean, sum, min, and max. We will learn more summary
statistics as we go, but these are important basic functions to start
with. Next week, we will use our data manipulation skills to learn how
to produce basic visuals and graphs using the ggplot2 package. The
skills we are learning in the first three weeks of this course are
foundational R concepts that we will utilize throughout the course and
that will help you if you choose to expand your programming knowledge in
the future.
Resources
Navarro, D. (2019). Learning Statistics with R. Retrieved from: https://learningstatisticswithr.com/book/index.html.
Wickham, H., François, R., Henry, L. & Müller, K. (2021). dplyr:
A grammar of data manipulation. R pack-age version 1.0.6. Retrieved from
https:// CRAN.R- proje ct. org/ packa
ge= dplyr.
LS0tDQp0aXRsZTogIkhhcnAgMTMwIFdlZWsgMiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCldlbGNvbWUgdG8gV2VlayAyIG9mIEhhcnAgMTMwISBUaGlzIHdlZWssIHdlIHdpbGwgbGVhcm4gc29tZSBhZGRpdGlvbmFsIGNvbmNlcHRzIGFuZCB0b29scyBpbiBSIHRoYXQgd2lsbCBoZWxwIHlvdSB0byBiZXR0ZXIgd29yayB3aXRoLCBtYW5hZ2UsIGFuZCBjbGVhbiBkYXRhIGZvciBzdGF0aXN0aWNhbCBhbmFseXNpcy4gU29tZSBvZiB0aGlzIHR1dG9yaWFsIHdpbGwgZm9sbG93IGFsb25nIHdpdGggdGhlIGNoYXB0ZXIgaW4gTGVhcm5pbmcgU3RhdGlzdGljcyB3aXRoIFI7IGluIGFkZGl0aW9uLCBJIHdpbGwgaW50cm9kdWNlIHlvdSB0byBzb21lIHRlY2huaXF1ZXMgdXNpbmcgdGhlIGRwbHlyIHBhY2thZ2UsIHdoaWNoIGNhbWUgb3V0IGFmdGVyIHRoZSBpbml0aWFsIHZlcnNpb24gb2Ygb3VyIHRleHRib29rLiBOb3Qgb25seSBpcyB0aGlzIHBhY2thZ2UgZXh0cmVtZWx5IHVzZWZ1bCBmb3IgZGF0YSBtYW5hZ21lbnQgdGFza3MsIGJ1dCBpdCBpcyBhbHNvIHZlcnkgcG9wdWxhciBpbiB0aGUgUiBjb21tdW5pdHkgYW5kIHdpbGwgYmUgYSB2ZXJ5IHZhbHVhYmxlIHRvb2wgaW4geW91ciBhcnNlbmFsLiBMZXQncyBnZXQgc3RhcnRlZCENCg0KYGBge3J9DQoNCiNMZXQncyBzdGFydCBieSBjb250aW51aW5nIGxhc3Qgd2VlaydzIGRpc2N1c3Npb24gb2YgdmFyaWFibGVzDQojV2hlbiB5b3Ugd29yayB3aXRoIGEgdmFyaWFibGUsIHRoZXJlIGFyZSBzb21lIHNwZWNpYWwgdmFsdWVzIHRoYXQgeW91IG1pZ2h0IHNlZQ0KDQojRm9yIGV4YW1wbGUsIGRvIHlvdSByZW1lbWJlciB3aGF0IHlvdSBnZXQgd2hlbiB5b3UgZGl2aWRlIGFueSBudW1iZXIgYnkgMD8gVHJ5IGl0IQ0KDQoxLzANCg0KI1RoZSBhbnN3ZXIgaXMgaW5maW5pdHksIG9yICJJbmYiDQoNCiNOZXh0LCB3aGF0IGhhcHBlbnMgaWYgSSB0cnkgdG8gcGVyZm9ybSBhbiBvcGVyYXRpb24gdGhhdCByZXN1bHRzIGluIGFuIGludmFsaWQgbnVtYmVyPyBGb3IgZXhhbXBsZToNCg0KMC8wDQoNCiNIZXJlLCB0aGUgcmVzdWx0IGlzICJOYU4iIHdoaWNoIHN0YW5kcyBmb3IgIk5vdCBhIE51bWJlciIuIFRoaXMgbWVhbnMgdGhhdCB0aGVyZSBpcyBubyBtZWFuaW5nZnVsIG51bWVyaWMgYW5zd2VyLCBvciB0aGUgYW5zd2VyIG1heSBiZSB1bmRlZmluZWQuIFRoaXMgaXMgZGlzdGluY3QgZnJvbSB0aGUgbmV4dCB0d28gdmFsdWVzIGJlY2F1c2Ugd2Uga25vdyB3aGF0IHRoZSBhbnN3ZXIgaXMsIGl0IGp1c3QgaXNuJ3QgbWVhbmluZ2Z1bA0KDQojQnkgY29udHJhc3QsICJOQSIgZGVub3RlcyBtaXNzaW5nIGRhdGEgLSB3ZSBkb24ndCBrbm93IHdoYXQncyBzdXBwb3NlZCB0byBiZSBzdG9yZWQgaW4gdGhpcyBlbGVtZW50LiAiTlVMTCIgb24gdGhlIG90aGVyIGhhbmQgaW5kaWNhdGVzIHRoYXQgdGhlcmUgaXMgbm8gdmFsdWUgYXQgYWxsLiANCg0KYGBgDQpgYGB7cn0NCiNJbiBwcmFjdGljZSwgeW91IGFyZSBtb3JlIGxpa2VseSB0byBzZWUgTmFOIG9yIE5BIC0gaXQgaXMgdmVyeSBpbXBvcnRhbnQgdG8gcGF5IGF0dGVudGlvbiB0byB0aGVzZSB2YWx1ZXMuIElmIHRoZXkgcG9wIHVwLCB0aGV5IGNhbiBpbnZhbGlkYXRlIHRoZSByZXN1bHRzIG9mIHlvdXIgYW5hbHlzaXMgb3IgY2F1c2UgUiB0byByZXR1cm4gYW4gaW5jb3JyZWN0IGFuc3dlci4gRm9yIGV4YW1wbGUsIGxldCdzIHNheSB3ZSBoYXZlIHRoaXMgdmVjdG9yIGFuZCB0aGVyZSdzIGFjY2lkZW50YWxseSBhIG1pc3NpbmcgdmFsdWUgaW4gaXQ6DQoNCm9iaiA8LSBjKDEsIDMsIDUsIE5BLCAyLCA3KQ0KDQojV2hhdCBpZiB3ZSB3YW50IHRvIHRha2UgdGhlIHN1bSBvZiB0aGVzZSB2YWx1ZXM/IFdoYXQgZG9lcyBSIGdpdmUgdXM/DQoNCnN1bShvYmopDQoNCiNXZSBnZXQgYW4gTkEhIFRoZXJlIGFyZSBhIG51bWJlciBvZiB3YXlzIHRvIHRyb3VibGVzaG9vdCB0aGlzOyB0aGUgbW9zdCBjb21tb24gd2F5IGlzIHRvIHRlbGwgUiB0byBzaW1wbHkgaWdub3JlIG1pc3NpbmcgdmFsdWVzLCBieSBzZXR0aW5nIG5hLnJtIChzaG9ydCBmb3IgTkEgUmVtb3ZlKSB0byBUUlVFOg0KDQpzdW0ob2JqLCBuYS5ybSA9IFQpDQoNCiNBcyBhIHJlbWluZGVyLCB5b3UgY2FuIGFsd2F5cyBjaGVjayB0aGUgZG9jdW1lbnRhdGlvbiBmb3IgYSBmdW5jdGlvbiB0byBzZWUgd2hhdCBhcmd1bWVudHMgaXQgdGFrZXM7IG1hbnkgZnVuY3Rpb25zIHdpbGwgaW5jbHVkZSBzb21lIHZhcmlhdGlvbiBvZiB0aGUgbmEucm0gYXJndW1lbnQgdG8gYWxsb3cgeW91IHRvIGlnbm9yZSBtaXNzaW5nIHZhbHVlcy4gVGhpcyBtYXkgbm90IGFsd2F5cyBiZSB0aGUgYmVzdCBvcHRpb24sIGJ1dCB3ZSBkb24ndCBuZWVkIHRvIHdvcnJ5IGFib3V0IHRoYXQgcmlnaHQgbm93LiANCmBgYA0KDQpgYGB7cn0NCiNXaGF0IGlmIHdlIHdhbnQgdG8gYWRkIG5hbWVzIHRvIHRoYXQgdmVjdG9yIHRoYXQgd2UganVzdCBjcmVhdGVkPyBXZSBjYW4gZWFzaWx5IGRvIHRoYXQgbGlrZSBzbzoNCg0KbmFtZXMob2JqKSA8LSBjKCJFMSIsICJFMiIsICJFMyIsICJFNCIsICJFNSIsICJFNiIpDQoNCiNIZXJlIEkndmUganVzdCB1c2VkICJFLSIgdG8gZ2VuZXJpY2FsbHkgbmFtZSBlYWNoIGVsZW1lbnQsIGJ1dCB5b3UgY2FuIHVzZSBhbnkgbmFtZSB0aGF0IHlvdSB3YW50DQojaW5zcGVjdCBvdXIgdmVjdG9yDQpvYmoNCg0KI0lmIEkgY2hhbmdlIG15IG1pbmQgYW5kIGRvbid0IHdhbnQgdGhlIG5hbWVzLCBJIGNhbiBhbHdheXMgZG8gdGhlIGZvbGxvd2luZyB0byBkZWxldGUgdGhlbToNCm5hbWVzKG9iaikgPC0gTlVMTA0KDQojV2UgdXNlICJOVUxMIiBpbiB0aGlzIGNhc2UgdG8gdGVsbCBSIHRoYXQgdGhlcmUgaXMgbm8gdmFsdWUgZm9yIHRoZSBuYW1lcyAtIGlmIHdlIHVzZWQgTkEgaW5zdGVhZCwgd2hhdCB3b3VsZCBoYXBwZW4/DQoNCm5hbWVzKG9iaikgPC0gTkENCg0Kb2JqDQoNCiNGaW5hbGx5LCBuYW1lcyBhcmUgdXNlZnVsIGJlY2F1c2Ugd2UgY2FuIGluZGV4IHZlY3RvcnMgdXNpbmcgZWxlbWVudCBuYW1lczoNCg0KbmFtZXMob2JqKSA8LSBjKCJFMSIsICJFMiIsICJFMyIsICJFNCIsICJFNSIsICJFNiIpDQpvYmpbIkUyIl0NCmBgYA0KYGBge3J9DQojTmV4dCwgd2UnbGwgdGFsayBhYm91dCBhIGRhdGEgdHlwZSB0aGF0IGlzIHNwZWNpZmljIHRvIHN0YXRpc3RpY3MuIFNvIGZhciwgd2UndmUgbGVhcm5lZCBhYm91dCBudW1lcmljIGFuZCBjaGFyYWN0ZXIgZGF0YS4gVGhlIG5leHQgZGF0YSB0eXBlIGlzIGEgRmFjdG9yDQojVGhpcyBiZWNvbWVzIGltcG9ydGFudCB3aGVuIHdlIHdhbnQgdG8gZGlzdGluZ3Vpc2ggYmV0d2VlbiBub21pbmFsLCBvcmRpbmFsLCBpbnRlcnZhbCBhbmQgcmF0aW8gc2NhbGUgZGF0YQ0KI051bWVyaWMgZGF0YSBtYWtlcyBhIGxvdCBvZiBzZW5zZSBmb3IgcmF0aW8gZGF0YSwgYW5kIHNvbWUgc2Vuc2UgZm9yIGludGVydmFsIGRhdGEgKGFsdGhvdWdoIG5vdGUgdGhhdCB0aGlzIGRhdGEgZG9lcyBub3QgaGF2ZSBhIG5hdHVyYWwgemVybyB2YWx1ZSwgc28gc29tZSBvcGVyYXRpb25zIHdvdWxkbid0IG1ha2Ugc2Vuc2UgdG8gdXNlKQ0KI1doYXQgYWJvdXQgZGF0YSB0eXBlcyB3aGVyZSBwZXJmb3JtaW5nIG51bWVyaWMgb3BlcmF0aW9ucyBkb24ndCBtYWtlIGEgbG90IG9mIHNlbnNlPyBGb3IgZXhhbXBsZSwgbGV0J3MgdGhpbmsgYWJvdXQgbm9taW5hbCBkYXRhLiBTYXkgSSd2ZSBhc3NpZ25lZCB5b3UgYWxsIHRvIHRocmVlIGdyb3VwczogZ3JvdXBzIDEsIDIsIGFuZCAzLiBXZSBjYW4ndCBzYXkgYW55dGhpbmcgYWJvdXQgdGhlc2UgbnVtYmVycyEgSXQgd291bGRuJ3QgbWFrZSBzZW5zZSB0byBzYXkgdGhhdCBncm91cCAyIGlzIDJ4IGdyb3VwIDEsIG9yIHRoYXQgZ3JvdXAgMyBtaW51cyBncm91cCAyIGVxdWFscyBncm91cCAxLCB3b3VsZCBpdD8gDQoNCiNCdXQsIGlmIEkgc3RvcmUgdGhpcyBhcyBudW1lcmljIGRhdGEsIHdoYXQgaGFwcGVucz8gTGV0J3Mgc2F5IEkgaGF2ZSB0aGlzIGdyb3VwIGRhdGE6DQoNCmdyb3VwIDwtIGMoMSwyLDMsMiwxLDMsMikNCg0KI1JlYWxpc3RpY2FsbHksIEkgc2hvdWxkbid0IGJlIGFibGUgdG8gcGVyZm9ybSBhbnkgb3BlcmF0aW9ucyBvbiB0aGlzIGRhdGEsIGJ1dCBSIHdpbGwgbGV0IG1lOg0KDQpncm91cCozDQpncm91cCsyDQpgYGANCmBgYHtyfQ0KI0luIG9yZGVyIHRvIGVuc3VyZSB0aGF0IG91ciBkYXRhIGlzIHByb3Blcmx5IHN0b3JlZCwgd2UgY2FuIHRyYW5zZm9ybSB0aGlzIGRhdGEgaW50byBhIGRpZmZlcmVudCBkYXRhIHR5cGU6IEZhY3RvciBkYXRhLiANCg0KZ3JvdXAgPC0gYXMuZmFjdG9yKGdyb3VwKQ0KDQojZGlkIGl0IHdvcms/DQoNCmNsYXNzKGdyb3VwKQ0KDQojQ2FuIEkgcGVyZm9ybSBhbnkgY29tcHV0YXRpb25zIG9uIHRoaXMgZGF0YT8NCg0KZ3JvdXArMQ0KDQojTm8hIFRoaXMgaXMgd2hhdCB3ZSB3YW50ZWQgdG8gc2VlLiANCmBgYA0KYGBge3J9DQojV2hhdCBoYXBwZW5zIGlmIHdlIHByaW50IG91dCB0aGlzIGRhdGE/DQoNCmdyb3VwDQoNCiNMZXZlbHMgd2lsbCBvZnRlbiByZWZlciB0byB0aGUgY2F0ZWdvcmllcyBpbiB0aGUgZGF0YSwgd2hpbGUgdGhlIGRhdGEgc3RvcmVzIHRoZSB2YWx1ZXMgaW4gb3VyIHZlY3Rvci4gV2UgY2FuIGFsc28gbWFrZSB0aGUgbGV2ZWxzIG1vcmUgbWVhbmluZ2Z1bCBoZXJlOg0KDQpsZXZlbHMoZ3JvdXApIDwtIGMoImdyb3VwXzEiLCAiZ3JvdXBfMiIsICJncm91cF8zIikNCg0KZ3JvdXANCg0KI0l0J3Mgbm90IG5lY2Vzc2FyaWx5IHByZXR0eSwgYnV0IGl0J3MgbW9yZSBtZWFuaW5nZnVsIHRoYW4gdGhlIHByZXZpb3VzIHZlcnNpb24NCmBgYA0KU28sIHlvdSBoYXZlIG5vdyBzZWVuIG51bWVyaWMsIGNoYXJhY3RlciwgYW5kIGZhY3RvciBkYXRhLCBhbmQgd2UnbGwgdXNlIGZhY3RvcnMgdGhyb3VnaG91dCB0aGUgY291cnNlIHRvIHN0b3JlIG5vbWluYWwgZGF0YS4gWW91IGhhdmUgYWxzbyB3b3JrZWQgd2l0aCBkaWZmZXJlbnQgdHlwZXMgb2Ygb2JqZWN0cywgaW5jbHVkaW5nIHZhbHVlcyBhbmQgdmVjdG9ycy4gTmV4dCwgd2Ugd2lsbCBpbnRyb2R1Y2UgYSB2ZXJ5IGltcG9ydGFudCB0eXBlIG9mIG9iamVjdDogdGhlIGRhdGEgZnJhbWUuIFlvdSBtYXkgYmUgZmFtaWxpYXIgd2l0aCB0aGlzIGRhdGEgdHlwZSBpZiB5b3UgaGF2ZSBldmVyIHdvcmtlZCBpbiBNaWNyb3NvZnQgRXhjZWwgYmVmb3JlIC0gYSBzcHJlYWRzaGVldCBpcyBvbmUgd2F5IHRvIHZpZXcgYSBkYXRhIGZyYW1lLiBBdCBpdHMgc2ltcGxlc3QsIGEgZGF0YSBmcmFtZSBpcyBhIHdheSBvZiBvcmdhbml6aW5nIHZlY3RvcnMgb2YgZGF0YSBpbnRvIGEgdGFibGUuIA0KDQpgYGB7cn0NCiNUbyBzdGFydCBvdXQsIGxldCdzIHNheSB3ZSBoYXZlIHNvbWUgZGF0YSBvbiB0aGUgc3R1ZGVudHMgaW4gdGhpcyBjbGFzcw0KI1dlIGtub3cgZXZlcnlvbmUncyBtYWpvciwgdGhlaXIgaG9tZSBzdGF0ZSwgYW5kIGFnZQ0KDQptYWpvciA8LSBjKCJtYXRoIiwgInNvY2lvbG9neSIsICJwc3ljaG9sb2d5IiwgImdlb2dyYXBoeSIsICJwaHlzaWNzIiwgImVuZ2xpc2giKQ0Kc3RhdGUgPC0gYygiTmV3IFlvcmsiLCAiTmV3IFlvcmsiLCAiUGVubnN5bHZhbmlhIiwgIk5ldyBKZXJzZXkiLCAiTmV3IFlvcmsiLCAiTmV3IFlvcmsiKQ0KYWdlIDwtIGMoMjEsMTgsMTksMjAsMTgsMTkpDQoNCiN3ZSBjYW4gdmlldyBhbmQgd29yayB3aXRoIGVhY2ggdmVjdG9yIGluZGl2aWR1YWxseSwgYnV0IHRoaXMgZG9lc24ndCB0ZWxsIHVzIGhvdyB0aGUgZGlmZmVyZW50IHZhcmlhYmxlcyByZWxhdGUgdG8gZWFjaCBvdGhlciEgQWRkaXRpb25hbGx5LCB3ZSBrbm93IHRoYXQgZWFjaCB2ZWN0b3IgaXMgdGhlIHNhbWUgc2l6ZSwgYW5kIGVhY2ggZWxlbWVudCByZXByZXNlbnRzIHRoZSBzYW1lIHN0dWRlbnQgaW4gZWFjaCB2ZWN0b3IgKGUuZyBlbGVtZW50IDEgaXMgc3R1ZGVudCAxIGluIGVhY2ggdmVjdG9yKQ0KI0luIG9yZGVyIHRvIHZpc3VhbGl6ZSB0aGlzIGRhdGEgaW4gYSBtb3JlIG9yZ2FuaXplZCB3YXksIHdlIGNhbiBwdXQgaXQgaW50byBhIGRhdGEgZnJhbWUhDQoNCnN0dWRlbnRzIDwtIGRhdGEuZnJhbWUoYWdlLCBtYWpvciwgc3RhdGUpDQoNCnN0dWRlbnRzDQpgYGANClRoYXQgaXMgc28gbXVjaCBuaWNlciEgTm90aWNlIG5vdyB0aGF0LCBpbiB0aGUgZW52aXJvbm1lbnQgcGFuZSwgdGhlICJzdHVkZW50cyIgZGF0YSBmcmFtZSBpcyBub3cgbGlzdGVkIHVuZGVyIERhdGEsIHdoaWxlIG91ciB2ZWN0b3JzIGFyZSBsaXN0ZWQgYXMgVmFsdWVzIC0gdGhpcyBpcyBob3cgUiBvcmdhbml6ZXMgdGhpcyBraW5kIG9mIGRhdGEuIFdoZW4gd2UgbWFuaXB1bGF0ZSBkYXRhLCBpdHMgYWxzbyBpbXBvcnRhbnQgdG8gcGF5IGF0dGVudGlvbiB0byBob3cgaXQgaXMgYmVpbmcgY2F0ZWdvcml6ZWQgLSBpZiB5b3UgY29udmVydCBhIGRhdGFmcmFtZSB0byBhIHZlY3RvciBvciBzZXJ2ZXJhbCB2ZWN0b3JzIHRvIGEgZGF0YSBmcmFtZSwgYWx3YXlzIHJlbWVtYmVyIHRvIGNoZWNrIHRoYXQgaXQgaXMgYmVpbmcgc3RvcmVkIGNvcnJlY3RseS4gDQoNCmBgYHtyfQ0KI1doYXQgaWYgd2Ugd2FudCB0byBqdXN0IGluc3BlY3Qgb25lIHZhcmlhYmxlIGluIHRoaXMgZGF0YSBmcmFtZT8gV2UgY2FuIGRvIHRoaXMgdXNpbmcgdGhlICckJyBzaWduIGxpa2UgdGhpczoNCg0Kc3R1ZGVudHMkc3RhdGUNCg0KI1RoaXMgdGVsbHMgUiB0byBwcmludCB0aGUgdmFyaWFibGUgInN0YXRlIiB3aXRoaW4gdGhlIGRhdGEgZnJhbWUgInN0dWRlbnQiDQoNCiNXaGF0IGlmIEkgaGF2ZSBhIHZlcnkgbGFyZ2UgZGF0YSBmcmFtZSwgYW5kIEkgbmVlZCB0byBrbm93IHdoYXQgdGhlIHZhcmlhYmxlIG5hbWVzIGFyZT8gVGhlcmUgYXJlIGEgZmV3IHdheXMgdG8gZG8gdGhpczoNCg0KbmFtZXMoc3R1ZGVudHMpDQoNCmNvbG5hbWVzKHN0dWRlbnRzKQ0KYGBgDQpgYGB7cn0NCiNTb21ldGltZXMsIHlvdSB3aWxsIGZpbmQgdGhhdCB5b3UgaGF2ZSBhIHZlcnkgbGFyZ2UgZGF0YSBmcmFtZSwgYW5kIGl0cyB0aW1lIGNvbnN1bWluZyB0byBwcmludCBvdXQgdGhlIHdob2xlIHRoaW5nLiBZb3UgY2FuIHZpZXcganVzdCBhIGZldyBsaW5lcyB1c2luZyB0aGUgZnVuY3Rpb24gaGVhZCgpDQoNCmhlYWQoc3R1ZGVudHMpDQoNCiNMZXQncyBsb29rIHVuZGVyIHRoZSBob29kIG9mIHRoaXMgZnVuY3Rpb246DQoNCj9oZWFkDQoNCiNIZXJlIHdlIHNlZSB0aGF0IHdlIGNhbiBzZXQgdGhlIG51bWJlciBvZiByb3dzIHRoYXQgYXJlIGRpc3BsYXllZCB1c2luZyB0aGUgbj0gYXJndW1lbnQgbGlrZSB0aGlzOg0KDQpoZWFkKHN0dWRlbnRzLCBuID0gMykNCmBgYA0KYGBge3J9DQojSXQgY2FuIGFsc28gYmUgaGVscGZ1bCB0byBjaGVjayB0aGUgdHlwZSBvZiBkYXRhIHRoYXQgaXMgc3RvcmVkIGluIG91ciBkYXRhIGZyYW1lOg0KI1RyeSB0aGlzIGZpcnN0IC0gd2hhdCB0eXBlIG9mIGRhdGEgaXMgaXQ/DQpzdHIoc3R1ZGVudHMpDQoNCiNUaGUgc3RyKCkgY29tbWFuZCBnaXZlcyB1cyBhIGxvdCBvZiB1c2VmdWwgaW5mb3JtYXRpb24gYWJvdXQgb3VyIGRhdGEgZnJhbWUhIFdlJ2xsIGRpc2N1c3MgZGF0YSBmcmFtZSBpbiBtb3JlIGRldGFpbCBsYXRlcjsgZm9yIG5vdywgaXQncyBqdXN0IGltcG9ydGFudCBmb3IgeW91IHRvIGJlIGZhbWlsaWFyIHdpdGggdGhpcyB0eXBlIG9mIG9iamVjdA0KYGBgDQpGaW5hbGx5LCB3ZSB3aWxsIGludHJvZHVjZSBvbmUgbW9yZSB0eXBlIG9mIG9iamVjdCwgdGhlIGxpc3QuIExpc3RzIHdpbGwgbm90IGJlIHVzZWQgZnJlcXVlbnRseSB0aHJvdWdob3V0IHRoaXMgY291cnNlLCBidXQgdGhleSBhcmUgYSBmdW5kYW1lbnRhbCBkYXRhIHN0cnVjdHVyZSB0byBSIGFuZCBpdHMgaGVscGZ1bCBmb3IgeW91IHRvIGF0IGxlYXN0IGJlIGZhbWlsaWFyIHdpdGggdGhlbSBub3cuIFlvdSB3aWxsIGxpa2VseSB1c2UgbGlzdHMgcXVpdGUgYSBiaXQgbW9yZSBhcyB5b3UgbGVhcm4gbW9yZSBhZHZhbmNlZCBwcm9ncmFtbWluZyAoSSB1c2UgbGlzdHMgY29uc3RhbnRseSBpbiBteSBvd24gcmVzZWFyY2gpLiBJdCBpcyBhbHNvIGhlbHBmdWwgdG8ga25vdyBhYm91dCBsaXN0cyBpbiBjYXNlIHlvdSBldmVyIGFjY2lkZW50YWxseSB0cmFuc2Zvcm0gYSB2ZWN0b3Igb3IgYSBkYXRhIGZyYW1lIGludG8gYSBsaXN0ICh3aGljaCBtYXkgb2NjYXNpb25hbGx5IGhhcHBlbiBpZiB5b3UgdXNlIGEgZnVuY3Rpb24gaW5jb3JyZWN0bHksIGFsdGhvdWdoIGhvcGVmdWxseSB3ZSB3aWxsIGF2b2lkIHRoaXMhKS4gV2hhdCBpcyBhIGxpc3Q/IEEgbGlzdCBpcyBhIGNvbGxlY3Rpb24gb2YgdmFyaWFibGVzIHNpbWlsYXJseSB0byBhIGRhdGEgZnJhbWUuIEEgbGlzdCwgaG93ZXZlciwgaXMgbm90IG5lYXQgYW5kIHN0cnVjdHVyZWQgaW4gdGhlIHNhbWUgd2F5IHRoYXQgYSBkYXRhIGZyYW1lIGlzLiBMZXQncyBsb29rIGF0IGFuIGV4YW1wbGUhDQoNCmBgYHtyfQ0KI0knbGwgY3JlYXRlIGEgbGlzdCBjb250YWluaW5nIHNvbWUgZGF0YSBvbiBhIGh5cG90aGV0aWNhbCBzdHVkZW50Og0Kc3R1ZGVudF9hIDwtIGxpc3QoIGFnZSA9IDIxLA0KICAgICAgICAgICAgICAgICAgIHN0YXRlID0gIk5ldyBZb3JrIiwNCiAgICAgICAgICAgICAgICAgICBtYWpvciA9IGMoIkVjb25vbWljcyIsIk1hdGgiKSANCikNCg0KI2luc3BlY3QgdGhlIGxpc3Q6DQpzdHVkZW50X2ENCg0KI2luIG91ciBkYXRhIGZyYW1lLCBlYWNoIHN0dWRlbnQgY291bGQgb25seSBoYXZlIGV4YWN0bHkgb25lIG1ham9yIC0gaW4gdGhpcyBsaXN0LCB0aGUgZWxlbWVudCAibWFqb3IiIGNhbiBjb250YWluIGFzIG1hbnkgdmFsdWVzIGFzIHdlIHdhbnQhIFdoaWxlIGFsbCBvZiB0aGUgY29sdW1ucyBtdXN0IGJlIHRoZSBzYW1lIGxlbmd0aCBpbiBhbnkgZGF0YSBmcmFtZSwgYSBsaXN0IGlzIGEgbmljZSB3YXkgb2Ygc3RvcmluZyBkYXRhIG9mIGRpZmZlcmVudCBsZW5ndGhzLiBXZSBjYW4gc2VsZWN0IGFuIGVsZW1lbnQgZnJvbSBhIGxpc3Qgc2ltaWxhcmx5IHRvIGEgZGF0YSBmcmFtZToNCg0Kc3R1ZGVudF9hJG1ham9yDQpgYGANCldoZW4gbWlnaHQgeW91IHdhbnQgdG8gdXNlIGEgbGlzdD8gQWdhaW4sIGluIHRoaXMgY2xhc3MsIHdlIGxpa2VseSB3b24ndCB1c2UgdGhlbSB2ZXJ5IG9mdGVuLiBCdXQsIHRoaW5rIGFib3V0IGEgdGltZSB3aGVuIHlvdSBtaWdodCB1c2UgYSBsYXJnZSBhbW91bnQgb2YgZGF0YSBmb3IgYSByZXNlYXJjaCBwcm9ibGVtLiBJZiBJJ20gd29ya2luZyB3aXRoIGEgYnVuY2ggb2YgZGF0YSBmcmFtZXMgYW5kIEkgbmVlZCB0byB1c2UgYSBmdW5jdGlvbiBvbiBlYWNoIG9uZSwgaXQgbWlnaHQgYmUgZWFzaWVyIGZvciBtZSB0byBjcmVhdGUgYSBsaXN0IG9mIGRhdGFmcmFtZXMgYW5kIHJ1biB0aGUgZnVuY3Rpb24gb24gdGhlIGxpc3QgaW5zdGVhZCAtIGxpc3RzIGVuZCB1cCBiZWluZyB2ZXJ5IHVzZWZ1bCBhdCBoZWxwaW5nIHlvdSB0byBzYXZlIHRpbWUuIEJ1dCBubyBuZWVkIHRvIHRoaW5rIG11Y2ggbW9yZSBhYm91dCB0aGF0IG5vdyEgVGhlIHB1cnBvc2Ugb2YgdGhpcyBzZWN0aW9uIHdhcyBqdXN0IHRvIGludHJvZHVjZSB5b3UgdG8gdGhlIGNvbmNlcHQuIA0KDQpJbiB0aGlzIG5leHQgc2VjdGlvbiwgd2UnbGwgaW50cm9kdWNlIGEgdXNlZnVsIG5ldyBSIHBhY2thZ2U6IGRwbHlyISBUaGlzIHBhY2thZ2UgaXMgcGFydCBvZiBhIGxhcmdlciBmYW1pbHkgb2YgcGFja2FnZXMgdGhhdCBhcmUga25vd24gYXMgdGhlIHRpZHl2ZXJzZS4gSSB1c2UgdGhpcyBwYWNrYWdlIGNvbnN0YW50bHkgaW4gbXkgb3duIHdvcms7IGl0J3MgdmVyeSBoZWxwZnVsIGZvciB3b3JraW5nIHdpdGggZGF0YSwgYW5kIGhvcGVmdWxseSB5b3UnbGwgYWdyZWUhDQoNCkJlZm9yZSBJIGludHJvZHVjZSBzb21lIGZ1bmN0aW9ucyBmcm9tIHRoZSBwYWNrYWdlIGxldCdzIGZpcnN0IGEpIGRvd25sb2FkIG91ciBmaXJzdCBwYWNrYWdlIGFuZCBiKSBsb2FkIGluIHNvbWUgZGF0YS4gDQoNClRvIGRvd25sb2FkIGEgcGFja2FnZSwgeW91J2xsIGdvIHRvIHRvb2xzID4gaW5zdGFsbCBwYWNrYWdlcyA+IHRoZW4gdHlwZSBpbiBkcGx5ciBpbiB0aGUgYm94DQoNCmBgYHtyfQ0KI1dlIGhhdmUgdG8gbG9hZCBpbiBwYWNrYWdlcyBldmVyeSB0aW1lIHdlIHN0YXJ0IGEgbmV3IHNlc3Npb24gaW4gUg0KI1doZW4geW91IHN0YXJ0IGEgbmV3IFIgZG9jdW1lbnQsIGl0J3Mgb2Z0ZW4gZWFzaWVzdCB0byBwdXQgYWxsIG9mIHRoZSBwYWNrYWdlcyB5b3UnbGwgYmUgDQojdXNpbmcgYXQgdGhlIHRvcCBvZiB0aGUgZG9jdW1lbnQNCiNCZWZvcmUgd2UgZG8gdGhhdCwgdXN1YWxseSBJIHN0YXJ0IGJ5IHNldHRpbmcgdGhlIHdvcmtpbmcgZGlyZWN0b3J5IGZvciBteSBSIHNlc3Npb24NCiNUaGlzIHRlbGxzIFIgd2hhdCBmb2xkZXIgSSdsbCBiZSB1c2luZyB0byBhY2Nlc3MgYW55IGZpbGVzIG9yIGRhdGEgLSBJIGZyZXF1ZW50bHkgd29yayB3aXRoIGV4Y2VsIGZpbGVzLCBzbyB0aGlzIGlzIHZlcnkgaW1wb3J0YW50IA0KI1dlIHNldCB0aGUgd29ya2luZyBkaXJlY3RvcnkgbGlrZSB0aGlzOg0KDQpzZXR3ZCgiQzovVXNlcnMvbWVsaGEvT25lRHJpdmUvRG9jdW1lbnRzL0JpbmdoYW10b24vSGFycDEzMCIpDQoNCiNIb3cgY2FuIEkgZmluZCBteSBmaWxlIHBhdGg/IE9uIGEgV2luZG93cyBtYWNoaW5lLCBnbyB0byB5b3VyIGZpbGUgZXhwbG9yZXINCiNJdCdsbCBzaG93IHRoZSBmaWxlIHBhdGggYXQgdGhlIHRvcDsgdXN1YWxseSBpdCBzYXlzIHNvbWV0aGluZyBsaWtlICI+IFRoaXMgUEMgPiBEb2N1bWVudHMgPi4uLi4iIC0gaWYgeW91IGNsaWNrIG9uIHRoaXMgbGluZSwgdGhlIGZ1bGwgZmlsZSBwYXRoIGlzIHNob3duLCBhbmQgeW91IGNhbiBjb3B5IGFuZCBwYXN0ZSBpdCByaWdodCBpbnRvIFINCiNOb3RlLCBob3dldmVyLCB0aGF0IFIgaXMgdmVyeSBwaWNreSBhYm91dCBzbGFzaGVzIGluIHlvdSdyZSB1c2luZyBhIFdpbmRvd3MgbWFjaGluZSAtIHdoaWxlIFdpbmRvd3MgdXNlcyBhIGJhY2tzbGFzaCwgeW91IHdpbGwgbmVlZCB0byBjaGFuZ2UgaXQgdG8gYSBmb3J3YXJkIHNsYXNoIG1hbnVhbGx5IChJJ2xsIHNob3cgeW91IHdoYXQgSSBtZWFuKQ0KDQojQWZ0ZXIgeW91IHNldCB0aGUgd29ya2luZyBkaXJlY3RvcnksIGxldCdzIGxvYWQgaW4gb3VyIGZpcnN0IHBhY2thZ2UhIERwbHlyDQoNCmxpYnJhcnkoZHBseXIpDQoNCiNVc3VhbGx5IGl0J2xsIHNob3cgc29tZSB0ZXh0IGluIHJlZCAtIHRoaXMgaXMgZ2VuZXJhbGx5IG5vdCBhbiBpc3N1ZSwgdW5sZXNzIHlvdSBnZXQgYW4gZXJyb3IgY29kZSB0aGF0IHNheXMgdGhlIHBhY2thZ2Ugd29uJ3QgbG9hZA0KYGBgDQpOb3csIHdlJ2xsIGxvYWQgaW4gb3VyIGZpcnN0IGRhdGEgZnJhbWUsIGFuZCB0aGVuIEkgd2lsbCBzaG93IHlvdSBob3cgdG8gY2xlYW4gaXQgdXAgdXNpbmcgZHBseXIhIFdlJ3JlIGdvaW5nIHRvIHBsYXkgYXJvdW5kIHdpdGggc29tZSBzYW1wbGUgZGF0YS4gVGhlIGRhdGEgaW4gdGhlIGZvbGRlciBpcyBBbWVyaWNhbiBDb21tdW5pdHkgU3VydmV5IGRhdGEgZnJvbSAyMDEwLTEyIHRoYXQgd2FzIGNvbXBpbGVkIGJ5IEZpdmVUaGlydHlFaWdodC4gSXQgaGFzIGEgYnJlYWtkb3duIG9mIHN1cnZleSByZXNwb25kZW50cycgY29sbGVnZSBtYWpvcnMsIHRoZWlyIGdlbmRlciwgYW5kIHRoZSBudW1iZXIgb2YgcmVzcG9uZGVudHMgdGhhdCB3ZXJlIGVtcGxveWVkIGFmdGVyIGdyYWR1YXRpb24uIE5vdGUgdGhhdCB0aGlzIGRhdGEgaXMgc29tZXdoYXQgb3V0ZGF0ZWQgKGUuZy4gbm90IGV2ZXJ5IHN0dWRlbnQgaXMgcmVwcmVzZW50ZWQgYnkgb25seSBpbmNsdWRpbmcgdHdvIGdlbmRlcnMpLCBidXQgaXQgaXMgZ29vZCBleGFtcGxlIGRhdGEgZm9yIHRoZSBleGVyY2lzZXMgdGhhdCBmb2xsb3cuIFdlIHdpbGwgdGFsayBtb3JlIGFib3V0IGRlc2lnbmluZyBpbmNsdXNpdmUgc3VydmV5cyBsYXRlci4gTWFrZSBzdXJlIHlvdSd2ZSBwdXQgdGhlIC5jc3YgZmlsZSBpbiB5b3VyIHdvcmtpbmcgZGlyZWN0b3J5IQ0KDQpTb3VyY2U6IGh0dHBzOi8vZ2l0aHViLmNvbS9maXZldGhpcnR5ZWlnaHQvZGF0YS9ibG9iL21hc3Rlci9jb2xsZWdlLW1ham9ycw0KDQpgYGB7cn0NCiNMZXQncyByZWFkIGluIHRoZSBkYXRhIHVzaW5nIHRoZSByZWFkLmNzdiBjb21tYW5kIC0gdGhpcyBjb21tYW5kIGlzIGhvdyB3ZSB3aWxsIGxvYWQgbW9zdCBkYXRhIGluIHRoZSBjb3Vyc2UNCg0KbWFqb3JzIDwtIHJlYWQuY3N2KCJjb2xsZWdlX21ham9ycy5jc3YiKQ0KDQojSG93IG1hbnkgb2JzZXJ2YXRpb25zIGFyZSBpbiB0aGlzIGRhdGE/IEhvdyBtYW55IHZhcmlhYmxlcz8NCg0KI0xldCdzIGluc3BlY3QgdGhlIGZpcnN0IGZldyByb3dzIG9mIHRoZSBkYXRhIHRvIG1ha2Ugc3VyZSBpdCBsb29rcyByaWdodA0KDQpoZWFkKG1ham9ycykNCmBgYA0KYGBge3J9DQojTGV0J3Mgc3RhcnQgbGVhcm5pbmcgaG93IHRvIHVzZSBkcGx5ciENCiNGaXJzdCB0aGluZ3MgZmlyc3Q6IHRoZSBwaXBlIHN5bWJvbCwgb3IgJT4lIA0KI1RoZSBwaXBlIGlzIGV4dHJlbWVseSB1c2VmdWwgYW5kIGZsZXhpYmxlLCBhbmQgaXQgbWFrZXMgY29kZSB2ZXJ5IGVhc3kgdG8gZm9sbG93IA0KI0Vzc2VudGlhbGx5LCBpdCBhbGxvd3MgdXMgdG8gcGVyZm9ybSBtdWx0aXBsZSBvcGVyYXRpb25zIG9yIGZ1bmN0aW9ucyBpbiBhIGxvZ2ljYWwgb3JkZXINCiNGb3IgZXhhbXBsZSwgSSBjYW4gd3JpdGUgdGhlIGZvbGxvd2luZyBjb2RlIHRvIHJlcGVhdCB0aGUgcHJldmlvdXMgc3RlcDoNCg0KbWFqb3JzICU+JSBoZWFkKCkNCg0KI0hlcmUsIEkgYW0gdGVsbGluZyBSLCAidGFrZSB0aGUgbWFqb3JzIGRhdGFmcmFtZSwgdGhlbiBwcmludCB0aGUgZmlyc3Qgc2l4IGxpbmVzIg0KI1RoZSBwaXBlIGlzIHRoZSAidGhlbiIgaW4gdGhlIHNlbnRlbmNlIC0gaXQgdGVsbHMgUiB3aGF0IHRvIGRvIG5leHQNCmBgYA0KYGBge3J9DQojV2UgY2FuIHByYWN0aWNlIHVzaW5nIGl0IHdpdGggb3RoZXIgc2ltcGxlIGZ1bmN0aW9uczoNCg0KbWFqb3JzICU+JSBzdHIoKQ0KDQojTm93IHdlIGtub3cgdGhlIHR5cGUgb2YgZWFjaCB2YXJpYWJsZSBpbiB0aGUgZGF0YSwgd2hpY2ggaXMgdmVyeSBoYW5keSBpbmZvcm1hdGlvbg0KI09idmlvdXNseSwgd2UgY291bGQgaGF2ZSBqdXN0IHdyaXR0ZW4gc3RyKG1ham9ycykgLSByaWdodCBub3csIHRoaXMgZG9lc24ndCBsb29rIGFsbCB0aGF0IHVzZWZ1bCENCiNMZXQncyBpbnRyb2R1Y2Ugc29tZSBtb3JlIGZ1bmN0aW9ucyBmcm9tIHRoZSBkcGx5ciBwYWNrYWdlLCBhbmQgeW91J2xsIHNlZSB3aHkgdGhlIHBpcGUgaXMgc28gdmVyc2F0aWxlDQpgYGANCmBgYHtyfQ0KI1RoZSBmaXJzdCBkcGx5ciBmdW5jdGlvbiB3ZSB3aWxsIGxlYXJuIGlzIGZpbHRlciENCiNMZXQncyBzYXkgSSB3YW50IHRvIG9ubHkgbG9vayBhdCBlbmdpbmVlcmluZyBtYWpvcnMuIEkgY2FuIHVzZSAiZmlsdGVyIiB0byBzZWxlY3Qgcm93cyBvZiBhIGRhdGFmcmFtZSBiYXNlZCBvbiBhIGxvZ2ljYWwgY29uZGl0aW9uIGxpa2UgdGhpczoNCg0KbWFqb3JzICU+JSBmaWx0ZXIoTWFqb3JfY2F0ZWdvcnkgPT0gIkVuZ2luZWVyaW5nIikgJT4lIGhlYWQoKQ0KYGBgDQpXaGF0IGRpZCBJIGRvIHRoZXJlPyBMZXQncyB0aGluayB0aHJvdWdoIHRoZSBzdGVwcy4gRmlyc3QsIEkgdG9sZCBSIHRvIHVzZSB0aGUgZGF0YWZyYW1lLCBtYWpvcnMuIE5leHQsIEkgdG9sZCBSIHRvIGZpbHRlciB0aGUgZGF0YWZyYW1lIGFuZCBvbmx5IGluY2x1ZGUgcm93cyB3aGVyZSBNYWpvcl9jYXRlZ29yeSBpcyBlcXVhbCB0byBFbmdpbmVlcmluZy4gVGhlbiwgSSB0b2xkIFIgdGhhdCBJIHdhbnRlZCB0byBzZWUgdGhlIGZpcnN0IHNpeCByb3dzIG9mIHRoaXMgZmlsdGVyZWQgZGF0YS4gTm90ZSB0aGF0LCB3aGVuIHVzaW5nIGZpbHRlciwgc3RyaW5ncyBhcmUgY2FzZSBzZW5zaXRpdmUuIElmIEkgaGFkIHR5cGVkICJlbmdpbmVlcmluZyIgdGhlIG5ldyBkYXRhIHdvdWxkIGhhdmUgY29udGFpbmVkIHplcm8gcm93cy4gSW4gYWRkaXRpb24sIG5vdGUgdGhhdCBmaWx0ZXJpbmcgaXMgYSBsb2dpY2FsIG9wZXJhdGlvbiAtIHRoYXQgaXMgd2h5IEkgdXNlZCB0d28gZXF1YWwgc2lnbnMuIFdoZW4gSSB3b3JrIHdpdGggY2hhcmFjdGVycyB1c2luZyAiZmlsdGVyIiwgSSBjYW4gUiB0aGF0IEkgd2FudCB0byBzZWxlY3Qgcm93cyB3aGVyZSBhIHZhcmlhYmxlIGlzIGVxdWFsICg9PSkgb3Igbm90IGVxdWFsICghPSkgdG8gYSBzcGVjaWZpZWQgdmFsdWUuIElmIEkgd2FzIGZpbHRlcmluZyBiYXNlZCBvbiBhIG51bWVyaWMgdmFsdWUsIEkgY2FuIGFsc28gdGVsbCBSIHRvIGZpbHRlciByb3dzIHRoYXQgYXJlIGxlc3MgdGhhbiAoPCkgb3IgZ3JlYXRlciB0aGFuICg+KSBhIHNwZWNpZmllZCB2YWx1ZS4gTGV0J3MgbG9vayBhdCBzb21lIGFkZGl0aW9uYWwgZXhhbXBsZXM6DQoNCmBgYHtyfQ0KI3NlbGVjdCBtYWpvcnMgdGhhdCBoYXZlIG1vcmUgdGhhbiAyLDAwMCBzdHVkZW50czoNCg0KbWFqb3JzICU+JSBmaWx0ZXIoVG90YWwgPiAyMDAwKSAlPiUgaGVhZCgpDQpgYGANCmBgYHtyfQ0KI1doYXQgaWYgSSB3YW50IHRvIGZpbHRlciBieSBtdWx0aXBsZSBjYXRlZ29yaWVzPw0KI0ZpcnN0LCBob3cgZG8gSSBmaW5kIG91dCB3aGF0IGFsbCBvZiB0aGUgY2F0ZWdvcmllcyBhcmUgd2l0aG91dCBzY3JvbGxpbmcgdGhyb3VnaCB0aGUgZW50aXJlIGRhdGFmcmFtZT8gV2UgY2FuIHVzZSB0aGUgYmFzZSBSIGZ1bmN0aW9uICJ1bmlxdWUoKSIgdG8gdmlldyB0aGUgdW5pcXVlIHZhbHVlcyBvZiBhIHZhcmlhYmxlIGxpa2UgdGhpczoNCg0KdW5pcXVlKG1ham9ycyRNYWpvcl9jYXRlZ29yeSkNCg0KI1doYXQgaWYgd2Ugd2FudCB0byBrbm93IHdoaWNoIGNhdGVnb3J5IGlzIHRoZSBsYXJnZXN0PyBXZSBjYW4gdXNlIGFub3RoZXIgYmFzZSBSIGZ1bmN0aW9uLCB0YWJsZSgpLCB0byBsb29rIGF0IHRoaXM6DQoNCnRhYmxlKG1ham9ycyRNYWpvcl9jYXRlZ29yeSkNCg0KI1doaWNoIGlzIHRoZSBsYXJnZXN0Pw0KYGBgDQpgYGB7cn0NCiNXaGF0IGlzIHdlIHdhbnRlZCB0byBmaWx0ZXIgYnkgdGhlIEhlYWx0aCBhbmQgQmlvbG9neSAmIExpZmUgU2NpZW5jZXMgY2F0ZWdvcmllcz8gV2UgY2FuIGRvIHRoYXQgbGlrZSBzbzoNCg0KbWFqb3JzICU+JSBmaWx0ZXIoTWFqb3JfY2F0ZWdvcnkgPT0gYygiSGVhbHRoIiwgIkJpb2xvZ3kgJiBMaWZlIFNjaWVuY2UiKSkgJT4lIGhlYWQoKQ0KYGBgDQpXaGF0IGRpZCB3ZSBhY3R1YWxseSBqdXN0IGRvPyBMZXQncyBicmVhayBpdCBkb3duLiBGaXJzdCwgd2UgdG9sZCBSIHRvIHVzZSB0aGUgbWFqb3JzIGRhdGEuIE5leHQsIHdlIHVzZSBmaWx0ZXIoKSB0byBzZWxlY3Qgcm93cyB0aGF0IGNvbnRhaW4gZWl0aGVyIEhlYWx0aCBvciBCaW9sb2d5ICYgTGlmZSBTY2llbmNlIGluIHRoZSB2YXJpYWJsZSBNYWpvcl9jYXRlZ29yeS4gVGhlbiB3ZSBhc2tlZCBSIHRvIHNob3cgdXMgdGhlIGZpcnN0IHNpeCByb3dzIG9mIHRoZSByZXN1bHQuIFlvdSB1c2UgdGhlIGMoKSB0aGF0IHdlIGxlYXJuZWQgYmVmb3JlIHRvIHRlbGwgUiB0byBmaWx0ZXIgYnkgbXVsdGlwbGUgY2hhcmFjdGVyIHZhbHVlcy4gDQoNCmBgYHtyfQ0KI0JlZm9yZSB3ZSBtb3ZlIG9uLCBpdCdzIGltcG9ydGFudCB0byBub3RlIHRoYXQgd2UgY2FuIHNhdmUgdGhlIGZpbHRlcmVkIGRhdGEgdG8gYSBuZXcgb2JqZWN0ISBUaGlzIGNvbWVzIGluIGhhbmR5IGlmIHdlIHdhbnQgdG8gcGVyZm9ybSBhbnkgYW5hbHlzaXMgb24gYSBzbWFsbGVyIHZlcnNpb24gb2YgdGhlIGRhdGEuIEFuIGV4YW1wbGU6DQoNCmVuZ2luZWVycyA8LSBtYWpvcnMgJT4lIGZpbHRlcihNYWpvcl9jYXRlZ29yeSA9PSAiRW5naW5lZXJpbmciKQ0KDQojTm93IHdlIGhhdmUgYSBuZXcgb2JqZWN0LCBlbmdpbmVlcnMsIHRoYXQgd2UgY2FuIGVhc2lseSB3b3JrIHdpdGgNCmBgYA0KDQpMZXQncyBsb29rIGF0IGFub3RoZXIgZnVuY3Rpb24gZnJvbSBkcGx5ci4gV2hhdCBpZiwgaW5zdGVhZCBvZiByb3dzLCBJIHdhbnQgdG8gc2VsZWN0IHNwZWNpZmljIGNvbHVtbnMgaW4gYSBkYXRhZnJhbWUuIFRoaXMgaXMgYWxzbyB2ZXJ5IHNpbXBsZSBpZiB3ZSB1c2UgdGhlICJzZWxlY3QoKSIgZnVuY3Rpb24uIExldCdzIGxvb2sgYXQgYW4gZXhhbXBsZSwgYW5kIHRoZW4gSSdsbCBleHBsYWluIGl0IGluIGEgYml0IG1vcmUgZGV0YWlsLiANCg0KYGBge3J9DQojV2hhdCBpZiB3ZSBqdXN0IHdhbnQgdG8gbG9vayBhdCBlbnJvbGxtZW50IGluIGVhY2ggbWFqb3I/DQoNCmVucm9sbCA8LSBtYWpvcnMgJT4lIHNlbGVjdChNYWpvciwgVG90YWwpDQoNCiNVc2luZyBzZWxlY3QsIEkganVzdCBuZWVkIHRvIHRlbGwgUiB0aGUgbmFtZXMgb2YgdGhlIGNvbHVtbnMgdGhhdCBJIGFtIGludGVyZXN0ZWQgaW4gc2VsZWN0aW5nLiBJZiB5b3UgbG9vayBhdCBteSBuZXcgZGF0YWZyYW1lLCBlbnJvbGwsIHlvdSdsbCBzZWUgdGhhdCBJIG9ubHkgaGF2ZSB0d28gY29sdW1ucy4gDQoNCiNJZiBJJ20gd29ya2luZyB3aXRoIHRoaXMgZGF0YSwgSSBtaWdodCB3YW50IHRvIGtub3cgd2hpY2ggbWFqb3JzIGhhdmUgdGhlIGxhcmdlc3QgZW5yb2xsbWVudC4gSGVyZSwgd2UnbGwgdXNlIGFub3RoZXIgbmV3IGRwbHlyIGZ1bmN0aW9uLCBhcnJhbmdlKCkgdG8gb3JkZXIgdGhlIGRhdGENCg0KZW5yb2xsIDwtIG1ham9ycyAlPiUgc2VsZWN0KE1ham9yLCBUb3RhbCkgJT4lIGFycmFuZ2UoZGVzYyhUb3RhbCkpDQoNCiNXaGVuIHVzaW5nIGFycmFuZ2UoKSwgaXQncyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0LCBieSBkZWZhdWx0LCB0aGlzIGZ1bmN0aW9uIG9yZGVycyBudW1lcmljIGRhdGEgZnJvbSBzbWFsbGVzdCB0byBsYXJnZXN0IChvciBpbiBhc2NlbmRpbmcgb3JkZXIpLiBJZiB5b3Ugd2lzaCB0byBvcmRlciB5b3VyIGRhdGEgZnJvbSBsYXJnZXN0IHRvIHNtYWxsZXN0IChpbiBkZXNjZW5kaW5nIG9yZGVyKSwgeW91IG11c3QgdGVsbCBSIHRoaXMgYnkgcHV0dGluZyB0aGUgdmFyaWFibGUgdGhhdCB5b3Ugd2lzaCB0byBvcmRlciB0aGUgZGF0YWZyYW1lIGJ5IGluc2lkZSBvZiB0aGUgZnVuY3Rpb24gZGVzYygpLiBJZiB5b3UgY2hlY2sgdGhlIGhlbHAgZG9jdW1lbnRhdGlvbiBmb3IgYXJyYW5nZSgpLCBpdCBzaG93cyBleGFtcGxlcyB1c2luZyBkZXNjKCkgLSBpZiB5b3UgZXZlciBmb3JnZXQsIGp1c3QgY2hlY2sgdGhlIGhlbHAgcGFnZSEgSXQgd2lsbCBvZnRlbiBoYXZlIHRoZSBpbmZvcm1hdGlvbiB5b3UncmUgbG9va2luZyBmb3IuIEknbGwgc2hvdyBtb3JlIGNvbXBsaWNhdGVkIHdheXMgdG8gdXNlIGFycmFuZ2UoKSBsYXRlciBpbiB0aGUgY291cnNlLiANCmBgYA0KDQpMZXQncyB0YWxrIGFib3V0IGFub3RoZXIgaW1wb3J0YW50IGZ1bmN0aW9uIGZyb20gdGhlIGRwbHlyIHBhY2thZ2U6IG11dGF0ZSgpLiBUaGlzIGZ1bmN0aW9uIGFsbG93cyB5b3UgdG8gZWFzaWx5IGNyZWF0ZSBhIG5ldyB2YXJpYWJsZSBpbiBhIGRhdGFmcmFtZS4gSXQgd29ya3MgbGlrZSB0aGlzOiBtdXRhdGUodmFyaWFibGVfbmFtZSA9IHgpLiBYIGNhbiBiZSBhbnkgbnVtYmVyIG9mIHRoaW5ncyAtIG9mdGVuLCB5b3Ugd2lsbCBjcmVhdGUgYSBuZXcgdmFyaWFibGUgYmFzZWQgb24gYSBmb3JtdWxhIG9yIG90aGVyIHZhcmlhYmxlcyBpbiB0aGUgZGF0YWZyYW1lLiBMZXQncyBnbyBiYWNrIHRvIHRoZSBsYXJnZXIgbWFqb3JzIGFuZCBkYXRhZnJhbWUgYW5kIGxvb2sgYXQgc29tZSBleGFtcGxlcyBvZiB0aGlzIGluIHByYWN0aWNlIQ0KDQpgYGB7cn0NCiNUaGUgc2ltcGxlc3QgcG9zc2libGUgdmFyaWFibGUgd291bGQganVzdCBiZSBhIG51bWJlciBvciBhIGxldHRlciBmb3IgZXZlcnkgcm93LiBJIGNhbiBjcmVhdGUgYSB2YXJpYWJsZSBsaWtlIHRoaXMgYXMgZm9sbG93cyAoSSdsbCBzaG93IHlvdSB3aHkgdGhpcyBpcyB1c2VmdWwgaW4gYSBiaXQpOg0KDQptYWpvcnMxIDwtIG1ham9ycyAlPiUgbXV0YXRlKG9uZSA9IDEpDQoNCiNUYWtlIGEgbG9vayBhdCB0aGUgZGF0YWZyYW1lIHRvIHNlZSB3aGF0IHRoaXMgbG9va3MgbGlrZSEgSSd2ZSBzdG9yZWQgdGhpcyBhcyBhIG5ldyBkYXRhZnJhbWUsIG1ham9yczEuIA0KI0FzIEkgc2FpZCBlYXJsaWVyLCBvZnRlbiB5b3Ugd2lsbCB1c2UgYSBmb3JtdWxhIHRvIGNyZWF0ZSBhIG5ldyB2YXJpYWJsZS4gTGV0J3Mgc2F5LCBmb3IgaW5zdGFuY2UsIEkgd2FudCB0byBjcmVhdGUgYSBuZXcgdmFyaWFibGUgdGhhdCBzaG93cyB0aGUgcGVyY2VudGFnZSBvZiBlYWNoIG1ham9yIHRoYXQgYXJlIHdvbWVuLiBJIGNhbiBkbyB0aGlzIHVzaW5nIHR3byBleGlzdGluZyB2YXJpYWJsZXMsIFRvdGFsIGFuZCBXb21lbiwgYXMgZm9sbG93czoNCg0KbWFqb3JzMSA8LSBtYWpvcnMxICU+JSBtdXRhdGUod29tZW5fZnJhYyA9IFdvbWVuL1RvdGFsKQ0KDQojSWYgd2Ugd2FudCB0byBrbm93IHdoaWNoIG1ham9yIGhhcyB0aGUgbGFyZ2VzdCBwZXJjZW50YWdlIG9mIHdvbWVuLCB3ZSBjYW4gYWRkIG9uIGFycmFuZ2UoKSBhdCB0aGUgZW5kIHRvIGZpbmQgb3V0Og0KDQptYWpvcnMxIDwtIG1ham9yczEgJT4lIG11dGF0ZSh3b21lbl9mcmFjID0gV29tZW4vVG90YWwpICU+JSBhcnJhbmdlKGRlc2Mod29tZW5fZnJhYykpDQojV2hpY2ggbWFqb3IgaGFzIHRoZSBsYXJnZXN0IHBlcmNlbnRhZ2Ugb2Ygd29tZW4/DQoNCiNXaGF0IGlmIEkgZG9uJ3Qgd2FudCB0aGVzZSBuZXcgdmFyaWFibGVzIGFueW1vcmU/IEkgY2FuIGVhc2lseSByZW1vdmUgdGhlbSB1c2luZyBzZWxlY3QoKToNCg0KbWFqb3JzMiA8LSBtYWpvcnMxICU+JSBzZWxlY3QoLWMob25lLCB3b21lbl9mcmFjKSkNCg0KI0RlbGV0aW5nIHR3byB2YXJpYWJsZXMgcmVxdWlyZXMgdHdvIHRoaW5nczogYSkgSSBuZWVkIHRvIHVzZSBhICItIiB0byB0ZWxsIFIgdGhhdCBJIGFtIHJlbW92aW5nIHR3byB2YXJpYWJsZXMgcmF0aGVyIHRoYW4gc2VsZWN0aW5nIHRoZW0uIGIpIEkgbmVlZCB0byB0ZWxsIFIgdGhhdCBJIGFtIHJlbW92aW5nIGJvdGgsIHNvIEkgdXNlIGMoKSB0byBjb21tdW5pY2F0ZSB0aGF0IHRvIFIuIFdoYXQgaGFwcGVucyBpZiBJIGRvbid0IGRvIHRoYXQ/IA0KDQptYWpvcnMzIDwtIG1ham9yczEgJT4lIHNlbGVjdCgtb25lLCB3b21lbl9mcmFjKQ0KDQojYWx0ZXJuYXRpdmVseSwgSSBjYW4gcHV0IGEgIi0iIGluIGZyb250IG9mIGVhY2ggdmFyaWFibGUgdG8gYWNjb21wbGlzaCB0aGUgc2FtZSBnb2FsIC0gdXNpbmcgYygpIGJlY29tZXMgdmVyeSBjb252ZW5pZW50LCBob3dldmVyLCBpZiB5b3UgYXJlIHJlbW92aW5nIGEgbGFyZ2UgbnVtYmVyIG9mIHZhcmlhYmxlcyBhdCBvbmNlLiANCg0KbWFqb3JzMSA8LSBtYWpvcnMxICU+JSBzZWxlY3QoLW9uZSwgLXdvbWVuX2ZyYWMpDQpgYGANCg0KSSBoYXZlIHR3byBtb3JlIGRwbHlyIGZ1bmN0aW9ucyB0byBpbnRyb2R1Y2UhIFRoZSB0d28gYXJlIHN1bW1hcmlzZSgpIGFuZCBncm91cF9ieSgpLiBPZnRlbiwgcmF0aGVyIHRoYW4gd29yayB3aXRoIHJhdyBkYXRhLCB3ZSB3aWxsIHdhbnQgdG8ga25vdyBpbmZvcm1hdGlvbiBhYm91dCBncm91cHMgd2l0aGluIG91ciBkYXRhLiBJbiB0aGUgbWFqb3JzIGRhdGEsIHdlIG1pZ2h0IHdhbnQgdG8ga25vdyBtb3JlIGFib3V0IGVhY2ggbWFqb3JfY2F0ZWdvcnksIGZvciBleGFtcGxlLCB0aGUgbnVtYmVyIG9mIHN0dWRlbnRzIGluIGVhY2ggY2F0ZWdvcnkuIFdlIGRvbid0IHdhbnQgdG8gY291bnQgdXAgZWFjaCBvbmUgYnkgaGFuZCwgdGhhdCB3b3VsZCBiZSB2ZXJ5IHRlZGlvdXMhIEluc3RlYWQsIHdlIGNhbiB0ZWxsIFIgdG8gZG8gdGhpcyBmb3IgdXMsIHVzaW5nIHRoZSB0d28gbmV3IGZ1bmN0aW9ucy4gDQpgYGB7cn0NCiNJZiBJIHdhbnQgUiB0byBwZXJmb3JtIGFuIG9wZXJhdGlvbiBvciBmdW5jdGlvbiBieSBncm91cCAoaW4gdGhpcyBjYXNlLCBieSBtYWpvcl9jYXRlZ29yeSksIEkgaGF2ZSB0byB0ZWxsIGl0IHRvIGRvIHNvIHVzaW5nIGdyb3VwX2J5KCkuIFRoaXMgZnVuY3Rpb24gZG9lc24ndCBjaGFuZ2UgdGhlIGRhdGFmcmFtZSBpbiBhbnkgd2F5IC0gaXQganVzdCBpbnN0cnVjdHMgUiB0byB1c2UgdGhlIHNwZWNpZmllZCBncm91cHMgaW4gYW55IHN1YnNlcXVlbnQgb3BlcmF0aW9ucy4gVXNpbmcgaXQgaXMgYXMgc2ltcGxlIGFzOg0KDQptYWpvcnMgJT4lIGdyb3VwX2J5KE1ham9yX2NhdGVnb3J5KQ0KDQojTm93LCBJIHdhbnQgdG8gY3JlYXRlIGEgbmV3IGRhdGFmcmFtZSB3aXRoIHRoZSB0b3RhbCBudW1iZXIgb2Ygc3R1ZGVudHMgaW4gZWFjaCBjYXRlZ29yeS4gV2UgY2FuIGRvIHRoaXMgYnkgc3VtbWluZyB0aGUgdmFyaWFibGUgVG90YWwgd2l0aGluIGVhY2ggZ3JvdXAuIHN1bW1hcmlzZSgpIGFsbG93cyB1cyB0byBkbyBqdXN0IHRoYXQgLSB0aGlzIGZ1bmN0aW9uIGNyZWF0ZXMgYSBuZXcgZGF0YWZyYW1lIGZvciBhIHN1bW1hcnkgc3RhdGlzdGljIG9mIG91ciBjaG9vc2luZy4gQmVjYXVzZSBpdCBpcyBhIHN1bW1hcnkgb2YgdGhlIGRhdGEsIHRoaXMgZnVuY3Rpb24gdHlwaWNhbGx5IGNvbGxhcHNlcyB0aGUgbGFyZ2VyIGRhdGFmcmFtZSBpbnRvIG9uZSB0aGF0IGhhcyBvbmUgdmFsdWUgZm9yIGVhY2ggZ3JvdXAuIEZvciBleGFtcGxlLCBpZiB3ZSB1c2Ugc3VtbWFyaXNlIHRvIGNhbGN1bGF0ZSB0aGUgbWVhbiBvZiB0aGUgdmFyaWFibGUgVG90YWwgKHdpdGhvdXQgZ3JvdXBpbmcgaXQpLCB0aGlzIGlzIHdoYXQgd2UgZ2V0Og0KDQptZWFuX3RvdGFsIDwtIG1ham9ycyAlPiUgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKFRvdGFsLCBuYS5ybT1UKSkNCg0KI0luIHRoaXMgbGluZSBvZiBjb2RlLCB0aGUgd2hvbGUgZGF0YSBmcmFtZSBpcyB0cmVhdGVkIGFzIGEgc2luZ2xlIGdyb3VwLCBzbyB0aGUgb3V0cHV0IG9mIHN1bW1hcmlzZSBpcyBvbmUgdmFsdWUuIExldCdzIHNlZSB3aGF0IGhhcHBlbnMgd2hlbiB3ZSBncm91cCB0aGUgZGF0YSBieSBjYXRlZ29yeS4gSGVyZSwgd2UnbGwgZ2V0IHRoZSB0b3RhbCBudW1iZXIgb2Ygc3R1ZGVudHMgaW4gZWFjaCBjYXRlZ29yeSwgc28gd2UnbGwgdXNlIHRoZSBzdW0oKSBmdW5jdGlvbiBhcyBvdXIgc3VtbWFyeSBzdGF0aXN0aWMuIA0KDQpjYXRfdG90YWwgPC0gbWFqb3JzICU+JSBncm91cF9ieShNYWpvcl9jYXRlZ29yeSkgJT4lIHN1bW1hcmlzZSh0b3RhbF9jYXQgPSBzdW0oVG90YWwpKQ0KDQojbGV0J3MgbG9vayBhdCB0aGlzIG5ldyBkYXRhZnJhbWU6DQpoZWFkKGNhdF90b3RhbCkNCg0KI1VoIG9oLCBvbmUgb2YgdGhlIHZhbHVlcyBpcyBOQSEgUmVjYWxsIHRoYXQsIHdoZW4gd2UgY2FsY3VsYXRlIGFueSBzdW1tYXJ5IHN0YXRpc3RpYywgUiBkb2Vzbid0IGtub3cgd2hhdCB0byBkbyB3aXRoIE5BIHZhbHVlcyAtIHdoZW4gaXQgZW5jb3VudGVycyBhbiBOQSB2YWx1ZSB3aXRoaW4gYSBncm91cCwgaXQgdGhlcmVmb3JlIHJldHVybnMgTkEgYXMgdGhlIGZpbmFsIHZhbHVlLiBXZSBuZWVkIHRvIHRlbGwgaXQgdG8gaWdub3JlIHRoZSBOQSB2YWx1ZXMgdG8gYXZvaWQgdGhpcy4gDQoNCmNhdF90b3RhbCA8LSBtYWpvcnMgJT4lIA0KICBncm91cF9ieShNYWpvcl9jYXRlZ29yeSkgJT4lIA0KICBzdW1tYXJpc2UodG90YWxfY2F0ID0gc3VtKFRvdGFsLCBuYS5ybT1UKSkNCg0KI1RoYXQgc2hvdWxkIHdvcmsgbm93ISBOb3RlIHRoYXQsIHdoZW4gSSB3cml0ZSBsb25nZXIgb3IgbW9yZSBjb21wbGljYXRlZCBjb2RlIHVzaW5nIGRwbHlyLCBJIGxpa2UgdG8gcHV0IGVhY2ggYWRkaXRpb25hbCBmdW5jdGlvbiBvbiBpdHMgb3duIGxpbmUgLSB0aGlzIGp1c3QgbWFrZXMgdGhlIGNvZGUgY2xlYW5lciBhbmQgZWFzaWVyIHRvIGZvbGxvdy4gDQpgYGANCg0KYGBge3J9DQojU28sIHRoaXMgZG9lcyBhIHJlYWxseSBuaWNlIGpvYiBwcm9kdWNpbmcgb25lIHN1bW1hcnkgc3RhdGlzdGljIGZvciB1cyEgQnV0IHdoYXQgaWYgd2Ugd2FudCB0byBjcmVhdGUgYSBkYXRhZnJhbWUgd2l0aCBhIG51bWJlciBvZiBzdW1tYXJ5IHN0YXRpc3RpY3MgYWJvdXQgdGhlIG1ham9yIGNhdGVnb3JpZXM/IFRoaXMgaXMgZWFzeSB0byBkbyB3aXRoIHN1bW1hcmlzZSgpIHRvbyEgSWYgeW91IGxvb2sgdXAgdGhlIGhlbHAgcGFnZSBmb3Igc3VtbWFyaXNlKCksIGl0IGxpc3RzIGEgbnVtYmVyIG9mIHN1Z2dlc3RlZCBzdW1tYXJ5IHN0YXRpc3RpY3MgdGhhdCB5b3UgY2FuIGNhbGN1bGF0ZSB1c2luZyB0aGlzIGZ1bmN0aW9uIC0gaWYgeW91IGFyZSBzdHVjayBhbmQgbmVlZCBpZGVhcywgaXQncyBoZWxwZnVsIHRvIHJldHVybiB0byB0aGUgaGVscCBwYWdlLiBMZXQncyBzYXkgSSB3YW50IHRvIGtub3cgdGhlIHRvdGFsIHN0dWRlbnRzIGluIGVhY2ggY2F0ZWdvcnksIGF2ZXJhZ2UgZW5yb2xsbWVudCBmb3IgZWFjaCBkZXBhcnRtZW50IGluIHRoZSBjYXRlZ29yaWVzLCBhcyB3ZWxsIGFzIHRoZSBsYXJnZXN0IGFuZCBzbWFsbGVzdCBlbnJvbGxtZW50IHZhbHVlcyBmb3IgdGhlIGRlcGFydG1lbnRzIGluIGVhY2ggY2F0ZWdvcnkuIEhlcmUncyBob3cgSSBkbyBpdCwgdXNpbmcgdGhlIHN1bSgpLCBtZWFuKCksIG1pbigpLCBhbmQgbWF4KCkgZnVuY3Rpb25zIHRoYXQgYXJlIGJ1aWx0IGludG8gUjoNCg0Kc3VtbWFyeV9jYXQgPC0gbWFqb3JzICU+JSANCiAgZ3JvdXBfYnkoTWFqb3JfY2F0ZWdvcnkpICU+JSANCiAgc3VtbWFyaXNlKHRvdGFsID0gc3VtKFRvdGFsLCBuYS5ybSA9IFQpLCBhdmcgPSBtZWFuKFRvdGFsLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgIHNtYWxsZXN0ID0gbWluKFRvdGFsLCBuYS5ybSA9IFQpLCBsYXJnZXN0ID0gbWF4KFRvdGFsLCBuYS5ybSA9IFQpKQ0KDQojTm93IHdlIGhhdmUgYSBuaWNlIHN1bW1hcnkgdGFibGUhIExldCdzIGFycmFuZ2UgdGhlIHRhYmxlIGluIGFuIG9yZGVyIHRoYXQgbWFrZXMgc2Vuc2UsIGZvciBleGFtcGxlLCBhbHBoYWJldGljYWxseToNCg0Kc3VtbWFyeV9jYXQgPC0gc3VtbWFyeV9jYXQgJT4lIGFycmFuZ2UoTWFqb3JfY2F0ZWdvcnkpDQpgYGANCg0KVGhhdCdzIGl0IGZvciBXZWVrIDIgLSB3ZSd2ZSBjb3ZlcmVkIGEgbG90IG9mIGdyb3VuZCEgSW4gdGhpcyB3ZWVrJ3MgdHV0b3JpYWwsIHdlJ3ZlIGRpc2N1c3NlZCBtaXNzaW5nIGRhdGEsIGhvdyB0byB3b3JrIHdpdGggZGF0YSBmcmFtZXMgYW5kIGxpc3RzLCBhbmQgdGhlIGJhc2ljcyBvZiB0aGUgZHBseXIgcGFja2FnZS4gVXNpbmcgdGhpcyBwYWNrYWdlLCB5b3Ugd2lsbCBiZSBhYmxlIHRvIGVhc2lseSBjbGVhbiBhbmQgbWFuaXB1bGF0ZSBkYXRhLCBjcmVhdGUgbmV3IHZhcmlhYmxlcywgYW5kIHByb2R1Y2Ugc3VtbWFyeSBzdGF0aXN0aWNzLiBXZSBsZWFybmVkIGFib3V0IHRoZSBwaXBlIG9wZXJhdG9yICggJT4lKSwgYW5kIHNvbWUgb2YgdGhlIG1vc3QgY29tbW9uIGRwbHlyIGZ1bmN0aW9uczogZmlsdGVyKCksIHNlbGVjdCgpLCBtdXRhdGUoKSwgYXJyYW5nZSgpLCBncm91cF9ieSgpLCBhbmQgc3VtbWFyaXNlKCkuIFdlIGFsc28gbGVhcm5lZCBzb21lIG5ldyBiYXNlIFIgZnVuY3Rpb25zIHRoYXQgd2Ugd2lsbCB1c2UgdG8gcHJvZHVjZSBzdW1tYXJ5IHN0YXRpc3RpY3MgYXMgd2UgZ286IG1lYW4sIHN1bSwgbWluLCBhbmQgbWF4LiBXZSB3aWxsIGxlYXJuIG1vcmUgc3VtbWFyeSBzdGF0aXN0aWNzIGFzIHdlIGdvLCBidXQgdGhlc2UgYXJlIGltcG9ydGFudCBiYXNpYyBmdW5jdGlvbnMgdG8gc3RhcnQgd2l0aC4gTmV4dCB3ZWVrLCB3ZSB3aWxsIHVzZSBvdXIgZGF0YSBtYW5pcHVsYXRpb24gc2tpbGxzIHRvIGxlYXJuIGhvdyB0byBwcm9kdWNlIGJhc2ljIHZpc3VhbHMgYW5kIGdyYXBocyB1c2luZyB0aGUgZ2dwbG90MiBwYWNrYWdlLiBUaGUgc2tpbGxzIHdlIGFyZSBsZWFybmluZyBpbiB0aGUgZmlyc3QgdGhyZWUgd2Vla3Mgb2YgdGhpcyBjb3Vyc2UgYXJlIGZvdW5kYXRpb25hbCBSIGNvbmNlcHRzIHRoYXQgd2Ugd2lsbCB1dGlsaXplIHRocm91Z2hvdXQgdGhlIGNvdXJzZSBhbmQgdGhhdCB3aWxsIGhlbHAgeW91IGlmIHlvdSBjaG9vc2UgdG8gZXhwYW5kIHlvdXIgcHJvZ3JhbW1pbmcga25vd2xlZGdlIGluIHRoZSBmdXR1cmUuIA0KDQpSZXNvdXJjZXMNCg0KTmF2YXJybywgRC4gKDIwMTkpLiBMZWFybmluZyBTdGF0aXN0aWNzIHdpdGggUi4gUmV0cmlldmVkIGZyb206DQpodHRwczovL2xlYXJuaW5nc3RhdGlzdGljc3dpdGhyLmNvbS9ib29rL2luZGV4Lmh0bWwuIA0KDQpXaWNraGFtLCBILiwgRnJhbsOnb2lzLCBSLiwgSGVucnksIEwuICYgTcO8bGxlciwgSy4gKDIwMjEpLiBkcGx5cjogQSBncmFtbWFyIG9mIGRhdGEgbWFuaXB1bGF0aW9uLiBSIHBhY2stYWdlIHZlcnNpb24gMS4wLjYuIFJldHJpZXZlZCBmcm9tIGh0dHBzOi8vIENSQU4uUi0gcHJvamUgY3QuIG9yZy8gcGFja2EgZ2U9IGRwbHlyLiANCg0K