Welcome to Week 2 of Geog 380A! 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 management 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

library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union

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 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
#Note that you can hold shift-control-m as a shortcut to insert the pipe symbol
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 ...

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:

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 
majors %>% filter(Major_category == c("Health", "Biology & Life Science")) %>% head()
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))
head(mean_total)
#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)

head(summary_cat)

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.

LS0tDQp0aXRsZTogIkdlb2cgMzgwQSBXZWVrIDIiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpXZWxjb21lIHRvIFdlZWsgMiBvZiBHZW9nIDM4MEEhIFRoaXMgd2Vlaywgd2Ugd2lsbCBsZWFybiBzb21lIGFkZGl0aW9uYWwgY29uY2VwdHMgYW5kIHRvb2xzIGluIFIgdGhhdCB3aWxsIGhlbHAgeW91IHRvIGJldHRlciB3b3JrIHdpdGgsIG1hbmFnZSwgYW5kIGNsZWFuIGRhdGEgZm9yIHN0YXRpc3RpY2FsIGFuYWx5c2lzLiBTb21lIG9mIHRoaXMgdHV0b3JpYWwgd2lsbCBmb2xsb3cgYWxvbmcgd2l0aCB0aGUgY2hhcHRlciBpbiBMZWFybmluZyBTdGF0aXN0aWNzIHdpdGggUjsgaW4gYWRkaXRpb24sIEkgd2lsbCBpbnRyb2R1Y2UgeW91IHRvIHNvbWUgdGVjaG5pcXVlcyB1c2luZyB0aGUgZHBseXIgcGFja2FnZSwgd2hpY2ggY2FtZSBvdXQgYWZ0ZXIgdGhlIGluaXRpYWwgdmVyc2lvbiBvZiBvdXIgdGV4dGJvb2suIE5vdCBvbmx5IGlzIHRoaXMgcGFja2FnZSBleHRyZW1lbHkgdXNlZnVsIGZvciBkYXRhIG1hbmFnZW1lbnQgdGFza3MsIGJ1dCBpdCBpcyBhbHNvIHZlcnkgcG9wdWxhciBpbiB0aGUgUiBjb21tdW5pdHkgYW5kIHdpbGwgYmUgYSB2ZXJ5IHZhbHVhYmxlIHRvb2wgaW4geW91ciBhcnNlbmFsLiBMZXQncyBnZXQgc3RhcnRlZCENCg0KYGBge3J9DQoNCiNMZXQncyBzdGFydCBieSBjb250aW51aW5nIGxhc3Qgd2VlaydzIGRpc2N1c3Npb24gb2YgdmFyaWFibGVzDQojV2hlbiB5b3Ugd29yayB3aXRoIGEgdmFyaWFibGUsIHRoZXJlIGFyZSBzb21lIHNwZWNpYWwgdmFsdWVzIHRoYXQgeW91IG1pZ2h0IHNlZQ0KDQojRm9yIGV4YW1wbGUsIGRvIHlvdSByZW1lbWJlciB3aGF0IHlvdSBnZXQgd2hlbiB5b3UgZGl2aWRlIGFueSBudW1iZXIgYnkgMD8gVHJ5IGl0IQ0KDQoxLzANCg0KI1RoZSBhbnN3ZXIgaXMgaW5maW5pdHksIG9yICJJbmYiDQoNCiNOZXh0LCB3aGF0IGhhcHBlbnMgaWYgSSB0cnkgdG8gcGVyZm9ybSBhbiBvcGVyYXRpb24gdGhhdCByZXN1bHRzIGluIGFuIGludmFsaWQgbnVtYmVyPyBGb3IgZXhhbXBsZToNCg0KMC8wDQoNCiNIZXJlLCB0aGUgcmVzdWx0IGlzICJOYU4iIHdoaWNoIHN0YW5kcyBmb3IgIk5vdCBhIE51bWJlciIuIFRoaXMgbWVhbnMgdGhhdCB0aGVyZSBpcyBubyBtZWFuaW5nZnVsIG51bWVyaWMgYW5zd2VyLCBvciB0aGUgYW5zd2VyIG1heSBiZSB1bmRlZmluZWQuIFRoaXMgaXMgZGlzdGluY3QgZnJvbSB0aGUgbmV4dCB0d28gdmFsdWVzIGJlY2F1c2Ugd2Uga25vdyB3aGF0IHRoZSBhbnN3ZXIgaXMsIGl0IGp1c3QgaXNuJ3QgbWVhbmluZ2Z1bA0KDQojQnkgY29udHJhc3QsICJOQSIgZGVub3RlcyBtaXNzaW5nIGRhdGEgLSB3ZSBkb24ndCBrbm93IHdoYXQncyBzdXBwb3NlZCB0byBiZSBzdG9yZWQgaW4gdGhpcyBlbGVtZW50LiAiTlVMTCIgb24gdGhlIG90aGVyIGhhbmQgaW5kaWNhdGVzIHRoYXQgdGhlcmUgaXMgbm8gdmFsdWUgYXQgYWxsLiANCg0KYGBgDQpgYGB7cn0NCiNJbiBwcmFjdGljZSwgeW91IGFyZSBtb3JlIGxpa2VseSB0byBzZWUgTmFOIG9yIE5BIC0gaXQgaXMgdmVyeSBpbXBvcnRhbnQgdG8gcGF5IGF0dGVudGlvbiB0byB0aGVzZSB2YWx1ZXMuIElmIHRoZXkgcG9wIHVwLCB0aGV5IGNhbiBpbnZhbGlkYXRlIHRoZSByZXN1bHRzIG9mIHlvdXIgYW5hbHlzaXMgb3IgY2F1c2UgUiB0byByZXR1cm4gYW4gaW5jb3JyZWN0IGFuc3dlci4gRm9yIGV4YW1wbGUsIGxldCdzIHNheSB3ZSBoYXZlIHRoaXMgdmVjdG9yIGFuZCB0aGVyZSdzIGFjY2lkZW50YWxseSBhIG1pc3NpbmcgdmFsdWUgaW4gaXQ6DQoNCm9iaiA8LSBjKDEsIDMsIDUsIE5BLCAyLCA3KQ0KDQojV2hhdCBpZiB3ZSB3YW50IHRvIHRha2UgdGhlIHN1bSBvZiB0aGVzZSB2YWx1ZXM/IFdoYXQgZG9lcyBSIGdpdmUgdXM/DQoNCnN1bShvYmopDQoNCiNXZSBnZXQgYW4gTkEhIFRoZXJlIGFyZSBhIG51bWJlciBvZiB3YXlzIHRvIHRyb3VibGVzaG9vdCB0aGlzOyB0aGUgbW9zdCBjb21tb24gd2F5IGlzIHRvIHRlbGwgUiB0byBzaW1wbHkgaWdub3JlIG1pc3NpbmcgdmFsdWVzLCBieSBzZXR0aW5nIG5hLnJtIChzaG9ydCBmb3IgTkEgUmVtb3ZlKSB0byBUUlVFOg0KDQpzdW0ob2JqLCBuYS5ybSA9IFQpDQoNCiNBcyBhIHJlbWluZGVyLCB5b3UgY2FuIGFsd2F5cyBjaGVjayB0aGUgZG9jdW1lbnRhdGlvbiBmb3IgYSBmdW5jdGlvbiB0byBzZWUgd2hhdCBhcmd1bWVudHMgaXQgdGFrZXM7IG1hbnkgZnVuY3Rpb25zIHdpbGwgaW5jbHVkZSBzb21lIHZhcmlhdGlvbiBvZiB0aGUgbmEucm0gYXJndW1lbnQgdG8gYWxsb3cgeW91IHRvIGlnbm9yZSBtaXNzaW5nIHZhbHVlcy4gVGhpcyBtYXkgbm90IGFsd2F5cyBiZSB0aGUgYmVzdCBvcHRpb24sIGJ1dCB3ZSBkb24ndCBuZWVkIHRvIHdvcnJ5IGFib3V0IHRoYXQgcmlnaHQgbm93LiANCmBgYA0KDQpgYGB7cn0NCiNXaGF0IGlmIHdlIHdhbnQgdG8gYWRkIG5hbWVzIHRvIHRoYXQgdmVjdG9yIHRoYXQgd2UganVzdCBjcmVhdGVkPyBXZSBjYW4gZWFzaWx5IGRvIHRoYXQgbGlrZSBzbzoNCg0KbmFtZXMob2JqKSA8LSBjKCJFMSIsICJFMiIsICJFMyIsICJFNCIsICJFNSIsICJFNiIpDQoNCiNIZXJlIEkndmUganVzdCB1c2VkICJFLSIgdG8gZ2VuZXJpY2FsbHkgbmFtZSBlYWNoIGVsZW1lbnQsIGJ1dCB5b3UgY2FuIHVzZSBhbnkgbmFtZSB0aGF0IHlvdSB3YW50DQojaW5zcGVjdCBvdXIgdmVjdG9yDQpvYmoNCg0KI0lmIEkgY2hhbmdlIG15IG1pbmQgYW5kIGRvbid0IHdhbnQgdGhlIG5hbWVzLCBJIGNhbiBhbHdheXMgZG8gdGhlIGZvbGxvd2luZyB0byBkZWxldGUgdGhlbToNCm5hbWVzKG9iaikgPC0gTlVMTA0KDQojV2UgdXNlICJOVUxMIiBpbiB0aGlzIGNhc2UgdG8gdGVsbCBSIHRoYXQgdGhlcmUgaXMgbm8gdmFsdWUgZm9yIHRoZSBuYW1lcyAtIGlmIHdlIHVzZWQgTkEgaW5zdGVhZCwgd2hhdCB3b3VsZCBoYXBwZW4/DQoNCm5hbWVzKG9iaikgPC0gTkENCg0Kb2JqDQoNCiNGaW5hbGx5LCBuYW1lcyBhcmUgdXNlZnVsIGJlY2F1c2Ugd2UgY2FuIGluZGV4IHZlY3RvcnMgdXNpbmcgZWxlbWVudCBuYW1lczoNCg0KbmFtZXMob2JqKSA8LSBjKCJFMSIsICJFMiIsICJFMyIsICJFNCIsICJFNSIsICJFNiIpDQpvYmpbIkUyIl0NCmBgYA0KYGBge3J9DQojTmV4dCwgd2UnbGwgdGFsayBhYm91dCBhIGRhdGEgdHlwZSB0aGF0IGlzIHNwZWNpZmljIHRvIHN0YXRpc3RpY3MuIFNvIGZhciwgd2UndmUgbGVhcm5lZCBhYm91dCBudW1lcmljIGFuZCBjaGFyYWN0ZXIgZGF0YS4gVGhlIG5leHQgZGF0YSB0eXBlIGlzIGEgRmFjdG9yDQojVGhpcyBiZWNvbWVzIGltcG9ydGFudCB3aGVuIHdlIHdhbnQgdG8gZGlzdGluZ3Vpc2ggYmV0d2VlbiBub21pbmFsLCBvcmRpbmFsLCBpbnRlcnZhbCBhbmQgcmF0aW8gc2NhbGUgZGF0YQ0KI051bWVyaWMgZGF0YSBtYWtlcyBhIGxvdCBvZiBzZW5zZSBmb3IgcmF0aW8gZGF0YSwgYW5kIHNvbWUgc2Vuc2UgZm9yIGludGVydmFsIGRhdGEgKGFsdGhvdWdoIG5vdGUgdGhhdCB0aGlzIGRhdGEgZG9lcyBub3QgaGF2ZSBhIG5hdHVyYWwgemVybyB2YWx1ZSwgc28gc29tZSBvcGVyYXRpb25zIHdvdWxkbid0IG1ha2Ugc2Vuc2UgdG8gdXNlKQ0KI1doYXQgYWJvdXQgZGF0YSB0eXBlcyB3aGVyZSBwZXJmb3JtaW5nIG51bWVyaWMgb3BlcmF0aW9ucyBkb24ndCBtYWtlIGEgbG90IG9mIHNlbnNlPyBGb3IgZXhhbXBsZSwgbGV0J3MgdGhpbmsgYWJvdXQgbm9taW5hbCBkYXRhLiBTYXkgSSd2ZSBhc3NpZ25lZCB5b3UgYWxsIHRvIHRocmVlIGdyb3VwczogZ3JvdXBzIDEsIDIsIGFuZCAzLiBXZSBjYW4ndCBzYXkgYW55dGhpbmcgYWJvdXQgdGhlc2UgbnVtYmVycyEgSXQgd291bGRuJ3QgbWFrZSBzZW5zZSB0byBzYXkgdGhhdCBncm91cCAyIGlzIDJ4IGdyb3VwIDEsIG9yIHRoYXQgZ3JvdXAgMyBtaW51cyBncm91cCAyIGVxdWFscyBncm91cCAxLCB3b3VsZCBpdD8gDQoNCiNCdXQsIGlmIEkgc3RvcmUgdGhpcyBhcyBudW1lcmljIGRhdGEsIHdoYXQgaGFwcGVucz8gTGV0J3Mgc2F5IEkgaGF2ZSB0aGlzIGdyb3VwIGRhdGE6DQoNCmdyb3VwIDwtIGMoMSwyLDMsMiwxLDMsMikNCg0KI1JlYWxpc3RpY2FsbHksIEkgc2hvdWxkbid0IGJlIGFibGUgdG8gcGVyZm9ybSBhbnkgb3BlcmF0aW9ucyBvbiB0aGlzIGRhdGEsIGJ1dCBSIHdpbGwgbGV0IG1lOg0KDQpncm91cCozDQpncm91cCsyDQpgYGANCmBgYHtyfQ0KI0luIG9yZGVyIHRvIGVuc3VyZSB0aGF0IG91ciBkYXRhIGlzIHByb3Blcmx5IHN0b3JlZCwgd2UgY2FuIHRyYW5zZm9ybSB0aGlzIGRhdGEgaW50byBhIGRpZmZlcmVudCBkYXRhIHR5cGU6IEZhY3RvciBkYXRhLiANCg0KZ3JvdXAgPC0gYXMuZmFjdG9yKGdyb3VwKQ0KDQojZGlkIGl0IHdvcms/DQoNCmNsYXNzKGdyb3VwKQ0KDQojQ2FuIEkgcGVyZm9ybSBhbnkgY29tcHV0YXRpb25zIG9uIHRoaXMgZGF0YT8NCg0KZ3JvdXArMQ0KDQojTm8hIFRoaXMgaXMgd2hhdCB3ZSB3YW50ZWQgdG8gc2VlLiANCmBgYA0KYGBge3J9DQojV2hhdCBoYXBwZW5zIGlmIHdlIHByaW50IG91dCB0aGlzIGRhdGE/DQoNCmdyb3VwDQoNCiNMZXZlbHMgd2lsbCBvZnRlbiByZWZlciB0byB0aGUgY2F0ZWdvcmllcyBpbiB0aGUgZGF0YSwgd2hpbGUgdGhlIGRhdGEgc3RvcmVzIHRoZSB2YWx1ZXMgaW4gb3VyIHZlY3Rvci4gV2UgY2FuIGFsc28gbWFrZSB0aGUgbGV2ZWxzIG1vcmUgbWVhbmluZ2Z1bCBoZXJlOg0KDQpsZXZlbHMoZ3JvdXApIDwtIGMoImdyb3VwXzEiLCAiZ3JvdXBfMiIsICJncm91cF8zIikNCg0KZ3JvdXANCg0KI0l0J3Mgbm90IG5lY2Vzc2FyaWx5IHByZXR0eSwgYnV0IGl0J3MgbW9yZSBtZWFuaW5nZnVsIHRoYW4gdGhlIHByZXZpb3VzIHZlcnNpb24NCmBgYA0KU28sIHlvdSBoYXZlIG5vdyBzZWVuIG51bWVyaWMsIGNoYXJhY3RlciwgYW5kIGZhY3RvciBkYXRhLCBhbmQgd2UnbGwgdXNlIGZhY3RvcnMgdGhyb3VnaG91dCB0aGUgY291cnNlIHRvIHN0b3JlIG5vbWluYWwgZGF0YS4gWW91IGhhdmUgYWxzbyB3b3JrZWQgd2l0aCBkaWZmZXJlbnQgdHlwZXMgb2Ygb2JqZWN0cywgaW5jbHVkaW5nIHZhbHVlcyBhbmQgdmVjdG9ycy4gTmV4dCwgd2Ugd2lsbCBpbnRyb2R1Y2UgYSB2ZXJ5IGltcG9ydGFudCB0eXBlIG9mIG9iamVjdDogdGhlIGRhdGEgZnJhbWUuIFlvdSBtYXkgYmUgZmFtaWxpYXIgd2l0aCB0aGlzIGRhdGEgdHlwZSBpZiB5b3UgaGF2ZSBldmVyIHdvcmtlZCBpbiBNaWNyb3NvZnQgRXhjZWwgYmVmb3JlIC0gYSBzcHJlYWRzaGVldCBpcyBvbmUgd2F5IHRvIHZpZXcgYSBkYXRhIGZyYW1lLiBBdCBpdHMgc2ltcGxlc3QsIGEgZGF0YSBmcmFtZSBpcyBhIHdheSBvZiBvcmdhbml6aW5nIHZlY3RvcnMgb2YgZGF0YSBpbnRvIGEgdGFibGUuIA0KDQpgYGB7cn0NCiNUbyBzdGFydCBvdXQsIGxldCdzIHNheSB3ZSBoYXZlIHNvbWUgZGF0YSBvbiB0aGUgc3R1ZGVudHMgaW4gdGhpcyBjbGFzcw0KI1dlIGtub3cgZXZlcnlvbmUncyBtYWpvciwgdGhlaXIgaG9tZSBzdGF0ZSwgYW5kIGFnZQ0KDQptYWpvciA8LSBjKCJtYXRoIiwgInNvY2lvbG9neSIsICJwc3ljaG9sb2d5IiwgImdlb2dyYXBoeSIsICJwaHlzaWNzIiwgImVuZ2xpc2giKQ0Kc3RhdGUgPC0gYygiTmV3IFlvcmsiLCAiTmV3IFlvcmsiLCAiUGVubnN5bHZhbmlhIiwgIk5ldyBKZXJzZXkiLCAiTmV3IFlvcmsiLCAiTmV3IFlvcmsiKQ0KYWdlIDwtIGMoMjEsMTgsMTksMjAsMTgsMTkpDQoNCiN3ZSBjYW4gdmlldyBhbmQgd29yayB3aXRoIGVhY2ggdmVjdG9yIGluZGl2aWR1YWxseSwgYnV0IHRoaXMgZG9lc24ndCB0ZWxsIHVzIGhvdyB0aGUgZGlmZmVyZW50IHZhcmlhYmxlcyByZWxhdGUgdG8gZWFjaCBvdGhlciEgQWRkaXRpb25hbGx5LCB3ZSBrbm93IHRoYXQgZWFjaCB2ZWN0b3IgaXMgdGhlIHNhbWUgc2l6ZSwgYW5kIGVhY2ggZWxlbWVudCByZXByZXNlbnRzIHRoZSBzYW1lIHN0dWRlbnQgaW4gZWFjaCB2ZWN0b3IgKGUuZyBlbGVtZW50IDEgaXMgc3R1ZGVudCAxIGluIGVhY2ggdmVjdG9yKQ0KI0luIG9yZGVyIHRvIHZpc3VhbGl6ZSB0aGlzIGRhdGEgaW4gYSBtb3JlIG9yZ2FuaXplZCB3YXksIHdlIGNhbiBwdXQgaXQgaW50byBhIGRhdGEgZnJhbWUhDQoNCnN0dWRlbnRzIDwtIGRhdGEuZnJhbWUoYWdlLCBtYWpvciwgc3RhdGUpDQoNCnN0dWRlbnRzDQpgYGANClRoYXQgaXMgc28gbXVjaCBuaWNlciEgTm90aWNlIG5vdyB0aGF0LCBpbiB0aGUgZW52aXJvbm1lbnQgcGFuZSwgdGhlICJzdHVkZW50cyIgZGF0YSBmcmFtZSBpcyBub3cgbGlzdGVkIHVuZGVyIERhdGEsIHdoaWxlIG91ciB2ZWN0b3JzIGFyZSBsaXN0ZWQgYXMgVmFsdWVzIC0gdGhpcyBpcyBob3cgUiBvcmdhbml6ZXMgdGhpcyBraW5kIG9mIGRhdGEuIFdoZW4gd2UgbWFuaXB1bGF0ZSBkYXRhLCBpdHMgYWxzbyBpbXBvcnRhbnQgdG8gcGF5IGF0dGVudGlvbiB0byBob3cgaXQgaXMgYmVpbmcgY2F0ZWdvcml6ZWQgLSBpZiB5b3UgY29udmVydCBhIGRhdGFmcmFtZSB0byBhIHZlY3RvciBvciBzZXJ2ZXJhbCB2ZWN0b3JzIHRvIGEgZGF0YSBmcmFtZSwgYWx3YXlzIHJlbWVtYmVyIHRvIGNoZWNrIHRoYXQgaXQgaXMgYmVpbmcgc3RvcmVkIGNvcnJlY3RseS4gDQoNCmBgYHtyfQ0KI1doYXQgaWYgd2Ugd2FudCB0byBqdXN0IGluc3BlY3Qgb25lIHZhcmlhYmxlIGluIHRoaXMgZGF0YSBmcmFtZT8gV2UgY2FuIGRvIHRoaXMgdXNpbmcgdGhlICckJyBzaWduIGxpa2UgdGhpczoNCg0Kc3R1ZGVudHMkc3RhdGUNCg0KI1RoaXMgdGVsbHMgUiB0byBwcmludCB0aGUgdmFyaWFibGUgInN0YXRlIiB3aXRoaW4gdGhlIGRhdGEgZnJhbWUgInN0dWRlbnQiDQoNCiNXaGF0IGlmIEkgaGF2ZSBhIHZlcnkgbGFyZ2UgZGF0YSBmcmFtZSwgYW5kIEkgbmVlZCB0byBrbm93IHdoYXQgdGhlIHZhcmlhYmxlIG5hbWVzIGFyZT8gVGhlcmUgYXJlIGEgZmV3IHdheXMgdG8gZG8gdGhpczoNCg0KbmFtZXMoc3R1ZGVudHMpDQoNCmNvbG5hbWVzKHN0dWRlbnRzKQ0KYGBgDQpgYGB7cn0NCiNTb21ldGltZXMsIHlvdSB3aWxsIGZpbmQgdGhhdCB5b3UgaGF2ZSBhIHZlcnkgbGFyZ2UgZGF0YSBmcmFtZSwgYW5kIGl0cyB0aW1lIGNvbnN1bWluZyB0byBwcmludCBvdXQgdGhlIHdob2xlIHRoaW5nLiBZb3UgY2FuIHZpZXcganVzdCBhIGZldyBsaW5lcyB1c2luZyB0aGUgZnVuY3Rpb24gaGVhZCgpDQoNCmhlYWQoc3R1ZGVudHMpDQoNCiNMZXQncyBsb29rIHVuZGVyIHRoZSBob29kIG9mIHRoaXMgZnVuY3Rpb246DQoNCj9oZWFkDQoNCiNIZXJlIHdlIHNlZSB0aGF0IHdlIGNhbiBzZXQgdGhlIG51bWJlciBvZiByb3dzIHRoYXQgYXJlIGRpc3BsYXllZCB1c2luZyB0aGUgbj0gYXJndW1lbnQgbGlrZSB0aGlzOg0KDQpoZWFkKHN0dWRlbnRzLCBuID0gMykNCmBgYA0KYGBge3J9DQojSXQgY2FuIGFsc28gYmUgaGVscGZ1bCB0byBjaGVjayB0aGUgdHlwZSBvZiBkYXRhIHRoYXQgaXMgc3RvcmVkIGluIG91ciBkYXRhIGZyYW1lOg0KI1RyeSB0aGlzIGZpcnN0IC0gd2hhdCB0eXBlIG9mIGRhdGEgaXMgaXQ/DQpzdHIoc3R1ZGVudHMpDQoNCiNUaGUgc3RyKCkgY29tbWFuZCBnaXZlcyB1cyBhIGxvdCBvZiB1c2VmdWwgaW5mb3JtYXRpb24gYWJvdXQgb3VyIGRhdGEgZnJhbWUhIFdlJ2xsIGRpc2N1c3MgZGF0YSBmcmFtZSBpbiBtb3JlIGRldGFpbCBsYXRlcjsgZm9yIG5vdywgaXQncyBqdXN0IGltcG9ydGFudCBmb3IgeW91IHRvIGJlIGZhbWlsaWFyIHdpdGggdGhpcyB0eXBlIG9mIG9iamVjdA0KYGBgDQpGaW5hbGx5LCB3ZSB3aWxsIGludHJvZHVjZSBvbmUgbW9yZSB0eXBlIG9mIG9iamVjdCwgdGhlIGxpc3QuIExpc3RzIHdpbGwgbm90IGJlIHVzZWQgZnJlcXVlbnRseSB0aHJvdWdob3V0IHRoaXMgY291cnNlLCBidXQgdGhleSBhcmUgYSBmdW5kYW1lbnRhbCBkYXRhIHN0cnVjdHVyZSB0byBSIGFuZCBpdHMgaGVscGZ1bCBmb3IgeW91IHRvIGF0IGxlYXN0IGJlIGZhbWlsaWFyIHdpdGggdGhlbSBub3cuIFlvdSB3aWxsIGxpa2VseSB1c2UgbGlzdHMgcXVpdGUgYSBiaXQgbW9yZSBhcyB5b3UgbGVhcm4gbW9yZSBhZHZhbmNlZCBwcm9ncmFtbWluZyAoSSB1c2UgbGlzdHMgY29uc3RhbnRseSBpbiBteSBvd24gcmVzZWFyY2gpLiBJdCBpcyBhbHNvIGhlbHBmdWwgdG8ga25vdyBhYm91dCBsaXN0cyBpbiBjYXNlIHlvdSBldmVyIGFjY2lkZW50YWxseSB0cmFuc2Zvcm0gYSB2ZWN0b3Igb3IgYSBkYXRhIGZyYW1lIGludG8gYSBsaXN0ICh3aGljaCBtYXkgb2NjYXNpb25hbGx5IGhhcHBlbiBpZiB5b3UgdXNlIGEgZnVuY3Rpb24gaW5jb3JyZWN0bHksIGFsdGhvdWdoIGhvcGVmdWxseSB3ZSB3aWxsIGF2b2lkIHRoaXMhKS4gV2hhdCBpcyBhIGxpc3Q/IEEgbGlzdCBpcyBhIGNvbGxlY3Rpb24gb2YgdmFyaWFibGVzIHNpbWlsYXJseSB0byBhIGRhdGEgZnJhbWUuIEEgbGlzdCwgaG93ZXZlciwgaXMgbm90IG5lYXQgYW5kIHN0cnVjdHVyZWQgaW4gdGhlIHNhbWUgd2F5IHRoYXQgYSBkYXRhIGZyYW1lIGlzLiBMZXQncyBsb29rIGF0IGFuIGV4YW1wbGUhDQoNCmBgYHtyfQ0KI0knbGwgY3JlYXRlIGEgbGlzdCBjb250YWluaW5nIHNvbWUgZGF0YSBvbiBhIGh5cG90aGV0aWNhbCBzdHVkZW50Og0Kc3R1ZGVudF9hIDwtIGxpc3QoIGFnZSA9IDIxLA0KICAgICAgICAgICAgICAgICAgIHN0YXRlID0gIk5ldyBZb3JrIiwNCiAgICAgICAgICAgICAgICAgICBtYWpvciA9IGMoIkVjb25vbWljcyIsIk1hdGgiKSANCikNCg0KI2luc3BlY3QgdGhlIGxpc3Q6DQpzdHVkZW50X2ENCg0KI2luIG91ciBkYXRhIGZyYW1lLCBlYWNoIHN0dWRlbnQgY291bGQgb25seSBoYXZlIGV4YWN0bHkgb25lIG1ham9yIC0gaW4gdGhpcyBsaXN0LCB0aGUgZWxlbWVudCAibWFqb3IiIGNhbiBjb250YWluIGFzIG1hbnkgdmFsdWVzIGFzIHdlIHdhbnQhIFdoaWxlIGFsbCBvZiB0aGUgY29sdW1ucyBtdXN0IGJlIHRoZSBzYW1lIGxlbmd0aCBpbiBhbnkgZGF0YSBmcmFtZSwgYSBsaXN0IGlzIGEgbmljZSB3YXkgb2Ygc3RvcmluZyBkYXRhIG9mIGRpZmZlcmVudCBsZW5ndGhzLiBXZSBjYW4gc2VsZWN0IGFuIGVsZW1lbnQgZnJvbSBhIGxpc3Qgc2ltaWxhcmx5IHRvIGEgZGF0YSBmcmFtZToNCg0Kc3R1ZGVudF9hJG1ham9yDQpgYGANCldoZW4gbWlnaHQgeW91IHdhbnQgdG8gdXNlIGEgbGlzdD8gQWdhaW4sIGluIHRoaXMgY2xhc3MsIHdlIGxpa2VseSB3b24ndCB1c2UgdGhlbSB2ZXJ5IG9mdGVuLiBCdXQsIHRoaW5rIGFib3V0IGEgdGltZSB3aGVuIHlvdSBtaWdodCB1c2UgYSBsYXJnZSBhbW91bnQgb2YgZGF0YSBmb3IgYSByZXNlYXJjaCBwcm9ibGVtLiBJZiBJJ20gd29ya2luZyB3aXRoIGEgYnVuY2ggb2YgZGF0YSBmcmFtZXMgYW5kIEkgbmVlZCB0byB1c2UgYSBmdW5jdGlvbiBvbiBlYWNoIG9uZSwgaXQgbWlnaHQgYmUgZWFzaWVyIGZvciBtZSB0byBjcmVhdGUgYSBsaXN0IG9mIGRhdGFmcmFtZXMgYW5kIHJ1biB0aGUgZnVuY3Rpb24gb24gdGhlIGxpc3QgaW5zdGVhZCAtIGxpc3RzIGVuZCB1cCBiZWluZyB2ZXJ5IHVzZWZ1bCBhdCBoZWxwaW5nIHlvdSB0byBzYXZlIHRpbWUuIEJ1dCBubyBuZWVkIHRvIHRoaW5rIG11Y2ggbW9yZSBhYm91dCB0aGF0IG5vdyEgVGhlIHB1cnBvc2Ugb2YgdGhpcyBzZWN0aW9uIHdhcyBqdXN0IHRvIGludHJvZHVjZSB5b3UgdG8gdGhlIGNvbmNlcHQuIA0KDQpJbiB0aGlzIG5leHQgc2VjdGlvbiwgd2UnbGwgaW50cm9kdWNlIGEgdXNlZnVsIG5ldyBSIHBhY2thZ2U6IGRwbHlyISBUaGlzIHBhY2thZ2UgaXMgcGFydCBvZiBhIGxhcmdlciBmYW1pbHkgb2YgcGFja2FnZXMgdGhhdCBhcmUga25vd24gYXMgdGhlIHRpZHl2ZXJzZS4gSSB1c2UgdGhpcyBwYWNrYWdlIGNvbnN0YW50bHkgaW4gbXkgb3duIHdvcms7IGl0J3MgdmVyeSBoZWxwZnVsIGZvciB3b3JraW5nIHdpdGggZGF0YSwgYW5kIGhvcGVmdWxseSB5b3UnbGwgYWdyZWUhDQoNCkJlZm9yZSBJIGludHJvZHVjZSBzb21lIGZ1bmN0aW9ucyBmcm9tIHRoZSBwYWNrYWdlIGxldCdzIGZpcnN0IGEpIGRvd25sb2FkIG91ciBmaXJzdCBwYWNrYWdlIGFuZCBiKSBsb2FkIGluIHNvbWUgZGF0YS4gDQoNClRvIGRvd25sb2FkIGEgcGFja2FnZSwgeW91J2xsIGdvIHRvIHRvb2xzID4gaW5zdGFsbCBwYWNrYWdlcyA+IHRoZW4gdHlwZSBpbiBkcGx5ciBpbiB0aGUgYm94DQoNCmBgYHtyfQ0KI1dlIGhhdmUgdG8gbG9hZCBpbiBwYWNrYWdlcyBldmVyeSB0aW1lIHdlIHN0YXJ0IGEgbmV3IHNlc3Npb24gaW4gUg0KI1doZW4geW91IHN0YXJ0IGEgbmV3IFIgZG9jdW1lbnQsIGl0J3Mgb2Z0ZW4gZWFzaWVzdCB0byBwdXQgYWxsIG9mIHRoZSBwYWNrYWdlcyB5b3UnbGwgYmUgDQojdXNpbmcgYXQgdGhlIHRvcCBvZiB0aGUgZG9jdW1lbnQNCiNCZWZvcmUgd2UgZG8gdGhhdCwgdXN1YWxseSBJIHN0YXJ0IGJ5IHNldHRpbmcgdGhlIHdvcmtpbmcgZGlyZWN0b3J5IGZvciBteSBSIHNlc3Npb24NCiNUaGlzIHRlbGxzIFIgd2hhdCBmb2xkZXIgSSdsbCBiZSB1c2luZyB0byBhY2Nlc3MgYW55IGZpbGVzIG9yIGRhdGEgLSBJIGZyZXF1ZW50bHkgd29yayB3aXRoIGV4Y2VsIGZpbGVzLCBzbyB0aGlzIGlzIHZlcnkgaW1wb3J0YW50IA0KI1dlIHNldCB0aGUgd29ya2luZyBkaXJlY3RvcnkgbGlrZSB0aGlzOg0KDQpzZXR3ZCgiQzovVXNlcnMvbWVsaGEvT25lRHJpdmUvRG9jdW1lbnRzL0JpbmdoYW10b24vZ2VvZzM4MEEiKQ0KDQojSG93IGNhbiBJIGZpbmQgbXkgZmlsZSBwYXRoPyBPbiBhIFdpbmRvd3MgbWFjaGluZSwgZ28gdG8geW91ciBmaWxlIGV4cGxvcmVyDQojSXQnbGwgc2hvdyB0aGUgZmlsZSBwYXRoIGF0IHRoZSB0b3A7IHVzdWFsbHkgaXQgc2F5cyBzb21ldGhpbmcgbGlrZSAiPiBUaGlzIFBDID4gRG9jdW1lbnRzID4uLi4uIiAtIGlmIHlvdSBjbGljayBvbiB0aGlzIGxpbmUsIHRoZSBmdWxsIGZpbGUgcGF0aCBpcyBzaG93biwgYW5kIHlvdSBjYW4gY29weSBhbmQgcGFzdGUgaXQgcmlnaHQgaW50byBSDQojTm90ZSwgaG93ZXZlciwgdGhhdCBSIGlzIHZlcnkgcGlja3kgYWJvdXQgc2xhc2hlcyBpbiB5b3UncmUgdXNpbmcgYSBXaW5kb3dzIG1hY2hpbmUgLSB3aGlsZSBXaW5kb3dzIHVzZXMgYSBiYWNrc2xhc2gsIHlvdSB3aWxsIG5lZWQgdG8gY2hhbmdlIGl0IHRvIGEgZm9yd2FyZCBzbGFzaCBtYW51YWxseSAoSSdsbCBzaG93IHlvdSB3aGF0IEkgbWVhbikNCg0KI0FmdGVyIHlvdSBzZXQgdGhlIHdvcmtpbmcgZGlyZWN0b3J5LCBsZXQncyBsb2FkIGluIG91ciBmaXJzdCBwYWNrYWdlISBEcGx5cg0KDQpsaWJyYXJ5KGRwbHlyKQ0KDQojVXN1YWxseSBpdCdsbCBzaG93IHNvbWUgdGV4dCBpbiByZWQgLSB0aGlzIGlzIGdlbmVyYWxseSBub3QgYW4gaXNzdWUsIHVubGVzcyB5b3UgZ2V0IGFuIGVycm9yIGNvZGUgdGhhdCBzYXlzIHRoZSBwYWNrYWdlIHdvbid0IGxvYWQNCmBgYA0KTm93LCB3ZSdsbCBsb2FkIGluIG91ciBmaXJzdCBkYXRhIGZyYW1lLCBhbmQgdGhlbiBJIHdpbGwgc2hvdyB5b3UgaG93IHRvIGNsZWFuIGl0IHVwIHVzaW5nIGRwbHlyISBXZSdyZSBnb2luZyB0byBwbGF5IGFyb3VuZCB3aXRoIHNvbWUgc2FtcGxlIGRhdGEuIFRoZSBkYXRhIGluIHRoZSBmb2xkZXIgaXMgQW1lcmljYW4gQ29tbXVuaXR5IFN1cnZleSBkYXRhIGZyb20gMjAxMC0xMiB0aGF0IHdhcyBjb21waWxlZCBieSBGaXZlVGhpcnR5RWlnaHQuIEl0IGhhcyBhIGJyZWFrZG93biBvZiBzdXJ2ZXkgcmVzcG9uZGVudHMnIGNvbGxlZ2UgbWFqb3JzLCB0aGVpciBnZW5kZXIsIGFuZCB0aGUgbnVtYmVyIG9mIHJlc3BvbmRlbnRzIHRoYXQgd2VyZSBlbXBsb3llZCBhZnRlciBncmFkdWF0aW9uLiBOb3RlIHRoYXQgdGhpcyBkYXRhIGlzIHNvbWV3aGF0IG91dGRhdGVkIChlLmcuIG5vdCBldmVyeSBzdHVkZW50IGlzIHJlcHJlc2VudGVkIGJ5IG9ubHkgaW5jbHVkaW5nIHR3byBnZW5kZXJzKSwgYnV0IGl0IGlzIGdvb2QgZXhhbXBsZSBkYXRhIGZvciB0aGUgZXhlcmNpc2VzIHRoYXQgZm9sbG93LiBXZSB3aWxsIHRhbGsgbW9yZSBhYm91dCBkZXNpZ25pbmcgaW5jbHVzaXZlIHN1cnZleXMgbGF0ZXIuIE1ha2Ugc3VyZSB5b3UndmUgcHV0IHRoZSAuY3N2IGZpbGUgaW4geW91ciB3b3JraW5nIGRpcmVjdG9yeSENCg0KU291cmNlOiBodHRwczovL2dpdGh1Yi5jb20vZml2ZXRoaXJ0eWVpZ2h0L2RhdGEvYmxvYi9tYXN0ZXIvY29sbGVnZS1tYWpvcnMNCg0KYGBge3J9DQojTGV0J3MgcmVhZCBpbiB0aGUgZGF0YSB1c2luZyB0aGUgcmVhZC5jc3YgY29tbWFuZCAtIHRoaXMgY29tbWFuZCBpcyBob3cgd2Ugd2lsbCBsb2FkIG1vc3QgZGF0YSBpbiB0aGUgY291cnNlDQpzZXR3ZCgiQzovVXNlcnMvbWVsaGEvT25lRHJpdmUvRG9jdW1lbnRzL0JpbmdoYW10b24vZ2VvZzM4MEEiKQ0KbWFqb3JzIDwtIHJlYWQuY3N2KCJjb2xsZWdlX21ham9ycy5jc3YiKQ0KDQojSG93IG1hbnkgb2JzZXJ2YXRpb25zIGFyZSBpbiB0aGlzIGRhdGE/IEhvdyBtYW55IHZhcmlhYmxlcz8NCg0KI0xldCdzIGluc3BlY3QgdGhlIGZpcnN0IGZldyByb3dzIG9mIHRoZSBkYXRhIHRvIG1ha2Ugc3VyZSBpdCBsb29rcyByaWdodA0KDQpoZWFkKG1ham9ycykNCmBgYA0KYGBge3J9DQojTGV0J3Mgc3RhcnQgbGVhcm5pbmcgaG93IHRvIHVzZSBkcGx5ciENCiNGaXJzdCB0aGluZ3MgZmlyc3Q6IHRoZSBwaXBlIHN5bWJvbCwgb3IgJT4lIA0KI1RoZSBwaXBlIGlzIGV4dHJlbWVseSB1c2VmdWwgYW5kIGZsZXhpYmxlLCBhbmQgaXQgbWFrZXMgY29kZSB2ZXJ5IGVhc3kgdG8gZm9sbG93IA0KI0Vzc2VudGlhbGx5LCBpdCBhbGxvd3MgdXMgdG8gcGVyZm9ybSBtdWx0aXBsZSBvcGVyYXRpb25zIG9yIGZ1bmN0aW9ucyBpbiBhIGxvZ2ljYWwgb3JkZXINCiNGb3IgZXhhbXBsZSwgSSBjYW4gd3JpdGUgdGhlIGZvbGxvd2luZyBjb2RlIHRvIHJlcGVhdCB0aGUgcHJldmlvdXMgc3RlcDoNCg0KbWFqb3JzICU+JSBoZWFkKCkNCg0KI0hlcmUsIEkgYW0gdGVsbGluZyBSLCAidGFrZSB0aGUgbWFqb3JzIGRhdGFmcmFtZSwgdGhlbiBwcmludCB0aGUgZmlyc3Qgc2l4IGxpbmVzIg0KI1RoZSBwaXBlIGlzIHRoZSAidGhlbiIgaW4gdGhlIHNlbnRlbmNlIC0gaXQgdGVsbHMgUiB3aGF0IHRvIGRvIG5leHQNCiNOb3RlIHRoYXQgeW91IGNhbiBob2xkIHNoaWZ0LWNvbnRyb2wtbSBhcyBhIHNob3J0Y3V0IHRvIGluc2VydCB0aGUgcGlwZSBzeW1ib2wNCmBgYA0KYGBge3J9DQojV2UgY2FuIHByYWN0aWNlIHVzaW5nIGl0IHdpdGggb3RoZXIgc2ltcGxlIGZ1bmN0aW9uczoNCg0KbWFqb3JzICU+JSBzdHIoKQ0KDQojTm93IHdlIGtub3cgdGhlIHR5cGUgb2YgZWFjaCB2YXJpYWJsZSBpbiB0aGUgZGF0YSwgd2hpY2ggaXMgdmVyeSBoYW5keSBpbmZvcm1hdGlvbg0KI09idmlvdXNseSwgd2UgY291bGQgaGF2ZSBqdXN0IHdyaXR0ZW4gc3RyKG1ham9ycykgLSByaWdodCBub3csIHRoaXMgZG9lc24ndCBsb29rIGFsbCB0aGF0IHVzZWZ1bCENCiNMZXQncyBpbnRyb2R1Y2Ugc29tZSBtb3JlIGZ1bmN0aW9ucyBmcm9tIHRoZSBkcGx5ciBwYWNrYWdlLCBhbmQgeW91J2xsIHNlZSB3aHkgdGhlIHBpcGUgaXMgc28gdmVyc2F0aWxlDQpgYGANCmBgYHtyfQ0KI1RoZSBmaXJzdCBkcGx5ciBmdW5jdGlvbiB3ZSB3aWxsIGxlYXJuIGlzIGZpbHRlciENCiNMZXQncyBzYXkgSSB3YW50IHRvIG9ubHkgbG9vayBhdCBlbmdpbmVlcmluZyBtYWpvcnMuIEkgY2FuIHVzZSAiZmlsdGVyIiB0byBzZWxlY3Qgcm93cyBvZiBhIGRhdGFmcmFtZSBiYXNlZCBvbiBhIGxvZ2ljYWwgY29uZGl0aW9uIGxpa2UgdGhpczoNCg0KbWFqb3JzICU+JSBmaWx0ZXIoTWFqb3JfY2F0ZWdvcnkgPT0gIkVuZ2luZWVyaW5nIikgJT4lIGhlYWQoKQ0KYGBgDQpXaGF0IGRpZCBJIGRvIHRoZXJlPyBMZXQncyB0aGluayB0aHJvdWdoIHRoZSBzdGVwcy4gRmlyc3QsIEkgdG9sZCBSIHRvIHVzZSB0aGUgZGF0YWZyYW1lLCBtYWpvcnMuIE5leHQsIEkgdG9sZCBSIHRvIGZpbHRlciB0aGUgZGF0YWZyYW1lIGFuZCBvbmx5IGluY2x1ZGUgcm93cyB3aGVyZSBNYWpvcl9jYXRlZ29yeSBpcyBlcXVhbCB0byBFbmdpbmVlcmluZy4gVGhlbiwgSSB0b2xkIFIgdGhhdCBJIHdhbnRlZCB0byBzZWUgdGhlIGZpcnN0IHNpeCByb3dzIG9mIHRoaXMgZmlsdGVyZWQgZGF0YS4gTm90ZSB0aGF0LCB3aGVuIHVzaW5nIGZpbHRlciwgc3RyaW5ncyBhcmUgY2FzZSBzZW5zaXRpdmUuIElmIEkgaGFkIHR5cGVkICJlbmdpbmVlcmluZyIgdGhlIG5ldyBkYXRhIHdvdWxkIGhhdmUgY29udGFpbmVkIHplcm8gcm93cy4gSW4gYWRkaXRpb24sIG5vdGUgdGhhdCBmaWx0ZXJpbmcgaXMgYSBsb2dpY2FsIG9wZXJhdGlvbiAtIHRoYXQgaXMgd2h5IEkgdXNlZCB0d28gZXF1YWwgc2lnbnMuIFdoZW4gSSB3b3JrIHdpdGggY2hhcmFjdGVycyB1c2luZyAiZmlsdGVyIiwgSSBjYW4gUiB0aGF0IEkgd2FudCB0byBzZWxlY3Qgcm93cyB3aGVyZSBhIHZhcmlhYmxlIGlzIGVxdWFsICg9PSkgb3Igbm90IGVxdWFsICghPSkgdG8gYSBzcGVjaWZpZWQgdmFsdWUuIElmIEkgd2FzIGZpbHRlcmluZyBiYXNlZCBvbiBhIG51bWVyaWMgdmFsdWUsIEkgY2FuIGFsc28gdGVsbCBSIHRvIGZpbHRlciByb3dzIHRoYXQgYXJlIGxlc3MgdGhhbiAoPCkgb3IgZ3JlYXRlciB0aGFuICg+KSBhIHNwZWNpZmllZCB2YWx1ZS4gTGV0J3MgbG9vayBhdCBzb21lIGFkZGl0aW9uYWwgZXhhbXBsZXM6DQoNCmBgYHtyfQ0KI3NlbGVjdCBtYWpvcnMgdGhhdCBoYXZlIG1vcmUgdGhhbiAyLDAwMCBzdHVkZW50czoNCg0KbWFqb3JzICU+JSBmaWx0ZXIoVG90YWwgPiAyMDAwKSAlPiUgaGVhZCgpDQpgYGANCmBgYHtyfQ0KI1doYXQgaWYgSSB3YW50IHRvIGZpbHRlciBieSBtdWx0aXBsZSBjYXRlZ29yaWVzPw0KI0ZpcnN0LCBob3cgZG8gSSBmaW5kIG91dCB3aGF0IGFsbCBvZiB0aGUgY2F0ZWdvcmllcyBhcmUgd2l0aG91dCBzY3JvbGxpbmcgdGhyb3VnaCB0aGUgZW50aXJlIGRhdGFmcmFtZT8gV2UgY2FuIHVzZSB0aGUgYmFzZSBSIGZ1bmN0aW9uICJ1bmlxdWUoKSIgdG8gdmlldyB0aGUgdW5pcXVlIHZhbHVlcyBvZiBhIHZhcmlhYmxlIGxpa2UgdGhpczoNCg0KdW5pcXVlKG1ham9ycyRNYWpvcl9jYXRlZ29yeSkNCg0KI1doYXQgaWYgd2Ugd2FudCB0byBrbm93IHdoaWNoIGNhdGVnb3J5IGlzIHRoZSBsYXJnZXN0PyBXZSBjYW4gdXNlIGFub3RoZXIgYmFzZSBSIGZ1bmN0aW9uLCB0YWJsZSgpLCB0byBsb29rIGF0IHRoaXM6DQoNCnRhYmxlKG1ham9ycyRNYWpvcl9jYXRlZ29yeSkNCg0KI1doaWNoIGlzIHRoZSBsYXJnZXN0Pw0KYGBgDQpgYGB7cn0NCiNXaGF0IGlzIHdlIHdhbnRlZCB0byBmaWx0ZXIgYnkgdGhlIEhlYWx0aCBhbmQgQmlvbG9neSAmIExpZmUgU2NpZW5jZXMgY2F0ZWdvcmllcz8gV2UgY2FuIGRvIHRoYXQgbGlrZSBzbzoNCg0KbWFqb3JzICU+JSBmaWx0ZXIoTWFqb3JfY2F0ZWdvcnkgPT0gYygiSGVhbHRoIiwgIkJpb2xvZ3kgJiBMaWZlIFNjaWVuY2UiKSkgJT4lIGhlYWQoKQ0KYGBgDQpXaGF0IGRpZCB3ZSBhY3R1YWxseSBqdXN0IGRvPyBMZXQncyBicmVhayBpdCBkb3duLiBGaXJzdCwgd2UgdG9sZCBSIHRvIHVzZSB0aGUgbWFqb3JzIGRhdGEuIE5leHQsIHdlIHVzZSBmaWx0ZXIoKSB0byBzZWxlY3Qgcm93cyB0aGF0IGNvbnRhaW4gZWl0aGVyIEhlYWx0aCBvciBCaW9sb2d5ICYgTGlmZSBTY2llbmNlIGluIHRoZSB2YXJpYWJsZSBNYWpvcl9jYXRlZ29yeS4gVGhlbiB3ZSBhc2tlZCBSIHRvIHNob3cgdXMgdGhlIGZpcnN0IHNpeCByb3dzIG9mIHRoZSByZXN1bHQuIFlvdSB1c2UgdGhlIGMoKSB0aGF0IHdlIGxlYXJuZWQgYmVmb3JlIHRvIHRlbGwgUiB0byBmaWx0ZXIgYnkgbXVsdGlwbGUgY2hhcmFjdGVyIHZhbHVlcy4gDQoNCmBgYHtyfQ0KI0JlZm9yZSB3ZSBtb3ZlIG9uLCBpdCdzIGltcG9ydGFudCB0byBub3RlIHRoYXQgd2UgY2FuIHNhdmUgdGhlIGZpbHRlcmVkIGRhdGEgdG8gYSBuZXcgb2JqZWN0ISBUaGlzIGNvbWVzIGluIGhhbmR5IGlmIHdlIHdhbnQgdG8gcGVyZm9ybSBhbnkgYW5hbHlzaXMgb24gYSBzbWFsbGVyIHZlcnNpb24gb2YgdGhlIGRhdGEuIEFuIGV4YW1wbGU6DQoNCmVuZ2luZWVycyA8LSBtYWpvcnMgJT4lIGZpbHRlcihNYWpvcl9jYXRlZ29yeSA9PSAiRW5naW5lZXJpbmciKQ0KDQojTm93IHdlIGhhdmUgYSBuZXcgb2JqZWN0LCBlbmdpbmVlcnMsIHRoYXQgd2UgY2FuIGVhc2lseSB3b3JrIHdpdGgNCmBgYA0KDQpMZXQncyBsb29rIGF0IGFub3RoZXIgZnVuY3Rpb24gZnJvbSBkcGx5ci4gV2hhdCBpZiwgaW5zdGVhZCBvZiByb3dzLCBJIHdhbnQgdG8gc2VsZWN0IHNwZWNpZmljIGNvbHVtbnMgaW4gYSBkYXRhZnJhbWUuIFRoaXMgaXMgYWxzbyB2ZXJ5IHNpbXBsZSBpZiB3ZSB1c2UgdGhlICJzZWxlY3QoKSIgZnVuY3Rpb24uIExldCdzIGxvb2sgYXQgYW4gZXhhbXBsZSwgYW5kIHRoZW4gSSdsbCBleHBsYWluIGl0IGluIGEgYml0IG1vcmUgZGV0YWlsLiANCg0KYGBge3J9DQojV2hhdCBpZiB3ZSBqdXN0IHdhbnQgdG8gbG9vayBhdCBlbnJvbGxtZW50IGluIGVhY2ggbWFqb3I/DQoNCmVucm9sbCA8LSBtYWpvcnMgJT4lIHNlbGVjdChNYWpvciwgVG90YWwpDQoNCiNVc2luZyBzZWxlY3QsIEkganVzdCBuZWVkIHRvIHRlbGwgUiB0aGUgbmFtZXMgb2YgdGhlIGNvbHVtbnMgdGhhdCBJIGFtIGludGVyZXN0ZWQgaW4gc2VsZWN0aW5nLiBJZiB5b3UgbG9vayBhdCBteSBuZXcgZGF0YWZyYW1lLCBlbnJvbGwsIHlvdSdsbCBzZWUgdGhhdCBJIG9ubHkgaGF2ZSB0d28gY29sdW1ucy4gDQoNCiNJZiBJJ20gd29ya2luZyB3aXRoIHRoaXMgZGF0YSwgSSBtaWdodCB3YW50IHRvIGtub3cgd2hpY2ggbWFqb3JzIGhhdmUgdGhlIGxhcmdlc3QgZW5yb2xsbWVudC4gSGVyZSwgd2UnbGwgdXNlIGFub3RoZXIgbmV3IGRwbHlyIGZ1bmN0aW9uLCBhcnJhbmdlKCkgdG8gb3JkZXIgdGhlIGRhdGENCg0KZW5yb2xsIDwtIG1ham9ycyAlPiUgc2VsZWN0KE1ham9yLCBUb3RhbCkgJT4lIGFycmFuZ2UoZGVzYyhUb3RhbCkpDQoNCiNXaGVuIHVzaW5nIGFycmFuZ2UoKSwgaXQncyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0LCBieSBkZWZhdWx0LCB0aGlzIGZ1bmN0aW9uIG9yZGVycyBudW1lcmljIGRhdGEgZnJvbSBzbWFsbGVzdCB0byBsYXJnZXN0IChvciBpbiBhc2NlbmRpbmcgb3JkZXIpLiBJZiB5b3Ugd2lzaCB0byBvcmRlciB5b3VyIGRhdGEgZnJvbSBsYXJnZXN0IHRvIHNtYWxsZXN0IChpbiBkZXNjZW5kaW5nIG9yZGVyKSwgeW91IG11c3QgdGVsbCBSIHRoaXMgYnkgcHV0dGluZyB0aGUgdmFyaWFibGUgdGhhdCB5b3Ugd2lzaCB0byBvcmRlciB0aGUgZGF0YWZyYW1lIGJ5IGluc2lkZSBvZiB0aGUgZnVuY3Rpb24gZGVzYygpLiBJZiB5b3UgY2hlY2sgdGhlIGhlbHAgZG9jdW1lbnRhdGlvbiBmb3IgYXJyYW5nZSgpLCBpdCBzaG93cyBleGFtcGxlcyB1c2luZyBkZXNjKCkgLSBpZiB5b3UgZXZlciBmb3JnZXQsIGp1c3QgY2hlY2sgdGhlIGhlbHAgcGFnZSEgSXQgd2lsbCBvZnRlbiBoYXZlIHRoZSBpbmZvcm1hdGlvbiB5b3UncmUgbG9va2luZyBmb3IuIEknbGwgc2hvdyBtb3JlIGNvbXBsaWNhdGVkIHdheXMgdG8gdXNlIGFycmFuZ2UoKSBsYXRlciBpbiB0aGUgY291cnNlLiANCmBgYA0KDQpMZXQncyB0YWxrIGFib3V0IGFub3RoZXIgaW1wb3J0YW50IGZ1bmN0aW9uIGZyb20gdGhlIGRwbHlyIHBhY2thZ2U6IG11dGF0ZSgpLiBUaGlzIGZ1bmN0aW9uIGFsbG93cyB5b3UgdG8gZWFzaWx5IGNyZWF0ZSBhIG5ldyB2YXJpYWJsZSBpbiBhIGRhdGFmcmFtZS4gSXQgd29ya3MgbGlrZSB0aGlzOiBtdXRhdGUodmFyaWFibGVfbmFtZSA9IHgpLiBYIGNhbiBiZSBhbnkgbnVtYmVyIG9mIHRoaW5ncyAtIG9mdGVuLCB5b3Ugd2lsbCBjcmVhdGUgYSBuZXcgdmFyaWFibGUgYmFzZWQgb24gYSBmb3JtdWxhIG9yIG90aGVyIHZhcmlhYmxlcyBpbiB0aGUgZGF0YWZyYW1lLiBMZXQncyBnbyBiYWNrIHRvIHRoZSBsYXJnZXIgbWFqb3JzIGFuZCBkYXRhZnJhbWUgYW5kIGxvb2sgYXQgc29tZSBleGFtcGxlcyBvZiB0aGlzIGluIHByYWN0aWNlIQ0KDQpgYGB7cn0NCiNUaGUgc2ltcGxlc3QgcG9zc2libGUgdmFyaWFibGUgd291bGQganVzdCBiZSBhIG51bWJlciBvciBhIGxldHRlciBmb3IgZXZlcnkgcm93LiBJIGNhbiBjcmVhdGUgYSB2YXJpYWJsZSBsaWtlIHRoaXMgYXMgZm9sbG93cyAoSSdsbCBzaG93IHlvdSB3aHkgdGhpcyBpcyB1c2VmdWwgaW4gYSBiaXQpOg0KDQptYWpvcnMxIDwtIG1ham9ycyAlPiUgbXV0YXRlKG9uZSA9IDEpDQoNCiNUYWtlIGEgbG9vayBhdCB0aGUgZGF0YWZyYW1lIHRvIHNlZSB3aGF0IHRoaXMgbG9va3MgbGlrZSEgSSd2ZSBzdG9yZWQgdGhpcyBhcyBhIG5ldyBkYXRhZnJhbWUsIG1ham9yczEuIA0KI0FzIEkgc2FpZCBlYXJsaWVyLCBvZnRlbiB5b3Ugd2lsbCB1c2UgYSBmb3JtdWxhIHRvIGNyZWF0ZSBhIG5ldyB2YXJpYWJsZS4gTGV0J3Mgc2F5LCBmb3IgaW5zdGFuY2UsIEkgd2FudCB0byBjcmVhdGUgYSBuZXcgdmFyaWFibGUgdGhhdCBzaG93cyB0aGUgcGVyY2VudGFnZSBvZiBlYWNoIG1ham9yIHRoYXQgYXJlIHdvbWVuLiBJIGNhbiBkbyB0aGlzIHVzaW5nIHR3byBleGlzdGluZyB2YXJpYWJsZXMsIFRvdGFsIGFuZCBXb21lbiwgYXMgZm9sbG93czoNCg0KbWFqb3JzMSA8LSBtYWpvcnMxICU+JSBtdXRhdGUod29tZW5fZnJhYyA9IFdvbWVuL1RvdGFsKQ0KDQojSWYgd2Ugd2FudCB0byBrbm93IHdoaWNoIG1ham9yIGhhcyB0aGUgbGFyZ2VzdCBwZXJjZW50YWdlIG9mIHdvbWVuLCB3ZSBjYW4gYWRkIG9uIGFycmFuZ2UoKSBhdCB0aGUgZW5kIHRvIGZpbmQgb3V0Og0KDQptYWpvcnMxIDwtIG1ham9yczEgJT4lIG11dGF0ZSh3b21lbl9mcmFjID0gV29tZW4vVG90YWwpICU+JSBhcnJhbmdlKGRlc2Mod29tZW5fZnJhYykpDQojV2hpY2ggbWFqb3IgaGFzIHRoZSBsYXJnZXN0IHBlcmNlbnRhZ2Ugb2Ygd29tZW4/DQoNCiNXaGF0IGlmIEkgZG9uJ3Qgd2FudCB0aGVzZSBuZXcgdmFyaWFibGVzIGFueW1vcmU/IEkgY2FuIGVhc2lseSByZW1vdmUgdGhlbSB1c2luZyBzZWxlY3QoKToNCg0KbWFqb3JzMiA8LSBtYWpvcnMxICU+JSBzZWxlY3QoLWMob25lLCB3b21lbl9mcmFjKSkNCg0KI0RlbGV0aW5nIHR3byB2YXJpYWJsZXMgcmVxdWlyZXMgdHdvIHRoaW5nczogYSkgSSBuZWVkIHRvIHVzZSBhICItIiB0byB0ZWxsIFIgdGhhdCBJIGFtIHJlbW92aW5nIHR3byB2YXJpYWJsZXMgcmF0aGVyIHRoYW4gc2VsZWN0aW5nIHRoZW0uIGIpIEkgbmVlZCB0byB0ZWxsIFIgdGhhdCBJIGFtIHJlbW92aW5nIGJvdGgsIHNvIEkgdXNlIGMoKSB0byBjb21tdW5pY2F0ZSB0aGF0IHRvIFIuIFdoYXQgaGFwcGVucyBpZiBJIGRvbid0IGRvIHRoYXQ/IA0KDQptYWpvcnMzIDwtIG1ham9yczEgJT4lIHNlbGVjdCgtb25lLCB3b21lbl9mcmFjKQ0KDQojYWx0ZXJuYXRpdmVseSwgSSBjYW4gcHV0IGEgIi0iIGluIGZyb250IG9mIGVhY2ggdmFyaWFibGUgdG8gYWNjb21wbGlzaCB0aGUgc2FtZSBnb2FsIC0gdXNpbmcgYygpIGJlY29tZXMgdmVyeSBjb252ZW5pZW50LCBob3dldmVyLCBpZiB5b3UgYXJlIHJlbW92aW5nIGEgbGFyZ2UgbnVtYmVyIG9mIHZhcmlhYmxlcyBhdCBvbmNlLiANCg0KbWFqb3JzMSA8LSBtYWpvcnMxICU+JSBzZWxlY3QoLW9uZSwgLXdvbWVuX2ZyYWMpDQpgYGANCg0KSSBoYXZlIHR3byBtb3JlIGRwbHlyIGZ1bmN0aW9ucyB0byBpbnRyb2R1Y2UhIFRoZSB0d28gYXJlIHN1bW1hcmlzZSgpIGFuZCBncm91cF9ieSgpLiBPZnRlbiwgcmF0aGVyIHRoYW4gd29yayB3aXRoIHJhdyBkYXRhLCB3ZSB3aWxsIHdhbnQgdG8ga25vdyBpbmZvcm1hdGlvbiBhYm91dCBncm91cHMgd2l0aGluIG91ciBkYXRhLiBJbiB0aGUgbWFqb3JzIGRhdGEsIHdlIG1pZ2h0IHdhbnQgdG8ga25vdyBtb3JlIGFib3V0IGVhY2ggbWFqb3JfY2F0ZWdvcnksIGZvciBleGFtcGxlLCB0aGUgbnVtYmVyIG9mIHN0dWRlbnRzIGluIGVhY2ggY2F0ZWdvcnkuIFdlIGRvbid0IHdhbnQgdG8gY291bnQgdXAgZWFjaCBvbmUgYnkgaGFuZCwgdGhhdCB3b3VsZCBiZSB2ZXJ5IHRlZGlvdXMhIEluc3RlYWQsIHdlIGNhbiB0ZWxsIFIgdG8gZG8gdGhpcyBmb3IgdXMsIHVzaW5nIHRoZSB0d28gbmV3IGZ1bmN0aW9ucy4gDQpgYGB7cn0NCiNJZiBJIHdhbnQgUiB0byBwZXJmb3JtIGFuIG9wZXJhdGlvbiBvciBmdW5jdGlvbiBieSBncm91cCAoaW4gdGhpcyBjYXNlLCBieSBtYWpvcl9jYXRlZ29yeSksIEkgaGF2ZSB0byB0ZWxsIGl0IHRvIGRvIHNvIHVzaW5nIGdyb3VwX2J5KCkuIFRoaXMgZnVuY3Rpb24gZG9lc24ndCBjaGFuZ2UgdGhlIGRhdGFmcmFtZSBpbiBhbnkgd2F5IC0gaXQganVzdCBpbnN0cnVjdHMgUiB0byB1c2UgdGhlIHNwZWNpZmllZCBncm91cHMgaW4gYW55IHN1YnNlcXVlbnQgb3BlcmF0aW9ucy4gVXNpbmcgaXQgaXMgYXMgc2ltcGxlIGFzOg0KDQptYWpvcnMgJT4lIGdyb3VwX2J5KE1ham9yX2NhdGVnb3J5KQ0KDQojTm93LCBJIHdhbnQgdG8gY3JlYXRlIGEgbmV3IGRhdGFmcmFtZSB3aXRoIHRoZSB0b3RhbCBudW1iZXIgb2Ygc3R1ZGVudHMgaW4gZWFjaCBjYXRlZ29yeS4gV2UgY2FuIGRvIHRoaXMgYnkgc3VtbWluZyB0aGUgdmFyaWFibGUgVG90YWwgd2l0aGluIGVhY2ggZ3JvdXAuIHN1bW1hcmlzZSgpIGFsbG93cyB1cyB0byBkbyBqdXN0IHRoYXQgLSB0aGlzIGZ1bmN0aW9uIGNyZWF0ZXMgYSBuZXcgZGF0YWZyYW1lIGZvciBhIHN1bW1hcnkgc3RhdGlzdGljIG9mIG91ciBjaG9vc2luZy4gQmVjYXVzZSBpdCBpcyBhIHN1bW1hcnkgb2YgdGhlIGRhdGEsIHRoaXMgZnVuY3Rpb24gdHlwaWNhbGx5IGNvbGxhcHNlcyB0aGUgbGFyZ2VyIGRhdGFmcmFtZSBpbnRvIG9uZSB0aGF0IGhhcyBvbmUgdmFsdWUgZm9yIGVhY2ggZ3JvdXAuIEZvciBleGFtcGxlLCBpZiB3ZSB1c2Ugc3VtbWFyaXNlIHRvIGNhbGN1bGF0ZSB0aGUgbWVhbiBvZiB0aGUgdmFyaWFibGUgVG90YWwgKHdpdGhvdXQgZ3JvdXBpbmcgaXQpLCB0aGlzIGlzIHdoYXQgd2UgZ2V0Og0KDQptZWFuX3RvdGFsIDwtIG1ham9ycyAlPiUgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKFRvdGFsLCBuYS5ybT1UKSkNCmhlYWQobWVhbl90b3RhbCkNCmBgYA0KYGBge3J9DQojSW4gdGhpcyBsaW5lIG9mIGNvZGUsIHRoZSB3aG9sZSBkYXRhIGZyYW1lIGlzIHRyZWF0ZWQgYXMgYSBzaW5nbGUgZ3JvdXAsIHNvIHRoZSBvdXRwdXQgb2Ygc3VtbWFyaXNlIGlzIG9uZSB2YWx1ZS4gTGV0J3Mgc2VlIHdoYXQgaGFwcGVucyB3aGVuIHdlIGdyb3VwIHRoZSBkYXRhIGJ5IGNhdGVnb3J5LiBIZXJlLCB3ZSdsbCBnZXQgdGhlIHRvdGFsIG51bWJlciBvZiBzdHVkZW50cyBpbiBlYWNoIGNhdGVnb3J5LCBzbyB3ZSdsbCB1c2UgdGhlIHN1bSgpIGZ1bmN0aW9uIGFzIG91ciBzdW1tYXJ5IHN0YXRpc3RpYy4gDQoNCmNhdF90b3RhbCA8LSBtYWpvcnMgJT4lIGdyb3VwX2J5KE1ham9yX2NhdGVnb3J5KSAlPiUgc3VtbWFyaXNlKHRvdGFsX2NhdCA9IHN1bShUb3RhbCkpDQoNCiNsZXQncyBsb29rIGF0IHRoaXMgbmV3IGRhdGFmcmFtZToNCmhlYWQoY2F0X3RvdGFsKQ0KDQojVWggb2gsIG9uZSBvZiB0aGUgdmFsdWVzIGlzIE5BISBSZWNhbGwgdGhhdCwgd2hlbiB3ZSBjYWxjdWxhdGUgYW55IHN1bW1hcnkgc3RhdGlzdGljLCBSIGRvZXNuJ3Qga25vdyB3aGF0IHRvIGRvIHdpdGggTkEgdmFsdWVzIC0gd2hlbiBpdCBlbmNvdW50ZXJzIGFuIE5BIHZhbHVlIHdpdGhpbiBhIGdyb3VwLCBpdCB0aGVyZWZvcmUgcmV0dXJucyBOQSBhcyB0aGUgZmluYWwgdmFsdWUuIFdlIG5lZWQgdG8gdGVsbCBpdCB0byBpZ25vcmUgdGhlIE5BIHZhbHVlcyB0byBhdm9pZCB0aGlzLiANCg0KY2F0X3RvdGFsIDwtIG1ham9ycyAlPiUgDQogIGdyb3VwX2J5KE1ham9yX2NhdGVnb3J5KSAlPiUgDQogIHN1bW1hcmlzZSh0b3RhbF9jYXQgPSBzdW0oVG90YWwsIG5hLnJtPVQpKQ0KDQojVGhhdCBzaG91bGQgd29yayBub3chIE5vdGUgdGhhdCwgd2hlbiBJIHdyaXRlIGxvbmdlciBvciBtb3JlIGNvbXBsaWNhdGVkIGNvZGUgdXNpbmcgZHBseXIsIEkgbGlrZSB0byBwdXQgZWFjaCBhZGRpdGlvbmFsIGZ1bmN0aW9uIG9uIGl0cyBvd24gbGluZSAtIHRoaXMganVzdCBtYWtlcyB0aGUgY29kZSBjbGVhbmVyIGFuZCBlYXNpZXIgdG8gZm9sbG93LiANCmBgYA0KDQpgYGB7cn0NCiNTbywgdGhpcyBkb2VzIGEgcmVhbGx5IG5pY2Ugam9iIHByb2R1Y2luZyBvbmUgc3VtbWFyeSBzdGF0aXN0aWMgZm9yIHVzISBCdXQgd2hhdCBpZiB3ZSB3YW50IHRvIGNyZWF0ZSBhIGRhdGFmcmFtZSB3aXRoIGEgbnVtYmVyIG9mIHN1bW1hcnkgc3RhdGlzdGljcyBhYm91dCB0aGUgbWFqb3IgY2F0ZWdvcmllcz8gVGhpcyBpcyBlYXN5IHRvIGRvIHdpdGggc3VtbWFyaXNlKCkgdG9vISBJZiB5b3UgbG9vayB1cCB0aGUgaGVscCBwYWdlIGZvciBzdW1tYXJpc2UoKSwgaXQgbGlzdHMgYSBudW1iZXIgb2Ygc3VnZ2VzdGVkIHN1bW1hcnkgc3RhdGlzdGljcyB0aGF0IHlvdSBjYW4gY2FsY3VsYXRlIHVzaW5nIHRoaXMgZnVuY3Rpb24gLSBpZiB5b3UgYXJlIHN0dWNrIGFuZCBuZWVkIGlkZWFzLCBpdCdzIGhlbHBmdWwgdG8gcmV0dXJuIHRvIHRoZSBoZWxwIHBhZ2UuIExldCdzIHNheSBJIHdhbnQgdG8ga25vdyB0aGUgdG90YWwgc3R1ZGVudHMgaW4gZWFjaCBjYXRlZ29yeSwgYXZlcmFnZSBlbnJvbGxtZW50IGZvciBlYWNoIGRlcGFydG1lbnQgaW4gdGhlIGNhdGVnb3JpZXMsIGFzIHdlbGwgYXMgdGhlIGxhcmdlc3QgYW5kIHNtYWxsZXN0IGVucm9sbG1lbnQgdmFsdWVzIGZvciB0aGUgZGVwYXJ0bWVudHMgaW4gZWFjaCBjYXRlZ29yeS4gSGVyZSdzIGhvdyBJIGRvIGl0LCB1c2luZyB0aGUgc3VtKCksIG1lYW4oKSwgbWluKCksIGFuZCBtYXgoKSBmdW5jdGlvbnMgdGhhdCBhcmUgYnVpbHQgaW50byBSOg0KDQpzdW1tYXJ5X2NhdCA8LSBtYWpvcnMgJT4lIA0KICBncm91cF9ieShNYWpvcl9jYXRlZ29yeSkgJT4lIA0KICBzdW1tYXJpc2UodG90YWwgPSBzdW0oVG90YWwsIG5hLnJtID0gVCksIGF2ZyA9IG1lYW4oVG90YWwsIG5hLnJtID0gVCksIA0KICAgICAgICAgICAgc21hbGxlc3QgPSBtaW4oVG90YWwsIG5hLnJtID0gVCksIGxhcmdlc3QgPSBtYXgoVG90YWwsIG5hLnJtID0gVCkpDQoNCiNOb3cgd2UgaGF2ZSBhIG5pY2Ugc3VtbWFyeSB0YWJsZSEgTGV0J3MgYXJyYW5nZSB0aGUgdGFibGUgaW4gYW4gb3JkZXIgdGhhdCBtYWtlcyBzZW5zZSwgZm9yIGV4YW1wbGUsIGFscGhhYmV0aWNhbGx5Og0KDQpzdW1tYXJ5X2NhdCA8LSBzdW1tYXJ5X2NhdCAlPiUgYXJyYW5nZShNYWpvcl9jYXRlZ29yeSkNCg0KaGVhZChzdW1tYXJ5X2NhdCkNCmBgYA0KDQpUaGF0J3MgaXQgZm9yIFdlZWsgMiAtIHdlJ3ZlIGNvdmVyZWQgYSBsb3Qgb2YgZ3JvdW5kISBJbiB0aGlzIHdlZWsncyB0dXRvcmlhbCwgd2UndmUgZGlzY3Vzc2VkIG1pc3NpbmcgZGF0YSwgaG93IHRvIHdvcmsgd2l0aCBkYXRhIGZyYW1lcyBhbmQgbGlzdHMsIGFuZCB0aGUgYmFzaWNzIG9mIHRoZSBkcGx5ciBwYWNrYWdlLiBVc2luZyB0aGlzIHBhY2thZ2UsIHlvdSB3aWxsIGJlIGFibGUgdG8gZWFzaWx5IGNsZWFuIGFuZCBtYW5pcHVsYXRlIGRhdGEsIGNyZWF0ZSBuZXcgdmFyaWFibGVzLCBhbmQgcHJvZHVjZSBzdW1tYXJ5IHN0YXRpc3RpY3MuIFdlIGxlYXJuZWQgYWJvdXQgdGhlIHBpcGUgb3BlcmF0b3IgKCAlPiUpLCBhbmQgc29tZSBvZiB0aGUgbW9zdCBjb21tb24gZHBseXIgZnVuY3Rpb25zOiBmaWx0ZXIoKSwgc2VsZWN0KCksIG11dGF0ZSgpLCBhcnJhbmdlKCksIGdyb3VwX2J5KCksIGFuZCBzdW1tYXJpc2UoKS4gV2UgYWxzbyBsZWFybmVkIHNvbWUgbmV3IGJhc2UgUiBmdW5jdGlvbnMgdGhhdCB3ZSB3aWxsIHVzZSB0byBwcm9kdWNlIHN1bW1hcnkgc3RhdGlzdGljcyBhcyB3ZSBnbzogbWVhbiwgc3VtLCBtaW4sIGFuZCBtYXguIFdlIHdpbGwgbGVhcm4gbW9yZSBzdW1tYXJ5IHN0YXRpc3RpY3MgYXMgd2UgZ28sIGJ1dCB0aGVzZSBhcmUgaW1wb3J0YW50IGJhc2ljIGZ1bmN0aW9ucyB0byBzdGFydCB3aXRoLiBOZXh0IHdlZWssIHdlIHdpbGwgdXNlIG91ciBkYXRhIG1hbmlwdWxhdGlvbiBza2lsbHMgdG8gbGVhcm4gaG93IHRvIHByb2R1Y2UgYmFzaWMgdmlzdWFscyBhbmQgZ3JhcGhzIHVzaW5nIHRoZSBnZ3Bsb3QyIHBhY2thZ2UuIFRoZSBza2lsbHMgd2UgYXJlIGxlYXJuaW5nIGluIHRoZSBmaXJzdCB0aHJlZSB3ZWVrcyBvZiB0aGlzIGNvdXJzZSBhcmUgZm91bmRhdGlvbmFsIFIgY29uY2VwdHMgdGhhdCB3ZSB3aWxsIHV0aWxpemUgdGhyb3VnaG91dCB0aGUgY291cnNlIGFuZCB0aGF0IHdpbGwgaGVscCB5b3UgaWYgeW91IGNob29zZSB0byBleHBhbmQgeW91ciBwcm9ncmFtbWluZyBrbm93bGVkZ2UgaW4gdGhlIGZ1dHVyZS4gDQoNClJlc291cmNlcw0KDQpOYXZhcnJvLCBELiAoMjAxOSkuIExlYXJuaW5nIFN0YXRpc3RpY3Mgd2l0aCBSLiBSZXRyaWV2ZWQgZnJvbToNCmh0dHBzOi8vbGVhcm5pbmdzdGF0aXN0aWNzd2l0aHIuY29tL2Jvb2svaW5kZXguaHRtbC4gDQoNCldpY2toYW0sIEguLCBGcmFuw6dvaXMsIFIuLCBIZW5yeSwgTC4gJiBNw7xsbGVyLCBLLiAoMjAyMSkuIGRwbHlyOiBBIGdyYW1tYXIgb2YgZGF0YSBtYW5pcHVsYXRpb24uIFIgcGFjay1hZ2UgdmVyc2lvbiAxLjAuNi4gUmV0cmlldmVkIGZyb20gaHR0cHM6Ly8gQ1JBTi5SLSBwcm9qZSBjdC4gb3JnLyBwYWNrYSBnZT0gZHBseXIuIA0KDQo=