Introduction

This code through introduces a diverse range of data visualizations available in R. We’ll create a series of choropleth maps using social vulnerability data from the CDC. By the end of this code through, you’ll be able to classify data visualizations and replicate a choropleth map.

Why You Should Care
It’s tough to make decisions about how to communicate data visually. Sometimes it feels easier to go with a trusty bar chart or line plot. Knowing what’s possible is the first step to expanding your data viz repertoire and challenging people to think about community health data in new ways.
R & Its Value
R is a programming language used to perform statistical analysis and create graphics. It’s free to use (and learn) and is a valid alternative to paid platforms. Public health staff who learn R grow organizational capacity for assessment and health communication.

Audience Notes

This code through was built for two audiences at Spokane Regional Health District (SRHD).

Healthy Living staff requested a “menu” of R data visualizations. Data Visualizations introduces R data viz options and is designed to be approachable. It purposefully only includes codes with the examples. The goal is to increase the Healthy Living team’s interest in R as consumers of Data Center staff hours.

Data Center staff requested a code through featuring mapping. Choropleth Mapping Tutorial walks through the choropleth mapping process so staff with coding and Tableau or PowerBI experience can compare difficulty. Ideally, both sections will introduce staff to the potential applications of R in our public health assessment work.

Data Visualizations

By Purpose

Each data visualization communicates uniquely, but they can be categorized by what they communicate to an audience. The categories in this table come from From Data to Viz.

Category What does it communicate?
Correlation How much two things are connected, like whether they change together or in different ways
Distribution How values are spread across a range
Evolution How something changes or develops over time
Flow How things move or change from one place or state to another over time
Map How things are distributed or related across different locations
Part of a Whole How individual pieces or categories make up a total amount
Ranking How items or people are ordered from highest to lowest based on a specific measure or score
Note: I generated this text in part with ChatGPT-4, OpenAI’s large-scale language generation model. Upon generating draft language, I reviewed, edited, and revised the language to my liking. I take ultimate responsibility for the content of this publication.

By Data Type

The type of data you want to visualize also matters. When you aren’t sure what to communicate to your audience, explore what is possible with your dataset using the Decision Tree. It helps you make decisions based on the number of variables, type of variable(s), number of observations, and data structure. Click the image below to explore an interactive version of the Decision Tree poster.

Data Viz Decision Tree Decision Tree by From Data to Viz, a partner of R Graph Gallery

The List and Examples

There are thousands of data visualization options in R, but these lists are a good start to exploring what is possible. The categories and viz types come from From Data to Viz.

Correlation

Type Description
Bubble Plots individual points to show the relationship between two variables, but the size of each point represents an additional variable
Connected scatter Shows how data points change over time by connecting them with a line
Correlogram Shows the relationships between multiple variables in a color-coded grid
Density 2d Displays the density of data points across two dimensions using a contour-like effect
Heatmap Uses color to represent values in a grid, showing patterns or intensities
Scatter Plots individual points to show the relationship between two variables
Note: I generated this text in part with ChatGPT-4, OpenAI’s large-scale language generation model. Upon generating draft language, I reviewed, edited, and revised the language to my liking. I take ultimate responsibility for the content of this publication.
This is a 2d density chart.

2d
2d density chart found on The R Graph Gallery

Distribution

Type Description
Beeswarm Displays individual data points spread out to avoid overlap, showing the overall distribution
Boxplot Summarizes data by showing its range, middle value, and potential outliers
Density A smooth curve that shows how data is distributed across its range
Histogram Uses bars to show how often different ranges of values appear in the data
Ridgeline Stacks multiple distribution curves on top of each other to compare groups
Violin Shows the spread of data and how common certain values are in different groups
Note: I generated this text in part with ChatGPT-4, OpenAI’s large-scale language generation model. Upon generating draft language, I reviewed, edited, and revised the language to my liking. I take ultimate responsibility for the content of this publication.
This is a ridgeline chart.

Rent
Ridgeline chart found on The R Graph Gallery

Evolution

Type Description
Area Fills the space below a line to show the size or magnitude of changes
Line plot Connects data points with a line to show changes over time
Stacked area Multiple areas are layered on top of each other to show how parts add up over time
Streamchart Uses flowing shapes to show how values change over time
Time series A chart that tracks data points over time to show trends
Note: I generated this text in part with ChatGPT-4, OpenAI’s large-scale language generation model. Upon generating draft language, I reviewed, edited, and revised the language to my liking. I take ultimate responsibility for the content of this publication.
This is a stream chart, also called a stream graph.

Comics
Stream chart found on The R Graph Gallery

Flow

Type Description
Arc diagram Draws curved lines between points to show relationships
Chord diagram Displays connections between groups using arcs in a circular layout
Edge bundling Groups similar connections in a network diagram to reduce clutter
Network Shows how things are connected with lines between points (nodes)
Sankey Uses arrows of different widths to represent flow between different categories
Note: I generated this text in part with ChatGPT-4, OpenAI’s large-scale language generation model. Upon generating draft language, I reviewed, edited, and revised the language to my liking. I take ultimate responsibility for the content of this publication.
This is a chord diagram.

Migration
Chord found on The R Graph Gallery

Map

Type Description
Bubble map Places bubbles of different sizes on a map to represent data points
Cartogram Distorts the size of geographic areas to reflect data, like population size
Choropleth A map where areas are shaded based on a variable value, like population or income
Connection Shows lines between points on a map to represent links or routes
Hexbin map Groups data points into hexagons on a map to show density
Map A visual representation of geographic data
Note: I generated this text in part with ChatGPT-4, OpenAI’s large-scale language generation model. Upon generating draft language, I reviewed, edited, and revised the language to my liking. I take ultimate responsibility for the content of this publication.
This is a cartogram map.

Africa Population
Cartogram from the R Graph Gallery

Part of a Whole

Type Description
Circular packing Uses circles inside larger circles to show hierarchical data and their sizes
Dendrogram A tree-like diagram used to show how items are related in clusters
Doughnut A round chart with a hole in the middle that shows parts of a whole
Grouped and stacked barplots Shows how different groups or parts contribute to the total, either side by side or stacked
Pie chart A circular chart divided into slices to show parts of a whole
Treemap Uses nested rectangles to represent hierarchical data with size showing value
Waffle A grid of squares where each square represents a part of the total value
Note: I generated this text in part with ChatGPT-4, OpenAI’s large-scale language generation model. Upon generating draft language, I reviewed, edited, and revised the language to my liking. I take ultimate responsibility for the content of this publication.
This is a waffle chart. This particular chart serves two purposes: parts of a whole and evolution.

Cyclones
Waffle chart found on The R Graph Gallery

Ranking

Type Description
Barplot Uses bars to compare the values of different categories
Circular barplot Displays bar chart data in a circular layout for visual effect
Lollipop Represents data points with lines and circles, like a stick with a ball on top
Parallel Plots multiple variables on separate axes to compare data across different categories
Spider or radar Compares several variables for different items using a web-like shape
Table Organizes data into rows and columns for easy comparison
Wordcloud Displays words where the size of each word shows its frequency or importance
Note: I generated this text in part with ChatGPT-4, OpenAI’s large-scale language generation model. Upon generating draft language, I reviewed, edited, and revised the language to my liking. I take ultimate responsibility for the content of this publication.
This is a circular lolipop plot.

Password
Plot found on The R Graph Gallery

Choropleth Mapping Tutorial

We’ll create a series of static choropleth maps using The Centers for Disease Control and Prevention and Agency for Toxic Substances and Disease Registry Social Vulnerability Index (or CDC/ATSDR SVI).

Code in the tutorial section was adapted from Kyle Walker’s book, Analyzing US Census Data: Methods, Maps, and Models in R. Instances where Walker’s exact code is used are noted.

About the SVI

What is Social Vulnerability?

The CDC/ATSDR describes social vulnerability as “the degree to which a community exhibits certain social conditions, including high poverty, low percentage of vehicle access, or crowded households, among others, may affect that community’s ability to prevent human suffering and financial loss in the event of a disaster.”

Social conditions are the conditions in which people live and work, known better to public health practitioners as the social determinants of health. The variables used by the CDC/ATSDR affect people’s ability to prepare for hazards, take protective actions, and recover from events. At the population level, the result is social vulnerability. Remember that the community is socially vulnerable, not individual people.

The Methodology tab will use language from the Health Equity Action Spectrum from the Mobilizing for Action through Planning and Partnerships (MAPP) 2.0 User Handbook. If you missed October’s All-Staff Meeting, the most important idea from the spectrum is: > The root causes of inequity create hierarchies of privilege and oppression which lead to imbalances in power and access to power, generating preventable differences in individual health.

Methodology

The Social Vulnerability Index scores census tracts based on 16 variables. Census tracts are ranked in several ways. Each variable is ranked individually. Then, the variables are separated into four themes, each of which receives a rank. The final ranking is the overall score. The image below visualizes this concept. The scores range from 0-1 with 1 indicating high social vulnerability.

Tracts that rank in the top 10% are given a “flag.” The overall flag value adds all flags received. The higher the overall flag value is, the more frequently a census tract appeared in 90th percentiles for social vulnerability.

Variables by Theme
Overall Social Vulnerability by the CDC/ATSDR

Using the SVI in Public Health

The Social Vulnerability Index is frequently used to study associations between social vulnerability and health outcomes. It has been used to study things like healthcare resource utilization in medically complex patients, outcomes in cancer patients, and even long-term outcomes after traumatic injury.

The SVI can also be used to study other social determinants of health and systems of power, privilege, and oppression. One study used the SVI and BRFSS data to assess access to healthcare at the state-level. Another study combined the SVI with 15 additional Census measures to measure the association between structural racism and cardiovascular health risk among Black/African American women.

Flags can indicate areas where upstream approaches might have significant impact on social vulnerability and individual health. The flag approach could even be modified to include more tracts (like those in the top 15% or 85th percentile) or to identify resource rich environments (like tracts with ten or more variables in the bottom 20%).

While the SVI is used primarily as an indicator of community preparedness, the truth is that it measures social determinants of health. The SVI has potential as a measure of the root causes of inequity and of the downstream effects of the social determinants of health and the systems of power, privilege, and oppression on individual health.

Creating the Base Map

Installing Packages

The very first step is to install packages you don’t have. R packages extend the capabilities of the base R system. Packages are free and often come with useful documentation.

You can install packages using install.packages("name"). For example, install.packages("dplyr") will install dplyr. The tutorial requires the following packages.

  • ggplot2
  • sf
  • tigris
  • patchwork
  • mapview
  • viridis

Loading Libraries

Once the packages are installed, we have to load the mapping tools we need. We do this by running library(name).

# Loads libraries
library(ggplot2)
library(sf)
library(tigris)
library(patchwork)
library(mapview)
library(viridis)

Creating the Initial Map

Now we can create an object with the shapefiles we need for the map. We only want a map that includes census tracts for Spokane County.

# Creates an object we can map with our specifications
sc_tracts <- tracts("WA", "Spokane")
## Retrieving data for the year 2022

Let’s create the base map. We can change the look of a map in many ways.

# Creates a basic ggplot map
ggplot(sc_tracts) +
  geom_sf()

# Voids the default theme
ggplot(sc_tracts) + 
  geom_sf() + 
  theme_void()

Let’s save these maps as objects to compare them using the patchwork library. This allows us to do a side-by-side comparison. If we wanted to compare them vertically, we’d replace sc_map_gg1 + sc_map_gg2 with sc_map_gg1 / sc_map_gg2. We’ll use this package again.

# Creates ggplot map objects
sc_map_gg1 <- ggplot(sc_tracts) + 
  geom_sf()

sc_map_gg2 <- ggplot(sc_tracts) + 
  geom_sf() + 
  theme_void()
# Compares objects
sc_map_gg1 + sc_map_gg2

Strange Shapes

Walker’s Michigan Example

TIGER/Line shapefiles can look sometimes strange. We can use cartographic boundaries when that happens.

The following example is pulled directly from Kyle Walker’s book, Analyzing US Census Data: Methods, Maps, and Models in R. Walker uses Michigan to highlight the power of cartographic boundaries because the Great Lakes significantly alter the state’s shape.

# Creates an object defaulted to no cartographic boundaries
mi_counties <- counties("MI")
## Retrieving data for the year 2022
# Creates an object with cartographic boundaries
mi_counties_cb <- counties("MI", cb = TRUE)
## Retrieving data for the year 2022
# Creates ggplot map objects
mi_tiger_gg <- ggplot(mi_counties) +
  geom_sf() + 
  theme_void() + 
  labs(title = "TIGER/Line")

mi_cb_gg <- ggplot(mi_counties_cb) + 
  geom_sf() + 
  theme_void() + 
  labs(title = "Cartographic boundary")
# Compares objects
mi_tiger_gg + mi_cb_gg

What It Means Locally

This doesn’t have much effect on Spokane County, but it could be useful when analyzing smaller areas within Spokane County or when providing regional support services to other counties.

# Creates an object we can map
sc_tracts_cb <- tracts("WA", "Spokane", cb = TRUE)
## Retrieving data for the year 2022
# Creates ggplot map objects
sc_tiger_gg <- ggplot(sc_tracts) + 
  geom_sf() + 
  theme_void() + 
  labs(title = "TIGER/Line")

sc_cb_gg <- ggplot(sc_tracts_cb) + 
  geom_sf() + 
  theme_void() + 
  labs(title = "Cartographic boundary")
# Compares objects
sc_tiger_gg + sc_cb_gg

Adding the Data

Now that we have a usable base map, we can prepare and add the SVI data we need. We’ll use the overall SVI score and themes scores for each census tract.

Preparing the Data

Luckily for us, the SVI data is already in a usable format. The headers are abbreviated, and we need to make sure that we understand which columns we’ll be using for our choropleth maps. However, the CDC/ATSDR posts a data dictionary we can. You can access it in an interactive and searchable table or in a PDF file.

We’ll use the following columns.

  • Overall score
    • RPL_THEMES
  • Theme scores
    • Socioeconomic Status - RPL_THEME1
    • Household Characteristics - RPL_THEME2
    • Racial & Ethnic Minority Status - RPL_THEME3
    • Housing Type & Transportation - RPL_THEME4
  • Location
    • FIPS

Reading the Data

We need to “read” the data into R Studio. You can use a URL or local file to do this. The CDC/ATSDR provides the data as a .csv download. This means the file is local.

# Reads a local .csv file in the same folder and recognizes headers
sc_svi <- read.csv("sc-svi.csv", header = TRUE)

Exploring the Data

Now that the data appears in our global environment, we could peek at what’s in the file using a variety of commands. We could use verbs like dim(), head(), tail(), str(), or glimpse() to preview or learn about the data. This is more than we need now, but here’s an overview of what these verbs do.

  • dim() gives row and column dimensions
  • head() previews the first six rows or variables, but you can specify more or less
  • tail() is the same as head() except that it previews the last six rows or variables
  • str() shows dimensions, variables, classes, variable preview, etc.
  • glimpse() is similar to str() but previews more variables

Setting the SVI Score Class

We have to tell R how to classify scores.

# Uses dplyr to add a new column based on other columns within the data set
sc_svi <- sc_svi %>%
  mutate(overallquartile = ntile(RPL_THEMES, 4),
         theme1quartile = ntile(RPL_THEME1, 4),
         theme2quartile = ntile(RPL_THEME2, 4),
         theme3quartile = ntile(RPL_THEME3, 4),
         theme4quartile = ntile(RPL_THEME4, 4))

Joining the Data

We need to combine sc_svi and sc_tracts using a left join. A left join keeps all observations from the first data set listed (x). The census tract FIPS (also called a GEOID) is a unique identifier, which is to our advantage. We’ll use this variable to merge() the data, but they have different names: sc_svi$FIPS and sc_tracts$GEOID. We need to account for this.

# Joins two data sets together, keeping all x observations
sv_tracts_scores <- merge(sc_tracts, sc_svi, by.x="GEOID", by.y="FIPS", all.x=TRUE)

Overall SVI Score

We have our data and our base map. Let’s create our first choropleth map using the overall SVI score or RPL_THEMES.

# Creates the map as an object
overallscores_map <- ggplot(sv_tracts_scores) +
  geom_sf(aes(fill = overallquartile), color = "white", linewidth = 0.2) +
  scale_fill_viridis(option="viridis",
                     name="SVI Score",
                     breaks=c(1, 4),
                     labels=c("Lowest", "Highest")) + 
  labs(title = "Overall SVI Scores in Spokane County") +
  theme_void() + 
  theme(title=element_text(face="bold"))

# Shows or "prints" the map
overallscores_map

Themes SVI Scores

We have our first map and can use it as a template. We just wash, rinse, and repeat for the themes scores. However, this time, we’ll use the patchwork package to display charts in twos.

# Creates the maps as objects
theme1scores_map <- ggplot(sv_tracts_scores) +
  geom_sf(aes(fill = theme1quartile), color = "white", linewidth = 0.2) +
  scale_fill_viridis(option="viridis", guide = "none") + 
  labs(subtitle = "Socioeconomic Status") +
  theme_void() + 
  theme(title=element_text(face="bold"),
        plot.margin = margin(t = 1,  # Top margin
                             r = 1,  # Right margin
                             b = 1,  # Bottom margin
                             l = 1))

theme2scores_map <- ggplot(sv_tracts_scores) +
  geom_sf(aes(fill = theme2quartile), color = "white", linewidth = 0.2) +
  scale_fill_viridis(option="viridis",
                     name="SVI Score",
                     breaks=c(1, 4),
                     labels=c("Lowest", "Highest")) + 
  labs(subtitle = "Household Characteristics") +
  theme_void() + 
  theme(title=element_text(face="bold"),
        plot.margin = margin(t = 1,  # Top margin
                             r = 1,  # Right margin
                             b = 1,  # Bottom margin
                             l = 1))

theme3scores_map <- ggplot(sv_tracts_scores) +
  geom_sf(aes(fill = theme3quartile), color = "white", linewidth = 0.2) +
  scale_fill_viridis(option="viridis", guide = "none") + 
  labs(subtitle = "Race & Ethnicity Status") +
  theme_void() + 
  theme(title=element_text(face="bold"),
        plot.margin = margin(t = 1,  # Top margin
                             r = 1,  # Right margin
                             b = 1,  # Bottom margin
                             l = 1))

theme4scores_map <- ggplot(sv_tracts_scores) +
  geom_sf(aes(fill = theme4quartile), color = "white", linewidth = 0.2) +
  scale_fill_viridis(option="viridis",
                     name="SVI Score",
                     breaks=c(1, 4),
                     labels=c("Lowest", "Highest")) + 
  labs(subtitle = "Housing Type & Transportation") +
  theme_void() + 
  theme(title=element_text(face="bold"),
        plot.margin = margin(t = 1,  # Top margin
                             r = 1,  # Right margin
                             b = 1,  # Bottom margin
                             l = 1))
# Shows or "prints" the maps
theme1scores_map + theme2scores_map

# Shows or "prints" the maps
theme3scores_map + theme4scores_map

Making Meaning

Static choropleths are great visuals for printed materials. However, many census tracts located in and around downtown Spokane are too small for us make sense from as practitioners. An interactive map would improve staff uptake of the data in planning.

Visit this dashboard to see an example of a responsive map built using R and Shiny.

Recap

R can be incredibly useful for public health practice. Although it may seem intimidating, the community of R programmers is welcoming and committed to improvement. Better yet, it’s free and so is learning R.

R & DataCamp
If you like structured learning, the Washington State Department of Health pays for a statewide DataCamp account and offers it free of charge to certain local public health programs. Contact me at jlandes@srhd.org to see if there are open seats.
LS0tDQp0aXRsZTogIkRhdGEgVml6IGluIFIiDQphdXRob3I6ICJKYXp6eSBMYW5kZXMiDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUNCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6IA0KICAgICAgY29sbGFwc2libGU6IEZBTFNFDQogICAgICBzbW9vdGhfc2Nyb2xsOiBUUlVFDQpjc3M6ICJyZWFkYWJsZS5jc3MiDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQoNCiMgTG9hZCBsaWJyYXJpZXMNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShzZikNCmxpYnJhcnkodGlncmlzKQ0KbGlicmFyeShwYXRjaHdvcmspDQpsaWJyYXJ5KG1hcHZpZXcpDQpsaWJyYXJ5KHJtYXJrZG93bikNCmxpYnJhcnkodmlyaWRpcykNCg0KIyBSZWFkIGRhdGENCmRhdGFfdml6X2NhdHMgPC0gcmVhZC5jc3YoImRhdGF2aXpjYXRzLmNzdiIsIGhlYWRlciA9IFRSVUUpICMicmVhZCIgdGhlIENTViBpbnRvIHRoZSBSTUQNCg0KYmlnbGlzdGRhdHZpeiA8LSByZWFkLmNzdigiYmlnbGlzdGRhdGF2aXouY3N2IiwgaGVhZGVyID0gVFJVRSkNCg0KYGBgDQoNCiMjIEludHJvZHVjdGlvbg0KDQpUaGlzIGNvZGUgdGhyb3VnaCBpbnRyb2R1Y2VzIGEgZGl2ZXJzZSByYW5nZSBvZiBkYXRhIHZpc3VhbGl6YXRpb25zIGF2YWlsYWJsZSBpbiBSLiBXZSdsbCBjcmVhdGUgYSBzZXJpZXMgb2YgY2hvcm9wbGV0aCBtYXBzIHVzaW5nIHNvY2lhbCB2dWxuZXJhYmlsaXR5IGRhdGEgZnJvbSB0aGUgQ0RDLiBCeSB0aGUgZW5kIG9mIHRoaXMgY29kZSB0aHJvdWdoLCB5b3UnbGwgYmUgYWJsZSB0byBjbGFzc2lmeSBkYXRhIHZpc3VhbGl6YXRpb25zIGFuZCByZXBsaWNhdGUgYSBjaG9yb3BsZXRoIG1hcC4NCg0KPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCI+DQogIDxkaXYgY2xhc3M9InBhbmVsLWhlYWRpbmciPjxiPldoeSBZb3UgU2hvdWxkIENhcmU8L2I+PC9kaXY+DQogIDxkaXYgY2xhc3M9InBhbmVsLWJvZHkiPiBJdCdzIHRvdWdoIHRvIG1ha2UgZGVjaXNpb25zIGFib3V0IGhvdyB0byBjb21tdW5pY2F0ZSBkYXRhIHZpc3VhbGx5LiBTb21ldGltZXMgaXQgZmVlbHMgZWFzaWVyIHRvIGdvIHdpdGggYSB0cnVzdHkgYmFyIGNoYXJ0IG9yIGxpbmUgcGxvdC4gS25vd2luZyB3aGF0J3MgcG9zc2libGUgaXMgdGhlIGZpcnN0IHN0ZXAgdG8gZXhwYW5kaW5nIHlvdXIgZGF0YSB2aXogcmVwZXJ0b2lyZSBhbmQgY2hhbGxlbmdpbmcgcGVvcGxlIHRvIHRoaW5rIGFib3V0IGNvbW11bml0eSBoZWFsdGggZGF0YSBpbiBuZXcgd2F5cy48L2Rpdj4NCjwvZGl2Pg0KDQo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0Ij4NCiAgPGRpdiBjbGFzcz0icGFuZWwtaGVhZGluZyI+PGI+UiAmIEl0cyBWYWx1ZTwvYj48L2Rpdj4NCiAgPGRpdiBjbGFzcz0icGFuZWwtYm9keSI+IFIgaXMgYSBwcm9ncmFtbWluZyBsYW5ndWFnZSB1c2VkIHRvIHBlcmZvcm0gc3RhdGlzdGljYWwgYW5hbHlzaXMgYW5kIGNyZWF0ZSBncmFwaGljcy4gSXQncyBmcmVlIHRvIHVzZSAoYW5kIGxlYXJuKSBhbmQgaXMgYSB2YWxpZCBhbHRlcm5hdGl2ZSB0byBwYWlkIHBsYXRmb3Jtcy4gUHVibGljIGhlYWx0aCBzdGFmZiB3aG8gbGVhcm4gUiBncm93IG9yZ2FuaXphdGlvbmFsIGNhcGFjaXR5IGZvciBhc3Nlc3NtZW50IGFuZCBoZWFsdGggY29tbXVuaWNhdGlvbi48L2Rpdj4NCjwvZGl2Pg0KDQojIyMgQXVkaWVuY2UgTm90ZXMNCg0KVGhpcyBjb2RlIHRocm91Z2ggd2FzIGJ1aWx0IGZvciB0d28gYXVkaWVuY2VzIGF0IFNwb2thbmUgUmVnaW9uYWwgSGVhbHRoIERpc3RyaWN0IChTUkhEKS4NCg0KSGVhbHRoeSBMaXZpbmcgc3RhZmYgcmVxdWVzdGVkIGEgIm1lbnUiIG9mIFIgZGF0YSB2aXN1YWxpemF0aW9ucy4gPHN0cm9uZz5EYXRhIFZpc3VhbGl6YXRpb25zPC9zdHJvbmc+IGludHJvZHVjZXMgUiBkYXRhIHZpeiBvcHRpb25zIGFuZCBpcyBkZXNpZ25lZCB0byBiZSBhcHByb2FjaGFibGUuIEl0IHB1cnBvc2VmdWxseSBvbmx5IGluY2x1ZGVzIGNvZGVzIHdpdGggdGhlIGV4YW1wbGVzLiBUaGUgZ29hbCBpcyB0byBpbmNyZWFzZSB0aGUgSGVhbHRoeSBMaXZpbmcgdGVhbSdzIGludGVyZXN0IGluIFIgYXMgY29uc3VtZXJzIG9mIERhdGEgQ2VudGVyIHN0YWZmIGhvdXJzLg0KDQpEYXRhIENlbnRlciBzdGFmZiByZXF1ZXN0ZWQgYSBjb2RlIHRocm91Z2ggZmVhdHVyaW5nIG1hcHBpbmcuIDxzdHJvbmc+Q2hvcm9wbGV0aCBNYXBwaW5nIFR1dG9yaWFsPC9zdHJvbmc+IHdhbGtzIHRocm91Z2ggdGhlIGNob3JvcGxldGggbWFwcGluZyBwcm9jZXNzIHNvIHN0YWZmIHdpdGggY29kaW5nIGFuZCBUYWJsZWF1IG9yIFBvd2VyQkkgZXhwZXJpZW5jZSBjYW4gY29tcGFyZSBkaWZmaWN1bHR5LiBJZGVhbGx5LCBib3RoIHNlY3Rpb25zIHdpbGwgaW50cm9kdWNlIHN0YWZmIHRvIHRoZSBwb3RlbnRpYWwgYXBwbGljYXRpb25zIG9mIFIgaW4gb3VyIHB1YmxpYyBoZWFsdGggYXNzZXNzbWVudCB3b3JrLg0KDQojIyBEYXRhIFZpc3VhbGl6YXRpb25zDQoNCiMjIyBCeSBQdXJwb3NlDQoNCkVhY2ggZGF0YSB2aXN1YWxpemF0aW9uIGNvbW11bmljYXRlcyB1bmlxdWVseSwgYnV0IHRoZXkgY2FuIGJlIGNhdGVnb3JpemVkIGJ5IHdoYXQgdGhleSBjb21tdW5pY2F0ZSB0byBhbiBhdWRpZW5jZS4gVGhlIGNhdGVnb3JpZXMgaW4gdGhpcyB0YWJsZSBjb21lIGZyb20gW0Zyb20gRGF0YSB0byBWaXpdKGh0dHBzOi8vd3d3LmRhdGEtdG8tdml6LmNvbS8pLg0KDQo8c3R5bGU+DQoudGFibGUtaG92ZXIgPiB0Ym9keSA+IHRyOmhvdmVyIHsgDQogIGJhY2tncm91bmQtY29sb3I6ICNjNGUzZjM7fQ0KPC9zdHlsZT4NCg0KYGBge3IgZGF0YXZpemNhdHMtdGFibGUsIGluY2x1ZGU9VFJVRSwgZWNobz1GQUxTRX0NCg0KI2NyZWF0ZXMgdGhlIHRhYmxlIGFuZCByZW5hbWVzIHRoZSBjb2x1bW5zDQprYWJsZShkYXRhX3Zpel9jYXRzLA0KICAgICAgY29sLm5hbWVzID0gYygiQ2F0ZWdvcnkiLCAiV2hhdCBkb2VzIGl0IGNvbW11bmljYXRlPyIpKSAlPiUNCg0KI2NyZWF0ZXMgdGhlIGZvcm1hdHRpbmcgd2l0aCBob3ZlciBmdW5jdGlvbmFsaXR5IGFuZCBpbXByb3ZlcyBmdW5jdGlvbmFsaXR5IG9uIG1vYmlsZSBkZXZpY2VzDQprYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJyZXNwb25zaXZlIikpICU+JSANCiAgDQojY3JlYXRlcyB0aGUgZm9vdG5vdGUgYW5kIGZvcm1hdHRpbmc7IGVzY2FwZSBpcyBuZWNlc3NhcnkgZm9yIHRoZSBodG1sIHRvIHJlZHVjZSB0ZXh0IHNpemUNCmZvb3Rub3RlKGdlbmVyYWwgPSAiPHNtYWxsPkkgZ2VuZXJhdGVkIHRoaXMgdGV4dCBpbiBwYXJ0IHdpdGggQ2hhdEdQVC00LCBPcGVuQUnigJlzIGxhcmdlLXNjYWxlIGxhbmd1YWdlIGdlbmVyYXRpb24gbW9kZWwuIFVwb24gZ2VuZXJhdGluZyBkcmFmdCBsYW5ndWFnZSwgSSByZXZpZXdlZCwgZWRpdGVkLCBhbmQgcmV2aXNlZCB0aGUgbGFuZ3VhZ2UgdG8gbXkgbGlraW5nLiBJIHRha2UgdWx0aW1hdGUgcmVzcG9uc2liaWxpdHkgZm9yIHRoZSBjb250ZW50IG9mIHRoaXMgcHVibGljYXRpb24uPC9zbWFsbD4iLA0KICAgICAgICAgZ2VuZXJhbF90aXRsZSA9ICI8c21hbGw+Tm90ZTogPC9zbWFsbD4iLA0KICAgICAgICAgZm9vdG5vdGVfYXNfY2h1bmsgPSBUUlVFLA0KICAgICAgICAgZXNjYXBlID0gRkFMU0UpDQpgYGANCg0KIyMjIEJ5IERhdGEgVHlwZQ0KDQpUaGUgdHlwZSBvZiBkYXRhIHlvdSB3YW50IHRvIHZpc3VhbGl6ZSBhbHNvIG1hdHRlcnMuIFdoZW4geW91IGFyZW4ndCBzdXJlIHdoYXQgdG8gY29tbXVuaWNhdGUgdG8geW91ciBhdWRpZW5jZSwgZXhwbG9yZSB3aGF0IGlzIHBvc3NpYmxlIHdpdGggeW91ciBkYXRhc2V0IHVzaW5nIHRoZSBEZWNpc2lvbiBUcmVlLiBJdCBoZWxwcyB5b3UgbWFrZSBkZWNpc2lvbnMgYmFzZWQgb24gdGhlIG51bWJlciBvZiB2YXJpYWJsZXMsIHR5cGUgb2YgdmFyaWFibGUocyksIG51bWJlciBvZiBvYnNlcnZhdGlvbnMsIGFuZCBkYXRhIHN0cnVjdHVyZS4gQ2xpY2sgdGhlIGltYWdlIGJlbG93IHRvIGV4cGxvcmUgYW4gaW50ZXJhY3RpdmUgdmVyc2lvbiBvZiB0aGUgRGVjaXNpb24gVHJlZSBwb3N0ZXIuDQoNClshW0RhdGEgVml6IERlY2lzaW9uIFRyZWVdKGh0dHBzOi8vYXR0YWNobWVudHMuY29udmVydGtpdGNkbm4yLmNvbS8xMzAwMTQ2LzRiNTIyODQwLWJkNWQtNGU1OC1iMmYzLTYwNDJmYjlmYTlkNi9wb3N0ZXItYmlnLnBuZyldKGh0dHBzOi8vd3d3LmRhdGEtdG8tdml6LmNvbS8pDQo8c21hbGw+RGVjaXNpb24gVHJlZSBieSBGcm9tIERhdGEgdG8gVml6LCBhIHBhcnRuZXIgb2YgUiBHcmFwaCBHYWxsZXJ5PC9zbWFsbD4NCg0KIyMjIFRoZSBMaXN0IGFuZCBFeGFtcGxlcyB7LnRhYnNldH0NCg0KVGhlcmUgYXJlIHRob3VzYW5kcyBvZiBkYXRhIHZpc3VhbGl6YXRpb24gb3B0aW9ucyBpbiBSLCBidXQgdGhlc2UgbGlzdHMgYXJlIGEgZ29vZCBzdGFydCB0byBleHBsb3Jpbmcgd2hhdCBpcyBwb3NzaWJsZS4gVGhlIGNhdGVnb3JpZXMgYW5kIHZpeiB0eXBlcyBjb21lIGZyb20gW0Zyb20gRGF0YSB0byBWaXpdKGh0dHBzOi8vd3d3LmRhdGEtdG8tdml6LmNvbS8pLg0KDQojIyMjIENvcnJlbGF0aW9uDQoNCmBgYHtyIGNvcnJlbGF0aW9uLCBpbmNsdWRlPVRSVUUsIGVjaG89RkFMU0V9DQoNCmNvcnJlbGF0aW9uX2xpc3QgPC0gZmlsdGVyKGJpZ2xpc3RkYXR2aXosIENhdGVnb3J5PT0iQ29ycmVsYXRpb24iKQ0KDQoNCmNvcnJlbGF0aW9uX3RhYmxlIDwtIGthYmxlKGNvcnJlbGF0aW9uX2xpc3QpICU+JSANCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAicmVzcG9uc2l2ZSIpKSAlPiUNCiAgZm9vdG5vdGUoZ2VuZXJhbCA9ICI8c21hbGw+SSBnZW5lcmF0ZWQgdGhpcyB0ZXh0IGluIHBhcnQgd2l0aCBDaGF0R1BULTQsIE9wZW5BSeKAmXMgbGFyZ2Utc2NhbGUgbGFuZ3VhZ2UgZ2VuZXJhdGlvbiBtb2RlbC4gVXBvbiBnZW5lcmF0aW5nIGRyYWZ0IGxhbmd1YWdlLCBJIHJldmlld2VkLCBlZGl0ZWQsIGFuZCByZXZpc2VkIHRoZSBsYW5ndWFnZSB0byBteSBsaWtpbmcuIEkgdGFrZSB1bHRpbWF0ZSByZXNwb25zaWJpbGl0eSBmb3IgdGhlIGNvbnRlbnQgb2YgdGhpcyBwdWJsaWNhdGlvbi48L3NtYWxsPiIsDQogICAgICAgICBnZW5lcmFsX3RpdGxlID0gIjxzbWFsbD5Ob3RlOiA8L3NtYWxsPiIsDQogICAgICAgICBmb290bm90ZV9hc19jaHVuayA9IFRSVUUsDQogICAgICAgICBlc2NhcGUgPSBGQUxTRSkNCg0KcmVtb3ZlX2NvbHVtbihjb3JyZWxhdGlvbl90YWJsZSwgMSkNCg0KYGBgDQoNCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXN1Y2Nlc3MiPg0KICBUaGlzIGlzIGEgMmQgZGVuc2l0eSBjaGFydC48L2Rpdj4NCiAgIVsyZF0oaHR0cHM6Ly9yLWdyYXBoLWdhbGxlcnkuY29tLzJkLWRlbnNpdHktcGxvdC13aXRoLWdncGxvdDJfZmlsZXMvZmlndXJlLWh0bWwvdGhlY29kZTItMi5wbmcpDQogIDxicj48c21hbGw+MmQgZGVuc2l0eSBjaGFydCBmb3VuZCBvbiBUaGUgUiBHcmFwaCBHYWxsZXJ5PC9zbWFsbD4NCg0KIyMjIyBEaXN0cmlidXRpb24NCg0KYGBge3IgZGlzdHJpYnV0aW9uLCBpbmNsdWRlPVRSVUUsIGVjaG89RkFMU0V9DQoNCmRpc3RyaWJ1dGlvbl9saXN0IDwtIGZpbHRlcihiaWdsaXN0ZGF0dml6LCBDYXRlZ29yeT09IkRpc3RyaWJ1dGlvbiIpDQoNCg0KZGlzdHJpYnV0aW9uX3RhYmxlIDwtIGthYmxlKGRpc3RyaWJ1dGlvbl9saXN0KSAlPiUgDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgInJlc3BvbnNpdmUiKSkgJT4lDQogIGZvb3Rub3RlKGdlbmVyYWwgPSAiPHNtYWxsPkkgZ2VuZXJhdGVkIHRoaXMgdGV4dCBpbiBwYXJ0IHdpdGggQ2hhdEdQVC00LCBPcGVuQUnigJlzIGxhcmdlLXNjYWxlIGxhbmd1YWdlIGdlbmVyYXRpb24gbW9kZWwuIFVwb24gZ2VuZXJhdGluZyBkcmFmdCBsYW5ndWFnZSwgSSByZXZpZXdlZCwgZWRpdGVkLCBhbmQgcmV2aXNlZCB0aGUgbGFuZ3VhZ2UgdG8gbXkgbGlraW5nLiBJIHRha2UgdWx0aW1hdGUgcmVzcG9uc2liaWxpdHkgZm9yIHRoZSBjb250ZW50IG9mIHRoaXMgcHVibGljYXRpb24uPC9zbWFsbD4iLA0KICAgICAgICAgZ2VuZXJhbF90aXRsZSA9ICI8c21hbGw+Tm90ZTogPC9zbWFsbD4iLA0KICAgICAgICAgZm9vdG5vdGVfYXNfY2h1bmsgPSBUUlVFLA0KICAgICAgICAgZXNjYXBlID0gRkFMU0UpDQoNCnJlbW92ZV9jb2x1bW4oZGlzdHJpYnV0aW9uX3RhYmxlLCAxKQ0KDQpgYGANCg0KPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtaW5mbyI+DQogIFRoaXMgaXMgYSByaWRnZWxpbmUgY2hhcnQuPC9kaXY+DQogICFbUmVudF0oaHR0cHM6Ly9yLWdyYXBoLWdhbGxlcnkuY29tL3dlYi1yaWRnZWxpbmUtcGxvdC13aXRoLWluc2lkZS1wbG90LWFuZC1hbm5vdGF0aW9uc19maWxlcy9maWd1cmUtaHRtbC91bm5hbWVkLWNodW5rLTMtMS5wbmcpDQogIDxicj48c21hbGw+UmlkZ2VsaW5lIGNoYXJ0IGZvdW5kIG9uIFRoZSBSIEdyYXBoIEdhbGxlcnk8L3NtYWxsPg0KDQojIyMjIEV2b2x1dGlvbg0KDQpgYGB7ciBldm9sdXRpb24sIGluY2x1ZGU9VFJVRSwgZWNobz1GQUxTRX0NCg0KZXZvbHV0aW9uX2xpc3QgPC0gZmlsdGVyKGJpZ2xpc3RkYXR2aXosIENhdGVnb3J5PT0iRXZvbHV0aW9uIikNCg0KDQpldm9sdXRpb25fdGFibGUgPC0ga2FibGUoZXZvbHV0aW9uX2xpc3QpICU+JSANCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAicmVzcG9uc2l2ZSIpKSAlPiUNCiAgZm9vdG5vdGUoZ2VuZXJhbCA9ICI8c21hbGw+SSBnZW5lcmF0ZWQgdGhpcyB0ZXh0IGluIHBhcnQgd2l0aCBDaGF0R1BULTQsIE9wZW5BSeKAmXMgbGFyZ2Utc2NhbGUgbGFuZ3VhZ2UgZ2VuZXJhdGlvbiBtb2RlbC4gVXBvbiBnZW5lcmF0aW5nIGRyYWZ0IGxhbmd1YWdlLCBJIHJldmlld2VkLCBlZGl0ZWQsIGFuZCByZXZpc2VkIHRoZSBsYW5ndWFnZSB0byBteSBsaWtpbmcuIEkgdGFrZSB1bHRpbWF0ZSByZXNwb25zaWJpbGl0eSBmb3IgdGhlIGNvbnRlbnQgb2YgdGhpcyBwdWJsaWNhdGlvbi48L3NtYWxsPiIsDQogICAgICAgICBnZW5lcmFsX3RpdGxlID0gIjxzbWFsbD5Ob3RlOiA8L3NtYWxsPiIsDQogICAgICAgICBmb290bm90ZV9hc19jaHVuayA9IFRSVUUsDQogICAgICAgICBlc2NhcGUgPSBGQUxTRSkNCg0KcmVtb3ZlX2NvbHVtbihldm9sdXRpb25fdGFibGUsIDEpDQoNCmBgYA0KDQo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC13YXJuaW5nIj4NCiAgVGhpcyBpcyBhIHN0cmVhbSBjaGFydCwgYWxzbyBjYWxsZWQgYSBzdHJlYW0gZ3JhcGguPC9kaXY+DQogICFbQ29taWNzXShodHRwczovL3ItZ3JhcGgtZ2FsbGVyeS5jb20vaW1nL2Zyb21UaGVXZWIvc3RyZWFtY2hhcnQteG1lbi5wbmcpDQogIDxicj48c21hbGw+U3RyZWFtIGNoYXJ0IGZvdW5kIG9uIFRoZSBSIEdyYXBoIEdhbGxlcnk8L3NtYWxsPg0KDQojIyMjIEZsb3cNCg0KYGBge3IgZmxvdywgaW5jbHVkZT1UUlVFLCBlY2hvPUZBTFNFfQ0KDQpmbG93X2xpc3QgPC0gZmlsdGVyKGJpZ2xpc3RkYXR2aXosIENhdGVnb3J5PT0iRmxvdyIpDQoNCg0KZmxvd190YWJsZSA8LSBrYWJsZShmbG93X2xpc3QpICU+JSANCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAicmVzcG9uc2l2ZSIpKSAlPiUNCiAgZm9vdG5vdGUoZ2VuZXJhbCA9ICI8c21hbGw+SSBnZW5lcmF0ZWQgdGhpcyB0ZXh0IGluIHBhcnQgd2l0aCBDaGF0R1BULTQsIE9wZW5BSeKAmXMgbGFyZ2Utc2NhbGUgbGFuZ3VhZ2UgZ2VuZXJhdGlvbiBtb2RlbC4gVXBvbiBnZW5lcmF0aW5nIGRyYWZ0IGxhbmd1YWdlLCBJIHJldmlld2VkLCBlZGl0ZWQsIGFuZCByZXZpc2VkIHRoZSBsYW5ndWFnZSB0byBteSBsaWtpbmcuIEkgdGFrZSB1bHRpbWF0ZSByZXNwb25zaWJpbGl0eSBmb3IgdGhlIGNvbnRlbnQgb2YgdGhpcyBwdWJsaWNhdGlvbi48L3NtYWxsPiIsDQogICAgICAgICBnZW5lcmFsX3RpdGxlID0gIjxzbWFsbD5Ob3RlOiA8L3NtYWxsPiIsDQogICAgICAgICBmb290bm90ZV9hc19jaHVuayA9IFRSVUUsDQogICAgICAgICBlc2NhcGUgPSBGQUxTRSkNCg0KcmVtb3ZlX2NvbHVtbihmbG93X3RhYmxlLCAxKQ0KDQpgYGANCg0KPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtZGFuZ2VyIj4NCiAgVGhpcyBpcyBhIGNob3JkIGRpYWdyYW0uPC9kaXY+DQogICFbTWlncmF0aW9uXShodHRwczovL3d3dy5kYXRhLXRvLXZpei5jb20vZ3JhcGgvY2hvcmRfZmlsZXMvZmlndXJlLWh0bWwvdW5uYW1lZC1jaHVuay0xLTEucG5nKQ0KICA8YnI+PHNtYWxsPkNob3JkIGZvdW5kIG9uIFRoZSBSIEdyYXBoIEdhbGxlcnk8L3NtYWxsPg0KDQojIyMjIE1hcA0KDQpgYGB7ciBtYXAsIGluY2x1ZGU9VFJVRSwgZWNobz1GQUxTRX0NCg0KbWFwX2xpc3QgPC0gZmlsdGVyKGJpZ2xpc3RkYXR2aXosIENhdGVnb3J5PT0iTWFwIikNCg0KDQptYXBfdGFibGUgPC0ga2FibGUobWFwX2xpc3QpICU+JSANCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAicmVzcG9uc2l2ZSIpKSAlPiUNCiAgZm9vdG5vdGUoZ2VuZXJhbCA9ICI8c21hbGw+SSBnZW5lcmF0ZWQgdGhpcyB0ZXh0IGluIHBhcnQgd2l0aCBDaGF0R1BULTQsIE9wZW5BSeKAmXMgbGFyZ2Utc2NhbGUgbGFuZ3VhZ2UgZ2VuZXJhdGlvbiBtb2RlbC4gVXBvbiBnZW5lcmF0aW5nIGRyYWZ0IGxhbmd1YWdlLCBJIHJldmlld2VkLCBlZGl0ZWQsIGFuZCByZXZpc2VkIHRoZSBsYW5ndWFnZSB0byBteSBsaWtpbmcuIEkgdGFrZSB1bHRpbWF0ZSByZXNwb25zaWJpbGl0eSBmb3IgdGhlIGNvbnRlbnQgb2YgdGhpcyBwdWJsaWNhdGlvbi48L3NtYWxsPiIsDQogICAgICAgICBnZW5lcmFsX3RpdGxlID0gIjxzbWFsbD5Ob3RlOiA8L3NtYWxsPiIsDQogICAgICAgICBmb290bm90ZV9hc19jaHVuayA9IFRSVUUsDQogICAgICAgICBlc2NhcGUgPSBGQUxTRSkNCg0KcmVtb3ZlX2NvbHVtbihtYXBfdGFibGUsIDEpDQoNCmBgYA0KDQo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1zdWNjZXNzIj4NCiAgVGhpcyBpcyBhIGNhcnRvZ3JhbSBtYXAuPC9kaXY+DQogICFbQWZyaWNhIFBvcHVsYXRpb25dKGh0dHBzOi8vci1ncmFwaC1nYWxsZXJ5LmNvbS8zMzEtYmFzaWMtY2FydG9ncmFtX2ZpbGVzL2ZpZ3VyZS1odG1sL3RoZWNvZGU0LTEucG5nKQ0KICA8YnI+PHNtYWxsPkNhcnRvZ3JhbSBmcm9tIHRoZSBSIEdyYXBoIEdhbGxlcnk8L3NtYWxsPg0KDQojIyMjIFBhcnQgb2YgYSBXaG9sZQ0KDQpgYGB7ciBwYXJ0LCBpbmNsdWRlPVRSVUUsIGVjaG89RkFMU0V9DQoNCnBhcnRfbGlzdCA8LSBmaWx0ZXIoYmlnbGlzdGRhdHZpeiwgQ2F0ZWdvcnk9PSJQYXJ0IG9mIGEgV2hvbGUiKQ0KDQoNCnBhcnRfdGFibGUgPC0ga2FibGUocGFydF9saXN0KSAlPiUgDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgInJlc3BvbnNpdmUiKSkgJT4lDQogIGZvb3Rub3RlKGdlbmVyYWwgPSAiPHNtYWxsPkkgZ2VuZXJhdGVkIHRoaXMgdGV4dCBpbiBwYXJ0IHdpdGggQ2hhdEdQVC00LCBPcGVuQUnigJlzIGxhcmdlLXNjYWxlIGxhbmd1YWdlIGdlbmVyYXRpb24gbW9kZWwuIFVwb24gZ2VuZXJhdGluZyBkcmFmdCBsYW5ndWFnZSwgSSByZXZpZXdlZCwgZWRpdGVkLCBhbmQgcmV2aXNlZCB0aGUgbGFuZ3VhZ2UgdG8gbXkgbGlraW5nLiBJIHRha2UgdWx0aW1hdGUgcmVzcG9uc2liaWxpdHkgZm9yIHRoZSBjb250ZW50IG9mIHRoaXMgcHVibGljYXRpb24uPC9zbWFsbD4iLA0KICAgICAgICAgZ2VuZXJhbF90aXRsZSA9ICI8c21hbGw+Tm90ZTogPC9zbWFsbD4iLA0KICAgICAgICAgZm9vdG5vdGVfYXNfY2h1bmsgPSBUUlVFLA0KICAgICAgICAgZXNjYXBlID0gRkFMU0UpDQoNCnJlbW92ZV9jb2x1bW4ocGFydF90YWJsZSwgMSkNCg0KYGBgDQoNCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LWluZm8iPg0KICBUaGlzIGlzIGEgd2FmZmxlIGNoYXJ0LiBUaGlzIHBhcnRpY3VsYXIgY2hhcnQgc2VydmVzIHR3byBwdXJwb3NlczogcGFydHMgb2YgYSB3aG9sZSBhbmQgZXZvbHV0aW9uLjwvZGl2Pg0KICAhW0N5Y2xvbmVzXShodHRwczovL3ItZ3JhcGgtZ2FsbGVyeS5jb20vaW1nL2dyYXBoL3dlYi13YWZmbGUtZm9yLXRpbWUtZXZvbHV0aW9uLnBuZykNCiAgPGJyPjxzbWFsbD5XYWZmbGUgY2hhcnQgZm91bmQgb24gVGhlIFIgR3JhcGggR2FsbGVyeTwvc21hbGw+DQoNCiMjIyMgUmFua2luZw0KDQpgYGB7ciByYW5rLCBpbmNsdWRlPVRSVUUsIGVjaG89RkFMU0V9DQoNCnJhbmtfbGlzdCA8LSBmaWx0ZXIoYmlnbGlzdGRhdHZpeiwgQ2F0ZWdvcnk9PSJSYW5raW5nIikNCg0KDQpyYW5rX3RhYmxlIDwtIGthYmxlKHJhbmtfbGlzdCkgJT4lIA0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJyZXNwb25zaXZlIikpICU+JQ0KICBmb290bm90ZShnZW5lcmFsID0gIjxzbWFsbD5JIGdlbmVyYXRlZCB0aGlzIHRleHQgaW4gcGFydCB3aXRoIENoYXRHUFQtNCwgT3BlbkFJ4oCZcyBsYXJnZS1zY2FsZSBsYW5ndWFnZSBnZW5lcmF0aW9uIG1vZGVsLiBVcG9uIGdlbmVyYXRpbmcgZHJhZnQgbGFuZ3VhZ2UsIEkgcmV2aWV3ZWQsIGVkaXRlZCwgYW5kIHJldmlzZWQgdGhlIGxhbmd1YWdlIHRvIG15IGxpa2luZy4gSSB0YWtlIHVsdGltYXRlIHJlc3BvbnNpYmlsaXR5IGZvciB0aGUgY29udGVudCBvZiB0aGlzIHB1YmxpY2F0aW9uLjwvc21hbGw+IiwNCiAgICAgICAgIGdlbmVyYWxfdGl0bGUgPSAiPHNtYWxsPk5vdGU6IDwvc21hbGw+IiwNCiAgICAgICAgIGZvb3Rub3RlX2FzX2NodW5rID0gVFJVRSwNCiAgICAgICAgIGVzY2FwZSA9IEZBTFNFKQ0KDQpyZW1vdmVfY29sdW1uKHJhbmtfdGFibGUsIDEpDQoNCmBgYA0KDQo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC13YXJuaW5nIj4NCiAgVGhpcyBpcyBhIGNpcmN1bGFyIGxvbGlwb3AgcGxvdC48L2Rpdj4NCiAgIVtQYXNzd29yZF0oaHR0cHM6Ly9yLWdyYXBoLWdhbGxlcnkuY29tL2ltZy9mcm9tVGhlV2ViL3dlYi1jaXJjdWxhci1sb2xsaXBvcC1wbG90LXdpdGgtZ2dwbG90Mi5wbmcpDQogIDxicj48c21hbGw+UGxvdCBmb3VuZCBvbiBUaGUgUiBHcmFwaCBHYWxsZXJ5PC9zbWFsbD4NCg0KIyMgQ2hvcm9wbGV0aCBNYXBwaW5nIFR1dG9yaWFsDQoNCldlJ2xsIGNyZWF0ZSBhIHNlcmllcyBvZiBzdGF0aWMgY2hvcm9wbGV0aCBtYXBzIHVzaW5nIFRoZSBDZW50ZXJzIGZvciBEaXNlYXNlIENvbnRyb2wgYW5kIFByZXZlbnRpb24gYW5kIEFnZW5jeSBmb3IgVG94aWMgU3Vic3RhbmNlcyBhbmQgRGlzZWFzZSBSZWdpc3RyeSBTb2NpYWwgVnVsbmVyYWJpbGl0eSBJbmRleCAob3IgQ0RDL0FUU0RSIFNWSSkuDQoNCkNvZGUgaW4gdGhlIHR1dG9yaWFsIHNlY3Rpb24gd2FzIGFkYXB0ZWQgZnJvbSBLeWxlIFdhbGtlcidzIGJvb2ssIDxpPltBbmFseXppbmcgVVMgQ2Vuc3VzIERhdGE6IE1ldGhvZHMsIE1hcHMsIGFuZCBNb2RlbHMgaW4gUl0oaHR0cHM6Ly93YWxrZXItZGF0YS5jb20vY2Vuc3VzLXIvaW5kZXguaHRtbCk8L2k+LiBJbnN0YW5jZXMgd2hlcmUgV2Fsa2VyJ3MgZXhhY3QgY29kZSBpcyB1c2VkIGFyZSBub3RlZC4NCg0KIyMjIEFib3V0IHRoZSBTVkkgey50YWJzZXR9DQoNCiMjIyMgV2hhdCBpcyBTb2NpYWwgVnVsbmVyYWJpbGl0eT8NCg0KVGhlIENEQy9BVFNEUiBkZXNjcmliZXMgc29jaWFsIHZ1bG5lcmFiaWxpdHkgYXMgInRoZSBkZWdyZWUgdG8gd2hpY2ggYSBjb21tdW5pdHkgZXhoaWJpdHMgY2VydGFpbiA8c3Ryb25nPnNvY2lhbCBjb25kaXRpb25zPC9zdHJvbmc+LCBpbmNsdWRpbmcgaGlnaCBwb3ZlcnR5LCBsb3cgcGVyY2VudGFnZSBvZiB2ZWhpY2xlIGFjY2Vzcywgb3IgY3Jvd2RlZCBob3VzZWhvbGRzLCBhbW9uZyBvdGhlcnMsIG1heSBhZmZlY3QgdGhhdCBjb21tdW5pdHnigJlzIGFiaWxpdHkgdG8gcHJldmVudCBodW1hbiBzdWZmZXJpbmcgYW5kIGZpbmFuY2lhbCBsb3NzIGluIHRoZSBldmVudCBvZiBhIGRpc2FzdGVyLiINCg0KU29jaWFsIGNvbmRpdGlvbnMgYXJlIHRoZSBjb25kaXRpb25zIGluIHdoaWNoIHBlb3BsZSBsaXZlIGFuZCB3b3JrLCBrbm93biBiZXR0ZXIgdG8gcHVibGljIGhlYWx0aCBwcmFjdGl0aW9uZXJzIGFzIHRoZSBzb2NpYWwgZGV0ZXJtaW5hbnRzIG9mIGhlYWx0aC4gVGhlIHZhcmlhYmxlcyB1c2VkIGJ5IHRoZSBDREMvQVRTRFIgYWZmZWN0IHBlb3BsZSdzIGFiaWxpdHkgdG8gcHJlcGFyZSBmb3IgaGF6YXJkcywgdGFrZSBwcm90ZWN0aXZlIGFjdGlvbnMsIGFuZCByZWNvdmVyIGZyb20gZXZlbnRzLiBBdCB0aGUgcG9wdWxhdGlvbiBsZXZlbCwgdGhlIHJlc3VsdCBpcyBzb2NpYWwgdnVsbmVyYWJpbGl0eS4gUmVtZW1iZXIgdGhhdCB0aGUgY29tbXVuaXR5IGlzIHNvY2lhbGx5IHZ1bG5lcmFibGUsIG5vdCBpbmRpdmlkdWFsIHBlb3BsZS4NCg0KVGhlIDxpPk1ldGhvZG9sb2d5PC9pPiB0YWIgd2lsbCB1c2UgbGFuZ3VhZ2UgZnJvbSB0aGUgSGVhbHRoIEVxdWl0eSBBY3Rpb24gU3BlY3RydW0gZnJvbSB0aGUgW01vYmlsaXppbmcgZm9yIEFjdGlvbiB0aHJvdWdoIFBsYW5uaW5nIGFuZCBQYXJ0bmVyc2hpcHMgKE1BUFApIDIuMCBVc2VyIEhhbmRib29rXShodHRwczovL3d3dy5uYWNjaG8ub3JnL3VwbG9hZHMvY2FyZC1pbWFnZXMvcHVibGljLWhlYWx0aC1pbmZyYXN0cnVjdHVyZS1hbmQtc3lzdGVtcy9NQVBQLTIuMC1MYXVuY2gtVjMucGRmKS4gSWYgeW91IG1pc3NlZCBPY3RvYmVyJ3MgQWxsLVN0YWZmIE1lZXRpbmcsIHRoZSBtb3N0IGltcG9ydGFudCBpZGVhIGZyb20gdGhlIHNwZWN0cnVtIGlzOg0KPiBUaGUgcm9vdCBjYXVzZXMgb2YgaW5lcXVpdHkgY3JlYXRlIGhpZXJhcmNoaWVzIG9mIHByaXZpbGVnZSBhbmQgb3BwcmVzc2lvbiB3aGljaCBsZWFkIHRvIGltYmFsYW5jZXMgaW4gcG93ZXIgYW5kIGFjY2VzcyB0byBwb3dlciwgZ2VuZXJhdGluZyBwcmV2ZW50YWJsZSBkaWZmZXJlbmNlcyBpbiBpbmRpdmlkdWFsIGhlYWx0aC4NCg0KIyMjIyBNZXRob2RvbG9neQ0KDQpUaGUgU29jaWFsIFZ1bG5lcmFiaWxpdHkgSW5kZXggc2NvcmVzIGNlbnN1cyB0cmFjdHMgYmFzZWQgb24gMTYgdmFyaWFibGVzLiBDZW5zdXMgdHJhY3RzIGFyZSByYW5rZWQgaW4gc2V2ZXJhbCB3YXlzLiBFYWNoIHZhcmlhYmxlIGlzIHJhbmtlZCBpbmRpdmlkdWFsbHkuIFRoZW4sIHRoZSB2YXJpYWJsZXMgYXJlIHNlcGFyYXRlZCBpbnRvIGZvdXIgdGhlbWVzLCBlYWNoIG9mIHdoaWNoIHJlY2VpdmVzIGEgcmFuay4gVGhlIGZpbmFsIHJhbmtpbmcgaXMgdGhlIG92ZXJhbGwgc2NvcmUuIFRoZSBpbWFnZSBiZWxvdyB2aXN1YWxpemVzIHRoaXMgY29uY2VwdC4gVGhlIHNjb3JlcyByYW5nZSBmcm9tIDAtMSB3aXRoIDEgaW5kaWNhdGluZyBoaWdoIHNvY2lhbCB2dWxuZXJhYmlsaXR5Lg0KDQpUcmFjdHMgdGhhdCByYW5rIGluIHRoZSB0b3AgMTAlIGFyZSBnaXZlbiBhICJmbGFnLiIgVGhlIG92ZXJhbGwgZmxhZyB2YWx1ZSBhZGRzIGFsbCBmbGFncyByZWNlaXZlZC4gVGhlIGhpZ2hlciB0aGUgb3ZlcmFsbCBmbGFnIHZhbHVlIGlzLCB0aGUgbW9yZSBmcmVxdWVudGx5IGEgY2Vuc3VzIHRyYWN0IGFwcGVhcmVkIGluIDkwdGggcGVyY2VudGlsZXMgZm9yIHNvY2lhbCB2dWxuZXJhYmlsaXR5Lg0KDQpbIVtWYXJpYWJsZXMgYnkgVGhlbWVdKGh0dHBzOi8vd3d3LmF0c2RyLmNkYy5nb3YvcGxhY2VhbmRoZWFsdGgvc3ZpL2ltZy9TVkktVmFyaWFibGUtVGFibGUucG5nP189MjcwNjYpe3dpZHRoPTUwJX1dKGh0dHBzOi8vd3d3LmF0c2RyLmNkYy5nb3YvcGxhY2VhbmRoZWFsdGgvc3ZpL2ltZy9TVkktVmFyaWFibGUtVGFibGUucG5nP189MjcwNjYpPGJyPg0KPHNtYWxsPk92ZXJhbGwgU29jaWFsIFZ1bG5lcmFiaWxpdHkgYnkgdGhlIENEQy9BVFNEUjwvc21hbGw+DQoNCiMjIyMgVXNpbmcgdGhlIFNWSSBpbiBQdWJsaWMgSGVhbHRoDQoNClRoZSBTb2NpYWwgVnVsbmVyYWJpbGl0eSBJbmRleCBpcyBmcmVxdWVudGx5IHVzZWQgdG8gc3R1ZHkgYXNzb2NpYXRpb25zIGJldHdlZW4gc29jaWFsIHZ1bG5lcmFiaWxpdHkgYW5kIGhlYWx0aCBvdXRjb21lcy4gSXQgaGFzIGJlZW4gdXNlZCB0byBzdHVkeSB0aGluZ3MgbGlrZSBbaGVhbHRoY2FyZSByZXNvdXJjZSB1dGlsaXphdGlvbiBpbiBtZWRpY2FsbHkgY29tcGxleCBwYXRpZW50c10oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DOTc5ODM4My8pLCBbb3V0Y29tZXMgaW4gY2FuY2VyIHBhdGllbnRzXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3BtYy9hcnRpY2xlcy9QTUMxMDA4MDUxMC8pLCBhbmQgZXZlbiBbbG9uZy10ZXJtIG91dGNvbWVzIGFmdGVyIHRyYXVtYXRpYyBpbmp1cnldKGh0dHBzOi8vcHVibWVkLm5jYmkubmxtLm5paC5nb3YvMzU3MDM0NTUvKS4NCg0KVGhlIFNWSSBjYW4gYWxzbyBiZSB1c2VkIHRvIHN0dWR5IG90aGVyIHNvY2lhbCBkZXRlcm1pbmFudHMgb2YgaGVhbHRoIGFuZCBzeXN0ZW1zIG9mIHBvd2VyLCBwcml2aWxlZ2UsIGFuZCBvcHByZXNzaW9uLiBPbmUgc3R1ZHkgdXNlZCB0aGUgU1ZJIGFuZCBCUkZTUyBkYXRhIHRvIGFzc2VzcyBbYWNjZXNzIHRvIGhlYWx0aGNhcmVdKGh0dHBzOi8vcHVibWVkLm5jYmkubmxtLm5paC5nb3YvMzU1MDQ3OTYvKSBhdCB0aGUgc3RhdGUtbGV2ZWwuIEFub3RoZXIgc3R1ZHkgY29tYmluZWQgdGhlIFNWSSB3aXRoIDE1IGFkZGl0aW9uYWwgQ2Vuc3VzIG1lYXN1cmVzIHRvIG1lYXN1cmUgdGhlIFthc3NvY2lhdGlvbiBiZXR3ZWVuIHN0cnVjdHVyYWwgcmFjaXNtIGFuZCBjYXJkaW92YXNjdWxhciBoZWFsdGggcmlza10oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DODQwNTU0NS8pIGFtb25nIEJsYWNrL0FmcmljYW4gQW1lcmljYW4gd29tZW4uDQoNCkZsYWdzIGNhbiBpbmRpY2F0ZSBhcmVhcyB3aGVyZSB1cHN0cmVhbSBhcHByb2FjaGVzIG1pZ2h0IGhhdmUgc2lnbmlmaWNhbnQgaW1wYWN0IG9uIHNvY2lhbCB2dWxuZXJhYmlsaXR5IGFuZCBpbmRpdmlkdWFsIGhlYWx0aC4gVGhlIGZsYWcgYXBwcm9hY2ggY291bGQgZXZlbiBiZSBtb2RpZmllZCB0byBpbmNsdWRlIG1vcmUgdHJhY3RzIChsaWtlIHRob3NlIGluIHRoZSB0b3AgMTUlIG9yIDg1dGggcGVyY2VudGlsZSkgb3IgdG8gaWRlbnRpZnkgcmVzb3VyY2UgcmljaCBlbnZpcm9ubWVudHMgKGxpa2UgdHJhY3RzIHdpdGggdGVuIG9yIG1vcmUgdmFyaWFibGVzIGluIHRoZSBib3R0b20gMjAlKS4NCg0KV2hpbGUgdGhlIFNWSSBpcyB1c2VkIHByaW1hcmlseSBhcyBhbiBpbmRpY2F0b3Igb2YgY29tbXVuaXR5IHByZXBhcmVkbmVzcywgdGhlIHRydXRoIGlzIHRoYXQgaXQgbWVhc3VyZXMgc29jaWFsIGRldGVybWluYW50cyBvZiBoZWFsdGguIFRoZSBTVkkgaGFzIHBvdGVudGlhbCBhcyBhIG1lYXN1cmUgb2YgdGhlIHJvb3QgY2F1c2VzIG9mIGluZXF1aXR5IGFuZCBvZiB0aGUgZG93bnN0cmVhbSBlZmZlY3RzIG9mIHRoZSBzb2NpYWwgZGV0ZXJtaW5hbnRzIG9mIGhlYWx0aCBhbmQgdGhlIHN5c3RlbXMgb2YgcG93ZXIsIHByaXZpbGVnZSwgYW5kIG9wcHJlc3Npb24gb24gaW5kaXZpZHVhbCBoZWFsdGguDQoNCiMjIyBDcmVhdGluZyB0aGUgQmFzZSBNYXANCg0KIyMjIyBJbnN0YWxsaW5nIFBhY2thZ2VzDQoNClRoZSB2ZXJ5IGZpcnN0IHN0ZXAgaXMgdG8gaW5zdGFsbCBwYWNrYWdlcyB5b3UgZG9uJ3QgaGF2ZS4gUiBwYWNrYWdlcyBleHRlbmQgdGhlIGNhcGFiaWxpdGllcyBvZiB0aGUgYmFzZSBSIHN5c3RlbS4gUGFja2FnZXMgYXJlIGZyZWUgYW5kIG9mdGVuIGNvbWUgd2l0aCB1c2VmdWwgZG9jdW1lbnRhdGlvbi4NCg0KWW91IGNhbiBpbnN0YWxsIHBhY2thZ2VzIHVzaW5nIGBpbnN0YWxsLnBhY2thZ2VzKCJuYW1lIilgLiBGb3IgZXhhbXBsZSwgYGluc3RhbGwucGFja2FnZXMoImRwbHlyIilgIHdpbGwgaW5zdGFsbCBkcGx5ci4gVGhlIHR1dG9yaWFsIHJlcXVpcmVzIHRoZSBmb2xsb3dpbmcgcGFja2FnZXMuDQoNCiogZ2dwbG90Mg0KKiBzZg0KKiB0aWdyaXMNCiogcGF0Y2h3b3JrDQoqIG1hcHZpZXcNCiogdmlyaWRpcw0KDQojIyMjIExvYWRpbmcgTGlicmFyaWVzDQoNCk9uY2UgdGhlIHBhY2thZ2VzIGFyZSBpbnN0YWxsZWQsIHdlIGhhdmUgdG8gbG9hZCB0aGUgbWFwcGluZyB0b29scyB3ZSBuZWVkLiBXZSBkbyB0aGlzIGJ5IHJ1bm5pbmcgYGxpYnJhcnkobmFtZSlgLg0KYGBge3IgbWFwLWxpYnJhcnl9DQoNCiMgTG9hZHMgbGlicmFyaWVzDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeSh0aWdyaXMpDQpsaWJyYXJ5KHBhdGNod29yaykNCmxpYnJhcnkobWFwdmlldykNCmxpYnJhcnkodmlyaWRpcykNCg0KYGBgDQoNCiMjIyMgQ3JlYXRpbmcgdGhlIEluaXRpYWwgTWFwDQoNCk5vdyB3ZSBjYW4gY3JlYXRlIGFuIG9iamVjdCB3aXRoIHRoZSBzaGFwZWZpbGVzIHdlIG5lZWQgZm9yIHRoZSBtYXAuIFdlIG9ubHkgd2FudCBhIG1hcCB0aGF0IGluY2x1ZGVzIGNlbnN1cyB0cmFjdHMgZm9yIFNwb2thbmUgQ291bnR5Lg0KYGBge3IgY3JlYXRlLXRyYWN0cywgcmVzdWx0cz0iaGlkZSJ9DQoNCiMgQ3JlYXRlcyBhbiBvYmplY3Qgd2UgY2FuIG1hcCB3aXRoIG91ciBzcGVjaWZpY2F0aW9ucw0Kc2NfdHJhY3RzIDwtIHRyYWN0cygiV0EiLCAiU3Bva2FuZSIpDQoNCmBgYA0KDQpMZXQncyBjcmVhdGUgdGhlIGJhc2UgbWFwLiBXZSBjYW4gY2hhbmdlIHRoZSBsb29rIG9mIGEgbWFwIGluIG1hbnkgd2F5cy4NCmBgYHtyIG91dC53aWR0aCA9ICIxMDAlIn0NCg0KIyBDcmVhdGVzIGEgYmFzaWMgZ2dwbG90IG1hcA0KZ2dwbG90KHNjX3RyYWN0cykgKw0KICBnZW9tX3NmKCkNCmBgYA0KDQpgYGB7ciBvdXQud2lkdGggPSAiMTAwJSJ9DQojIFZvaWRzIHRoZSBkZWZhdWx0IHRoZW1lDQpnZ3Bsb3Qoc2NfdHJhY3RzKSArIA0KICBnZW9tX3NmKCkgKyANCiAgdGhlbWVfdm9pZCgpDQpgYGANCg0KTGV0J3Mgc2F2ZSB0aGVzZSBtYXBzIGFzIG9iamVjdHMgdG8gY29tcGFyZSB0aGVtIHVzaW5nIHRoZSBwYXRjaHdvcmsgbGlicmFyeS4gVGhpcyBhbGxvd3MgdXMgdG8gZG8gYSBzaWRlLWJ5LXNpZGUgY29tcGFyaXNvbi4gSWYgd2Ugd2FudGVkIHRvIGNvbXBhcmUgdGhlbSB2ZXJ0aWNhbGx5LCB3ZSdkIHJlcGxhY2UgYHNjX21hcF9nZzEgKyBzY19tYXBfZ2cyYCB3aXRoIGBzY19tYXBfZ2cxIC8gc2NfbWFwX2dnMmAuIFdlJ2xsIHVzZSB0aGlzIHBhY2thZ2UgYWdhaW4uDQpgYGB7cn0NCg0KIyBDcmVhdGVzIGdncGxvdCBtYXAgb2JqZWN0cw0Kc2NfbWFwX2dnMSA8LSBnZ3Bsb3Qoc2NfdHJhY3RzKSArIA0KICBnZW9tX3NmKCkNCg0Kc2NfbWFwX2dnMiA8LSBnZ3Bsb3Qoc2NfdHJhY3RzKSArIA0KICBnZW9tX3NmKCkgKyANCiAgdGhlbWVfdm9pZCgpDQpgYGANCg0KYGBge3Igb3V0LndpZHRoID0gIjEwMCUifQ0KIyBDb21wYXJlcyBvYmplY3RzDQpzY19tYXBfZ2cxICsgc2NfbWFwX2dnMg0KDQpgYGANCg0KIyMjIyBTdHJhbmdlIFNoYXBlcyB7LnRhYnNldH0NCg0KIyMjIyMgV2Fsa2VyJ3MgTWljaGlnYW4gRXhhbXBsZQ0KDQpUSUdFUi9MaW5lIHNoYXBlZmlsZXMgY2FuIGxvb2sgc29tZXRpbWVzIHN0cmFuZ2UuIFdlIGNhbiB1c2UgY2FydG9ncmFwaGljIGJvdW5kYXJpZXMgd2hlbiB0aGF0IGhhcHBlbnMuIA0KDQpUaGUgZm9sbG93aW5nIGV4YW1wbGUgaXMgcHVsbGVkIGRpcmVjdGx5IGZyb20gS3lsZSBXYWxrZXIncyBib29rLCA8aT5bQW5hbHl6aW5nIFVTIENlbnN1cyBEYXRhOiBNZXRob2RzLCBNYXBzLCBhbmQgTW9kZWxzIGluIFJdKGh0dHBzOi8vd2Fsa2VyLWRhdGEuY29tL2NlbnN1cy1yL2luZGV4Lmh0bWwpPC9pPi4gV2Fsa2VyIHVzZXMgTWljaGlnYW4gdG8gaGlnaGxpZ2h0IHRoZSBwb3dlciBvZiBjYXJ0b2dyYXBoaWMgYm91bmRhcmllcyBiZWNhdXNlIHRoZSBHcmVhdCBMYWtlcyBzaWduaWZpY2FudGx5IGFsdGVyIHRoZSBzdGF0ZSdzIHNoYXBlLg0KYGBge3IgbWktc2hhcGUtY291bnRpZXMsIHJlc3VsdHM9ImhpZGUifQ0KDQojIENyZWF0ZXMgYW4gb2JqZWN0IGRlZmF1bHRlZCB0byBubyBjYXJ0b2dyYXBoaWMgYm91bmRhcmllcw0KbWlfY291bnRpZXMgPC0gY291bnRpZXMoIk1JIikNCg0KIyBDcmVhdGVzIGFuIG9iamVjdCB3aXRoIGNhcnRvZ3JhcGhpYyBib3VuZGFyaWVzDQptaV9jb3VudGllc19jYiA8LSBjb3VudGllcygiTUkiLCBjYiA9IFRSVUUpDQoNCmBgYA0KDQpgYGB7cn0NCg0KIyBDcmVhdGVzIGdncGxvdCBtYXAgb2JqZWN0cw0KbWlfdGlnZXJfZ2cgPC0gZ2dwbG90KG1pX2NvdW50aWVzKSArDQogIGdlb21fc2YoKSArIA0KICB0aGVtZV92b2lkKCkgKyANCiAgbGFicyh0aXRsZSA9ICJUSUdFUi9MaW5lIikNCg0KbWlfY2JfZ2cgPC0gZ2dwbG90KG1pX2NvdW50aWVzX2NiKSArIA0KICBnZW9tX3NmKCkgKyANCiAgdGhlbWVfdm9pZCgpICsgDQogIGxhYnModGl0bGUgPSAiQ2FydG9ncmFwaGljIGJvdW5kYXJ5IikNCmBgYA0KDQpgYGB7ciBvdXQud2lkdGggPSAiMTAwJSJ9DQojIENvbXBhcmVzIG9iamVjdHMNCm1pX3RpZ2VyX2dnICsgbWlfY2JfZ2cNCmBgYA0KDQojIyMjIyBXaGF0IEl0IE1lYW5zIExvY2FsbHkNCg0KVGhpcyBkb2Vzbid0IGhhdmUgbXVjaCBlZmZlY3Qgb24gU3Bva2FuZSBDb3VudHksIGJ1dCBpdCBjb3VsZCBiZSB1c2VmdWwgd2hlbiBhbmFseXppbmcgc21hbGxlciBhcmVhcyB3aXRoaW4gU3Bva2FuZSBDb3VudHkgb3Igd2hlbiBwcm92aWRpbmcgcmVnaW9uYWwgc3VwcG9ydCBzZXJ2aWNlcyB0byBvdGhlciBjb3VudGllcy4NCmBgYHtyIGdncGxvdC1jYiwgcmVzdWx0cz0iaGlkZSJ9DQoNCiMgQ3JlYXRlcyBhbiBvYmplY3Qgd2UgY2FuIG1hcA0Kc2NfdHJhY3RzX2NiIDwtIHRyYWN0cygiV0EiLCAiU3Bva2FuZSIsIGNiID0gVFJVRSkNCg0KYGBgDQoNCmBgYHtyIGdncGxvdC1USUdFUmNiLWNvbXBhcmlzb259DQoNCiMgQ3JlYXRlcyBnZ3Bsb3QgbWFwIG9iamVjdHMNCnNjX3RpZ2VyX2dnIDwtIGdncGxvdChzY190cmFjdHMpICsgDQogIGdlb21fc2YoKSArIA0KICB0aGVtZV92b2lkKCkgKyANCiAgbGFicyh0aXRsZSA9ICJUSUdFUi9MaW5lIikNCg0Kc2NfY2JfZ2cgPC0gZ2dwbG90KHNjX3RyYWN0c19jYikgKyANCiAgZ2VvbV9zZigpICsgDQogIHRoZW1lX3ZvaWQoKSArIA0KICBsYWJzKHRpdGxlID0gIkNhcnRvZ3JhcGhpYyBib3VuZGFyeSIpDQpgYGANCg0KYGBge3Igb3V0LndpZHRoPSIxMDAlIn0NCiMgQ29tcGFyZXMgb2JqZWN0cw0Kc2NfdGlnZXJfZ2cgKyBzY19jYl9nZw0KDQpgYGANCg0KIyMjIEFkZGluZyB0aGUgRGF0YQ0KDQpOb3cgdGhhdCB3ZSBoYXZlIGEgdXNhYmxlIGJhc2UgbWFwLCB3ZSBjYW4gcHJlcGFyZSBhbmQgYWRkIHRoZSBTVkkgZGF0YSB3ZSBuZWVkLiBXZSdsbCB1c2UgdGhlIG92ZXJhbGwgU1ZJIHNjb3JlIGFuZCB0aGVtZXMgc2NvcmVzIGZvciBlYWNoIGNlbnN1cyB0cmFjdC4NCg0KIyMjIyBQcmVwYXJpbmcgdGhlIERhdGENCg0KTHVja2lseSBmb3IgdXMsIHRoZSBTVkkgZGF0YSBpcyBhbHJlYWR5IGluIGEgdXNhYmxlIGZvcm1hdC4gVGhlIGhlYWRlcnMgYXJlIGFiYnJldmlhdGVkLCBhbmQgd2UgbmVlZCB0byBtYWtlIHN1cmUgdGhhdCB3ZSB1bmRlcnN0YW5kIHdoaWNoIGNvbHVtbnMgd2UnbGwgYmUgdXNpbmcgZm9yIG91ciBjaG9yb3BsZXRoIG1hcHMuIEhvd2V2ZXIsIHRoZSBDREMvQVRTRFIgcG9zdHMgYSBkYXRhIGRpY3Rpb25hcnkgd2UgY2FuLiBZb3UgY2FuIGFjY2VzcyBpdCBpbiBhbiBbaW50ZXJhY3RpdmUgYW5kIHNlYXJjaGFibGUgdGFibGVdKGh0dHBzOi8vd3d3LmF0c2RyLmNkYy5nb3YvcGxhY2VhbmRoZWFsdGgvc3ZpL2RvY3VtZW50YXRpb24vU1ZJX2RvY3VtZW50YXRpb25fMjAyMi5odG1sKSBvciBpbiBhIFtQREYgZmlsZV0oaHR0cHM6Ly93d3cuYXRzZHIuY2RjLmdvdi9wbGFjZWFuZGhlYWx0aC9zdmkvZG9jdW1lbnRhdGlvbi9wZGYvU1ZJLTIwMjItRG9jdW1lbnRhdGlvbi1ILnBkZikuDQoNCldlJ2xsIHVzZSB0aGUgZm9sbG93aW5nIGNvbHVtbnMuDQoNCiogT3ZlcmFsbCBzY29yZQ0KICArIFJQTF9USEVNRVMNCiogVGhlbWUgc2NvcmVzDQogICsgU29jaW9lY29ub21pYyBTdGF0dXMgLSBSUExfVEhFTUUxDQogICsgSG91c2Vob2xkIENoYXJhY3RlcmlzdGljcyAtIFJQTF9USEVNRTINCiAgKyBSYWNpYWwgJiBFdGhuaWMgTWlub3JpdHkgU3RhdHVzIC0gUlBMX1RIRU1FMw0KICArIEhvdXNpbmcgVHlwZSAmIFRyYW5zcG9ydGF0aW9uIC0gUlBMX1RIRU1FNA0KKiBMb2NhdGlvbg0KICArIEZJUFMNCg0KIyMjIyBSZWFkaW5nIHRoZSBEYXRhDQoNCldlIG5lZWQgdG8gInJlYWQiIHRoZSBkYXRhIGludG8gUiBTdHVkaW8uIFlvdSBjYW4gdXNlIGEgVVJMIG9yIGxvY2FsIGZpbGUgdG8gZG8gdGhpcy4gVGhlIENEQy9BVFNEUiBwcm92aWRlcyB0aGUgZGF0YSBhcyBhIC5jc3YgZG93bmxvYWQuIFRoaXMgbWVhbnMgdGhlIGZpbGUgaXMgbG9jYWwuDQoNCmBgYHtyfQ0KDQojIFJlYWRzIGEgbG9jYWwgLmNzdiBmaWxlIGluIHRoZSBzYW1lIGZvbGRlciBhbmQgcmVjb2duaXplcyBoZWFkZXJzDQpzY19zdmkgPC0gcmVhZC5jc3YoInNjLXN2aS5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KDQpgYGANCg0KIyMjIyBFeHBsb3JpbmcgdGhlIERhdGENCg0KTm93IHRoYXQgdGhlIGRhdGEgYXBwZWFycyBpbiBvdXIgZ2xvYmFsIGVudmlyb25tZW50LCB3ZSBjb3VsZCBwZWVrIGF0IHdoYXQncyBpbiB0aGUgZmlsZSB1c2luZyBhIHZhcmlldHkgb2YgY29tbWFuZHMuIFdlIGNvdWxkIHVzZSB2ZXJicyBsaWtlIGBkaW0oKWAsIGBoZWFkKClgLCBgdGFpbCgpYCwgYHN0cigpYCwgb3IgYGdsaW1wc2UoKWAgdG8gcHJldmlldyBvciBsZWFybiBhYm91dCB0aGUgZGF0YS4gVGhpcyBpcyBtb3JlIHRoYW4gd2UgbmVlZCBub3csIGJ1dCBoZXJlJ3MgYW4gb3ZlcnZpZXcgb2Ygd2hhdCB0aGVzZSB2ZXJicyBkby4NCg0KKiBgZGltKClgIGdpdmVzIHJvdyBhbmQgY29sdW1uIGRpbWVuc2lvbnMNCiogYGhlYWQoKWAgcHJldmlld3MgdGhlIGZpcnN0IHNpeCByb3dzIG9yIHZhcmlhYmxlcywgYnV0IHlvdSBjYW4gc3BlY2lmeSBtb3JlIG9yIGxlc3MNCiogYHRhaWwoKWAgaXMgdGhlIHNhbWUgYXMgYGhlYWQoKWAgZXhjZXB0IHRoYXQgaXQgcHJldmlld3MgdGhlIGxhc3Qgc2l4IHJvd3Mgb3IgdmFyaWFibGVzDQoqIGBzdHIoKWAgc2hvd3MgZGltZW5zaW9ucywgdmFyaWFibGVzLCBjbGFzc2VzLCB2YXJpYWJsZSBwcmV2aWV3LCBldGMuDQoqIGBnbGltcHNlKClgIGlzIHNpbWlsYXIgdG8gYHN0cigpYCBidXQgcHJldmlld3MgbW9yZSB2YXJpYWJsZXMNCg0KIyMjIyBTZXR0aW5nIHRoZSBTVkkgU2NvcmUgQ2xhc3MgDQoNCldlIGhhdmUgdG8gdGVsbCBSIGhvdyB0byBjbGFzc2lmeSBzY29yZXMuDQoNCmBgYHtyfQ0KDQojIFVzZXMgZHBseXIgdG8gYWRkIGEgbmV3IGNvbHVtbiBiYXNlZCBvbiBvdGhlciBjb2x1bW5zIHdpdGhpbiB0aGUgZGF0YSBzZXQNCnNjX3N2aSA8LSBzY19zdmkgJT4lDQogIG11dGF0ZShvdmVyYWxscXVhcnRpbGUgPSBudGlsZShSUExfVEhFTUVTLCA0KSwNCiAgICAgICAgIHRoZW1lMXF1YXJ0aWxlID0gbnRpbGUoUlBMX1RIRU1FMSwgNCksDQogICAgICAgICB0aGVtZTJxdWFydGlsZSA9IG50aWxlKFJQTF9USEVNRTIsIDQpLA0KICAgICAgICAgdGhlbWUzcXVhcnRpbGUgPSBudGlsZShSUExfVEhFTUUzLCA0KSwNCiAgICAgICAgIHRoZW1lNHF1YXJ0aWxlID0gbnRpbGUoUlBMX1RIRU1FNCwgNCkpDQoNCmBgYA0KDQojIyMjIEpvaW5pbmcgdGhlIERhdGENCg0KV2UgbmVlZCB0byBjb21iaW5lIGBzY19zdmlgIGFuZCBgc2NfdHJhY3RzYCB1c2luZyBhIGxlZnQgam9pbi4gQSBsZWZ0IGpvaW4ga2VlcHMgYWxsIG9ic2VydmF0aW9ucyBmcm9tIHRoZSBmaXJzdCBkYXRhIHNldCBsaXN0ZWQgKHgpLiBUaGUgY2Vuc3VzIHRyYWN0IEZJUFMgKGFsc28gY2FsbGVkIGEgR0VPSUQpIGlzIGEgdW5pcXVlIGlkZW50aWZpZXIsIHdoaWNoIGlzIHRvIG91ciBhZHZhbnRhZ2UuIFdlJ2xsIHVzZSB0aGlzIHZhcmlhYmxlIHRvIGBtZXJnZSgpYCB0aGUgZGF0YSwgYnV0IHRoZXkgaGF2ZSBkaWZmZXJlbnQgbmFtZXM6IGBzY19zdmkkRklQU2AgYW5kIGBzY190cmFjdHMkR0VPSURgLiBXZSBuZWVkIHRvIGFjY291bnQgZm9yIHRoaXMuDQoNCmBgYHtyfQ0KDQojIEpvaW5zIHR3byBkYXRhIHNldHMgdG9nZXRoZXIsIGtlZXBpbmcgYWxsIHggb2JzZXJ2YXRpb25zDQpzdl90cmFjdHNfc2NvcmVzIDwtIG1lcmdlKHNjX3RyYWN0cywgc2Nfc3ZpLCBieS54PSJHRU9JRCIsIGJ5Lnk9IkZJUFMiLCBhbGwueD1UUlVFKQ0KDQpgYGANCg0KIyMjIyBPdmVyYWxsIFNWSSBTY29yZQ0KDQpXZSBoYXZlIG91ciBkYXRhIGFuZCBvdXIgYmFzZSBtYXAuIExldCdzIGNyZWF0ZSBvdXIgZmlyc3QgY2hvcm9wbGV0aCBtYXAgdXNpbmcgdGhlIG92ZXJhbGwgU1ZJIHNjb3JlIG9yIFJQTF9USEVNRVMuDQoNCmBgYHtyIG91dC53aWR0aCA9ICIxMDAlIn0NCg0KIyBDcmVhdGVzIHRoZSBtYXAgYXMgYW4gb2JqZWN0DQpvdmVyYWxsc2NvcmVzX21hcCA8LSBnZ3Bsb3Qoc3ZfdHJhY3RzX3Njb3JlcykgKw0KICBnZW9tX3NmKGFlcyhmaWxsID0gb3ZlcmFsbHF1YXJ0aWxlKSwgY29sb3IgPSAid2hpdGUiLCBsaW5ld2lkdGggPSAwLjIpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzKG9wdGlvbj0idmlyaWRpcyIsDQogICAgICAgICAgICAgICAgICAgICBuYW1lPSJTVkkgU2NvcmUiLA0KICAgICAgICAgICAgICAgICAgICAgYnJlYWtzPWMoMSwgNCksDQogICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiTG93ZXN0IiwgIkhpZ2hlc3QiKSkgKyANCiAgbGFicyh0aXRsZSA9ICJPdmVyYWxsIFNWSSBTY29yZXMgaW4gU3Bva2FuZSBDb3VudHkiKSArDQogIHRoZW1lX3ZvaWQoKSArIA0KICB0aGVtZSh0aXRsZT1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIpKQ0KDQojIFNob3dzIG9yICJwcmludHMiIHRoZSBtYXANCm92ZXJhbGxzY29yZXNfbWFwDQoNCmBgYA0KDQojIyMjIFRoZW1lcyBTVkkgU2NvcmVzDQoNCldlIGhhdmUgb3VyIGZpcnN0IG1hcCBhbmQgY2FuIHVzZSBpdCBhcyBhIHRlbXBsYXRlLiBXZSBqdXN0IHdhc2gsIHJpbnNlLCBhbmQgcmVwZWF0IGZvciB0aGUgdGhlbWVzIHNjb3Jlcy4gSG93ZXZlciwgdGhpcyB0aW1lLCB3ZSdsbCB1c2UgdGhlIHBhdGNod29yayBwYWNrYWdlIHRvIGRpc3BsYXkgY2hhcnRzIGluIHR3b3MuDQoNCmBgYHtyfQ0KDQojIENyZWF0ZXMgdGhlIG1hcHMgYXMgb2JqZWN0cw0KdGhlbWUxc2NvcmVzX21hcCA8LSBnZ3Bsb3Qoc3ZfdHJhY3RzX3Njb3JlcykgKw0KICBnZW9tX3NmKGFlcyhmaWxsID0gdGhlbWUxcXVhcnRpbGUpLCBjb2xvciA9ICJ3aGl0ZSIsIGxpbmV3aWR0aCA9IDAuMikgKw0KICBzY2FsZV9maWxsX3ZpcmlkaXMob3B0aW9uPSJ2aXJpZGlzIiwgZ3VpZGUgPSAibm9uZSIpICsgDQogIGxhYnMoc3VidGl0bGUgPSAiU29jaW9lY29ub21pYyBTdGF0dXMiKSArDQogIHRoZW1lX3ZvaWQoKSArIA0KICB0aGVtZSh0aXRsZT1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIpLA0KICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbih0ID0gMSwgICMgVG9wIG1hcmdpbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICByID0gMSwgICMgUmlnaHQgbWFyZ2luDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGIgPSAxLCAgIyBCb3R0b20gbWFyZ2luDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGwgPSAxKSkNCg0KdGhlbWUyc2NvcmVzX21hcCA8LSBnZ3Bsb3Qoc3ZfdHJhY3RzX3Njb3JlcykgKw0KICBnZW9tX3NmKGFlcyhmaWxsID0gdGhlbWUycXVhcnRpbGUpLCBjb2xvciA9ICJ3aGl0ZSIsIGxpbmV3aWR0aCA9IDAuMikgKw0KICBzY2FsZV9maWxsX3ZpcmlkaXMob3B0aW9uPSJ2aXJpZGlzIiwNCiAgICAgICAgICAgICAgICAgICAgIG5hbWU9IlNWSSBTY29yZSIsDQogICAgICAgICAgICAgICAgICAgICBicmVha3M9YygxLCA0KSwNCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJMb3dlc3QiLCAiSGlnaGVzdCIpKSArIA0KICBsYWJzKHN1YnRpdGxlID0gIkhvdXNlaG9sZCBDaGFyYWN0ZXJpc3RpY3MiKSArDQogIHRoZW1lX3ZvaWQoKSArIA0KICB0aGVtZSh0aXRsZT1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIpLA0KICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbih0ID0gMSwgICMgVG9wIG1hcmdpbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICByID0gMSwgICMgUmlnaHQgbWFyZ2luDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGIgPSAxLCAgIyBCb3R0b20gbWFyZ2luDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGwgPSAxKSkNCg0KdGhlbWUzc2NvcmVzX21hcCA8LSBnZ3Bsb3Qoc3ZfdHJhY3RzX3Njb3JlcykgKw0KICBnZW9tX3NmKGFlcyhmaWxsID0gdGhlbWUzcXVhcnRpbGUpLCBjb2xvciA9ICJ3aGl0ZSIsIGxpbmV3aWR0aCA9IDAuMikgKw0KICBzY2FsZV9maWxsX3ZpcmlkaXMob3B0aW9uPSJ2aXJpZGlzIiwgZ3VpZGUgPSAibm9uZSIpICsgDQogIGxhYnMoc3VidGl0bGUgPSAiUmFjZSAmIEV0aG5pY2l0eSBTdGF0dXMiKSArDQogIHRoZW1lX3ZvaWQoKSArIA0KICB0aGVtZSh0aXRsZT1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIpLA0KICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbih0ID0gMSwgICMgVG9wIG1hcmdpbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICByID0gMSwgICMgUmlnaHQgbWFyZ2luDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGIgPSAxLCAgIyBCb3R0b20gbWFyZ2luDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGwgPSAxKSkNCg0KdGhlbWU0c2NvcmVzX21hcCA8LSBnZ3Bsb3Qoc3ZfdHJhY3RzX3Njb3JlcykgKw0KICBnZW9tX3NmKGFlcyhmaWxsID0gdGhlbWU0cXVhcnRpbGUpLCBjb2xvciA9ICJ3aGl0ZSIsIGxpbmV3aWR0aCA9IDAuMikgKw0KICBzY2FsZV9maWxsX3ZpcmlkaXMob3B0aW9uPSJ2aXJpZGlzIiwNCiAgICAgICAgICAgICAgICAgICAgIG5hbWU9IlNWSSBTY29yZSIsDQogICAgICAgICAgICAgICAgICAgICBicmVha3M9YygxLCA0KSwNCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJMb3dlc3QiLCAiSGlnaGVzdCIpKSArIA0KICBsYWJzKHN1YnRpdGxlID0gIkhvdXNpbmcgVHlwZSAmIFRyYW5zcG9ydGF0aW9uIikgKw0KICB0aGVtZV92b2lkKCkgKyANCiAgdGhlbWUodGl0bGU9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiKSwNCiAgICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4odCA9IDEsICAjIFRvcCBtYXJnaW4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgciA9IDEsICAjIFJpZ2h0IG1hcmdpbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiID0gMSwgICMgQm90dG9tIG1hcmdpbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsID0gMSkpDQpgYGANCg0KYGBge3Igb3V0LndpZHRoID0gIjEwMCUifQ0KDQojIFNob3dzIG9yICJwcmludHMiIHRoZSBtYXBzDQp0aGVtZTFzY29yZXNfbWFwICsgdGhlbWUyc2NvcmVzX21hcA0KDQpgYGANCg0KDQpgYGB7ciBvdXQud2lkdGggPSAiMTAwJSJ9DQoNCiMgU2hvd3Mgb3IgInByaW50cyIgdGhlIG1hcHMNCnRoZW1lM3Njb3Jlc19tYXAgKyB0aGVtZTRzY29yZXNfbWFwDQoNCmBgYA0KDQojIyMgTWFraW5nIE1lYW5pbmcNCg0KU3RhdGljIGNob3JvcGxldGhzIGFyZSBncmVhdCB2aXN1YWxzIGZvciBwcmludGVkIG1hdGVyaWFscy4gSG93ZXZlciwgbWFueSBjZW5zdXMgdHJhY3RzIGxvY2F0ZWQgaW4gYW5kIGFyb3VuZCBkb3dudG93biBTcG9rYW5lIGFyZSB0b28gc21hbGwgZm9yIHVzIG1ha2Ugc2Vuc2UgZnJvbSBhcyBwcmFjdGl0aW9uZXJzLiBBbiBpbnRlcmFjdGl2ZSBtYXAgd291bGQgaW1wcm92ZSBzdGFmZiB1cHRha2Ugb2YgdGhlIGRhdGEgaW4gcGxhbm5pbmcuDQoNClZpc2l0IFt0aGlzIGRhc2hib2FyZF0oaHR0cHM6Ly9qc2xhbmRlcy5zaGlueWFwcHMuaW8vUEFGLTUxMy1EYXNoYm9hcmRGdWxsLUxhbmRlcy8pIHRvIHNlZSBhbiBleGFtcGxlIG9mIGEgcmVzcG9uc2l2ZSBtYXAgYnVpbHQgdXNpbmcgUiBhbmQgU2hpbnkuDQoNCiMjIFJlY2FwDQoNClIgY2FuIGJlIGluY3JlZGlibHkgdXNlZnVsIGZvciBwdWJsaWMgaGVhbHRoIHByYWN0aWNlLiBBbHRob3VnaCBpdCBtYXkgc2VlbSBpbnRpbWlkYXRpbmcsIHRoZSBjb21tdW5pdHkgb2YgUiBwcm9ncmFtbWVycyBpcyB3ZWxjb21pbmcgYW5kIGNvbW1pdHRlZCB0byBpbXByb3ZlbWVudC4gQmV0dGVyIHlldCwgaXQncyA8aT5mcmVlPC9pPiBhbmQgc28gaXMgbGVhcm5pbmcgUi4NCg0KPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCI+DQogIDxkaXYgY2xhc3M9InBhbmVsLWhlYWRpbmciPjxiPlIgJiBEYXRhQ2FtcDwvYj48L2Rpdj4NCiAgPGRpdiBjbGFzcz0icGFuZWwtYm9keSI+IElmIHlvdSBsaWtlIHN0cnVjdHVyZWQgbGVhcm5pbmcsIHRoZSBXYXNoaW5ndG9uIFN0YXRlIERlcGFydG1lbnQgb2YgSGVhbHRoIHBheXMgZm9yIGEgc3RhdGV3aWRlIERhdGFDYW1wIGFjY291bnQgYW5kIG9mZmVycyBpdCBmcmVlIG9mIGNoYXJnZSB0byBjZXJ0YWluIGxvY2FsIHB1YmxpYyBoZWFsdGggcHJvZ3JhbXMuIENvbnRhY3QgbWUgYXQgW2psYW5kZXNAc3JoZC5vcmddKGpsYW5kZXNAc2hyZC5vcmcpIHRvIHNlZSBpZiB0aGVyZSBhcmUgb3BlbiBzZWF0cy4gPC9kaXY+DQo8L2Rpdj4NCg0KIyMgUmVzb3VyY2VzDQoNCiogV2Vic2l0ZXMNCiAgKyBbRGF0YUNhbXBdKGh0dHBzOi8vYXBwLmRhdGFjYW1wLmNvbS8pDQogICsgW0Zyb20gRGF0YSB0byBWaXpdKGh0dHBzOi8vd3d3LmRhdGEtdG8tdml6LmNvbS8pDQogICsgW1RoZSBSIEdyYXBoIEdhbGxlcnldKGh0dHBzOi8vci1ncmFwaC1nYWxsZXJ5LmNvbS8pDQogICsgW1N0YWNrb3ZlcmZsb3cgUXVlc3Rpb25zXShodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucykNCiogT3BlbiBTb3VyY2UgQm9va3MNCiAgKyBbQW5hbHl6aW5nIFVTIENlbnN1cyBEYXRhOiBNZXRob2RzLCBNYXBzLCBhbmQgTW9kZWxzIGluIFJdKGh0dHBzOi8vd2Fsa2VyLWRhdGEuY29tL2NlbnN1cy1yL2luZGV4Lmh0bWwpDQogICsgW1IgTWFya2Rvd24gQ29va2Jvb2tdKGh0dHBzOi8vYm9va2Rvd24ub3JnL3lpaHVpL3JtYXJrZG93bi1jb29rYm9vay8pDQogICsgW3JzdHVkaW80ZWR1XShodHRwczovL3JzdHVkaW80ZWR1LmdpdGh1Yi5pby9yc3R1ZGlvNGVkdS1ib29rLykNCg0KPGJyPg0KPGJyPg0K