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:

How does social media usage influence the mental health of university students?

There could be a number of ways to address this question, but for the purpose of this course we’re going to focus on a fairly short survey as a way to get a sense managing this type of data.

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:

  1. Go to your Desktop folder
  2. Create a folder called social_media_project
  3. Move the file you just downloaded, called social-media-survey.csv to the social_media_project folder
  4. 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:

  1. 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.
  1. 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:

  1. Make the data long, or tidy, which aims to reduce columns but creates more rows.
  2. 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

  1. 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 <-.
  2. The survey_data object represents our dataset that we want to pass through the pipe |> to manipulate it.
  3. 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.
  4. 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.
  5. 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:

  1. We start by writing a new r object called survey_data_longer, that will hold everything to the left of the assignment operator |>.
  2. The survey_data_long object represents our dataset that we want to pass through the pipe |> to manipulate it.
  3. 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.
  4. The cols = starts_with("feel-") function tells pivot_longer which columns to gather. (You can see why variable naming can help with data cleaning!)
  5. 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.
  6. 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.
  7. 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:

  1. We start by writing a new r object called survey_data_wide, that will hold everything to the left of the assignment operator |>.
  2. The survey_data object represents our dataset that we want to pass through the pipe |> to manipulate it.
  3. 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.
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  8. names_from = platforms assigns new columns to the unique platform names.
  9. values_from = present assigns values in the new columns to come from the present column, which is 1.
  10. 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=