Introduction
In this module we’re going to cover some ways to improve your
workflow as you use R. As you develop your understanding of R and
proceed to do fancier things, you’ll want to start bringing in extra
features to make your life easier. When we think of a workflow there are
three main phases we undertake. At the very beginning we’re setting
ourselves up, establishing how things will be organised, and how we
intend to work. Second, we do the work - which involves testing and
adjusting the established systems, and lastly, we wrap things up.
Getting organised
In the first module we discussed creating a structure for your work
inside an RStudio project. For both analysis and programming projects it
is useful to have a pre-established ‘go-to’ template structure to keep
things organised.
An overarching principle is “keep similar things together”. For an
analysis project, this can mean the structure we first covered when
setting up an RStudio Project:
My_Project/
|- data/
|- docs/
|- output/
\- scripts/
Beyond the structure of where we put things, we also want to
establish the the principles of how the project will operate. Two
important files in this regard are the README and the LICENSE. The
README will tell yourself and others important details about the project
such as where the source data came from, or how to run the code in the
project (e.g. order of scripts). Secondly a LICENSE - this will become
important later on when code you have written may be released for others
to see (e.g. as part of a research paper) as it will set out the rules
under which people may use your code.
Licensing
When we’re dealing with research, by and large we’re operating in an
“open source” manner - i.e. the code that is used to perform the
research is shared alongside the results so that people can view it.
Just because the code is available doesn’t mean that people get to do
what they like with your code though.
It’s always a good practice to add a license to go along with your
code. A license is a document that lets people who come across the code
what they’re allowed to do with it, and what they’re not. There are many
open source licenses available and they vary in what behaviours they
permit or restrict. When choosing an open source licence there are 3
main questions you need to answer:
- Do you care about how any modifications that people make to the code
are distributed?
- Do you or your institution own any related software patents?
- Do you care about the way your name is or isn’t mentioned when
someone makes use of your code?
An extremely common license in research code/software is the MIT
license which is the simplest and most permissive, and essentially says
the code is “as is” without any warranties, and lets people use, copy,
modify, and distribute your code so long as the copyright notice goes
along with it (i.e. for attribution purposes). For help selecting an
appropriate license have a look at https://choosealicense.com.
The usethis
Package
The usethis
package is designed to assist in the creation of new packages and
setting up of new projects. It is is an extremely useful package for
several “workflow” tasks. It provides functions for many common workflow
tasks such as creating new projects, adding README files, or opening R
files.
usethis::create_project(path = "path/to/new/project")
usethis::use_readme_md()
usethis::use_readme_rmd()
usethis::use_r(name = "myfile.R")
On top of these, there are many other helper functions, such as for
creating various licenses, editing configurations, interacting with
version control software, or setting up automatic testing. All of which
we’ll touch on in this module.
Once you have chosen an appropriate license, usethis
likely has a template ready to go.
e.g. usethis::use_mit_license()
.
Configuration
As part of the set up stage, we’re also wanting to make things easier
on ourselves to that we can be more productive during the “do stuff”
stage.
There is a hidden file called .Rprofile which is loaded as R launches
and is a place where you can place customisations of options to make
your R life easier. For instance I have mine set to automatically load
workflow helper packages such as usethis
testthat
and devtools
. And set a few options
to make R produce more warnings so that it helps me know when something
might cause an issue. It’s also a good place to set some defaults such
as your favourite CRAN mirror so that R doesn’t need to ask you when you
go to install packages.
usethis::edit_r_profile()
if (interactive()) {
suppressMessages(require(devtools))
suppressMessages(require(usethis))
suppressMessages(require(testthat))
}
options(repos = c(CRAN = "https://cloud.r-project.org/"))
options(
warnPartialMatchArgs = TRUE,
warnPartialMatchDollar = TRUE,
warnPartialMatchAttr = TRUE
)
options(useFancyQuotes = FALSE)
Don’t put analysis modifying options into your .Rprofile
e.g. automatic loading of tidyverse
. It will make the code
you write less reproducible because it will start depending on these
hidden settings, and it can make debugging harder.
Keyboard shortcuts
The keyboard shortcut to rule them all: Alt +
Shift + K
Other useful shortcuts
Ctrl + Shift + M |
%>% |
Alt + - |
<- |
Ctrl + Shift + K |
knits Rmd |
Ctrl + Shift + F10 |
Restart R |
Ctrl + Alt + I |
Insert code chunk |
Ctrl + Shift + S |
Source active file |
Ctrl + . |
Go to file/function |
Make your own…
Tools -> Modify Keyboard Shortcuts
Scripts
Establish the structure of how you want to capture your code. Are you
going to do everything in Rscripts? RMarkdown? A combination? Create the
appropriate script files. It can be useful to have a separate Rscript
where you store functions that you create which can be ‘sourced’ into
your other scripts through source("scriptname.R)
.
Initialise Version Control
This section is a very brief overview of version control,
specifically to say that you should start to build it into your workflow
and we’ll touch on it again in the Automating Version
Control section but ultimately the details are outside of the scope
of this course.
You are likely familiar with versioning, usually people try to
achieve this through file names. This is ok to a point but can
cumbersome and doesn’t scale well across multiple files nor does it give
you an easy way to see exactly what the differences were between those
files. This is where using version control software such as
git
can make your life easier.
It’s always a good idea to get this set up before you get under way
doing actual work so that you can track you changes from the the very
start. In the case of git
, following Happy Git with R for installing and
configuring git
and subsequently telling RStudio about your
installation is a good place to start.
Once you have RStudio set up with git
, when you add
(initialise) version control onto your project you’ll get an new tab
appear and a hidden directory called .git
will be created
inside your project directory. A directory under version control is
called a ‘repository’ or ‘repo’.

Version control is used for keeping track of the changes made to your
scripts, we don’t usually use it to manage our data - since our initial
raw data isn’t going to be changing. For managing data, we use an
appropriate backup or archiving system.
Testing and Adjusting
Once things are set up, we’re ready to actually start doing the work
we want to do. As we develop our code however, we constantly cycle
through testing and adjusting. Each piece of code we write needs to be
checked that is is working correctly. Often this type of testing is
performed manually as you go: ‘does the line of code run?’ - checking
for syntax errors, and then ‘does the output look right?’. When the
answer to these either question is no, we then enter a debugging mode
where we try and find out why the code isn’t doing what we think it
should be.
Debugging
Errors messages are common when coding and are a way the computer
communicates it doesn’t understand what the instructions it has been
given are. Common types of errors we encounter are:
- syntactical
- logical
- runtime
Syntactical errors are usually the most straight forward, the
computer says that no straight away due to improper syntax. These are
usually the easiest to find and correct. Logical errors come about
through incorrect implementation of logic. The computer will run the
code without complaint but the result isn’t correct - these can be
tricky to find and fix because they often involve checking each logical
statement and subsequent code pathway in order to track down what is
going wrong. Runtime errors are errors where you are trying to make the
computer do something it can’t in certain situations, such as storing a
result in a certain location. The code will run sometimes but not others
and again can be tricky to track down.
Remember, each time we find and fix an error, we must retest. This
can get quite laborious to do manually so we can find better systems to
help such as automatic testing but first
we’ll cover some general principles on how to go about debugging.
Where do I start?
Knowing where to start debugging takes practice. some general good
advice can be found in https://adv-r.hadley.nz/debugging.html with some
specific tips and tricks for R. The general premise is that we want to
test and confirm all of our assumptions.
Finding your bug is a process of confirming the many things that you
believe are true — until you find one which is not true.
— Norm Matloff
Some techniques for solving errors and confirming our assumptions can
include:
- using print statements to confirm values at key stages
- googling the error message
- restart R and rerun the code
- reading the documentation
- talk through the problem

‘Rubber duck debugging’ is a technique which involves talking your
way through what you are trying to achieve with your code and explaining
what your code is actually doing at each step to a rubber duck (or other
toy). Often by being systematic and saying out loud what is happening
this will trigger an “a-ha” moment as to what is causing the issue. You
can also use this technique with another person e.g. co-worker instead
of a toy if you prefer.
General process
My general process focuses on the initial source of the error and
then starts to work backwards in command history.
- Do I recognise the message?
- Re-look at the command I ran looking for
- typos
- missing syntax (e.g. brackets, semicolons, etc.)
- correct naming of things
- Is the input for my command what I expect it is?
- Did the previous command run properly?
- if not jump to 1. for the previous command
Getting to know some errors
R is notorious for having messages that are not user friendly. Lets
look at a few common R errors and warnings so that we can become more
familiar with a) what they look like, b) how to find the useful bits
Anatomy of a message
- Usually the first word is “Error”, but sometimes it can be
“Warning”. Code that produces errors won’t run. Code that produces
warnings will run but is signifying that you should be extra careful
about the output because it might not be doing what you think it
is.
- Immediately following is the exact code that is producing the
error/warning. This tells you where to start looking.
- after the
:
gives the details about what the
error/warning actually is.
Caused by trying to access a variable that hasn’t been defined
yet.
Caused by using the subsetting brackets []
instead of
()
which are used for a function.
a <- c(one = 1,two = 2, three = 3)
a$one
You can’t use $
on an atomic vector, it’s used on
structures such as data.frames or lists.
Caused by trying to access an element at an index that doesn’t
exist.
Caused by providing a file name that R cannot find in the working
directory.
Caused by not having a ggplot
function either user
defined in the environment or not loaded a library that contains it
(ggplot2
or tidyverse
).
notapackage::notafunction()
Caused by trying to call a function from a package that doesn’t exist
is not be installed on the library path.
if(NA){
print("was NA")
}
if
requires the result to be TRUE or FALSE,
NA
isn’t a TRUE or FALSE.
if(c(3 > c(1,2,3))){
print("less than three")
}
if(c(1,2,3) > 3){
print("less than one")
}
if
requires a single TRUE or FALSE result, these
statements create multiple. In older versions of R this produced a
warning and not an error.
Caused by the a data type that doesn’t coerce into a numeric
automatically.
Adjusting
In the process of developing, it’s also important to take
opportunities to adjust how things are being done. Working code is
better than no code, but you create more code it’s also a good idea to
every so often look for opportunities to make things better - efficiency
or maintenance wise.
Code replication is a good place to start - if you’ve found yourself
copy and pasting the same code over in the same project, consider making
it into a function. This then gives you a single place that needs to be
changed. If you find yourself copy and pasting your functions across
projects, consider creating your own package.
RMarkdown driven dev
Emily Riederer has a great blog post about RMarkdown
driven development which describes a process of development using
RMarkdown documents, where first you get things to a working situation,
then go through rounds of tidying your document bringing like-to-like
with your code so that code blocks contain similar processes. As the
tidying is performed, it provides an opportunity to also reduce
duplication of code and increase the maintainability by converting
processes into functions.
Packages
If you find yourself copy and pasting function between documents, it
might be time to start creating your own package, that way you reduce
the number of individual places your function is defined and this makes
it easier in the future to maintain. Packages also bring in an extra
level of utility in that you can improve documentation and implement
automated testing so that you know when changes break functionality.
If you want to look further into how to create packages, check out
the R Packages online book
and you can use usethis::create_package()
to create a new
package from a template.
Automating
As you go about developing, there are two main things you will find
yourself doing over and over again - trying to remember what you have
changed, and making sure that any changes haven’t broken anything. These
processes can be quite time intensive so it’s quite useful to try and
automate the pieces that you can.
Automated testing
As you code and manually test, it can be beneficial to formalise the
manual tests into an automated solution so that you can be more
efficient and also ensure that you know when you ‘break things’ with
future changes. This is particularly useful when you fix bugs in your
code, create a test that replicates the condition that caused the
bug.
In R, one system uses the package testthat
which
provides a framework to create these formal tests which will evaluate a
piece of code against the known expected output and tell you if they
don’t match.
testthat::expect_equal(mean(c(1,2,3)), 2)
testthat
operates by setting up expectations and testing
if they hold true. If they are true the expectation function is silent,
if thy aren’t it will tell you when run. This lets you formalise tests
that you would be running manually and as you make adjustments to your
code you can rerun these tests to check things are still working.
Automating differences
Version control software is slightly different from what you might
have experienced with something like ‘track changes’ in Microsoft Word
which tracks all changes live.
In the case of git
, once you have everything set up and
configured there is a (simplified) mini-workflow which can be done after
clicking the ‘commit’ button in the git tab:

- Tell
git
you want it to track the changes on a
file
- Make some changes
- Tell
git
you want to include these changes in its
tracking
- click the ‘staged’ checkbox on the file in the git-commit
window
- Tell
git
to ‘snapshot’ your changes and include a
message about them
- write a message and click commit in the git - commit window
- go back to step 2.
Why would you do this workflow? For your future self. Every snapshot
you take with git
gives you a point in time that you can
roll back to if you wish - from a reproducibility point of view this
lets you run any version of your code at a snapshot.
git
can also let you see exactly what changes there were
between snapshots which can be extremely helpful for debugging
git
is a fairly complex piece of software and provides
more functionality than this, but for starting out this workflow covers
the main need and use case.
Finalise
Congratulations! You’ve made it to the end-stage of your project
where you’re ready to wrap things up and share your project with others.
What you do at this stage entirely depends on what output your project
was for. Perhaps it’s sending your entire project directory to your
lecturer or supervisor. Or this could involve uploading your version
controlled code to an online code repository such as https://github.com and publishing the url
in your paper or other output.
Regardless, embrace the completion. Then continue on to your next
project, bringing with you the skills you learnt on this one.
LS0tCnRpdGxlOiAiV29ya2Zsb3dzIgpkYXRlOiAiU2VtZXN0ZXIgMiwgMjAyMyIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKLS0tCiAgCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGNvbW1lbnQgPSAiIz4iLAogIGZpZy5wYXRoID0gImZpZ3VyZXMvMTAvIiwgIyB1c2Ugb25seSBmb3Igc2luZ2xlIFJtZCBmaWxlcwogIGNvbGxhcHNlID0gVFJVRSwKICBlY2hvID0gVFJVRQopCmBgYAoKPiAjIyMjIEFzc29jaWF0ZWQgTWF0ZXJpYWwKPgo+IFpvb20gTm90ZXM6IFtab29tIE5vdGVzIDEwIC0gV29ya2Zsb3dzXSh6b29tX25vdGVzXzEwX3dvcmtmbG93cy5odG1sKQoKCgoKCiMjIEludHJvZHVjdGlvbgoKSW4gdGhpcyBtb2R1bGUgd2UncmUgZ29pbmcgdG8gY292ZXIgc29tZSB3YXlzIHRvIGltcHJvdmUgeW91ciB3b3JrZmxvdyBhcyB5b3UgdXNlIFIuIEFzIHlvdSBkZXZlbG9wIHlvdXIgdW5kZXJzdGFuZGluZyBvZiBSIGFuZCBwcm9jZWVkIHRvIGRvIGZhbmNpZXIgdGhpbmdzLCB5b3UnbGwgd2FudCB0byBzdGFydCBicmluZ2luZyBpbiBleHRyYSBmZWF0dXJlcyB0byBtYWtlIHlvdXIgbGlmZSBlYXNpZXIuIFdoZW4gd2UgdGhpbmsgb2YgYSB3b3JrZmxvdyB0aGVyZSBhcmUgdGhyZWUgbWFpbiBwaGFzZXMgd2UgdW5kZXJ0YWtlLiBBdCB0aGUgdmVyeSBiZWdpbm5pbmcgd2UncmUgc2V0dGluZyBvdXJzZWx2ZXMgdXAsIGVzdGFibGlzaGluZyBob3cgdGhpbmdzIHdpbGwgYmUgb3JnYW5pc2VkLCBhbmQgaG93IHdlIGludGVuZCB0byB3b3JrLiBTZWNvbmQsIHdlIGRvIHRoZSB3b3JrIC0gd2hpY2ggaW52b2x2ZXMgdGVzdGluZyBhbmQgYWRqdXN0aW5nIHRoZSBlc3RhYmxpc2hlZCBzeXN0ZW1zLCBhbmQgbGFzdGx5LCB3ZSB3cmFwIHRoaW5ncyB1cC4KClwKCiMjIEdldHRpbmcgb3JnYW5pc2VkCgpJbiB0aGUgZmlyc3QgbW9kdWxlIHdlIGRpc2N1c3NlZCBjcmVhdGluZyBhIHN0cnVjdHVyZSBmb3IgeW91ciB3b3JrIGluc2lkZSBhbiBSU3R1ZGlvIHByb2plY3QuIEZvciBib3RoIGFuYWx5c2lzIGFuZCBwcm9ncmFtbWluZyBwcm9qZWN0cyBpdCBpcyB1c2VmdWwgdG8gaGF2ZSBhIHByZS1lc3RhYmxpc2hlZCAnZ28tdG8nIHRlbXBsYXRlIHN0cnVjdHVyZSB0byBrZWVwIHRoaW5ncyBvcmdhbmlzZWQuCgpBbiBvdmVyYXJjaGluZyBwcmluY2lwbGUgaXMgImtlZXAgc2ltaWxhciB0aGluZ3MgdG9nZXRoZXIiLiBGb3IgYW4gYW5hbHlzaXMgcHJvamVjdCwgdGhpcyBjYW4gbWVhbiB0aGUgc3RydWN0dXJlIHdlIGZpcnN0IGNvdmVyZWQgd2hlbiBzZXR0aW5nIHVwIGFuIFJTdHVkaW8gUHJvamVjdDoKCmBgYApNeV9Qcm9qZWN0LwogIHwtIGRhdGEvCiAgfC0gZG9jcy8KICB8LSBvdXRwdXQvCiAgXC0gc2NyaXB0cy8KYGBgCgpCZXlvbmQgdGhlIHN0cnVjdHVyZSBvZiB3aGVyZSB3ZSBwdXQgdGhpbmdzLCB3ZSBhbHNvIHdhbnQgdG8gZXN0YWJsaXNoIHRoZSB0aGUgcHJpbmNpcGxlcyBvZiBob3cgdGhlIHByb2plY3Qgd2lsbCBvcGVyYXRlLiBUd28gaW1wb3J0YW50IGZpbGVzIGluIHRoaXMgcmVnYXJkIGFyZSB0aGUgUkVBRE1FIGFuZCB0aGUgTElDRU5TRS4gVGhlIFJFQURNRSB3aWxsIHRlbGwgeW91cnNlbGYgYW5kIG90aGVycyBpbXBvcnRhbnQgZGV0YWlscyBhYm91dCB0aGUgcHJvamVjdCBzdWNoIGFzIHdoZXJlIHRoZSBzb3VyY2UgZGF0YSBjYW1lIGZyb20sIG9yIGhvdyB0byBydW4gdGhlIGNvZGUgaW4gdGhlIHByb2plY3QgKGUuZy4gb3JkZXIgb2Ygc2NyaXB0cykuIFNlY29uZGx5IGEgTElDRU5TRSAtIHRoaXMgd2lsbCBiZWNvbWUgaW1wb3J0YW50IGxhdGVyIG9uIHdoZW4gY29kZSB5b3UgaGF2ZSB3cml0dGVuIG1heSBiZSByZWxlYXNlZCBmb3Igb3RoZXJzIHRvIHNlZSAoZS5nLiBhcyBwYXJ0IG9mIGEgcmVzZWFyY2ggcGFwZXIpIGFzIGl0IHdpbGwgc2V0IG91dCB0aGUgcnVsZXMgdW5kZXIgd2hpY2ggcGVvcGxlIG1heSB1c2UgeW91ciBjb2RlLgoKXAoKIyMjIExpY2Vuc2luZwoKV2hlbiB3ZSdyZSBkZWFsaW5nIHdpdGggcmVzZWFyY2gsIGJ5IGFuZCBsYXJnZSB3ZSdyZSBvcGVyYXRpbmcgaW4gYW4gIm9wZW4gc291cmNlIiBtYW5uZXIgLSBpLmUuIHRoZSBjb2RlIHRoYXQgaXMgdXNlZCB0byBwZXJmb3JtIHRoZSByZXNlYXJjaCBpcyBzaGFyZWQgYWxvbmdzaWRlIHRoZSByZXN1bHRzIHNvIHRoYXQgcGVvcGxlIGNhbiB2aWV3IGl0LiBKdXN0IGJlY2F1c2UgdGhlIGNvZGUgaXMgYXZhaWxhYmxlIGRvZXNuJ3QgbWVhbiB0aGF0IHBlb3BsZSBnZXQgdG8gZG8gd2hhdCB0aGV5IGxpa2Ugd2l0aCB5b3VyIGNvZGUgdGhvdWdoLiAKCkl0J3MgYWx3YXlzIGEgZ29vZCBwcmFjdGljZSB0byBhZGQgYSBsaWNlbnNlIHRvIGdvIGFsb25nIHdpdGggeW91ciBjb2RlLiBBIGxpY2Vuc2UgaXMgYSBkb2N1bWVudCB0aGF0IGxldHMgcGVvcGxlIHdobyBjb21lIGFjcm9zcyB0aGUgY29kZSB3aGF0IHRoZXkncmUgYWxsb3dlZCB0byBkbyB3aXRoIGl0LCBhbmQgd2hhdCB0aGV5J3JlIG5vdC4gVGhlcmUgYXJlIG1hbnkgb3BlbiBzb3VyY2UgbGljZW5zZXMgYXZhaWxhYmxlIGFuZCB0aGV5IHZhcnkgaW4gd2hhdCBiZWhhdmlvdXJzIHRoZXkgcGVybWl0IG9yIHJlc3RyaWN0LiBXaGVuIGNob29zaW5nIGFuIG9wZW4gc291cmNlIGxpY2VuY2UgdGhlcmUgYXJlIDMgbWFpbiBxdWVzdGlvbnMgeW91IG5lZWQgdG8gYW5zd2VyOgoKMS4gRG8geW91IGNhcmUgYWJvdXQgaG93IGFueSBtb2RpZmljYXRpb25zIHRoYXQgcGVvcGxlIG1ha2UgdG8gdGhlIGNvZGUgYXJlIGRpc3RyaWJ1dGVkPwoyLiBEbyB5b3Ugb3IgeW91ciBpbnN0aXR1dGlvbiBvd24gYW55IHJlbGF0ZWQgc29mdHdhcmUgcGF0ZW50cz8KMy4gRG8geW91IGNhcmUgYWJvdXQgdGhlIHdheSB5b3VyIG5hbWUgaXMgb3IgaXNuJ3QgbWVudGlvbmVkIHdoZW4gc29tZW9uZSBtYWtlcyB1c2Ugb2YgeW91ciBjb2RlPwoKQW4gZXh0cmVtZWx5IGNvbW1vbiBsaWNlbnNlIGluIHJlc2VhcmNoIGNvZGUvc29mdHdhcmUgaXMgdGhlIE1JVCBsaWNlbnNlIHdoaWNoIGlzIHRoZSBzaW1wbGVzdCBhbmQgbW9zdCBwZXJtaXNzaXZlLCBhbmQgZXNzZW50aWFsbHkgc2F5cyB0aGUgY29kZSBpcyAiYXMgaXMiIHdpdGhvdXQgYW55IHdhcnJhbnRpZXMsIGFuZCBsZXRzIHBlb3BsZSB1c2UsIGNvcHksIG1vZGlmeSwgYW5kIGRpc3RyaWJ1dGUgeW91ciBjb2RlIHNvIGxvbmcgYXMgdGhlIGNvcHlyaWdodCBub3RpY2UgZ29lcyBhbG9uZyB3aXRoIGl0IChpLmUuIGZvciBhdHRyaWJ1dGlvbiBwdXJwb3NlcykuIEZvciBoZWxwIHNlbGVjdGluZyBhbiBhcHByb3ByaWF0ZSBsaWNlbnNlIGhhdmUgYSBsb29rIGF0IFtodHRwczovL2Nob29zZWFsaWNlbnNlLmNvbV0oaHR0cHM6Ly9jaG9vc2VhbGljZW5zZS5jb20pLgoKXAoKIyMjIFRoZSBgdXNldGhpc2AgUGFja2FnZQoKVGhlIFtgdXNldGhpc2BdKGh0dHBzOi8vdXNldGhpcy5yLWxpYi5vcmcpIHBhY2thZ2UgaXMgZGVzaWduZWQgdG8gYXNzaXN0IGluIHRoZSBjcmVhdGlvbiBvZiBuZXcgcGFja2FnZXMgYW5kIHNldHRpbmcgdXAgb2YgbmV3IHByb2plY3RzLiBJdCBpcyBpcyBhbiBleHRyZW1lbHkgdXNlZnVsIHBhY2thZ2UgZm9yIHNldmVyYWwgIndvcmtmbG93IiB0YXNrcy4gSXQgcHJvdmlkZXMgZnVuY3Rpb25zIGZvciBtYW55IGNvbW1vbiB3b3JrZmxvdyB0YXNrcyBzdWNoIGFzIGNyZWF0aW5nIG5ldyBwcm9qZWN0cywgYWRkaW5nIFJFQURNRSBmaWxlcywgb3Igb3BlbmluZyBSIGZpbGVzLiAKCmBgYHtyLCBldmFsID0gRkFMU0V9CiMgQ3JlYXRlIGFuZCBvcGVuIGEgbmV3IHBhY2thZ2UKdXNldGhpczo6Y3JlYXRlX3Byb2plY3QocGF0aCA9ICJwYXRoL3RvL25ldy9wcm9qZWN0IikKCiMgQ3JlYXRlIGEgbWFya2Rvd24gUkVBRE1FCnVzZXRoaXM6OnVzZV9yZWFkbWVfbWQoKQoKIyBDcmVhdGUgYW4gUk1hcmtkb3duIFJFQURNRQp1c2V0aGlzOjp1c2VfcmVhZG1lX3JtZCgpCgojIENyZWF0ZSBhIG5ldyBSIHNjcmlwdCBpbiB5b3VyIHByb2plY3QgaW4gZGlyZWN0b3J5IFIvCnVzZXRoaXM6OnVzZV9yKG5hbWUgPSAibXlmaWxlLlIiKQoKYGBgCgpPbiB0b3Agb2YgdGhlc2UsIHRoZXJlIGFyZSBtYW55IG90aGVyIGhlbHBlciBmdW5jdGlvbnMsIHN1Y2ggYXMgZm9yIGNyZWF0aW5nIHZhcmlvdXMgbGljZW5zZXMsIGVkaXRpbmcgY29uZmlndXJhdGlvbnMsIGludGVyYWN0aW5nIHdpdGggdmVyc2lvbiBjb250cm9sIHNvZnR3YXJlLCBvciBzZXR0aW5nIHVwIGF1dG9tYXRpYyB0ZXN0aW5nLiBBbGwgb2Ygd2hpY2ggd2UnbGwgdG91Y2ggb24gaW4gdGhpcyBtb2R1bGUuCgpPbmNlIHlvdSBoYXZlIGNob3NlbiBhbiBhcHByb3ByaWF0ZSBsaWNlbnNlLCBgdXNldGhpc2AgbGlrZWx5IGhhcyBhIHRlbXBsYXRlIHJlYWR5IHRvIGdvLiBlLmcuIGB1c2V0aGlzOjp1c2VfbWl0X2xpY2Vuc2UoKWAuCgpcCgojIyMgQ29uZmlndXJhdGlvbgoKQXMgcGFydCBvZiB0aGUgc2V0IHVwIHN0YWdlLCB3ZSdyZSBhbHNvIHdhbnRpbmcgdG8gbWFrZSB0aGluZ3MgZWFzaWVyIG9uIG91cnNlbHZlcyB0byB0aGF0IHdlIGNhbiBiZSBtb3JlIHByb2R1Y3RpdmUgZHVyaW5nIHRoZSAiZG8gc3R1ZmYiIHN0YWdlLgoKVGhlcmUgaXMgYSBoaWRkZW4gZmlsZSBjYWxsZWQgLlJwcm9maWxlIHdoaWNoIGlzIGxvYWRlZCBhcyBSIGxhdW5jaGVzIGFuZCBpcyBhIHBsYWNlIHdoZXJlIHlvdSBjYW4gcGxhY2UgY3VzdG9taXNhdGlvbnMgb2Ygb3B0aW9ucyB0byBtYWtlIHlvdXIgUiBsaWZlIGVhc2llci4gRm9yIGluc3RhbmNlIEkgaGF2ZSBtaW5lIHNldCB0byBhdXRvbWF0aWNhbGx5IGxvYWQgd29ya2Zsb3cgaGVscGVyIHBhY2thZ2VzIHN1Y2ggYXMgYHVzZXRoaXNgIGB0ZXN0dGhhdGAgYW5kIGBkZXZ0b29sc2AuIEFuZCBzZXQgYSBmZXcgb3B0aW9ucyB0byBtYWtlIFIgcHJvZHVjZSBtb3JlIHdhcm5pbmdzIHNvIHRoYXQgaXQgaGVscHMgbWUga25vdyB3aGVuIHNvbWV0aGluZyBtaWdodCBjYXVzZSBhbiBpc3N1ZS4gSXQncyBhbHNvIGEgZ29vZCBwbGFjZSB0byBzZXQgc29tZSBkZWZhdWx0cyBzdWNoIGFzIHlvdXIgZmF2b3VyaXRlIENSQU4gbWlycm9yIHNvIHRoYXQgUiBkb2Vzbid0IG5lZWQgdG8gYXNrIHlvdSB3aGVuIHlvdSBnbyB0byBpbnN0YWxsIHBhY2thZ2VzLgoKYGBge3IsIGV2YWw9RkFMU0V9CnVzZXRoaXM6OmVkaXRfcl9wcm9maWxlKCkKYGBgCgoKYGBge3IsIGV2YWw9RkFMU0V9CiAjIGxvYWQgd29ya2Zsb3cgaGVscGVyIHBhY2thZ2VzIGlmIGluIGludGVyYWN0aXZlIHNlc3Npb24KaWYgKGludGVyYWN0aXZlKCkpIHsKICBzdXBwcmVzc01lc3NhZ2VzKHJlcXVpcmUoZGV2dG9vbHMpKQogIHN1cHByZXNzTWVzc2FnZXMocmVxdWlyZSh1c2V0aGlzKSkKICBzdXBwcmVzc01lc3NhZ2VzKHJlcXVpcmUodGVzdHRoYXQpKQp9CgoKIyBzZXQgQ1JBTgpvcHRpb25zKHJlcG9zID0gYyhDUkFOID0gImh0dHBzOi8vY2xvdWQuci1wcm9qZWN0Lm9yZy8iKSkKCgojIHdhcm4gb24gcGFydGlhbCBtYXRjaGVzCm9wdGlvbnMoCiAgd2FyblBhcnRpYWxNYXRjaEFyZ3MgPSBUUlVFLAogIHdhcm5QYXJ0aWFsTWF0Y2hEb2xsYXIgPSBUUlVFLAogIHdhcm5QYXJ0aWFsTWF0Y2hBdHRyID0gVFJVRQopCgojIGZhbmN5IHF1b3RlcyBhcmUgYW5ub3lpbmcgYW5kIGxlYWQgdG8KIyAnY29weSArIHBhc3RlJyBidWdzIC8gZnJ1c3RyYXRpb25zCm9wdGlvbnModXNlRmFuY3lRdW90ZXMgPSBGQUxTRSkKYGBgCgpEb24ndCBwdXQgYW5hbHlzaXMgbW9kaWZ5aW5nIG9wdGlvbnMgaW50byB5b3VyIC5ScHJvZmlsZSBlLmcuIGF1dG9tYXRpYyBsb2FkaW5nIG9mIGB0aWR5dmVyc2VgLiBJdCB3aWxsIG1ha2UgdGhlIGNvZGUgeW91IHdyaXRlIGxlc3MgcmVwcm9kdWNpYmxlIGJlY2F1c2UgaXQgd2lsbCBzdGFydCBkZXBlbmRpbmcgb24gdGhlc2UgaGlkZGVuIHNldHRpbmdzLCBhbmQgaXQgY2FuIG1ha2UgZGVidWdnaW5nIGhhcmRlci4KClwKCiMjIyMgS2V5Ym9hcmQgc2hvcnRjdXRzCgpUaGUga2V5Ym9hcmQgc2hvcnRjdXQgdG8gcnVsZSB0aGVtIGFsbDogPGtiZD5BbHQ8L2tiZD4gKyA8a2JkPlNoaWZ0PC9rYmQ+ICsgPGtiZD5LPC9rYmQ+CgpPdGhlciB1c2VmdWwgc2hvcnRjdXRzCgpLZXlzIHwgcHJvZHVjZXMKLS0tfC0tLQo8a2JkPkN0cmw8L2tiZD4gKyA8a2JkPlNoaWZ0PC9rYmQ+ICsgPGtiZD5NPC9rYmQ+IHwgJT4lCjxrYmQ+QWx0PC9rYmQ+ICsgPGtiZD4tPC9rYmQ+IHwgPC0KPGtiZD5DdHJsPC9rYmQ+ICsgPGtiZD5TaGlmdDwva2JkPiArIDxrYmQ+Szwva2JkPiB8IGtuaXRzIFJtZAo8a2JkPkN0cmw8L2tiZD4gKyA8a2JkPlNoaWZ0PC9rYmQ+ICsgPGtiZD5GMTA8L2tiZD4gfCBSZXN0YXJ0IFIKPGtiZD5DdHJsPC9rYmQ+ICsgPGtiZD5BbHQ8L2tiZD4gKyA8a2JkPkk8L2tiZD4gfCBJbnNlcnQgY29kZSBjaHVuawo8a2JkPkN0cmw8L2tiZD4gKyA8a2JkPlNoaWZ0PC9rYmQ+ICsgPGtiZD5TPC9rYmQ+IHwgU291cmNlIGFjdGl2ZSBmaWxlCjxrYmQ+Q3RybDwva2JkPiArIDxrYmQ+Ljwva2JkPiB8IEdvIHRvIGZpbGUvZnVuY3Rpb24KCk1ha2UgeW91ciBvd24uLi4KClRvb2xzIC0+IE1vZGlmeSBLZXlib2FyZCBTaG9ydGN1dHMKClwKCiMjIyBTY3JpcHRzCgpFc3RhYmxpc2ggdGhlIHN0cnVjdHVyZSBvZiBob3cgeW91IHdhbnQgdG8gY2FwdHVyZSB5b3VyIGNvZGUuIEFyZSB5b3UgZ29pbmcgdG8gZG8gZXZlcnl0aGluZyBpbiBSc2NyaXB0cz8gUk1hcmtkb3duPyBBIGNvbWJpbmF0aW9uPyBDcmVhdGUgdGhlIGFwcHJvcHJpYXRlIHNjcmlwdCBmaWxlcy4gSXQgY2FuIGJlIHVzZWZ1bCB0byBoYXZlIGEgc2VwYXJhdGUgUnNjcmlwdCB3aGVyZSB5b3Ugc3RvcmUgZnVuY3Rpb25zIHRoYXQgeW91IGNyZWF0ZSB3aGljaCBjYW4gYmUgJ3NvdXJjZWQnIGludG8geW91ciBvdGhlciBzY3JpcHRzIHRocm91Z2ggYHNvdXJjZSgic2NyaXB0bmFtZS5SKWAuCgpcCgojIyMgSW5pdGlhbGlzZSBWZXJzaW9uIENvbnRyb2wKClRoaXMgc2VjdGlvbiBpcyBhIHZlcnkgYnJpZWYgb3ZlcnZpZXcgb2YgdmVyc2lvbiBjb250cm9sLCBzcGVjaWZpY2FsbHkgdG8gc2F5IHRoYXQgeW91IHNob3VsZCBzdGFydCB0byBidWlsZCBpdCBpbnRvIHlvdXIgd29ya2Zsb3cgYW5kIHdlJ2xsIHRvdWNoIG9uIGl0IGFnYWluIGluIHRoZSBbQXV0b21hdGluZyBWZXJzaW9uIENvbnRyb2xdKCNhdXRvLXZjKSBzZWN0aW9uIGJ1dCB1bHRpbWF0ZWx5IHRoZSBkZXRhaWxzIGFyZSBvdXRzaWRlIG9mIHRoZSBzY29wZSBvZiB0aGlzIGNvdXJzZS4KCllvdSBhcmUgbGlrZWx5IGZhbWlsaWFyIHdpdGggdmVyc2lvbmluZywgdXN1YWxseSBwZW9wbGUgdHJ5IHRvIGFjaGlldmUgdGhpcyB0aHJvdWdoIGZpbGUgbmFtZXMuIFRoaXMgaXMgb2sgdG8gYSBwb2ludCBidXQgY2FuIGN1bWJlcnNvbWUgYW5kIGRvZXNuJ3Qgc2NhbGUgd2VsbCBhY3Jvc3MgbXVsdGlwbGUgZmlsZXMgbm9yIGRvZXMgaXQgZ2l2ZSB5b3UgYW4gZWFzeSB3YXkgdG8gc2VlIGV4YWN0bHkgd2hhdCB0aGUgZGlmZmVyZW5jZXMgd2VyZSBiZXR3ZWVuIHRob3NlIGZpbGVzLiBUaGlzIGlzIHdoZXJlIHVzaW5nIHZlcnNpb24gY29udHJvbCBzb2Z0d2FyZSBzdWNoIGFzIGBnaXRgIGNhbiBtYWtlIHlvdXIgbGlmZSBlYXNpZXIuCgpJdCdzIGFsd2F5cyBhIGdvb2QgaWRlYSB0byBnZXQgdGhpcyBzZXQgdXAgYmVmb3JlIHlvdSBnZXQgdW5kZXIgd2F5IGRvaW5nIGFjdHVhbCB3b3JrIHNvIHRoYXQgeW91IGNhbiB0cmFjayB5b3UgY2hhbmdlcyBmcm9tIHRoZSB0aGUgdmVyeSBzdGFydC4gSW4gdGhlIGNhc2Ugb2YgYGdpdGAsIGZvbGxvd2luZyBbSGFwcHkgR2l0IHdpdGggUl0oaHR0cHM6Ly9oYXBweWdpdHdpdGhyLmNvbSkgZm9yIGluc3RhbGxpbmcgYW5kIGNvbmZpZ3VyaW5nIGBnaXRgIGFuZCBzdWJzZXF1ZW50bHkgdGVsbGluZyBSU3R1ZGlvIGFib3V0IHlvdXIgaW5zdGFsbGF0aW9uIGlzIGEgZ29vZCBwbGFjZSB0byBzdGFydC4KCk9uY2UgeW91IGhhdmUgUlN0dWRpbyBzZXQgdXAgd2l0aCBgZ2l0YCwgd2hlbiB5b3UgYWRkIChpbml0aWFsaXNlKSB2ZXJzaW9uIGNvbnRyb2wgb250byB5b3VyIHByb2plY3QgeW91J2xsIGdldCBhbiBuZXcgdGFiIGFwcGVhciBhbmQgYSBoaWRkZW4gZGlyZWN0b3J5IGNhbGxlZCBgLmdpdGAgd2lsbCBiZSBjcmVhdGVkIGluc2lkZSB5b3VyIHByb2plY3QgZGlyZWN0b3J5LiBBIGRpcmVjdG9yeSB1bmRlciB2ZXJzaW9uIGNvbnRyb2wgaXMgY2FsbGVkIGEgJ3JlcG9zaXRvcnknIG9yICdyZXBvJy4KCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcid9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8xMC1naXRfcGFuZWwucG5nIikKYGBgCgoKClZlcnNpb24gY29udHJvbCBpcyB1c2VkIGZvciBrZWVwaW5nIHRyYWNrIG9mIHRoZSBjaGFuZ2VzIG1hZGUgdG8geW91ciBzY3JpcHRzLCB3ZSBkb24ndCB1c3VhbGx5IHVzZSBpdCB0byBtYW5hZ2Ugb3VyIGRhdGEgLSBzaW5jZSBvdXIgaW5pdGlhbCByYXcgZGF0YSBpc24ndCBnb2luZyB0byBiZSBjaGFuZ2luZy4gRm9yIG1hbmFnaW5nIGRhdGEsIHdlIHVzZSBhbiBhcHByb3ByaWF0ZSBiYWNrdXAgb3IgYXJjaGl2aW5nIHN5c3RlbS4KClwKCiMjIFRlc3RpbmcgYW5kIEFkanVzdGluZwoKT25jZSB0aGluZ3MgYXJlIHNldCB1cCwgd2UncmUgcmVhZHkgdG8gYWN0dWFsbHkgc3RhcnQgZG9pbmcgdGhlIHdvcmsgd2Ugd2FudCB0byBkby4gQXMgd2UgZGV2ZWxvcCBvdXIgY29kZSBob3dldmVyLCB3ZSBjb25zdGFudGx5IGN5Y2xlIHRocm91Z2ggdGVzdGluZyBhbmQgYWRqdXN0aW5nLiBFYWNoIHBpZWNlIG9mIGNvZGUgd2Ugd3JpdGUgbmVlZHMgdG8gYmUgY2hlY2tlZCB0aGF0IGlzIGlzIHdvcmtpbmcgY29ycmVjdGx5LiBPZnRlbiB0aGlzIHR5cGUgb2YgdGVzdGluZyBpcyBwZXJmb3JtZWQgbWFudWFsbHkgYXMgeW91IGdvOiAnZG9lcyB0aGUgbGluZSBvZiBjb2RlIHJ1bj8nIC0gY2hlY2tpbmcgZm9yIHN5bnRheCBlcnJvcnMsIGFuZCB0aGVuICdkb2VzIHRoZSBvdXRwdXQgbG9vayByaWdodD8nLiBXaGVuIHRoZSBhbnN3ZXIgdG8gdGhlc2UgZWl0aGVyIHF1ZXN0aW9uIGlzIG5vLCB3ZSB0aGVuIGVudGVyIGEgZGVidWdnaW5nIG1vZGUgd2hlcmUgd2UgdHJ5IGFuZCBmaW5kIG91dCB3aHkgdGhlIGNvZGUgaXNuJ3QgZG9pbmcgd2hhdCB3ZSB0aGluayBpdCBzaG91bGQgYmUuICAgCgpcCgojIyMgRGVidWdnaW5nCgoKRXJyb3JzIG1lc3NhZ2VzIGFyZSBjb21tb24gd2hlbiBjb2RpbmcgYW5kIGFyZSBhIHdheSB0aGUgY29tcHV0ZXIgY29tbXVuaWNhdGVzIGl0IGRvZXNuJ3QgdW5kZXJzdGFuZCB3aGF0IHRoZSBpbnN0cnVjdGlvbnMgaXQgaGFzIGJlZW4gZ2l2ZW4gYXJlLgpDb21tb24gdHlwZXMgb2YgZXJyb3JzIHdlIGVuY291bnRlciBhcmU6CgotIHN5bnRhY3RpY2FsCi0gbG9naWNhbAotIHJ1bnRpbWUKClN5bnRhY3RpY2FsIGVycm9ycyBhcmUgdXN1YWxseSB0aGUgbW9zdCBzdHJhaWdodCBmb3J3YXJkLCB0aGUgY29tcHV0ZXIgc2F5cyB0aGF0IG5vIHN0cmFpZ2h0IGF3YXkgZHVlIHRvIGltcHJvcGVyIHN5bnRheC4gVGhlc2UgYXJlIHVzdWFsbHkgdGhlIGVhc2llc3QgdG8gZmluZCBhbmQgY29ycmVjdC4gTG9naWNhbCBlcnJvcnMgY29tZSBhYm91dCB0aHJvdWdoIGluY29ycmVjdCBpbXBsZW1lbnRhdGlvbiBvZiBsb2dpYy4gVGhlIGNvbXB1dGVyIHdpbGwgcnVuIHRoZSBjb2RlIHdpdGhvdXQgY29tcGxhaW50IGJ1dCB0aGUgcmVzdWx0IGlzbid0IGNvcnJlY3QgLSB0aGVzZSBjYW4gYmUgdHJpY2t5IHRvIGZpbmQgYW5kIGZpeCBiZWNhdXNlIHRoZXkgb2Z0ZW4gaW52b2x2ZSBjaGVja2luZyBlYWNoIGxvZ2ljYWwgc3RhdGVtZW50IGFuZCBzdWJzZXF1ZW50IGNvZGUgcGF0aHdheSBpbiBvcmRlciB0byB0cmFjayBkb3duIHdoYXQgaXMgZ29pbmcgd3JvbmcuIFJ1bnRpbWUgZXJyb3JzIGFyZSBlcnJvcnMgd2hlcmUgeW91IGFyZSB0cnlpbmcgdG8gbWFrZSB0aGUgY29tcHV0ZXIgZG8gc29tZXRoaW5nIGl0IGNhbid0IGluIGNlcnRhaW4gc2l0dWF0aW9ucywgc3VjaCBhcyBzdG9yaW5nIGEgcmVzdWx0IGluIGEgY2VydGFpbiBsb2NhdGlvbi4gVGhlIGNvZGUgd2lsbCBydW4gc29tZXRpbWVzIGJ1dCBub3Qgb3RoZXJzIGFuZCBhZ2FpbiBjYW4gYmUgdHJpY2t5IHRvIHRyYWNrIGRvd24uIAoKUmVtZW1iZXIsIGVhY2ggdGltZSB3ZSBmaW5kIGFuZCBmaXggYW4gZXJyb3IsIHdlIG11c3QgcmV0ZXN0LiBUaGlzIGNhbiBnZXQgcXVpdGUgbGFib3Jpb3VzIHRvIGRvIG1hbnVhbGx5IHNvIHdlIGNhbiBmaW5kIGJldHRlciBzeXN0ZW1zIHRvIGhlbHAgc3VjaCBhcyBbYXV0b21hdGljIHRlc3RpbmddKCNhdXRvbWF0aWMtdGVzdHMpIGJ1dCBmaXJzdCB3ZSdsbCBjb3ZlciBzb21lIGdlbmVyYWwgcHJpbmNpcGxlcyBvbiBob3cgdG8gZ28gYWJvdXQgZGVidWdnaW5nLgoKCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQuaGVpZ2h0ID0gJzUwJScsIG91dC53aWR0aD0nNTAlJywgZmlnLmNhcCA9ICJodHRwczovL3hrY2QuY29tLzE3MzkvIiwgZmlnLmFsaWduPSdjZW50ZXInfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzEwLWZpeGluZ19wcm9ibGVtcy5wbmciKQpgYGAKClwKCiMjIyMgV2hlcmUgZG8gSSBzdGFydD8KCktub3dpbmcgd2hlcmUgdG8gc3RhcnQgZGVidWdnaW5nIHRha2VzIHByYWN0aWNlLiBzb21lIGdlbmVyYWwgZ29vZCBhZHZpY2UgY2FuIGJlIGZvdW5kIGluIGh0dHBzOi8vYWR2LXIuaGFkbGV5Lm56L2RlYnVnZ2luZy5odG1sIHdpdGggc29tZSBzcGVjaWZpYyB0aXBzIGFuZCB0cmlja3MgZm9yIFIuIFRoZSBnZW5lcmFsIHByZW1pc2UgaXMgdGhhdCB3ZSB3YW50IHRvIHRlc3QgYW5kIGNvbmZpcm0gYWxsIG9mIG91ciBhc3N1bXB0aW9ucy4KCj4gRmluZGluZyB5b3VyIGJ1ZyBpcyBhIHByb2Nlc3Mgb2YgY29uZmlybWluZyB0aGUgbWFueSB0aGluZ3MgdGhhdCB5b3UgYmVsaWV2ZSBhcmUgdHJ1ZSDigJQgdW50aWwgeW91IGZpbmQgb25lIHdoaWNoIGlzIG5vdCB0cnVlLgo+Cj4g4oCUIE5vcm0gTWF0bG9mZgoKU29tZSB0ZWNobmlxdWVzIGZvciBzb2x2aW5nIGVycm9ycyBhbmQgY29uZmlybWluZyBvdXIgYXNzdW1wdGlvbnMgY2FuIGluY2x1ZGU6CgoKLSB1c2luZyBwcmludCBzdGF0ZW1lbnRzIHRvIGNvbmZpcm0gdmFsdWVzIGF0IGtleSBzdGFnZXMKLSBnb29nbGluZyB0aGUgZXJyb3IgbWVzc2FnZQotIHJlc3RhcnQgUiBhbmQgcmVydW4gdGhlIGNvZGUKLSByZWFkaW5nIHRoZSBkb2N1bWVudGF0aW9uCi0gdGFsayB0aHJvdWdoIHRoZSBwcm9ibGVtCgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gJzUwJScsIG91dC5oZWlnaHQgPSAnNTAlJywgZmlnLmFsaWduPSdjZW50ZXInfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzEwLXJ1YmJlcmR1Y2suanBnIikKYGBgCgonUnViYmVyIGR1Y2sgZGVidWdnaW5nJyBpcyBhIHRlY2huaXF1ZSB3aGljaCBpbnZvbHZlcyB0YWxraW5nIHlvdXIgd2F5IHRocm91Z2ggd2hhdCB5b3UgYXJlIHRyeWluZyB0byBhY2hpZXZlIHdpdGggeW91ciBjb2RlIGFuZCBleHBsYWluaW5nIHdoYXQgeW91ciBjb2RlIGlzIGFjdHVhbGx5IGRvaW5nIGF0IGVhY2ggc3RlcCB0byBhIHJ1YmJlciBkdWNrIChvciBvdGhlciB0b3kpLiBPZnRlbiBieSBiZWluZyBzeXN0ZW1hdGljIGFuZCBzYXlpbmcgb3V0IGxvdWQgd2hhdCBpcyBoYXBwZW5pbmcgdGhpcyB3aWxsIHRyaWdnZXIgYW4gImEtaGEiIG1vbWVudCBhcyB0byB3aGF0IGlzIGNhdXNpbmcgdGhlIGlzc3VlLiBZb3UgY2FuIGFsc28gdXNlIHRoaXMgdGVjaG5pcXVlIHdpdGggYW5vdGhlciBwZXJzb24gZS5nLiBjby13b3JrZXIgaW5zdGVhZCBvZiBhIHRveSBpZiB5b3UgcHJlZmVyLgoKXAoKIyMjIyBHZW5lcmFsIHByb2Nlc3MKCk15IGdlbmVyYWwgcHJvY2VzcyBmb2N1c2VzIG9uIHRoZSBpbml0aWFsIHNvdXJjZSBvZiB0aGUgZXJyb3IgYW5kIHRoZW4gc3RhcnRzIHRvIHdvcmsgYmFja3dhcmRzIGluIGNvbW1hbmQgaGlzdG9yeS4KCjEuIERvIEkgcmVjb2duaXNlIHRoZSBtZXNzYWdlPwoyLiBSZS1sb29rIGF0IHRoZSBjb21tYW5kIEkgcmFuIGxvb2tpbmcgZm9yCiAgICAtIHR5cG9zCiAgICAtIG1pc3Npbmcgc3ludGF4IChlLmcuIGJyYWNrZXRzLCBzZW1pY29sb25zLCBldGMuKQogICAgLSBjb3JyZWN0IG5hbWluZyBvZiB0aGluZ3MKMy4gSXMgdGhlIGlucHV0IGZvciBteSBjb21tYW5kIHdoYXQgSSBleHBlY3QgaXQgaXM/CjQuIERpZCB0aGUgcHJldmlvdXMgY29tbWFuZCBydW4gcHJvcGVybHk/CiAgICAtIGlmIG5vdCBqdW1wIHRvIDEuIGZvciB0aGUgcHJldmlvdXMgY29tbWFuZAoKXAoKIyMjIyBHZXR0aW5nIHRvIGtub3cgc29tZSBlcnJvcnMKClIgaXMgbm90b3Jpb3VzIGZvciBoYXZpbmcgbWVzc2FnZXMgdGhhdCBhcmUgbm90IHVzZXIgZnJpZW5kbHkuIExldHMgbG9vayBhdCBhIGZldyBjb21tb24gUiBlcnJvcnMgYW5kIHdhcm5pbmdzIHNvIHRoYXQgd2UgY2FuIGJlY29tZSBtb3JlIGZhbWlsaWFyIHdpdGggYSkgd2hhdCB0aGV5IGxvb2sgbGlrZSwgYikgaG93IHRvIGZpbmQgdGhlIHVzZWZ1bCBiaXRzCgoqKkFuYXRvbXkgb2YgYSBtZXNzYWdlKioKCjEuIFVzdWFsbHkgdGhlIGZpcnN0IHdvcmQgaXMgIkVycm9yIiwgYnV0IHNvbWV0aW1lcyBpdCBjYW4gYmUgIldhcm5pbmciLiBDb2RlIHRoYXQgcHJvZHVjZXMgZXJyb3JzIHdvbid0IHJ1bi4gQ29kZSB0aGF0IHByb2R1Y2VzIHdhcm5pbmdzIHdpbGwgcnVuIGJ1dCBpcyBzaWduaWZ5aW5nIHRoYXQgeW91IHNob3VsZCBiZSBleHRyYSBjYXJlZnVsIGFib3V0IHRoZSBvdXRwdXQgYmVjYXVzZSBpdCBtaWdodCBub3QgYmUgZG9pbmcgd2hhdCB5b3UgdGhpbmsgaXQgaXMuIAoyLiBJbW1lZGlhdGVseSBmb2xsb3dpbmcgaXMgdGhlIGV4YWN0IGNvZGUgdGhhdCBpcyBwcm9kdWNpbmcgdGhlIGVycm9yL3dhcm5pbmcuIFRoaXMgdGVsbHMgeW91IHdoZXJlIHRvIHN0YXJ0IGxvb2tpbmcuCjMuIGFmdGVyIHRoZSBgOmAgZ2l2ZXMgdGhlIGRldGFpbHMgYWJvdXQgd2hhdCB0aGUgZXJyb3Ivd2FybmluZyBhY3R1YWxseSBpcy4gCgpgYGB7ciwgZXZhbCA9IFRSVUUsIGVycm9yID0gVFJVRSwgd2FybmluZyA9IFRSVUUsIHJlc3VsdHM9J2hpZGUnfQpteV92YXIKYGBgCgpDYXVzZWQgYnkgdHJ5aW5nIHRvIGFjY2VzcyBhIHZhcmlhYmxlIHRoYXQgaGFzbid0IGJlZW4gZGVmaW5lZCB5ZXQuCgpgYGB7ciwgZXZhbCA9IFRSVUUsIGVycm9yID0gVFJVRSwgd2FybmluZyA9IFRSVUUsIHJlc3VsdHM9J2hpZGUnfQptZWFuWzJdCmBgYAoKQ2F1c2VkIGJ5IHVzaW5nIHRoZSBzdWJzZXR0aW5nIGJyYWNrZXRzIGBbXWAgaW5zdGVhZCBvZiBgKClgIHdoaWNoIGFyZSB1c2VkIGZvciBhIGZ1bmN0aW9uLgoKYGBge3IsIGV2YWwgPSBUUlVFLCBlcnJvciA9IFRSVUUsIHdhcm5pbmcgPSBUUlVFLCByZXN1bHRzPSdoaWRlJ30KYSA8LSBjKG9uZSA9IDEsdHdvID0gMiwgdGhyZWUgPSAzKQphJG9uZQpgYGAKCllvdSBjYW4ndCB1c2UgYCRgIG9uIGFuIGF0b21pYyB2ZWN0b3IsIGl0J3MgdXNlZCBvbiBzdHJ1Y3R1cmVzIHN1Y2ggYXMgZGF0YS5mcmFtZXMgb3IgbGlzdHMuCgpgYGB7ciwgZXZhbCA9IFRSVUUsIGVycm9yID0gVFJVRSwgd2FybmluZyA9IFRSVUUsIHJlc3VsdHM9J2hpZGUnfQphW1syMF1dCmBgYAoKQ2F1c2VkIGJ5IHRyeWluZyB0byBhY2Nlc3MgYW4gZWxlbWVudCBhdCBhbiBpbmRleCB0aGF0IGRvZXNuJ3QgZXhpc3QuCgpgYGB7ciwgZXZhbCA9IFRSVUUsIGVycm9yID0gVFJVRSwgd2FybmluZyA9IFRSVUUsIHJlc3VsdHM9J2hpZGUnfQpyZWFkLmNzdigibXlmaWxlLmNzdiIpCmBgYAoKQ2F1c2VkIGJ5IHByb3ZpZGluZyBhIGZpbGUgbmFtZSB0aGF0IFIgY2Fubm90IGZpbmQgaW4gdGhlIHdvcmtpbmcgZGlyZWN0b3J5LgoKYGBge3IsIGV2YWwgPSBUUlVFLCBlcnJvciA9IFRSVUUsIHdhcm5pbmcgPSBUUlVFLCByZXN1bHRzPSdoaWRlJ30KZ2dwbG90KCkKYGBgCgpDYXVzZWQgYnkgbm90IGhhdmluZyBhIGBnZ3Bsb3RgIGZ1bmN0aW9uIGVpdGhlciB1c2VyIGRlZmluZWQgaW4gdGhlIGVudmlyb25tZW50IG9yIG5vdCBsb2FkZWQgYSBsaWJyYXJ5IHRoYXQgY29udGFpbnMgaXQgKGBnZ3Bsb3QyYCBvciBgdGlkeXZlcnNlYCkuCgpgYGB7ciwgZXZhbCA9IFRSVUUsIGVycm9yID0gVFJVRSwgd2FybmluZyA9IFRSVUUsIHJlc3VsdHM9J2hpZGUnfQpub3RhcGFja2FnZTo6bm90YWZ1bmN0aW9uKCkKYGBgCgpDYXVzZWQgYnkgdHJ5aW5nIHRvIGNhbGwgYSBmdW5jdGlvbiBmcm9tIGEgcGFja2FnZSB0aGF0IGRvZXNuJ3QgZXhpc3QgaXMgbm90IGJlIGluc3RhbGxlZCBvbiB0aGUgbGlicmFyeSBwYXRoLgoKYGBge3IsIGV2YWwgPSBUUlVFLCBlcnJvciA9IFRSVUUsIHdhcm5pbmcgPSBUUlVFLCByZXN1bHRzPSdoaWRlJ30KaWYoTkEpewogIHByaW50KCJ3YXMgTkEiKQp9CmBgYAoKYGlmYCByZXF1aXJlcyB0aGUgcmVzdWx0IHRvIGJlIFRSVUUgb3IgRkFMU0UsIGBOQWAgaXNuJ3QgYSBUUlVFIG9yIEZBTFNFLgoKCmBgYHtyLCBldmFsID0gVFJVRSwgZXJyb3IgPSBUUlVFLCB3YXJuaW5nID0gVFJVRSwgcmVzdWx0cz0naGlkZSd9CmlmKGMoMyA+IGMoMSwyLDMpKSl7CiAgcHJpbnQoImxlc3MgdGhhbiB0aHJlZSIpCn0KCmlmKGMoMSwyLDMpID4gMyl7CiAgcHJpbnQoImxlc3MgdGhhbiBvbmUiKQp9CmBgYAoKYGlmYCByZXF1aXJlcyBhIHNpbmdsZSBUUlVFIG9yIEZBTFNFIHJlc3VsdCwgdGhlc2Ugc3RhdGVtZW50cyBjcmVhdGUgbXVsdGlwbGUuIEluIG9sZGVyIHZlcnNpb25zIG9mIFIgdGhpcyBwcm9kdWNlZCBhIHdhcm5pbmcgYW5kIG5vdCBhbiBlcnJvci4KCmBgYHtyLCBldmFsID0gVFJVRSwgZXJyb3IgPSBUUlVFLCB3YXJuaW5nID0gVFJVRSwgcmVzdWx0cz0naGlkZSd9Cm1lYW4oYygiMSIsICIyIikpCmBgYAoKQ2F1c2VkIGJ5IHRoZSBhIGRhdGEgdHlwZSB0aGF0IGRvZXNuJ3QgY29lcmNlIGludG8gYSBudW1lcmljIGF1dG9tYXRpY2FsbHkuCgpcCgojIyMgQWRqdXN0aW5nCgpJbiB0aGUgcHJvY2VzcyBvZiBkZXZlbG9waW5nLCBpdCdzIGFsc28gaW1wb3J0YW50IHRvIHRha2Ugb3Bwb3J0dW5pdGllcyB0byBhZGp1c3QgaG93IHRoaW5ncyBhcmUgYmVpbmcgZG9uZS4gV29ya2luZyBjb2RlIGlzIGJldHRlciB0aGFuIG5vIGNvZGUsIGJ1dCB5b3UgY3JlYXRlIG1vcmUgY29kZSBpdCdzIGFsc28gYSBnb29kIGlkZWEgdG8gZXZlcnkgc28gb2Z0ZW4gbG9vayBmb3Igb3Bwb3J0dW5pdGllcyB0byBtYWtlIHRoaW5ncyBiZXR0ZXIgLSBlZmZpY2llbmN5IG9yIG1haW50ZW5hbmNlIHdpc2UuCgpDb2RlIHJlcGxpY2F0aW9uIGlzIGEgZ29vZCBwbGFjZSB0byBzdGFydCAtIGlmIHlvdSd2ZSBmb3VuZCB5b3Vyc2VsZiBjb3B5IGFuZCBwYXN0aW5nIHRoZSBzYW1lIGNvZGUgb3ZlciBpbiB0aGUgc2FtZSBwcm9qZWN0LCBjb25zaWRlciBtYWtpbmcgaXQgaW50byBhIGZ1bmN0aW9uLiBUaGlzIHRoZW4gZ2l2ZXMgeW91IGEgc2luZ2xlIHBsYWNlIHRoYXQgbmVlZHMgdG8gYmUgY2hhbmdlZC4gSWYgeW91IGZpbmQgeW91cnNlbGYgY29weSBhbmQgcGFzdGluZyB5b3VyIGZ1bmN0aW9ucyBhY3Jvc3MgcHJvamVjdHMsIGNvbnNpZGVyIGNyZWF0aW5nIHlvdXIgb3duIHBhY2thZ2UuCgpcCgojIyMjIFJNYXJrZG93biBkcml2ZW4gZGV2CgpFbWlseSBSaWVkZXJlciBoYXMgYSBncmVhdCBibG9nIHBvc3QgYWJvdXQgW1JNYXJrZG93biBkcml2ZW4gZGV2ZWxvcG1lbnRdKGh0dHBzOi8vZW1pbHlyaWVkZXJlci5uZXRsaWZ5LmFwcC9wb3N0L3JtYXJrZG93bi1kcml2ZW4tZGV2ZWxvcG1lbnQvKSB3aGljaCBkZXNjcmliZXMgYSBwcm9jZXNzIG9mIGRldmVsb3BtZW50IHVzaW5nIFJNYXJrZG93biBkb2N1bWVudHMsIHdoZXJlIGZpcnN0IHlvdSBnZXQgdGhpbmdzIHRvIGEgd29ya2luZyBzaXR1YXRpb24sIHRoZW4gZ28gdGhyb3VnaCByb3VuZHMgb2YgdGlkeWluZyB5b3VyIGRvY3VtZW50IGJyaW5naW5nIGxpa2UtdG8tbGlrZSB3aXRoIHlvdXIgY29kZSBzbyB0aGF0IGNvZGUgYmxvY2tzIGNvbnRhaW4gc2ltaWxhciBwcm9jZXNzZXMuIEFzIHRoZSB0aWR5aW5nIGlzIHBlcmZvcm1lZCwgaXQgcHJvdmlkZXMgYW4gb3Bwb3J0dW5pdHkgdG8gYWxzbyByZWR1Y2UgZHVwbGljYXRpb24gb2YgY29kZSBhbmQgaW5jcmVhc2UgdGhlIG1haW50YWluYWJpbGl0eSBieSBjb252ZXJ0aW5nIHByb2Nlc3NlcyBpbnRvIGZ1bmN0aW9ucy4gCgpcCgojIyMjIFBhY2thZ2VzCgpJZiB5b3UgZmluZCB5b3Vyc2VsZiBjb3B5IGFuZCBwYXN0aW5nIGZ1bmN0aW9uIGJldHdlZW4gZG9jdW1lbnRzLCBpdCBtaWdodCBiZSB0aW1lIHRvIHN0YXJ0IGNyZWF0aW5nIHlvdXIgb3duIHBhY2thZ2UsIHRoYXQgd2F5IHlvdSByZWR1Y2UgdGhlIG51bWJlciBvZiBpbmRpdmlkdWFsIHBsYWNlcyB5b3VyIGZ1bmN0aW9uIGlzIGRlZmluZWQgYW5kIHRoaXMgbWFrZXMgaXQgZWFzaWVyIGluIHRoZSBmdXR1cmUgdG8gbWFpbnRhaW4uIFBhY2thZ2VzIGFsc28gYnJpbmcgaW4gYW4gZXh0cmEgbGV2ZWwgb2YgdXRpbGl0eSBpbiB0aGF0IHlvdSBjYW4gaW1wcm92ZSBkb2N1bWVudGF0aW9uIGFuZCBpbXBsZW1lbnQgYXV0b21hdGVkIHRlc3Rpbmcgc28gdGhhdCB5b3Uga25vdyB3aGVuIGNoYW5nZXMgYnJlYWsgZnVuY3Rpb25hbGl0eS4KCklmIHlvdSB3YW50IHRvIGxvb2sgZnVydGhlciBpbnRvIGhvdyB0byBjcmVhdGUgcGFja2FnZXMsIGNoZWNrIG91dCB0aGUgW1IgUGFja2FnZXMgb25saW5lIGJvb2tdKGh0dHBzOi8vci1wa2dzLm9yZy9pbmRleC5odG1sKSBhbmQgeW91IGNhbiB1c2UgYHVzZXRoaXM6OmNyZWF0ZV9wYWNrYWdlKClgIHRvIGNyZWF0ZSBhIG5ldyBwYWNrYWdlIGZyb20gYSB0ZW1wbGF0ZS4KClwKCiMjIEF1dG9tYXRpbmcKCkFzIHlvdSBnbyBhYm91dCBkZXZlbG9waW5nLCB0aGVyZSBhcmUgdHdvIG1haW4gdGhpbmdzIHlvdSB3aWxsIGZpbmQgeW91cnNlbGYgZG9pbmcgb3ZlciBhbmQgb3ZlciBhZ2FpbiAtIHRyeWluZyB0byByZW1lbWJlciB3aGF0IHlvdSBoYXZlIGNoYW5nZWQsIGFuZCBtYWtpbmcgc3VyZSB0aGF0IGFueSBjaGFuZ2VzIGhhdmVuJ3QgYnJva2VuIGFueXRoaW5nLiBUaGVzZSBwcm9jZXNzZXMgY2FuIGJlIHF1aXRlIHRpbWUgaW50ZW5zaXZlIHNvIGl0J3MgcXVpdGUgdXNlZnVsIHRvIHRyeSBhbmQgYXV0b21hdGUgdGhlIHBpZWNlcyB0aGF0IHlvdSBjYW4uCgpcCgojIyMgQXV0b21hdGVkIHRlc3RpbmcgeyNhdXRvbWF0aWMtdGVzdHN9CgpBcyB5b3UgY29kZSBhbmQgbWFudWFsbHkgdGVzdCwgaXQgY2FuIGJlIGJlbmVmaWNpYWwgdG8gZm9ybWFsaXNlIHRoZSBtYW51YWwgdGVzdHMgaW50byBhbiBhdXRvbWF0ZWQgc29sdXRpb24gc28gdGhhdCB5b3UgY2FuIGJlIG1vcmUgZWZmaWNpZW50IGFuZCBhbHNvIGVuc3VyZSB0aGF0IHlvdSBrbm93IHdoZW4geW91ICdicmVhayB0aGluZ3MnIHdpdGggZnV0dXJlIGNoYW5nZXMuIFRoaXMgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHlvdSBmaXggYnVncyBpbiB5b3VyIGNvZGUsIGNyZWF0ZSBhIHRlc3QgdGhhdCByZXBsaWNhdGVzIHRoZSBjb25kaXRpb24gdGhhdCBjYXVzZWQgdGhlIGJ1Zy4KCkluIFIsIG9uZSBzeXN0ZW0gdXNlcyB0aGUgcGFja2FnZSBgdGVzdHRoYXRgIHdoaWNoIHByb3ZpZGVzIGEgZnJhbWV3b3JrIHRvIGNyZWF0ZSB0aGVzZSBmb3JtYWwgdGVzdHMgd2hpY2ggd2lsbCBldmFsdWF0ZSBhIHBpZWNlIG9mIGNvZGUgYWdhaW5zdCB0aGUga25vd24gZXhwZWN0ZWQgb3V0cHV0IGFuZCB0ZWxsIHlvdSBpZiB0aGV5IGRvbid0IG1hdGNoLgoKYGBge3IsIGV2YWwgPSBGQUxTRX0KCiMgZXhwZWN0IGEgbWVhbiBvZiAyCnRlc3R0aGF0OjpleHBlY3RfZXF1YWwobWVhbihjKDEsMiwzKSksIDIpCmBgYAoKYHRlc3R0aGF0YCBvcGVyYXRlcyBieSBzZXR0aW5nIHVwIGV4cGVjdGF0aW9ucyBhbmQgdGVzdGluZyBpZiB0aGV5IGhvbGQgdHJ1ZS4gSWYgdGhleSBhcmUgdHJ1ZSB0aGUgZXhwZWN0YXRpb24gZnVuY3Rpb24gaXMgc2lsZW50LCBpZiB0aHkgYXJlbid0IGl0IHdpbGwgdGVsbCB5b3Ugd2hlbiBydW4uIFRoaXMgbGV0cyB5b3UgZm9ybWFsaXNlIHRlc3RzIHRoYXQgeW91IHdvdWxkIGJlIHJ1bm5pbmcgbWFudWFsbHkgYW5kIGFzIHlvdSBtYWtlIGFkanVzdG1lbnRzIHRvIHlvdXIgY29kZSB5b3UgY2FuIHJlcnVuIHRoZXNlIHRlc3RzIHRvIGNoZWNrIHRoaW5ncyBhcmUgc3RpbGwgd29ya2luZy4KClwKCiMjIyBBdXRvbWF0aW5nIGRpZmZlcmVuY2VzIHsjYXV0by12Y30KClZlcnNpb24gY29udHJvbCBzb2Z0d2FyZSBpcyBzbGlnaHRseSBkaWZmZXJlbnQgZnJvbSB3aGF0IHlvdSBtaWdodCBoYXZlIGV4cGVyaWVuY2VkIHdpdGggc29tZXRoaW5nIGxpa2UgJ3RyYWNrIGNoYW5nZXMnIGluIE1pY3Jvc29mdCBXb3JkIHdoaWNoIHRyYWNrcyBhbGwgY2hhbmdlcyBsaXZlLiAKCkluIHRoZSBjYXNlIG9mIGBnaXRgLCBvbmNlIHlvdSBoYXZlIGV2ZXJ5dGhpbmcgc2V0IHVwIGFuZCBjb25maWd1cmVkIHRoZXJlIGlzIGEgKHNpbXBsaWZpZWQpIG1pbmktd29ya2Zsb3cgd2hpY2ggY2FuIGJlIGRvbmUgYWZ0ZXIgY2xpY2tpbmcgdGhlICdjb21taXQnIGJ1dHRvbiBpbiB0aGUgZ2l0IHRhYjoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJ30KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzEwLWNvbW1pdC5wbmciKQpgYGAKCgoKMS4gVGVsbCBgZ2l0YCB5b3Ugd2FudCBpdCB0byB0cmFjayB0aGUgY2hhbmdlcyBvbiBhIGZpbGUKMi4gTWFrZSBzb21lIGNoYW5nZXMKMy4gVGVsbCBgZ2l0YCB5b3Ugd2FudCB0byBpbmNsdWRlIHRoZXNlIGNoYW5nZXMgaW4gaXRzIHRyYWNraW5nCiAgICAtIGNsaWNrIHRoZSAnc3RhZ2VkJyBjaGVja2JveCBvbiB0aGUgZmlsZSBpbiB0aGUgZ2l0LWNvbW1pdCB3aW5kb3cKNC4gVGVsbCBgZ2l0YCB0byAnc25hcHNob3QnIHlvdXIgY2hhbmdlcyBhbmQgaW5jbHVkZSBhIG1lc3NhZ2UgYWJvdXQgdGhlbQogICAgLSB3cml0ZSBhIG1lc3NhZ2UgYW5kIGNsaWNrIGNvbW1pdCBpbiB0aGUgZ2l0IC0gY29tbWl0IHdpbmRvdwo1LiBnbyBiYWNrIHRvIHN0ZXAgMi4KCgoKCldoeSB3b3VsZCB5b3UgZG8gdGhpcyB3b3JrZmxvdz8gRm9yIHlvdXIgZnV0dXJlIHNlbGYuIEV2ZXJ5IHNuYXBzaG90IHlvdSB0YWtlIHdpdGggYGdpdGAgZ2l2ZXMgeW91IGEgcG9pbnQgaW4gdGltZSB0aGF0IHlvdSBjYW4gcm9sbCBiYWNrIHRvIGlmIHlvdSB3aXNoIC0gZnJvbSBhIHJlcHJvZHVjaWJpbGl0eSBwb2ludCBvZiB2aWV3IHRoaXMgbGV0cyB5b3UgcnVuIF9hbnlfIHZlcnNpb24gb2YgeW91ciBjb2RlIGF0IGEgc25hcHNob3QuIGBnaXRgIGNhbiBhbHNvIGxldCB5b3Ugc2VlIGV4YWN0bHkgd2hhdCBjaGFuZ2VzIHRoZXJlIHdlcmUgYmV0d2VlbiBzbmFwc2hvdHMgd2hpY2ggY2FuIGJlIGV4dHJlbWVseSBoZWxwZnVsIGZvciBkZWJ1Z2dpbmcKCmBnaXRgIGlzIGEgZmFpcmx5IGNvbXBsZXggcGllY2Ugb2Ygc29mdHdhcmUgYW5kIHByb3ZpZGVzIG1vcmUgZnVuY3Rpb25hbGl0eSB0aGFuIHRoaXMsIGJ1dCBmb3Igc3RhcnRpbmcgb3V0IHRoaXMgd29ya2Zsb3cgY292ZXJzIHRoZSBtYWluIG5lZWQgYW5kIHVzZSBjYXNlLgoKXAoKIyMgRmluYWxpc2UKCkNvbmdyYXR1bGF0aW9ucyEgWW91J3ZlIG1hZGUgaXQgdG8gdGhlIGVuZC1zdGFnZSBvZiB5b3VyIHByb2plY3Qgd2hlcmUgeW91J3JlIHJlYWR5IHRvIHdyYXAgdGhpbmdzIHVwIGFuZCBzaGFyZSB5b3VyIHByb2plY3Qgd2l0aCBvdGhlcnMuIFdoYXQgeW91IGRvIGF0IHRoaXMgc3RhZ2UgZW50aXJlbHkgZGVwZW5kcyBvbiB3aGF0IG91dHB1dCB5b3VyIHByb2plY3Qgd2FzIGZvci4gUGVyaGFwcyBpdCdzIHNlbmRpbmcgeW91ciBlbnRpcmUgcHJvamVjdCBkaXJlY3RvcnkgdG8geW91ciBsZWN0dXJlciBvciBzdXBlcnZpc29yLiBPciB0aGlzIGNvdWxkIGludm9sdmUgdXBsb2FkaW5nIHlvdXIgdmVyc2lvbiBjb250cm9sbGVkIGNvZGUgdG8gYW4gb25saW5lIGNvZGUgcmVwb3NpdG9yeSBzdWNoIGFzIFtodHRwczovL2dpdGh1Yi5jb21dKGh0dHBzOi8vZ2l0aHViLmNvbSkgYW5kIHB1Ymxpc2hpbmcgdGhlIHVybCBpbiB5b3VyIHBhcGVyIG9yIG90aGVyIG91dHB1dC4KClJlZ2FyZGxlc3MsIGVtYnJhY2UgdGhlIGNvbXBsZXRpb24uIFRoZW4gY29udGludWUgb24gdG8geW91ciBuZXh0IHByb2plY3QsIGJyaW5naW5nIHdpdGggeW91IHRoZSBza2lsbHMgeW91IGxlYXJudCBvbiB0aGlzIG9uZS4KClwKCiMjIFdoYXQncyBOZXh0CgpQbGVhc2UgZmlsbCBpbiB0aGUgZmVlZGJhY2sgZm9ybSBbaHR0cHM6Ly90aW55dXJsLmNvbS9yNHNzcC1tb2R1bGUtZmItczItMjNdKGh0dHBzOi8vdGlueXVybC5jb20vcjRzc3AtbW9kdWxlLWZiLXMyLTIzKS4gWW91ciBpbnB1dCBoZWxwcyB1cyBtYWtlIFI0U1NQIGJldHRlci4KClwKCiMjIEFwcGVuZGl4CgpBbiBleGFtcGxlIHdvcmtmbG93IHNldCB1cAoKYGBge3IsIGV2YWw9RkFMU0V9CiMgQ3JlYXRlIGFuZCBvcGVuIGEgbmV3IHByb2plY3QKdXNldGhpczo6Y3JlYXRlX3Byb2plY3QocGF0aCA9ICJ+L215cHJvamVjdCIpCgojIEluaXRpYWxpc2UgdmVyc2lvbiBjb250cm9sCnVzZXRoaXM6OnVzZV9naXQoKQoKIyBDcmVhdGUgdGhlIHByb2plY3Qgc3RydWN0dXJlCmRpci5jcmVhdGUoImRhdGEiKQpkaXIuY3JlYXRlKCJzY3JpcHRzIikKZGlyLmNyZWF0ZSgib3V0cHV0IikKZGlyLmNyZWF0ZSgiZG9jcyIpCgojIFRlbGwgZ2l0IHRvIGlnbm9yZSB0aGUgZGF0YSBkaXJlY3RvcnkgYnkgYWRkaW5nIGxpbmU6CiMgZGF0YS8KdXNldGhpczo6ZWRpdF9naXRfaWdub3JlKCkKCgojIEFkZCBhIFJFQURNRQp1c2V0aGlzOjp1c2VfcmVhZG1lX21kKCkKCiMgQWRkIE1JVCBMaWNlbnNlCnVzZXRoaXM6OnVzZV9taXRfbGljZW5zZShjb3B5cmlnaHRfaG9sZGVyID0gIkZpcnN0bmFtZSBMYXN0bmFtZSIpCmBgYAoKCgo=