Collecting and Cleaning Survey Data
Before we jump into cleaning survey data, it’s helpful to get a sense
of what the survey actually looks like. Ideas of survey and study design
are a bit beyond the focus of this course, but you’re encouraged to
think about these concepts as you go through these materials. If you’re
attending a session live, please feel free to ask questions and offer
insights!
Our Research Question:
Our Survey
The survey we’re going to be working with was created using Google
Forms because it is an open platform that is freely accessible to anyone
with a computer. The survey was designed in such a way to use the main
question types offered by survey tools. This will allow us to see how
these different question types produce different types of data, and then
explore how to work with these different data types. Despite using
Google Forms, the actions we’ll perform in this workshop apply to any
survey tool that you might use.
So to start things off, take a couple minutes to go through the
survey: survey
link
Our Data
Now that we know what the survey / data collection looks like, let’s
take a look at the data. The dataset that we’ll be using contains mock
entries that resemble some general trends you might find in a real
survey of this kind.
Download the dataset
Let’s take a look at the dataset!
- Is it what you expected to see?
- Are there any fields that you think might be tricky to work
with?
- Can you imagine how the data might need to change in order to ask
questions of it?
Beginning Our Work
Now that we have our data, we can start getting to work!
The first thing we need to do is to create a project folder to keep
our files in one place. To keep everything consistent, follow these
steps:
- Go to your
Desktop folder
- Create a folder called
social_media_project
- Move the file you just downloaded, called
social-media-survey.csv to the
social_media_project folder
- It is best practice to save a copy of your original data and
not to touch it, to retain transparency and reproducibility.
Make a copy of
social-media-survey.csv and change the name
of the copied file to social-media-survey_ORIGINAL.csv
A quick note on folder and file naming
Much like naming objects in R, that was covered in the
the Introduction to R, when
naming both files and folders follow these
practices:
- Only use letters in the English alphabet, number 0-9, dashes -, and
underscores _
- Do not use spaces or special characters such as:
~!@#$%^&*()+=…
- Separate naming elements with dashes - and underscores _
R Projects & Working Directories
Setting a Working Directory
When working in a coding environment like RStudio, you need to let R
(or other coding environments) know what folder you want to be working
from so you can easily access your files. This concept is know as
setting a working directory. For more information on
file paths and directories, see File
and Directory Paths
There are two main ways of doing this in R:
- You can use the
setwd() function, by manually inserting
your file path in the brackets like this:
setwd("directory-name/secondary-directory/etc...")
- See section on File and Directory
Paths for more information on paths.
- Selecting the
Session tab in the toolbar, and selecting
Set Working Directory:

But here’s the problem…
Using setwd() can break your code when:
- Someone else tries to run it on their machine.
- You move your project folder.
- You’re running your code on a server or in cloud environments like
RStudio Cloud.
Since file paths are hardcoded and depend on your machine,
it’s not reproducible.
Create an R Project
An R Project is a feature in RStudio (and supported in base R too)
that provides a self-contained working environment. When you create an R
Project it creates a .Rproj file in a folder and that folder becomes the
root directory of your project. Every time you open the project (via the
.Rproj file), R automatically sets the working directory to that folder.
You can reference files relative to the project root — no need to
hardcode file paths.
This is super useful when you’re working on multiple analyses,
sharing code with collaborators, or version-controlling with Git.
It is a good practice for reproducibility.
To create an R Project, select File > New Project

Let’s create our first RProject. Let’s figure out what we should call
it!
Let’s Get Started!
Let’s get started by opening a new R script.
To create an R script file, select File > New File > R
Script

Packages and Libraries
Now that we’ve set our working directory, there’s one more thing to
cover before we jump into the data, which is the ideas of
packages and libraries in R.
When you first download R, it comes equipped with a number of
pre-installed functions, or capabilities, that you can start using
immediately. This is often called “Base R”. However, for certain tasks
and workflows, it can be beneficial to use more specialized tools, or
functions, to accomplish work and facilitate workflows more efficiently.
This is where packages and libraries come into play.
Packages: Packages are an extension of the
pre-built functions in R, and can be installed to bring in specific
functions to accomplish tasks, among many other things. There are
tons of R packages out there, but here is a list of
some of the most common/useful ones: Quick
list of useful R packages
Libraries: Once you have installed a package,
they are stored as libraries in R. You only have to install them once,
and anytime you want to use the package you can use the
library() function, which is described below.
Tidyverse
The Tidyverse is a very commonly used package for research and data
science activities, and instead of being a single package, it is a
collection of packages that are designed to work together and that focus
on the connections between activities in the data science workflow. Each
package follows the same syntax, which makes learning them easier, and
the website functions as a really good reference point if you’re
struggling with how to approach a specific task.

Let’s take a closer look! Tidyverse
Install Package
To install a package we use the function
install.packages().
When you install a package, you should do this in the R
console because you don’t need this saved in your script.
install.packages("tidyverse")
Load Libraries
Packages are stored in libraries. Once a package is installed, we
need to call the library with the function library().
It’s best practice to load libraries in your script so that others
can see what libraries need to be loaded to run the script.
library(tidyverse)
Note that the package name needs to be in quotations when installing
the package, but not when loading the library.
Because packages only need to be installed once, we can do this in
the R console as opposed to in the script.
Because libraries need to be loaded in each working session, we can
do this in the R script so that others can see what libraries we are
using and need to be loaded.
Reading Data

In order to start working with a dataset in R, we first need to
import, or “read in”, the data. To do this, we will be using the readr package in the
Tidyverse.
Read a csv file
Because our data is in .csv format, we’ll be using the
read_csv() fuction.
To import a csv file we can use the read_csv() function
and assign it to a new object we will call survey_data. We
create a new object to be able to call it in different functions later
on.
survey_data <- read_csv("social-media-survey.csv")
Exploring Data
Before we start manipulating the data, it’s good to get a sense of
some ways to quickly explore the data.
Looking at the Dataset
To look at a spreadsheet version of your data we can use the
View() function.
View(survey_data)
Listing Column Names
To ask for a list of all the column names in our dataset we can use
the names() function.
names(survey_data)
## [1] "Timestamp"
## [2] "Name"
## [3] "Email"
## [4] "Age"
## [5] "Gender"
## [6] "Year of Study"
## [7] "How many hours per day do you spend on social media?"
## [8] "Which social media platforms do you use at least once a week?"
## [9] "Social media makes me feel connected"
## [10] "Social media increases my stress"
## [11] "I find social media distracting from studies"
## [12] "Social media positively impacts my mood"
## [13] "Staying connected with friends/family"
## [14] "Entertainment/passing time"
## [15] "Academic or professional networking"
## [16] "Staying informed about news/events"
## [17] "Self-expression/creativity"
Head Function
The head function will display the top rows of the dataset. It will
include information about the default data type assigned to each
column.
head(survey_data)
## # A tibble: 6 × 17
## Timestamp Name Email Age Gender `Year of Study` How many hours per d…¹
## <chr> <chr> <chr> <dbl> <chr> <dbl> <chr>
## 1 2024-01-20 1:… Tulk… tulk… 24 Male 4 Less than 2 hours
## 2 2024-01-24 22… Lanf… lanf… 24 Female 4 2-4 hours
## 3 2024-04-30 10… Mat … mat.… 20 Male 2 Less than 2 hours
## 4 2024-06-06 15… Bifu… bifu… 23 Female 4 2-4 hours
## 5 2024-02-07 5:… Remu… remu… 21 Male 2 4-6 hours
## 6 2024-01-05 21… Moir… moir… 19 Male 1 4-6 hours
## # ℹ abbreviated name: ¹`How many hours per day do you spend on social media?`
## # ℹ 10 more variables:
## # `Which social media platforms do you use at least once a week?` <chr>,
## # `Social media makes me feel connected` <chr>,
## # `Social media increases my stress` <chr>,
## # `I find social media distracting from studies` <chr>,
## # `Social media positively impacts my mood` <chr>, …
Cleaning Data
When we talk about “cleaning data”, we’re talking about manipulating
the original data so that it’s easier to start exploring trends,
analyzing, and visualizing. As we go through this process, it can be
helpful to save different versions, or stages of the data, to help
promote a transparent and reproducible process. In this session, we’re
going to focus on some common cleaning techniques that are used on
survey data.
In the Introduction to R
session we discussed objects and
functions, and played with the idea of objects storing
information, and functions manipulating the object/data.
Now we’re going to start implementing pipes as a way
to connect objects to functions and
arguments.
Pipes
Pipes are used to chain steps of instructions or actions together,
and often involve writing over an object to give it a new value. We’ll
walk through some examples of how this works, and start to see how the
full syntax of R comes together.

Changing Column Names
You’ll notice that the column names are reflective of the questions
in the survey. While some of the shorter names will work, those that are
very long and have spaces in the names can be annoying to work with. The
first step in our cleaning will be to get all of the column names in a
way that will be easy to work with.
To change column names we can use the function rename().
The function rename() is part of the dplyr package that was
installed with tidyverse.
Type the following code to change the column name from “Year of
Study” to “year_of_study”
survey_data <- survey_data |>
rename("year_of_study" = "Year of Study")
Step-by-step explanation:
- This command first starts off with the
survey_data
object, which is our dataset.
- The assignment operator comes next, and will re-write the
information stored in
survey_data with all the information
that is to the right side of the operator.
- We then use the
survey_data object and the pipe
|> to tell R that we want to take the data that is
stored in survey_data, and then do something to it (which
is what comes after the pipe).
- The
rename function is used to rename columns, and is
always followed by brackets. Inside those brackets, we’ll put the new
column name that we want in quotation marks "", followed by
an equal sign =, followed by the existing column name in
quotation marks "".
- We then run the command and hope it works!
Your Turn!
First, use the functionnames() to display the column
names.
names(survey_data)
Now, see if you can change the
How many hours per day do you spend on social media? column
name to hours-per-day
survey_data <- survey_data |>
rename("hours_per_day" = "How many hours per day do you spend on social media?")
Next, try to change the following 3 column names:
- Change
Which social media platforms do you use at least once a week?
to platforms
- Change
Social media makes me feel connected to
feel_connected
- Change
Social media increases my stress to
feel_increase_stress
Hint: It can be tedious to do these changes one by
one, but by using commas , you can rename column names with
a single code chunk.
survey_data <- survey_data |>
rename("platforms" = "Which social media platforms do you use at least once a week?",
"feel_connected" = "Social media makes me feel connected",
"feel_increase_stress" = "Social media increases my stress")
Now, let’s change the rest of the column names copy the following
code. (If you feel you’re starting to understand how this works, you can
show the code below and cope + paste it into your script,
or if you want some more practice, feel free to do it yourself!
survey_data <- survey_data |>
rename( "feel_distracted" = "I find social media distracting from studies",
"feel_improved_mood" = "Social media positively impacts my mood",
"usage_stay_in_touch" = "Staying connected with friends/family",
"usage_entertainment" = "Entertainment/passing time",
"usage_networking" = "Academic or professional networking",
"usage_news" = "Staying informed about news/events",
"usage_expression" = "Self-expression/creativity",
"timestamp" = "Timestamp",
"name" = "Name",
"email" = "Email",
"age" = "Age",
"gender" = "Gender")
Personal Idenfiers, ID Codes, and Data Versioning
You probably noticed that in this survey we collected names and email
addresses. This can be necessary for several reasons, but it also poses
ethical issues with respect to who is able to see this information. It
is common practice to remove personal identifiers from survey data, but
you may also wish to create a code for each entry should you ever need
to connect information back to the respondent.
Let’s try this is a few steps:
Add an ID column
The mutate() function, that is part of the dplyr package, is
useful when you want to create new columns that are functions of
existing variables.
While not technically the function of an existing variable, we can
use mutuate with the row_number() function to
create a new column that will contain the number of each row, thus given
entry a unique ID number.
survey_data <- survey_data |>
mutate(ID = row_number())
You can see that the grammar works in the same way as the
rename function, which is one of the strengths of using the
Tidyverse.
- The mutate function is followed by brackets, and the first value
that is entered is what you want the new column to be called.
- After the
= sign, insert what is to go in the rows of
the new column.
- In this case,
row_number() is adding the number of the
corresponding row to the column.
We’ll play with more uses of mutate in just a little
bit!
Move the ID column to the left-most position of the data
Having an ID column as the left-most, or first, column in your
dataset makes things generally easier to keep track of.
The relocate() function, which is also part of the
dplyr package, which does just what its name implies:
it relocates columns in a dataset.
The default of relocate is to put the specified column
in the first position, so we don’t need to specify location for this
task.
survey_data <- survey_data |>
relocate(ID)
Every time you make a change to your data, you can use the
View(survey_data) function to check what was done.
Before we go any further, let’s save another copy of this data. This
will allow the data holder to have a copy of the data that has both the
personal identifiers and the ID codes. We won’t be analyzing this
dataset, but it will be necessary should you need to reconnect with
respondents.
Saving a dataset
Much like we did with reading .csv data into R, there is
a similar command to save, or “write” .csv data back to
your computer called write_csv(). The syntax is as
follows:
write_csv(data-object-name, file="file-path/datafile-name.csv")
If you use the same file name as the one you are working on, it will
change that file based on what you’ve done. However, we don’t
want to touch our original data, so we’re going to make a new
file to indicate that it has clean columns, ID codes, and personal
identifiers.
write_csv(survey_data, "survey-data_clean-cols_IDs.csv")
Back to Cleaning!
Now that we’ve saved that version of the data, let’s now remove the
email and name columns to de-identify the
dataset, and also remove some unnecessary columns.
Removing Columns
There are a number of ways to remove columns in R, we’ll focus on the
the select function from the dplyr package in
Tidyverse.
This follows the same syntax that we’ve been using, and after the
select function, you insert a dash -, or minus
symbol, plus the name of the column you want to remove.
Let’s start be removing the timestamp column by using
its column name.
survey_data <- survey_data |>
select(-timestamp)
You can take a look at the dataset and now see that the
timestamp column is now gone.
Let’s now remove the identifiers name and
email.
See if you can remove the name and email
columns, as we want to get rid of the identifying variables.
Hint: To do this is a single command, see if you can figure out how
to use the c() function that was introduced in the Introduction to R session
survey_data <- survey_data |>
select(-c(name, email))
Save Another Version of the Data
Now that we have a dataset that has cleaned columns, no identifiers,
and no unnecessary columns, let’s save a copy of this should we ever
need to go back to the beginning.
write_csv(survey_data, "survey-data_clean-cols_no-ID.csv")
Cleaning Values
Now that we’ve cleaned up the variables/columns, let’s take a look at
our dataset and see what values might need some work.
View(survey_data)
Cleaning Survey Values
Now that we’ve cleaned up our headers, it’s time to start looking at
the values to see if we’ll be easily able to analyze them, or if they
need cleaning too.
If you take a look at the platforms column, you’ll see
that the values are pretty messy, and can include any combination of up
to 6 options. This is very hard to work with, so we’ll need to figure
out the best way to format things.
Wide Data, Long Data, and the Tidy Data Principles
When considering these types of messy columns, there are two
different strategies we can take to clean them up:
- Make the data long, or tidy, which aims to reduce
columns but creates more rows.
- Make the data wide, which creates more columns and
creates a wider spreadsheet.
In the next session of this series, Making Sense of Survey Data,
we will be looking at the pros and cons of wide vs long data, but in
this session we will focus on the techniques to play with the shape of
our data.
Making Data Long or “Tidy”
In R, and specifically the Tidyverse, the Tidy
Data Principles specify qualities of what is considered “tidy data”,
with data that doesn’t meet all criteria being “messy data”. They
provide a standard way to organize data to “facilitate initial
exploration and analysis of the data, and to simplify the development of
data analysis tools that work well together” (source).
Tidy Data Principles:
- Each variable is a column.
- Each observation is a row.
- Each value is a cell.
Here is an example of what would be considered a messy dataset:

While structuring data in this way is much easier for a human to scan
and for summary tables, it’s trickier for a coding language to parse and
work with. The various packages of the Tidyverse are specifically geared
towards working with tidy data, and making your data tidy will make
faceting, grouping, modelling, and visualizing much easier.
Here’s an example of what a tidy version of this data would look
like:

As you’ll notice, the repeating values in the Name
column seems clunky and weird to scan. But a way to think about think
about why this might be useful would be if instead of 3 quizs, there
were 50. Having a unique column for each would be tedious in its own
way, and this is just a single variable. There could be several sets of
wide spanning columns to capture what could be captured in a single
variable. The concept of tidy data focuses on minimizing the amount of
columns in favour of fewer columns with rich amounts of
observations.
Making a Dataset Tidy
The tidyr package in the
Tidyverse specializes in making data tidy.
The seperate_longer_delim() function specializes in
dealing with the messy values in our platforms column.
The trimsw function is useful to add with the
sepearate_longer_delim() function, because it removes all
the white space surrounding on either side of a value, avoiding any
complications this could bring up.
Let’s give this a try!
survey_data_long <- survey_data |>
separate_longer_delim(cols = platforms, delim = ",") |>
mutate(platforms = trimws(platforms))
Step-by-step explanation
- We start off by creating a new r object called
survey_data_long, which is going to take on all the
information that is passed to it from the right side of the assignment
operator <-.
- The
survey_data object represents our dataset that we
want to pass through the pipe |> to manipulate it.
- The
sepearate_longer_delim function is applied to the
platforms column to create a new row for each of the values
in the cell, and because the values separated by commas, the
delim = "," function tells R to separate each new row after
a comma.
- The data object with the separate rows is then piped into the next
function, which uses the
mutate function to tell R that we
want to modify the newly updated platforms values, and the
trimsw then removes any whitespace on either side of the
values.
- Et voila!
If we take another look at the dataset, you’ll see that the
platforms variable now has single observations in each
cell.
More Tidying
In addition to the platforms variable, the survey
contained two additional multiple-choice questions:
“Please indicate how much you agree or disagree with the
following statements about social media and your mental
health:”
“Rank the following reasons for using social media in order of
importance to you (1 = most important, 5 = least important):”
You’ll notice that each of these questions create create 4 and 5
columns, respectively, to capture the responses. This isn’t necessarily
a bad thing, but in the spirit of making our data tidy, let’s see try to
reduce the amount of variables to represent these values.
Take a look at the dataset, focusing on the variables that begin with
feel- and usage-, and think about how you
might make these variables tidy.
These variables are a bit trickier to conceptualize than the
platforms variable, but R has a function that is designed to handle
things like this, and will hopefully make sense when you see it!
Here’s the code to do this:
survey_data_longer <- survey_data_long |>
pivot_longer(
cols = starts_with("feel_"),
names_to = "feel_question",
values_to = "feel_response"
)
Step-by-step explanation:
- We start by writing a new r object called
survey_data_longer, that will hold everything to the left
of the assignment operator |>.
- The
survey_data_long object represents our dataset that
we want to pass through the pipe |> to manipulate
it.
- The
pivot_longer() function reshapes the data from wide
to long. In this case we had several variables that started with
feel-, and this function will gather them into two columns:
one for the question name and one for the response value.
- The
cols = starts_with("feel-") function tells
pivot_longer which columns to gather. (You can see why
variable naming can help with data cleaning!)
names_to = "feel_question" names of the new column that
will hold the original column names (ie. the question
identifiers. The new column will be called
feel_question.
values_to “feel_response” names the new column that
will hold the values (answers) that used to sit in the
feel- columns. The new column will be called
feel_response.
- Close the bracket, and take a look to see what the data looks
like.
Your Turn!
Now that you’ve seen how the pivot_long() function
works, see if you can create a new object called
survey_data_tidy, that lenghthen the usage-
columns just as we did with the feel- columns.
Hint: The syntax is exactly the same as the example above, you just
need to change the values in quotations "".
survey_data_tidy <- survey_data_longer |>
pivot_longer(
cols = starts_with("usage_"),
names_to = "usage_question",
values_to = "usage_response"
)
Take a look at the data:
View(survey_data_tidy)
It looks pretty weird! As mentioned, tidy data is very hard to scan
for a human, but really easy for R to scan. You might notice that
there’s over 26,000 rows, which may seem overwhelming and unnecessary.
The Tidy Data Principles are very much geared towards using R, and there
are times when making your data completely tidy might not suite your
purpose. However, the purpose of the exercise was to get you to think
about how you might want or need to structure your data, and you now
have code that you can easily adapt to play with your surveys.
Save a copy of the data
Now that we’ve fully tidied our dataset, save a copy of it:
write_csv(survey_data_tidy, "survey_data_tidy.csv")
Making data wide
As mentioned, there are pros and cons to making data wide and long.
The benefit of creating a wider structure is that it easier for human
eyes to scan and creating basic summary tables.
If we revisit the R object survey_data, which was saved
as the survey-data_clean-cols_no-ID.csv file, we can step
back to a stage in which the platforms variable was still
quite messy.
View(survey_data)
Instead of creating a new row for each of the platforms via the Tidy
Data Principles, we can make the data wider and create a new column for
each of the platforms.
Here’s how to do this:
survey_data_wide <- survey_data |>
mutate(platforms = strsplit(platforms, ",")) |>
unnest_longer(platforms) |>
mutate(platforms = trimws(platforms), present = 1) |>
pivot_wider(
names_from = platforms,
values_from = present,
values_fill = 0
)
Step-by-step explanation:
- We start by writing a new r object called
survey_data_wide, that will hold everything to the left of
the assignment operator |>.
- The
survey_data object represents our dataset that we
want to pass through the pipe |> to manipulate it.
- The
mutate function is used to modify a column, which
is applied to the strsplit(platforms, ",") function, to
tell it to split the comma-separated strings in the
platforms column into lists of individual platform
names.
- We then pipe
|> this into the
unnest_longer(platforms) function to expand each element
into its own row (which is like making the data longer). At this point,
new rows only exists for those that selected a platform.
- This is then piped
|> into
mutate(platforms = trimws(platforms) which continues to
manipulate the platforms column, and much like we did when
making this variable long, the trimsw removes white space
surrounding the values.
- The
present = 1 function creates a new column called
present that applies a value of 1 for every row. This is a
temporary column to help facilitate the next step.
- Using another pipe
|>, this information goes into
the pivot_wider function, that works with a very similar
syntax as pivot_longer that we used earlier, but instead of
making the data longer, it initiates data widening.
names_from = platforms assigns new columns to the
unique platform names.
values_from = present assigns values in the new columns
to come from the present column, which is
1.
- Finally, with
values_fill = 0, if a platform wasn’t
present for a survey entry, that column will get the value of
0.
This will end up with a wide dataset where each row is a survey
entry, each platform is a column, and the value 1 means a
platform was listed, and 0 means a platform was not
listed.
Save a copy of the data
Let’s save a copy of this dataset, and we’ll be taking a look at it
in the next section.
write_csv(survey_data_wide, "survey_data_wide.csv")
Save your script
Before we wrap up, we want to save our script. You can do this by
clicking file > Save As.... Because we set up an
RProject, R should automatically choose the correct directory to save
your script.
Let’s save the script as survey_cleaning_script.R
File Management
With just a few steps of data cleaning, we now have 6 data files in
our folder:
social-media-survey_ORIGINAL.csv
social-media-survey.csv
survey_data_tidy.csv
survey_data_wide.csv
survey_data.Rproj
survey_cleaning_script.R
survey-data_clean-cols_IDs.csv
survey-data_clean-cols_no-ID.csv
These names aren’t necessarily bad, but you can see that there are
some inconsistencies with the naming prefix
social-media-survey vs survey-data, and some
of the descriptors, clean-cols_IDs and
clean-cols_no-ID might not be as evident as we might
like.
It is always recommended to document and describe your files and
naming convention in a README file, which is described in details in the
Documentation session. You can
also refer to the Organizing
Files and Folders session for inspiration in how you might go about
renaming and structuring these files.
Finish
You have now seen some of the foundational functions to clean survey
data, and the various types of data that a survey might create. The goal
of this session is to give you a sense of how to approach your own
survey data, and to be comfortable enough with these code chunks that
you can switch out the data/variables for your own surveys, and work
through them in quick and reproducible ways!
LS0tCnRpdGxlOiAiQ29sbGVjdGluZyBhbmQgQ2xlYW5pbmcgU3VydmV5IERhdGEiCnBhZ2V0aXRsZTogIkNvbGxlY3RpbmcgYW5kIENsZWFuaW5nIFN1cnZleSBEYXRhIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZm9sZGluZzogc2hvdyAjIGFsbG93cyB0b2dnbGluZyBvZiBzaG93aW5nIGFuZCBoaWRpbmcgY29kZS4gUmVtb3ZlIGlmIG5vdCB1c2luZyBjb2RlLgogICAgY29kZV9kb3dubG9hZDogdHJ1ZSAjIGFsbG93cyB0aGUgdXNlciB0byBkb3dubG9hZCB0aGUgc291cmNlIC5SbWQgZmlsZS4gUmVtb3ZlIGlmIG5vdCB1c2luZyBjb2RlLgogICAgaW5jbHVkZXM6CiAgICAgIGFmdGVyX2JvZHk6IGZvb3Rlci5odG1sICMgaW5jbHVkZSBhIGN1c3RvbSBmb290ZXIuCiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZ3MgPSBGQUxTRSkKYGBgCgojIyBDb2xsZWN0aW5nIGFuZCBDbGVhbmluZyBTdXJ2ZXkgRGF0YQoKQmVmb3JlIHdlIGp1bXAgaW50byBjbGVhbmluZyBzdXJ2ZXkgZGF0YSwgaXQncyBoZWxwZnVsIHRvIGdldCBhIHNlbnNlIG9mIHdoYXQgdGhlIHN1cnZleSBhY3R1YWxseSBsb29rcyBsaWtlLiBJZGVhcyBvZiBzdXJ2ZXkgYW5kIHN0dWR5IGRlc2lnbiBhcmUgYSBiaXQgYmV5b25kIHRoZSBmb2N1cyBvZiB0aGlzIGNvdXJzZSwgYnV0IHlvdSdyZSBlbmNvdXJhZ2VkIHRvIHRoaW5rIGFib3V0IHRoZXNlIGNvbmNlcHRzIGFzIHlvdSBnbyB0aHJvdWdoIHRoZXNlIG1hdGVyaWFscy4gSWYgeW91J3JlIGF0dGVuZGluZyBhIHNlc3Npb24gbGl2ZSwgcGxlYXNlIGZlZWwgZnJlZSB0byBhc2sgcXVlc3Rpb25zIGFuZCBvZmZlciBpbnNpZ2h0cyEKCiMjIyBPdXIgUmVzZWFyY2ggUXVlc3Rpb246IAojIyMgKipIb3cgZG9lcyBzb2NpYWwgbWVkaWEgdXNhZ2UgaW5mbHVlbmNlIHRoZSBtZW50YWwgaGVhbHRoIG9mIHVuaXZlcnNpdHkgc3R1ZGVudHM/KioKClRoZXJlIGNvdWxkIGJlIGEgbnVtYmVyIG9mIHdheXMgdG8gYWRkcmVzcyB0aGlzIHF1ZXN0aW9uLCBidXQgZm9yIHRoZSBwdXJwb3NlIG9mIHRoaXMgY291cnNlIHdlJ3JlIGdvaW5nIHRvIGZvY3VzIG9uIGEgZmFpcmx5IHNob3J0IHN1cnZleSBhcyBhIHdheSB0byBnZXQgYSBzZW5zZSBtYW5hZ2luZyB0aGlzIHR5cGUgb2YgZGF0YS4gIAoKIyMjIE91ciBTdXJ2ZXkKClRoZSBzdXJ2ZXkgd2UncmUgZ29pbmcgdG8gYmUgd29ya2luZyB3aXRoIHdhcyBjcmVhdGVkIHVzaW5nIEdvb2dsZSBGb3JtcyBiZWNhdXNlIGl0IGlzIGFuIG9wZW4gcGxhdGZvcm0gdGhhdCBpcyBmcmVlbHkgYWNjZXNzaWJsZSB0byBhbnlvbmUgd2l0aCBhIGNvbXB1dGVyLiAgVGhlIHN1cnZleSB3YXMgZGVzaWduZWQgaW4gc3VjaCBhIHdheSB0byB1c2UgdGhlIG1haW4gcXVlc3Rpb24gdHlwZXMgb2ZmZXJlZCBieSBzdXJ2ZXkgdG9vbHMuICBUaGlzIHdpbGwgYWxsb3cgdXMgdG8gc2VlIGhvdyB0aGVzZSBkaWZmZXJlbnQgcXVlc3Rpb24gdHlwZXMgcHJvZHVjZSBkaWZmZXJlbnQgdHlwZXMgb2YgZGF0YSwgYW5kIHRoZW4gZXhwbG9yZSBob3cgdG8gd29yayB3aXRoIHRoZXNlIGRpZmZlcmVudCBkYXRhIHR5cGVzLiAgRGVzcGl0ZSB1c2luZyBHb29nbGUgRm9ybXMsIHRoZSBhY3Rpb25zIHdlJ2xsIHBlcmZvcm0gaW4gdGhpcyB3b3Jrc2hvcCBhcHBseSB0byBhbnkgc3VydmV5IHRvb2wgdGhhdCB5b3UgbWlnaHQgdXNlLgoKU28gdG8gc3RhcnQgdGhpbmdzIG9mZiwgdGFrZSBhIGNvdXBsZSBtaW51dGVzIHRvIGdvIHRocm91Z2ggdGhlIHN1cnZleTogW3N1cnZleSBsaW5rXShodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9mb3Jtcy9kL2UvMUZBSXBRTFNjWkVwN01QYUN6Nkc5VGdpaVotcTRMakFnZk1Gc0FBYS0zUmhOWnFIRlVmclJFYXcvdmlld2Zvcm0/dXNwPWhlYWRlcikKCiMjIyBPdXIgRGF0YQoKTm93IHRoYXQgd2Uga25vdyB3aGF0IHRoZSBzdXJ2ZXkgLyBkYXRhIGNvbGxlY3Rpb24gbG9va3MgbGlrZSwgbGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlIGRhdGEuICBUaGUgZGF0YXNldCB0aGF0IHdlJ2xsIGJlIHVzaW5nIGNvbnRhaW5zIG1vY2sgZW50cmllcyB0aGF0IHJlc2VtYmxlIHNvbWUgZ2VuZXJhbCB0cmVuZHMgeW91IG1pZ2h0IGZpbmQgaW4gYSByZWFsIHN1cnZleSBvZiB0aGlzIGtpbmQuCgo8YSBocmVmPSJodHRwczovL25pY2tyb2NobGluLmdpdGh1Yi5pby9yZG0tanVtcHN0YXJ0Mi9kYXRhL3N1cnZleS1jbGVhbmluZy13b3Jrc2hvcC9zb2NpYWwtbWVkaWEtc3VydmV5LmNzdiIgZG93bmxvYWQ+CiAgRG93bmxvYWQgdGhlIGRhdGFzZXQKPC9hPgoKOjo6cXVlc3Rpb24KCkxldCdzIHRha2UgYSBsb29rIGF0IHRoZSBkYXRhc2V0IQoKKiBJcyBpdCB3aGF0IHlvdSBleHBlY3RlZCB0byBzZWU/CiogQXJlIHRoZXJlIGFueSBmaWVsZHMgdGhhdCB5b3UgdGhpbmsgbWlnaHQgYmUgdHJpY2t5IHRvIHdvcmsgd2l0aD8KKiBDYW4geW91IGltYWdpbmUgaG93IHRoZSBkYXRhIG1pZ2h0IG5lZWQgdG8gY2hhbmdlIGluIG9yZGVyIHRvIGFzayBxdWVzdGlvbnMgb2YgaXQ/Cgo6OjoKCgojIyMgQmVnaW5uaW5nIE91ciBXb3JrCgpOb3cgdGhhdCB3ZSBoYXZlIG91ciBkYXRhLCB3ZSBjYW4gc3RhcnQgZ2V0dGluZyB0byB3b3JrISAgCgo6OjpxdWVzdGlvbgoKVGhlIGZpcnN0IHRoaW5nIHdlIG5lZWQgdG8gZG8gaXMgdG8gY3JlYXRlIGEgcHJvamVjdCBmb2xkZXIgdG8ga2VlcCBvdXIgZmlsZXMgaW4gb25lIHBsYWNlLiBUbyBrZWVwIGV2ZXJ5dGhpbmcgY29uc2lzdGVudCwgZm9sbG93IHRoZXNlIHN0ZXBzOgoKMSkgR28gdG8geW91ciBgRGVza3RvcGAgZm9sZGVyCjIpIENyZWF0ZSBhIGZvbGRlciBjYWxsZWQgYHNvY2lhbF9tZWRpYV9wcm9qZWN0YAozKSBNb3ZlIHRoZSBmaWxlIHlvdSBqdXN0IGRvd25sb2FkZWQsIGNhbGxlZCBgc29jaWFsLW1lZGlhLXN1cnZleS5jc3ZgIHRvIHRoZSBgc29jaWFsX21lZGlhX3Byb2plY3RgIGZvbGRlcgo0KSBJdCBpcyBiZXN0IHByYWN0aWNlIHRvICoqc2F2ZSBhIGNvcHkgb2YgeW91ciBvcmlnaW5hbCBkYXRhIGFuZCBub3QgdG8gdG91Y2ggaXQqKiwgdG8gcmV0YWluIHRyYW5zcGFyZW5jeSBhbmQgcmVwcm9kdWNpYmlsaXR5LiBNYWtlIGEgY29weSBvZiBgc29jaWFsLW1lZGlhLXN1cnZleS5jc3ZgIGFuZCBjaGFuZ2UgdGhlIG5hbWUgb2YgdGhlIGNvcGllZCBmaWxlIHRvIGBzb2NpYWwtbWVkaWEtc3VydmV5X09SSUdJTkFMLmNzdmAKCjo6OgoKOjo6bm90ZQoKKipBIHF1aWNrIG5vdGUgb24gZm9sZGVyIGFuZCBmaWxlIG5hbWluZyoqCgpNdWNoIGxpa2UgbmFtaW5nIG9iamVjdHMgaW4gUiwgdGhhdCB3YXMgY292ZXJlZCBpbiB0aGUgPGEgaHJlZj0iQmxvY2s4LTFfU1VSX0ludHJvLXRvLVIuaHRtbCI+dGhlIEludHJvZHVjdGlvbiB0byBSPC9hPiwgd2hlbiBuYW1pbmcgYm90aCAqKmZpbGVzIGFuZCBmb2xkZXJzKiogZm9sbG93IHRoZXNlIHByYWN0aWNlczoKCiogT25seSB1c2UgbGV0dGVycyBpbiB0aGUgRW5nbGlzaCBhbHBoYWJldCwgbnVtYmVyIDAtOSwgZGFzaGVzIC0sIGFuZCB1bmRlcnNjb3JlcyBfCiogRG8gbm90IHVzZSBzcGFjZXMgb3Igc3BlY2lhbCBjaGFyYWN0ZXJzIHN1Y2ggYXM6IH4hQCMkJV4mKigpKz3igKYKKiBTZXBhcmF0ZSBuYW1pbmcgZWxlbWVudHMgd2l0aCBkYXNoZXMgLSBhbmQgdW5kZXJzY29yZXMgXwoKOjo6CgojIyBSIFByb2plY3RzICYgV29ya2luZyBEaXJlY3RvcmllcwoKIyMjIFNldHRpbmcgYSBXb3JraW5nIERpcmVjdG9yeQoKV2hlbiB3b3JraW5nIGluIGEgY29kaW5nIGVudmlyb25tZW50IGxpa2UgUlN0dWRpbywgeW91IG5lZWQgdG8gbGV0IFIgKG9yIG90aGVyIGNvZGluZyBlbnZpcm9ubWVudHMpIGtub3cgd2hhdCBmb2xkZXIgeW91IHdhbnQgdG8gYmUgd29ya2luZyBmcm9tIHNvIHlvdSBjYW4gZWFzaWx5IGFjY2VzcyB5b3VyIGZpbGVzLiAgVGhpcyBjb25jZXB0IGlzIGtub3cgYXMgKipzZXR0aW5nIGEgd29ya2luZyBkaXJlY3RvcnkqKi4gIEZvciBtb3JlIGluZm9ybWF0aW9uIG9uIGZpbGUgcGF0aHMgYW5kIGRpcmVjdG9yaWVzLCBzZWUgPGEgaHJlZj0iQmxvY2s0LTFfRmlsZS1QYXRocy5odG1sIj5GaWxlIGFuZCBEaXJlY3RvcnkgUGF0aHM8L2E+CgpUaGVyZSBhcmUgdHdvIG1haW4gd2F5cyBvZiBkb2luZyB0aGlzIGluIFI6CgoxKSBZb3UgY2FuIHVzZSB0aGUgYHNldHdkKClgIGZ1bmN0aW9uLCBieSBtYW51YWxseSBpbnNlcnRpbmcgeW91ciBmaWxlIHBhdGggaW4gdGhlIGJyYWNrZXRzIGxpa2UgdGhpczoKICAqIGBzZXR3ZCgiZGlyZWN0b3J5LW5hbWUvc2Vjb25kYXJ5LWRpcmVjdG9yeS9ldGMuLi4iKWAgCiAgKiBTZWUgc2VjdGlvbiBvbiBbRmlsZSBhbmQgRGlyZWN0b3J5IFBhdGhzXShCbG9jazQtMV9GaWxlLVBhdGhzLmh0bWwpIGZvciBtb3JlIGluZm9ybWF0aW9uIG9uIHBhdGhzLgogIAoyKSBTZWxlY3RpbmcgdGhlIGBTZXNzaW9uYCB0YWIgaW4gdGhlIHRvb2xiYXIsIGFuZCBzZWxlY3RpbmcgYFNldCBXb3JraW5nIERpcmVjdG9yeWA6CgohW10oaW1hZ2VzL0Jsb2NrOC0yX3NldC13ZC5naWYpCgpCdXQgaGVyZeKAmXMgdGhlIHByb2JsZW0uLi4KClVzaW5nIGBzZXR3ZCgpYCBjYW4gYnJlYWsgeW91ciBjb2RlIHdoZW46CgogLSBTb21lb25lIGVsc2UgdHJpZXMgdG8gcnVuIGl0IG9uIHRoZWlyIG1hY2hpbmUuCiAtIFlvdSBtb3ZlIHlvdXIgcHJvamVjdCBmb2xkZXIuCiAtIFlvdSdyZSBydW5uaW5nIHlvdXIgY29kZSBvbiBhIHNlcnZlciBvciBpbiBjbG91ZCBlbnZpcm9ubWVudHMgbGlrZSBSU3R1ZGlvIENsb3VkLgoKU2luY2UgZmlsZSBwYXRocyBhcmUgaGFyZGNvZGVkIGFuZCBkZXBlbmQgb24geW91ciBtYWNoaW5lLCAqKml0J3Mgbm90IHJlcHJvZHVjaWJsZSoqLgoKIyMjIENyZWF0ZSBhbiBSIFByb2plY3QKCkFuIFIgUHJvamVjdCBpcyBhIGZlYXR1cmUgaW4gUlN0dWRpbyAoYW5kIHN1cHBvcnRlZCBpbiBiYXNlIFIgdG9vKSB0aGF0IHByb3ZpZGVzIGEgc2VsZi1jb250YWluZWQgd29ya2luZyBlbnZpcm9ubWVudC4gV2hlbiB5b3UgY3JlYXRlIGFuIFIgUHJvamVjdCBpdCBjcmVhdGVzIGEgLlJwcm9qIGZpbGUgaW4gYSBmb2xkZXIgYW5kIHRoYXQgZm9sZGVyIGJlY29tZXMgdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHlvdXIgcHJvamVjdC4gRXZlcnkgdGltZSB5b3Ugb3BlbiB0aGUgcHJvamVjdCAodmlhIHRoZSAuUnByb2ogZmlsZSksIFIgYXV0b21hdGljYWxseSBzZXRzIHRoZSB3b3JraW5nIGRpcmVjdG9yeSB0byB0aGF0IGZvbGRlci4gWW91IGNhbiByZWZlcmVuY2UgZmlsZXMgcmVsYXRpdmUgdG8gdGhlIHByb2plY3Qgcm9vdCDigJQgbm8gbmVlZCB0byBoYXJkY29kZSBmaWxlIHBhdGhzLgoKVGhpcyBpcyBzdXBlciB1c2VmdWwgd2hlbiB5b3UncmUgd29ya2luZyBvbiBtdWx0aXBsZSBhbmFseXNlcywgc2hhcmluZyBjb2RlIHdpdGggY29sbGFib3JhdG9ycywgb3IgdmVyc2lvbi1jb250cm9sbGluZyB3aXRoIEdpdC4gKipJdCBpcyBhIGdvb2QgcHJhY3RpY2UgZm9yIHJlcHJvZHVjaWJpbGl0eS4qKgoKVG8gY3JlYXRlIGFuIFIgUHJvamVjdCwgc2VsZWN0IEZpbGUgPiBOZXcgUHJvamVjdAoKIVtdKGltYWdlcy9kYXkyX0NyZWF0ZVByb2plY3QuZ2lmKQoKCjo6OnF1ZXN0aW9uCkxldCdzIGNyZWF0ZSBvdXIgZmlyc3QgUlByb2plY3QuIExldCdzIGZpZ3VyZSBvdXQgd2hhdCB3ZSBzaG91bGQgY2FsbCBpdCEKOjo6CgojIyBMZXQncyBHZXQgU3RhcnRlZCEKCkxldCdzIGdldCBzdGFydGVkIGJ5IG9wZW5pbmcgYSBuZXcgUiBzY3JpcHQuCgpUbyBjcmVhdGUgYW4gUiBzY3JpcHQgZmlsZSwgc2VsZWN0IEZpbGUgPiBOZXcgRmlsZSA+IFIgU2NyaXB0CgohW10oaW1hZ2VzL2Jsb2NrM19jcmVhdGUtci1zY3JpcHQuZ2lmKQoKCiMjIyBQYWNrYWdlcyBhbmQgTGlicmFyaWVzCgpOb3cgdGhhdCB3ZSd2ZSBzZXQgb3VyIHdvcmtpbmcgZGlyZWN0b3J5LCB0aGVyZSdzIG9uZSBtb3JlIHRoaW5nIHRvIGNvdmVyIGJlZm9yZSB3ZSBqdW1wIGludG8gdGhlIGRhdGEsIHdoaWNoIGlzIHRoZSBpZGVhcyBvZiAqKnBhY2thZ2VzIGFuZCBsaWJyYXJpZXMqKiBpbiBSLgoKV2hlbiB5b3UgZmlyc3QgZG93bmxvYWQgUiwgaXQgY29tZXMgZXF1aXBwZWQgd2l0aCBhIG51bWJlciBvZiBwcmUtaW5zdGFsbGVkIGZ1bmN0aW9ucywgb3IgY2FwYWJpbGl0aWVzLCB0aGF0IHlvdSBjYW4gc3RhcnQgdXNpbmcgaW1tZWRpYXRlbHkuICBUaGlzIGlzIG9mdGVuIGNhbGxlZCAiQmFzZSBSIi4gIEhvd2V2ZXIsIGZvciBjZXJ0YWluIHRhc2tzIGFuZCB3b3JrZmxvd3MsIGl0IGNhbiBiZSBiZW5lZmljaWFsIHRvIHVzZSBtb3JlIHNwZWNpYWxpemVkIHRvb2xzLCBvciBmdW5jdGlvbnMsIHRvIGFjY29tcGxpc2ggd29yayBhbmQgZmFjaWxpdGF0ZSB3b3JrZmxvd3MgbW9yZSBlZmZpY2llbnRseS4gIFRoaXMgaXMgd2hlcmUgcGFja2FnZXMgYW5kIGxpYnJhcmllcyBjb21lIGludG8gcGxheS4KCjo6Om5vdGUKCiogKipQYWNrYWdlcyoqOiBQYWNrYWdlcyBhcmUgYW4gZXh0ZW5zaW9uIG9mIHRoZSBwcmUtYnVpbHQgZnVuY3Rpb25zIGluIFIsIGFuZCBjYW4gYmUgaW5zdGFsbGVkIHRvIGJyaW5nIGluIHNwZWNpZmljIGZ1bmN0aW9ucyB0byBhY2NvbXBsaXNoIHRhc2tzLCBhbW9uZyBtYW55IG90aGVyIHRoaW5ncy4gIFRoZXJlIGFyZSAqKnRvbnMqKiBvZiBSIHBhY2thZ2VzIG91dCB0aGVyZSwgYnV0IGhlcmUgaXMgYSBsaXN0IG9mIHNvbWUgb2YgdGhlIG1vc3QgY29tbW9uL3VzZWZ1bCBvbmVzOiBbUXVpY2sgbGlzdCBvZiB1c2VmdWwgUiBwYWNrYWdlc10oaHR0cHM6Ly9zdXBwb3J0LnBvc2l0LmNvL2hjL2VuLXVzL2FydGljbGVzLzIwMTA1Nzk4Ny1RdWljay1saXN0LW9mLXVzZWZ1bC1SLXBhY2thZ2VzKQoKKiAqKkxpYnJhcmllcyoqOiBPbmNlIHlvdSBoYXZlIGluc3RhbGxlZCBhIHBhY2thZ2UsIHRoZXkgYXJlIHN0b3JlZCBhcyBsaWJyYXJpZXMgaW4gUi4gIFlvdSBvbmx5IGhhdmUgdG8gaW5zdGFsbCB0aGVtIG9uY2UsIGFuZCBhbnl0aW1lIHlvdSB3YW50IHRvIHVzZSB0aGUgcGFja2FnZSB5b3UgY2FuIHVzZSB0aGUgYGxpYnJhcnkoKWAgZnVuY3Rpb24sIHdoaWNoIGlzIGRlc2NyaWJlZCBiZWxvdy4KCjo6OgoKCiMjIyBUaWR5dmVyc2UKClRoZSBUaWR5dmVyc2UgaXMgYSB2ZXJ5IGNvbW1vbmx5IHVzZWQgcGFja2FnZSBmb3IgcmVzZWFyY2ggYW5kIGRhdGEgc2NpZW5jZSBhY3Rpdml0aWVzLCBhbmQgaW5zdGVhZCBvZiBiZWluZyBhIHNpbmdsZSBwYWNrYWdlLCBpdCBpcyBhIGNvbGxlY3Rpb24gb2YgcGFja2FnZXMgdGhhdCBhcmUgZGVzaWduZWQgdG8gd29yayB0b2dldGhlciBhbmQgdGhhdCBmb2N1cyBvbiB0aGUgY29ubmVjdGlvbnMgYmV0d2VlbiBhY3Rpdml0aWVzIGluIHRoZSBkYXRhIHNjaWVuY2Ugd29ya2Zsb3cuICBFYWNoIHBhY2thZ2UgZm9sbG93cyB0aGUgc2FtZSBzeW50YXgsIHdoaWNoIG1ha2VzIGxlYXJuaW5nIHRoZW0gZWFzaWVyLCBhbmQgdGhlIHdlYnNpdGUgZnVuY3Rpb25zIGFzIGEgcmVhbGx5IGdvb2QgcmVmZXJlbmNlIHBvaW50IGlmIHlvdSdyZSBzdHJ1Z2dsaW5nIHdpdGggaG93IHRvIGFwcHJvYWNoIGEgc3BlY2lmaWMgdGFzay4KCiFbXShpbWFnZXMvYmxvY2s4LTJfZGF0YS1zY2llbmNlLXdvcmtmbG93LmpwZykKCgoKTGV0J3MgdGFrZSBhIGNsb3NlciBsb29rISAgW1RpZHl2ZXJzZV0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy9wYWNrYWdlcy8pCgo8YnI+CgojIyMgSW5zdGFsbCBQYWNrYWdlClRvIGluc3RhbGwgYSBwYWNrYWdlIHdlIHVzZSB0aGUgZnVuY3Rpb24gYGluc3RhbGwucGFja2FnZXMoKWAuIAoKV2hlbiB5b3UgaW5zdGFsbCBhIHBhY2thZ2UsIHlvdSBzaG91bGQgZG8gdGhpcyBpbiB0aGUgKipSIGNvbnNvbGUqKiBiZWNhdXNlIHlvdSBkb24ndCBuZWVkIHRoaXMgc2F2ZWQgaW4geW91ciBzY3JpcHQuCgpgYGB7ciwgZXZhbD1GQUxTRX0KaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikKYGBgCgojIyMgTG9hZCBMaWJyYXJpZXMKUGFja2FnZXMgYXJlIHN0b3JlZCBpbiBsaWJyYXJpZXMuIE9uY2UgYSBwYWNrYWdlIGlzIGluc3RhbGxlZCwgd2UgbmVlZCB0byBjYWxsIHRoZSBsaWJyYXJ5IHdpdGggdGhlIGZ1bmN0aW9uIGBsaWJyYXJ5KClgLiAgCgpJdCdzIGJlc3QgcHJhY3RpY2UgdG8gbG9hZCBsaWJyYXJpZXMgaW4geW91ciBzY3JpcHQgc28gdGhhdCBvdGhlcnMgY2FuIHNlZSB3aGF0IGxpYnJhcmllcyBuZWVkIHRvIGJlIGxvYWRlZCB0byBydW4gdGhlIHNjcmlwdC4KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgo6OjpmbGFnCk5vdGUgdGhhdCB0aGUgcGFja2FnZSBuYW1lIG5lZWRzIHRvIGJlIGluIHF1b3RhdGlvbnMgd2hlbiBpbnN0YWxsaW5nIHRoZSBwYWNrYWdlLCBidXQgbm90IHdoZW4gbG9hZGluZyB0aGUgbGlicmFyeS4KCkJlY2F1c2UgcGFja2FnZXMgb25seSBuZWVkIHRvIGJlIGluc3RhbGxlZCBvbmNlLCB3ZSBjYW4gZG8gdGhpcyBpbiB0aGUgUiBjb25zb2xlIGFzIG9wcG9zZWQgdG8gaW4gdGhlIHNjcmlwdC4KCkJlY2F1c2UgbGlicmFyaWVzIG5lZWQgdG8gYmUgbG9hZGVkIGluIGVhY2ggd29ya2luZyBzZXNzaW9uLCB3ZSBjYW4gZG8gdGhpcyBpbiB0aGUgUiBzY3JpcHQgc28gdGhhdCBvdGhlcnMgY2FuIHNlZSB3aGF0IGxpYnJhcmllcyB3ZSBhcmUgdXNpbmcgYW5kIG5lZWQgdG8gYmUgbG9hZGVkLgo6OjoKCiMjIFJlYWRpbmcgRGF0YQoKIVtdKGltYWdlcy9CbG9jazgtMl9pbXBvcnQucG5nKQoKSW4gb3JkZXIgdG8gc3RhcnQgd29ya2luZyB3aXRoIGEgZGF0YXNldCBpbiBSLCB3ZSBmaXJzdCBuZWVkIHRvIGltcG9ydCwgb3IgInJlYWQgaW4iLCB0aGUgZGF0YS4gIFRvIGRvIHRoaXMsIHdlIHdpbGwgYmUgdXNpbmcgdGhlIFtyZWFkciBwYWNrYWdlXShodHRwczovL3JlYWRyLnRpZHl2ZXJzZS5vcmcvKSBpbiB0aGUgVGlkeXZlcnNlLiAKCiMjIyBSZWFkIGEgY3N2IGZpbGUKQmVjYXVzZSBvdXIgZGF0YSBpcyBpbiBgLmNzdmAgZm9ybWF0LCB3ZSdsbCBiZSB1c2luZyB0aGUgYHJlYWRfY3N2KClgIGZ1Y3Rpb24uCgpUbyBpbXBvcnQgYSBjc3YgZmlsZSB3ZSBjYW4gdXNlIHRoZSBgcmVhZF9jc3YoKWAgZnVuY3Rpb24gYW5kIGFzc2lnbiBpdCB0byBhIG5ldyBvYmplY3Qgd2Ugd2lsbCBjYWxsIGBzdXJ2ZXlfZGF0YWAuIFdlIGNyZWF0ZSBhIG5ldyBvYmplY3QgdG8gYmUgYWJsZSB0byBjYWxsIGl0IGluIGRpZmZlcmVudCBmdW5jdGlvbnMgbGF0ZXIgb24uCmBgYHtyLCBldmFsPUZBTFNFfQpzdXJ2ZXlfZGF0YSA8LSByZWFkX2Nzdigic29jaWFsLW1lZGlhLXN1cnZleS5jc3YiKQpgYGAKCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQpzdXJ2ZXlfZGF0YSA8LSByZWFkX2NzdigiZGF0YS9zdXJ2ZXktY2xlYW5pbmctd29ya3Nob3Avc29jaWFsLW1lZGlhLXN1cnZleS5jc3YiKQpgYGAKCgojIyBFeHBsb3JpbmcgRGF0YQoKQmVmb3JlIHdlIHN0YXJ0IG1hbmlwdWxhdGluZyB0aGUgZGF0YSwgaXQncyBnb29kIHRvIGdldCBhIHNlbnNlIG9mIHNvbWUgd2F5cyB0byBxdWlja2x5IGV4cGxvcmUgdGhlIGRhdGEuCgojIyMgTG9va2luZyBhdCB0aGUgRGF0YXNldApUbyBsb29rIGF0IGEgc3ByZWFkc2hlZXQgdmVyc2lvbiBvZiB5b3VyIGRhdGEgd2UgY2FuIHVzZSB0aGUgYFZpZXcoKWAgZnVuY3Rpb24uCmBgYHtyLCBldmFsPUZBTFNFfQpWaWV3KHN1cnZleV9kYXRhKQpgYGAKCiMjIyBMaXN0aW5nIENvbHVtbiBOYW1lcwpUbyBhc2sgZm9yIGEgbGlzdCBvZiBhbGwgdGhlIGNvbHVtbiBuYW1lcyBpbiBvdXIgZGF0YXNldCB3ZSBjYW4gdXNlIHRoZSBgbmFtZXMoKWAgZnVuY3Rpb24uCmBgYHtyLCBldmFsPVRSVUV9Cm5hbWVzKHN1cnZleV9kYXRhKQpgYGAKCgojIyMgSGVhZCBGdW5jdGlvbgpUaGUgaGVhZCBmdW5jdGlvbiB3aWxsIGRpc3BsYXkgdGhlIHRvcCByb3dzIG9mIHRoZSBkYXRhc2V0LiBJdCB3aWxsIGluY2x1ZGUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGRlZmF1bHQgZGF0YSB0eXBlIGFzc2lnbmVkIHRvIGVhY2ggY29sdW1uLgpgYGB7ciwgZXZhbD1UUlVFfQpoZWFkKHN1cnZleV9kYXRhKQpgYGAKCgojIyBDbGVhbmluZyBEYXRhCgpXaGVuIHdlIHRhbGsgYWJvdXQgImNsZWFuaW5nIGRhdGEiLCB3ZSdyZSB0YWxraW5nIGFib3V0IG1hbmlwdWxhdGluZyB0aGUgb3JpZ2luYWwgZGF0YSBzbyB0aGF0IGl0J3MgZWFzaWVyIHRvIHN0YXJ0IGV4cGxvcmluZyB0cmVuZHMsIGFuYWx5emluZywgYW5kIHZpc3VhbGl6aW5nLiAgQXMgd2UgZ28gdGhyb3VnaCB0aGlzIHByb2Nlc3MsIGl0IGNhbiBiZSBoZWxwZnVsIHRvIHNhdmUgZGlmZmVyZW50IHZlcnNpb25zLCBvciBzdGFnZXMgb2YgdGhlIGRhdGEsIHRvIGhlbHAgcHJvbW90ZSBhIHRyYW5zcGFyZW50IGFuZCByZXByb2R1Y2libGUgcHJvY2Vzcy4gIEluIHRoaXMgc2Vzc2lvbiwgd2UncmUgZ29pbmcgdG8gZm9jdXMgb24gc29tZSBjb21tb24gY2xlYW5pbmcgdGVjaG5pcXVlcyB0aGF0IGFyZSB1c2VkIG9uIHN1cnZleSBkYXRhLiAgCgpJbiB0aGUgW0ludHJvZHVjdGlvbiB0byBSIHNlc3Npb25dKEJsb2NrOC0xX1NVUl9JbnRyby10by1SLmh0bWwpIHdlIGRpc2N1c3NlZCAqKm9iamVjdHMqKiBhbmQgKipmdW5jdGlvbnMqKiwgYW5kIHBsYXllZCB3aXRoIHRoZSBpZGVhIG9mIG9iamVjdHMgc3RvcmluZyBpbmZvcm1hdGlvbiwgYW5kIGZ1bmN0aW9ucyBtYW5pcHVsYXRpbmcgdGhlIG9iamVjdC9kYXRhLgoKTm93IHdlJ3JlIGdvaW5nIHRvIHN0YXJ0IGltcGxlbWVudGluZyAqKnBpcGVzKiogYXMgYSB3YXkgdG8gY29ubmVjdCBvYmplY3RzIHRvICoqZnVuY3Rpb25zKiogYW5kICoqYXJndW1lbnRzKiouCgojIyMjIFBpcGVzCgpQaXBlcyBhcmUgdXNlZCB0byBjaGFpbiBzdGVwcyBvZiBpbnN0cnVjdGlvbnMgb3IgYWN0aW9ucyB0b2dldGhlciwgYW5kIG9mdGVuIGludm9sdmUgd3JpdGluZyBvdmVyIGFuIG9iamVjdCB0byBnaXZlIGl0IGEgbmV3IHZhbHVlLiBXZSdsbCB3YWxrIHRocm91Z2ggc29tZSBleGFtcGxlcyBvZiBob3cgdGhpcyB3b3JrcywgYW5kIHN0YXJ0IHRvIHNlZSBob3cgdGhlIGZ1bGwgc3ludGF4IG9mIFIgY29tZXMgdG9nZXRoZXIuCgohW10oaW1hZ2VzL2RheTJfUlN5bnRheC5wbmcpCgoKPGJyPgoKIyMjIENoYW5naW5nIENvbHVtbiBOYW1lcwoKWW91J2xsIG5vdGljZSB0aGF0IHRoZSBjb2x1bW4gbmFtZXMgYXJlIHJlZmxlY3RpdmUgb2YgdGhlIHF1ZXN0aW9ucyBpbiB0aGUgc3VydmV5LiBXaGlsZSBzb21lIG9mIHRoZSBzaG9ydGVyIG5hbWVzIHdpbGwgd29yaywgdGhvc2UgdGhhdCBhcmUgdmVyeSBsb25nIGFuZCBoYXZlIHNwYWNlcyBpbiB0aGUgbmFtZXMgY2FuIGJlIGFubm95aW5nIHRvIHdvcmsgd2l0aC4gIFRoZSBmaXJzdCBzdGVwIGluIG91ciBjbGVhbmluZyB3aWxsIGJlIHRvIGdldCBhbGwgb2YgdGhlIGNvbHVtbiBuYW1lcyBpbiBhIHdheSB0aGF0IHdpbGwgYmUgZWFzeSB0byB3b3JrIHdpdGguCgpUbyBjaGFuZ2UgY29sdW1uIG5hbWVzIHdlIGNhbiB1c2UgdGhlIGZ1bmN0aW9uIGByZW5hbWUoKWAuICBUaGUgZnVuY3Rpb24gYHJlbmFtZSgpYCBpcyBwYXJ0IG9mIHRoZSBbZHBseXIgcGFja2FnZV0oaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnL2luZGV4Lmh0bWwpIHRoYXQgd2FzIGluc3RhbGxlZCB3aXRoIHRpZHl2ZXJzZS4KCjo6OndhbGt0aHJvdWdoClR5cGUgdGhlIGZvbGxvd2luZyBjb2RlIHRvIGNoYW5nZSB0aGUgY29sdW1uIG5hbWUgZnJvbSAiWWVhciBvZiBTdHVkeSIgdG8gInllYXJfb2Zfc3R1ZHkiCmBgYHtyfQpzdXJ2ZXlfZGF0YSA8LSBzdXJ2ZXlfZGF0YSB8PgogIHJlbmFtZSgieWVhcl9vZl9zdHVkeSIgPSAiWWVhciBvZiBTdHVkeSIpCmBgYAoKKipTdGVwLWJ5LXN0ZXAgZXhwbGFuYXRpb246KioKCiogVGhpcyBjb21tYW5kIGZpcnN0IHN0YXJ0cyBvZmYgd2l0aCB0aGUgYHN1cnZleV9kYXRhYCBvYmplY3QsIHdoaWNoIGlzIG91ciBkYXRhc2V0LgoqIFRoZSBhc3NpZ25tZW50IG9wZXJhdG9yIGNvbWVzIG5leHQsIGFuZCB3aWxsIHJlLXdyaXRlIHRoZSBpbmZvcm1hdGlvbiBzdG9yZWQgaW4gYHN1cnZleV9kYXRhYCB3aXRoIGFsbCB0aGUgaW5mb3JtYXRpb24gdGhhdCBpcyB0byB0aGUgcmlnaHQgc2lkZSBvZiB0aGUgb3BlcmF0b3IuCiogV2UgdGhlbiB1c2UgdGhlIGBzdXJ2ZXlfZGF0YWAgb2JqZWN0IGFuZCB0aGUgcGlwZSBgfD5gIHRvIHRlbGwgUiB0aGF0IHdlIHdhbnQgdG8gdGFrZSB0aGUgZGF0YSB0aGF0IGlzIHN0b3JlZCBpbiBgc3VydmV5X2RhdGFgLCBhbmQgdGhlbiBkbyBzb21ldGhpbmcgdG8gaXQgKHdoaWNoIGlzIHdoYXQgY29tZXMgYWZ0ZXIgdGhlIHBpcGUpLgoqIFRoZSBgcmVuYW1lYCBmdW5jdGlvbiBpcyB1c2VkIHRvIHJlbmFtZSBjb2x1bW5zLCBhbmQgaXMgYWx3YXlzIGZvbGxvd2VkIGJ5IGJyYWNrZXRzLiAgSW5zaWRlIHRob3NlIGJyYWNrZXRzLCB3ZSdsbCBwdXQgdGhlIG5ldyBjb2x1bW4gbmFtZSB0aGF0IHdlIHdhbnQgaW4gcXVvdGF0aW9uIG1hcmtzIGAiImAsIGZvbGxvd2VkIGJ5IGFuIGVxdWFsIHNpZ24gYD1gLCBmb2xsb3dlZCBieSB0aGUgZXhpc3RpbmcgY29sdW1uIG5hbWUgaW4gcXVvdGF0aW9uIG1hcmtzIGAiImAuCiogV2UgdGhlbiBydW4gdGhlIGNvbW1hbmQgYW5kIGhvcGUgaXQgd29ya3MhCjo6OgoKCiMjIFlvdXIgVHVybiEKCjo6OnF1ZXN0aW9uCkZpcnN0LCB1c2UgdGhlIGZ1bmN0aW9uYG5hbWVzKClgIHRvIGRpc3BsYXkgdGhlIGNvbHVtbiBuYW1lcy4KYGBge3IsIGV2YWw9RkFMU0V9Cm5hbWVzKHN1cnZleV9kYXRhKQpgYGAKOjo6Cgo6OjpxdWVzdGlvbgpOb3csIHNlZSBpZiB5b3UgY2FuIGNoYW5nZSB0aGUgYEhvdyBtYW55IGhvdXJzIHBlciBkYXkgZG8geW91IHNwZW5kIG9uIHNvY2lhbCBtZWRpYT9gIGNvbHVtbiBuYW1lIHRvIGBob3Vycy1wZXItZGF5YApgYGB7ciwgY2xhc3Muc291cmNlID0gJ2ZvbGQtaGlkZSd9CnN1cnZleV9kYXRhIDwtIHN1cnZleV9kYXRhIHw+CiAgcmVuYW1lKCJob3Vyc19wZXJfZGF5IiA9ICJIb3cgbWFueSBob3VycyBwZXIgZGF5IGRvIHlvdSBzcGVuZCBvbiBzb2NpYWwgbWVkaWE/IikgCmBgYAoKOjo6Cgo6OjpxdWVzdGlvbgpOZXh0LCB0cnkgdG8gY2hhbmdlIHRoZSBmb2xsb3dpbmcgMyBjb2x1bW4gbmFtZXM6CgoqIENoYW5nZSBgV2hpY2ggc29jaWFsIG1lZGlhIHBsYXRmb3JtcyBkbyB5b3UgdXNlIGF0IGxlYXN0IG9uY2UgYSB3ZWVrP2AgdG8gYHBsYXRmb3Jtc2AKKiBDaGFuZ2UgYFNvY2lhbCBtZWRpYSBtYWtlcyBtZSBmZWVsIGNvbm5lY3RlZGAgdG8gYGZlZWxfY29ubmVjdGVkYAoqIENoYW5nZSBgU29jaWFsIG1lZGlhIGluY3JlYXNlcyBteSBzdHJlc3NgIHRvIGBmZWVsX2luY3JlYXNlX3N0cmVzc2AKCioqSGludDoqKiBJdCBjYW4gYmUgdGVkaW91cyB0byBkbyB0aGVzZSBjaGFuZ2VzIG9uZSBieSBvbmUsIGJ1dCBieSB1c2luZyBjb21tYXMgYCxgIHlvdSBjYW4gcmVuYW1lIGNvbHVtbiBuYW1lcyB3aXRoIGEgc2luZ2xlIGNvZGUgY2h1bmsuICAKYGBge3IsIGNsYXNzLnNvdXJjZSA9ICdmb2xkLWhpZGUnfQpzdXJ2ZXlfZGF0YSA8LSBzdXJ2ZXlfZGF0YSB8PgogIHJlbmFtZSgicGxhdGZvcm1zIiA9ICJXaGljaCBzb2NpYWwgbWVkaWEgcGxhdGZvcm1zIGRvIHlvdSB1c2UgYXQgbGVhc3Qgb25jZSBhIHdlZWs/IiwKICAgICAgICAgICJmZWVsX2Nvbm5lY3RlZCIgPSAiU29jaWFsIG1lZGlhIG1ha2VzIG1lIGZlZWwgY29ubmVjdGVkIiwKICAgICAgICAgICJmZWVsX2luY3JlYXNlX3N0cmVzcyIgPSAiU29jaWFsIG1lZGlhIGluY3JlYXNlcyBteSBzdHJlc3MiKSAKYGBgCjo6OgoKOjo6cXVlc3Rpb24KTm93LCBsZXQncyBjaGFuZ2UgdGhlIHJlc3Qgb2YgdGhlIGNvbHVtbiBuYW1lcyBjb3B5IHRoZSBmb2xsb3dpbmcgY29kZS4gKElmIHlvdSBmZWVsIHlvdSdyZSBzdGFydGluZyB0byB1bmRlcnN0YW5kIGhvdyB0aGlzIHdvcmtzLCB5b3UgY2FuIHNob3cgdGhlIGNvZGUgYmVsb3cgYW5kIGBjb3BlICsgcGFzdGVgIGl0IGludG8geW91ciBzY3JpcHQsIG9yIGlmIHlvdSB3YW50IHNvbWUgbW9yZSBwcmFjdGljZSwgZmVlbCBmcmVlIHRvIGRvIGl0IHlvdXJzZWxmIQoKYGBge3IsIGNsYXNzLnNvdXJjZSA9ICdmb2xkLWhpZGUnfQpzdXJ2ZXlfZGF0YSA8LSBzdXJ2ZXlfZGF0YSB8PgogIHJlbmFtZSggImZlZWxfZGlzdHJhY3RlZCIgPSAiSSBmaW5kIHNvY2lhbCBtZWRpYSBkaXN0cmFjdGluZyBmcm9tIHN0dWRpZXMiLAogICAgICAgICAiZmVlbF9pbXByb3ZlZF9tb29kIiA9ICJTb2NpYWwgbWVkaWEgcG9zaXRpdmVseSBpbXBhY3RzIG15IG1vb2QiLAogICAgICAgICAidXNhZ2Vfc3RheV9pbl90b3VjaCIgPSAiU3RheWluZyBjb25uZWN0ZWQgd2l0aCBmcmllbmRzL2ZhbWlseSIsCiAgICAgICAgICJ1c2FnZV9lbnRlcnRhaW5tZW50IiA9ICJFbnRlcnRhaW5tZW50L3Bhc3NpbmcgdGltZSIsCiAgICAgICAgICJ1c2FnZV9uZXR3b3JraW5nIiA9ICJBY2FkZW1pYyBvciBwcm9mZXNzaW9uYWwgbmV0d29ya2luZyIsCiAgICAgICAgICJ1c2FnZV9uZXdzIiA9ICJTdGF5aW5nIGluZm9ybWVkIGFib3V0IG5ld3MvZXZlbnRzIiwKICAgICAgICAgInVzYWdlX2V4cHJlc3Npb24iID0gIlNlbGYtZXhwcmVzc2lvbi9jcmVhdGl2aXR5IiwKICAgICAgICAgInRpbWVzdGFtcCIgPSAiVGltZXN0YW1wIiwKICAgICAgICAgIm5hbWUiID0gIk5hbWUiLAogICAgICAgICAiZW1haWwiID0gIkVtYWlsIiwKICAgICAgICAgImFnZSIgPSAiQWdlIiwKICAgICAgICAgImdlbmRlciIgPSAiR2VuZGVyIikKYGBgCgo6OjoKCgojIyBQZXJzb25hbCBJZGVuZmllcnMsIElEIENvZGVzLCBhbmQgRGF0YSBWZXJzaW9uaW5nCgpZb3UgcHJvYmFibHkgbm90aWNlZCB0aGF0IGluIHRoaXMgc3VydmV5IHdlIGNvbGxlY3RlZCBuYW1lcyBhbmQgZW1haWwgYWRkcmVzc2VzLiBUaGlzIGNhbiBiZSBuZWNlc3NhcnkgZm9yIHNldmVyYWwgcmVhc29ucywgYnV0IGl0IGFsc28gcG9zZXMgZXRoaWNhbCBpc3N1ZXMgd2l0aCByZXNwZWN0IHRvIHdobyBpcyBhYmxlIHRvIHNlZSB0aGlzIGluZm9ybWF0aW9uLiBJdCBpcyBjb21tb24gcHJhY3RpY2UgdG8gcmVtb3ZlIHBlcnNvbmFsIGlkZW50aWZpZXJzIGZyb20gc3VydmV5IGRhdGEsIGJ1dCB5b3UgbWF5IGFsc28gd2lzaCB0byBjcmVhdGUgYSBjb2RlIGZvciBlYWNoIGVudHJ5IHNob3VsZCB5b3UgZXZlciBuZWVkIHRvIGNvbm5lY3QgaW5mb3JtYXRpb24gYmFjayB0byB0aGUgcmVzcG9uZGVudC4KCkxldCdzIHRyeSB0aGlzIGlzIGEgZmV3IHN0ZXBzOgoKIyMjIEFkZCBhbiBJRCBjb2x1bW4KClRoZSBgbXV0YXRlKClgIGZ1bmN0aW9uLCB0aGF0IGlzIHBhcnQgb2YgdGhlIFtkcGx5ciBwYWNrYWdlXShodHRwczovL2RwbHlyLnRpZHl2ZXJzZS5vcmcvaW5kZXguaHRtbCksIGlzIHVzZWZ1bCB3aGVuIHlvdSB3YW50IHRvIGNyZWF0ZSBuZXcgY29sdW1ucyB0aGF0IGFyZSBmdW5jdGlvbnMgb2YgZXhpc3RpbmcgdmFyaWFibGVzLgoKV2hpbGUgbm90IHRlY2huaWNhbGx5IHRoZSBmdW5jdGlvbiBvZiBhbiBleGlzdGluZyB2YXJpYWJsZSwgd2UgY2FuIHVzZSBgbXV0dWF0ZWAgd2l0aCB0aGUgYHJvd19udW1iZXIoKWAgZnVuY3Rpb24gdG8gY3JlYXRlIGEgbmV3IGNvbHVtbiB0aGF0IHdpbGwgY29udGFpbiB0aGUgbnVtYmVyIG9mIGVhY2ggcm93LCB0aHVzIGdpdmVuIGVudHJ5IGEgdW5pcXVlIElEIG51bWJlci4KCgpgYGB7ciwgZXZhbD1GQUxTRX0Kc3VydmV5X2RhdGEgPC0gc3VydmV5X2RhdGEgfD4KICBtdXRhdGUoSUQgPSByb3dfbnVtYmVyKCkpCmBgYAoKOjo6d2Fsa3Rocm91Z2gKWW91IGNhbiBzZWUgdGhhdCB0aGUgZ3JhbW1hciB3b3JrcyBpbiB0aGUgc2FtZSB3YXkgYXMgdGhlIGByZW5hbWVgIGZ1bmN0aW9uLCB3aGljaCBpcyBvbmUgb2YgdGhlIHN0cmVuZ3RocyBvZiB1c2luZyB0aGUgVGlkeXZlcnNlLiAgCgoqIFRoZSBtdXRhdGUgZnVuY3Rpb24gaXMgZm9sbG93ZWQgYnkgYnJhY2tldHMsIGFuZCB0aGUgZmlyc3QgdmFsdWUgdGhhdCBpcyBlbnRlcmVkIGlzIHdoYXQgeW91IHdhbnQgdGhlIG5ldyBjb2x1bW4gdG8gYmUgY2FsbGVkLgoqIEFmdGVyIHRoZSBgPWAgc2lnbiwgaW5zZXJ0IHdoYXQgaXMgdG8gZ28gaW4gdGhlIHJvd3Mgb2YgdGhlIG5ldyBjb2x1bW4uCiogSW4gdGhpcyBjYXNlLCBgcm93X251bWJlcigpYCBpcyBhZGRpbmcgdGhlIG51bWJlciBvZiB0aGUgY29ycmVzcG9uZGluZyByb3cgdG8gdGhlIGNvbHVtbi4KCldlJ2xsIHBsYXkgd2l0aCBtb3JlIHVzZXMgb2YgYG11dGF0ZWAgaW4ganVzdCBhIGxpdHRsZSBiaXQhCjo6OgoKPGJyPgoKIyMjIE1vdmUgdGhlIElEIGNvbHVtbiB0byB0aGUgbGVmdC1tb3N0IHBvc2l0aW9uIG9mIHRoZSBkYXRhCgpIYXZpbmcgYW4gSUQgY29sdW1uIGFzIHRoZSBsZWZ0LW1vc3QsIG9yIGZpcnN0LCBjb2x1bW4gaW4geW91ciBkYXRhc2V0IG1ha2VzIHRoaW5ncyBnZW5lcmFsbHkgZWFzaWVyIHRvIGtlZXAgdHJhY2sgb2YuCgpUaGUgYHJlbG9jYXRlKClgIGZ1bmN0aW9uLCB3aGljaCBpcyBhbHNvIHBhcnQgb2YgdGhlICoqZHBseXIqKiBwYWNrYWdlLCB3aGljaCBkb2VzIGp1c3Qgd2hhdCBpdHMgbmFtZSBpbXBsaWVzOiBpdCByZWxvY2F0ZXMgY29sdW1ucyBpbiBhIGRhdGFzZXQuCgpUaGUgZGVmYXVsdCBvZiBgcmVsb2NhdGVgIGlzIHRvIHB1dCB0aGUgc3BlY2lmaWVkIGNvbHVtbiBpbiB0aGUgZmlyc3QgcG9zaXRpb24sIHNvIHdlIGRvbid0IG5lZWQgdG8gc3BlY2lmeSBsb2NhdGlvbiBmb3IgdGhpcyB0YXNrLgoKYGBge3IsIGV2YWw9RkFMU0V9CnN1cnZleV9kYXRhIDwtIHN1cnZleV9kYXRhIHw+CiAgcmVsb2NhdGUoSUQpCmBgYAoKOjo6bm90ZQpFdmVyeSB0aW1lIHlvdSBtYWtlIGEgY2hhbmdlIHRvIHlvdXIgZGF0YSwgeW91IGNhbiB1c2UgdGhlIGBWaWV3KHN1cnZleV9kYXRhKWAgZnVuY3Rpb24gdG8gY2hlY2sgd2hhdCB3YXMgZG9uZS4KOjo6CgpCZWZvcmUgd2UgZ28gYW55IGZ1cnRoZXIsIGxldCdzIHNhdmUgYW5vdGhlciBjb3B5IG9mIHRoaXMgZGF0YS4gIFRoaXMgd2lsbCBhbGxvdyB0aGUgZGF0YSBob2xkZXIgdG8gaGF2ZSBhIGNvcHkgb2YgdGhlIGRhdGEgdGhhdCBoYXMgYm90aCB0aGUgcGVyc29uYWwgaWRlbnRpZmllcnMgYW5kIHRoZSBJRCBjb2Rlcy4gIFdlIHdvbid0IGJlIGFuYWx5emluZyB0aGlzIGRhdGFzZXQsIGJ1dCBpdCB3aWxsIGJlIG5lY2Vzc2FyeSBzaG91bGQgeW91IG5lZWQgdG8gcmVjb25uZWN0IHdpdGggcmVzcG9uZGVudHMuICAKCjxicj4KCiMjIyMgU2F2aW5nIGEgZGF0YXNldAoKTXVjaCBsaWtlIHdlIGRpZCB3aXRoIHJlYWRpbmcgYC5jc3ZgIGRhdGEgaW50byBSLCB0aGVyZSBpcyBhIHNpbWlsYXIgY29tbWFuZCB0byBzYXZlLCBvciAid3JpdGUiIGAuY3N2YCBkYXRhIGJhY2sgdG8geW91ciBjb21wdXRlciBjYWxsZWQgYHdyaXRlX2NzdigpYC4gIFRoZSBzeW50YXggaXMgYXMgZm9sbG93czoKCmB3cml0ZV9jc3YoZGF0YS1vYmplY3QtbmFtZSwgZmlsZT0iZmlsZS1wYXRoL2RhdGFmaWxlLW5hbWUuY3N2IilgCgpJZiB5b3UgdXNlIHRoZSBzYW1lIGZpbGUgbmFtZSBhcyB0aGUgb25lIHlvdSBhcmUgd29ya2luZyBvbiwgaXQgd2lsbCBjaGFuZ2UgdGhhdCBmaWxlIGJhc2VkIG9uIHdoYXQgeW91J3ZlIGRvbmUuICBIb3dldmVyLCAqKndlIGRvbid0IHdhbnQgdG8gdG91Y2ggb3VyIG9yaWdpbmFsIGRhdGEqKiwgc28gd2UncmUgZ29pbmcgdG8gbWFrZSBhIG5ldyBmaWxlIHRvIGluZGljYXRlIHRoYXQgaXQgaGFzIGNsZWFuIGNvbHVtbnMsIElEIGNvZGVzLCBhbmQgcGVyc29uYWwgaWRlbnRpZmllcnMuCgpgYGB7ciwgZXZhbD1GQUxTRX0Kd3JpdGVfY3N2KHN1cnZleV9kYXRhLCAic3VydmV5LWRhdGFfY2xlYW4tY29sc19JRHMuY3N2IikKYGBgCgoKIyMjIEJhY2sgdG8gQ2xlYW5pbmchCgpOb3cgdGhhdCB3ZSd2ZSBzYXZlZCB0aGF0IHZlcnNpb24gb2YgdGhlIGRhdGEsIGxldCdzIG5vdyByZW1vdmUgdGhlIGBlbWFpbGAgYW5kIGBuYW1lYCBjb2x1bW5zIHRvIGRlLWlkZW50aWZ5IHRoZSBkYXRhc2V0LCBhbmQgYWxzbyByZW1vdmUgc29tZSB1bm5lY2Vzc2FyeSBjb2x1bW5zLgoKIyMjIyBSZW1vdmluZyBDb2x1bW5zCgpUaGVyZSBhcmUgYSBudW1iZXIgb2Ygd2F5cyB0byByZW1vdmUgY29sdW1ucyBpbiBSLCB3ZSdsbCBmb2N1cyBvbiB0aGUgdGhlIGBzZWxlY3RgIGZ1bmN0aW9uIGZyb20gdGhlIGBkcGx5cmAgcGFja2FnZSBpbiBUaWR5dmVyc2UuCgpUaGlzIGZvbGxvd3MgdGhlIHNhbWUgc3ludGF4IHRoYXQgd2UndmUgYmVlbiB1c2luZywgYW5kIGFmdGVyIHRoZSBgc2VsZWN0YCBmdW5jdGlvbiwgeW91IGluc2VydCBhIGRhc2ggYC1gLCBvciBtaW51cyBzeW1ib2wsIHBsdXMgdGhlIG5hbWUgb2YgdGhlIGNvbHVtbiB5b3Ugd2FudCB0byByZW1vdmUuCgpMZXQncyBzdGFydCBiZSByZW1vdmluZyB0aGUgYHRpbWVzdGFtcGAgY29sdW1uIGJ5IHVzaW5nIGl0cyBjb2x1bW4gbmFtZS4KCmBgYHtyLCBldmFsPUZBTFNFfQpzdXJ2ZXlfZGF0YSA8LSBzdXJ2ZXlfZGF0YSB8PgogIHNlbGVjdCgtdGltZXN0YW1wKQpgYGAKCllvdSBjYW4gdGFrZSBhIGxvb2sgYXQgdGhlIGRhdGFzZXQgYW5kIG5vdyBzZWUgdGhhdCB0aGUgYHRpbWVzdGFtcGAgY29sdW1uIGlzIG5vdyBnb25lLgoKTGV0J3Mgbm93IHJlbW92ZSB0aGUgaWRlbnRpZmllcnMgYG5hbWVgIGFuZCBgZW1haWxgLiAgCgo6OjpxdWVzdGlvbgoKU2VlIGlmIHlvdSBjYW4gcmVtb3ZlIHRoZSBgbmFtZWAgYW5kIGBlbWFpbGAgY29sdW1ucywgYXMgd2Ugd2FudCB0byBnZXQgcmlkIG9mIHRoZSBpZGVudGlmeWluZyB2YXJpYWJsZXMuCgpIaW50OiBUbyBkbyB0aGlzIGlzIGEgc2luZ2xlIGNvbW1hbmQsIHNlZSBpZiB5b3UgY2FuIGZpZ3VyZSBvdXQgaG93IHRvIHVzZSB0aGUgYGMoKWAgZnVuY3Rpb24gdGhhdCB3YXMgaW50cm9kdWNlZCBpbiB0aGUgW0ludHJvZHVjdGlvbiB0byBSIHNlc3Npb25dKEJsb2NrOC0xX1NVUl9JbnRyby10by1SLmh0bWwpCmBgYHtyLCBjbGFzcy5zb3VyY2UgPSAnZm9sZC1oaWRlJywgZXZhbCA9IEZBTFNFfQoKc3VydmV5X2RhdGEgPC0gc3VydmV5X2RhdGEgfD4KICBzZWxlY3QoLWMobmFtZSwgZW1haWwpKQpgYGAKOjo6CgoKPGJyPgoKIyMjIyBTYXZlIEFub3RoZXIgVmVyc2lvbiBvZiB0aGUgRGF0YQoKTm93IHRoYXQgd2UgaGF2ZSBhIGRhdGFzZXQgdGhhdCBoYXMgY2xlYW5lZCBjb2x1bW5zLCBubyBpZGVudGlmaWVycywgYW5kIG5vIHVubmVjZXNzYXJ5IGNvbHVtbnMsIGxldCdzIHNhdmUgYSBjb3B5IG9mIHRoaXMgc2hvdWxkIHdlIGV2ZXIgbmVlZCB0byBnbyBiYWNrIHRvIHRoZSBiZWdpbm5pbmcuCgpgYGB7ciwgZXZhbD1GQUxTRX0Kd3JpdGVfY3N2KHN1cnZleV9kYXRhLCAic3VydmV5LWRhdGFfY2xlYW4tY29sc19uby1JRC5jc3YiKQpgYGAKCiMjIyBDbGVhbmluZyBWYWx1ZXMKCk5vdyB0aGF0IHdlJ3ZlIGNsZWFuZWQgdXAgdGhlIHZhcmlhYmxlcy9jb2x1bW5zLCBsZXQncyB0YWtlIGEgbG9vayBhdCBvdXIgZGF0YXNldCBhbmQgc2VlIHdoYXQgdmFsdWVzIG1pZ2h0IG5lZWQgc29tZSB3b3JrLgoKYGBge3IsIGV2YWw9RkFMU0V9ClZpZXcoc3VydmV5X2RhdGEpCmBgYAoKIyMgQ2xlYW5pbmcgU3VydmV5IFZhbHVlcwoKTm93IHRoYXQgd2UndmUgY2xlYW5lZCB1cCBvdXIgaGVhZGVycywgaXQncyB0aW1lIHRvIHN0YXJ0IGxvb2tpbmcgYXQgdGhlIHZhbHVlcyB0byBzZWUgaWYgd2UnbGwgYmUgZWFzaWx5IGFibGUgdG8gYW5hbHl6ZSB0aGVtLCBvciBpZiB0aGV5IG5lZWQgY2xlYW5pbmcgdG9vLiAgCgpJZiB5b3UgdGFrZSBhIGxvb2sgYXQgdGhlIGBwbGF0Zm9ybXNgIGNvbHVtbiwgeW91J2xsIHNlZSB0aGF0IHRoZSB2YWx1ZXMgYXJlIHByZXR0eSBtZXNzeSwgYW5kIGNhbiBpbmNsdWRlIGFueSBjb21iaW5hdGlvbiBvZiB1cCB0byA2IG9wdGlvbnMuIFRoaXMgaXMgdmVyeSBoYXJkIHRvIHdvcmsgd2l0aCwgc28gd2UnbGwgbmVlZCB0byBmaWd1cmUgb3V0IHRoZSBiZXN0IHdheSB0byBmb3JtYXQgdGhpbmdzLgoKIyMjIFdpZGUgRGF0YSwgTG9uZyBEYXRhLCBhbmQgdGhlIFRpZHkgRGF0YSBQcmluY2lwbGVzCgpXaGVuIGNvbnNpZGVyaW5nIHRoZXNlIHR5cGVzIG9mIG1lc3N5IGNvbHVtbnMsIHRoZXJlIGFyZSB0d28gZGlmZmVyZW50IHN0cmF0ZWdpZXMgd2UgY2FuIHRha2UgdG8gY2xlYW4gdGhlbSB1cDoKCjEpIE1ha2UgdGhlIGRhdGEgKipsb25nLCBvciB0aWR5KiosIHdoaWNoIGFpbXMgdG8gcmVkdWNlIGNvbHVtbnMgYnV0IGNyZWF0ZXMgbW9yZSByb3dzLgoyKSBNYWtlIHRoZSBkYXRhICoqd2lkZSoqLCB3aGljaCBjcmVhdGVzIG1vcmUgY29sdW1ucyBhbmQgY3JlYXRlcyBhIHdpZGVyIHNwcmVhZHNoZWV0LgoKCkluIHRoZSBuZXh0IHNlc3Npb24gb2YgdGhpcyBzZXJpZXMsIFtNYWtpbmcgU2Vuc2Ugb2YgU3VydmV5IERhdGFdKEJsb2NrOC0zX1NVUl9NYWtpbmctU2Vuc2UuaHRtbCksIHdlIHdpbGwgYmUgbG9va2luZyBhdCB0aGUgcHJvcyBhbmQgY29ucyBvZiB3aWRlIHZzIGxvbmcgZGF0YSwgYnV0IGluIHRoaXMgc2Vzc2lvbiB3ZSB3aWxsIGZvY3VzIG9uIHRoZSB0ZWNobmlxdWVzIHRvIHBsYXkgd2l0aCB0aGUgc2hhcGUgb2Ygb3VyIGRhdGEuCgoKIyMjIE1ha2luZyBEYXRhIExvbmcgb3IgIlRpZHkiCgpJbiBSLCBhbmQgc3BlY2lmaWNhbGx5IHRoZSBUaWR5dmVyc2UsIHRoZSBbVGlkeSBEYXRhIFByaW5jaXBsZXNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy90aWR5ci92aWduZXR0ZXMvdGlkeS1kYXRhLmh0bWwpIHNwZWNpZnkgcXVhbGl0aWVzIG9mIHdoYXQgaXMgY29uc2lkZXJlZCAidGlkeSBkYXRhIiwgd2l0aCBkYXRhIHRoYXQgZG9lc24ndCBtZWV0IGFsbCBjcml0ZXJpYSBiZWluZyAibWVzc3kgZGF0YSIuIFRoZXkgcHJvdmlkZSBhIHN0YW5kYXJkIHdheSB0byBvcmdhbml6ZSBkYXRhIHRvICJmYWNpbGl0YXRlIGluaXRpYWwgZXhwbG9yYXRpb24gYW5kIGFuYWx5c2lzIG9mIHRoZSBkYXRhLCBhbmQgdG8gc2ltcGxpZnkgdGhlIGRldmVsb3BtZW50IG9mIGRhdGEgYW5hbHlzaXMgdG9vbHMgdGhhdCB3b3JrIHdlbGwgdG9nZXRoZXIiICAoW3NvdXJjZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3RpZHlyL3ZpZ25ldHRlcy90aWR5LWRhdGEuaHRtbCkpLiAKCioqVGlkeSBEYXRhIFByaW5jaXBsZXM6KioKCiogRWFjaCB2YXJpYWJsZSBpcyBhIGNvbHVtbi4KKiBFYWNoIG9ic2VydmF0aW9uIGlzIGEgcm93LgoqIEVhY2ggdmFsdWUgaXMgYSBjZWxsLiAKCkhlcmUgaXMgYW4gZXhhbXBsZSBvZiB3aGF0IHdvdWxkIGJlIGNvbnNpZGVyZWQgYSBtZXNzeSBkYXRhc2V0OgoKIVtdKGltYWdlcy9ibG9jazgtMl90aWR5LWRhdGExLnBuZykKCldoaWxlIHN0cnVjdHVyaW5nIGRhdGEgaW4gdGhpcyB3YXkgaXMgbXVjaCBlYXNpZXIgZm9yIGEgaHVtYW4gdG8gc2NhbiBhbmQgZm9yIHN1bW1hcnkgdGFibGVzLCBpdCdzIHRyaWNraWVyIGZvciBhIGNvZGluZyBsYW5ndWFnZSB0byBwYXJzZSBhbmQgd29yayB3aXRoLiAgVGhlIHZhcmlvdXMgcGFja2FnZXMgb2YgdGhlIFRpZHl2ZXJzZSBhcmUgc3BlY2lmaWNhbGx5IGdlYXJlZCB0b3dhcmRzIHdvcmtpbmcgd2l0aCB0aWR5IGRhdGEsIGFuZCBtYWtpbmcgeW91ciBkYXRhIHRpZHkgd2lsbCBtYWtlIGZhY2V0aW5nLCBncm91cGluZywgbW9kZWxsaW5nLCBhbmQgdmlzdWFsaXppbmcgbXVjaCBlYXNpZXIuCgpIZXJlJ3MgYW4gZXhhbXBsZSBvZiB3aGF0IGEgdGlkeSB2ZXJzaW9uIG9mIHRoaXMgZGF0YSB3b3VsZCBsb29rIGxpa2U6CgohW10oaW1hZ2VzL2Jsb2NrOC0yX3RpZHktZGF0YTIucG5nKQoKQXMgeW91J2xsIG5vdGljZSwgdGhlIHJlcGVhdGluZyB2YWx1ZXMgaW4gdGhlIGBOYW1lYCBjb2x1bW4gc2VlbXMgY2x1bmt5IGFuZCB3ZWlyZCB0byBzY2FuLiAgQnV0IGEgd2F5IHRvIHRoaW5rIGFib3V0IHRoaW5rIGFib3V0IHdoeSB0aGlzIG1pZ2h0IGJlIHVzZWZ1bCB3b3VsZCBiZSBpZiBpbnN0ZWFkIG9mIDMgcXVpenMsIHRoZXJlIHdlcmUgNTAuICBIYXZpbmcgYSB1bmlxdWUgY29sdW1uIGZvciBlYWNoIHdvdWxkIGJlIHRlZGlvdXMgaW4gaXRzIG93biB3YXksIGFuZCB0aGlzIGlzIGp1c3QgYSBzaW5nbGUgdmFyaWFibGUuIFRoZXJlIGNvdWxkIGJlIHNldmVyYWwgc2V0cyBvZiB3aWRlIHNwYW5uaW5nIGNvbHVtbnMgdG8gY2FwdHVyZSB3aGF0IGNvdWxkIGJlIGNhcHR1cmVkIGluIGEgc2luZ2xlIHZhcmlhYmxlLiAgVGhlIGNvbmNlcHQgb2YgdGlkeSBkYXRhIGZvY3VzZXMgb24gbWluaW1pemluZyB0aGUgYW1vdW50IG9mIGNvbHVtbnMgaW4gZmF2b3VyIG9mIGZld2VyIGNvbHVtbnMgd2l0aCByaWNoIGFtb3VudHMgb2Ygb2JzZXJ2YXRpb25zLgoKIyMgTWFraW5nIGEgRGF0YXNldCBUaWR5CgpUaGUgW3RpZHlyXShodHRwczovL3RpZHlyLnRpZHl2ZXJzZS5vcmcvKSBwYWNrYWdlIGluIHRoZSBUaWR5dmVyc2Ugc3BlY2lhbGl6ZXMgaW4gbWFraW5nIGRhdGEgdGlkeS4KClRoZSBgc2VwZXJhdGVfbG9uZ2VyX2RlbGltKClgIGZ1bmN0aW9uIHNwZWNpYWxpemVzIGluIGRlYWxpbmcgd2l0aCB0aGUgbWVzc3kgdmFsdWVzIGluIG91ciBgcGxhdGZvcm1zYCBjb2x1bW4uCgpUaGUgYHRyaW1zd2AgZnVuY3Rpb24gaXMgdXNlZnVsIHRvIGFkZCB3aXRoIHRoZSBgc2VwZWFyYXRlX2xvbmdlcl9kZWxpbSgpYCBmdW5jdGlvbiwgYmVjYXVzZSBpdCByZW1vdmVzIGFsbCB0aGUgd2hpdGUgc3BhY2Ugc3Vycm91bmRpbmcgb24gZWl0aGVyIHNpZGUgb2YgYSB2YWx1ZSwgYXZvaWRpbmcgYW55IGNvbXBsaWNhdGlvbnMgdGhpcyBjb3VsZCBicmluZyB1cC4KCjo6OndhbGt0aHJvdWdoCgpMZXQncyBnaXZlIHRoaXMgYSB0cnkhCgpgYGB7cn0Kc3VydmV5X2RhdGFfbG9uZyA8LSBzdXJ2ZXlfZGF0YSB8PgogIHNlcGFyYXRlX2xvbmdlcl9kZWxpbShjb2xzID0gcGxhdGZvcm1zLCBkZWxpbSA9ICIsIikgfD4gCiAgbXV0YXRlKHBsYXRmb3JtcyA9IHRyaW13cyhwbGF0Zm9ybXMpKSAKYGBgCgoqKlN0ZXAtYnktc3RlcCBleHBsYW5hdGlvbioqCgoxKSBXZSBzdGFydCBvZmYgYnkgY3JlYXRpbmcgYSBuZXcgciBvYmplY3QgY2FsbGVkIGBzdXJ2ZXlfZGF0YV9sb25nYCwgd2hpY2ggaXMgZ29pbmcgdG8gdGFrZSBvbiBhbGwgdGhlIGluZm9ybWF0aW9uIHRoYXQgaXMgcGFzc2VkIHRvIGl0IGZyb20gdGhlIHJpZ2h0IHNpZGUgb2YgdGhlIGFzc2lnbm1lbnQgb3BlcmF0b3IgYDwtYC4KMikgVGhlIGBzdXJ2ZXlfZGF0YWAgb2JqZWN0IHJlcHJlc2VudHMgb3VyIGRhdGFzZXQgdGhhdCB3ZSB3YW50IHRvIHBhc3MgdGhyb3VnaCB0aGUgcGlwZSBgfD5gIHRvIG1hbmlwdWxhdGUgaXQuCjMpIFRoZSBgc2VwZWFyYXRlX2xvbmdlcl9kZWxpbWAgZnVuY3Rpb24gaXMgYXBwbGllZCB0byB0aGUgYHBsYXRmb3Jtc2AgY29sdW1uIHRvIGNyZWF0ZSBhIG5ldyByb3cgZm9yIGVhY2ggb2YgdGhlIHZhbHVlcyBpbiB0aGUgY2VsbCwgYW5kIGJlY2F1c2UgdGhlIHZhbHVlcyBzZXBhcmF0ZWQgYnkgY29tbWFzLCB0aGUgYGRlbGltID0gIiwiYCBmdW5jdGlvbiB0ZWxscyBSIHRvIHNlcGFyYXRlIGVhY2ggbmV3IHJvdyBhZnRlciBhIGNvbW1hLgo0KSBUaGUgZGF0YSBvYmplY3Qgd2l0aCB0aGUgc2VwYXJhdGUgcm93cyBpcyB0aGVuIHBpcGVkIGludG8gdGhlIG5leHQgZnVuY3Rpb24sIHdoaWNoIHVzZXMgdGhlIGBtdXRhdGVgIGZ1bmN0aW9uIHRvIHRlbGwgUiB0aGF0IHdlIHdhbnQgdG8gbW9kaWZ5IHRoZSBuZXdseSB1cGRhdGVkIGBwbGF0Zm9ybXNgIHZhbHVlcywgYW5kIHRoZSBgdHJpbXN3YCB0aGVuIHJlbW92ZXMgYW55IHdoaXRlc3BhY2Ugb24gZWl0aGVyIHNpZGUgb2YgdGhlIHZhbHVlcy4KNSkgRXQgdm9pbGEhCgo6OjoKCgpJZiB3ZSB0YWtlIGFub3RoZXIgbG9vayBhdCB0aGUgZGF0YXNldCwgeW91J2xsIHNlZSB0aGF0IHRoZSBgcGxhdGZvcm1zYCB2YXJpYWJsZSBub3cgaGFzIHNpbmdsZSBvYnNlcnZhdGlvbnMgaW4gZWFjaCBjZWxsLgoKIyMjIE1vcmUgVGlkeWluZwoKSW4gYWRkaXRpb24gdG8gdGhlIGBwbGF0Zm9ybXNgIHZhcmlhYmxlLCB0aGUgc3VydmV5IGNvbnRhaW5lZCB0d28gYWRkaXRpb25hbCBtdWx0aXBsZS1jaG9pY2UgcXVlc3Rpb25zOgoKKiAiUGxlYXNlIGluZGljYXRlIGhvdyBtdWNoIHlvdSBhZ3JlZSBvciBkaXNhZ3JlZSB3aXRoIHRoZSBmb2xsb3dpbmcgc3RhdGVtZW50cyBhYm91dCBzb2NpYWwgbWVkaWEgYW5kIHlvdXIgbWVudGFsIGhlYWx0aDoiCgoqICJSYW5rIHRoZSBmb2xsb3dpbmcgcmVhc29ucyBmb3IgdXNpbmcgc29jaWFsIG1lZGlhIGluIG9yZGVyIG9mIGltcG9ydGFuY2UgdG8geW91ICgxID0gbW9zdCBpbXBvcnRhbnQsIDUgPSBsZWFzdCBpbXBvcnRhbnQpOiIKCllvdSdsbCBub3RpY2UgdGhhdCBlYWNoIG9mIHRoZXNlIHF1ZXN0aW9ucyBjcmVhdGUgY3JlYXRlIDQgYW5kIDUgY29sdW1ucywgcmVzcGVjdGl2ZWx5LCB0byBjYXB0dXJlIHRoZSByZXNwb25zZXMuICBUaGlzIGlzbid0IG5lY2Vzc2FyaWx5IGEgYmFkIHRoaW5nLCBidXQgaW4gdGhlIHNwaXJpdCBvZiBtYWtpbmcgb3VyIGRhdGEgdGlkeSwgbGV0J3Mgc2VlIHRyeSB0byByZWR1Y2UgdGhlIGFtb3VudCBvZiB2YXJpYWJsZXMgdG8gcmVwcmVzZW50IHRoZXNlIHZhbHVlcy4KCjo6OnF1ZXN0aW9uCgpUYWtlIGEgbG9vayBhdCB0aGUgZGF0YXNldCwgZm9jdXNpbmcgb24gdGhlIHZhcmlhYmxlcyB0aGF0IGJlZ2luIHdpdGggYGZlZWwtYCBhbmQgYHVzYWdlLWAsIGFuZCB0aGluayBhYm91dCBob3cgeW91IG1pZ2h0IG1ha2UgdGhlc2UgdmFyaWFibGVzIHRpZHkuCgo6OjoKClRoZXNlIHZhcmlhYmxlcyBhcmUgYSBiaXQgdHJpY2tpZXIgdG8gY29uY2VwdHVhbGl6ZSB0aGFuIHRoZSBwbGF0Zm9ybXMgdmFyaWFibGUsIGJ1dCBSIGhhcyBhIGZ1bmN0aW9uIHRoYXQgaXMgZGVzaWduZWQgdG8gaGFuZGxlIHRoaW5ncyBsaWtlIHRoaXMsIGFuZCB3aWxsIGhvcGVmdWxseSBtYWtlIHNlbnNlIHdoZW4geW91IHNlZSBpdCEKCjo6OndhbGt0aHJvdWdoCgpIZXJlJ3MgdGhlIGNvZGUgdG8gZG8gdGhpczoKCmBgYHtyfQpzdXJ2ZXlfZGF0YV9sb25nZXIgPC0gc3VydmV5X2RhdGFfbG9uZyB8PgogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSBzdGFydHNfd2l0aCgiZmVlbF8iKSwKICAgIG5hbWVzX3RvID0gImZlZWxfcXVlc3Rpb24iLAogICAgdmFsdWVzX3RvID0gImZlZWxfcmVzcG9uc2UiCiAgKQpgYGAKCioqU3RlcC1ieS1zdGVwIGV4cGxhbmF0aW9uOioqCgoxKSBXZSBzdGFydCBieSB3cml0aW5nIGEgbmV3IHIgb2JqZWN0IGNhbGxlZCBgc3VydmV5X2RhdGFfbG9uZ2VyYCwgdGhhdCB3aWxsIGhvbGQgZXZlcnl0aGluZyB0byB0aGUgbGVmdCBvZiB0aGUgYXNzaWdubWVudCBvcGVyYXRvciBgfD5gLgoyKSBUaGUgYHN1cnZleV9kYXRhX2xvbmdgIG9iamVjdCByZXByZXNlbnRzIG91ciBkYXRhc2V0IHRoYXQgd2Ugd2FudCB0byBwYXNzIHRocm91Z2ggdGhlIHBpcGUgYHw+YCB0byBtYW5pcHVsYXRlIGl0LgozKSBUaGUgYHBpdm90X2xvbmdlcigpYCBmdW5jdGlvbiByZXNoYXBlcyB0aGUgZGF0YSBmcm9tIHdpZGUgdG8gbG9uZy4gIEluIHRoaXMgY2FzZSB3ZSBoYWQgc2V2ZXJhbCB2YXJpYWJsZXMgdGhhdCBzdGFydGVkIHdpdGggYGZlZWwtYCwgYW5kIHRoaXMgZnVuY3Rpb24gd2lsbCBnYXRoZXIgdGhlbSBpbnRvIHR3byBjb2x1bW5zOiBvbmUgZm9yIHRoZSBxdWVzdGlvbiBuYW1lIGFuZCBvbmUgZm9yIHRoZSByZXNwb25zZSB2YWx1ZS4KNCkgVGhlIGBjb2xzID0gc3RhcnRzX3dpdGgoImZlZWwtIilgIGZ1bmN0aW9uIHRlbGxzIGBwaXZvdF9sb25nZXJgIHdoaWNoIGNvbHVtbnMgdG8gZ2F0aGVyLiAoWW91IGNhbiBzZWUgd2h5IHZhcmlhYmxlIG5hbWluZyBjYW4gaGVscCB3aXRoIGRhdGEgY2xlYW5pbmchKQo1KSBgbmFtZXNfdG8gPSAiZmVlbF9xdWVzdGlvbiJgIG5hbWVzIG9mIHRoZSBuZXcgY29sdW1uIHRoYXQgd2lsbCAqKmhvbGQgdGhlIG9yaWdpbmFsIGNvbHVtbiBuYW1lcyoqIChpZS4gdGhlIHF1ZXN0aW9uIGlkZW50aWZpZXJzLiAgVGhlIG5ldyBjb2x1bW4gd2lsbCBiZSBjYWxsZWQgYGZlZWxfcXVlc3Rpb25gLgo2KSBgdmFsdWVzX3RvYCAiZmVlbF9yZXNwb25zZSIgbmFtZXMgdGhlIG5ldyBjb2x1bW4gdGhhdCB3aWxsICoqaG9sZCB0aGUgdmFsdWVzIChhbnN3ZXJzKSB0aGF0IHVzZWQgdG8gc2l0IGluIHRoZSBgZmVlbC1gIGNvbHVtbnMqKi4gIFRoZSBuZXcgY29sdW1uIHdpbGwgYmUgY2FsbGVkIGBmZWVsX3Jlc3BvbnNlYC4KNykgQ2xvc2UgdGhlIGJyYWNrZXQsIGFuZCB0YWtlIGEgbG9vayB0byBzZWUgd2hhdCB0aGUgZGF0YSBsb29rcyBsaWtlLgoKOjo6CgojIyBZb3VyIFR1cm4hCgo6OjogcXVlc3Rpb24KCk5vdyB0aGF0IHlvdSd2ZSBzZWVuIGhvdyB0aGUgYHBpdm90X2xvbmcoKWAgZnVuY3Rpb24gd29ya3MsIHNlZSBpZiB5b3UgY2FuIGNyZWF0ZSBhIG5ldyBvYmplY3QgY2FsbGVkIGBzdXJ2ZXlfZGF0YV90aWR5YCwgdGhhdCBsZW5naHRoZW4gdGhlIGB1c2FnZS1gIGNvbHVtbnMganVzdCBhcyB3ZSBkaWQgd2l0aCB0aGUgYGZlZWwtYCBjb2x1bW5zLgoKSGludDogVGhlIHN5bnRheCBpcyBleGFjdGx5IHRoZSBzYW1lIGFzIHRoZSBleGFtcGxlIGFib3ZlLCB5b3UganVzdCBuZWVkIHRvIGNoYW5nZSB0aGUgdmFsdWVzIGluIHF1b3RhdGlvbnMgYCIiYC4KCmBgYHtyLCBjbGFzcy5zb3VyY2UgPSAnZm9sZC1oaWRlJywgZXZhbCA9IEZBTFNFfQpzdXJ2ZXlfZGF0YV90aWR5IDwtIHN1cnZleV9kYXRhX2xvbmdlciB8PgogIHBpdm90X2xvbmdlcigKICBjb2xzID0gc3RhcnRzX3dpdGgoInVzYWdlXyIpLAogIG5hbWVzX3RvID0gInVzYWdlX3F1ZXN0aW9uIiwKICB2YWx1ZXNfdG8gPSAidXNhZ2VfcmVzcG9uc2UiCikKYGBgCgo6OjoKClRha2UgYSBsb29rIGF0IHRoZSBkYXRhOgoKYGBge3IsIGV2YWw9RkFMU0V9ClZpZXcoc3VydmV5X2RhdGFfdGlkeSkKYGBgCgpJdCBsb29rcyBwcmV0dHkgd2VpcmQhICBBcyBtZW50aW9uZWQsIHRpZHkgZGF0YSBpcyB2ZXJ5IGhhcmQgdG8gc2NhbiBmb3IgYSBodW1hbiwgYnV0IHJlYWxseSBlYXN5IGZvciBSIHRvIHNjYW4uIFlvdSBtaWdodCBub3RpY2UgdGhhdCB0aGVyZSdzIG92ZXIgMjYsMDAwIHJvd3MsIHdoaWNoIG1heSBzZWVtIG92ZXJ3aGVsbWluZyBhbmQgdW5uZWNlc3NhcnkuICBUaGUgVGlkeSBEYXRhIFByaW5jaXBsZXMgYXJlIHZlcnkgbXVjaCBnZWFyZWQgdG93YXJkcyB1c2luZyBSLCBhbmQgdGhlcmUgYXJlIHRpbWVzIHdoZW4gbWFraW5nIHlvdXIgZGF0YSBjb21wbGV0ZWx5IHRpZHkgbWlnaHQgbm90IHN1aXRlIHlvdXIgcHVycG9zZS4gIEhvd2V2ZXIsIHRoZSBwdXJwb3NlIG9mIHRoZSBleGVyY2lzZSB3YXMgdG8gZ2V0IHlvdSB0byB0aGluayBhYm91dCBob3cgeW91IG1pZ2h0IHdhbnQgb3IgbmVlZCB0byBzdHJ1Y3R1cmUgeW91ciBkYXRhLCBhbmQgeW91IG5vdyBoYXZlIGNvZGUgdGhhdCB5b3UgY2FuIGVhc2lseSBhZGFwdCB0byBwbGF5IHdpdGggeW91ciBzdXJ2ZXlzLgoKCiMjIyBTYXZlIGEgY29weSBvZiB0aGUgZGF0YQoKTm93IHRoYXQgd2UndmUgZnVsbHkgdGlkaWVkIG91ciBkYXRhc2V0LCBzYXZlIGEgY29weSBvZiBpdDoKCmBgYHtyLCBldmFsPUZBTFNFfQp3cml0ZV9jc3Yoc3VydmV5X2RhdGFfdGlkeSwgInN1cnZleV9kYXRhX3RpZHkuY3N2IikKYGBgCgojIyBNYWtpbmcgZGF0YSB3aWRlCgpBcyBtZW50aW9uZWQsIHRoZXJlIGFyZSBwcm9zIGFuZCBjb25zIHRvIG1ha2luZyBkYXRhIHdpZGUgYW5kIGxvbmcuIFRoZSBiZW5lZml0IG9mIGNyZWF0aW5nIGEgd2lkZXIgc3RydWN0dXJlIGlzIHRoYXQgaXQgZWFzaWVyIGZvciBodW1hbiBleWVzIHRvIHNjYW4gYW5kIGNyZWF0aW5nIGJhc2ljIHN1bW1hcnkgdGFibGVzLiAgCgpJZiB3ZSByZXZpc2l0IHRoZSBSIG9iamVjdCBgc3VydmV5X2RhdGFgLCB3aGljaCB3YXMgc2F2ZWQgYXMgdGhlIGBzdXJ2ZXktZGF0YV9jbGVhbi1jb2xzX25vLUlELmNzdmAgZmlsZSwgd2UgY2FuIHN0ZXAgYmFjayB0byBhIHN0YWdlIGluIHdoaWNoIHRoZSBgcGxhdGZvcm1zYCB2YXJpYWJsZSB3YXMgc3RpbGwgcXVpdGUgbWVzc3kuCgoKYGBge3IsIGV2YWw9RkFMU0V9ClZpZXcoc3VydmV5X2RhdGEpCmBgYAoKSW5zdGVhZCBvZiBjcmVhdGluZyBhIG5ldyByb3cgZm9yIGVhY2ggb2YgdGhlIHBsYXRmb3JtcyB2aWEgdGhlIFRpZHkgRGF0YSBQcmluY2lwbGVzLCB3ZSBjYW4gbWFrZSB0aGUgZGF0YSB3aWRlciBhbmQgY3JlYXRlIGEgbmV3IGNvbHVtbiBmb3IgZWFjaCBvZiB0aGUgcGxhdGZvcm1zLgoKOjo6d2Fsa3Rocm91Z2gKCkhlcmUncyBob3cgdG8gZG8gdGhpczoKCmBgYHtyfQpzdXJ2ZXlfZGF0YV93aWRlIDwtIHN1cnZleV9kYXRhIHw+CiAgbXV0YXRlKHBsYXRmb3JtcyA9IHN0cnNwbGl0KHBsYXRmb3JtcywgIiwiKSkgfD4KICB1bm5lc3RfbG9uZ2VyKHBsYXRmb3JtcykgfD4KICBtdXRhdGUocGxhdGZvcm1zID0gdHJpbXdzKHBsYXRmb3JtcyksIHByZXNlbnQgPSAxKSB8PgogIHBpdm90X3dpZGVyKAogICAgbmFtZXNfZnJvbSA9IHBsYXRmb3JtcywKICAgIHZhbHVlc19mcm9tID0gcHJlc2VudCwKICAgIHZhbHVlc19maWxsID0gMAogICkKYGBgCgoqKlN0ZXAtYnktc3RlcCBleHBsYW5hdGlvbjoqKgoKMSkgV2Ugc3RhcnQgYnkgd3JpdGluZyBhIG5ldyByIG9iamVjdCBjYWxsZWQgYHN1cnZleV9kYXRhX3dpZGVgLCB0aGF0IHdpbGwgaG9sZCBldmVyeXRoaW5nIHRvIHRoZSBsZWZ0IG9mIHRoZSBhc3NpZ25tZW50IG9wZXJhdG9yIGB8PmAuCjIpIFRoZSBgc3VydmV5X2RhdGFgIG9iamVjdCByZXByZXNlbnRzIG91ciBkYXRhc2V0IHRoYXQgd2Ugd2FudCB0byBwYXNzIHRocm91Z2ggdGhlIHBpcGUgYHw+YCB0byBtYW5pcHVsYXRlIGl0LgozKSBUaGUgYG11dGF0ZWAgZnVuY3Rpb24gaXMgdXNlZCB0byBtb2RpZnkgYSBjb2x1bW4sIHdoaWNoIGlzIGFwcGxpZWQgdG8gdGhlIGBzdHJzcGxpdChwbGF0Zm9ybXMsICIsIilgIGZ1bmN0aW9uLCB0byB0ZWxsIGl0IHRvIHNwbGl0IHRoZSBjb21tYS1zZXBhcmF0ZWQgc3RyaW5ncyBpbiB0aGUgYHBsYXRmb3Jtc2AgY29sdW1uIGludG8gbGlzdHMgb2YgaW5kaXZpZHVhbCBwbGF0Zm9ybSBuYW1lcy4KNCkgV2UgdGhlbiBwaXBlIGB8PmAgdGhpcyBpbnRvIHRoZSBgdW5uZXN0X2xvbmdlcihwbGF0Zm9ybXMpYCBmdW5jdGlvbiB0byBleHBhbmQgZWFjaCBlbGVtZW50IGludG8gaXRzIG93biByb3cgKHdoaWNoIGlzIGxpa2UgbWFraW5nIHRoZSBkYXRhIGxvbmdlcikuIEF0IHRoaXMgcG9pbnQsIG5ldyByb3dzIG9ubHkgZXhpc3RzIGZvciB0aG9zZSB0aGF0IHNlbGVjdGVkIGEgcGxhdGZvcm0uCjUpIFRoaXMgaXMgdGhlbiBwaXBlZCBgfD5gIGludG8gYG11dGF0ZShwbGF0Zm9ybXMgPSB0cmltd3MocGxhdGZvcm1zKWAgd2hpY2ggY29udGludWVzIHRvIG1hbmlwdWxhdGUgdGhlIGBwbGF0Zm9ybXNgIGNvbHVtbiwgYW5kIG11Y2ggbGlrZSB3ZSBkaWQgd2hlbiBtYWtpbmcgdGhpcyB2YXJpYWJsZSBsb25nLCB0aGUgYHRyaW1zd2AgcmVtb3ZlcyB3aGl0ZSBzcGFjZSBzdXJyb3VuZGluZyB0aGUgdmFsdWVzLgo2KSBUaGUgYHByZXNlbnQgPSAxYCBmdW5jdGlvbiBjcmVhdGVzIGEgbmV3IGNvbHVtbiBjYWxsZWQgYHByZXNlbnRgIHRoYXQgYXBwbGllcyBhIHZhbHVlIG9mIDEgZm9yIGV2ZXJ5IHJvdy4gVGhpcyBpcyBhIHRlbXBvcmFyeSBjb2x1bW4gdG8gaGVscCBmYWNpbGl0YXRlIHRoZSBuZXh0IHN0ZXAuCjcpIFVzaW5nIGFub3RoZXIgcGlwZSBgfD5gLCB0aGlzIGluZm9ybWF0aW9uIGdvZXMgaW50byB0aGUgYHBpdm90X3dpZGVyYCBmdW5jdGlvbiwgdGhhdCB3b3JrcyB3aXRoIGEgdmVyeSBzaW1pbGFyIHN5bnRheCBhcyBgcGl2b3RfbG9uZ2VyYCB0aGF0IHdlIHVzZWQgZWFybGllciwgYnV0IGluc3RlYWQgb2YgbWFraW5nIHRoZSBkYXRhIGxvbmdlciwgaXQgaW5pdGlhdGVzIGRhdGEgd2lkZW5pbmcuIAo4KSBgbmFtZXNfZnJvbSA9IHBsYXRmb3Jtc2AgYXNzaWducyBuZXcgY29sdW1ucyB0byB0aGUgdW5pcXVlIHBsYXRmb3JtIG5hbWVzLgo5KSBgdmFsdWVzX2Zyb20gPSBwcmVzZW50YCBhc3NpZ25zIHZhbHVlcyBpbiB0aGUgbmV3IGNvbHVtbnMgdG8gY29tZSBmcm9tIHRoZSBgcHJlc2VudGAgY29sdW1uLCB3aGljaCBpcyBgMWAuCjEwKSBGaW5hbGx5LCB3aXRoIGB2YWx1ZXNfZmlsbCA9IDBgLCBpZiBhIHBsYXRmb3JtIHdhc24ndCBwcmVzZW50IGZvciBhIHN1cnZleSBlbnRyeSwgdGhhdCBjb2x1bW4gd2lsbCBnZXQgdGhlIHZhbHVlIG9mIGAwYC4KClRoaXMgd2lsbCBlbmQgdXAgd2l0aCBhIHdpZGUgZGF0YXNldCB3aGVyZSBlYWNoIHJvdyBpcyBhIHN1cnZleSBlbnRyeSwgZWFjaCBwbGF0Zm9ybSBpcyBhIGNvbHVtbiwgYW5kIHRoZSB2YWx1ZSBgMWAgbWVhbnMgYSBwbGF0Zm9ybSB3YXMgbGlzdGVkLCBhbmQgYDBgIG1lYW5zIGEgcGxhdGZvcm0gd2FzIG5vdCBsaXN0ZWQuCgo6OjoKCiMjIyBTYXZlIGEgY29weSBvZiB0aGUgZGF0YQoKTGV0J3Mgc2F2ZSBhIGNvcHkgb2YgdGhpcyBkYXRhc2V0LCBhbmQgd2UnbGwgYmUgdGFraW5nIGEgbG9vayBhdCBpdCBpbiB0aGUgbmV4dCBzZWN0aW9uLgoKYGBge3IsIGV2YWw9RkFMU0V9CndyaXRlX2NzdihzdXJ2ZXlfZGF0YV93aWRlLCAic3VydmV5X2RhdGFfd2lkZS5jc3YiKQpgYGAKCiMjIyBTYXZlIHlvdXIgc2NyaXB0CgpCZWZvcmUgd2Ugd3JhcCB1cCwgd2Ugd2FudCB0byBzYXZlIG91ciBzY3JpcHQuIFlvdSBjYW4gZG8gdGhpcyBieSBjbGlja2luZyBgZmlsZSA+IFNhdmUgQXMuLi5gLiBCZWNhdXNlIHdlIHNldCB1cCBhbiBSUHJvamVjdCwgUiBzaG91bGQgYXV0b21hdGljYWxseSBjaG9vc2UgdGhlIGNvcnJlY3QgZGlyZWN0b3J5IHRvIHNhdmUgeW91ciBzY3JpcHQuCgpMZXQncyBzYXZlIHRoZSBzY3JpcHQgYXMgYHN1cnZleV9jbGVhbmluZ19zY3JpcHQuUmAKCiMjIEZpbGUgTWFuYWdlbWVudAoKV2l0aCBqdXN0IGEgZmV3IHN0ZXBzIG9mIGRhdGEgY2xlYW5pbmcsIHdlIG5vdyBoYXZlIDYgZGF0YSBmaWxlcyBpbiBvdXIgZm9sZGVyOgoKLSBgc29jaWFsLW1lZGlhLXN1cnZleV9PUklHSU5BTC5jc3ZgCi0gYHNvY2lhbC1tZWRpYS1zdXJ2ZXkuY3N2YAotIGBzdXJ2ZXlfZGF0YV90aWR5LmNzdmAKLSBgc3VydmV5X2RhdGFfd2lkZS5jc3ZgCi0gYHN1cnZleV9kYXRhLlJwcm9qYAotIGBzdXJ2ZXlfY2xlYW5pbmdfc2NyaXB0LlJgCi0gYHN1cnZleS1kYXRhX2NsZWFuLWNvbHNfSURzLmNzdmAKLSBgc3VydmV5LWRhdGFfY2xlYW4tY29sc19uby1JRC5jc3ZgCgoKVGhlc2UgbmFtZXMgYXJlbid0IG5lY2Vzc2FyaWx5IGJhZCwgYnV0IHlvdSBjYW4gc2VlIHRoYXQgdGhlcmUgYXJlIHNvbWUgaW5jb25zaXN0ZW5jaWVzIHdpdGggdGhlIG5hbWluZyBwcmVmaXggYHNvY2lhbC1tZWRpYS1zdXJ2ZXlgIHZzIGBzdXJ2ZXktZGF0YWAsIGFuZCBzb21lIG9mIHRoZSBkZXNjcmlwdG9ycywgYGNsZWFuLWNvbHNfSURzYCBhbmQgYGNsZWFuLWNvbHNfbm8tSURgIG1pZ2h0IG5vdCBiZSBhcyBldmlkZW50IGFzIHdlIG1pZ2h0IGxpa2UuICAKCkl0IGlzIGFsd2F5cyByZWNvbW1lbmRlZCB0byBkb2N1bWVudCBhbmQgZGVzY3JpYmUgeW91ciBmaWxlcyBhbmQgbmFtaW5nIGNvbnZlbnRpb24gaW4gYSBSRUFETUUgZmlsZSwgd2hpY2ggaXMgZGVzY3JpYmVkIGluIGRldGFpbHMgaW4gdGhlIFtEb2N1bWVudGF0aW9uIF0oQmxvY2syLTNfRG9jdW1lbnRhdGlvbi5odG1sKSBzZXNzaW9uLiBZb3UgY2FuIGFsc28gcmVmZXIgdG8gdGhlIFtPcmdhbml6aW5nIEZpbGVzIGFuZCBGb2xkZXJzXShCbG9jazItMV9GaWxlcy1hbmQtRm9sZGVycy5odG1sKSBzZXNzaW9uIGZvciBpbnNwaXJhdGlvbiBpbiBob3cgeW91IG1pZ2h0IGdvIGFib3V0IHJlbmFtaW5nIGFuZCBzdHJ1Y3R1cmluZyB0aGVzZSBmaWxlcy4KCgojIyBGaW5pc2gKCllvdSBoYXZlIG5vdyBzZWVuIHNvbWUgb2YgdGhlIGZvdW5kYXRpb25hbCBmdW5jdGlvbnMgdG8gY2xlYW4gc3VydmV5IGRhdGEsIGFuZCB0aGUgdmFyaW91cyB0eXBlcyBvZiBkYXRhIHRoYXQgYSBzdXJ2ZXkgbWlnaHQgY3JlYXRlLiBUaGUgZ29hbCBvZiB0aGlzIHNlc3Npb24gaXMgdG8gZ2l2ZSB5b3UgYSBzZW5zZSBvZiBob3cgdG8gYXBwcm9hY2ggeW91ciBvd24gc3VydmV5IGRhdGEsIGFuZCB0byBiZSBjb21mb3J0YWJsZSBlbm91Z2ggd2l0aCB0aGVzZSBjb2RlIGNodW5rcyB0aGF0IHlvdSBjYW4gc3dpdGNoIG91dCB0aGUgZGF0YS92YXJpYWJsZXMgZm9yIHlvdXIgb3duIHN1cnZleXMsIGFuZCB3b3JrIHRocm91Z2ggdGhlbSBpbiBxdWljayBhbmQgcmVwcm9kdWNpYmxlIHdheXMhCgoKCgo=