Instructions and Overview

In this assignment, we will examine what makes observations in our dataset both similar and different. To do so, we will consider how values in the dataset are distributed across observations, and how those values vary when considered in relation to other variables in the dataset. In this sense, we will practice graphically representing variation and co-variation in a dataset. To begin you will need to import and clean your dataset. You may reference last week’s lab to help with this. After this, you should follow the prompts and complete the short answer questions. Following each code chunk you compose and run in this assignment, I will ask you to do four things: 1) query, 2) summarize), 3) interpret, and 4) reflect.

  1. QUERY: I’m going to ask you to write a question that the code that you composed and ran is designed to answer. This is an opportunity to reflect on whether you understand what the code is actually doing. If you are struggling to come up with a question, it is most likely because you are not fully certain what the code is doing. If this is the case, you may need to study the functions a bit more.
  2. SUMMARIZE: I’m then going to ask you to summarize one thing that you learn from your data based on the output of the code. What do the results tell you empirically? Here you will want to be specific making sure your summary considers the scope of the data - its geographic, temporal, and topical bounds.
  3. INTERPRET: I’m going to ask you to then interpret your data, considering why the result matters in a broader sense. If you were to convey the results to a decision-maker, how would you convey to them the significance of the result? What should the numbers make us think? What questions do they bring up?
  4. REFLECT: Finally, I’m going to ask you to reflect on some of the limitations to answering the questions that you posed with the data at hand. Knowing what you know about how the data was collected and aggregated, what uncertainties remain in regards to addressing this question? In what ways is the analysis limited by the scope of the data’s definitions or categories?

Getting Started

Load the relevant libraries

library(tidyverse)
library(lubridate)

Import and clean example datasets

hospitals <- read.csv("datasets/Hospitals.csv", stringsAsFactors = FALSE)

world_health_econ <- read.csv("datasets/world_health_econ.csv", stringsAsFactors = FALSE)

cases <- read.csv("https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-counties.csv", stringsAsFactors = FALSE)

hospitals$ZIP <- as.character(hospitals$ZIP)

hospitals$ZIP <- str_pad(hospitals$ZIP, 5, pad = "0") 

is.na(hospitals) <- hospitals == "NOT AVAILABLE"
is.na(hospitals) <- hospitals == -999

hospitals$SOURCEDATE <- ymd_hms(hospitals$SOURCEDATE)
hospitals$VAL_DATE <- ymd_hms(hospitals$VAL_DATE)
cases$date <- ymd(date)
Error in as.character(x) : 
  cannot coerce type 'closure' to vector of type 'character'

Import and clean your dataset.

#Copy and paste the code from lab 4 to both import and clean your dataset here. 

Zooming in to Explore Filtered Data

Before we get into how to graphically represent variation and co-variation, we will first need to consider what sets of observations we will be comparing. Often in data exploration, we do not just want to examine the dataset as a whole, but to also examine how values, calculations, and plots change when we zoom in to one specific set of observations in the dataset. Last week, we explored how your data was defined, how it was categorized, and how missing values were represented. Through this exercise, we were able to develop a general overview of the observations, variables, and values in our datasets. Knowing this we likely have a better sense of areas we want to be able to zoom into and explore in our data. As we prepare to visualize variation and co-variation in the dataset, let’s first go over how we can both zoom in on certain observations.

Filtering to a Category

Filtering is one way we can zoom in on our data - exploring only those observations that meet a particular criteria.

For instance, last week we learned above that one criteria for being designated as a Critical Access Hospital is that the hospital must have 25 or fewer inpatient beds. We may want to see how the values for BEDS change when we filter to (or zoom into) just those observations representing critical access hospitals. Notice how we can combine any number of dplyr verbs using the pipe (%>%). Below I will filter to rows that meet a criteria and then select a variable to examine from the filtered data.

#Run this code chunk.

#df %>% filter(CATEGORICAL_VARIABLE == "VALUE") %>% select(CATEGORICAL_VARIABLE)
hospitals %>% filter(TYPE == "CRITICAL ACCESS") %>% select(NAME, BEDS)
hospitals %>% filter(TYPE == "CRITICAL ACCESS") %>% select(BEDS) %>% summary()
      BEDS      
 Min.   :  3.0  
 1st Qu.: 22.0  
 Median : 25.0  
 Mean   : 27.7  
 3rd Qu.: 25.0  
 Max.   :286.0  
 NA's   :42     
  1. QUERY: This analysis might help us answer the question: Do all critical access hospitals in the US have 25 beds or fewer, and what is average number of beds at a critical access hospital?
  2. SUMMARIZE: We can see that there are some hospitals in the US that have been designated as critical access hospitals that have more than 25 beds, that at least one critical access hospital has as many as 286 beds, that all critical access hospitals have at least three beds, and that the average number of beds hovers around 25.
  3. INTERPRET: Since critical access hospitals are legally supposed to have 25 beds or fewer, we may want to look into which critical access hospitals have more than 25 beds. This may indicate that these hospitals are not meeting the requirements to receive federal funding or that there is an issue with the data being recorded.
#Run this code chunk.

hospitals %>% filter(TYPE == "CRITICAL ACCESS" & BEDS > 25) %>% select(NAME, TYPE, STATE, BEDS, STATUS)
  1. REFLECT: There are 180 critical access hospitals in the dataset with more than 25 beds. This brings up question of how the HIFLD team determined 1) that the hospital was a critical access hospital and 2) the number of beds. If the hospital was part of a complex with multiple facilities and just one of those facilities was critical access, was the hospital classed as critical access? If so, how were beds then calculated? What was the source of the bed count - the hospital’s website? State or other government documents? Were these sources reliable?

Filtering to Numeric Observations Above or Below a Threshold

We may also want to explore if there are certain hospital ownership models that tend to have more beds. To do so, we would filter the data to those observations where BEDS is greater than a certain threshold - let’s say 1200. The first time I do this below, I select() the NAME of the hospital and the OWNER. This shows every hospital with more than 1200 beds, along with its OWNER type. However, what if I only wanted to know which owner types had hospitals with more than 1000 beds? I wouldn’t necessarily want to select() OWNER in this case because this would show me the owner for every observation in my filtered data. As you can see below, this means that GOVERNMENT-STATE would appear 13 times! Instead, I would want to check the distinct() OWNER in the filtered data. Check out how I do this below.

#Run this code chunk.

#df %>% filter(NUMBERIC_VARIABLE > VALUE) %>% distinct(CATEGORICAL_VARIABLE)

#Lists name and owner of hospitals with more than 1000 beds.
hospitals %>% filter(BEDS > 1000) %>% select(NAME, OWNER) 

#Lists owner for every hospital with more than 1000 beds in the dataset
hospitals %>% filter(BEDS > 1000) %>% select(OWNER) 

#Lists the owners with more than 1000 beds
hospitals %>% filter(BEDS > 1000) %>% distinct(OWNER) 
  1. QUERY: Which ownership models have at least one hospital with more than 1000 beds?
  2. SUMMARIZE: We can see that 3 ownership models have hospitals with more than 1000 beds, including state government hospitals, district government hospitals, and non-profit hospitals.
  3. INTERPRET: This indicates that the largest hospitals in the country tend to be district and state government hospitals and non-profit hospitals, whereas, according to this data, there are no private hospitals, federal, or local hospitals with more than 1000 beds. As the US federal government considers how to distribute federal aid to hospitals, this is one (very tiny) step towards understanding the various relationships between hospital business models and patient capacity. Consider some of the consequences of these decisions.
  4. REFLECT: What counts as a bed in the hospitals dataset? Do ambulatory beds count? Are beds calculated based on the number of actual cots in the hospital, or the number of spaces available for beds? Does a bed count assume that there are enough staff and resources to support that many patients in those beds?

When I Need to Filter First: One-Dimensional vs. Multi-Dimensional Data

For some of you, filtering your data in this way will be necessary before performing operations across numeric variables in your dataset. This is because, as we learned last week, some of you have observational units that span multiple time periods, multiple geographies, or multiple issues. Before performing an operation across a numeric variable, we need to ensure all of the values in that variable are referring to observations reported across the same timeframe or geographic scale.

In the hospitals dataset, this is less of a concern because as we learned last week, the observational unit of the dataset is one thing - a hospital. The BEDS variable is always going to refer to the number of BEDS at a hospital. This means that the hospitals dataset is one-dimensional.

With the world_health_econ data, we learned last week that every observation refers to a country and a year. There are two variables that make up the unique key. This means that the world_health_econ dataset is two-dimensional. Let’s say that we wanted to call summary() on life_exp variable to compare life expectancies across countries. Without first zooming in to to a specific year, we would be including multiple values taken at the same place at different times. Let’s filter the data to only include the most recent reporting year and then call summary():

#Run this code chunk.

world_health_econ %>%
  filter(year == max(year, na.rm = TRUE)) %>% #Note that this is how we can filter to the rows with the maximum value in a variable; in this case, this would be the most recent year. 
  select(life_exp) %>%
  summary()

With the cases data, we learned last week that every observation refers to a county, state, and date. There are three variables that make up the unique key. This means that the cases dataset is three-dimensional. Let’s say that we wanted to call summary() on cases variable to compare cases across counties. Without first zooming in to to a specific date and state, we would be including multiple values taken at the same place at different times. Let’s filter the data to only include the most recent date and the state of California and then call summary():

#Run this code chunk.

cases %>%
  filter(date == max(date, na.rm = TRUE) & state == "California") %>% #Note that this is how we can filter to the rows with the maximum value in a variable; in this case, this would be the most recent year. 
  select(cases) %>%
  summary()
     cases      
 Min.   :    1  
 1st Qu.:   49  
 Median :  370  
 Mean   : 3437  
 3rd Qu.: 2553  
 Max.   :89490  
cases %>%
  filter(date == max(date, na.rm = TRUE) & state == "California")

Let’s test the extent to which you will need to zoom in to statistically analyze numeric values your data. Think what variables make up the unique key in your dataset. If you have more than one variable in your unique key, make sure that each is represented in your statement below.

#Uncomment the line associated with your dataset and fill in the blank. Then run the code.

#paste(df$NUMERIC_VARIABLE[1], "refers to a number/measure of [FILL NUMERIC VARIABLE] in a _____ in my dataset.")

#Example:
paste(hospitals$BEDS[1], "refers to a number of beds in a hospital in my dataset.")
paste(world_health_econ$pop[1], "refers to a number of people in a country in a given year in my dataset.")
paste(cases$cases[1], "refers to a number of cumulative cases in a county and state on a given dau in my dataset.")

#paste(_____$_____[1], "refers to a number of _____ in a _____ in my dataset.")

How did you fill in the last _____?

Is your observational unit one thing (e.g. one hospital, or one country)? If this is the case, it will likely not be as essential for you to zoom in before operating on numeric variables because you are working with one-dimensional data.

OR

Is your observational unit a combination of things or factors (e.g. one chemical reported at a particular facility or one census tract reporting in a particular year)? If this is the case, it will likely be essential for you to zoom in before operating on numeric variables because you will be working with multi-dimensional data.

If you are working with multi-dimensional data, in some places throughout this lab, you will need to filter your data to particular observations before analyzing across a variable. This is because we will be summarizing information across groups of data, and it will be important to ensure that you are summarizing information across like observations.

Think about what you might filter to in order to ensure that you will be comparing like observations (hint: it will involve a variable in your unique key). Perhaps you will filter to the most recent year, so that you can compare observations across geographies in that year. Or perhaps you will filter to a particular geography, so that you can compare observations across time in that geography. Or perhaps you will filter to a particular diagnosis group, so that you can compare costs across hospitals for that diagnosis. Or perhaps you will filter to a particular year and family type so that you can compare observations across counties in that year for that family type. Characterize one way you might filter your data below. Be specific. Which variable in the dataset will you filter on and to what value(s) will you filter it to?

Fill your response here. 

Filtering Your Own Dataset

Filtering to a Categorical Value in your Dataset

Select one of the values that you identified from calling distinct() on a categorical variable in last week’s lab. Filter the dataset to the rows representing that value, select a numeric variable to explore, and then call summary(). If you have multi-dimensional data, be sure to first zoom into a set of observations in your data (using filter()).

#Uncomment the appropriate lines below, and fill in your data frame, variables, and value. Run the code.

#_____ %>% filter(_____ == "_____") %>% select(_____) %>% summary()

#If you have multi-dimensional data, you may need to call:
#_____ %>% filter(_____ == _____ & _____ == "_____") %>% select(_____) %>% summary()

Copy and paste the definition of the categorical variable you selected from the data dictionary below.

Fill your response here. 
  1. QUERY: Below, write a research question that the code you just ran is designed to be able to answer. Make sure you phrase your question directly in relation to the results of your code. In other words, you have the answer; now come up with the question. Consider this a check on whether you understand what the code above is doing. If you are unsure how to compose this question, you probably want to study the functions above a bit more closely.
Fill your response here. 

Are there any other variables in your dataset that you need to take into consideration before directing this analysis towards answering that question? In other words, do you need to zoom into any specific areas of the dataset (by filtering) in order to appropriately address this question? If so, which? (For instance, for the hospitals dataset we needed to filter to hospitals that were OPEN in order to address questions about infrastructure). Briefly note this below.

Fill your response here. 
  1. SUMMARIZE: Reviewing the output of your code, summarize one thing that you learn about your topic from running this code chunk. In other words, what is one thing that the results of this analysis empirically tell us about the topic? Be specific, considering the geographic, temporal, and topical scope of your data.
Fill your response here. 
  1. INTERPRET: Now imagine you were reporting your findings to a decision-maker on your topic. Describe to that decision-maker why they should care. In other words, interpret what is important about this finding.
Fill your response here. 
  1. REFLECT: What else would we need to know to fully address this question? Knowing what you know about how the data was collected and aggregated, what uncertainties remain in regards to addressing this question? In what ways is the analysis limited by the scope of the data’s definitions or categories?
Fill your response here. 

Filtering to Numeric Values in your Dataset

Select a numeric variable in your dataset that represents the extent or scale of the issue you are studying. Pick a number that you believe serves as a good indicator that this issue is at a notable extent or scale, and filter the dataset to all the rows greater than (or less than) this number. Check the remaining distinct values in a categorical variable in the dataset. If you have multi-dimensional data, be sure to first zoom into a set of observations in your data (using filter()).

#Uncomment the appropriate lines below, and fill in your data frame, variables, condition, and value. Run the code.
#_____ %>% filter(_____ _____ _____) %>% distinct(_____)

#If you have multi-dimensional data, you may need to call:
#_____ %>% filter(_____ == _____ & _____ _____ _____) %>% distinct(_____)

Copy and paste the definition of the numeric variable you selected from the data dictionary below.

Fill your response here. 
  1. QUERY: Below, write a research question that the code you just ran is designed to be able to answer. Make sure you phrase your question directly in relation to the results of your code. In other words, you have the answer; now come up with the question. Consider this a check on whether you understand what the code above is doing. If you are unsure how to compose this question, you probably want to study the functions above a bit more closely.
Fill your response here. 

Are there any other variables in your dataset that you need to take into consideration before directing this analysis towards answering that question? In other words, do you need to zoom into any specific areas of the dataset (by filtering) in order to appropriately address this question? If so, which? (For instance, for the hospitals dataset we needed to filter to hospitals that were OPEN in order to address questions about infrastructure). Briefly note this below.

Fill your response here. 
  1. SUMMARIZE: Reviewing the output of your code, summarize one thing that you learn about your topic from running this code chunk. In other words, what is one thing that the results of this analysis empirically tell us about the topic? Be specific, considering the geographic, temporal, and topical scope of your data.
Fill your response here. 
  1. INTERPRET: Now imagine you were reporting your findings to a decision-maker on your topic. Describe to that decision-maker why they should care. In other words, interpret what is important about this finding.
Fill your response here. 
  1. REFLECT: What else would we need to know to fully address this question? Knowing what you know about how the data was collected and aggregated, what uncertainties remain in regards to addressing this question? In what ways is the analysis limited by the scope of the data’s definitions or categories?
Fill your response here. 

ggplot

At this point in the assignment, we will begin leveraging the Tidyverse package ggplot to create plots for visualizing the data. To create a plot with ggplot, we will follow this basic formula:

df %>% 
  ggplot(aes(x = VARIABLE_NAME)) + 
  CHART_TYPE

For example, for a bar chart, you will call:

df %>% 
  ggplot(aes(x = VARIABLE_NAME)) + 
  geom_bar()

For a column chart, you will call:

df %>% 
  ggplot(aes(x = VARIABLE_NAME, y = VARIABLE_NAME)) + 
  geom_col()

Let’s break that down a bit. First, you will call your dataframe. Following your dataframe and a pipe, you will call ggplot(), which basically tells R to prepare to create a plot. Inside ggplot, you will list aesthetics. These are variables in the dataset that you would like to appear on your plot. Setting x = VARIABLE_NAME tells ggplot() what variable to plot on the x-axis. Setting y = VARIABLE_NAME tells ggplot() what variable to plot on the y-axis. Finally, following a plus (+) sign, you tell ggplot which type of plot to create. The ggplot cheatsheet lists a number of plots that you can create with ggplot, as well as a number of different ways to style the plot. We will practice several of these below.

For every plot that you produce, I will expect you to add a title and labels to the x and y axis. You can do this as follows:

df %>% 
  ggplot(aes(x = VARIABLE_NAME, y = VARIABLE_NAME)) + 
  geom_col() +
  labs(title = "FILL TITLE", x = "FILL X-AXIS LABEL", y = "FILL Y-AXIS LABEL)

There are also a number of useful tools for styling your plots. For instance we can set the theme of the plot to look a bit more polished by adding “+ theme_bw()” to the plot. I will do this for all plots in this lab.

df %>% 
  ggplot(aes(x = VARIABLE_NAME, y = VARIABLE_NAME)) + 
  geom_col() +
  labs(title = "FILL TITLE", x = "FILL X-AXIS LABEL", y = "FILL Y-AXIS LABEL") +
  theme_bw()

Two styling issues that I’m sure will come up in most of your plots include: * changing x or y axis tick numbers from scientific to comma notation: + scale_x_continuous(labels = scales::comma) OR + scale_y_continuous(labels = scales::comma) * turning x axis tick marks 90 degrees so that they do not overlap: + theme(axis.text.x = element_text(angle = 90, hjust=1)) OR + theme(axis.text.y = element_text(angle = 90, hjust=1))

df %>% 
  ggplot(aes(x = VARIABLE_NAME, y = VARIABLE_NAME)) + 
  geom_col() +
  labs(title = "FILL TITLE", x = "FILL X-AXIS LABEL", y = "FILL Y-AXIS LABEL") +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 90, hjust=1)) + #Turn labels 90 degrees
  scale_x_continuous(labels = scales::comma) #Change labels from scientific to comma notation

Variation

Variation is the extent to which the values in a particular variable vary from observation to observation. Examining variation involves looking at the distribution of values in a particular column in the dataset. Specifically, we are counting the number of times each value or set of values appears in that variable. Do we have a whole bunch of one particular value in a certain variable, and very few of another? Or maybe, do we have a more even distribution of values across a variable?

So how do we visualize variation with ggplot? Below I describe two different plots that you can leverage to visualize variation - a bar plot and a histogram.

Bar Plot

A bar plot displays the number of times each value appears in a categorical variable. It counts the number of times each value appears in that variable and then sets the height of a bar in the plot according to that count. This will tell us how the observations in the dataset vary in regards to that variable. In other words, this plot will communicate the number of observations in your dataset by that variable.

#Run this code chunk.

#df %>% ggplot(aes(x = CATEGORICAL_VARIABLE)) + geom_bar() + labs(title = "TITLE", x = "X-AXIS NAME", y = "Y-AXIS NAME")

hospitals %>% 
  ggplot(aes(x = TYPE)) + 
  geom_bar() +
  labs(title = "Number of Hospitals in the US by Type", x = "Type", y = "Count of Hospitals") + #Adds a title to the plot
  theme_bw() +
  theme(axis.text.x = element_text(angle = 90, hjust=1)) #Changes x-axis tick labels 90 degrees 

Remember that this dataset includes hospitals that are designated as closed. Depending on the question we are trying to address, we may wish to zoom in to only the observations signifying a hospital that is open before creating this plot.

#Run this code chunk.

#df %>% ggplot(aes(x = CATEGORICAL_VARIABLE)) + geom_bar() + labs(title = "TITLE", x = "X-AXIS NAME", y = "Y-AXIS NAME")

hospitals %>% 
  filter(STATUS == "OPEN") %>%
  ggplot(aes(x = TYPE)) + 
  geom_bar() +
  labs(title = "Number of Hospitals in the US that are Open by Type", x = "Type", y = "Count of Hospitals") + #Adds a title to the plot
  theme_bw() +
  theme(axis.text.x = element_text(angle = 90, hjust=1)) #Changes x-axis tick labels 90 degrees 

Titling a Bar Plot

Note how I titled my first plot above: “Number of Hospitals in the US by Type” Remember last week, when we identified what makes each observation in our dataset unique? Here I am counting the observations by Type, and in order to know what I’m counting, I need to know what each observation refers to. A good formula for titling bar plots is as follows:

Number of _____ by [x-axis variable name]

In order to fill in the blank line above, consider the statement we produced last week: “I have nrow(df) unique _____ represented in my dataset.” That blank line told us what each observation in the dataset represented - or its observational unit. However we filled in that blank line should also be how we fill in the title of a bar plot.

The [x-axis variable name] should be your x-label and “Count of ______” (filled the same as above) should be your y-label. Note that if you filter your dataset, you should account for this in the title: “Number of Hospitals in the US by Type”

What if I have multi-dimensional data?

When we create a bar plot, we are counting the number of observations that fall into each category. If there is only one variable that makes up your unique key, that one variable will represent what is being counted (e.g. above we are counting hospitals by category). However, if there are multiple variables in your unique key, then identifying what it is that you are counting becomes a little more complicated. For instance, let’s say your data reports the population of each country each year as it does in the world_health_econ dataset. Now let’s say that you wanted to plot the number of countries per continent. If you were to call:

#Run this code chunk.

world_health_econ %>% 
  ggplot(aes(x = continent)) + 
  geom_bar() +
  labs(title = "Number of Countries per Continent - Incorrect", x = "Continent", y = "Count of Countries") + #Adds a title to the plot
  theme_bw() +
  theme(axis.text.x = element_text(angle = 90, hjust=1)) #Changes x-axis tick labels 90 degrees 

… you would be counting the combination of the number of countries and years per continent. There are not 800 countries in Africa, but Africa appears in the dataset 800 times because each country in Africa has several rows in the dataset - one for each reporting year. In other words, each country is represented in the bar for every year that it was included in the dataset. The y-axis does not just represent countries but both countries and years. If we want the y-axis to only be counting one thing, then we need to first reduce the dataset to values in a particular context. You can do this by filtering the data as you had been doing above.

#Run this code chunk.

world_health_econ %>% 
  filter(year == max(year, na.rm = TRUE)) %>%
  ggplot(aes(x = continent)) + 
  geom_bar() +
  labs(title = "Number of Countries per Continent in the most Recent Reporting Year", x = "Continent", y = "Count of Countries") + #Adds a title to the plot
  theme_bw() +
  theme(axis.text.x = element_text(angle = 90, hjust=1)) #Changes x-axis tick labels 90 degrees

Note the addition to my title above. If you filter your dataset, the formula for titling changes a bit to Frequency of [x-axis variable name] across _____ in [filtered value]

Select a categorical variable for which you want to graphically represent the number of times it appears in the dataset.

I recommend that you select one of the same categorical variables that you analyzed with the distinct() function last week. If you have multi-dimensional data, be sure to filter your data first so that all of the observations you are counting have one variable as a unique key. If you notice styling issues with your data, be sure to consider my notes about how to fix them above.

#Uncomment the line below and fill appropriately. Add a title and labels to your plots, and adjust its style to be legible. Then run the code.
#_____ %>% ggplot(aes(x = _____)) + geom_bar()

#If multi-dimensional:
#_____ %>% filter(_____ == _____) %>% ggplot(aes(x = _____)) + geom_bar()

Copy and paste the definition of the categorical variable you selected from the data dictionary below.

Fill your response here. 

Complete the following statement:

Each bar in the bar plot above is counting the number of _____ in my dataset according to _____.
  1. QUERY: Below, write a research question that the code you just ran is designed to be able to answer. Make sure you phrase your question directly in relation to the results of your code. In other words, you have the answer; now come up with the question. Consider this a check on whether you understand what the code above is doing. If you are unsure how to compose this question, you probably want to study the functions above a bit more closely.
Fill your response here. 

Are there any other variables in your dataset that you need to take into consideration before directing this analysis towards answering that question? In other words, do you need to zoom into any specific areas of the dataset (by filtering) in order to appropriately address this question? If so, which? (For instance, for the hospitals dataset we needed to filter to hospitals that were OPEN in order to address questions about infrastructure). Briefly note this below.

Fill your response here. 
  1. SUMMARIZE: Reviewing the output of your code, summarize one thing that you learn about your topic from running this code chunk. In other words, what is one thing that the results of this analysis empirically tell us about the topic? Be specific, considering the geographic, temporal, and topical scope of your data.
Fill your response here. 
  1. INTERPRET: Now imagine you were reporting your findings to a decision-maker on your topic. Describe to that decision-maker why they should care. In other words, interpret what is important about this finding.
Fill your response here. 

4a. REFLECT: Reflect on the distribution of categories in the dataset. Is there an even distribution of observations across each category, or are certain categories more represented than others? Why might this be? What does this say about the social, political, or economic landscape of your topic?

Fill response here. 

4b. REFLECT: Reflect on what you learned about the history of the categories you plotted above in last week’s lab. How have the social, political, and economic forces shaping this categorization impacted how we count observations related to this topic? How might this plot look different if this variable had been categorized in a different way?

Fill response here. 

4c. REFLECT: Reflect on what we cannot see with this data. What might be one topic or issue that does not fit neatly into the designated categories?

Fill response here. 

Histogram

A histogram will display the distribution of values in a numeric variable within a designated set of increments. After you designate a certain number to group increments by, it will count the number of values in the variable that fall into each increment. Let’s say you designate the number 10 to group increments by, starting at 0. The plot will count how many values in the variable fall in the increment 0-9, 10-19, 20-29, and so on. This will tell us how the observations in the dataset vary in regards to that variable.

Consider the plot below. This plot tells us the distribution of beds across open hospitals. It counts how many hospitals there are in each increment of 10 beds.

#Run this code chunk.

#df %>% ggplot(aes(x = NUMERIC_VARIABLE)) + geom_histogram(binwidth = 1, boundary = 0) + labs(title = "TITLE", x = "X-AXIS NAME", y = "Y-AXIS NAME")

hospitals %>% 
  filter(STATUS == "OPEN") %>%
  ggplot(aes(x = BEDS)) +
  geom_histogram(binwidth = 10, boundary = 0) +
  labs(title = "Distribution of Beds across Hospitals in the US that are Open", x = "Beds", y = "Count of Hospitals") +
  theme_bw()

Note that boundary refers to where we want our increments to begin and binwidth refers to the size of the increments at which frequency will be calculated. Above the binwidth is set to 10. This means that ggplot will display the frequency of each value at intervals of 10, 20, 30, 40, etc. When we set the binwidth to 1, ggplot will display the frequency of each value at intervals of 1, 2, 3, 4. etc. What difference does this make?

Notice what happens when we set the binwidth to 1. While above we count the number of hospitals with 0-9 beds 10-19 beds, 20-29 beds, etc, this will count the number of hospitals with 0 beds, 1 bed, 2 beds, and so on. Because we are counting the number in such small increments, the plot will look much more jagged and will take a longer time to load. This plot displays the counts in finer granularity than the first plot.

#Run this code chunk.

hospitals %>% 
  filter(STATUS == "OPEN") %>%
  ggplot(aes(x = BEDS)) +
  geom_histogram(binwidth = 1, boundary = 0) +
  labs(title = "Distribution of Beds across Hospitals in the US that are Open", x = "Beds", y = "Count of Hospitals") +
  theme_bw()

When we set the binwidth to 100, we count the number of hospitals with 0-99 beds, 100-199 beds, 200-299 beds, and so on. Because we are counting the number in larger increments, the plot will look much smoother and will take less time to load. This plot displays the counts in thicker granularity than the first plot.

#Run this code chunk.

hospitals %>% 
  filter(STATUS == "OPEN") %>%
  ggplot(aes(x = BEDS)) +
  geom_histogram(binwidth = 100, boundary = 0) +
  labs(title = "Distribution of Beds across Hospitals in the US that are Open", x = "Beds", y = "Count of Hospitals") +
  theme_bw()

Titling a Histogram

Note how I titled my plot above: “Distribution of Beds across Hospitals in the US that are Open” Consider again what makes each observation unique. A good formula for titling histograms is as follows:

Distribution of [x-axis variable name] across _____

Again, we can fill in the blank with our observational unit. The [x-axis variable name] should be your x-label and “Count of ______” (filled the same as above) should be your y-label.

What if I have multi-dimensional data?

In the world_health_econ data, without separating out units of observation, we would be visualizing multiple values reported at the same place at different periods in time (i.e. every year since 1995). Instead, we want to zoom into a single year in the dataset so we are just comparing values across place.

#Run this code chunk.

world_health_econ %>% 
  filter(year == max(year, na.rm = TRUE) & tot_health_sp_pp >100) %>%
  ggplot(aes(x = tot_health_sp_pp)) + 
  geom_histogram(binwidth = 1000, boundary = 0) +
  labs(title = "Distribution of Total Health Spending per Person across Countries in 2010", x = "Total Health Spending per Person", y = "Count of Countries") + # To add titles and labels
  theme_bw() +
  scale_x_continuous(labels = scales::comma) #Change labels from scientific to comma notation

Note the addition to my title above. If you filter your dataset, the formula for titling changes a bit to Distribution of [x-axis variable name] across _____ in [filtered value]

Select a numeric variable for which you want to visualize the distribution of a set of values.

Be sure to select a variable that describes something about the observational unit and not another categorical variable in your dataset. For instance, let’s say you had the following data table - with each row reporting an environmental violation at a facility:

Violation Number | Facility Name | Facility Town | Population of Facility Town _________________ | _________________ | _________________ | _________________ 1234567 | Facility A | Tarrytown | 90000 2345678 | Facility B | Tarrytown | 90000 3456789 | Facility C | Another Town | 70000

In this table, we would not want to create a histogram with population of facility town. This is because our observational unit is a violation, not a town, and population does not describe something about the violation but instead describes something about the town the facility is in. If we were to create a histogram with this variable, we would be counting the number of times each population value appears in the dataset - something that does not make much sense, since we can have the same town’s population appear several times in the dataset if there are more than one violations or more than one facilities in a town.

If you have multi-dimensional data, be sure to first zoom into a set of observations in your data (using filter()).

#Uncomment the line below and fill appropriately. Add a title and labels to your plots. Run the code.

#_____ %>% ggplot(aes(x = _____)) + geom_histogram(binwidth = _____, boundary = 0) 

Copy and paste the definition of the numeric variable you selected from the data dictionary below.

Fill your response here. 

Complete the following statement:

Each bar in the histogram above is counting the number of _____ in my dataset according to _____.
  1. QUERY: Below, write a research question that the code you just ran is designed to be able to answer. Make sure you phrase your question directly in relation to the results of your code. In other words, you have the answer; now come up with the question. Consider this a check on whether you understand what the code above is doing. If you are unsure how to compose this question, you probably want to study the functions above a bit more closely.
Fill your response here. 

Are there any other variables in your dataset that you need to take into consideration before directing this analysis towards answering that question? In other words, do you need to zoom into any specific areas of the dataset (by filtering) in order to appropriately address this question? If so, which? (For instance, for the hospitals dataset we needed to filter to hospitals that were OPEN in order to address questions about infrastructure). Briefly note this below.

Fill your response here. 
  1. SUMMARIZE: Reviewing the output of your code, summarize one thing that you learn about your topic from running this code chunk. In other words, what is one thing that the results of this analysis empirically tell us about the topic? Be specific, considering the geographic, temporal, and topical scope of your data.
Fill your response here. 
  1. INTERPRET: Now imagine you were reporting your findings to a decision-maker on your topic. Describe to that decision-maker why they should care. In other words, interpret what is important about this finding.
Fill your response here. 

4a. REFLECT: Reflect on the distribution of values. What are the range of values represented in the data? Are the values evenly distributed, or are certain values more represented than others? Why might this be? Do any of the values surprise you? Why?

Fill response here. 

4b. REFLECT: Why did you select the binwidth that you did? How might the story your plot tells change if you were to change the binwidth? What anomalies might be hidden with a larger binwidth, and what trends might be hidden with a smaller binwidth?

Fill response here. 

4c. REFLECT: Check how the numeric variable was defined in the data dictionary, and quote the definition below. How might the counts represented in your frequency plot appear differently if this variable was defined differently?

Fill response here. 

Co-variation

Co-variation is the extent to which the values that constitute two or more variables vary in relation to one another. To visualize co-variation, we might create:

Count Plots

Count plots display how many times two categorical values appear together in a dataset. For instance, in the count plot below, we display the number of open hospitals with each combination of OWNER and TYPE.

#Run this code chunk.

#df %>% ggplot(aes(x = CATEGORICAL_VARIABLE, y = CATEGORICAL_VARIABLE)) + geom_count()

hospitals %>% 
  filter(STATUS == "OPEN") %>%
  ggplot(aes(x = TYPE, y = OWNER)) + 
  geom_count() +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 45, hjust=1)) +
  labs(title = "Number of Hospitals in the US that are Open by Type and Ownership", x = "Type", y = "Ownership", size = "Number of Hospitals")

Titling a Count Plot

Note how I titled my plot above: “Number of Hospitals in the US that are Open by Type and Ownership” Consider again what makes each observation unique. Here I am counting the observations by Type and Ownership, and in order to know what I’m counting, I need to know what each observation refers to. A good formula for titling count plots is as follows:

Number of _____ by [x-axis variable name] and [y-axis variable name]

The blank should be filled with your unit of observation. The [x-axis variable name] should be your x-label and [y-axis variable name] should be your y-label. You should also set the size attribute label to “Number of [observational unit]”

What if I have multi-dimensional data?

If this is the case I would encourage you to include one of the variables in your unique key in the x or y-axis. For instance, if the unique key for world_health_econ is country and year, I can include year as the y-axis below to visualize how counts of observations change over time. (Notice how they don’t in the plot below.) Alternatively, if you wish to compare two categorical variables that are not a part of the unique key, be sure to filter the data so that only one variable constitutes the unique key.

#Run this code chunk.

world_health_econ %>% 
  ggplot(aes(x = continent, y = as.factor(year))) + 
  geom_count() +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 45, hjust=1)) +
  labs(title = "Number of Countries by Continent and Year", x = "Continent", y = "Year")

Stacked Frequency Plots

Similar to histograms, frequency plots display the distribution of numeric values in a variable. In other words, they count the number observations in a dataset that fall into each bracketed increment of a numeric variable. Unlike histograms, they display these values as lines rather than as bars. We tend to use frequency plots instead of histograms when we are looking to compare frequencies across different values in a categorical variable. Stacked frequency plots display the distribution of numeric values in a variable, grouped by a categorical value. For instance, the plot below display the distribution of beds across open hospitals, categorized by the hospital type.

#Run this code chunk.

#df %>% ggplot(aes(x = NUMERIC_VARIABLE, col = CATEGORICAL_VARIABLE)) + geom_freqpoly(binwidth = 1)

hospitals %>% 
  filter(STATUS == "OPEN") %>%
  ggplot(aes(x = BEDS, col = TYPE)) + 
  geom_freqpoly(binwidth = 100, boundary = 0) +
  labs(title = "Frequency of Beds across Hospitals in the US that are Open by Hospital Type", x = "Beds", y = "Count of Hospital", col = "Type") + # To add titles and labels
  theme_bw() 

Stacked frequency plots work best when categorizing by a variable with 10 or fewer distinct values. Otherwise, it can be tricky to see the differences in color gradations. If all of your categorical variables have more than 10 distinct values, one thing you might consider is first filtering your data to a few representative categories. For instance, let’s say that I would like to see the distribution of beds in hospitals across states. Since there are 57 states, if I were to categorize the distribution by state, the plot would be very difficult to read.

#Run this code chunk.

#df %>% ggplot(aes(x = NUMERIC_VARIABLE, col = CATEGORICAL_VARIABLE)) + geom_freqpoly(binwidth = 1)

hospitals %>% 
  filter(STATUS == "OPEN") %>%
  ggplot(aes(x = BEDS, col = STATE)) + 
  geom_freqpoly(binwidth = 100, boundary = 0) +
  labs(title = "Frequency of Beds across Hospitals in the US that are Open by Hospital State", x = "Beds", y = "Count of Hospital", col = "Type") + # To add titles and labels
  theme_bw() 

In this case, we may wish to first filter our data to a few representative states using %in%.

#Run this code chunk.

#df %>% ggplot(aes(x = NUMERIC_VARIABLE, col = CATEGORICAL_VARIABLE)) + geom_freqpoly(binwidth = 1)

hospitals %>% 
  filter(STATUS == "OPEN" & STATE %in% (c("CA", "MA", "NY", "FL", "LA"))) %>%
  ggplot(aes(x = BEDS, col = STATE)) + 
  geom_freqpoly(binwidth = 100, boundary = 0) +
  labs(title = "Frequency of Beds across Hospitals in the US that are Open by Hospital State", x = "Beds", y = "Count of Hospital", col = "Type") + # To add titles and labels
  theme_bw() 

Titling a Stacked Frequency Plot

Note how I titled my plot above: “Distribution of Beds across Hospitals in the US that are Open by Hospital Type” Consider again what makes each observation unique. Here I am counting the observations by number of Beds and Hospital Type. A good formula for titling stacked frequency plots is as follows:

Distribution of [x-axis variable name] across _____ by [col variable name]

The blank should be filled with your unit of observation. The [x-axis variable name] should be your x-label, “Count of ______” (filled the same as above) should be your y-label, and the [col variable name] should be your col-label.

What if I have multi-dimensional data?

If this is the case I would encourage you to include one of the variables in your unique key in the col variable. For instance, if world_health_econ is unique by country and year, I can include year as the col variable below to visualize how the frequency of countries with various life expectancies changes over time.

#Run this code chunk.

#df %>% ggplot(aes(x = NUMERIC_VARIABLE, col = CATEGORICAL_VARIABLE)) + geom_freqpoly(binwidth = 1)

world_health_econ %>% 
  ggplot(aes(x = life_exp, col = as.factor(year))) + 
  geom_freqpoly(binwidth = 5, boundary = 0) +
  theme_bw() +
  labs(title = "Frequency of Life Expectancies across Countries by Year", x = "Life Expectancy", y = "Count of Countries", col = "Life Expectancy") 

Note that this is one plot that is particularly susceptible to missing data. If certain countries did not report data in certain years, the count of countries in a bracket will appear lower, not necessarily because fewer countries fell within a certain life expectancy bracket, but because fewer countries reported that life expectancy.

Alternatively, you could zoom in to one value in one of the variables in you unique key, filtering to a specific subset of observations and then divide by a different categorical variable.

#Run this code chunk.

#df %>% ggplot(aes(x = NUMERIC_VARIABLE, col = CATEGORICAL_VARIABLE)) + geom_freqpoly(binwidth = 1)

world_health_econ %>% 
  filter(year == max(year, na.rm = TRUE)) %>%
  ggplot(aes(x = life_exp, col = continent)) + 
  geom_freqpoly(binwidth = 5, boundary = 0) +
  theme_bw() +
  labs(title = "Frequency of Life Expectancies across Countries by Continent in 2010", x = "Life Expectancy", y = "Count of Countries", col = "Continent")

Point plots

Point plots display the relationship between a categorical variable and a numeric variable. For instance, the plot below displays a relationship between hospital type and the number of beds at the hospital. Notably, unlike the plots we have been viewing until now, with point plots, we see a point for every observation in the dataset. Because point plots display every observation (rather than aggregating them into other polygons and lines), they are particularly good for seeing outliers in the data. However, with large datasets, this also can mean that points will overlap. Note that the first plot below exhibits overplotting - when the data represented on a plot overlaps, making it difficult to discern one point from the next. There are various tools available to deal with over-plotting. You can reduce the size of points on the plot, increase their transparency, or set them to slightly offset each other (known as adding jitter). We do all three in the second plot below.

#Run this code chunk.

#df %>% ggplot(aes(x = CATEGORICAL_VARIABLE, y = NUMERIC_VARIABLE)) + geom_point()

hospitals %>% 
  filter(STATUS == "OPEN") %>%
  ggplot(aes(x = TYPE, y = BEDS)) + 
  geom_point() +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 45, hjust=1)) +
  labs(title = "Number of Beds in Hospitals by Type", x = "Type", y = "Number of Beds")



hospitals %>% 
  filter(STATUS == "OPEN") %>%
  ggplot(aes(x = TYPE, y = BEDS)) + 
  geom_jitter(size = 0.5, alpha = 0.1) + #Change geom_point to geom_jitter, reduce the size, add transparency for overplotting
  theme_bw() +
  theme(axis.text.x = element_text(angle = 45, hjust=1)) +
  labs(title = "Number of Beds in Hospitals by Type", x = "Type", y = "Number of Beds")

Titling a Point Plot

Note how I titled my plot above: “Number of Beds in Hospitals in the US that are Open by Type” Here I am displaying the number of beds by Type. A good formula for titling point plots is as follows:

Number/Measure of [y-axis variable name] in _____ by [x-axis variable name]

The blank should be filled with your unit of observation. The [x-axis variable name] should be your x-label and “Number/Measure of [y-axis variable name]” should be your y-label.

What if I have multi-dimensional data?

If this is the case I would encourage you to filter your data as you have been doing elsewhere. For instance if cases is unique by county, state, and date, I can filter to the most recent date before creating a point plot of the cases by state. This will show me the differences in cases across the third variable in my unique key - county. Note that to create my title, I will need to create a string that includes the most recent date. I also do this below, using summarize (a function we will go over next week).

#Run this code chunk.

plot_title <- paste("Covid-19 Cases per County by State as of", cases %>% summarize(date = max(date, na.rm = TRUE)) %>% pull())

cases %>% 
  filter(date == max(date, na.rm = TRUE)) %>%
  ggplot(aes(x = state, y = cases)) + 
  geom_point(size = 3, alpha = 0.25) +  
  theme_bw() +
  theme(axis.text.x = element_text(angle = 45, hjust=1)) +
  labs(title = plot_title, x = "State", y = "Covid-19 Cases") 

From this plot, I can see the states with counties with particularly high case counts by the most recent reporting date.

Scatterplots

Scatterplots display the relationship or correlation between two numeric variables. For instance, below we plot the relationship between the BEDS variable and the POPULATION variable in the hospitals dataset.

There are different ways to characterize the correlations between variables in data. We may consider the strength of a correlation, the shape of a correlation, and whether the correlation is positive or negative.

  • Two variables in a scatterplot can be said to have a strong correlation when points are clustered closely to a central line or curve. The more scattered throughout the plot the points are, the weaker the correlation.
  • Two variables in a scatterplot can be said to have a linear correlation when the scatterplot tends to produce a straight line. This means that the rate of change between two variables is steady. However, when a scatterplot produces a curve, this indicates that the rate of change between two variables is not as constant.
  • Two variables in a scatterplot can be said to have a positive correlation when the points move upward from the bottom left corner towards the top right corner of the plot. This means that as values in variable increases, the values in the other variable also increase. When points move downward from the top left corner to the bottom right corner of the plot, we can say that the variables negatively correlation. This means that as values in variable increases, the values in the other variable decreases.
#Run this code chunk.

#ggplot(df, aes(x = NUMERIC_VARIABLE, y = NUMERIC_VARIABLE)) + geom_point()

hospitals %>% 
  filter(STATUS == "OPEN") %>%
  ggplot(aes(x = BEDS, y = POPULATION)) + 
  geom_point(size = 3, alpha = 0.1) +
  theme_bw() +
  labs(title = "Relationship between Hospital Beds and Population in the US", x = "Beds", y = "Population") 

Note that this plot has a strong, linear positive correlation. As BEDS increase in this variable, POPULATION also tends to increase.

Titling a Scatterplot

Note how I titled my plot above: “Relationship between Hospital Beds and Population in the US” A good formula for titling scatterplots is as follows:

Relationship between _____ [x-axis variable name] and [y-axis variable name]

The blank should be filled with your unit of observation. The [x-axis variable name] should be your x-label and [y-axis variable name]" should be your y-label.

What if I have multi-dimensional data?

If this is the case I would encourage you to filter your plot to one value in one of the variables that make up your unique key. For instance if world_health_econ is unique by country and year, I can filter to the most recent year before creating a point plot of the private share of health spending by continent.

#Run this code chunk.

#ggplot(df, aes(x = NUMERIC_VARIABLE, y = NUMERIC_VARIABLE)) + geom_point()

world_health_econ %>% 
  filter(year == max(year, na.rm = TRUE)) %>%
  ggplot(aes(x = tot_health_sp_pp, y = life_exp, size = pop, col = continent)) + 
  geom_point(shape = 21, stroke = 1) +
  labs(title = "Relationship between Country Total Health Spending Per Person and Life Expectancy", x = "Total Health Spending Per Person", y = "Life Expectancy", size = "Population", col = "Continent") + 
  theme_bw() +
  scale_size_continuous(range = c(1, 10), labels = scales::comma)

Note that this plot has a weaker, curvilinear, positive correlation. As Total Health Spending per Person increases in this variable, Life Expectancy also tends to increase, but the rate of change at which it increases is not constant.

Have you heard the quip “Correlation does not equal causation”? This is particularly important to consider here. In lab 7, we will examine some confounding variables that may be mediating how values appear to correlate in our data. For now, it’s important to note that just because we see a correlation between total health spending and life expectancy does not mean that increasing total health spending in a country causes life expectancy to increase. This is of course a complex issue with lots of other variables involved.

Produce two plots that represent co-variation in your dataset.

You need not include every plot I described above. Be sure to zoom in to certain observations in your data if you have multi-dimensional data.

Plot Co-Variation in your Dataset

#Fill the code for plot 1 here. Add a title and labels to your plots. Be sure to adjust for overplotting.

Copy and paste the definitions of the variables you selected from the data dictionary below.

Fill your response here. 
  1. QUERY: Below, write a research question that the code you just ran is designed to be able to answer. Make sure you phrase your question directly in relation to the results of your code. In other words, you have the answer; now come up with the question. Consider this a check on whether you understand what the code above is doing. If you are unsure how to compose this question, you probably want to study the functions above a bit more closely.
Fill your response here. 

Are there any other variables in your dataset that you need to take into consideration before directing this analysis towards answering that question? In other words, do you need to zoom into any specific areas of the dataset (by filtering) in order to appropriately address this question? If so, which? (For instance, for the hospitals dataset we needed to filter to hospitals that were OPEN in order to address questions about infrastructure). Briefly note this below.

Fill your response here. 
  1. SUMMARIZE: Reviewing the output of your code, summarize one thing that you learn about your topic from running this code chunk. In other words, what is one thing that the results of this analysis empirically tell us about the topic? Be specific, considering the geographic, temporal, and topical scope of your data.
Fill your response here. 
  1. INTERPRET: Now imagine you were reporting your findings to a decision-maker on your topic. Describe to that decision-maker why they should care. In other words, interpret what is important about this finding.
Fill your response here. 
  1. REFLECT: What else would we need to know to fully address this question? Knowing what you know about how the data was collected and aggregated, what uncertainties remain in regards to addressing this question? In what ways is the analysis limited by the scope of the data’s definitions or categories?
Fill response here. 

Plot Co-Variation in your Dataset an Alternative Way

#Fill the code for plot 2 here. Add a title and labels to your plots. Be sure to adjust for overplotting.

Copy and paste the definitions of the variables you selected from the data dictionary below.

Fill your response here. 
  1. QUERY: Below, write a research question that the code you just ran is designed to be able to answer. Make sure you phrase your question directly in relation to the results of your code. In other words, you have the answer; now come up with the question. Consider this a check on whether you understand what the code above is doing. If you are unsure how to compose this question, you probably want to study the functions above a bit more closely.
Fill your response here. 

Are there any other variables in your dataset that you need to take into consideration before directing this analysis towards answering that question? In other words, do you need to zoom into any specific areas of the dataset (by filtering) in order to appropriately address this question? If so, which? (For instance, for the hospitals dataset we needed to filter to hospitals that were OPEN in order to address questions about infrastructure). Briefly note this below.

Fill your response here. 
  1. SUMMARIZE: Reviewing the output of your code, summarize one thing that you learn about your topic from running this code chunk. In other words, what is one thing that the results of this analysis empirically tell us about the topic? Be specific, considering the geographic, temporal, and topical scope of your data.
Fill your response here. 
  1. INTERPRET: Now imagine you were reporting your findings to a decision-maker on your topic. Describe to that decision-maker why they should care. In other words, interpret what is important about this finding.
Fill your response here. 
  1. REFLECT: What else would we need to know to fully address this question? Knowing what you know about how the data was collected and aggregated, what uncertainties remain in regards to addressing this question? In what ways is the analysis limited by the scope of the data’s definitions or categories?
Fill response here. 
LS0tCnRpdGxlOiAiTGFiIDUgLSBEYXRhIFZhcmlhdGlvbiBhbmQgQ28tVmFyaWF0aW9uIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDMKICAgIHRvY19mbG9hdDogeWVzCiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogJzMnCmVkaXRvcl9vcHRpb25zOgogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUKLS0tCgojIyBJbnN0cnVjdGlvbnMgYW5kIE92ZXJ2aWV3CgpJbiB0aGlzIGFzc2lnbm1lbnQsIHdlIHdpbGwgZXhhbWluZSB3aGF0IG1ha2VzIG9ic2VydmF0aW9ucyBpbiBvdXIgZGF0YXNldCBib3RoIHNpbWlsYXIgYW5kIGRpZmZlcmVudC4gVG8gZG8gc28sIHdlIHdpbGwgY29uc2lkZXIgaG93IHZhbHVlcyBpbiB0aGUgZGF0YXNldCBhcmUgZGlzdHJpYnV0ZWQgYWNyb3NzIG9ic2VydmF0aW9ucywgYW5kIGhvdyB0aG9zZSB2YWx1ZXMgdmFyeSB3aGVuIGNvbnNpZGVyZWQgaW4gcmVsYXRpb24gdG8gb3RoZXIgdmFyaWFibGVzIGluIHRoZSBkYXRhc2V0LiBJbiB0aGlzIHNlbnNlLCB3ZSB3aWxsIHByYWN0aWNlIGdyYXBoaWNhbGx5IHJlcHJlc2VudGluZyB2YXJpYXRpb24gYW5kIGNvLXZhcmlhdGlvbiBpbiBhIGRhdGFzZXQuIFRvIGJlZ2luIHlvdSB3aWxsIG5lZWQgdG8gaW1wb3J0IGFuZCBjbGVhbiB5b3VyIGRhdGFzZXQuIFlvdSBtYXkgcmVmZXJlbmNlIGxhc3Qgd2VlaydzIGxhYiB0byBoZWxwIHdpdGggdGhpcy4gQWZ0ZXIgdGhpcywgeW91IHNob3VsZCBmb2xsb3cgdGhlIHByb21wdHMgYW5kIGNvbXBsZXRlIHRoZSBzaG9ydCBhbnN3ZXIgcXVlc3Rpb25zLiBGb2xsb3dpbmcgZWFjaCBjb2RlIGNodW5rIHlvdSBjb21wb3NlIGFuZCBydW4gaW4gdGhpcyBhc3NpZ25tZW50LCBJIHdpbGwgYXNrIHlvdSB0byBkbyBmb3VyIHRoaW5nczogMSkgcXVlcnksIDIpIHN1bW1hcml6ZSksIDMpIGludGVycHJldCwgYW5kIDQpIHJlZmxlY3QuIAoKMS4gUVVFUlk6IEknbSBnb2luZyB0byBhc2sgeW91IHRvIHdyaXRlIGEgcXVlc3Rpb24gdGhhdCB0aGUgY29kZSB0aGF0IHlvdSBjb21wb3NlZCBhbmQgcmFuIGlzIGRlc2lnbmVkIHRvIGFuc3dlci4gVGhpcyBpcyBhbiBvcHBvcnR1bml0eSB0byByZWZsZWN0IG9uIHdoZXRoZXIgeW91IHVuZGVyc3RhbmQgd2hhdCB0aGUgY29kZSBpcyBhY3R1YWxseSBkb2luZy4gSWYgeW91IGFyZSBzdHJ1Z2dsaW5nIHRvIGNvbWUgdXAgd2l0aCBhIHF1ZXN0aW9uLCBpdCBpcyBtb3N0IGxpa2VseSBiZWNhdXNlIHlvdSBhcmUgbm90IGZ1bGx5IGNlcnRhaW4gd2hhdCB0aGUgY29kZSBpcyBkb2luZy4gSWYgdGhpcyBpcyB0aGUgY2FzZSwgeW91IG1heSBuZWVkIHRvIHN0dWR5IHRoZSBmdW5jdGlvbnMgYSBiaXQgbW9yZS4gCjIuIFNVTU1BUklaRTogSSdtIHRoZW4gZ29pbmcgdG8gYXNrIHlvdSB0byBzdW1tYXJpemUgb25lIHRoaW5nIHRoYXQgeW91IGxlYXJuIGZyb20geW91ciBkYXRhIGJhc2VkIG9uIHRoZSBvdXRwdXQgb2YgdGhlIGNvZGUuIFdoYXQgZG8gdGhlIHJlc3VsdHMgdGVsbCB5b3UgZW1waXJpY2FsbHk/IEhlcmUgeW91IHdpbGwgd2FudCB0byBiZSBzcGVjaWZpYyBtYWtpbmcgc3VyZSB5b3VyIHN1bW1hcnkgY29uc2lkZXJzIHRoZSBzY29wZSBvZiB0aGUgZGF0YSAtIGl0cyBnZW9ncmFwaGljLCB0ZW1wb3JhbCwgYW5kIHRvcGljYWwgYm91bmRzLiAKMy4gSU5URVJQUkVUOiBJJ20gZ29pbmcgdG8gYXNrIHlvdSB0byB0aGVuIGludGVycHJldCB5b3VyIGRhdGEsIGNvbnNpZGVyaW5nIHdoeSB0aGUgcmVzdWx0IG1hdHRlcnMgaW4gYSBicm9hZGVyIHNlbnNlLiBJZiB5b3Ugd2VyZSB0byBjb252ZXkgdGhlIHJlc3VsdHMgdG8gYSBkZWNpc2lvbi1tYWtlciwgaG93IHdvdWxkIHlvdSBjb252ZXkgdG8gdGhlbSB0aGUgc2lnbmlmaWNhbmNlIG9mIHRoZSByZXN1bHQ/IFdoYXQgc2hvdWxkIHRoZSBudW1iZXJzIG1ha2UgdXMgdGhpbms/IFdoYXQgcXVlc3Rpb25zIGRvIHRoZXkgYnJpbmcgdXA/CjQuIFJFRkxFQ1Q6IEZpbmFsbHksIEknbSBnb2luZyB0byBhc2sgeW91IHRvIHJlZmxlY3Qgb24gc29tZSBvZiB0aGUgbGltaXRhdGlvbnMgdG8gYW5zd2VyaW5nIHRoZSBxdWVzdGlvbnMgdGhhdCB5b3UgcG9zZWQgd2l0aCB0aGUgZGF0YSBhdCBoYW5kLiBLbm93aW5nIHdoYXQgeW91IGtub3cgYWJvdXQgaG93IHRoZSBkYXRhIHdhcyBjb2xsZWN0ZWQgYW5kIGFnZ3JlZ2F0ZWQsIHdoYXQgdW5jZXJ0YWludGllcyByZW1haW4gaW4gcmVnYXJkcyB0byBhZGRyZXNzaW5nIHRoaXMgcXVlc3Rpb24/IEluIHdoYXQgd2F5cyBpcyB0aGUgYW5hbHlzaXMgbGltaXRlZCBieSB0aGUgc2NvcGUgb2YgdGhlIGRhdGEncyBkZWZpbml0aW9ucyBvciBjYXRlZ29yaWVzPwoKIyMgR2V0dGluZyBTdGFydGVkCgojIyMgTG9hZCB0aGUgcmVsZXZhbnQgbGlicmFyaWVzCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkobHVicmlkYXRlKQpgYGAKCiMjIyBJbXBvcnQgYW5kIGNsZWFuIGV4YW1wbGUgZGF0YXNldHMgCgpgYGB7cn0KaG9zcGl0YWxzIDwtIHJlYWQuY3N2KCJkYXRhc2V0cy9Ib3NwaXRhbHMuY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKd29ybGRfaGVhbHRoX2Vjb24gPC0gcmVhZC5jc3YoImRhdGFzZXRzL3dvcmxkX2hlYWx0aF9lY29uLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCmNhc2VzIDwtIHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vbnl0aW1lcy9jb3ZpZC0xOS1kYXRhL21hc3Rlci91cy1jb3VudGllcy5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgpob3NwaXRhbHMkWklQIDwtIGFzLmNoYXJhY3Rlcihob3NwaXRhbHMkWklQKQoKaG9zcGl0YWxzJFpJUCA8LSBzdHJfcGFkKGhvc3BpdGFscyRaSVAsIDUsIHBhZCA9ICIwIikgCgppcy5uYShob3NwaXRhbHMpIDwtIGhvc3BpdGFscyA9PSAiTk9UIEFWQUlMQUJMRSIKaXMubmEoaG9zcGl0YWxzKSA8LSBob3NwaXRhbHMgPT0gLTk5OQoKaG9zcGl0YWxzJFNPVVJDRURBVEUgPC0geW1kX2htcyhob3NwaXRhbHMkU09VUkNFREFURSkKaG9zcGl0YWxzJFZBTF9EQVRFIDwtIHltZF9obXMoaG9zcGl0YWxzJFZBTF9EQVRFKQpjYXNlcyRkYXRlIDwtIHltZChjYXNlcyRkYXRlKQpgYGAKCiMjIyBJbXBvcnQgYW5kIGNsZWFuIHlvdXIgZGF0YXNldC4gCgpgYGB7cn0KI0NvcHkgYW5kIHBhc3RlIHRoZSBjb2RlIGZyb20gbGFiIDQgdG8gYm90aCBpbXBvcnQgYW5kIGNsZWFuIHlvdXIgZGF0YXNldCBoZXJlLiAKYGBgCgojIyBab29taW5nIGluIHRvIEV4cGxvcmUgRmlsdGVyZWQgRGF0YQoKQmVmb3JlIHdlIGdldCBpbnRvIGhvdyB0byBncmFwaGljYWxseSByZXByZXNlbnQgdmFyaWF0aW9uIGFuZCBjby12YXJpYXRpb24sIHdlIHdpbGwgZmlyc3QgbmVlZCB0byBjb25zaWRlciB3aGF0IHNldHMgb2Ygb2JzZXJ2YXRpb25zIHdlIHdpbGwgYmUgY29tcGFyaW5nLiBPZnRlbiBpbiBkYXRhIGV4cGxvcmF0aW9uLCB3ZSBkbyBub3QganVzdCB3YW50IHRvIGV4YW1pbmUgdGhlIGRhdGFzZXQgYXMgYSB3aG9sZSwgYnV0IHRvIGFsc28gZXhhbWluZSBob3cgdmFsdWVzLCBjYWxjdWxhdGlvbnMsIGFuZCBwbG90cyBjaGFuZ2Ugd2hlbiB3ZSB6b29tIGluIHRvIG9uZSBzcGVjaWZpYyBzZXQgb2Ygb2JzZXJ2YXRpb25zIGluIHRoZSBkYXRhc2V0LiBMYXN0IHdlZWssIHdlIGV4cGxvcmVkIGhvdyB5b3VyIGRhdGEgd2FzIGRlZmluZWQsIGhvdyBpdCB3YXMgY2F0ZWdvcml6ZWQsIGFuZCBob3cgbWlzc2luZyB2YWx1ZXMgd2VyZSByZXByZXNlbnRlZC4gVGhyb3VnaCB0aGlzIGV4ZXJjaXNlLCB3ZSB3ZXJlIGFibGUgdG8gZGV2ZWxvcCBhIGdlbmVyYWwgb3ZlcnZpZXcgb2YgdGhlIG9ic2VydmF0aW9ucywgdmFyaWFibGVzLCBhbmQgdmFsdWVzIGluIG91ciBkYXRhc2V0cy4gS25vd2luZyB0aGlzIHdlIGxpa2VseSBoYXZlIGEgYmV0dGVyIHNlbnNlIG9mIGFyZWFzIHdlIHdhbnQgdG8gYmUgYWJsZSB0byB6b29tIGludG8gYW5kIGV4cGxvcmUgaW4gb3VyIGRhdGEuIEFzIHdlIHByZXBhcmUgdG8gdmlzdWFsaXplIHZhcmlhdGlvbiBhbmQgY28tdmFyaWF0aW9uIGluIHRoZSBkYXRhc2V0LCBsZXQncyBmaXJzdCBnbyBvdmVyIGhvdyB3ZSBjYW4gYm90aCB6b29tIGluIG9uIGNlcnRhaW4gb2JzZXJ2YXRpb25zLiAKCiMjIyBGaWx0ZXJpbmcgdG8gYSBDYXRlZ29yeQoKRmlsdGVyaW5nIGlzIG9uZSB3YXkgd2UgY2FuIHpvb20gaW4gb24gb3VyIGRhdGEgLSBleHBsb3Jpbmcgb25seSB0aG9zZSBvYnNlcnZhdGlvbnMgdGhhdCBtZWV0IGEgcGFydGljdWxhciBjcml0ZXJpYS4KCkZvciBpbnN0YW5jZSwgbGFzdCB3ZWVrIHdlIGxlYXJuZWQgYWJvdmUgdGhhdCBvbmUgY3JpdGVyaWEgZm9yIGJlaW5nIGRlc2lnbmF0ZWQgYXMgYSBDcml0aWNhbCBBY2Nlc3MgSG9zcGl0YWwgaXMgdGhhdCB0aGUgaG9zcGl0YWwgbXVzdCBoYXZlIDI1IG9yIGZld2VyIGlucGF0aWVudCBiZWRzLiBXZSBtYXkgd2FudCB0byBzZWUgaG93IHRoZSB2YWx1ZXMgZm9yIEJFRFMgY2hhbmdlIHdoZW4gd2UgZmlsdGVyIHRvIChvciB6b29tIGludG8pIGp1c3QgdGhvc2Ugb2JzZXJ2YXRpb25zIHJlcHJlc2VudGluZyBjcml0aWNhbCBhY2Nlc3MgaG9zcGl0YWxzLiBOb3RpY2UgaG93IHdlIGNhbiBjb21iaW5lIGFueSBudW1iZXIgb2YgZHBseXIgdmVyYnMgdXNpbmcgdGhlIHBpcGUgKCU+JSkuIEJlbG93IEkgd2lsbCBmaWx0ZXIgdG8gcm93cyB0aGF0IG1lZXQgYSBjcml0ZXJpYSBhbmQgdGhlbiBzZWxlY3QgYSB2YXJpYWJsZSB0byBleGFtaW5lIGZyb20gdGhlIGZpbHRlcmVkIGRhdGEuCgpgYGB7cn0KI1J1biB0aGlzIGNvZGUgY2h1bmsuCgojZGYgJT4lIGZpbHRlcihDQVRFR09SSUNBTF9WQVJJQUJMRSA9PSAiVkFMVUUiKSAlPiUgc2VsZWN0KENBVEVHT1JJQ0FMX1ZBUklBQkxFKQpob3NwaXRhbHMgJT4lIGZpbHRlcihUWVBFID09ICJDUklUSUNBTCBBQ0NFU1MiKSAlPiUgc2VsZWN0KE5BTUUsIEJFRFMpCmhvc3BpdGFscyAlPiUgZmlsdGVyKFRZUEUgPT0gIkNSSVRJQ0FMIEFDQ0VTUyIpICU+JSBzZWxlY3QoQkVEUykgJT4lIHN1bW1hcnkoKQpgYGAKMS4gUVVFUlk6IFRoaXMgYW5hbHlzaXMgbWlnaHQgaGVscCB1cyBhbnN3ZXIgdGhlIHF1ZXN0aW9uOiBEbyBhbGwgY3JpdGljYWwgYWNjZXNzIGhvc3BpdGFscyBpbiB0aGUgVVMgaGF2ZSAyNSBiZWRzIG9yIGZld2VyLCBhbmQgd2hhdCBpcyBhdmVyYWdlIG51bWJlciBvZiBiZWRzIGF0IGEgY3JpdGljYWwgYWNjZXNzIGhvc3BpdGFsPwoyLiBTVU1NQVJJWkU6IFdlIGNhbiBzZWUgdGhhdCB0aGVyZSBhcmUgc29tZSBob3NwaXRhbHMgaW4gdGhlIFVTIHRoYXQgaGF2ZSBiZWVuIGRlc2lnbmF0ZWQgYXMgY3JpdGljYWwgYWNjZXNzIGhvc3BpdGFscyB0aGF0IGhhdmUgbW9yZSB0aGFuIDI1IGJlZHMsIHRoYXQgYXQgbGVhc3Qgb25lIGNyaXRpY2FsIGFjY2VzcyBob3NwaXRhbCBoYXMgYXMgbWFueSBhcyAyODYgYmVkcywgdGhhdCBhbGwgY3JpdGljYWwgYWNjZXNzIGhvc3BpdGFscyBoYXZlIGF0IGxlYXN0IHRocmVlIGJlZHMsIGFuZCB0aGF0IHRoZSBhdmVyYWdlIG51bWJlciBvZiBiZWRzIGhvdmVycyBhcm91bmQgMjUuIAozLiBJTlRFUlBSRVQ6IFNpbmNlIGNyaXRpY2FsIGFjY2VzcyBob3NwaXRhbHMgYXJlIGxlZ2FsbHkgc3VwcG9zZWQgdG8gaGF2ZSAyNSBiZWRzIG9yIGZld2VyLCB3ZSBtYXkgd2FudCB0byBsb29rIGludG8gd2hpY2ggY3JpdGljYWwgYWNjZXNzIGhvc3BpdGFscyBoYXZlIG1vcmUgdGhhbiAyNSBiZWRzLiBUaGlzIG1heSBpbmRpY2F0ZSB0aGF0IHRoZXNlIGhvc3BpdGFscyBhcmUgbm90IG1lZXRpbmcgdGhlIHJlcXVpcmVtZW50cyB0byByZWNlaXZlIGZlZGVyYWwgZnVuZGluZyBvciB0aGF0IHRoZXJlIGlzIGFuIGlzc3VlIHdpdGggdGhlIGRhdGEgYmVpbmcgcmVjb3JkZWQuIAoKYGBge3J9CiNSdW4gdGhpcyBjb2RlIGNodW5rLgoKaG9zcGl0YWxzICU+JSBmaWx0ZXIoVFlQRSA9PSAiQ1JJVElDQUwgQUNDRVNTIiAmIEJFRFMgPiAyNSkgJT4lIHNlbGVjdChOQU1FLCBUWVBFLCBTVEFURSwgQkVEUywgU1RBVFVTKQpgYGAKCjQuIFJFRkxFQ1Q6IFRoZXJlIGFyZSAxODAgY3JpdGljYWwgYWNjZXNzIGhvc3BpdGFscyBpbiB0aGUgZGF0YXNldCB3aXRoIG1vcmUgdGhhbiAyNSBiZWRzLiBUaGlzIGJyaW5ncyB1cCBxdWVzdGlvbiBvZiBob3cgdGhlIEhJRkxEIHRlYW0gZGV0ZXJtaW5lZCAxKSB0aGF0IHRoZSBob3NwaXRhbCB3YXMgYSBjcml0aWNhbCBhY2Nlc3MgaG9zcGl0YWwgYW5kIDIpIHRoZSBudW1iZXIgb2YgYmVkcy4gIElmIHRoZSBob3NwaXRhbCB3YXMgcGFydCBvZiBhIGNvbXBsZXggd2l0aCBtdWx0aXBsZSBmYWNpbGl0aWVzIGFuZCBqdXN0IG9uZSBvZiB0aG9zZSBmYWNpbGl0aWVzIHdhcyBjcml0aWNhbCBhY2Nlc3MsIHdhcyB0aGUgaG9zcGl0YWwgY2xhc3NlZCBhcyBjcml0aWNhbCBhY2Nlc3M/IElmIHNvLCBob3cgd2VyZSBiZWRzIHRoZW4gY2FsY3VsYXRlZD8gV2hhdCB3YXMgdGhlIHNvdXJjZSBvZiB0aGUgYmVkIGNvdW50IC0gdGhlIGhvc3BpdGFsJ3Mgd2Vic2l0ZT8gU3RhdGUgb3Igb3RoZXIgZ292ZXJubWVudCBkb2N1bWVudHM/IFdlcmUgdGhlc2Ugc291cmNlcyByZWxpYWJsZT8KCiMjIyBGaWx0ZXJpbmcgdG8gTnVtZXJpYyBPYnNlcnZhdGlvbnMgQWJvdmUgb3IgQmVsb3cgYSBUaHJlc2hvbGQKCldlIG1heSBhbHNvIHdhbnQgdG8gZXhwbG9yZSBpZiB0aGVyZSBhcmUgY2VydGFpbiBob3NwaXRhbCBvd25lcnNoaXAgbW9kZWxzIHRoYXQgdGVuZCB0byBoYXZlIG1vcmUgYmVkcy4gVG8gZG8gc28sIHdlIHdvdWxkIGZpbHRlciB0aGUgZGF0YSB0byB0aG9zZSBvYnNlcnZhdGlvbnMgd2hlcmUgQkVEUyBpcyBncmVhdGVyIHRoYW4gYSBjZXJ0YWluIHRocmVzaG9sZCAtIGxldCdzIHNheSAxMjAwLiBUaGUgZmlyc3QgdGltZSBJIGRvIHRoaXMgYmVsb3csIEkgc2VsZWN0KCkgdGhlIE5BTUUgb2YgdGhlIGhvc3BpdGFsIGFuZCB0aGUgT1dORVIuIFRoaXMgc2hvd3MgZXZlcnkgaG9zcGl0YWwgd2l0aCBtb3JlIHRoYW4gMTIwMCBiZWRzLCBhbG9uZyB3aXRoIGl0cyBPV05FUiB0eXBlLiBIb3dldmVyLCB3aGF0IGlmIEkgb25seSB3YW50ZWQgdG8ga25vdyB3aGljaCBvd25lciB0eXBlcyBoYWQgaG9zcGl0YWxzIHdpdGggbW9yZSB0aGFuIDEwMDAgYmVkcz8gSSB3b3VsZG4ndCBuZWNlc3NhcmlseSB3YW50IHRvIHNlbGVjdCgpIE9XTkVSIGluIHRoaXMgY2FzZSBiZWNhdXNlIHRoaXMgd291bGQgc2hvdyBtZSB0aGUgb3duZXIgZm9yIGV2ZXJ5IG9ic2VydmF0aW9uIGluIG15IGZpbHRlcmVkIGRhdGEuIEFzIHlvdSBjYW4gc2VlIGJlbG93LCB0aGlzIG1lYW5zIHRoYXQgR09WRVJOTUVOVC1TVEFURSB3b3VsZCBhcHBlYXIgMTMgdGltZXMhIEluc3RlYWQsIEkgd291bGQgd2FudCB0byBjaGVjayB0aGUgZGlzdGluY3QoKSBPV05FUiBpbiB0aGUgZmlsdGVyZWQgZGF0YS4gQ2hlY2sgb3V0IGhvdyBJIGRvIHRoaXMgYmVsb3cuIAoKYGBge3J9CiNSdW4gdGhpcyBjb2RlIGNodW5rLgoKI2RmICU+JSBmaWx0ZXIoTlVNQkVSSUNfVkFSSUFCTEUgPiBWQUxVRSkgJT4lIGRpc3RpbmN0KENBVEVHT1JJQ0FMX1ZBUklBQkxFKQoKI0xpc3RzIG5hbWUgYW5kIG93bmVyIG9mIGhvc3BpdGFscyB3aXRoIG1vcmUgdGhhbiAxMDAwIGJlZHMuCmhvc3BpdGFscyAlPiUgZmlsdGVyKEJFRFMgPiAxMDAwKSAlPiUgc2VsZWN0KE5BTUUsIE9XTkVSKSAKCiNMaXN0cyBvd25lciBmb3IgZXZlcnkgaG9zcGl0YWwgd2l0aCBtb3JlIHRoYW4gMTAwMCBiZWRzIGluIHRoZSBkYXRhc2V0Cmhvc3BpdGFscyAlPiUgZmlsdGVyKEJFRFMgPiAxMDAwKSAlPiUgc2VsZWN0KE9XTkVSKSAKCiNMaXN0cyB0aGUgb3duZXJzIHdpdGggbW9yZSB0aGFuIDEwMDAgYmVkcwpob3NwaXRhbHMgJT4lIGZpbHRlcihCRURTID4gMTAwMCkgJT4lIGRpc3RpbmN0KE9XTkVSKSAKYGBgCgoxLiBRVUVSWTogV2hpY2ggb3duZXJzaGlwIG1vZGVscyBoYXZlIGF0IGxlYXN0IG9uZSBob3NwaXRhbCB3aXRoIG1vcmUgdGhhbiAxMDAwIGJlZHM/CjIuIFNVTU1BUklaRTogV2UgY2FuIHNlZSB0aGF0IDMgb3duZXJzaGlwIG1vZGVscyBoYXZlIGhvc3BpdGFscyB3aXRoIG1vcmUgdGhhbiAxMDAwIGJlZHMsIGluY2x1ZGluZyBzdGF0ZSBnb3Zlcm5tZW50IGhvc3BpdGFscywgZGlzdHJpY3QgZ292ZXJubWVudCBob3NwaXRhbHMsIGFuZCBub24tcHJvZml0IGhvc3BpdGFscy4KMy4gSU5URVJQUkVUOiBUaGlzIGluZGljYXRlcyB0aGF0IHRoZSBsYXJnZXN0IGhvc3BpdGFscyBpbiB0aGUgY291bnRyeSB0ZW5kIHRvIGJlIGRpc3RyaWN0IGFuZCBzdGF0ZSBnb3Zlcm5tZW50IGhvc3BpdGFscyBhbmQgbm9uLXByb2ZpdCBob3NwaXRhbHMsIHdoZXJlYXMsIGFjY29yZGluZyB0byB0aGlzIGRhdGEsIHRoZXJlIGFyZSBubyBwcml2YXRlIGhvc3BpdGFscywgZmVkZXJhbCwgb3IgbG9jYWwgaG9zcGl0YWxzIHdpdGggbW9yZSB0aGFuIDEwMDAgYmVkcy4gQXMgdGhlIFVTIGZlZGVyYWwgZ292ZXJubWVudCBjb25zaWRlcnMgaG93IHRvIGRpc3RyaWJ1dGUgZmVkZXJhbCBhaWQgdG8gaG9zcGl0YWxzLCB0aGlzIGlzIG9uZSAodmVyeSB0aW55KSBzdGVwIHRvd2FyZHMgdW5kZXJzdGFuZGluZyB0aGUgdmFyaW91cyByZWxhdGlvbnNoaXBzIGJldHdlZW4gaG9zcGl0YWwgYnVzaW5lc3MgbW9kZWxzIGFuZCBwYXRpZW50IGNhcGFjaXR5LiBDb25zaWRlciBzb21lIG9mIHRoZSBbY29uc2VxdWVuY2VzXShodHRwczovL3d3dy5tb2Rlcm5oZWFsdGhjYXJlLmNvbS9maW5hbmNlL3doeS1zb21lLXNtYWxsZXItaG9zcGl0YWxzLXRyZWF0aW5nLWxvdHMtY292aWQtcGF0aWVudHMtYXJlbnQtZ2V0dGluZy1oaWdoLWltcGFjdC1mZWRlcmFsKSBvZiB0aGVzZSBkZWNpc2lvbnMuCjQuIFJFRkxFQ1Q6IFdoYXQgY291bnRzIGFzIGEgYmVkIGluIHRoZSBob3NwaXRhbHMgZGF0YXNldD8gRG8gYW1idWxhdG9yeSBiZWRzIGNvdW50PyBBcmUgYmVkcyBjYWxjdWxhdGVkIGJhc2VkIG9uIHRoZSBudW1iZXIgb2YgYWN0dWFsIGNvdHMgaW4gdGhlIGhvc3BpdGFsLCBvciB0aGUgbnVtYmVyIG9mIHNwYWNlcyBhdmFpbGFibGUgZm9yIGJlZHM/IERvZXMgYSBiZWQgY291bnQgYXNzdW1lIHRoYXQgdGhlcmUgYXJlIGVub3VnaCBzdGFmZiBhbmQgcmVzb3VyY2VzIHRvIHN1cHBvcnQgdGhhdCBtYW55IHBhdGllbnRzIGluIHRob3NlIGJlZHM/CgojIyMgV2hlbiBJIE5lZWQgdG8gRmlsdGVyIEZpcnN0OiBPbmUtRGltZW5zaW9uYWwgdnMuIE11bHRpLURpbWVuc2lvbmFsIERhdGEKCkZvciBzb21lIG9mIHlvdSwgZmlsdGVyaW5nIHlvdXIgZGF0YSBpbiB0aGlzIHdheSB3aWxsIGJlIG5lY2Vzc2FyeSBiZWZvcmUgcGVyZm9ybWluZyBvcGVyYXRpb25zIGFjcm9zcyBudW1lcmljIHZhcmlhYmxlcyBpbiB5b3VyIGRhdGFzZXQuIFRoaXMgaXMgYmVjYXVzZSwgYXMgd2UgbGVhcm5lZCBsYXN0IHdlZWssIHNvbWUgb2YgeW91IGhhdmUgb2JzZXJ2YXRpb25hbCB1bml0cyB0aGF0IHNwYW4gbXVsdGlwbGUgdGltZSBwZXJpb2RzLCBtdWx0aXBsZSBnZW9ncmFwaGllcywgb3IgbXVsdGlwbGUgaXNzdWVzLiBCZWZvcmUgcGVyZm9ybWluZyBhbiBvcGVyYXRpb24gYWNyb3NzIGEgbnVtZXJpYyB2YXJpYWJsZSwgd2UgbmVlZCB0byBlbnN1cmUgYWxsIG9mIHRoZSB2YWx1ZXMgaW4gdGhhdCB2YXJpYWJsZSBhcmUgcmVmZXJyaW5nIHRvIG9ic2VydmF0aW9ucyByZXBvcnRlZCBhY3Jvc3MgdGhlIHNhbWUgdGltZWZyYW1lIG9yIGdlb2dyYXBoaWMgc2NhbGUuCgpJbiB0aGUgaG9zcGl0YWxzIGRhdGFzZXQsIHRoaXMgaXMgbGVzcyBvZiBhIGNvbmNlcm4gYmVjYXVzZSBhcyB3ZSBsZWFybmVkIGxhc3Qgd2VlaywgdGhlIG9ic2VydmF0aW9uYWwgdW5pdCBvZiB0aGUgZGF0YXNldCBpcyBvbmUgdGhpbmcgLSBhIGhvc3BpdGFsLiBUaGUgQkVEUyB2YXJpYWJsZSBpcyBhbHdheXMgZ29pbmcgdG8gcmVmZXIgdG8gdGhlIG51bWJlciBvZiBCRURTIGF0IGEgaG9zcGl0YWwuIFRoaXMgbWVhbnMgdGhhdCB0aGUgaG9zcGl0YWxzIGRhdGFzZXQgaXMgKm9uZS1kaW1lbnNpb25hbC4qCgpXaXRoIHRoZSB3b3JsZF9oZWFsdGhfZWNvbiBkYXRhLCB3ZSBsZWFybmVkIGxhc3Qgd2VlayB0aGF0IGV2ZXJ5IG9ic2VydmF0aW9uIHJlZmVycyB0byBhIGNvdW50cnkgKmFuZCBhIHllYXIqLiBUaGVyZSBhcmUgdHdvIHZhcmlhYmxlcyB0aGF0IG1ha2UgdXAgdGhlIHVuaXF1ZSBrZXkuIFRoaXMgbWVhbnMgdGhhdCB0aGUgd29ybGRfaGVhbHRoX2Vjb24gZGF0YXNldCBpcyAqdHdvLWRpbWVuc2lvbmFsLiogTGV0J3Mgc2F5IHRoYXQgd2Ugd2FudGVkIHRvIGNhbGwgc3VtbWFyeSgpIG9uIGxpZmVfZXhwIHZhcmlhYmxlIHRvIGNvbXBhcmUgbGlmZSBleHBlY3RhbmNpZXMgYWNyb3NzIGNvdW50cmllcy4gV2l0aG91dCBmaXJzdCB6b29taW5nIGluIHRvIHRvIGEgc3BlY2lmaWMgeWVhciwgd2Ugd291bGQgYmUgaW5jbHVkaW5nIG11bHRpcGxlIHZhbHVlcyB0YWtlbiBhdCB0aGUgc2FtZSBwbGFjZSBhdCBkaWZmZXJlbnQgdGltZXMuIExldCdzIGZpbHRlciB0aGUgZGF0YSB0byBvbmx5IGluY2x1ZGUgdGhlIG1vc3QgcmVjZW50IHJlcG9ydGluZyB5ZWFyIGFuZCB0aGVuIGNhbGwgc3VtbWFyeSgpOgoKYGBge3J9CiNSdW4gdGhpcyBjb2RlIGNodW5rLgoKd29ybGRfaGVhbHRoX2Vjb24gJT4lCiAgZmlsdGVyKHllYXIgPT0gbWF4KHllYXIsIG5hLnJtID0gVFJVRSkpICU+JSAjTm90ZSB0aGF0IHRoaXMgaXMgaG93IHdlIGNhbiBmaWx0ZXIgdG8gdGhlIHJvd3Mgd2l0aCB0aGUgbWF4aW11bSB2YWx1ZSBpbiBhIHZhcmlhYmxlOyBpbiB0aGlzIGNhc2UsIHRoaXMgd291bGQgYmUgdGhlIG1vc3QgcmVjZW50IHllYXIuIAogIHNlbGVjdChsaWZlX2V4cCkgJT4lCiAgc3VtbWFyeSgpCmBgYAoKV2l0aCB0aGUgY2FzZXMgZGF0YSwgd2UgbGVhcm5lZCBsYXN0IHdlZWsgdGhhdCBldmVyeSBvYnNlcnZhdGlvbiByZWZlcnMgdG8gYSBjb3VudHksIHN0YXRlLCBhbmQgZGF0ZS4gVGhlcmUgYXJlIHRocmVlIHZhcmlhYmxlcyB0aGF0IG1ha2UgdXAgdGhlIHVuaXF1ZSBrZXkuIFRoaXMgbWVhbnMgdGhhdCB0aGUgY2FzZXMgZGF0YXNldCBpcyAqdGhyZWUtZGltZW5zaW9uYWwuKiBMZXQncyBzYXkgdGhhdCB3ZSB3YW50ZWQgdG8gY2FsbCBzdW1tYXJ5KCkgb24gY2FzZXMgdmFyaWFibGUgdG8gY29tcGFyZSBjYXNlcyBhY3Jvc3MgY291bnRpZXMuIFdpdGhvdXQgZmlyc3Qgem9vbWluZyBpbiB0byB0byBhIHNwZWNpZmljIGRhdGUgYW5kIHN0YXRlLCB3ZSB3b3VsZCBiZSBpbmNsdWRpbmcgbXVsdGlwbGUgdmFsdWVzIHRha2VuIGF0IHRoZSBzYW1lIHBsYWNlIGF0IGRpZmZlcmVudCB0aW1lcy4gTGV0J3MgZmlsdGVyIHRoZSBkYXRhIHRvIG9ubHkgaW5jbHVkZSB0aGUgbW9zdCByZWNlbnQgZGF0ZSBhbmQgdGhlIHN0YXRlIG9mIENhbGlmb3JuaWEgYW5kIHRoZW4gY2FsbCBzdW1tYXJ5KCk6CgpgYGB7cn0KI1J1biB0aGlzIGNvZGUgY2h1bmsuCgpjYXNlcyAlPiUKICBmaWx0ZXIoZGF0ZSA9PSBtYXgoZGF0ZSwgbmEucm0gPSBUUlVFKSAmIHN0YXRlID09ICJDYWxpZm9ybmlhIikgJT4lIAogIHNlbGVjdChjYXNlcykgJT4lCiAgc3VtbWFyeSgpCmBgYAoKYGBge3J9CmNhc2VzICU+JQogIGZpbHRlcihkYXRlID09IG1heChkYXRlLCBuYS5ybSA9IFRSVUUpICYgc3RhdGUgPT0gIkNhbGlmb3JuaWEiKQpgYGAKCgpMZXQncyB0ZXN0IHRoZSBleHRlbnQgdG8gd2hpY2ggeW91IHdpbGwgbmVlZCB0byB6b29tIGluIHRvIHN0YXRpc3RpY2FsbHkgYW5hbHl6ZSBudW1lcmljIHZhbHVlcyB5b3VyIGRhdGEuIFRoaW5rIHdoYXQgdmFyaWFibGVzIG1ha2UgdXAgdGhlIHVuaXF1ZSBrZXkgaW4geW91ciBkYXRhc2V0LiBJZiB5b3UgaGF2ZSBtb3JlIHRoYW4gb25lIHZhcmlhYmxlIGluIHlvdXIgdW5pcXVlIGtleSwgbWFrZSBzdXJlIHRoYXQgZWFjaCBpcyByZXByZXNlbnRlZCBpbiB5b3VyIHN0YXRlbWVudCBiZWxvdy4gCgpgYGB7cn0KI1VuY29tbWVudCB0aGUgbGluZSBhc3NvY2lhdGVkIHdpdGggeW91ciBkYXRhc2V0IGFuZCBmaWxsIGluIHRoZSBibGFuay4gVGhlbiBydW4gdGhlIGNvZGUuCgojcGFzdGUoZGYkTlVNRVJJQ19WQVJJQUJMRVsxXSwgInJlZmVycyB0byBhIG51bWJlci9tZWFzdXJlIG9mIFtGSUxMIE5VTUVSSUMgVkFSSUFCTEVdIGluIGEgX19fX18gaW4gbXkgZGF0YXNldC4iKQoKI0V4YW1wbGU6CnBhc3RlKGhvc3BpdGFscyRCRURTWzFdLCAicmVmZXJzIHRvIGEgbnVtYmVyIG9mIGJlZHMgaW4gYSBob3NwaXRhbCBpbiBteSBkYXRhc2V0LiIpCnBhc3RlKHdvcmxkX2hlYWx0aF9lY29uJHBvcFsxXSwgInJlZmVycyB0byBhIG51bWJlciBvZiBwZW9wbGUgaW4gYSBjb3VudHJ5IGluIGEgZ2l2ZW4geWVhciBpbiBteSBkYXRhc2V0LiIpCnBhc3RlKGNhc2VzJGNhc2VzWzFdLCAicmVmZXJzIHRvIGEgbnVtYmVyIG9mIGN1bXVsYXRpdmUgY2FzZXMgaW4gYSBjb3VudHkgYW5kIHN0YXRlIG9uIGEgZ2l2ZW4gZGF1IGluIG15IGRhdGFzZXQuIikKCiNwYXN0ZShfX19fXyRfX19fX1sxXSwgInJlZmVycyB0byBhIG51bWJlciBvZiBfX19fXyBpbiBhIF9fX19fIGluIG15IGRhdGFzZXQuIikKYGBgCgpIb3cgZGlkIHlvdSBmaWxsIGluIHRoZSBsYXN0IF9fX19fPyAKCklzIHlvdXIgb2JzZXJ2YXRpb25hbCB1bml0IG9uZSB0aGluZyAoZS5nLiBvbmUgaG9zcGl0YWwsIG9yIG9uZSBjb3VudHJ5KT8gSWYgdGhpcyBpcyB0aGUgY2FzZSwgaXQgd2lsbCBsaWtlbHkgbm90IGJlIGFzIGVzc2VudGlhbCBmb3IgeW91IHRvIHpvb20gaW4gYmVmb3JlIG9wZXJhdGluZyBvbiBudW1lcmljIHZhcmlhYmxlcyBiZWNhdXNlIHlvdSBhcmUgd29ya2luZyB3aXRoIG9uZS1kaW1lbnNpb25hbCBkYXRhLgoKT1IgCgpJcyB5b3VyIG9ic2VydmF0aW9uYWwgdW5pdCBhIGNvbWJpbmF0aW9uIG9mIHRoaW5ncyBvciBmYWN0b3JzIChlLmcuIG9uZSBjaGVtaWNhbCByZXBvcnRlZCBhdCBhIHBhcnRpY3VsYXIgZmFjaWxpdHkgb3Igb25lIGNlbnN1cyB0cmFjdCByZXBvcnRpbmcgaW4gYSBwYXJ0aWN1bGFyIHllYXIpPyBJZiB0aGlzIGlzIHRoZSBjYXNlLCBpdCB3aWxsIGxpa2VseSBiZSBlc3NlbnRpYWwgZm9yIHlvdSB0byB6b29tIGluIGJlZm9yZSBvcGVyYXRpbmcgb24gbnVtZXJpYyB2YXJpYWJsZXMgYmVjYXVzZSB5b3Ugd2lsbCBiZSB3b3JraW5nIHdpdGggbXVsdGktZGltZW5zaW9uYWwgZGF0YS4gCgpJZiB5b3UgYXJlIHdvcmtpbmcgd2l0aCBtdWx0aS1kaW1lbnNpb25hbCBkYXRhLCBpbiBzb21lIHBsYWNlcyB0aHJvdWdob3V0IHRoaXMgbGFiLCB5b3Ugd2lsbCBuZWVkIHRvIGZpbHRlciB5b3VyIGRhdGEgdG8gcGFydGljdWxhciBvYnNlcnZhdGlvbnMgYmVmb3JlIGFuYWx5emluZyBhY3Jvc3MgYSB2YXJpYWJsZS4gVGhpcyBpcyBiZWNhdXNlIHdlIHdpbGwgYmUgc3VtbWFyaXppbmcgaW5mb3JtYXRpb24gYWNyb3NzIGdyb3VwcyBvZiBkYXRhLCBhbmQgaXQgd2lsbCBiZSBpbXBvcnRhbnQgdG8gZW5zdXJlIHRoYXQgeW91IGFyZSBzdW1tYXJpemluZyBpbmZvcm1hdGlvbiBhY3Jvc3MgbGlrZSBvYnNlcnZhdGlvbnMuCgpUaGluayBhYm91dCB3aGF0IHlvdSBtaWdodCBmaWx0ZXIgdG8gaW4gb3JkZXIgdG8gZW5zdXJlIHRoYXQgeW91IHdpbGwgYmUgY29tcGFyaW5nIGxpa2Ugb2JzZXJ2YXRpb25zIChoaW50OiBpdCB3aWxsIGludm9sdmUgYSB2YXJpYWJsZSBpbiB5b3VyIHVuaXF1ZSBrZXkpLiBQZXJoYXBzIHlvdSB3aWxsIGZpbHRlciB0byB0aGUgbW9zdCByZWNlbnQgeWVhciwgc28gdGhhdCB5b3UgY2FuIGNvbXBhcmUgb2JzZXJ2YXRpb25zIGFjcm9zcyBnZW9ncmFwaGllcyBpbiB0aGF0IHllYXIuIE9yIHBlcmhhcHMgeW91IHdpbGwgZmlsdGVyIHRvIGEgcGFydGljdWxhciBnZW9ncmFwaHksIHNvIHRoYXQgeW91IGNhbiBjb21wYXJlIG9ic2VydmF0aW9ucyBhY3Jvc3MgdGltZSBpbiB0aGF0IGdlb2dyYXBoeS4gT3IgcGVyaGFwcyB5b3Ugd2lsbCBmaWx0ZXIgdG8gYSBwYXJ0aWN1bGFyIGRpYWdub3NpcyBncm91cCwgc28gdGhhdCB5b3UgY2FuIGNvbXBhcmUgY29zdHMgYWNyb3NzIGhvc3BpdGFscyBmb3IgdGhhdCBkaWFnbm9zaXMuIE9yIHBlcmhhcHMgeW91IHdpbGwgZmlsdGVyIHRvIGEgcGFydGljdWxhciB5ZWFyIGFuZCBmYW1pbHkgdHlwZSBzbyB0aGF0IHlvdSBjYW4gY29tcGFyZSBvYnNlcnZhdGlvbnMgYWNyb3NzIGNvdW50aWVzIGluIHRoYXQgeWVhciBmb3IgdGhhdCBmYW1pbHkgdHlwZS4gQ2hhcmFjdGVyaXplIG9uZSB3YXkgeW91IG1pZ2h0IGZpbHRlciB5b3VyIGRhdGEgYmVsb3cuIEJlIHNwZWNpZmljLiBXaGljaCB2YXJpYWJsZSBpbiB0aGUgZGF0YXNldCB3aWxsIHlvdSBmaWx0ZXIgb24gYW5kIHRvIHdoYXQgdmFsdWUocykgd2lsbCB5b3UgZmlsdGVyIGl0IHRvPwoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCB5b3VyIHJlc3BvbnNlIGhlcmUuIApgYGAKCiMjIyBGaWx0ZXJpbmcgWW91ciBPd24gRGF0YXNldAoKIyMjIyBGaWx0ZXJpbmcgdG8gYSBDYXRlZ29yaWNhbCBWYWx1ZSBpbiB5b3VyIERhdGFzZXQKClNlbGVjdCBvbmUgb2YgdGhlIHZhbHVlcyB0aGF0IHlvdSBpZGVudGlmaWVkIGZyb20gY2FsbGluZyBkaXN0aW5jdCgpIG9uIGEgY2F0ZWdvcmljYWwgdmFyaWFibGUgaW4gbGFzdCB3ZWVrJ3MgbGFiLiBGaWx0ZXIgdGhlIGRhdGFzZXQgdG8gdGhlIHJvd3MgcmVwcmVzZW50aW5nIHRoYXQgdmFsdWUsIHNlbGVjdCBhIG51bWVyaWMgdmFyaWFibGUgdG8gZXhwbG9yZSwgYW5kIHRoZW4gY2FsbCBzdW1tYXJ5KCkuIElmIHlvdSBoYXZlIG11bHRpLWRpbWVuc2lvbmFsIGRhdGEsIGJlIHN1cmUgdG8gZmlyc3Qgem9vbSBpbnRvIGEgc2V0IG9mIG9ic2VydmF0aW9ucyBpbiB5b3VyIGRhdGEgKHVzaW5nIGZpbHRlcigpKS4gCgpgYGB7cn0KI1VuY29tbWVudCB0aGUgYXBwcm9wcmlhdGUgbGluZXMgYmVsb3csIGFuZCBmaWxsIGluIHlvdXIgZGF0YSBmcmFtZSwgdmFyaWFibGVzLCBhbmQgdmFsdWUuIFJ1biB0aGUgY29kZS4KCiNfX19fXyAlPiUgZmlsdGVyKF9fX19fID09ICJfX19fXyIpICU+JSBzZWxlY3QoX19fX18pICU+JSBzdW1tYXJ5KCkKCiNJZiB5b3UgaGF2ZSBtdWx0aS1kaW1lbnNpb25hbCBkYXRhLCB5b3UgbWF5IG5lZWQgdG8gY2FsbDoKI19fX19fICU+JSBmaWx0ZXIoX19fX18gPT0gX19fX18gJiBfX19fXyA9PSAiX19fX18iKSAlPiUgc2VsZWN0KF9fX19fKSAlPiUgc3VtbWFyeSgpCgpgYGAKCkNvcHkgYW5kIHBhc3RlIHRoZSBkZWZpbml0aW9uIG9mIHRoZSBjYXRlZ29yaWNhbCB2YXJpYWJsZSB5b3Ugc2VsZWN0ZWQgZnJvbSB0aGUgZGF0YSBkaWN0aW9uYXJ5IGJlbG93LiAKCmBgYHtyIGV2YWw9RkFMU0V9CkZpbGwgeW91ciByZXNwb25zZSBoZXJlLiAKYGBgCgoxLiBRVUVSWTogQmVsb3csIHdyaXRlIGEgcmVzZWFyY2ggcXVlc3Rpb24gdGhhdCB0aGUgY29kZSB5b3UganVzdCByYW4gaXMgZGVzaWduZWQgdG8gYmUgYWJsZSB0byBhbnN3ZXIuIE1ha2Ugc3VyZSB5b3UgcGhyYXNlIHlvdXIgcXVlc3Rpb24gZGlyZWN0bHkgaW4gcmVsYXRpb24gdG8gdGhlIHJlc3VsdHMgb2YgeW91ciBjb2RlLiBJbiBvdGhlciB3b3JkcywgeW91IGhhdmUgdGhlIGFuc3dlcjsgbm93IGNvbWUgdXAgd2l0aCB0aGUgcXVlc3Rpb24uIENvbnNpZGVyIHRoaXMgYSBjaGVjayBvbiB3aGV0aGVyIHlvdSB1bmRlcnN0YW5kIHdoYXQgdGhlIGNvZGUgYWJvdmUgaXMgZG9pbmcuIElmIHlvdSBhcmUgdW5zdXJlIGhvdyB0byBjb21wb3NlIHRoaXMgcXVlc3Rpb24sIHlvdSBwcm9iYWJseSB3YW50IHRvIHN0dWR5IHRoZSBmdW5jdGlvbnMgYWJvdmUgYSBiaXQgbW9yZSBjbG9zZWx5LgoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCB5b3VyIHJlc3BvbnNlIGhlcmUuIApgYGAKCkFyZSB0aGVyZSBhbnkgb3RoZXIgdmFyaWFibGVzIGluIHlvdXIgZGF0YXNldCB0aGF0IHlvdSBuZWVkIHRvIHRha2UgaW50byBjb25zaWRlcmF0aW9uIGJlZm9yZSBkaXJlY3RpbmcgdGhpcyBhbmFseXNpcyB0b3dhcmRzIGFuc3dlcmluZyB0aGF0IHF1ZXN0aW9uPyBJbiBvdGhlciB3b3JkcywgZG8geW91IG5lZWQgdG8gem9vbSBpbnRvIGFueSBzcGVjaWZpYyBhcmVhcyBvZiB0aGUgZGF0YXNldCAoYnkgZmlsdGVyaW5nKSBpbiBvcmRlciB0byBhcHByb3ByaWF0ZWx5IGFkZHJlc3MgdGhpcyBxdWVzdGlvbj8gSWYgc28sIHdoaWNoPyAoRm9yIGluc3RhbmNlLCBmb3IgdGhlIGhvc3BpdGFscyBkYXRhc2V0IHdlIG5lZWRlZCB0byBmaWx0ZXIgdG8gaG9zcGl0YWxzIHRoYXQgd2VyZSBPUEVOIGluIG9yZGVyIHRvIGFkZHJlc3MgcXVlc3Rpb25zIGFib3V0IGluZnJhc3RydWN0dXJlKS4gQnJpZWZseSBub3RlIHRoaXMgYmVsb3cuIAoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCB5b3VyIHJlc3BvbnNlIGhlcmUuIApgYGAKCjIuIFNVTU1BUklaRTogUmV2aWV3aW5nIHRoZSBvdXRwdXQgb2YgeW91ciBjb2RlLCBzdW1tYXJpemUgb25lIHRoaW5nIHRoYXQgeW91IGxlYXJuIGFib3V0IHlvdXIgdG9waWMgZnJvbSBydW5uaW5nIHRoaXMgY29kZSBjaHVuay4gSW4gb3RoZXIgd29yZHMsIHdoYXQgaXMgb25lIHRoaW5nIHRoYXQgdGhlIHJlc3VsdHMgb2YgdGhpcyBhbmFseXNpcyBlbXBpcmljYWxseSB0ZWxsIHVzIGFib3V0IHRoZSB0b3BpYz8gQmUgc3BlY2lmaWMsIGNvbnNpZGVyaW5nIHRoZSBnZW9ncmFwaGljLCB0ZW1wb3JhbCwgYW5kIHRvcGljYWwgc2NvcGUgb2YgeW91ciBkYXRhLgoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCB5b3VyIHJlc3BvbnNlIGhlcmUuIApgYGAKCjMuIElOVEVSUFJFVDogTm93IGltYWdpbmUgeW91IHdlcmUgcmVwb3J0aW5nIHlvdXIgZmluZGluZ3MgdG8gYSBkZWNpc2lvbi1tYWtlciBvbiB5b3VyIHRvcGljLiBEZXNjcmliZSB0byB0aGF0IGRlY2lzaW9uLW1ha2VyIHdoeSB0aGV5IHNob3VsZCBjYXJlLiBJbiBvdGhlciB3b3JkcywgKmludGVycHJldCogd2hhdCBpcyBpbXBvcnRhbnQgYWJvdXQgdGhpcyBmaW5kaW5nLiAKCmBgYHtyIGV2YWw9RkFMU0V9CkZpbGwgeW91ciByZXNwb25zZSBoZXJlLiAKYGBgCgo0LiBSRUZMRUNUOiBXaGF0IGVsc2Ugd291bGQgd2UgbmVlZCB0byBrbm93IHRvIGZ1bGx5IGFkZHJlc3MgdGhpcyBxdWVzdGlvbj8gS25vd2luZyB3aGF0IHlvdSBrbm93IGFib3V0IGhvdyB0aGUgZGF0YSB3YXMgY29sbGVjdGVkIGFuZCBhZ2dyZWdhdGVkLCB3aGF0IHVuY2VydGFpbnRpZXMgcmVtYWluIGluIHJlZ2FyZHMgdG8gYWRkcmVzc2luZyB0aGlzIHF1ZXN0aW9uPyBJbiB3aGF0IHdheXMgaXMgdGhlIGFuYWx5c2lzIGxpbWl0ZWQgYnkgdGhlIHNjb3BlIG9mIHRoZSBkYXRhJ3MgZGVmaW5pdGlvbnMgb3IgY2F0ZWdvcmllcz8KCmBgYHtyIGV2YWw9RkFMU0V9CkZpbGwgeW91ciByZXNwb25zZSBoZXJlLiAKYGBgCgojIyMjIEZpbHRlcmluZyB0byBOdW1lcmljIFZhbHVlcyBpbiB5b3VyIERhdGFzZXQKClNlbGVjdCBhIG51bWVyaWMgdmFyaWFibGUgaW4geW91ciBkYXRhc2V0IHRoYXQgcmVwcmVzZW50cyB0aGUgZXh0ZW50IG9yIHNjYWxlIG9mIHRoZSBpc3N1ZSB5b3UgYXJlIHN0dWR5aW5nLiBQaWNrIGEgbnVtYmVyIHRoYXQgeW91IGJlbGlldmUgc2VydmVzIGFzIGEgZ29vZCBpbmRpY2F0b3IgdGhhdCB0aGlzIGlzc3VlIGlzIGF0IGEgbm90YWJsZSBleHRlbnQgb3Igc2NhbGUsIGFuZCBmaWx0ZXIgdGhlIGRhdGFzZXQgdG8gYWxsIHRoZSByb3dzIGdyZWF0ZXIgdGhhbiAob3IgbGVzcyB0aGFuKSB0aGlzIG51bWJlci4gQ2hlY2sgdGhlIHJlbWFpbmluZyBkaXN0aW5jdCB2YWx1ZXMgaW4gYSBjYXRlZ29yaWNhbCB2YXJpYWJsZSBpbiB0aGUgZGF0YXNldC4gSWYgeW91IGhhdmUgbXVsdGktZGltZW5zaW9uYWwgZGF0YSwgYmUgc3VyZSB0byBmaXJzdCB6b29tIGludG8gYSBzZXQgb2Ygb2JzZXJ2YXRpb25zIGluIHlvdXIgZGF0YSAodXNpbmcgZmlsdGVyKCkpLgoKYGBge3J9CiNVbmNvbW1lbnQgdGhlIGFwcHJvcHJpYXRlIGxpbmVzIGJlbG93LCBhbmQgZmlsbCBpbiB5b3VyIGRhdGEgZnJhbWUsIHZhcmlhYmxlcywgY29uZGl0aW9uLCBhbmQgdmFsdWUuIFJ1biB0aGUgY29kZS4KI19fX19fICU+JSBmaWx0ZXIoX19fX18gX19fX18gX19fX18pICU+JSBkaXN0aW5jdChfX19fXykKCiNJZiB5b3UgaGF2ZSBtdWx0aS1kaW1lbnNpb25hbCBkYXRhLCB5b3UgbWF5IG5lZWQgdG8gY2FsbDoKI19fX19fICU+JSBmaWx0ZXIoX19fX18gPT0gX19fX18gJiBfX19fXyBfX19fXyBfX19fXykgJT4lIGRpc3RpbmN0KF9fX19fKQoKYGBgCgpDb3B5IGFuZCBwYXN0ZSB0aGUgZGVmaW5pdGlvbiBvZiB0aGUgbnVtZXJpYyB2YXJpYWJsZSB5b3Ugc2VsZWN0ZWQgZnJvbSB0aGUgZGF0YSBkaWN0aW9uYXJ5IGJlbG93LiAKCmBgYHtyIGV2YWw9RkFMU0V9CkZpbGwgeW91ciByZXNwb25zZSBoZXJlLiAKYGBgCgoxLiBRVUVSWTogQmVsb3csIHdyaXRlIGEgcmVzZWFyY2ggcXVlc3Rpb24gdGhhdCB0aGUgY29kZSB5b3UganVzdCByYW4gaXMgZGVzaWduZWQgdG8gYmUgYWJsZSB0byBhbnN3ZXIuIE1ha2Ugc3VyZSB5b3UgcGhyYXNlIHlvdXIgcXVlc3Rpb24gZGlyZWN0bHkgaW4gcmVsYXRpb24gdG8gdGhlIHJlc3VsdHMgb2YgeW91ciBjb2RlLiBJbiBvdGhlciB3b3JkcywgeW91IGhhdmUgdGhlIGFuc3dlcjsgbm93IGNvbWUgdXAgd2l0aCB0aGUgcXVlc3Rpb24uIENvbnNpZGVyIHRoaXMgYSBjaGVjayBvbiB3aGV0aGVyIHlvdSB1bmRlcnN0YW5kIHdoYXQgdGhlIGNvZGUgYWJvdmUgaXMgZG9pbmcuIElmIHlvdSBhcmUgdW5zdXJlIGhvdyB0byBjb21wb3NlIHRoaXMgcXVlc3Rpb24sIHlvdSBwcm9iYWJseSB3YW50IHRvIHN0dWR5IHRoZSBmdW5jdGlvbnMgYWJvdmUgYSBiaXQgbW9yZSBjbG9zZWx5LgoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCB5b3VyIHJlc3BvbnNlIGhlcmUuIApgYGAKCkFyZSB0aGVyZSBhbnkgb3RoZXIgdmFyaWFibGVzIGluIHlvdXIgZGF0YXNldCB0aGF0IHlvdSBuZWVkIHRvIHRha2UgaW50byBjb25zaWRlcmF0aW9uIGJlZm9yZSBkaXJlY3RpbmcgdGhpcyBhbmFseXNpcyB0b3dhcmRzIGFuc3dlcmluZyB0aGF0IHF1ZXN0aW9uPyBJbiBvdGhlciB3b3JkcywgZG8geW91IG5lZWQgdG8gem9vbSBpbnRvIGFueSBzcGVjaWZpYyBhcmVhcyBvZiB0aGUgZGF0YXNldCAoYnkgZmlsdGVyaW5nKSBpbiBvcmRlciB0byBhcHByb3ByaWF0ZWx5IGFkZHJlc3MgdGhpcyBxdWVzdGlvbj8gSWYgc28sIHdoaWNoPyAoRm9yIGluc3RhbmNlLCBmb3IgdGhlIGhvc3BpdGFscyBkYXRhc2V0IHdlIG5lZWRlZCB0byBmaWx0ZXIgdG8gaG9zcGl0YWxzIHRoYXQgd2VyZSBPUEVOIGluIG9yZGVyIHRvIGFkZHJlc3MgcXVlc3Rpb25zIGFib3V0IGluZnJhc3RydWN0dXJlKS4gQnJpZWZseSBub3RlIHRoaXMgYmVsb3cuIAoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCB5b3VyIHJlc3BvbnNlIGhlcmUuIApgYGAKCjIuIFNVTU1BUklaRTogUmV2aWV3aW5nIHRoZSBvdXRwdXQgb2YgeW91ciBjb2RlLCBzdW1tYXJpemUgb25lIHRoaW5nIHRoYXQgeW91IGxlYXJuIGFib3V0IHlvdXIgdG9waWMgZnJvbSBydW5uaW5nIHRoaXMgY29kZSBjaHVuay4gSW4gb3RoZXIgd29yZHMsIHdoYXQgaXMgb25lIHRoaW5nIHRoYXQgdGhlIHJlc3VsdHMgb2YgdGhpcyBhbmFseXNpcyBlbXBpcmljYWxseSB0ZWxsIHVzIGFib3V0IHRoZSB0b3BpYz8gQmUgc3BlY2lmaWMsIGNvbnNpZGVyaW5nIHRoZSBnZW9ncmFwaGljLCB0ZW1wb3JhbCwgYW5kIHRvcGljYWwgc2NvcGUgb2YgeW91ciBkYXRhLgoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCB5b3VyIHJlc3BvbnNlIGhlcmUuIApgYGAKCjMuIElOVEVSUFJFVDogTm93IGltYWdpbmUgeW91IHdlcmUgcmVwb3J0aW5nIHlvdXIgZmluZGluZ3MgdG8gYSBkZWNpc2lvbi1tYWtlciBvbiB5b3VyIHRvcGljLiBEZXNjcmliZSB0byB0aGF0IGRlY2lzaW9uLW1ha2VyIHdoeSB0aGV5IHNob3VsZCBjYXJlLiBJbiBvdGhlciB3b3JkcywgKmludGVycHJldCogd2hhdCBpcyBpbXBvcnRhbnQgYWJvdXQgdGhpcyBmaW5kaW5nLiAKCmBgYHtyIGV2YWw9RkFMU0V9CkZpbGwgeW91ciByZXNwb25zZSBoZXJlLiAKYGBgCgo0LiBSRUZMRUNUOiBXaGF0IGVsc2Ugd291bGQgd2UgbmVlZCB0byBrbm93IHRvIGZ1bGx5IGFkZHJlc3MgdGhpcyBxdWVzdGlvbj8gS25vd2luZyB3aGF0IHlvdSBrbm93IGFib3V0IGhvdyB0aGUgZGF0YSB3YXMgY29sbGVjdGVkIGFuZCBhZ2dyZWdhdGVkLCB3aGF0IHVuY2VydGFpbnRpZXMgcmVtYWluIGluIHJlZ2FyZHMgdG8gYWRkcmVzc2luZyB0aGlzIHF1ZXN0aW9uPyBJbiB3aGF0IHdheXMgaXMgdGhlIGFuYWx5c2lzIGxpbWl0ZWQgYnkgdGhlIHNjb3BlIG9mIHRoZSBkYXRhJ3MgZGVmaW5pdGlvbnMgb3IgY2F0ZWdvcmllcz8KCmBgYHtyIGV2YWw9RkFMU0V9CkZpbGwgeW91ciByZXNwb25zZSBoZXJlLiAKYGBgCgotLS0KCiMjIGdncGxvdAoKQXQgdGhpcyBwb2ludCBpbiB0aGUgYXNzaWdubWVudCwgd2Ugd2lsbCBiZWdpbiBsZXZlcmFnaW5nIHRoZSBUaWR5dmVyc2UgcGFja2FnZSAqKmdncGxvdCoqIHRvIGNyZWF0ZSBwbG90cyBmb3IgdmlzdWFsaXppbmcgdGhlIGRhdGEuIFRvIGNyZWF0ZSBhIHBsb3Qgd2l0aCBnZ3Bsb3QsIHdlIHdpbGwgZm9sbG93IHRoaXMgYmFzaWMgZm9ybXVsYToKCmBgYHtyIGV2YWw9RkFMU0V9CmRmICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBWQVJJQUJMRV9OQU1FKSkgKyAKICBDSEFSVF9UWVBFCmBgYAoKRm9yIGV4YW1wbGUsIGZvciBhIGJhciBjaGFydCwgeW91IHdpbGwgY2FsbDoKCmBgYHtyIGV2YWw9RkFMU0V9CmRmICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBWQVJJQUJMRV9OQU1FKSkgKyAKICBnZW9tX2JhcigpCmBgYAoKRm9yIGEgY29sdW1uIGNoYXJ0LCB5b3Ugd2lsbCBjYWxsOgoKYGBge3IgZXZhbD1GQUxTRX0KZGYgJT4lIAogIGdncGxvdChhZXMoeCA9IFZBUklBQkxFX05BTUUsIHkgPSBWQVJJQUJMRV9OQU1FKSkgKyAKICBnZW9tX2NvbCgpCmBgYAogIApMZXQncyBicmVhayB0aGF0IGRvd24gYSBiaXQuIEZpcnN0LCB5b3Ugd2lsbCBjYWxsIHlvdXIgZGF0YWZyYW1lLiBGb2xsb3dpbmcgeW91ciBkYXRhZnJhbWUgYW5kIGEgcGlwZSwgeW91IHdpbGwgY2FsbCBnZ3Bsb3QoKSwgd2hpY2ggYmFzaWNhbGx5IHRlbGxzIFIgdG8gcHJlcGFyZSB0byBjcmVhdGUgYSBwbG90LiBJbnNpZGUgZ2dwbG90LCB5b3Ugd2lsbCBsaXN0ICphZXN0aGV0aWNzKi4gVGhlc2UgYXJlIHZhcmlhYmxlcyBpbiB0aGUgZGF0YXNldCB0aGF0IHlvdSB3b3VsZCBsaWtlIHRvIGFwcGVhciBvbiB5b3VyIHBsb3QuIFNldHRpbmcgeCA9IFZBUklBQkxFX05BTUUgdGVsbHMgZ2dwbG90KCkgd2hhdCB2YXJpYWJsZSB0byBwbG90IG9uIHRoZSB4LWF4aXMuIFNldHRpbmcgeSA9IFZBUklBQkxFX05BTUUgdGVsbHMgZ2dwbG90KCkgd2hhdCB2YXJpYWJsZSB0byBwbG90IG9uIHRoZSB5LWF4aXMuIEZpbmFsbHksIGZvbGxvd2luZyBhIHBsdXMgKCspIHNpZ24sIHlvdSB0ZWxsIGdncGxvdCB3aGljaCB0eXBlIG9mIHBsb3QgdG8gY3JlYXRlLiBUaGUgW2dncGxvdCBjaGVhdHNoZWV0XShodHRwczovL3JzdHVkaW8uY29tL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDE1LzAzL2dncGxvdDItY2hlYXRzaGVldC5wZGYpIGxpc3RzIGEgbnVtYmVyIG9mIHBsb3RzIHRoYXQgeW91IGNhbiBjcmVhdGUgd2l0aCBnZ3Bsb3QsIGFzIHdlbGwgYXMgYSBudW1iZXIgb2YgZGlmZmVyZW50IHdheXMgdG8gc3R5bGUgdGhlIHBsb3QuIFdlIHdpbGwgcHJhY3RpY2Ugc2V2ZXJhbCBvZiB0aGVzZSBiZWxvdy4gCgpGb3IgZXZlcnkgcGxvdCB0aGF0IHlvdSBwcm9kdWNlLCBJIHdpbGwgZXhwZWN0IHlvdSB0byBhZGQgYSB0aXRsZSBhbmQgbGFiZWxzIHRvIHRoZSB4IGFuZCB5IGF4aXMuIFlvdSBjYW4gZG8gdGhpcyBhcyBmb2xsb3dzOgoKYGBge3IgZXZhbD1GQUxTRX0KZGYgJT4lIAogIGdncGxvdChhZXMoeCA9IFZBUklBQkxFX05BTUUsIHkgPSBWQVJJQUJMRV9OQU1FKSkgKyAKICBnZW9tX2NvbCgpICsKICBsYWJzKHRpdGxlID0gIkZJTEwgVElUTEUiLCB4ID0gIkZJTEwgWC1BWElTIExBQkVMIiwgeSA9ICJGSUxMIFktQVhJUyBMQUJFTCkKYGBgCgpUaGVyZSBhcmUgYWxzbyBhIG51bWJlciBvZiB1c2VmdWwgdG9vbHMgZm9yIHN0eWxpbmcgeW91ciBwbG90cy4gRm9yIGluc3RhbmNlIHdlIGNhbiBzZXQgdGhlIHRoZW1lIG9mIHRoZSBwbG90IHRvIGxvb2sgYSBiaXQgbW9yZSBwb2xpc2hlZCBieSBhZGRpbmcgIisgdGhlbWVfYncoKSIgdG8gdGhlIHBsb3QuIEkgd2lsbCBkbyB0aGlzIGZvciBhbGwgcGxvdHMgaW4gdGhpcyBsYWIuCgpgYGB7ciBldmFsPUZBTFNFfQpkZiAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gVkFSSUFCTEVfTkFNRSwgeSA9IFZBUklBQkxFX05BTUUpKSArIAogIGdlb21fY29sKCkgKwogIGxhYnModGl0bGUgPSAiRklMTCBUSVRMRSIsIHggPSAiRklMTCBYLUFYSVMgTEFCRUwiLCB5ID0gIkZJTEwgWS1BWElTIExBQkVMIikgKwogIHRoZW1lX2J3KCkKYGBgCgpUd28gc3R5bGluZyBpc3N1ZXMgdGhhdCBJJ20gc3VyZSB3aWxsIGNvbWUgdXAgaW4gbW9zdCBvZiB5b3VyIHBsb3RzIGluY2x1ZGU6CiogY2hhbmdpbmcgeCBvciB5IGF4aXMgdGljayBudW1iZXJzIGZyb20gc2NpZW50aWZpYyB0byBjb21tYSBub3RhdGlvbjogKyBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkgT1IgKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkKKiB0dXJuaW5nIHggYXhpcyB0aWNrIG1hcmtzIDkwIGRlZ3JlZXMgc28gdGhhdCB0aGV5IGRvIG5vdCBvdmVybGFwOiArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0PTEpKSBPUiArIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0PTEpKQoKYGBge3IgZXZhbD1GQUxTRX0KZGYgJT4lIAogIGdncGxvdChhZXMoeCA9IFZBUklBQkxFX05BTUUsIHkgPSBWQVJJQUJMRV9OQU1FKSkgKyAKICBnZW9tX2NvbCgpICsKICBsYWJzKHRpdGxlID0gIkZJTEwgVElUTEUiLCB4ID0gIkZJTEwgWC1BWElTIExBQkVMIiwgeSA9ICJGSUxMIFktQVhJUyBMQUJFTCIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdD0xKSkgKyAjVHVybiBsYWJlbHMgOTAgZGVncmVlcwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKSAjQ2hhbmdlIGxhYmVscyBmcm9tIHNjaWVudGlmaWMgdG8gY29tbWEgbm90YXRpb24KYGBgCgojIyBWYXJpYXRpb24KClZhcmlhdGlvbiBpcyB0aGUgZXh0ZW50IHRvIHdoaWNoIHRoZSB2YWx1ZXMgaW4gYSBwYXJ0aWN1bGFyIHZhcmlhYmxlIHZhcnkgZnJvbSBvYnNlcnZhdGlvbiB0byBvYnNlcnZhdGlvbi4gRXhhbWluaW5nIHZhcmlhdGlvbiBpbnZvbHZlcyBsb29raW5nIGF0IHRoZSBkaXN0cmlidXRpb24gb2YgdmFsdWVzIGluIGEgcGFydGljdWxhciBjb2x1bW4gaW4gdGhlIGRhdGFzZXQuIFNwZWNpZmljYWxseSwgd2UgYXJlICpjb3VudGluZyogdGhlIG51bWJlciBvZiB0aW1lcyBlYWNoIHZhbHVlIG9yIHNldCBvZiB2YWx1ZXMgYXBwZWFycyBpbiB0aGF0IHZhcmlhYmxlLiBEbyB3ZSBoYXZlIGEgd2hvbGUgYnVuY2ggb2Ygb25lIHBhcnRpY3VsYXIgdmFsdWUgaW4gYSBjZXJ0YWluIHZhcmlhYmxlLCBhbmQgdmVyeSBmZXcgb2YgYW5vdGhlcj8gT3IgbWF5YmUsIGRvIHdlIGhhdmUgYSBtb3JlIGV2ZW4gZGlzdHJpYnV0aW9uIG9mIHZhbHVlcyBhY3Jvc3MgYSB2YXJpYWJsZT8KClNvIGhvdyBkbyB3ZSB2aXN1YWxpemUgdmFyaWF0aW9uIHdpdGggZ2dwbG90PyBCZWxvdyBJIGRlc2NyaWJlIHR3byBkaWZmZXJlbnQgcGxvdHMgdGhhdCB5b3UgY2FuIGxldmVyYWdlIHRvIHZpc3VhbGl6ZSB2YXJpYXRpb24gLSBhIGJhciBwbG90IGFuZCBhIGhpc3RvZ3JhbS4gCgojIyMgQmFyIFBsb3QKCkEgKmJhciBwbG90KiBkaXNwbGF5cyB0aGUgbnVtYmVyIG9mIHRpbWVzIGVhY2ggdmFsdWUgYXBwZWFycyBpbiBhIGNhdGVnb3JpY2FsIHZhcmlhYmxlLiBJdCAqY291bnRzKiB0aGUgbnVtYmVyIG9mIHRpbWVzIGVhY2ggdmFsdWUgYXBwZWFycyBpbiB0aGF0IHZhcmlhYmxlIGFuZCB0aGVuIHNldHMgdGhlIGhlaWdodCBvZiBhIGJhciBpbiB0aGUgcGxvdCBhY2NvcmRpbmcgdG8gdGhhdCBjb3VudC4gVGhpcyB3aWxsIHRlbGwgdXMgaG93IHRoZSBvYnNlcnZhdGlvbnMgaW4gdGhlIGRhdGFzZXQgKnZhcnkqIGluIHJlZ2FyZHMgdG8gdGhhdCB2YXJpYWJsZS4gSW4gb3RoZXIgd29yZHMsIHRoaXMgcGxvdCB3aWxsIGNvbW11bmljYXRlIHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIGluIHlvdXIgZGF0YXNldCBieSB0aGF0IHZhcmlhYmxlLiAKCmBgYHtyIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTEwfQojUnVuIHRoaXMgY29kZSBjaHVuay4KCiNkZiAlPiUgZ2dwbG90KGFlcyh4ID0gQ0FURUdPUklDQUxfVkFSSUFCTEUpKSArIGdlb21fYmFyKCkgKyBsYWJzKHRpdGxlID0gIlRJVExFIiwgeCA9ICJYLUFYSVMgTkFNRSIsIHkgPSAiWS1BWElTIE5BTUUiKQoKaG9zcGl0YWxzICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBUWVBFKSkgKyAKICBnZW9tX2JhcigpICsKICBsYWJzKHRpdGxlID0gIk51bWJlciBvZiBIb3NwaXRhbHMgaW4gdGhlIFVTIGJ5IFR5cGUiLCB4ID0gIlR5cGUiLCB5ID0gIkNvdW50IG9mIEhvc3BpdGFscyIpICsgI0FkZHMgYSB0aXRsZSB0byB0aGUgcGxvdAogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0PTEpKSAjQ2hhbmdlcyB4LWF4aXMgdGljayBsYWJlbHMgOTAgZGVncmVlcyAKYGBgCgpSZW1lbWJlciB0aGF0IHRoaXMgZGF0YXNldCBpbmNsdWRlcyBob3NwaXRhbHMgdGhhdCBhcmUgZGVzaWduYXRlZCBhcyBjbG9zZWQuIERlcGVuZGluZyBvbiB0aGUgcXVlc3Rpb24gd2UgYXJlIHRyeWluZyB0byBhZGRyZXNzLCB3ZSBtYXkgd2lzaCB0byB6b29tIGluIHRvIG9ubHkgdGhlIG9ic2VydmF0aW9ucyBzaWduaWZ5aW5nIGEgaG9zcGl0YWwgdGhhdCBpcyBvcGVuIGJlZm9yZSBjcmVhdGluZyB0aGlzIHBsb3QuIAoKYGBge3IgZmlnLmhlaWdodD01LCBmaWcud2lkdGg9MTB9CiNSdW4gdGhpcyBjb2RlIGNodW5rLgoKI2RmICU+JSBnZ3Bsb3QoYWVzKHggPSBDQVRFR09SSUNBTF9WQVJJQUJMRSkpICsgZ2VvbV9iYXIoKSArIGxhYnModGl0bGUgPSAiVElUTEUiLCB4ID0gIlgtQVhJUyBOQU1FIiwgeSA9ICJZLUFYSVMgTkFNRSIpCgpob3NwaXRhbHMgJT4lIAogIGZpbHRlcihTVEFUVVMgPT0gIk9QRU4iKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBUWVBFKSkgKyAKICBnZW9tX2JhcigpICsKICBsYWJzKHRpdGxlID0gIk51bWJlciBvZiBIb3NwaXRhbHMgaW4gdGhlIFVTIHRoYXQgYXJlIE9wZW4gYnkgVHlwZSIsIHggPSAiVHlwZSIsIHkgPSAiQ291bnQgb2YgSG9zcGl0YWxzIikgKyAjQWRkcyBhIHRpdGxlIHRvIHRoZSBwbG90CiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3Q9MSkpICNDaGFuZ2VzIHgtYXhpcyB0aWNrIGxhYmVscyA5MCBkZWdyZWVzIApgYGAKCiMjIyMgVGl0bGluZyBhIEJhciBQbG90CgpOb3RlIGhvdyBJIHRpdGxlZCBteSBmaXJzdCBwbG90IGFib3ZlOiAiTnVtYmVyIG9mIEhvc3BpdGFscyBpbiB0aGUgVVMgYnkgVHlwZSIgUmVtZW1iZXIgbGFzdCB3ZWVrLCB3aGVuIHdlIGlkZW50aWZpZWQgd2hhdCBtYWtlcyBlYWNoIG9ic2VydmF0aW9uIGluIG91ciBkYXRhc2V0IHVuaXF1ZT8gSGVyZSBJIGFtIGNvdW50aW5nIHRoZSBvYnNlcnZhdGlvbnMgYnkgVHlwZSwgYW5kIGluIG9yZGVyIHRvIGtub3cgd2hhdCBJJ20gY291bnRpbmcsIEkgbmVlZCB0byBrbm93IHdoYXQgZWFjaCBvYnNlcnZhdGlvbiByZWZlcnMgdG8uIEEgZ29vZCBmb3JtdWxhIGZvciB0aXRsaW5nIGJhciBwbG90cyBpcyBhcyBmb2xsb3dzOgoKTnVtYmVyIG9mIF9fX19fIGJ5IFt4LWF4aXMgdmFyaWFibGUgbmFtZV0KCkluIG9yZGVyIHRvIGZpbGwgaW4gdGhlIGJsYW5rIGxpbmUgYWJvdmUsIGNvbnNpZGVyIHRoZSBzdGF0ZW1lbnQgd2UgcHJvZHVjZWQgbGFzdCB3ZWVrOiAiSSBoYXZlIG5yb3coZGYpIHVuaXF1ZSBfX19fXyByZXByZXNlbnRlZCBpbiBteSBkYXRhc2V0LiIgVGhhdCBibGFuayBsaW5lIHRvbGQgdXMgd2hhdCBlYWNoIG9ic2VydmF0aW9uIGluIHRoZSBkYXRhc2V0IHJlcHJlc2VudGVkIC0gb3IgaXRzICpvYnNlcnZhdGlvbmFsIHVuaXQqLiBIb3dldmVyIHdlIGZpbGxlZCBpbiB0aGF0IGJsYW5rIGxpbmUgc2hvdWxkIGFsc28gYmUgaG93IHdlIGZpbGwgaW4gdGhlIHRpdGxlIG9mIGEgYmFyIHBsb3QuIAoKVGhlIFt4LWF4aXMgdmFyaWFibGUgbmFtZV0gc2hvdWxkIGJlIHlvdXIgeC1sYWJlbCBhbmQgIkNvdW50IG9mIF9fX19fXyIgKGZpbGxlZCB0aGUgc2FtZSBhcyBhYm92ZSkgc2hvdWxkIGJlIHlvdXIgeS1sYWJlbC4gTm90ZSB0aGF0IGlmIHlvdSBmaWx0ZXIgeW91ciBkYXRhc2V0LCB5b3Ugc2hvdWxkIGFjY291bnQgZm9yIHRoaXMgaW4gdGhlIHRpdGxlOiAiTnVtYmVyIG9mIEhvc3BpdGFscyBpbiB0aGUgVVMgYnkgVHlwZSIKCiMjIyMjIFdoYXQgaWYgSSBoYXZlIG11bHRpLWRpbWVuc2lvbmFsIGRhdGE/CgpXaGVuIHdlIGNyZWF0ZSBhIGJhciBwbG90LCB3ZSBhcmUgY291bnRpbmcgdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgdGhhdCBmYWxsIGludG8gZWFjaCBjYXRlZ29yeS4gSWYgdGhlcmUgaXMgb25seSBvbmUgdmFyaWFibGUgdGhhdCBtYWtlcyB1cCB5b3VyIHVuaXF1ZSBrZXksIHRoYXQgb25lIHZhcmlhYmxlIHdpbGwgcmVwcmVzZW50IHdoYXQgaXMgYmVpbmcgY291bnRlZCAoZS5nLiBhYm92ZSB3ZSBhcmUgY291bnRpbmcgaG9zcGl0YWxzIGJ5IGNhdGVnb3J5KS4gSG93ZXZlciwgaWYgdGhlcmUgYXJlIG11bHRpcGxlIHZhcmlhYmxlcyBpbiB5b3VyIHVuaXF1ZSBrZXksIHRoZW4gaWRlbnRpZnlpbmcgd2hhdCBpdCBpcyB0aGF0IHlvdSBhcmUgY291bnRpbmcgYmVjb21lcyBhIGxpdHRsZSBtb3JlIGNvbXBsaWNhdGVkLiBGb3IgaW5zdGFuY2UsIGxldCdzIHNheSB5b3VyIGRhdGEgcmVwb3J0cyB0aGUgcG9wdWxhdGlvbiBvZiBlYWNoIGNvdW50cnkgZWFjaCB5ZWFyIGFzIGl0IGRvZXMgaW4gdGhlIHdvcmxkX2hlYWx0aF9lY29uIGRhdGFzZXQuIE5vdyBsZXQncyBzYXkgdGhhdCB5b3Ugd2FudGVkIHRvIHBsb3QgdGhlIG51bWJlciBvZiBjb3VudHJpZXMgcGVyIGNvbnRpbmVudC4gSWYgeW91IHdlcmUgdG8gY2FsbDoKCmBgYHtyfQojUnVuIHRoaXMgY29kZSBjaHVuay4KCndvcmxkX2hlYWx0aF9lY29uICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBjb250aW5lbnQpKSArIAogIGdlb21fYmFyKCkgKwogIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIENvdW50cmllcyBwZXIgQ29udGluZW50IC0gSW5jb3JyZWN0IiwgeCA9ICJDb250aW5lbnQiLCB5ID0gIkNvdW50IG9mIENvdW50cmllcyIpICsgI0FkZHMgYSB0aXRsZSB0byB0aGUgcGxvdAogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0PTEpKSAjQ2hhbmdlcyB4LWF4aXMgdGljayBsYWJlbHMgOTAgZGVncmVlcyAKYGBgCgouLi4geW91IHdvdWxkIGJlIGNvdW50aW5nIHRoZSBjb21iaW5hdGlvbiBvZiB0aGUgbnVtYmVyIG9mIGNvdW50cmllcyBhbmQgeWVhcnMgcGVyIGNvbnRpbmVudC4gVGhlcmUgYXJlIG5vdCA4MDAgY291bnRyaWVzIGluIEFmcmljYSwgYnV0IEFmcmljYSBhcHBlYXJzIGluIHRoZSBkYXRhc2V0IDgwMCB0aW1lcyBiZWNhdXNlIGVhY2ggY291bnRyeSBpbiBBZnJpY2EgaGFzIHNldmVyYWwgcm93cyBpbiB0aGUgZGF0YXNldCAtIG9uZSBmb3IgZWFjaCByZXBvcnRpbmcgeWVhci4gSW4gb3RoZXIgd29yZHMsIGVhY2ggY291bnRyeSBpcyByZXByZXNlbnRlZCBpbiB0aGUgYmFyIGZvciBldmVyeSB5ZWFyIHRoYXQgaXQgd2FzIGluY2x1ZGVkIGluIHRoZSBkYXRhc2V0LiBUaGUgeS1heGlzIGRvZXMgbm90IGp1c3QgcmVwcmVzZW50IGNvdW50cmllcyBidXQgYm90aCBjb3VudHJpZXMgYW5kIHllYXJzLiBJZiB3ZSB3YW50IHRoZSB5LWF4aXMgdG8gb25seSBiZSBjb3VudGluZyBvbmUgdGhpbmcsIHRoZW4gd2UgbmVlZCB0byBmaXJzdCByZWR1Y2UgdGhlIGRhdGFzZXQgdG8gdmFsdWVzIGluIGEgcGFydGljdWxhciBjb250ZXh0LiBZb3UgY2FuIGRvIHRoaXMgYnkgZmlsdGVyaW5nIHRoZSBkYXRhIGFzIHlvdSBoYWQgYmVlbiBkb2luZyBhYm92ZS4KCmBgYHtyfQojUnVuIHRoaXMgY29kZSBjaHVuay4KCndvcmxkX2hlYWx0aF9lY29uICU+JSAKICBmaWx0ZXIoeWVhciA9PSBtYXgoeWVhciwgbmEucm0gPSBUUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gY29udGluZW50KSkgKyAKICBnZW9tX2JhcigpICsKICBsYWJzKHRpdGxlID0gIk51bWJlciBvZiBDb3VudHJpZXMgcGVyIENvbnRpbmVudCBpbiB0aGUgbW9zdCBSZWNlbnQgUmVwb3J0aW5nIFllYXIiLCB4ID0gIkNvbnRpbmVudCIsIHkgPSAiQ291bnQgb2YgQ291bnRyaWVzIikgKyAjQWRkcyBhIHRpdGxlIHRvIHRoZSBwbG90CiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3Q9MSkpICNDaGFuZ2VzIHgtYXhpcyB0aWNrIGxhYmVscyA5MCBkZWdyZWVzCmBgYAoKPiBOb3RlIHRoZSBhZGRpdGlvbiB0byBteSB0aXRsZSBhYm92ZS4gSWYgeW91IGZpbHRlciB5b3VyIGRhdGFzZXQsIHRoZSBmb3JtdWxhIGZvciB0aXRsaW5nIGNoYW5nZXMgYSBiaXQgdG8gRnJlcXVlbmN5IG9mIFt4LWF4aXMgdmFyaWFibGUgbmFtZV0gYWNyb3NzIF9fX19fIGluIFtmaWx0ZXJlZCB2YWx1ZV0KCiMjIyMgU2VsZWN0IGEgY2F0ZWdvcmljYWwgdmFyaWFibGUgZm9yIHdoaWNoIHlvdSB3YW50IHRvIGdyYXBoaWNhbGx5IHJlcHJlc2VudCB0aGUgbnVtYmVyIG9mIHRpbWVzIGl0IGFwcGVhcnMgaW4gdGhlIGRhdGFzZXQuIAoKSSByZWNvbW1lbmQgdGhhdCB5b3Ugc2VsZWN0IG9uZSBvZiB0aGUgc2FtZSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgdGhhdCB5b3UgYW5hbHl6ZWQgd2l0aCB0aGUgZGlzdGluY3QoKSBmdW5jdGlvbiBsYXN0IHdlZWsuIElmIHlvdSBoYXZlIG11bHRpLWRpbWVuc2lvbmFsIGRhdGEsIGJlIHN1cmUgdG8gZmlsdGVyIHlvdXIgZGF0YSBmaXJzdCBzbyB0aGF0IGFsbCBvZiB0aGUgb2JzZXJ2YXRpb25zIHlvdSBhcmUgY291bnRpbmcgaGF2ZSBvbmUgdmFyaWFibGUgYXMgYSB1bmlxdWUga2V5LiBJZiB5b3Ugbm90aWNlIHN0eWxpbmcgaXNzdWVzIHdpdGggeW91ciBkYXRhLCBiZSBzdXJlIHRvIGNvbnNpZGVyIG15IG5vdGVzIGFib3V0IGhvdyB0byBmaXggdGhlbSBhYm92ZS4KCmBgYHtyIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTEwfQojVW5jb21tZW50IHRoZSBsaW5lIGJlbG93IGFuZCBmaWxsIGFwcHJvcHJpYXRlbHkuIEFkZCBhIHRpdGxlIGFuZCBsYWJlbHMgdG8geW91ciBwbG90cywgYW5kIGFkanVzdCBpdHMgc3R5bGUgdG8gYmUgbGVnaWJsZS4gVGhlbiBydW4gdGhlIGNvZGUuCiNfX19fXyAlPiUgZ2dwbG90KGFlcyh4ID0gX19fX18pKSArIGdlb21fYmFyKCkKCiNJZiBtdWx0aS1kaW1lbnNpb25hbDoKI19fX19fICU+JSBmaWx0ZXIoX19fX18gPT0gX19fX18pICU+JSBnZ3Bsb3QoYWVzKHggPSBfX19fXykpICsgZ2VvbV9iYXIoKQpgYGAKCkNvcHkgYW5kIHBhc3RlIHRoZSBkZWZpbml0aW9uIG9mIHRoZSBjYXRlZ29yaWNhbCB2YXJpYWJsZSB5b3Ugc2VsZWN0ZWQgZnJvbSB0aGUgZGF0YSBkaWN0aW9uYXJ5IGJlbG93LiAKCmBgYHtyIGV2YWw9RkFMU0V9CkZpbGwgeW91ciByZXNwb25zZSBoZXJlLiAKYGBgCgpDb21wbGV0ZSB0aGUgZm9sbG93aW5nIHN0YXRlbWVudDoKCmBgYHtyIGV2YWw9RkFMU0V9CkVhY2ggYmFyIGluIHRoZSBiYXIgcGxvdCBhYm92ZSBpcyBjb3VudGluZyB0aGUgbnVtYmVyIG9mIF9fX19fIGluIG15IGRhdGFzZXQgYWNjb3JkaW5nIHRvIF9fX19fLgpgYGAKCjEuIFFVRVJZOiBCZWxvdywgd3JpdGUgYSByZXNlYXJjaCBxdWVzdGlvbiB0aGF0IHRoZSBjb2RlIHlvdSBqdXN0IHJhbiBpcyBkZXNpZ25lZCB0byBiZSBhYmxlIHRvIGFuc3dlci4gTWFrZSBzdXJlIHlvdSBwaHJhc2UgeW91ciBxdWVzdGlvbiBkaXJlY3RseSBpbiByZWxhdGlvbiB0byB0aGUgcmVzdWx0cyBvZiB5b3VyIGNvZGUuIEluIG90aGVyIHdvcmRzLCB5b3UgaGF2ZSB0aGUgYW5zd2VyOyBub3cgY29tZSB1cCB3aXRoIHRoZSBxdWVzdGlvbi4gQ29uc2lkZXIgdGhpcyBhIGNoZWNrIG9uIHdoZXRoZXIgeW91IHVuZGVyc3RhbmQgd2hhdCB0aGUgY29kZSBhYm92ZSBpcyBkb2luZy4gSWYgeW91IGFyZSB1bnN1cmUgaG93IHRvIGNvbXBvc2UgdGhpcyBxdWVzdGlvbiwgeW91IHByb2JhYmx5IHdhbnQgdG8gc3R1ZHkgdGhlIGZ1bmN0aW9ucyBhYm92ZSBhIGJpdCBtb3JlIGNsb3NlbHkuCgpgYGB7ciBldmFsPUZBTFNFfQpGaWxsIHlvdXIgcmVzcG9uc2UgaGVyZS4gCmBgYAoKQXJlIHRoZXJlIGFueSBvdGhlciB2YXJpYWJsZXMgaW4geW91ciBkYXRhc2V0IHRoYXQgeW91IG5lZWQgdG8gdGFrZSBpbnRvIGNvbnNpZGVyYXRpb24gYmVmb3JlIGRpcmVjdGluZyB0aGlzIGFuYWx5c2lzIHRvd2FyZHMgYW5zd2VyaW5nIHRoYXQgcXVlc3Rpb24/IEluIG90aGVyIHdvcmRzLCBkbyB5b3UgbmVlZCB0byB6b29tIGludG8gYW55IHNwZWNpZmljIGFyZWFzIG9mIHRoZSBkYXRhc2V0IChieSBmaWx0ZXJpbmcpIGluIG9yZGVyIHRvIGFwcHJvcHJpYXRlbHkgYWRkcmVzcyB0aGlzIHF1ZXN0aW9uPyBJZiBzbywgd2hpY2g/IChGb3IgaW5zdGFuY2UsIGZvciB0aGUgaG9zcGl0YWxzIGRhdGFzZXQgd2UgbmVlZGVkIHRvIGZpbHRlciB0byBob3NwaXRhbHMgdGhhdCB3ZXJlIE9QRU4gaW4gb3JkZXIgdG8gYWRkcmVzcyBxdWVzdGlvbnMgYWJvdXQgaW5mcmFzdHJ1Y3R1cmUpLiBCcmllZmx5IG5vdGUgdGhpcyBiZWxvdy4gCgpgYGB7ciBldmFsPUZBTFNFfQpGaWxsIHlvdXIgcmVzcG9uc2UgaGVyZS4gCmBgYAoKMi4gU1VNTUFSSVpFOiBSZXZpZXdpbmcgdGhlIG91dHB1dCBvZiB5b3VyIGNvZGUsIHN1bW1hcml6ZSBvbmUgdGhpbmcgdGhhdCB5b3UgbGVhcm4gYWJvdXQgeW91ciB0b3BpYyBmcm9tIHJ1bm5pbmcgdGhpcyBjb2RlIGNodW5rLiBJbiBvdGhlciB3b3Jkcywgd2hhdCBpcyBvbmUgdGhpbmcgdGhhdCB0aGUgcmVzdWx0cyBvZiB0aGlzIGFuYWx5c2lzIGVtcGlyaWNhbGx5IHRlbGwgdXMgYWJvdXQgdGhlIHRvcGljPyBCZSBzcGVjaWZpYywgY29uc2lkZXJpbmcgdGhlIGdlb2dyYXBoaWMsIHRlbXBvcmFsLCBhbmQgdG9waWNhbCBzY29wZSBvZiB5b3VyIGRhdGEuCgpgYGB7ciBldmFsPUZBTFNFfQpGaWxsIHlvdXIgcmVzcG9uc2UgaGVyZS4gCmBgYAoKMy4gSU5URVJQUkVUOiBOb3cgaW1hZ2luZSB5b3Ugd2VyZSByZXBvcnRpbmcgeW91ciBmaW5kaW5ncyB0byBhIGRlY2lzaW9uLW1ha2VyIG9uIHlvdXIgdG9waWMuIERlc2NyaWJlIHRvIHRoYXQgZGVjaXNpb24tbWFrZXIgd2h5IHRoZXkgc2hvdWxkIGNhcmUuIEluIG90aGVyIHdvcmRzLCAqaW50ZXJwcmV0KiB3aGF0IGlzIGltcG9ydGFudCBhYm91dCB0aGlzIGZpbmRpbmcuIAoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCB5b3VyIHJlc3BvbnNlIGhlcmUuIApgYGAKCjRhLiBSRUZMRUNUOiBSZWZsZWN0IG9uIHRoZSBkaXN0cmlidXRpb24gb2YgY2F0ZWdvcmllcyBpbiB0aGUgZGF0YXNldC4gSXMgdGhlcmUgYW4gZXZlbiBkaXN0cmlidXRpb24gb2Ygb2JzZXJ2YXRpb25zIGFjcm9zcyBlYWNoIGNhdGVnb3J5LCBvciBhcmUgY2VydGFpbiBjYXRlZ29yaWVzIG1vcmUgcmVwcmVzZW50ZWQgdGhhbiBvdGhlcnM/IFdoeSBtaWdodCB0aGlzIGJlPyBXaGF0IGRvZXMgdGhpcyBzYXkgYWJvdXQgdGhlIHNvY2lhbCwgcG9saXRpY2FsLCBvciBlY29ub21pYyBsYW5kc2NhcGUgb2YgeW91ciB0b3BpYz8gCgpgYGB7ciBldmFsPUZBTFNFfQpGaWxsIHJlc3BvbnNlIGhlcmUuIApgYGAKCjRiLiBSRUZMRUNUOiBSZWZsZWN0IG9uIHdoYXQgeW91IGxlYXJuZWQgYWJvdXQgdGhlIGhpc3Rvcnkgb2YgdGhlIGNhdGVnb3JpZXMgeW91IHBsb3R0ZWQgYWJvdmUgaW4gbGFzdCB3ZWVrJ3MgbGFiLiBIb3cgaGF2ZSB0aGUgc29jaWFsLCBwb2xpdGljYWwsIGFuZCBlY29ub21pYyBmb3JjZXMgc2hhcGluZyB0aGlzIGNhdGVnb3JpemF0aW9uIGltcGFjdGVkIGhvdyB3ZSBjb3VudCBvYnNlcnZhdGlvbnMgcmVsYXRlZCB0byB0aGlzIHRvcGljPyBIb3cgbWlnaHQgdGhpcyBwbG90IGxvb2sgZGlmZmVyZW50IGlmIHRoaXMgdmFyaWFibGUgaGFkIGJlZW4gY2F0ZWdvcml6ZWQgaW4gYSBkaWZmZXJlbnQgd2F5PwoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCByZXNwb25zZSBoZXJlLiAKYGBgCgo0Yy4gUkVGTEVDVDogUmVmbGVjdCBvbiB3aGF0IHdlIGNhbm5vdCBzZWUgd2l0aCB0aGlzIGRhdGEuIFdoYXQgbWlnaHQgYmUgb25lIHRvcGljIG9yIGlzc3VlIHRoYXQgZG9lcyBub3QgZml0IG5lYXRseSBpbnRvIHRoZSBkZXNpZ25hdGVkIGNhdGVnb3JpZXM/CgpgYGB7ciBldmFsPUZBTFNFfQpGaWxsIHJlc3BvbnNlIGhlcmUuIApgYGAKCiMjIyBIaXN0b2dyYW0KCkEgKmhpc3RvZ3JhbSogd2lsbCBkaXNwbGF5IHRoZSBkaXN0cmlidXRpb24gb2YgdmFsdWVzIGluIGEgbnVtZXJpYyB2YXJpYWJsZSB3aXRoaW4gYSBkZXNpZ25hdGVkIHNldCBvZiBpbmNyZW1lbnRzLiBBZnRlciB5b3UgZGVzaWduYXRlIGEgY2VydGFpbiBudW1iZXIgdG8gZ3JvdXAgaW5jcmVtZW50cyBieSwgaXQgd2lsbCAqY291bnQqIHRoZSBudW1iZXIgb2YgdmFsdWVzIGluIHRoZSB2YXJpYWJsZSB0aGF0IGZhbGwgaW50byBlYWNoIGluY3JlbWVudC4gTGV0J3Mgc2F5IHlvdSBkZXNpZ25hdGUgdGhlIG51bWJlciAxMCB0byBncm91cCBpbmNyZW1lbnRzIGJ5LCBzdGFydGluZyBhdCAwLiBUaGUgcGxvdCB3aWxsIGNvdW50IGhvdyBtYW55IHZhbHVlcyBpbiB0aGUgdmFyaWFibGUgZmFsbCBpbiB0aGUgaW5jcmVtZW50IDAtOSwgMTAtMTksIDIwLTI5LCBhbmQgc28gb24uIFRoaXMgd2lsbCB0ZWxsIHVzIGhvdyB0aGUgb2JzZXJ2YXRpb25zIGluIHRoZSBkYXRhc2V0ICp2YXJ5KiBpbiByZWdhcmRzIHRvIHRoYXQgdmFyaWFibGUuIAoKQ29uc2lkZXIgdGhlIHBsb3QgYmVsb3cuIFRoaXMgcGxvdCB0ZWxscyB1cyB0aGUgZGlzdHJpYnV0aW9uIG9mIGJlZHMgYWNyb3NzIG9wZW4gaG9zcGl0YWxzLiBJdCAqY291bnRzKiBob3cgbWFueSBob3NwaXRhbHMgdGhlcmUgYXJlIGluIGVhY2ggaW5jcmVtZW50IG9mIDEwIGJlZHMuCgpgYGB7ciBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0xMH0KI1J1biB0aGlzIGNvZGUgY2h1bmsuCgojZGYgJT4lIGdncGxvdChhZXMoeCA9IE5VTUVSSUNfVkFSSUFCTEUpKSArIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgYm91bmRhcnkgPSAwKSArIGxhYnModGl0bGUgPSAiVElUTEUiLCB4ID0gIlgtQVhJUyBOQU1FIiwgeSA9ICJZLUFYSVMgTkFNRSIpCgpob3NwaXRhbHMgJT4lIAogIGZpbHRlcihTVEFUVVMgPT0gIk9QRU4iKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBCRURTKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTAsIGJvdW5kYXJ5ID0gMCkgKwogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEJlZHMgYWNyb3NzIEhvc3BpdGFscyBpbiB0aGUgVVMgdGhhdCBhcmUgT3BlbiIsIHggPSAiQmVkcyIsIHkgPSAiQ291bnQgb2YgSG9zcGl0YWxzIikgKwogIHRoZW1lX2J3KCkKYGBgCgpOb3RlIHRoYXQgYm91bmRhcnkgcmVmZXJzIHRvIHdoZXJlIHdlIHdhbnQgb3VyIGluY3JlbWVudHMgdG8gYmVnaW4gYW5kIGJpbndpZHRoIHJlZmVycyB0byB0aGUgc2l6ZSBvZiB0aGUgaW5jcmVtZW50cyBhdCB3aGljaCBmcmVxdWVuY3kgd2lsbCBiZSBjYWxjdWxhdGVkLiBBYm92ZSB0aGUgYmlud2lkdGggaXMgc2V0IHRvIDEwLiBUaGlzIG1lYW5zIHRoYXQgZ2dwbG90IHdpbGwgZGlzcGxheSB0aGUgZnJlcXVlbmN5IG9mIGVhY2ggdmFsdWUgYXQgaW50ZXJ2YWxzIG9mIDEwLCAyMCwgMzAsIDQwLCBldGMuIFdoZW4gd2Ugc2V0IHRoZSBiaW53aWR0aCB0byAxLCBnZ3Bsb3Qgd2lsbCBkaXNwbGF5IHRoZSBmcmVxdWVuY3kgb2YgZWFjaCB2YWx1ZSBhdCBpbnRlcnZhbHMgb2YgMSwgMiwgMywgNC4gZXRjLiBXaGF0IGRpZmZlcmVuY2UgZG9lcyB0aGlzIG1ha2U/IAoKTm90aWNlIHdoYXQgaGFwcGVucyB3aGVuIHdlIHNldCB0aGUgYmlud2lkdGggdG8gMS4gV2hpbGUgYWJvdmUgd2UgY291bnQgdGhlIG51bWJlciBvZiBob3NwaXRhbHMgd2l0aCAwLTkgYmVkcyAgMTAtMTkgYmVkcywgMjAtMjkgYmVkcywgZXRjLCB0aGlzIHdpbGwgY291bnQgdGhlIG51bWJlciBvZiBob3NwaXRhbHMgd2l0aCAwIGJlZHMsIDEgYmVkLCAyIGJlZHMsIGFuZCBzbyBvbi4gQmVjYXVzZSB3ZSBhcmUgY291bnRpbmcgdGhlIG51bWJlciBpbiBzdWNoIHNtYWxsIGluY3JlbWVudHMsIHRoZSBwbG90IHdpbGwgbG9vayBtdWNoIG1vcmUgamFnZ2VkIGFuZCB3aWxsIHRha2UgYSBsb25nZXIgdGltZSB0byBsb2FkLiBUaGlzIHBsb3QgZGlzcGxheXMgdGhlIGNvdW50cyBpbiAqZmluZXIqIGdyYW51bGFyaXR5IHRoYW4gdGhlIGZpcnN0IHBsb3QuCgpgYGB7ciBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0xMH0KI1J1biB0aGlzIGNvZGUgY2h1bmsuCgpob3NwaXRhbHMgJT4lIAogIGZpbHRlcihTVEFUVVMgPT0gIk9QRU4iKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBCRURTKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgYm91bmRhcnkgPSAwKSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgQmVkcyBhY3Jvc3MgSG9zcGl0YWxzIGluIHRoZSBVUyB0aGF0IGFyZSBPcGVuIiwgeCA9ICJCZWRzIiwgeSA9ICJDb3VudCBvZiBIb3NwaXRhbHMiKSArCiAgdGhlbWVfYncoKQpgYGAKCldoZW4gd2Ugc2V0IHRoZSBiaW53aWR0aCB0byAxMDAsIHdlIGNvdW50IHRoZSBudW1iZXIgb2YgaG9zcGl0YWxzIHdpdGggMC05OSBiZWRzLCAxMDAtMTk5IGJlZHMsIDIwMC0yOTkgYmVkcywgYW5kIHNvIG9uLiBCZWNhdXNlIHdlIGFyZSBjb3VudGluZyB0aGUgbnVtYmVyIGluIGxhcmdlciBpbmNyZW1lbnRzLCB0aGUgcGxvdCB3aWxsIGxvb2sgbXVjaCBzbW9vdGhlciBhbmQgd2lsbCB0YWtlIGxlc3MgdGltZSB0byBsb2FkLiBUaGlzIHBsb3QgZGlzcGxheXMgdGhlIGNvdW50cyBpbiAqdGhpY2tlciogZ3JhbnVsYXJpdHkgdGhhbiB0aGUgZmlyc3QgcGxvdC4KCmBgYHtyIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTEwfQojUnVuIHRoaXMgY29kZSBjaHVuay4KCmhvc3BpdGFscyAlPiUgCiAgZmlsdGVyKFNUQVRVUyA9PSAiT1BFTiIpICU+JQogIGdncGxvdChhZXMoeCA9IEJFRFMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxMDAsIGJvdW5kYXJ5ID0gMCkgKwogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEJlZHMgYWNyb3NzIEhvc3BpdGFscyBpbiB0aGUgVVMgdGhhdCBhcmUgT3BlbiIsIHggPSAiQmVkcyIsIHkgPSAiQ291bnQgb2YgSG9zcGl0YWxzIikgKwogIHRoZW1lX2J3KCkKYGBgCgojIyMjIFRpdGxpbmcgYSBIaXN0b2dyYW0KCk5vdGUgaG93IEkgdGl0bGVkIG15IHBsb3QgYWJvdmU6ICJEaXN0cmlidXRpb24gb2YgQmVkcyBhY3Jvc3MgSG9zcGl0YWxzIGluIHRoZSBVUyB0aGF0IGFyZSBPcGVuIiBDb25zaWRlciBhZ2FpbiB3aGF0IG1ha2VzIGVhY2ggb2JzZXJ2YXRpb24gdW5pcXVlLiBBIGdvb2QgZm9ybXVsYSBmb3IgdGl0bGluZyBoaXN0b2dyYW1zIGlzIGFzIGZvbGxvd3M6CgpEaXN0cmlidXRpb24gb2YgW3gtYXhpcyB2YXJpYWJsZSBuYW1lXSBhY3Jvc3MgX19fX18gCgpBZ2Fpbiwgd2UgY2FuIGZpbGwgaW4gdGhlIGJsYW5rIHdpdGggb3VyIG9ic2VydmF0aW9uYWwgdW5pdC4gVGhlIFt4LWF4aXMgdmFyaWFibGUgbmFtZV0gc2hvdWxkIGJlIHlvdXIgeC1sYWJlbCBhbmQgIkNvdW50IG9mIF9fX19fXyIgKGZpbGxlZCB0aGUgc2FtZSBhcyBhYm92ZSkgc2hvdWxkIGJlIHlvdXIgeS1sYWJlbC4KCiMjIyMgV2hhdCBpZiBJIGhhdmUgbXVsdGktZGltZW5zaW9uYWwgZGF0YT8KCkluIHRoZSB3b3JsZF9oZWFsdGhfZWNvbiBkYXRhLCB3aXRob3V0IHNlcGFyYXRpbmcgb3V0IHVuaXRzIG9mIG9ic2VydmF0aW9uLCB3ZSB3b3VsZCBiZSB2aXN1YWxpemluZyBtdWx0aXBsZSB2YWx1ZXMgcmVwb3J0ZWQgYXQgdGhlIHNhbWUgcGxhY2UgYXQgZGlmZmVyZW50IHBlcmlvZHMgaW4gdGltZSAoaS5lLiBldmVyeSB5ZWFyIHNpbmNlIDE5OTUpLiBJbnN0ZWFkLCB3ZSB3YW50IHRvIHpvb20gaW50byBhIHNpbmdsZSB5ZWFyIGluIHRoZSBkYXRhc2V0IHNvIHdlIGFyZSBqdXN0IGNvbXBhcmluZyB2YWx1ZXMgYWNyb3NzIHBsYWNlLiAKCmBgYHtyIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTEwfQojUnVuIHRoaXMgY29kZSBjaHVuay4KCndvcmxkX2hlYWx0aF9lY29uICU+JSAKICBmaWx0ZXIoeWVhciA9PSBtYXgoeWVhciwgbmEucm0gPSBUUlVFKSAmIHRvdF9oZWFsdGhfc3BfcHAgPjEwMCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gdG90X2hlYWx0aF9zcF9wcCkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxMDAwLCBib3VuZGFyeSA9IDApICsKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBUb3RhbCBIZWFsdGggU3BlbmRpbmcgcGVyIFBlcnNvbiBhY3Jvc3MgQ291bnRyaWVzIGluIDIwMTAiLCB4ID0gIlRvdGFsIEhlYWx0aCBTcGVuZGluZyBwZXIgUGVyc29uIiwgeSA9ICJDb3VudCBvZiBDb3VudHJpZXMiKSArICMgVG8gYWRkIHRpdGxlcyBhbmQgbGFiZWxzCiAgdGhlbWVfYncoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEpICNDaGFuZ2UgbGFiZWxzIGZyb20gc2NpZW50aWZpYyB0byBjb21tYSBub3RhdGlvbgpgYGAKCj4gTm90ZSB0aGUgYWRkaXRpb24gdG8gbXkgdGl0bGUgYWJvdmUuIElmIHlvdSBmaWx0ZXIgeW91ciBkYXRhc2V0LCB0aGUgZm9ybXVsYSBmb3IgdGl0bGluZyBjaGFuZ2VzIGEgYml0IHRvIERpc3RyaWJ1dGlvbiBvZiBbeC1heGlzIHZhcmlhYmxlIG5hbWVdIGFjcm9zcyBfX19fXyBpbiBbZmlsdGVyZWQgdmFsdWVdCgojIyMjIFNlbGVjdCBhIG51bWVyaWMgdmFyaWFibGUgZm9yIHdoaWNoIHlvdSB3YW50IHRvIHZpc3VhbGl6ZSB0aGUgZGlzdHJpYnV0aW9uIG9mIGEgc2V0IG9mIHZhbHVlcy4gCgpCZSBzdXJlIHRvIHNlbGVjdCBhIHZhcmlhYmxlIHRoYXQgZGVzY3JpYmVzIHNvbWV0aGluZyBhYm91dCB0aGUgb2JzZXJ2YXRpb25hbCB1bml0IGFuZCBub3QgYW5vdGhlciBjYXRlZ29yaWNhbCB2YXJpYWJsZSBpbiB5b3VyIGRhdGFzZXQuIEZvciBpbnN0YW5jZSwgbGV0J3Mgc2F5IHlvdSBoYWQgdGhlIGZvbGxvd2luZyBkYXRhIHRhYmxlIC0gd2l0aCBlYWNoIHJvdyByZXBvcnRpbmcgYW4gZW52aXJvbm1lbnRhbCB2aW9sYXRpb24gYXQgYSBmYWNpbGl0eToKClZpb2xhdGlvbiBOdW1iZXIgfCBGYWNpbGl0eSBOYW1lIHwgRmFjaWxpdHkgVG93biB8IFBvcHVsYXRpb24gb2YgRmFjaWxpdHkgVG93bgpfX19fX19fX19fX19fX19fXyB8IF9fX19fX19fX19fX19fX19fIHwgX19fX19fX19fX19fX19fX18gfCBfX19fX19fX19fX19fX19fXyAKMTIzNDU2NyB8IEZhY2lsaXR5IEEgfCBUYXJyeXRvd24gfCA5MDAwMAoyMzQ1Njc4IHwgRmFjaWxpdHkgQiB8IFRhcnJ5dG93biB8IDkwMDAwCjM0NTY3ODkgfCBGYWNpbGl0eSBDIHwgQW5vdGhlciBUb3duIHwgNzAwMDAKCkluIHRoaXMgdGFibGUsIHdlIHdvdWxkIG5vdCB3YW50IHRvIGNyZWF0ZSBhIGhpc3RvZ3JhbSB3aXRoIHBvcHVsYXRpb24gb2YgZmFjaWxpdHkgdG93bi4gVGhpcyBpcyBiZWNhdXNlIG91ciBvYnNlcnZhdGlvbmFsIHVuaXQgaXMgYSB2aW9sYXRpb24sIG5vdCBhIHRvd24sIGFuZCBwb3B1bGF0aW9uIGRvZXMgbm90IGRlc2NyaWJlIHNvbWV0aGluZyBhYm91dCB0aGUgdmlvbGF0aW9uIGJ1dCBpbnN0ZWFkIGRlc2NyaWJlcyBzb21ldGhpbmcgYWJvdXQgdGhlIHRvd24gdGhlIGZhY2lsaXR5IGlzIGluLiBJZiB3ZSB3ZXJlIHRvIGNyZWF0ZSBhIGhpc3RvZ3JhbSB3aXRoIHRoaXMgdmFyaWFibGUsIHdlIHdvdWxkIGJlIGNvdW50aW5nIHRoZSBudW1iZXIgb2YgdGltZXMgZWFjaCBwb3B1bGF0aW9uIHZhbHVlIGFwcGVhcnMgaW4gdGhlIGRhdGFzZXQgLSBzb21ldGhpbmcgdGhhdCBkb2VzIG5vdCBtYWtlIG11Y2ggc2Vuc2UsIHNpbmNlIHdlIGNhbiBoYXZlIHRoZSBzYW1lIHRvd24ncyBwb3B1bGF0aW9uIGFwcGVhciBzZXZlcmFsIHRpbWVzIGluIHRoZSBkYXRhc2V0IGlmIHRoZXJlIGFyZSBtb3JlIHRoYW4gb25lIHZpb2xhdGlvbnMgb3IgbW9yZSB0aGFuIG9uZSBmYWNpbGl0aWVzIGluIGEgdG93bi4gCgpJZiB5b3UgaGF2ZSBtdWx0aS1kaW1lbnNpb25hbCBkYXRhLCBiZSBzdXJlIHRvIGZpcnN0IHpvb20gaW50byBhIHNldCBvZiBvYnNlcnZhdGlvbnMgaW4geW91ciBkYXRhICh1c2luZyBmaWx0ZXIoKSkuCgpgYGB7ciBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0xMH0KI1VuY29tbWVudCB0aGUgbGluZSBiZWxvdyBhbmQgZmlsbCBhcHByb3ByaWF0ZWx5LiBBZGQgYSB0aXRsZSBhbmQgbGFiZWxzIHRvIHlvdXIgcGxvdHMuIFJ1biB0aGUgY29kZS4KCiNfX19fXyAlPiUgZ2dwbG90KGFlcyh4ID0gX19fX18pKSArIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gX19fX18sIGJvdW5kYXJ5ID0gMCkgCgpgYGAKCkNvcHkgYW5kIHBhc3RlIHRoZSBkZWZpbml0aW9uIG9mIHRoZSBudW1lcmljIHZhcmlhYmxlIHlvdSBzZWxlY3RlZCBmcm9tIHRoZSBkYXRhIGRpY3Rpb25hcnkgYmVsb3cuIAoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCB5b3VyIHJlc3BvbnNlIGhlcmUuIApgYGAKCkNvbXBsZXRlIHRoZSBmb2xsb3dpbmcgc3RhdGVtZW50OgoKYGBge3IgZXZhbD1GQUxTRX0KRWFjaCBiYXIgaW4gdGhlIGhpc3RvZ3JhbSBhYm92ZSBpcyBjb3VudGluZyB0aGUgbnVtYmVyIG9mIF9fX19fIGluIG15IGRhdGFzZXQgYWNjb3JkaW5nIHRvIF9fX19fLgpgYGAKCjEuIFFVRVJZOiBCZWxvdywgd3JpdGUgYSByZXNlYXJjaCBxdWVzdGlvbiB0aGF0IHRoZSBjb2RlIHlvdSBqdXN0IHJhbiBpcyBkZXNpZ25lZCB0byBiZSBhYmxlIHRvIGFuc3dlci4gTWFrZSBzdXJlIHlvdSBwaHJhc2UgeW91ciBxdWVzdGlvbiBkaXJlY3RseSBpbiByZWxhdGlvbiB0byB0aGUgcmVzdWx0cyBvZiB5b3VyIGNvZGUuIEluIG90aGVyIHdvcmRzLCB5b3UgaGF2ZSB0aGUgYW5zd2VyOyBub3cgY29tZSB1cCB3aXRoIHRoZSBxdWVzdGlvbi4gQ29uc2lkZXIgdGhpcyBhIGNoZWNrIG9uIHdoZXRoZXIgeW91IHVuZGVyc3RhbmQgd2hhdCB0aGUgY29kZSBhYm92ZSBpcyBkb2luZy4gSWYgeW91IGFyZSB1bnN1cmUgaG93IHRvIGNvbXBvc2UgdGhpcyBxdWVzdGlvbiwgeW91IHByb2JhYmx5IHdhbnQgdG8gc3R1ZHkgdGhlIGZ1bmN0aW9ucyBhYm92ZSBhIGJpdCBtb3JlIGNsb3NlbHkuCgpgYGB7ciBldmFsPUZBTFNFfQpGaWxsIHlvdXIgcmVzcG9uc2UgaGVyZS4gCmBgYAoKQXJlIHRoZXJlIGFueSBvdGhlciB2YXJpYWJsZXMgaW4geW91ciBkYXRhc2V0IHRoYXQgeW91IG5lZWQgdG8gdGFrZSBpbnRvIGNvbnNpZGVyYXRpb24gYmVmb3JlIGRpcmVjdGluZyB0aGlzIGFuYWx5c2lzIHRvd2FyZHMgYW5zd2VyaW5nIHRoYXQgcXVlc3Rpb24/IEluIG90aGVyIHdvcmRzLCBkbyB5b3UgbmVlZCB0byB6b29tIGludG8gYW55IHNwZWNpZmljIGFyZWFzIG9mIHRoZSBkYXRhc2V0IChieSBmaWx0ZXJpbmcpIGluIG9yZGVyIHRvIGFwcHJvcHJpYXRlbHkgYWRkcmVzcyB0aGlzIHF1ZXN0aW9uPyBJZiBzbywgd2hpY2g/IChGb3IgaW5zdGFuY2UsIGZvciB0aGUgaG9zcGl0YWxzIGRhdGFzZXQgd2UgbmVlZGVkIHRvIGZpbHRlciB0byBob3NwaXRhbHMgdGhhdCB3ZXJlIE9QRU4gaW4gb3JkZXIgdG8gYWRkcmVzcyBxdWVzdGlvbnMgYWJvdXQgaW5mcmFzdHJ1Y3R1cmUpLiBCcmllZmx5IG5vdGUgdGhpcyBiZWxvdy4gCgpgYGB7ciBldmFsPUZBTFNFfQpGaWxsIHlvdXIgcmVzcG9uc2UgaGVyZS4gCmBgYAoKMi4gU1VNTUFSSVpFOiBSZXZpZXdpbmcgdGhlIG91dHB1dCBvZiB5b3VyIGNvZGUsIHN1bW1hcml6ZSBvbmUgdGhpbmcgdGhhdCB5b3UgbGVhcm4gYWJvdXQgeW91ciB0b3BpYyBmcm9tIHJ1bm5pbmcgdGhpcyBjb2RlIGNodW5rLiBJbiBvdGhlciB3b3Jkcywgd2hhdCBpcyBvbmUgdGhpbmcgdGhhdCB0aGUgcmVzdWx0cyBvZiB0aGlzIGFuYWx5c2lzIGVtcGlyaWNhbGx5IHRlbGwgdXMgYWJvdXQgdGhlIHRvcGljPyBCZSBzcGVjaWZpYywgY29uc2lkZXJpbmcgdGhlIGdlb2dyYXBoaWMsIHRlbXBvcmFsLCBhbmQgdG9waWNhbCBzY29wZSBvZiB5b3VyIGRhdGEuCgpgYGB7ciBldmFsPUZBTFNFfQpGaWxsIHlvdXIgcmVzcG9uc2UgaGVyZS4gCmBgYAoKMy4gSU5URVJQUkVUOiBOb3cgaW1hZ2luZSB5b3Ugd2VyZSByZXBvcnRpbmcgeW91ciBmaW5kaW5ncyB0byBhIGRlY2lzaW9uLW1ha2VyIG9uIHlvdXIgdG9waWMuIERlc2NyaWJlIHRvIHRoYXQgZGVjaXNpb24tbWFrZXIgd2h5IHRoZXkgc2hvdWxkIGNhcmUuIEluIG90aGVyIHdvcmRzLCAqaW50ZXJwcmV0KiB3aGF0IGlzIGltcG9ydGFudCBhYm91dCB0aGlzIGZpbmRpbmcuIAoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCB5b3VyIHJlc3BvbnNlIGhlcmUuIApgYGAKCjRhLiBSRUZMRUNUOiBSZWZsZWN0IG9uIHRoZSBkaXN0cmlidXRpb24gb2YgdmFsdWVzLiBXaGF0IGFyZSB0aGUgcmFuZ2Ugb2YgdmFsdWVzIHJlcHJlc2VudGVkIGluIHRoZSBkYXRhPyBBcmUgdGhlIHZhbHVlcyBldmVubHkgZGlzdHJpYnV0ZWQsIG9yIGFyZSBjZXJ0YWluIHZhbHVlcyBtb3JlIHJlcHJlc2VudGVkIHRoYW4gb3RoZXJzPyBXaHkgbWlnaHQgdGhpcyBiZT8gRG8gYW55IG9mIHRoZSB2YWx1ZXMgc3VycHJpc2UgeW91PyBXaHk/IAoKCmBgYHtyIGV2YWw9RkFMU0V9CkZpbGwgcmVzcG9uc2UgaGVyZS4gCmBgYAoKNGIuIFJFRkxFQ1Q6IFdoeSBkaWQgeW91IHNlbGVjdCB0aGUgYmlud2lkdGggdGhhdCB5b3UgZGlkPyBIb3cgbWlnaHQgdGhlIHN0b3J5IHlvdXIgcGxvdCB0ZWxscyBjaGFuZ2UgaWYgeW91IHdlcmUgdG8gY2hhbmdlIHRoZSBiaW53aWR0aD8gV2hhdCBhbm9tYWxpZXMgbWlnaHQgYmUgaGlkZGVuIHdpdGggYSBsYXJnZXIgYmlud2lkdGgsIGFuZCB3aGF0IHRyZW5kcyBtaWdodCBiZSBoaWRkZW4gd2l0aCBhIHNtYWxsZXIgYmlud2lkdGg/CgpgYGB7ciBldmFsPUZBTFNFfQpGaWxsIHJlc3BvbnNlIGhlcmUuIApgYGAKCjRjLiBSRUZMRUNUOiBDaGVjayBob3cgdGhlIG51bWVyaWMgdmFyaWFibGUgd2FzIGRlZmluZWQgaW4gdGhlIGRhdGEgZGljdGlvbmFyeSwgYW5kIHF1b3RlIHRoZSBkZWZpbml0aW9uIGJlbG93LiBIb3cgbWlnaHQgdGhlIGNvdW50cyByZXByZXNlbnRlZCBpbiB5b3VyIGZyZXF1ZW5jeSBwbG90IGFwcGVhciBkaWZmZXJlbnRseSBpZiB0aGlzIHZhcmlhYmxlIHdhcyBkZWZpbmVkIGRpZmZlcmVudGx5PwoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCByZXNwb25zZSBoZXJlLiAKYGBgCgojIyBDby12YXJpYXRpb24KCkNvLXZhcmlhdGlvbiBpcyB0aGUgZXh0ZW50IHRvIHdoaWNoIHRoZSB2YWx1ZXMgdGhhdCBjb25zdGl0dXRlIHR3byBvciBtb3JlIHZhcmlhYmxlcyB2YXJ5IGluIHJlbGF0aW9uIHRvIG9uZSBhbm90aGVyLiBUbyB2aXN1YWxpemUgY28tdmFyaWF0aW9uLCB3ZSBtaWdodCBjcmVhdGU6CgojIyMgQ291bnQgUGxvdHMKCipDb3VudCBwbG90cyogZGlzcGxheSBob3cgbWFueSB0aW1lcyB0d28gY2F0ZWdvcmljYWwgdmFsdWVzIGFwcGVhciB0b2dldGhlciBpbiBhIGRhdGFzZXQuIEZvciBpbnN0YW5jZSwgaW4gdGhlIGNvdW50IHBsb3QgYmVsb3csIHdlIGRpc3BsYXkgdGhlIG51bWJlciBvZiBvcGVuIGhvc3BpdGFscyB3aXRoIGVhY2ggY29tYmluYXRpb24gb2YgT1dORVIgYW5kIFRZUEUuCgpgYGB7ciBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0xMH0KI1J1biB0aGlzIGNvZGUgY2h1bmsuCgojZGYgJT4lIGdncGxvdChhZXMoeCA9IENBVEVHT1JJQ0FMX1ZBUklBQkxFLCB5ID0gQ0FURUdPUklDQUxfVkFSSUFCTEUpKSArIGdlb21fY291bnQoKQoKaG9zcGl0YWxzICU+JSAKICBmaWx0ZXIoU1RBVFVTID09ICJPUEVOIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gVFlQRSwgeSA9IE9XTkVSKSkgKyAKICBnZW9tX2NvdW50KCkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0PTEpKSArCiAgbGFicyh0aXRsZSA9ICJOdW1iZXIgb2YgSG9zcGl0YWxzIGluIHRoZSBVUyB0aGF0IGFyZSBPcGVuIGJ5IFR5cGUgYW5kIE93bmVyc2hpcCIsIHggPSAiVHlwZSIsIHkgPSAiT3duZXJzaGlwIiwgc2l6ZSA9ICJOdW1iZXIgb2YgSG9zcGl0YWxzIikKYGBgCgojIyMjIFRpdGxpbmcgYSBDb3VudCBQbG90CgpOb3RlIGhvdyBJIHRpdGxlZCBteSBwbG90IGFib3ZlOiAiTnVtYmVyIG9mIEhvc3BpdGFscyBpbiB0aGUgVVMgdGhhdCBhcmUgT3BlbiBieSBUeXBlIGFuZCBPd25lcnNoaXAiIENvbnNpZGVyIGFnYWluIHdoYXQgbWFrZXMgZWFjaCBvYnNlcnZhdGlvbiB1bmlxdWUuIEhlcmUgSSBhbSBjb3VudGluZyB0aGUgb2JzZXJ2YXRpb25zIGJ5IFR5cGUgYW5kIE93bmVyc2hpcCwgYW5kIGluIG9yZGVyIHRvIGtub3cgd2hhdCBJJ20gY291bnRpbmcsIEkgbmVlZCB0byBrbm93IHdoYXQgZWFjaCBvYnNlcnZhdGlvbiByZWZlcnMgdG8uIEEgZ29vZCBmb3JtdWxhIGZvciB0aXRsaW5nIGNvdW50IHBsb3RzIGlzIGFzIGZvbGxvd3M6CgpOdW1iZXIgb2YgX19fX18gYnkgW3gtYXhpcyB2YXJpYWJsZSBuYW1lXSBhbmQgW3ktYXhpcyB2YXJpYWJsZSBuYW1lXQoKVGhlIGJsYW5rIHNob3VsZCBiZSBmaWxsZWQgd2l0aCB5b3VyIHVuaXQgb2Ygb2JzZXJ2YXRpb24uIFRoZSBbeC1heGlzIHZhcmlhYmxlIG5hbWVdIHNob3VsZCBiZSB5b3VyIHgtbGFiZWwgYW5kIFt5LWF4aXMgdmFyaWFibGUgbmFtZV0gc2hvdWxkIGJlIHlvdXIgeS1sYWJlbC4gWW91IHNob3VsZCBhbHNvIHNldCB0aGUgc2l6ZSBhdHRyaWJ1dGUgbGFiZWwgdG8gIk51bWJlciBvZiBbb2JzZXJ2YXRpb25hbCB1bml0XSIKCiMjIyMgV2hhdCBpZiBJIGhhdmUgbXVsdGktZGltZW5zaW9uYWwgZGF0YT8KCklmIHRoaXMgaXMgdGhlIGNhc2UgSSB3b3VsZCBlbmNvdXJhZ2UgeW91IHRvIGluY2x1ZGUgb25lIG9mIHRoZSB2YXJpYWJsZXMgaW4geW91ciB1bmlxdWUga2V5IGluIHRoZSB4IG9yIHktYXhpcy4gRm9yIGluc3RhbmNlLCBpZiB0aGUgdW5pcXVlIGtleSBmb3Igd29ybGRfaGVhbHRoX2Vjb24gaXMgY291bnRyeSBhbmQgeWVhciwgSSBjYW4gaW5jbHVkZSB5ZWFyIGFzIHRoZSB5LWF4aXMgYmVsb3cgdG8gdmlzdWFsaXplIGhvdyBjb3VudHMgb2Ygb2JzZXJ2YXRpb25zIGNoYW5nZSBvdmVyIHRpbWUuIChOb3RpY2UgaG93IHRoZXkgZG9uJ3QgaW4gdGhlIHBsb3QgYmVsb3cuKSBBbHRlcm5hdGl2ZWx5LCBpZiB5b3Ugd2lzaCB0byBjb21wYXJlIHR3byBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgdGhhdCBhcmUgbm90IGEgcGFydCBvZiB0aGUgdW5pcXVlIGtleSwgYmUgc3VyZSB0byBmaWx0ZXIgdGhlIGRhdGEgc28gdGhhdCBvbmx5IG9uZSB2YXJpYWJsZSBjb25zdGl0dXRlcyB0aGUgdW5pcXVlIGtleS4KCmBgYHtyIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTEwfQojUnVuIHRoaXMgY29kZSBjaHVuay4KCndvcmxkX2hlYWx0aF9lY29uICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBjb250aW5lbnQsIHkgPSBhcy5mYWN0b3IoeWVhcikpKSArIAogIGdlb21fY291bnQoKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3Q9MSkpICsKICBsYWJzKHRpdGxlID0gIk51bWJlciBvZiBDb3VudHJpZXMgYnkgQ29udGluZW50IGFuZCBZZWFyIiwgeCA9ICJDb250aW5lbnQiLCB5ID0gIlllYXIiKQpgYGAKCiMjIyBTdGFja2VkIEZyZXF1ZW5jeSBQbG90cyAKClNpbWlsYXIgdG8gaGlzdG9ncmFtcywgZnJlcXVlbmN5IHBsb3RzIGRpc3BsYXkgdGhlIGRpc3RyaWJ1dGlvbiBvZiBudW1lcmljIHZhbHVlcyBpbiBhIHZhcmlhYmxlLiBJbiBvdGhlciB3b3JkcywgdGhleSAqY291bnQqIHRoZSBudW1iZXIgb2JzZXJ2YXRpb25zIGluIGEgZGF0YXNldCB0aGF0IGZhbGwgaW50byBlYWNoIGJyYWNrZXRlZCBpbmNyZW1lbnQgb2YgYSBudW1lcmljIHZhcmlhYmxlLiBVbmxpa2UgaGlzdG9ncmFtcywgdGhleSBkaXNwbGF5IHRoZXNlIHZhbHVlcyBhcyBsaW5lcyByYXRoZXIgdGhhbiBhcyBiYXJzLiBXZSB0ZW5kIHRvIHVzZSBmcmVxdWVuY3kgcGxvdHMgaW5zdGVhZCBvZiBoaXN0b2dyYW1zIHdoZW4gd2UgYXJlIGxvb2tpbmcgdG8gY29tcGFyZSBmcmVxdWVuY2llcyBhY3Jvc3MgZGlmZmVyZW50IHZhbHVlcyBpbiBhIGNhdGVnb3JpY2FsIHZhcmlhYmxlLiAqU3RhY2tlZCBmcmVxdWVuY3kgcGxvdHMqIGRpc3BsYXkgdGhlIGRpc3RyaWJ1dGlvbiBvZiBudW1lcmljIHZhbHVlcyBpbiBhIHZhcmlhYmxlLCBncm91cGVkIGJ5IGEgY2F0ZWdvcmljYWwgdmFsdWUuIEZvciBpbnN0YW5jZSwgdGhlIHBsb3QgYmVsb3cgZGlzcGxheSB0aGUgZGlzdHJpYnV0aW9uIG9mIGJlZHMgYWNyb3NzIG9wZW4gaG9zcGl0YWxzLCBjYXRlZ29yaXplZCBieSB0aGUgaG9zcGl0YWwgdHlwZS4KCmBgYHtyIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTEwfQojUnVuIHRoaXMgY29kZSBjaHVuay4KCiNkZiAlPiUgZ2dwbG90KGFlcyh4ID0gTlVNRVJJQ19WQVJJQUJMRSwgY29sID0gQ0FURUdPUklDQUxfVkFSSUFCTEUpKSArIGdlb21fZnJlcXBvbHkoYmlud2lkdGggPSAxKQoKaG9zcGl0YWxzICU+JSAKICBmaWx0ZXIoU1RBVFVTID09ICJPUEVOIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gQkVEUywgY29sID0gVFlQRSkpICsgCiAgZ2VvbV9mcmVxcG9seShiaW53aWR0aCA9IDEwMCwgYm91bmRhcnkgPSAwKSArCiAgbGFicyh0aXRsZSA9ICJGcmVxdWVuY3kgb2YgQmVkcyBhY3Jvc3MgSG9zcGl0YWxzIGluIHRoZSBVUyB0aGF0IGFyZSBPcGVuIGJ5IEhvc3BpdGFsIFR5cGUiLCB4ID0gIkJlZHMiLCB5ID0gIkNvdW50IG9mIEhvc3BpdGFsIiwgY29sID0gIlR5cGUiKSArICMgVG8gYWRkIHRpdGxlcyBhbmQgbGFiZWxzCiAgdGhlbWVfYncoKSAKYGBgCgpTdGFja2VkIGZyZXF1ZW5jeSBwbG90cyB3b3JrIGJlc3Qgd2hlbiBjYXRlZ29yaXppbmcgYnkgYSB2YXJpYWJsZSB3aXRoIDEwIG9yIGZld2VyIGRpc3RpbmN0IHZhbHVlcy4gT3RoZXJ3aXNlLCBpdCBjYW4gYmUgdHJpY2t5IHRvIHNlZSB0aGUgZGlmZmVyZW5jZXMgaW4gY29sb3IgZ3JhZGF0aW9ucy4gSWYgYWxsIG9mIHlvdXIgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGhhdmUgbW9yZSB0aGFuIDEwIGRpc3RpbmN0IHZhbHVlcywgb25lIHRoaW5nIHlvdSBtaWdodCBjb25zaWRlciBpcyBmaXJzdCBmaWx0ZXJpbmcgeW91ciBkYXRhIHRvIGEgZmV3IHJlcHJlc2VudGF0aXZlIGNhdGVnb3JpZXMuIEZvciBpbnN0YW5jZSwgbGV0J3Mgc2F5IHRoYXQgSSB3b3VsZCBsaWtlIHRvIHNlZSB0aGUgZGlzdHJpYnV0aW9uIG9mIGJlZHMgaW4gaG9zcGl0YWxzIGFjcm9zcyBzdGF0ZXMuIFNpbmNlIHRoZXJlIGFyZSA1NyBzdGF0ZXMsIGlmIEkgd2VyZSB0byBjYXRlZ29yaXplIHRoZSBkaXN0cmlidXRpb24gYnkgc3RhdGUsIHRoZSBwbG90IHdvdWxkIGJlIHZlcnkgZGlmZmljdWx0IHRvIHJlYWQuCgpgYGB7ciBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0xMH0KI1J1biB0aGlzIGNvZGUgY2h1bmsuCgojZGYgJT4lIGdncGxvdChhZXMoeCA9IE5VTUVSSUNfVkFSSUFCTEUsIGNvbCA9IENBVEVHT1JJQ0FMX1ZBUklBQkxFKSkgKyBnZW9tX2ZyZXFwb2x5KGJpbndpZHRoID0gMSkKCmhvc3BpdGFscyAlPiUgCiAgZmlsdGVyKFNUQVRVUyA9PSAiT1BFTiIpICU+JQogIGdncGxvdChhZXMoeCA9IEJFRFMsIGNvbCA9IFNUQVRFKSkgKyAKICBnZW9tX2ZyZXFwb2x5KGJpbndpZHRoID0gMTAwLCBib3VuZGFyeSA9IDApICsKICBsYWJzKHRpdGxlID0gIkZyZXF1ZW5jeSBvZiBCZWRzIGFjcm9zcyBIb3NwaXRhbHMgaW4gdGhlIFVTIHRoYXQgYXJlIE9wZW4gYnkgSG9zcGl0YWwgU3RhdGUiLCB4ID0gIkJlZHMiLCB5ID0gIkNvdW50IG9mIEhvc3BpdGFsIiwgY29sID0gIlR5cGUiKSArICMgVG8gYWRkIHRpdGxlcyBhbmQgbGFiZWxzCiAgdGhlbWVfYncoKSAKYGBgCgpJbiB0aGlzIGNhc2UsIHdlIG1heSB3aXNoIHRvIGZpcnN0IGZpbHRlciBvdXIgZGF0YSB0byBhIGZldyByZXByZXNlbnRhdGl2ZSBzdGF0ZXMgdXNpbmcgKiolaW4lKiouCgpgYGB7ciBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0xMH0KI1J1biB0aGlzIGNvZGUgY2h1bmsuCgojZGYgJT4lIGdncGxvdChhZXMoeCA9IE5VTUVSSUNfVkFSSUFCTEUsIGNvbCA9IENBVEVHT1JJQ0FMX1ZBUklBQkxFKSkgKyBnZW9tX2ZyZXFwb2x5KGJpbndpZHRoID0gMSkKCmhvc3BpdGFscyAlPiUgCiAgZmlsdGVyKFNUQVRVUyA9PSAiT1BFTiIgJiBTVEFURSAlaW4lIChjKCJDQSIsICJNQSIsICJOWSIsICJGTCIsICJMQSIpKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gQkVEUywgY29sID0gU1RBVEUpKSArIAogIGdlb21fZnJlcXBvbHkoYmlud2lkdGggPSAxMDAsIGJvdW5kYXJ5ID0gMCkgKwogIGxhYnModGl0bGUgPSAiRnJlcXVlbmN5IG9mIEJlZHMgYWNyb3NzIEhvc3BpdGFscyBpbiB0aGUgVVMgdGhhdCBhcmUgT3BlbiBieSBIb3NwaXRhbCBTdGF0ZSIsIHggPSAiQmVkcyIsIHkgPSAiQ291bnQgb2YgSG9zcGl0YWwiLCBjb2wgPSAiVHlwZSIpICsgIyBUbyBhZGQgdGl0bGVzIGFuZCBsYWJlbHMKICB0aGVtZV9idygpIApgYGAKCiMjIyMgVGl0bGluZyBhIFN0YWNrZWQgRnJlcXVlbmN5IFBsb3QKCk5vdGUgaG93IEkgdGl0bGVkIG15IHBsb3QgYWJvdmU6ICJEaXN0cmlidXRpb24gb2YgQmVkcyBhY3Jvc3MgSG9zcGl0YWxzIGluIHRoZSBVUyB0aGF0IGFyZSBPcGVuIGJ5IEhvc3BpdGFsIFR5cGUiIENvbnNpZGVyIGFnYWluIHdoYXQgbWFrZXMgZWFjaCBvYnNlcnZhdGlvbiB1bmlxdWUuIEhlcmUgSSBhbSBjb3VudGluZyB0aGUgb2JzZXJ2YXRpb25zIGJ5IG51bWJlciBvZiBCZWRzIGFuZCBIb3NwaXRhbCBUeXBlLiBBIGdvb2QgZm9ybXVsYSBmb3IgdGl0bGluZyBzdGFja2VkIGZyZXF1ZW5jeSBwbG90cyBpcyBhcyBmb2xsb3dzOiAKCkRpc3RyaWJ1dGlvbiBvZiBbeC1heGlzIHZhcmlhYmxlIG5hbWVdIGFjcm9zcyBfX19fXyBieSBbY29sIHZhcmlhYmxlIG5hbWVdCgpUaGUgYmxhbmsgc2hvdWxkIGJlIGZpbGxlZCB3aXRoIHlvdXIgdW5pdCBvZiBvYnNlcnZhdGlvbi4gVGhlIFt4LWF4aXMgdmFyaWFibGUgbmFtZV0gc2hvdWxkIGJlIHlvdXIgeC1sYWJlbCwgIkNvdW50IG9mIF9fX19fXyIgKGZpbGxlZCB0aGUgc2FtZSBhcyBhYm92ZSkgc2hvdWxkIGJlIHlvdXIgeS1sYWJlbCwgYW5kIHRoZSBbY29sIHZhcmlhYmxlIG5hbWVdIHNob3VsZCBiZSB5b3VyIGNvbC1sYWJlbC4KCiMjIyMgV2hhdCBpZiBJIGhhdmUgbXVsdGktZGltZW5zaW9uYWwgZGF0YT8KCklmIHRoaXMgaXMgdGhlIGNhc2UgSSB3b3VsZCBlbmNvdXJhZ2UgeW91IHRvIGluY2x1ZGUgb25lIG9mIHRoZSB2YXJpYWJsZXMgaW4geW91ciB1bmlxdWUga2V5IGluIHRoZSBjb2wgdmFyaWFibGUuIEZvciBpbnN0YW5jZSwgaWYgd29ybGRfaGVhbHRoX2Vjb24gaXMgdW5pcXVlIGJ5IGNvdW50cnkgYW5kIHllYXIsIEkgY2FuIGluY2x1ZGUgeWVhciBhcyB0aGUgY29sIHZhcmlhYmxlIGJlbG93IHRvIHZpc3VhbGl6ZSBob3cgdGhlIGZyZXF1ZW5jeSBvZiBjb3VudHJpZXMgd2l0aCB2YXJpb3VzIGxpZmUgZXhwZWN0YW5jaWVzIGNoYW5nZXMgb3ZlciB0aW1lLiAKCmBgYHtyIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTEwfQojUnVuIHRoaXMgY29kZSBjaHVuay4KCiNkZiAlPiUgZ2dwbG90KGFlcyh4ID0gTlVNRVJJQ19WQVJJQUJMRSwgY29sID0gQ0FURUdPUklDQUxfVkFSSUFCTEUpKSArIGdlb21fZnJlcXBvbHkoYmlud2lkdGggPSAxKQoKd29ybGRfaGVhbHRoX2Vjb24gJT4lIAogIGdncGxvdChhZXMoeCA9IGxpZmVfZXhwLCBjb2wgPSBhcy5mYWN0b3IoeWVhcikpKSArIAogIGdlb21fZnJlcXBvbHkoYmlud2lkdGggPSA1LCBib3VuZGFyeSA9IDApICsKICB0aGVtZV9idygpICsKICBsYWJzKHRpdGxlID0gIkZyZXF1ZW5jeSBvZiBMaWZlIEV4cGVjdGFuY2llcyBhY3Jvc3MgQ291bnRyaWVzIGJ5IFllYXIiLCB4ID0gIkxpZmUgRXhwZWN0YW5jeSIsIHkgPSAiQ291bnQgb2YgQ291bnRyaWVzIiwgY29sID0gIkxpZmUgRXhwZWN0YW5jeSIpIApgYGAKCj4gTm90ZSB0aGF0IHRoaXMgaXMgb25lIHBsb3QgdGhhdCBpcyBwYXJ0aWN1bGFybHkgc3VzY2VwdGlibGUgdG8gbWlzc2luZyBkYXRhLiBJZiBjZXJ0YWluIGNvdW50cmllcyBkaWQgbm90IHJlcG9ydCBkYXRhIGluIGNlcnRhaW4geWVhcnMsIHRoZSBjb3VudCBvZiBjb3VudHJpZXMgaW4gYSBicmFja2V0IHdpbGwgYXBwZWFyIGxvd2VyLCBub3QgbmVjZXNzYXJpbHkgYmVjYXVzZSBmZXdlciBjb3VudHJpZXMgZmVsbCB3aXRoaW4gYSBjZXJ0YWluIGxpZmUgZXhwZWN0YW5jeSBicmFja2V0LCBidXQgYmVjYXVzZSBmZXdlciBjb3VudHJpZXMgcmVwb3J0ZWQgdGhhdCBsaWZlIGV4cGVjdGFuY3kuIAoKQWx0ZXJuYXRpdmVseSwgeW91IGNvdWxkIHpvb20gaW4gdG8gb25lIHZhbHVlIGluIG9uZSBvZiB0aGUgdmFyaWFibGVzIGluIHlvdSB1bmlxdWUga2V5LCBmaWx0ZXJpbmcgdG8gYSBzcGVjaWZpYyBzdWJzZXQgb2Ygb2JzZXJ2YXRpb25zIGFuZCB0aGVuIGRpdmlkZSBieSBhIGRpZmZlcmVudCBjYXRlZ29yaWNhbCB2YXJpYWJsZS4gCgpgYGB7ciBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0xMH0KI1J1biB0aGlzIGNvZGUgY2h1bmsuCgojZGYgJT4lIGdncGxvdChhZXMoeCA9IE5VTUVSSUNfVkFSSUFCTEUsIGNvbCA9IENBVEVHT1JJQ0FMX1ZBUklBQkxFKSkgKyBnZW9tX2ZyZXFwb2x5KGJpbndpZHRoID0gMSkKCndvcmxkX2hlYWx0aF9lY29uICU+JSAKICBmaWx0ZXIoeWVhciA9PSBtYXgoeWVhciwgbmEucm0gPSBUUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gbGlmZV9leHAsIGNvbCA9IGNvbnRpbmVudCkpICsgCiAgZ2VvbV9mcmVxcG9seShiaW53aWR0aCA9IDUsIGJvdW5kYXJ5ID0gMCkgKwogIHRoZW1lX2J3KCkgKwogIGxhYnModGl0bGUgPSAiRnJlcXVlbmN5IG9mIExpZmUgRXhwZWN0YW5jaWVzIGFjcm9zcyBDb3VudHJpZXMgYnkgQ29udGluZW50IGluIDIwMTAiLCB4ID0gIkxpZmUgRXhwZWN0YW5jeSIsIHkgPSAiQ291bnQgb2YgQ291bnRyaWVzIiwgY29sID0gIkNvbnRpbmVudCIpCmBgYAoKIyMjIFBvaW50IHBsb3RzCgoqUG9pbnQgcGxvdHMqIGRpc3BsYXkgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGEgY2F0ZWdvcmljYWwgdmFyaWFibGUgYW5kIGEgbnVtZXJpYyB2YXJpYWJsZS4gRm9yIGluc3RhbmNlLCB0aGUgcGxvdCBiZWxvdyBkaXNwbGF5cyBhIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGhvc3BpdGFsIHR5cGUgYW5kIHRoZSBudW1iZXIgb2YgYmVkcyBhdCB0aGUgaG9zcGl0YWwuIE5vdGFibHksIHVubGlrZSB0aGUgcGxvdHMgd2UgaGF2ZSBiZWVuIHZpZXdpbmcgdW50aWwgbm93LCB3aXRoIHBvaW50IHBsb3RzLCB3ZSBzZWUgYSBwb2ludCBmb3IgZXZlcnkgb2JzZXJ2YXRpb24gaW4gdGhlIGRhdGFzZXQuIEJlY2F1c2UgcG9pbnQgcGxvdHMgZGlzcGxheSBldmVyeSBvYnNlcnZhdGlvbiAocmF0aGVyIHRoYW4gYWdncmVnYXRpbmcgdGhlbSBpbnRvIG90aGVyIHBvbHlnb25zIGFuZCBsaW5lcyksIHRoZXkgYXJlIHBhcnRpY3VsYXJseSBnb29kIGZvciBzZWVpbmcgb3V0bGllcnMgaW4gdGhlIGRhdGEuIEhvd2V2ZXIsIHdpdGggbGFyZ2UgZGF0YXNldHMsIHRoaXMgYWxzbyBjYW4gbWVhbiB0aGF0IHBvaW50cyB3aWxsIG92ZXJsYXAuIE5vdGUgdGhhdCB0aGUgZmlyc3QgcGxvdCBiZWxvdyBleGhpYml0cyBvdmVycGxvdHRpbmcgLSB3aGVuIHRoZSBkYXRhIHJlcHJlc2VudGVkIG9uIGEgcGxvdCBvdmVybGFwcywgbWFraW5nIGl0IGRpZmZpY3VsdCB0byBkaXNjZXJuIG9uZSBwb2ludCBmcm9tIHRoZSBuZXh0LiBUaGVyZSBhcmUgdmFyaW91cyB0b29scyBhdmFpbGFibGUgdG8gZGVhbCB3aXRoIG92ZXItcGxvdHRpbmcuIFlvdSBjYW4gcmVkdWNlIHRoZSBzaXplIG9mIHBvaW50cyBvbiB0aGUgcGxvdCwgaW5jcmVhc2UgdGhlaXIgdHJhbnNwYXJlbmN5LCBvciBzZXQgdGhlbSB0byBzbGlnaHRseSBvZmZzZXQgZWFjaCBvdGhlciAoa25vd24gYXMgYWRkaW5nIGppdHRlcikuIFdlIGRvIGFsbCB0aHJlZSBpbiB0aGUgc2Vjb25kIHBsb3QgYmVsb3cuCgpgYGB7ciBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0xMH0KI1J1biB0aGlzIGNvZGUgY2h1bmsuCgojZGYgJT4lIGdncGxvdChhZXMoeCA9IENBVEVHT1JJQ0FMX1ZBUklBQkxFLCB5ID0gTlVNRVJJQ19WQVJJQUJMRSkpICsgZ2VvbV9wb2ludCgpCgpob3NwaXRhbHMgJT4lIAogIGZpbHRlcihTVEFUVVMgPT0gIk9QRU4iKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBUWVBFLCB5ID0gQkVEUykpICsgCiAgZ2VvbV9wb2ludCgpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdD0xKSkgKwogIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIEJlZHMgaW4gSG9zcGl0YWxzIGJ5IFR5cGUiLCB4ID0gIlR5cGUiLCB5ID0gIk51bWJlciBvZiBCZWRzIikKCgpob3NwaXRhbHMgJT4lIAogIGZpbHRlcihTVEFUVVMgPT0gIk9QRU4iKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBUWVBFLCB5ID0gQkVEUykpICsgCiAgZ2VvbV9qaXR0ZXIoc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjEpICsgI0NoYW5nZSBnZW9tX3BvaW50IHRvIGdlb21faml0dGVyLCByZWR1Y2UgdGhlIHNpemUsIGFkZCB0cmFuc3BhcmVuY3kgZm9yIG92ZXJwbG90dGluZwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0PTEpKSArCiAgbGFicyh0aXRsZSA9ICJOdW1iZXIgb2YgQmVkcyBpbiBIb3NwaXRhbHMgYnkgVHlwZSIsIHggPSAiVHlwZSIsIHkgPSAiTnVtYmVyIG9mIEJlZHMiKQoKYGBgCgojIyMjIFRpdGxpbmcgYSBQb2ludCBQbG90CgpOb3RlIGhvdyBJIHRpdGxlZCBteSBwbG90IGFib3ZlOiAiTnVtYmVyIG9mIEJlZHMgaW4gSG9zcGl0YWxzIGluIHRoZSBVUyB0aGF0IGFyZSBPcGVuIGJ5IFR5cGUiIEhlcmUgSSBhbSBkaXNwbGF5aW5nIHRoZSBudW1iZXIgb2YgYmVkcyBieSBUeXBlLiBBIGdvb2QgZm9ybXVsYSBmb3IgdGl0bGluZyBwb2ludCBwbG90cyBpcyBhcyBmb2xsb3dzOgoKTnVtYmVyL01lYXN1cmUgb2YgW3ktYXhpcyB2YXJpYWJsZSBuYW1lXSBpbiBfX19fXyBieSBbeC1heGlzIHZhcmlhYmxlIG5hbWVdIAoKVGhlIGJsYW5rIHNob3VsZCBiZSBmaWxsZWQgd2l0aCB5b3VyIHVuaXQgb2Ygb2JzZXJ2YXRpb24uIFRoZSBbeC1heGlzIHZhcmlhYmxlIG5hbWVdIHNob3VsZCBiZSB5b3VyIHgtbGFiZWwgYW5kICJOdW1iZXIvTWVhc3VyZSBvZiBbeS1heGlzIHZhcmlhYmxlIG5hbWVdIiBzaG91bGQgYmUgeW91ciB5LWxhYmVsLgoKIyMjIyBXaGF0IGlmIEkgaGF2ZSBtdWx0aS1kaW1lbnNpb25hbCBkYXRhPwoKSWYgdGhpcyBpcyB0aGUgY2FzZSBJIHdvdWxkIGVuY291cmFnZSB5b3UgdG8gZmlsdGVyIHlvdXIgZGF0YSBhcyB5b3UgaGF2ZSBiZWVuIGRvaW5nIGVsc2V3aGVyZS4gRm9yIGluc3RhbmNlIGlmIGNhc2VzIGlzIHVuaXF1ZSBieSBjb3VudHksIHN0YXRlLCBhbmQgZGF0ZSwgSSBjYW4gZmlsdGVyIHRvIHRoZSBtb3N0IHJlY2VudCBkYXRlIGJlZm9yZSBjcmVhdGluZyBhIHBvaW50IHBsb3Qgb2YgdGhlIGNhc2VzIGJ5IHN0YXRlLiBUaGlzIHdpbGwgc2hvdyBtZSB0aGUgZGlmZmVyZW5jZXMgaW4gY2FzZXMgYWNyb3NzIHRoZSB0aGlyZCB2YXJpYWJsZSBpbiBteSB1bmlxdWUga2V5IC0gY291bnR5LiBOb3RlIHRoYXQgdG8gY3JlYXRlIG15IHRpdGxlLCBJIHdpbGwgbmVlZCB0byBjcmVhdGUgYSBzdHJpbmcgdGhhdCBpbmNsdWRlcyB0aGUgbW9zdCByZWNlbnQgZGF0ZS4gSSBhbHNvIGRvIHRoaXMgYmVsb3csIHVzaW5nIHN1bW1hcml6ZSAoYSBmdW5jdGlvbiB3ZSB3aWxsIGdvIG92ZXIgbmV4dCB3ZWVrKS4KCmBgYHtyIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTEwfQojUnVuIHRoaXMgY29kZSBjaHVuay4KCnBsb3RfdGl0bGUgPC0gcGFzdGUoIkNvdmlkLTE5IENhc2VzIHBlciBDb3VudHkgYnkgU3RhdGUgYXMgb2YiLCBjYXNlcyAlPiUgc3VtbWFyaXplKGRhdGUgPSBtYXgoZGF0ZSwgbmEucm0gPSBUUlVFKSkgJT4lIHB1bGwoKSkKCmNhc2VzICU+JSAKICBmaWx0ZXIoZGF0ZSA9PSBtYXgoZGF0ZSwgbmEucm0gPSBUUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc3RhdGUsIHkgPSBjYXNlcykpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMywgYWxwaGEgPSAwLjI1KSArICAKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdD0xKSkgKwogIGxhYnModGl0bGUgPSBwbG90X3RpdGxlLCB4ID0gIlN0YXRlIiwgeSA9ICJDb3ZpZC0xOSBDYXNlcyIpIApgYGAKCkZyb20gdGhpcyBwbG90LCBJIGNhbiBzZWUgdGhlIHN0YXRlcyB3aXRoIGNvdW50aWVzIHdpdGggcGFydGljdWxhcmx5IGhpZ2ggY2FzZSBjb3VudHMgYnkgdGhlIG1vc3QgcmVjZW50IHJlcG9ydGluZyBkYXRlLgoKIyMjIFNjYXR0ZXJwbG90cwoKKlNjYXR0ZXJwbG90cyogZGlzcGxheSB0aGUgcmVsYXRpb25zaGlwIG9yIGNvcnJlbGF0aW9uIGJldHdlZW4gdHdvIG51bWVyaWMgdmFyaWFibGVzLiBGb3IgaW5zdGFuY2UsIGJlbG93IHdlIHBsb3QgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBCRURTIHZhcmlhYmxlIGFuZCB0aGUgUE9QVUxBVElPTiB2YXJpYWJsZSBpbiB0aGUgaG9zcGl0YWxzIGRhdGFzZXQuIAoKVGhlcmUgYXJlIGRpZmZlcmVudCB3YXlzIHRvIGNoYXJhY3Rlcml6ZSB0aGUgY29ycmVsYXRpb25zIGJldHdlZW4gdmFyaWFibGVzIGluIGRhdGEuIFdlIG1heSBjb25zaWRlciB0aGUgKnN0cmVuZ3RoKiBvZiBhIGNvcnJlbGF0aW9uLCB0aGUgKnNoYXBlKiBvZiBhIGNvcnJlbGF0aW9uLCBhbmQgd2hldGhlciB0aGUgY29ycmVsYXRpb24gaXMgcG9zaXRpdmUgb3IgbmVnYXRpdmUuIAoKKiBUd28gdmFyaWFibGVzIGluIGEgc2NhdHRlcnBsb3QgY2FuIGJlIHNhaWQgdG8gaGF2ZSBhIHN0cm9uZyBjb3JyZWxhdGlvbiB3aGVuIHBvaW50cyBhcmUgY2x1c3RlcmVkIGNsb3NlbHkgdG8gYSBjZW50cmFsIGxpbmUgb3IgY3VydmUuIFRoZSBtb3JlIHNjYXR0ZXJlZCB0aHJvdWdob3V0IHRoZSBwbG90IHRoZSBwb2ludHMgYXJlLCB0aGUgd2Vha2VyIHRoZSBjb3JyZWxhdGlvbi4KKiBUd28gdmFyaWFibGVzIGluIGEgc2NhdHRlcnBsb3QgY2FuIGJlIHNhaWQgdG8gaGF2ZSBhIGxpbmVhciBjb3JyZWxhdGlvbiB3aGVuIHRoZSBzY2F0dGVycGxvdCB0ZW5kcyB0byBwcm9kdWNlIGEgc3RyYWlnaHQgbGluZS4gVGhpcyBtZWFucyB0aGF0IHRoZSByYXRlIG9mIGNoYW5nZSBiZXR3ZWVuIHR3byB2YXJpYWJsZXMgaXMgc3RlYWR5LiBIb3dldmVyLCB3aGVuIGEgc2NhdHRlcnBsb3QgcHJvZHVjZXMgYSBjdXJ2ZSwgdGhpcyBpbmRpY2F0ZXMgdGhhdCB0aGUgcmF0ZSBvZiBjaGFuZ2UgYmV0d2VlbiB0d28gdmFyaWFibGVzIGlzIG5vdCBhcyBjb25zdGFudC4KKiBUd28gdmFyaWFibGVzIGluIGEgc2NhdHRlcnBsb3QgY2FuIGJlIHNhaWQgdG8gaGF2ZSBhIHBvc2l0aXZlIGNvcnJlbGF0aW9uIHdoZW4gdGhlIHBvaW50cyBtb3ZlIHVwd2FyZCBmcm9tIHRoZSBib3R0b20gbGVmdCBjb3JuZXIgdG93YXJkcyB0aGUgdG9wIHJpZ2h0IGNvcm5lciBvZiB0aGUgcGxvdC4gVGhpcyBtZWFucyB0aGF0IGFzIHZhbHVlcyBpbiB2YXJpYWJsZSBpbmNyZWFzZXMsIHRoZSB2YWx1ZXMgaW4gdGhlIG90aGVyIHZhcmlhYmxlIGFsc28gaW5jcmVhc2UuIFdoZW4gcG9pbnRzIG1vdmUgZG93bndhcmQgZnJvbSB0aGUgdG9wIGxlZnQgY29ybmVyIHRvIHRoZSBib3R0b20gcmlnaHQgY29ybmVyIG9mIHRoZSBwbG90LCB3ZSBjYW4gc2F5IHRoYXQgdGhlIHZhcmlhYmxlcyBuZWdhdGl2ZWx5IGNvcnJlbGF0aW9uLiBUaGlzIG1lYW5zIHRoYXQgYXMgdmFsdWVzIGluIHZhcmlhYmxlIGluY3JlYXNlcywgdGhlIHZhbHVlcyBpbiB0aGUgb3RoZXIgdmFyaWFibGUgZGVjcmVhc2VzLgoKYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTB9CiNSdW4gdGhpcyBjb2RlIGNodW5rLgoKI2dncGxvdChkZiwgYWVzKHggPSBOVU1FUklDX1ZBUklBQkxFLCB5ID0gTlVNRVJJQ19WQVJJQUJMRSkpICsgZ2VvbV9wb2ludCgpCgpob3NwaXRhbHMgJT4lIAogIGZpbHRlcihTVEFUVVMgPT0gIk9QRU4iKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBCRURTLCB5ID0gUE9QVUxBVElPTikpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMywgYWxwaGEgPSAwLjEpICsKICB0aGVtZV9idygpICsKICBsYWJzKHRpdGxlID0gIlJlbGF0aW9uc2hpcCBiZXR3ZWVuIEhvc3BpdGFsIEJlZHMgYW5kIFBvcHVsYXRpb24gaW4gdGhlIFVTIiwgeCA9ICJCZWRzIiwgeSA9ICJQb3B1bGF0aW9uIikgCmBgYAoKPiBOb3RlIHRoYXQgdGhpcyBwbG90IGhhcyBhIHN0cm9uZywgbGluZWFyIHBvc2l0aXZlIGNvcnJlbGF0aW9uLiBBcyBCRURTIGluY3JlYXNlIGluIHRoaXMgdmFyaWFibGUsIFBPUFVMQVRJT04gYWxzbyB0ZW5kcyB0byBpbmNyZWFzZS4gCgojIyMjIFRpdGxpbmcgYSBTY2F0dGVycGxvdAoKTm90ZSBob3cgSSB0aXRsZWQgbXkgcGxvdCBhYm92ZTogIlJlbGF0aW9uc2hpcCBiZXR3ZWVuIEhvc3BpdGFsIEJlZHMgYW5kIFBvcHVsYXRpb24gaW4gdGhlIFVTIiBBIGdvb2QgZm9ybXVsYSBmb3IgdGl0bGluZyBzY2F0dGVycGxvdHMgaXMgYXMgZm9sbG93czoKClJlbGF0aW9uc2hpcCBiZXR3ZWVuIF9fX19fIFt4LWF4aXMgdmFyaWFibGUgbmFtZV0gYW5kIFt5LWF4aXMgdmFyaWFibGUgbmFtZV0gCgpUaGUgYmxhbmsgc2hvdWxkIGJlIGZpbGxlZCB3aXRoIHlvdXIgdW5pdCBvZiBvYnNlcnZhdGlvbi4gVGhlIFt4LWF4aXMgdmFyaWFibGUgbmFtZV0gc2hvdWxkIGJlIHlvdXIgeC1sYWJlbCBhbmQgW3ktYXhpcyB2YXJpYWJsZSBuYW1lXSIgc2hvdWxkIGJlIHlvdXIgeS1sYWJlbC4KCiMjIyMgV2hhdCBpZiBJIGhhdmUgbXVsdGktZGltZW5zaW9uYWwgZGF0YT8KCklmIHRoaXMgaXMgdGhlIGNhc2UgSSB3b3VsZCBlbmNvdXJhZ2UgeW91IHRvIGZpbHRlciB5b3VyIHBsb3QgdG8gb25lIHZhbHVlIGluIG9uZSBvZiB0aGUgdmFyaWFibGVzIHRoYXQgbWFrZSB1cCB5b3VyIHVuaXF1ZSBrZXkuIEZvciBpbnN0YW5jZSBpZiB3b3JsZF9oZWFsdGhfZWNvbiBpcyB1bmlxdWUgYnkgY291bnRyeSBhbmQgeWVhciwgSSBjYW4gZmlsdGVyIHRvIHRoZSBtb3N0IHJlY2VudCB5ZWFyIGJlZm9yZSBjcmVhdGluZyBhIHBvaW50IHBsb3Qgb2YgdGhlIHByaXZhdGUgc2hhcmUgb2YgaGVhbHRoIHNwZW5kaW5nIGJ5IGNvbnRpbmVudC4KCmBgYHtyIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEwfQojUnVuIHRoaXMgY29kZSBjaHVuay4KCiNnZ3Bsb3QoZGYsIGFlcyh4ID0gTlVNRVJJQ19WQVJJQUJMRSwgeSA9IE5VTUVSSUNfVkFSSUFCTEUpKSArIGdlb21fcG9pbnQoKQoKd29ybGRfaGVhbHRoX2Vjb24gJT4lIAogIGZpbHRlcih5ZWFyID09IG1heCh5ZWFyLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB0b3RfaGVhbHRoX3NwX3BwLCB5ID0gbGlmZV9leHAsIHNpemUgPSBwb3AsIGNvbCA9IGNvbnRpbmVudCkpICsgCiAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBzdHJva2UgPSAxKSArCiAgbGFicyh0aXRsZSA9ICJSZWxhdGlvbnNoaXAgYmV0d2VlbiBDb3VudHJ5IFRvdGFsIEhlYWx0aCBTcGVuZGluZyBQZXIgUGVyc29uIGFuZCBMaWZlIEV4cGVjdGFuY3kiLCB4ID0gIlRvdGFsIEhlYWx0aCBTcGVuZGluZyBQZXIgUGVyc29uIiwgeSA9ICJMaWZlIEV4cGVjdGFuY3kiLCBzaXplID0gIlBvcHVsYXRpb24iLCBjb2wgPSAiQ29udGluZW50IikgKyAKICB0aGVtZV9idygpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDEsIDEwKSwgbGFiZWxzID0gc2NhbGVzOjpjb21tYSkKYGBgCgo+IE5vdGUgdGhhdCB0aGlzIHBsb3QgaGFzIGEgd2Vha2VyLCBjdXJ2aWxpbmVhciwgcG9zaXRpdmUgY29ycmVsYXRpb24uIEFzIFRvdGFsIEhlYWx0aCBTcGVuZGluZyBwZXIgUGVyc29uIGluY3JlYXNlcyBpbiB0aGlzIHZhcmlhYmxlLCBMaWZlIEV4cGVjdGFuY3kgYWxzbyB0ZW5kcyB0byBpbmNyZWFzZSwgYnV0IHRoZSByYXRlIG9mIGNoYW5nZSBhdCB3aGljaCBpdCBpbmNyZWFzZXMgaXMgbm90IGNvbnN0YW50LiAgCgpIYXZlIHlvdSBoZWFyZCB0aGUgcXVpcCAiQ29ycmVsYXRpb24gZG9lcyBub3QgZXF1YWwgY2F1c2F0aW9uIj8gVGhpcyBpcyBwYXJ0aWN1bGFybHkgaW1wb3J0YW50IHRvIGNvbnNpZGVyIGhlcmUuIEluIGxhYiA3LCB3ZSB3aWxsIGV4YW1pbmUgc29tZSBjb25mb3VuZGluZyB2YXJpYWJsZXMgdGhhdCBtYXkgYmUgbWVkaWF0aW5nIGhvdyB2YWx1ZXMgYXBwZWFyIHRvIGNvcnJlbGF0ZSBpbiBvdXIgZGF0YS4gRm9yIG5vdywgaXQncyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IGp1c3QgYmVjYXVzZSB3ZSBzZWUgYSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRvdGFsIGhlYWx0aCBzcGVuZGluZyBhbmQgbGlmZSBleHBlY3RhbmN5IGRvZXMgbm90IG1lYW4gdGhhdCBpbmNyZWFzaW5nIHRvdGFsIGhlYWx0aCBzcGVuZGluZyBpbiBhIGNvdW50cnkgKipjYXVzZXMqKiBsaWZlIGV4cGVjdGFuY3kgdG8gaW5jcmVhc2UuIFRoaXMgaXMgb2YgY291cnNlIGEgY29tcGxleCBpc3N1ZSB3aXRoIGxvdHMgb2Ygb3RoZXIgdmFyaWFibGVzIGludm9sdmVkLiAKCiMjIyBQcm9kdWNlIHR3byBwbG90cyB0aGF0IHJlcHJlc2VudCBjby12YXJpYXRpb24gaW4geW91ciBkYXRhc2V0LiAKCllvdSBuZWVkIG5vdCBpbmNsdWRlIGV2ZXJ5IHBsb3QgSSBkZXNjcmliZWQgYWJvdmUuIEJlIHN1cmUgdG8gem9vbSBpbiB0byBjZXJ0YWluIG9ic2VydmF0aW9ucyBpbiB5b3VyIGRhdGEgaWYgeW91IGhhdmUgbXVsdGktZGltZW5zaW9uYWwgZGF0YS4gCgojIyMjIFBsb3QgQ28tVmFyaWF0aW9uIGluIHlvdXIgRGF0YXNldAoKYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTB9CiNGaWxsIHRoZSBjb2RlIGZvciBwbG90IDEgaGVyZS4gQWRkIGEgdGl0bGUgYW5kIGxhYmVscyB0byB5b3VyIHBsb3RzLiBCZSBzdXJlIHRvIGFkanVzdCBmb3Igb3ZlcnBsb3R0aW5nLgpgYGAKCkNvcHkgYW5kIHBhc3RlIHRoZSBkZWZpbml0aW9ucyBvZiB0aGUgdmFyaWFibGVzIHlvdSBzZWxlY3RlZCBmcm9tIHRoZSBkYXRhIGRpY3Rpb25hcnkgYmVsb3cuIAoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCB5b3VyIHJlc3BvbnNlIGhlcmUuIApgYGAKCjEuIFFVRVJZOiBCZWxvdywgd3JpdGUgYSByZXNlYXJjaCBxdWVzdGlvbiB0aGF0IHRoZSBjb2RlIHlvdSBqdXN0IHJhbiBpcyBkZXNpZ25lZCB0byBiZSBhYmxlIHRvIGFuc3dlci4gTWFrZSBzdXJlIHlvdSBwaHJhc2UgeW91ciBxdWVzdGlvbiBkaXJlY3RseSBpbiByZWxhdGlvbiB0byB0aGUgcmVzdWx0cyBvZiB5b3VyIGNvZGUuIEluIG90aGVyIHdvcmRzLCB5b3UgaGF2ZSB0aGUgYW5zd2VyOyBub3cgY29tZSB1cCB3aXRoIHRoZSBxdWVzdGlvbi4gQ29uc2lkZXIgdGhpcyBhIGNoZWNrIG9uIHdoZXRoZXIgeW91IHVuZGVyc3RhbmQgd2hhdCB0aGUgY29kZSBhYm92ZSBpcyBkb2luZy4gSWYgeW91IGFyZSB1bnN1cmUgaG93IHRvIGNvbXBvc2UgdGhpcyBxdWVzdGlvbiwgeW91IHByb2JhYmx5IHdhbnQgdG8gc3R1ZHkgdGhlIGZ1bmN0aW9ucyBhYm92ZSBhIGJpdCBtb3JlIGNsb3NlbHkuCgpgYGB7ciBldmFsPUZBTFNFfQpGaWxsIHlvdXIgcmVzcG9uc2UgaGVyZS4gCmBgYAoKQXJlIHRoZXJlIGFueSBvdGhlciB2YXJpYWJsZXMgaW4geW91ciBkYXRhc2V0IHRoYXQgeW91IG5lZWQgdG8gdGFrZSBpbnRvIGNvbnNpZGVyYXRpb24gYmVmb3JlIGRpcmVjdGluZyB0aGlzIGFuYWx5c2lzIHRvd2FyZHMgYW5zd2VyaW5nIHRoYXQgcXVlc3Rpb24/IEluIG90aGVyIHdvcmRzLCBkbyB5b3UgbmVlZCB0byB6b29tIGludG8gYW55IHNwZWNpZmljIGFyZWFzIG9mIHRoZSBkYXRhc2V0IChieSBmaWx0ZXJpbmcpIGluIG9yZGVyIHRvIGFwcHJvcHJpYXRlbHkgYWRkcmVzcyB0aGlzIHF1ZXN0aW9uPyBJZiBzbywgd2hpY2g/IChGb3IgaW5zdGFuY2UsIGZvciB0aGUgaG9zcGl0YWxzIGRhdGFzZXQgd2UgbmVlZGVkIHRvIGZpbHRlciB0byBob3NwaXRhbHMgdGhhdCB3ZXJlIE9QRU4gaW4gb3JkZXIgdG8gYWRkcmVzcyBxdWVzdGlvbnMgYWJvdXQgaW5mcmFzdHJ1Y3R1cmUpLiBCcmllZmx5IG5vdGUgdGhpcyBiZWxvdy4gCgpgYGB7ciBldmFsPUZBTFNFfQpGaWxsIHlvdXIgcmVzcG9uc2UgaGVyZS4gCmBgYAoKMi4gU1VNTUFSSVpFOiBSZXZpZXdpbmcgdGhlIG91dHB1dCBvZiB5b3VyIGNvZGUsIHN1bW1hcml6ZSBvbmUgdGhpbmcgdGhhdCB5b3UgbGVhcm4gYWJvdXQgeW91ciB0b3BpYyBmcm9tIHJ1bm5pbmcgdGhpcyBjb2RlIGNodW5rLiBJbiBvdGhlciB3b3Jkcywgd2hhdCBpcyBvbmUgdGhpbmcgdGhhdCB0aGUgcmVzdWx0cyBvZiB0aGlzIGFuYWx5c2lzIGVtcGlyaWNhbGx5IHRlbGwgdXMgYWJvdXQgdGhlIHRvcGljPyBCZSBzcGVjaWZpYywgY29uc2lkZXJpbmcgdGhlIGdlb2dyYXBoaWMsIHRlbXBvcmFsLCBhbmQgdG9waWNhbCBzY29wZSBvZiB5b3VyIGRhdGEuCgpgYGB7ciBldmFsPUZBTFNFfQpGaWxsIHlvdXIgcmVzcG9uc2UgaGVyZS4gCmBgYAoKMy4gSU5URVJQUkVUOiBOb3cgaW1hZ2luZSB5b3Ugd2VyZSByZXBvcnRpbmcgeW91ciBmaW5kaW5ncyB0byBhIGRlY2lzaW9uLW1ha2VyIG9uIHlvdXIgdG9waWMuIERlc2NyaWJlIHRvIHRoYXQgZGVjaXNpb24tbWFrZXIgd2h5IHRoZXkgc2hvdWxkIGNhcmUuIEluIG90aGVyIHdvcmRzLCAqaW50ZXJwcmV0KiB3aGF0IGlzIGltcG9ydGFudCBhYm91dCB0aGlzIGZpbmRpbmcuIAoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCB5b3VyIHJlc3BvbnNlIGhlcmUuIApgYGAKCjQuIFJFRkxFQ1Q6IFdoYXQgZWxzZSB3b3VsZCB3ZSBuZWVkIHRvIGtub3cgdG8gZnVsbHkgYWRkcmVzcyB0aGlzIHF1ZXN0aW9uPyBLbm93aW5nIHdoYXQgeW91IGtub3cgYWJvdXQgaG93IHRoZSBkYXRhIHdhcyBjb2xsZWN0ZWQgYW5kIGFnZ3JlZ2F0ZWQsIHdoYXQgdW5jZXJ0YWludGllcyByZW1haW4gaW4gcmVnYXJkcyB0byBhZGRyZXNzaW5nIHRoaXMgcXVlc3Rpb24/IEluIHdoYXQgd2F5cyBpcyB0aGUgYW5hbHlzaXMgbGltaXRlZCBieSB0aGUgc2NvcGUgb2YgdGhlIGRhdGEncyBkZWZpbml0aW9ucyBvciBjYXRlZ29yaWVzPwoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCByZXNwb25zZSBoZXJlLiAKYGBgCgojIyMjIFBsb3QgQ28tVmFyaWF0aW9uIGluIHlvdXIgRGF0YXNldCBhbiBBbHRlcm5hdGl2ZSBXYXkKCmBgYHtyIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEwfQojRmlsbCB0aGUgY29kZSBmb3IgcGxvdCAyIGhlcmUuIEFkZCBhIHRpdGxlIGFuZCBsYWJlbHMgdG8geW91ciBwbG90cy4gQmUgc3VyZSB0byBhZGp1c3QgZm9yIG92ZXJwbG90dGluZy4KYGBgCgpDb3B5IGFuZCBwYXN0ZSB0aGUgZGVmaW5pdGlvbnMgb2YgdGhlIHZhcmlhYmxlcyB5b3Ugc2VsZWN0ZWQgZnJvbSB0aGUgZGF0YSBkaWN0aW9uYXJ5IGJlbG93LiAKCmBgYHtyIGV2YWw9RkFMU0V9CkZpbGwgeW91ciByZXNwb25zZSBoZXJlLiAKYGBgCgoxLiBRVUVSWTogQmVsb3csIHdyaXRlIGEgcmVzZWFyY2ggcXVlc3Rpb24gdGhhdCB0aGUgY29kZSB5b3UganVzdCByYW4gaXMgZGVzaWduZWQgdG8gYmUgYWJsZSB0byBhbnN3ZXIuIE1ha2Ugc3VyZSB5b3UgcGhyYXNlIHlvdXIgcXVlc3Rpb24gZGlyZWN0bHkgaW4gcmVsYXRpb24gdG8gdGhlIHJlc3VsdHMgb2YgeW91ciBjb2RlLiBJbiBvdGhlciB3b3JkcywgeW91IGhhdmUgdGhlIGFuc3dlcjsgbm93IGNvbWUgdXAgd2l0aCB0aGUgcXVlc3Rpb24uIENvbnNpZGVyIHRoaXMgYSBjaGVjayBvbiB3aGV0aGVyIHlvdSB1bmRlcnN0YW5kIHdoYXQgdGhlIGNvZGUgYWJvdmUgaXMgZG9pbmcuIElmIHlvdSBhcmUgdW5zdXJlIGhvdyB0byBjb21wb3NlIHRoaXMgcXVlc3Rpb24sIHlvdSBwcm9iYWJseSB3YW50IHRvIHN0dWR5IHRoZSBmdW5jdGlvbnMgYWJvdmUgYSBiaXQgbW9yZSBjbG9zZWx5LgoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCB5b3VyIHJlc3BvbnNlIGhlcmUuIApgYGAKCkFyZSB0aGVyZSBhbnkgb3RoZXIgdmFyaWFibGVzIGluIHlvdXIgZGF0YXNldCB0aGF0IHlvdSBuZWVkIHRvIHRha2UgaW50byBjb25zaWRlcmF0aW9uIGJlZm9yZSBkaXJlY3RpbmcgdGhpcyBhbmFseXNpcyB0b3dhcmRzIGFuc3dlcmluZyB0aGF0IHF1ZXN0aW9uPyBJbiBvdGhlciB3b3JkcywgZG8geW91IG5lZWQgdG8gem9vbSBpbnRvIGFueSBzcGVjaWZpYyBhcmVhcyBvZiB0aGUgZGF0YXNldCAoYnkgZmlsdGVyaW5nKSBpbiBvcmRlciB0byBhcHByb3ByaWF0ZWx5IGFkZHJlc3MgdGhpcyBxdWVzdGlvbj8gSWYgc28sIHdoaWNoPyAoRm9yIGluc3RhbmNlLCBmb3IgdGhlIGhvc3BpdGFscyBkYXRhc2V0IHdlIG5lZWRlZCB0byBmaWx0ZXIgdG8gaG9zcGl0YWxzIHRoYXQgd2VyZSBPUEVOIGluIG9yZGVyIHRvIGFkZHJlc3MgcXVlc3Rpb25zIGFib3V0IGluZnJhc3RydWN0dXJlKS4gQnJpZWZseSBub3RlIHRoaXMgYmVsb3cuIAoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCB5b3VyIHJlc3BvbnNlIGhlcmUuIApgYGAKCjIuIFNVTU1BUklaRTogUmV2aWV3aW5nIHRoZSBvdXRwdXQgb2YgeW91ciBjb2RlLCBzdW1tYXJpemUgb25lIHRoaW5nIHRoYXQgeW91IGxlYXJuIGFib3V0IHlvdXIgdG9waWMgZnJvbSBydW5uaW5nIHRoaXMgY29kZSBjaHVuay4gSW4gb3RoZXIgd29yZHMsIHdoYXQgaXMgb25lIHRoaW5nIHRoYXQgdGhlIHJlc3VsdHMgb2YgdGhpcyBhbmFseXNpcyBlbXBpcmljYWxseSB0ZWxsIHVzIGFib3V0IHRoZSB0b3BpYz8gQmUgc3BlY2lmaWMsIGNvbnNpZGVyaW5nIHRoZSBnZW9ncmFwaGljLCB0ZW1wb3JhbCwgYW5kIHRvcGljYWwgc2NvcGUgb2YgeW91ciBkYXRhLgoKYGBge3IgZXZhbD1GQUxTRX0KRmlsbCB5b3VyIHJlc3BvbnNlIGhlcmUuIApgYGAKCjMuIElOVEVSUFJFVDogTm93IGltYWdpbmUgeW91IHdlcmUgcmVwb3J0aW5nIHlvdXIgZmluZGluZ3MgdG8gYSBkZWNpc2lvbi1tYWtlciBvbiB5b3VyIHRvcGljLiBEZXNjcmliZSB0byB0aGF0IGRlY2lzaW9uLW1ha2VyIHdoeSB0aGV5IHNob3VsZCBjYXJlLiBJbiBvdGhlciB3b3JkcywgKmludGVycHJldCogd2hhdCBpcyBpbXBvcnRhbnQgYWJvdXQgdGhpcyBmaW5kaW5nLiAKCmBgYHtyIGV2YWw9RkFMU0V9CkZpbGwgeW91ciByZXNwb25zZSBoZXJlLiAKYGBgCgo0LiBSRUZMRUNUOiBXaGF0IGVsc2Ugd291bGQgd2UgbmVlZCB0byBrbm93IHRvIGZ1bGx5IGFkZHJlc3MgdGhpcyBxdWVzdGlvbj8gS25vd2luZyB3aGF0IHlvdSBrbm93IGFib3V0IGhvdyB0aGUgZGF0YSB3YXMgY29sbGVjdGVkIGFuZCBhZ2dyZWdhdGVkLCB3aGF0IHVuY2VydGFpbnRpZXMgcmVtYWluIGluIHJlZ2FyZHMgdG8gYWRkcmVzc2luZyB0aGlzIHF1ZXN0aW9uPyBJbiB3aGF0IHdheXMgaXMgdGhlIGFuYWx5c2lzIGxpbWl0ZWQgYnkgdGhlIHNjb3BlIG9mIHRoZSBkYXRhJ3MgZGVmaW5pdGlvbnMgb3IgY2F0ZWdvcmllcz8KCmBgYHtyIGV2YWw9RkFMU0V9CkZpbGwgcmVzcG9uc2UgaGVyZS4gCmBgYAo=