Introduction
Advances in computing and sensing technologies mean that modern
scientific research often involves very large data sets. There are now
many computer software tools available to work with big data, and
scientists from all disciplines need to be able to use them.
In this mini-course, we will help you learn to use one of the most
interesting (and popular) of these tools – the programming language R. R
is a special-purpose open-source language for statistics and data
analysis. Increasingly, R is the preferred tool for analysing and
presenting data for student research projects.
In this module, we show you how to get started with R. We will not
assume that you have any prior computer programming experience. In fact,
if you have programmed before in a language like Java or C, be aware
that R is, in many respects, very different from those languages – so
keep an open mind.
We will begin by explaining the different software tools you need,
and how to get them onto your own computers, if you wish to do so. Then
we will discuss the basic mechanics of these tools. Throughout this
handout (and all materials for this mini-course) there are code examples
and R exercises that you should work through carefully on the computer.
This will prepare you to use R for your in-course research projects
later in the semester.
This handout is designed to be read in conjunction with Chapter 1:
Introduction of R for Data
Science.
The Tools
We think of computers as storing rich meaningful data (mostly cat
videos). Actually, what computers really contain are millions of tiny
little storage units, each of which either holds an electrical charge
(usually called a 1) or holds nothing (usually called a 0). Really.
That’s it. That’s all there is.
All of the amazing things that computers do happen through extremely
complicated manipulation of all those 0s and 1s.This involves a lot of
maths and a lot of electronics, and is very, very confusing. So that
computer users don’t have to think about all these 0s and 1s, computer
scientists have developed programming languages, which
are symbolic systems that we can use to express what we want to happen
inside the machine. Programming languages are designed to be similar to
human languages, so they are easy for us to work with. Over the last 60
years many such languages have been developed: FORTRAN, BASIC, C, Java,
Python, etc., and the one we are using in this mini-course, R. Each
programming language has a vocabulary and a grammar (just like human
languages) which must be followed exactly (they are, in
fact, much stricter about this than human languages).
To communicate with your computer using a program language, you need
a special computer program (previously written in a programming
language, of course) that knows how to translate from the human-friendly
programming language into actions on the computer. These are called
Development Environments, because this is where people
develop software.
The most popular development environment for R is a program called
RStudio.
Both R and RStudio are installed on the computers in the Otago
University computer labs. You can work through this document on those
machines.
You can also install the R language and the RStudio program on your
own personal computers. These are completely open-source, free, and
safe.
First, install R from https://cran.r-project.org/bin/windows/base/ (for
Windows machines) or https://cran.r-project.org/bin/macosx/ (for Mac OS
machines). Then install RStudio from https://rstudio.com/products/rstudio/download/. Modern
scientists need to be comfortable installing software on their own
computers. This is a good opportunity for you to practice this important
skill, and we encourage you to try it. If you need any help, ask us.
How to Talk to a Computer
When programming a computer you must always remember one very
important fact: Computers Are Stupid.
Really. The computer “understands” only a very small and strictly
limited set of commands (the grammar and vocabulary of a
programming language). If you deviate from this set of commands in
any way, the computer cannot figure out what you mean. It is best
to think of your computer as a well-meaning, well-trained, but not
particularly bright dog. It wants to do as it is told, but if you use a
command it doesn’t know, it can’t figure out what you intend. Be nice to
your computer – don’t confuse it.
Using RStudio
RStudio is a program that can accept R statements and convey them to
the machine. In RStudio, you type in an R command, it is executed by the
machine, and RStudio can display the results of the command, if any.
In the first instance, just to make sure R and RStudio are working
correctly, we will type a few R commands directly into RStudio and
execute them in real time (see below). Later, we will see how to store a
set of R commands in a file so that we can run them repeatedly without
having to retype.
Parts of RStudio
The RStudio interface is divided into separate
panes. As you become more comfortable with RStudio, you
may wish to reorganise the locations of the different panes. In its
default configuration when it first opens, RStudio will have three
panes, each of which has multiple tabs. On the left is the Console pane.
This is where we will enter our first R commands. At the upper right is
the Environment pane. This is where we will see information about the
state of our program. At the lower right is the Files pane. Here we can
navigate among files on our computer. But more usefully, the Files pane
contains a tab labelled Plots. We will switch to this tab to see graphs
that we draw with R.
Parts of the R Programming Language
Programming languages have been designed to mimic human languages.
Therefore most of them have things (like nouns) and
actions (like verbs). Programming is just explaining to
the computer in ways it can understand, what actions to perform
on specific things. R understands many kinds of things and
many, many kinds of actions. We are going to start with the very
simplest case, just to practice interacting with RStudio (i.e., giving
it R commands to convey to the computer for us).
Numbers and mathematical operators
R understands numbers (things like 8 and 3.14159) and mathematical
operators (actions like + and -). We will type some numbers and
mathematical operators into RStudio and see how the computer
responds.
Code-along Exercise
Launch RStudio. If you have installed R and RStudio on your own
machine, you should have a Desktop (Windows) or Dock (Mac OS) icon that
you can click to launch RStudio. If not, search through the Programs
start-up menu (Windows) or Applications (Mac OS). Users of the Virtual
Student Desktop follow https://blogs.otago.ac.nz/studentit/student-desktop/student-desktop-own-device/
for how to access it from your computer.
The Console pane on the left will contain some explanatory text.
At the bottom of the text is a right angle bracket
>. That is where you will begin typing. There will
be a small, flashing, vertical line beside the angle bracket. (If you
don’t have the flashing vertical line, click your mouse beside and
slightly to the right of the angle bracket.)
Type the following characters into the Console pane, followed by
the Enter key.
If everything is working as it should, your screen should look like
this (the contents of the Files pane may be different):
You have given R two things: the number 4 and the
number 5. You have asked R to perform an action on
those things: addition. R has done so, and RStudio has displayed the
result (in this case, the value 9). It has also printed [1] on the
console screen. This is RStudio trying to help you. As your R commands
become more complicated, you will end up with many results rather than
just one. RStudio prints these numbers at the start of output lines to
help you count your results. It’s not really necessary when you only
have one result, but that’s just how RStudio behaves (we refer you again
to the picture of the well-meaning doggo above).
For the remainder of this document, we will not show you pictures of
the whole screen each time we enter an R command. Rather, we will
display what you should type and what output you should get like
this:
4 + 5
#> [1] 9
- Explore more of R’s mathematical operators. For division use / and
for multiplication use *. Enter each of these R commands into the
console and confirm that you receive the expected output.
10 / 8
8 * 12
6 - 12 + (3 * 7.4)
More actions: Function calls in R
R syntax (grammar) mimics mathematical equation syntax in some
respects. As we denote a function f(x) using round brackets in an
equation, so do we denote the application of a function in R. R knows
many useful functions. For example sqrt()
, which computes
the square root of a number, and abs()
which computes the
absolute value of a number. To apply one of these functions, we type the
name, and place the value we wish to operate on (the
argument) inside the round brackets.
Code-along Exercise
Try these examples:
abs(-42)
#> [1] 42
sqrt(200)
#> [1] 14.14214
Getting Help
Often you’ll need help for a specific function, such as
mean()
, you can search the help documentation using
?
in front of the function name to do this
(e.g. ?mean
) and this will bring up the manual page. It
provides information about what does, what the arguments are, and even
provides some examples that can be copy-pasted and run to give an
example of what it does.
The ?
is not the only way to find out how to run a
function – for more examples of how to find help refer to https://datacarpentry.org/R-ecology-lesson/00-before-we-start.html#Seeking_help
More things: Words
Lots of computing involves words rather than numbers. For example,
searching text and enrolling students by name both operate on words. R
understands words – the concept of things composed of
letters. However, when working with words, we must mark them
with special characters to prevent R from becoming confused (we see what
this confusion looks like in a moment).
In programming, a thing composed of letters doesn’t have to be a real
word (it could be, for example, a product code or user id), so we
actually call them strings. To denote a
string we surround it with quote marks, like this:
"plato"
#> [1] "plato"
There are functions that operate on strings, exactly equivalent to
ones like sqrt()
that operate on numbers. For example, R
has a function nchar()
that computes how many characters
(i.e. letters) are in its string argument.
nchar("plato")
#> [1] 5
Code-along Exercise
What do you think will happen if you give the commands below? Enter
them into the RStudio console to see.
nkhar("plato")
#> Error in nkhar("plato"): could not find function "nkhar"
sqrt("plato")
#> Error in sqrt("plato"): non-numeric argument to mathematical function
Remember that the language R is a set of vocabulary and grammar rules
that must be followed very strictly. There is no function
nkhar
in R’s vocabulary, only nchar
. And
function sqrt
only understands how to work on numbers, not
on strings.
R will never work out what you meant when you
deviate from its grammar. No programming language will. If you violate
its rules, R will throw an error. But this can be very instructive.
Enter the following command into RStudio and carefully consider the
outcome. What does this tell you about the rules of the R language?
NCHAR("plato")
#> Error in NCHAR("plato"): could not find function "NCHAR"
We know that R understands the function nchar
– we saw
it working just a few moments ago. But now it says it could not find
that function? This is because, to R, nchar
and
NCHAR
are not the same thing. R is a
case-sensitive language. Upper-case and lower-case
letters are completely different entities in R. When giving R commands
you must always exactly match its expectations about upper and lower
case (woof).
Storing Results
Imagine that you have two large numbers and, for some sound
scientific reason, you wish to take their ratio and then take the square
root of that value. Like this:
198.7 / 64.5
#> [1] 3.08062
sqrt(3.08062)
#> [1] 1.75517
This operation is risky. R has given you the ratio to five accurate
decimal places. But you must then be very careful to copy it
exactly into the sqrt
function, or your answer will be
wrong. Extrapolate this to thousands of data operations on a large data
set and it is certain that errors will be made.
It would be more convenient, and safer, to take the result R gave you
from the first statement, store it somewhere, and then pass the
stored entity to function sqrt. This is, in fact, a fundamental
action in programming: We can store values as named entities
(called variables) and use them whenever and wherever we need
them.
In R, this “storing” is performed with the <-
operator (called the “assignment” operator). The assignment
operator is formed by typing a left angle bracket and a hyphen. In the
following code example, we demonstrate the assignment operator. We also
demonstrate comments. In R, any text that is prefaced
with # is ignored rather than being treated as a command. It is just
text that the programmer adds for their own benefit.
Code-along Exercise
Make sure you can duplicate this code, with the same results, in
RStudio (you don’t need to type the comments).
# Store the result of the division in an entity (a variable) named ratio. We
# always use meaningful variable names.
ratio <- 198.7 / 64.5
# This will display the value of the variable named ratio. That's what R does
# when you enter a lone variable name.
ratio
#> [1] 3.08062
# This will pass the value of ratio as the argument to the sqrt function.
sqrt(ratio)
#> [1] 1.75517
Variable Names and Values
Look very carefully at the variable name on the left
hand side of the assignment operator <-. It is a string of
characters, but it is not surrounded by quote marks.
This is how, in R, we distinguish strings (a word thing – remember, like
“plato”) from variable names.
Inside our computer, variables are implemented (conceptually) as
shown below. A location in memory is “named”. When you refer to the
name, the computer supplies whatever value is stored at that
location.
This means that the value of a variable can change over time. (We
will see later that this turns out to be extremely useful.)
# Store the result of the division in an entity named ratio
ratio <- 198.7 / 64.5
# This will display the value of ratio. That's what R does when you enter a lone
# variable name.
ratio
#> [1] 3.08062
# Change the value stored in the variable named ratio by assigning it the result
# of a new command
ratio <- 25.9 * 12.15
# See the current value
ratio
#> [1] 314.685
Complex Things
One of the great strengths of R for data analysis is that “things” in
R aren’t restricted to single numbers or single strings. Things in R can
be collections – ordered sets of multiple things.
To get a collection, we must create it, using the built-in function
c()
. The c stands for combine. This
function combines multiple arguments into a single collection thing. In
R this kind of collection thing is called a vector.
Code-along Exercise
Enter these statements into RStudio, and check that you get the same
output.
# To combine elements into a vector, pass them to function c(), and separate
# them with commas
vector_of_primes <- c(1, 5, 7, 11)
vector_of_primes
#> [1] 1 5 7 11
animals <- c("Armadillo", "Buffalo", "Cougar")
animals
#> [1] "Armadillo" "Buffalo" "Cougar"
mixture <- c(1, "Buffalo", 42)
mixture
#> [1] "1" "Buffalo" "42"
Look very carefully at the third vector variable, mixture. Note that,
when it displays the vector, R has put quote marks around 1 and 42. That
is, R thinks they are strings (a series of alphanumeric characters), not
numbers. From this we see that:
Vectors must be homogeneous. That is, all the elements in the
vector must be the same kind (type) of thing.
If you don’t follow R’s rules, it will sometimes just enforce
them on your behalf. Here it sees that Buffalo is definitely a string.
It knows that vector elements have to be homogeneous, so it makes 1 and
42 into strings “1” and “42”. R is bossy this way.
(There are more complex things in R that allow combinations of
numbers and strings. Google “R lists” to explore.)
Operating on Vectors
The operators and functions we have used so far on single numbers and
strings (e.g. sqrt
, nchar
) will also work on
vectors. When you use this kind of function or operator with a vector, R
applies it to each element in turn, and returns all the results.
Code-along Exercise
Enter these statements into RStudio.
primes <- c(1, 5, 7, 11)
primes * 2
#> [1] 2 10 14 22
sqrt(primes)
#> [1] 1.000000 2.236068 2.645751 3.316625
Write Your Own Code
Enter a new command to divide all the values in vector
primes by 2. Make sure you get these results:
#> [1] 0.5 2.5 3.5 5.5
Note that vector operations work regardless of the number of elements
in the vector. You can have 1,000,000 data values in your vector and it
still requires only one command to process them all.
Whole-Vector Operations
There are also functions which summarise the contents of a vector.
For example, R has a function mean
that computes the
mathematical average of the elements in a vector, and a function
sd
that computes the standard deviation of the elements in
a vector. There are hundreds of such functions available, and we will
explore many of them throughout this mini-course.
Code-along Exercise
Enter these statements into RStudio.
exam_scores_vector <- c(82, 43, 97, 56, 78) # Create an example data vector
mean(exam_scores_vector) # Compute the mathematical mean of the exam scores
#> [1] 71.2
sd(exam_scores_vector) # Compute the standard deviation of the exam scores
#> [1] 21.53369
Write your own code
The R functions min
and max
return the
minimum and maximum values of a vector. Write commands to use these
functions on exam_scores_vector from the previous
exercise.
Not all R functions have such obvious names. Use Google or your
favourite R textbook to find out what function to call to get the
number of elements in a vector. Test this function on
exam_scores_vector.
Even More Complex Things
We have seen that R understands single numbers or strings, and
collections of numbers or strings (vectors). R also understands complete
tables of data (in rows and columns, like spreadsheets are arranged). In
fact, most real data analysis in R operates on tables of data. Some R
functions require you to first extract a row or column from your data
table; other functions will take an entire table and operate on it at
once (for example, many of the functions that perform inferential
statistical analyses operate on whole tables). In later modules, we will
use some of these functions. But before we do that, there is one more
very important mechanical feature of RStudio…
Saving Your Code
We have typed a lot of R commands into the console. When we close
RStudio, all that code will be gone forever. If we want
to do any of this again, we have to start over from the beginning and
type everything in again. This is unacceptable. So, RStudio lets us type
our code into a file, save the file, and retrieve the code whenever we
want, so that we can modify it or simply run it again.
Using a Script File
1. From the menu at the top of the RStudio screen select File->New
File then click on R Script. (Alternatively, you can type shift+ctrl+N
(Windows) or shift+cmd+N (Mac).)
2. This opens a new untitled file in an editing pane in the upper
left of the RStudio screen. The console pane will be pushed down to the
bottom half of the screen. You can click and drag the dividers between
the four panes to change their sizes as you prefer.
3. From the main RStudio menu select File->Save As.. to save your
file. Always give your files descriptive names to make it easy to find
the one you want later.
4. You can type R commands into the new file (in the upper left pane)
exactly as you typed into the console.
5. Executing a command that is typed into a file works a little
differently than executing a command that is typed into the console. To
execute a single line of code in the file, click your mouse cursor
anywhere on the line of code. DO NOT SELECT ANY CHARACTERS. HOLD
THE MOUSE STILL WHILE CLICKING. Then type ctrl+Enter (Windows)
or cmd+Enter (Mac).
6. To execute multiple lines of code in the file, select all the code
you want by clicking and dragging the mouse (ctrl+A or cmd+A for the
whole file), then type ctrl+Enter or cmd+Enter.
7. The output from your code will be written to the console, just as
though you had typed the code there.
8. After entering some code into your file, save it (the programmer’s
motto is Save Early, Save Often). You can then safely exit the RStudio
program.
9. Go to wherever you saved your named code file (it will have suffix
.R) and double-click on it to open it. The computer may ask you what
program to use – select RStudio.
10. The file will open in RStudio and you can run all your code again
(see items 5 and 6 above) without having to retype anything.
An Even Better Script File
We will cover RMarkdown in more depth in Module 6.
A basic script file (of type .R) will store and preserve your code.
RStudio also provides R Markdown files (of type .Rmd)
that can do much more. R Markdown is an extended script format that
allows you to embed R commands in formatted text. RStudio processes R
Markdown files, producing HTML, Word or pdf formats. During processing
(which is called knitting) RStudio runs any embedded R commands
and inserts the results into the output document. You
don’t need to process your data in RStudio and then copy/paste the
results into a separate Word document. You can insert the code directly
into your text in an R Markdown file, and it will be executed when
RStudio knits. Let’s give it a try:
1. In RStudio, click on the File menu, select New File and, from the
submenu that opens, click on R Markdown.
2. A dialogue box will open, where you have a chance to enter a title
for your document and the name of the author. These will appear at the
top of the knit document. You can select the output format. Leave it as
HTML for this exercise.
3. RStudio will create a new file and open it in a new tab. The file
is untitled, so save it and give it a sensible name.
The file already contains some text. This is some sample contents to
give you an idea of what an R Markdown file looks like. You will note
that the file has areas with a white background and areas with a shaded
background. The white areas are plain text, the shaded areas are R
commands. When the file is knit, that code will be run, and its output
inserted into the text. To see this in action, click the
Knit icon at the top the RStudio tab.
RStudio will produce a beautiful HTML document and open it in a local
browser window. See if you can match the R code segments in the R
Markdown document to the output that appears in the HTML page.
R Markdown is a powerful tool for generating research reports when
analysing data with R. As we proceed through this mini-course we will
explore additional features of R Markdown, and you may wish to consider
using it for your own course assignments. Check with your lecturers to
see if this is suitable.
Conclusion
In this module you have considered the inner workings of the
computer, written R commands into the RStudio Development Environment,
met some of the things R understands (number, strings, and vectors) and
some of the actions R can perform (functions). Congratulations.
What’s Next
Fill in the module feedback form https://tinyurl.com/r4ssp-module-fb.
In our next module, we will learn how to read real data files into R
and make plots and figures that you can use in a research report. We
will start with simple plots you can create using only base R. Then we
will learn to use a powerful graphics library called
ggplot (part of the tidyverse family
of R extensions). With ggplot you can make publication-quality graphs
with only a few lines of R code.
LS0tCnRpdGxlOiAiSW50cm9kdWNpbmcgUiBhbmQgUlN0dWRpbyIKZGF0ZTogIlNlbWVzdGVyIDIsIDIwMjIiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93Ci0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoa25pdHIpCgprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgY29tbWVudCA9ICIjPiIsCiAgZmlnLnBhdGggPSAiZmlndXJlcy8wMS8iLCAjIHVzZSBvbmx5IGZvciBzaW5nbGUgUm1kIGZpbGVzCiAgY29sbGFwc2UgPSBUUlVFLAogIGVjaG8gPSBUUlVFCikKCgpgYGAKCgo+ICMjIyMgQXNzb2NpYXRlZCBtYXRlcmlhbAo+Cj4gWm9vbSBub3RlczogW1pvb20gbm90ZXMgMDEgLSBJbnRyb2R1Y2luZyBSIGFuZCBSU3R1ZGlvXSh6b29tX25vdGVzXzAxLmh0bWwpCj4gCj4gUmVhZGluZ3M6Cj4KPiAtIFtSIGZvciBEYXRhIFNjaWVuY2UgLSBDaGFwdGVyIDFdKGh0dHBzOi8vcjRkcy5oYWQuY28ubnovaW50cm9kdWN0aW9uLmh0bWwpCj4gLSBbUiBmb3IgRGF0YSBTY2llbmNlIC0gQ2hhcHRlciA0XShodHRwczovL3I0ZHMuaGFkLmNvLm56L3dvcmtmbG93LWJhc2ljcy5odG0pCgojIyMjIEJlZm9yZSB3ZSBzdGFydAoKVGhpcyBjb3Vyc2UgaXMgZGVzaWduZWQgd2l0aCB0d28gY29tcG9uZW50cyAtIHRoZSBtb2R1bGUgYW5kIHRoZSB6b29tIG5vdGVzLiBUaGUgbW9kdWxlIGNvbnRlbnQgcHJvdmlkZXMgbW9yZSBleHBsYW5hdGlvbiBhbmQgYmFja2dyb3VuZCBzbyB0aGF0IHlvdSBjYW4gd29yayB0aHJvdWdoIGl0IG9uIHlvdXIgb3duIGlmIHlvdSB3aXNoLiBUaGUgem9vbSBub3RlcyBjb250ZW50IHByb3ZpZGVzIHRoZSBzdHJ1Y3R1cmUgZm9yIHRoZSBjb250ZW50IHRoYXQgd2lsbCBiZSBkZWxpdmVyZWQgaW4gdGhlIG9ubGluZSBzZXNzaW9ucy4gQm90aCBzZXRzIG9mIGNvbnRlbnQgYXJlIGNvbXBsZW1lbnRhcnkgdG8gZWFjaCBvdGhlci4KCkF0IHRoZSB0b3AgcmlnaHQgaGFuZCBjb3JuZXIgb2YgYm90aCB0aGUgbW9kdWxlIGFuZCB6b29tIG5vdGVzIHBhZ2VzIGlzIGEgImNvZGUiIGJ1dHRvbi4gVGhpcyBjYW4gYmUgdXNlZCB0byB0b2dnbGUgc2VlaW5nL2hpZGluZyB0aGUgY29kZSBvciB0byBkb3dubG9hZCB0aGUgY29kZSB0aGF0IHRoYXQgY3JlYXRlZCB0aGUgcGFnZSBhcyBhbiBSbWFya2Rvd24gZmlsZSAod2UgY292ZXIgUm1hcmtkb3duIG1vcmUgaW4tZGVwdGggaW4gW21vZHVsZV0oMDYtY29tbXVuaWNhdGUuaHRtbCkvW3pvb20gbm90ZXNdKHpvb21fbm90ZXNfMDYuaHRtbCkgNikuCgoKCgoKClwKCiMgSW50cm9kdWN0aW9uCgpBZHZhbmNlcyBpbiBjb21wdXRpbmcgYW5kIHNlbnNpbmcgdGVjaG5vbG9naWVzIG1lYW4gdGhhdCBtb2Rlcm4gc2NpZW50aWZpYyByZXNlYXJjaCBvZnRlbiBpbnZvbHZlcyB2ZXJ5IGxhcmdlIGRhdGEgc2V0cy4gVGhlcmUgYXJlIG5vdyBtYW55IGNvbXB1dGVyIHNvZnR3YXJlIHRvb2xzIGF2YWlsYWJsZSB0byB3b3JrIHdpdGggYmlnIGRhdGEsIGFuZCBzY2llbnRpc3RzIGZyb20gYWxsIGRpc2NpcGxpbmVzIG5lZWQgdG8gYmUgYWJsZSB0byB1c2UgdGhlbS4KCkluIHRoaXMgbWluaS1jb3Vyc2UsIHdlIHdpbGwgaGVscCB5b3UgbGVhcm4gdG8gdXNlIG9uZSBvZiB0aGUgbW9zdCBpbnRlcmVzdGluZyAoYW5kIHBvcHVsYXIpIG9mIHRoZXNlIHRvb2xzIC0tIHRoZSBwcm9ncmFtbWluZyBsYW5ndWFnZSBSLiBSIGlzIGEgc3BlY2lhbC1wdXJwb3NlIG9wZW4tc291cmNlIGxhbmd1YWdlIGZvciBzdGF0aXN0aWNzIGFuZCBkYXRhIGFuYWx5c2lzLiBJbmNyZWFzaW5nbHksIFIgaXMgdGhlIHByZWZlcnJlZCB0b29sIGZvciBhbmFseXNpbmcgYW5kIHByZXNlbnRpbmcgZGF0YSBmb3Igc3R1ZGVudCByZXNlYXJjaCBwcm9qZWN0cy4KCkluIHRoaXMgbW9kdWxlLCB3ZSBzaG93IHlvdSBob3cgdG8gZ2V0IHN0YXJ0ZWQgd2l0aCBSLiBXZSB3aWxsIG5vdCBhc3N1bWUgdGhhdCB5b3UgaGF2ZSBhbnkgcHJpb3IgY29tcHV0ZXIgcHJvZ3JhbW1pbmcgZXhwZXJpZW5jZS4gSW4gZmFjdCwgaWYgeW91IGhhdmUgcHJvZ3JhbW1lZCBiZWZvcmUgaW4gYSBsYW5ndWFnZSBsaWtlIEphdmEgb3IgQywgYmUgYXdhcmUgdGhhdCBSIGlzLCBpbiBtYW55IHJlc3BlY3RzLCB2ZXJ5IGRpZmZlcmVudCBmcm9tIHRob3NlIGxhbmd1YWdlcyAtLSBzbyBrZWVwIGFuIG9wZW4gbWluZC4KCldlIHdpbGwgYmVnaW4gYnkgZXhwbGFpbmluZyB0aGUgZGlmZmVyZW50IHNvZnR3YXJlIHRvb2xzIHlvdSBuZWVkLCBhbmQgaG93IHRvIGdldCB0aGVtIG9udG8geW91ciBvd24gY29tcHV0ZXJzLCBpZiB5b3Ugd2lzaCB0byBkbyBzby4gVGhlbiB3ZSB3aWxsIGRpc2N1c3MgdGhlIGJhc2ljIG1lY2hhbmljcyBvZiB0aGVzZSB0b29scy4gVGhyb3VnaG91dCB0aGlzIGhhbmRvdXQgKGFuZCBhbGwgbWF0ZXJpYWxzIGZvciB0aGlzIG1pbmktY291cnNlKSB0aGVyZSBhcmUgY29kZSBleGFtcGxlcyBhbmQgUiBleGVyY2lzZXMgdGhhdCB5b3Ugc2hvdWxkIHdvcmsgdGhyb3VnaCBjYXJlZnVsbHkgb24gdGhlIGNvbXB1dGVyLiBUaGlzIHdpbGwgcHJlcGFyZSB5b3UgdG8gdXNlIFIgZm9yIHlvdXIgaW4tY291cnNlIHJlc2VhcmNoIHByb2plY3RzIGxhdGVyIGluIHRoZSBzZW1lc3Rlci4KClRoaXMgaGFuZG91dCBpcyBkZXNpZ25lZCB0byBiZSByZWFkIGluIGNvbmp1bmN0aW9uIHdpdGggQ2hhcHRlciAxOiBJbnRyb2R1Y3Rpb24gb2YgW1IgZm9yIERhdGEgU2NpZW5jZV0oaHR0cHM6Ly9yNGRzLmhhZC5jby5ueikuCgpcCgpcCgojIyBUaGUgVG9vbHMKCldlIHRoaW5rIG9mIGNvbXB1dGVycyBhcyBzdG9yaW5nIHJpY2ggbWVhbmluZ2Z1bCBkYXRhIChtb3N0bHkgY2F0IHZpZGVvcykuIEFjdHVhbGx5LCB3aGF0IGNvbXB1dGVycyByZWFsbHkgY29udGFpbiBhcmUgbWlsbGlvbnMgb2YgdGlueSBsaXR0bGUgc3RvcmFnZSB1bml0cywgZWFjaCBvZiB3aGljaCBlaXRoZXIgaG9sZHMgYW4gZWxlY3RyaWNhbCBjaGFyZ2UgKHVzdWFsbHkgY2FsbGVkIGEgMSkgb3IgaG9sZHMgbm90aGluZyAodXN1YWxseSBjYWxsZWQgYSAwKS4gUmVhbGx5LiBUaGF0J3MgaXQuIFRoYXQncyBhbGwgdGhlcmUgaXMuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwPSJXaGF0J3MgaW5zaWRlIHRoZSBjb21wdXRlciIsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNTAlIn0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLWNvbXB1dGVyLnBuZyIgKQpgYGAKCkFsbCBvZiB0aGUgYW1hemluZyB0aGluZ3MgdGhhdCBjb21wdXRlcnMgZG8gaGFwcGVuIHRocm91Z2ggZXh0cmVtZWx5IGNvbXBsaWNhdGVkIG1hbmlwdWxhdGlvbiBvZiBhbGwgdGhvc2UgMHMgYW5kIDFzLlRoaXMgaW52b2x2ZXMgYSBsb3Qgb2YgbWF0aHMgYW5kIGEgbG90IG9mIGVsZWN0cm9uaWNzLCBhbmQgaXMgdmVyeSwgdmVyeSBjb25mdXNpbmcuIFNvIHRoYXQgY29tcHV0ZXIgdXNlcnMgZG9uJ3QgaGF2ZSB0byB0aGluayBhYm91dCBhbGwgdGhlc2UgMHMgYW5kIDFzLCBjb21wdXRlciBzY2llbnRpc3RzIGhhdmUgZGV2ZWxvcGVkICoqcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzKiosIHdoaWNoIGFyZSBzeW1ib2xpYyBzeXN0ZW1zIHRoYXQgd2UgY2FuIHVzZSB0byBleHByZXNzIHdoYXQgd2Ugd2FudCB0byBoYXBwZW4gaW5zaWRlIHRoZSBtYWNoaW5lLiBQcm9ncmFtbWluZyBsYW5ndWFnZXMgYXJlIGRlc2lnbmVkIHRvIGJlIHNpbWlsYXIgdG8gaHVtYW4gbGFuZ3VhZ2VzLCBzbyB0aGV5IGFyZSBlYXN5IGZvciB1cyB0byB3b3JrIHdpdGguIE92ZXIgdGhlIGxhc3QgNjAgeWVhcnMgbWFueSBzdWNoIGxhbmd1YWdlcyBoYXZlIGJlZW4gZGV2ZWxvcGVkOiBGT1JUUkFOLCBCQVNJQywgQywgSmF2YSwgUHl0aG9uLCBldGMuLCBhbmQgdGhlIG9uZSB3ZSBhcmUgdXNpbmcgaW4gdGhpcyBtaW5pLWNvdXJzZSwgUi4gRWFjaCBwcm9ncmFtbWluZyBsYW5ndWFnZSBoYXMgYSB2b2NhYnVsYXJ5IGFuZCBhIGdyYW1tYXIgKGp1c3QgbGlrZSBodW1hbiBsYW5ndWFnZXMpIHdoaWNoIG11c3QgYmUgZm9sbG93ZWQgKipleGFjdGx5KiogKHRoZXkgYXJlLCBpbiBmYWN0LCBtdWNoIHN0cmljdGVyIGFib3V0IHRoaXMgdGhhbiBodW1hbiBsYW5ndWFnZXMpLgoKVG8gY29tbXVuaWNhdGUgd2l0aCB5b3VyIGNvbXB1dGVyIHVzaW5nIGEgcHJvZ3JhbSBsYW5ndWFnZSwgeW91IG5lZWQgYSBzcGVjaWFsIGNvbXB1dGVyIHByb2dyYW0gKHByZXZpb3VzbHkgd3JpdHRlbiBpbiBhIHByb2dyYW1taW5nIGxhbmd1YWdlLCBvZiBjb3Vyc2UpIHRoYXQga25vd3MgaG93IHRvIHRyYW5zbGF0ZSBmcm9tIHRoZSBodW1hbi1mcmllbmRseSBwcm9ncmFtbWluZyBsYW5ndWFnZSBpbnRvIGFjdGlvbnMgb24gdGhlIGNvbXB1dGVyLiBUaGVzZSBhcmUgY2FsbGVkICoqRGV2ZWxvcG1lbnQgRW52aXJvbm1lbnRzKiosIGJlY2F1c2UgdGhpcyBpcyB3aGVyZSBwZW9wbGUgZGV2ZWxvcCBzb2Z0d2FyZS4KCmBgYHtyLCBmaWcuY2FwID0gIkFsbCBUaGUgUGFydHMiLCBlY2hvPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iMTAwJSJ9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1sYW5ndWFnZV9pZGVfbWFjaGluZS5wbmciKQpgYGAKClRoZSBtb3N0IHBvcHVsYXIgZGV2ZWxvcG1lbnQgZW52aXJvbm1lbnQgZm9yIFIgaXMgYSBwcm9ncmFtIGNhbGxlZCAqKlJTdHVkaW8qKi4KCkJvdGggUiBhbmQgUlN0dWRpbyBhcmUgaW5zdGFsbGVkIG9uIHRoZSBjb21wdXRlcnMgaW4gdGhlIE90YWdvIFVuaXZlcnNpdHkgY29tcHV0ZXIgbGFicy4gWW91IGNhbiB3b3JrIHRocm91Z2ggdGhpcyBkb2N1bWVudCBvbiB0aG9zZSBtYWNoaW5lcy4KCllvdSBjYW4gYWxzbyBpbnN0YWxsIHRoZSBSIGxhbmd1YWdlIGFuZCB0aGUgUlN0dWRpbyBwcm9ncmFtIG9uIHlvdXIgb3duIHBlcnNvbmFsIGNvbXB1dGVycy4gVGhlc2UgYXJlIGNvbXBsZXRlbHkgb3Blbi1zb3VyY2UsIGZyZWUsIGFuZCBzYWZlLgoKRmlyc3QsIGluc3RhbGwgUiBmcm9tIDxodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy9iaW4vd2luZG93cy9iYXNlLz4gKGZvciBXaW5kb3dzIG1hY2hpbmVzKSBvciA8aHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvYmluL21hY29zeC8+IChmb3IgTWFjIE9TIG1hY2hpbmVzKS4gVGhlbiBpbnN0YWxsIFJTdHVkaW8gZnJvbSA8aHR0cHM6Ly9yc3R1ZGlvLmNvbS9wcm9kdWN0cy9yc3R1ZGlvL2Rvd25sb2FkLz4uIE1vZGVybiBzY2llbnRpc3RzIG5lZWQgdG8gYmUgY29tZm9ydGFibGUgaW5zdGFsbGluZyBzb2Z0d2FyZSBvbiB0aGVpciBvd24gY29tcHV0ZXJzLiBUaGlzIGlzIGEgZ29vZCBvcHBvcnR1bml0eSBmb3IgeW91IHRvIHByYWN0aWNlIHRoaXMgaW1wb3J0YW50IHNraWxsLCBhbmQgd2UgZW5jb3VyYWdlIHlvdSB0byB0cnkgaXQuIElmIHlvdSBuZWVkIGFueSBoZWxwLCBhc2sgdXMuCgpcCgpcCgojIyBIb3cgdG8gVGFsayB0byBhIENvbXB1dGVyCgpXaGVuIHByb2dyYW1taW5nIGEgY29tcHV0ZXIgeW91IG11c3QgYWx3YXlzIHJlbWVtYmVyIG9uZSB2ZXJ5IGltcG9ydGFudCBmYWN0OiBDb21wdXRlcnMgQXJlIFN0dXBpZC4KClJlYWxseS4gVGhlIGNvbXB1dGVyICJ1bmRlcnN0YW5kcyIgb25seSBhIHZlcnkgc21hbGwgYW5kICpzdHJpY3RseSBsaW1pdGVkKiBzZXQgb2YgY29tbWFuZHMgKHRoZSBncmFtbWFyIGFuZCB2b2NhYnVsYXJ5IG9mIGEgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UpLiBJZiB5b3UgZGV2aWF0ZSBmcm9tIHRoaXMgc2V0IG9mIGNvbW1hbmRzICppbiBhbnkgd2F5KiwgdGhlIGNvbXB1dGVyIGNhbm5vdCBmaWd1cmUgb3V0IHdoYXQgeW91IG1lYW4uIEl0IGlzIGJlc3QgdG8gdGhpbmsgb2YgeW91ciBjb21wdXRlciBhcyBhIHdlbGwtbWVhbmluZywgd2VsbC10cmFpbmVkLCBidXQgbm90IHBhcnRpY3VsYXJseSBicmlnaHQgZG9nLiBJdCB3YW50cyB0byBkbyBhcyBpdCBpcyB0b2xkLCBidXQgaWYgeW91IHVzZSBhIGNvbW1hbmQgaXQgZG9lc24ndCBrbm93LCBpdCBjYW4ndCBmaWd1cmUgb3V0IHdoYXQgeW91IGludGVuZC4gQmUgbmljZSB0byB5b3VyIGNvbXB1dGVyIC0tIGRvbid0IGNvbmZ1c2UgaXQuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwID0gIkNvbmZ1c2VkIERvZyIsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLWRvZy5qcGciKQpgYGAKCjwhLS0gSW1hZ2U6IGh0dHBzOi8vaW1nZmxpcC5jb20vbWVtZXRlbXBsYXRlLzExNjIzNTU2OC9jb25mdXNlZC1kb2cgLS0+CgpcCgpcCgojIFVzaW5nIFJTdHVkaW8KClJTdHVkaW8gaXMgYSBwcm9ncmFtIHRoYXQgY2FuIGFjY2VwdCBSIHN0YXRlbWVudHMgYW5kIGNvbnZleSB0aGVtIHRvIHRoZSBtYWNoaW5lLiBJbiBSU3R1ZGlvLCB5b3UgdHlwZSBpbiBhbiBSIGNvbW1hbmQsIGl0IGlzIGV4ZWN1dGVkIGJ5IHRoZSBtYWNoaW5lLCBhbmQgUlN0dWRpbyBjYW4gZGlzcGxheSB0aGUgcmVzdWx0cyBvZiB0aGUgY29tbWFuZCwgaWYgYW55LgoKSW4gdGhlIGZpcnN0IGluc3RhbmNlLCBqdXN0IHRvIG1ha2Ugc3VyZSBSIGFuZCBSU3R1ZGlvIGFyZSB3b3JraW5nIGNvcnJlY3RseSwgd2Ugd2lsbCB0eXBlIGEgZmV3IFIgY29tbWFuZHMgZGlyZWN0bHkgaW50byBSU3R1ZGlvIGFuZCBleGVjdXRlIHRoZW0gaW4gcmVhbCB0aW1lIChzZWUgYmVsb3cpLiBMYXRlciwgd2Ugd2lsbCBzZWUgaG93IHRvIHN0b3JlIGEgc2V0IG9mIFIgY29tbWFuZHMgaW4gYSBmaWxlIHNvIHRoYXQgd2UgY2FuIHJ1biB0aGVtIHJlcGVhdGVkbHkgd2l0aG91dCBoYXZpbmcgdG8gcmV0eXBlLgoKXAoKIyMgUGFydHMgb2YgUlN0dWRpbwoKVGhlIFJTdHVkaW8gaW50ZXJmYWNlIGlzIGRpdmlkZWQgaW50byBzZXBhcmF0ZSAqKnBhbmVzKiouIEFzIHlvdSBiZWNvbWUgbW9yZSBjb21mb3J0YWJsZSB3aXRoIFJTdHVkaW8sIHlvdSBtYXkgd2lzaCB0byByZW9yZ2FuaXNlIHRoZSBsb2NhdGlvbnMgb2YgdGhlIGRpZmZlcmVudCBwYW5lcy4gSW4gaXRzIGRlZmF1bHQgY29uZmlndXJhdGlvbiB3aGVuIGl0IGZpcnN0IG9wZW5zLCBSU3R1ZGlvIHdpbGwgaGF2ZSB0aHJlZSBwYW5lcywgZWFjaCBvZiB3aGljaCBoYXMgbXVsdGlwbGUgdGFicy4gT24gdGhlIGxlZnQgaXMgdGhlIENvbnNvbGUgcGFuZS4gVGhpcyBpcyB3aGVyZSB3ZSB3aWxsIGVudGVyIG91ciBmaXJzdCBSIGNvbW1hbmRzLiBBdCB0aGUgdXBwZXIgcmlnaHQgaXMgdGhlIEVudmlyb25tZW50IHBhbmUuIFRoaXMgaXMgd2hlcmUgd2Ugd2lsbCBzZWUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHN0YXRlIG9mIG91ciBwcm9ncmFtLiBBdCB0aGUgbG93ZXIgcmlnaHQgaXMgdGhlIEZpbGVzIHBhbmUuIEhlcmUgd2UgY2FuIG5hdmlnYXRlIGFtb25nIGZpbGVzIG9uIG91ciBjb21wdXRlci4gQnV0IG1vcmUgdXNlZnVsbHksIHRoZSBGaWxlcyBwYW5lIGNvbnRhaW5zIGEgdGFiIGxhYmVsbGVkIFBsb3RzLiBXZSB3aWxsIHN3aXRjaCB0byB0aGlzIHRhYiB0byBzZWUgZ3JhcGhzIHRoYXQgd2UgZHJhdyB3aXRoIFIuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwID0gIlJTdHVkaW8iLCBlY2hvID0gRkFMU0UsIGZpZy5wb3MgPSAiSCIsIG91dC53aWR0aD0iMTAwJSJ9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1SU3R1ZGlvLnBuZyIpCmBgYAoKIyMjIFVzaW5nIFByb2plY3RzIGluIFJTdHVkaW8KClJTdHVkaW8gcHJvamVjdHMgYXJlIGEgZ3JlYXQgd2F5IG9mIGNvbXBhcnRtZW50YWxpc2luZyBhbmFseXNlcy4gSW4gW1IgZm9yIERhdGEgU2NpZW5jZSAtIFdvcmtmbG93OiBQcm9qZWN0cyAoaHR0cHM6Ly9yNGRzLmhhZC5jby5uei93b3JrZmxvdy1wcm9qZWN0cy5odG1sKV0oaHR0cHM6Ly9yNGRzLmhhZC5jby5uei93b3JrZmxvdy1wcm9qZWN0cy5odG1sKSBjaGFwdGVyIGl0IGRpc2N1c3NlcyBzb21lIGdvb2QgcHJhY3RpY2VzIGFuZCBjb25maWd1cmF0aW9ucyB0byBoZWxwIHlvdSB3b3JrIHdpdGggUlN0dWRpbyBlZmZlY3RpdmVseS4KCkl0IGlzIGhpZ2hseSByZWNvbW1lbmRlZCB0byByZWFkIHRoaXMgY2hhcHRlciBhbmQgaW1wbGVtZW50IHRoZSBzdWdnZXN0ZWQgY29uZmlndXJhdGlvbiBjaGFuZ2VzLgoKXAoKXAoKIyBQYXJ0cyBvZiB0aGUgUiBQcm9ncmFtbWluZyBMYW5ndWFnZQoKUHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzIGhhdmUgYmVlbiBkZXNpZ25lZCB0byBtaW1pYyBodW1hbiBsYW5ndWFnZXMuIFRoZXJlZm9yZSBtb3N0IG9mIHRoZW0gaGF2ZSAqKnRoaW5ncyoqIChsaWtlIG5vdW5zKSBhbmQgKiphY3Rpb25zKiogKGxpa2UgdmVyYnMpLiBQcm9ncmFtbWluZyBpcyBqdXN0IGV4cGxhaW5pbmcgdG8gdGhlIGNvbXB1dGVyIGluIHdheXMgaXQgY2FuIHVuZGVyc3RhbmQsIHdoYXQgKmFjdGlvbnMqIHRvIHBlcmZvcm0gb24gc3BlY2lmaWMgKnRoaW5ncyouIFIgdW5kZXJzdGFuZHMgbWFueSBraW5kcyBvZiB0aGluZ3MgYW5kIG1hbnksIG1hbnkga2luZHMgb2YgYWN0aW9ucy4gV2UgYXJlIGdvaW5nIHRvIHN0YXJ0IHdpdGggdGhlIHZlcnkgc2ltcGxlc3QgY2FzZSwganVzdCB0byBwcmFjdGljZSBpbnRlcmFjdGluZyB3aXRoIFJTdHVkaW8gKGkuZS4sIGdpdmluZyBpdCBSIGNvbW1hbmRzIHRvIGNvbnZleSB0byB0aGUgY29tcHV0ZXIgZm9yIHVzKS4KClwKCiMjIE51bWJlcnMgYW5kIG1hdGhlbWF0aWNhbCBvcGVyYXRvcnMKClIgdW5kZXJzdGFuZHMgbnVtYmVycyAodGhpbmdzIGxpa2UgOCBhbmQgMy4xNDE1OSkgYW5kIG1hdGhlbWF0aWNhbCBvcGVyYXRvcnMgKGFjdGlvbnMgbGlrZSArIGFuZCAtKS4gV2Ugd2lsbCB0eXBlIHNvbWUgbnVtYmVycyBhbmQgbWF0aGVtYXRpY2FsIG9wZXJhdG9ycyBpbnRvIFJTdHVkaW8gYW5kIHNlZSBob3cgdGhlIGNvbXB1dGVyIHJlc3BvbmRzLgoKXAoKIyMjIENvZGUtYWxvbmcgRXhlcmNpc2UKCjEuICBMYXVuY2ggUlN0dWRpby4gSWYgeW91IGhhdmUgaW5zdGFsbGVkIFIgYW5kIFJTdHVkaW8gb24geW91ciBvd24gbWFjaGluZSwgeW91IHNob3VsZCBoYXZlIGEgRGVza3RvcCAoV2luZG93cykgb3IgRG9jayAoTWFjIE9TKSBpY29uIHRoYXQgeW91IGNhbiBjbGljayB0byBsYXVuY2ggUlN0dWRpby4gSWYgbm90LCBzZWFyY2ggdGhyb3VnaCB0aGUgUHJvZ3JhbXMgc3RhcnQtdXAgbWVudSAoV2luZG93cykgb3IgQXBwbGljYXRpb25zIChNYWMgT1MpLiBVc2VycyBvZiB0aGUgVmlydHVhbCBTdHVkZW50IERlc2t0b3AgZm9sbG93IDxodHRwczovL2Jsb2dzLm90YWdvLmFjLm56L3N0dWRlbnRpdC9zdHVkZW50LWRlc2t0b3Avc3R1ZGVudC1kZXNrdG9wLW93bi1kZXZpY2UvPiBmb3IgaG93IHRvIGFjY2VzcyBpdCBmcm9tIHlvdXIgY29tcHV0ZXIuCgoyLiAgVGhlIENvbnNvbGUgcGFuZSBvbiB0aGUgbGVmdCB3aWxsIGNvbnRhaW4gc29tZSBleHBsYW5hdG9yeSB0ZXh0LiBBdCB0aGUgYm90dG9tIG9mIHRoZSB0ZXh0IGlzIGEgcmlnaHQgYW5nbGUgYnJhY2tldCAqKlw+KiouIFRoYXQgaXMgd2hlcmUgeW91IHdpbGwgYmVnaW4gdHlwaW5nLiBUaGVyZSB3aWxsIGJlIGEgc21hbGwsIGZsYXNoaW5nLCB2ZXJ0aWNhbCBsaW5lIGJlc2lkZSB0aGUgYW5nbGUgYnJhY2tldC4gKElmIHlvdSBkb24ndCBoYXZlIHRoZSBmbGFzaGluZyB2ZXJ0aWNhbCBsaW5lLCBjbGljayB5b3VyIG1vdXNlIGJlc2lkZSBhbmQgc2xpZ2h0bHkgdG8gdGhlIHJpZ2h0IG9mIHRoZSBhbmdsZSBicmFja2V0LikKCjMuICBUeXBlIHRoZSBmb2xsb3dpbmcgY2hhcmFjdGVycyBpbnRvIHRoZSBDb25zb2xlIHBhbmUsIGZvbGxvd2VkIGJ5IHRoZSA8a2JkPkVudGVyPC9rYmQ+IGtleS4KClteMV06IAoKKio0ICsgNSoqCgpJZiBldmVyeXRoaW5nIGlzIHdvcmtpbmcgYXMgaXQgc2hvdWxkLCB5b3VyIHNjcmVlbiBzaG91bGQgbG9vayBsaWtlIHRoaXMgKHRoZSBjb250ZW50cyBvZiB0aGUgRmlsZXMgcGFuZSBtYXkgYmUgZGlmZmVyZW50KToKCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0gIjEwMCUiLCBmaWcucG9zPSJIIiwgZmlnLmNhcCA9ICJGaXJzdCBSIENvbW1hbmQiLCBlY2hvID0gRkFMU0V9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1maXJzdF9jb21tYW5kLnBuZyIpCmBgYAoKWW91IGhhdmUgZ2l2ZW4gUiB0d28gKip0aGluZ3MqKjogdGhlIG51bWJlciA0IGFuZCB0aGUgbnVtYmVyIDUuIFlvdSBoYXZlIGFza2VkIFIgdG8gcGVyZm9ybSBhbiAqKmFjdGlvbioqIG9uIHRob3NlIHRoaW5nczogYWRkaXRpb24uIFIgaGFzIGRvbmUgc28sIGFuZCBSU3R1ZGlvIGhhcyBkaXNwbGF5ZWQgdGhlIHJlc3VsdCAoaW4gdGhpcyBjYXNlLCB0aGUgdmFsdWUgOSkuIEl0IGhhcyBhbHNvIHByaW50ZWQgWzFdIG9uIHRoZSBjb25zb2xlIHNjcmVlbi4gVGhpcyBpcyBSU3R1ZGlvIHRyeWluZyB0byBoZWxwIHlvdS4gQXMgeW91ciBSIGNvbW1hbmRzIGJlY29tZSBtb3JlIGNvbXBsaWNhdGVkLCB5b3Ugd2lsbCBlbmQgdXAgd2l0aCBtYW55IHJlc3VsdHMgcmF0aGVyIHRoYW4ganVzdCBvbmUuIFJTdHVkaW8gcHJpbnRzIHRoZXNlIG51bWJlcnMgYXQgdGhlIHN0YXJ0IG9mIG91dHB1dCBsaW5lcyB0byBoZWxwIHlvdSBjb3VudCB5b3VyIHJlc3VsdHMuIEl0J3Mgbm90IHJlYWxseSBuZWNlc3Nhcnkgd2hlbiB5b3Ugb25seSBoYXZlIG9uZSByZXN1bHQsIGJ1dCB0aGF0J3MganVzdCBob3cgUlN0dWRpbyBiZWhhdmVzICh3ZSByZWZlciB5b3UgYWdhaW4gdG8gdGhlIHBpY3R1cmUgb2YgdGhlIHdlbGwtbWVhbmluZyBkb2dnbyBhYm92ZSkuCgpGb3IgdGhlIHJlbWFpbmRlciBvZiB0aGlzIGRvY3VtZW50LCB3ZSB3aWxsIG5vdCBzaG93IHlvdSBwaWN0dXJlcyBvZiB0aGUgd2hvbGUgc2NyZWVuIGVhY2ggdGltZSB3ZSBlbnRlciBhbiBSIGNvbW1hbmQuIFJhdGhlciwgd2Ugd2lsbCBkaXNwbGF5IHdoYXQgeW91IHNob3VsZCB0eXBlIGFuZCB3aGF0IG91dHB1dCB5b3Ugc2hvdWxkIGdldCBsaWtlIHRoaXM6CgpgYGB7ciBmaXJzdF9jb21tYW5kfQo0ICsgNQpgYGAKCjQuICBFeHBsb3JlIG1vcmUgb2YgUidzIG1hdGhlbWF0aWNhbCBvcGVyYXRvcnMuIEZvciBkaXZpc2lvbiB1c2UgLyBhbmQgZm9yIG11bHRpcGxpY2F0aW9uIHVzZSBcKi4gRW50ZXIgZWFjaCBvZiB0aGVzZSBSIGNvbW1hbmRzIGludG8gdGhlIGNvbnNvbGUgYW5kIGNvbmZpcm0gdGhhdCB5b3UgcmVjZWl2ZSB0aGUgZXhwZWN0ZWQgb3V0cHV0LgoKYGBge3IgbW9yZSBtYXRocywgZXZhbCA9IEZBTFNFfQoxMCAvIDgKCjggKiAxMgoKNiAtIDEyICsgKDMgKiA3LjQpCmBgYAoKXAoKIyMgTW9yZSBhY3Rpb25zOiBGdW5jdGlvbiBjYWxscyBpbiBSCgpSIHN5bnRheCAoZ3JhbW1hcikgbWltaWNzIG1hdGhlbWF0aWNhbCBlcXVhdGlvbiBzeW50YXggaW4gc29tZSByZXNwZWN0cy4gQXMgd2UgZGVub3RlIGEgZnVuY3Rpb24gZih4KSB1c2luZyByb3VuZCBicmFja2V0cyBpbiBhbiBlcXVhdGlvbiwgc28gZG8gd2UgZGVub3RlIHRoZSBhcHBsaWNhdGlvbiBvZiBhIGZ1bmN0aW9uIGluIFIuIFIga25vd3MgbWFueSB1c2VmdWwgZnVuY3Rpb25zLiBGb3IgZXhhbXBsZSBgc3FydCgpYCAsIHdoaWNoIGNvbXB1dGVzIHRoZSBzcXVhcmUgcm9vdCBvZiBhIG51bWJlciwgYW5kIGBhYnMoKWAgd2hpY2ggY29tcHV0ZXMgdGhlIGFic29sdXRlIHZhbHVlIG9mIGEgbnVtYmVyLiBUbyBhcHBseSBvbmUgb2YgdGhlc2UgZnVuY3Rpb25zLCB3ZSB0eXBlIHRoZSBuYW1lLCBhbmQgcGxhY2UgdGhlIHZhbHVlIHdlIHdpc2ggdG8gb3BlcmF0ZSBvbiAqKih0aGUgYXJndW1lbnQpKiogaW5zaWRlIHRoZSByb3VuZCBicmFja2V0cy4KCiMjIyBDb2RlLWFsb25nIEV4ZXJjaXNlCgpUcnkgdGhlc2UgZXhhbXBsZXM6CgpgYGB7ciBhcHBseWluZyBmdW5jdGlvbnN9CmFicygtNDIpCgpzcXJ0KDIwMCkKCmBgYAoKIyMgR2V0dGluZyBIZWxwCgpPZnRlbiB5b3UnbGwgbmVlZCBoZWxwIGZvciBhIHNwZWNpZmljIGZ1bmN0aW9uLCBzdWNoIGFzIGBtZWFuKClgLCB5b3UgY2FuIHNlYXJjaCB0aGUgaGVscCBkb2N1bWVudGF0aW9uIHVzaW5nIGA/YCBpbiBmcm9udCBvZiB0aGUgZnVuY3Rpb24gbmFtZSB0byBkbyB0aGlzIChlLmcuIGA/bWVhbmApIGFuZCB0aGlzIHdpbGwgYnJpbmcgdXAgdGhlIG1hbnVhbCBwYWdlLiBJdCBwcm92aWRlcyBpbmZvcm1hdGlvbiBhYm91dCB3aGF0IGRvZXMsIHdoYXQgdGhlIGFyZ3VtZW50cyBhcmUsIGFuZCBldmVuIHByb3ZpZGVzIHNvbWUgZXhhbXBsZXMgdGhhdCBjYW4gYmUgY29weS1wYXN0ZWQgYW5kIHJ1biB0byBnaXZlIGFuIGV4YW1wbGUgb2Ygd2hhdCBpdCBkb2VzLgoKVGhlIGA/YCBpcyBub3QgdGhlIG9ubHkgd2F5IHRvIGZpbmQgb3V0IGhvdyB0byBydW4gYSBmdW5jdGlvbiAtLSBmb3IgbW9yZSBleGFtcGxlcyBvZiBob3cgdG8gZmluZCBoZWxwIHJlZmVyIHRvIDxodHRwczovL2RhdGFjYXJwZW50cnkub3JnL1ItZWNvbG9neS1sZXNzb24vMDAtYmVmb3JlLXdlLXN0YXJ0Lmh0bWwjU2Vla2luZ19oZWxwPgoKClwKCiMjIE1vcmUgdGhpbmdzOiBXb3JkcwoKTG90cyBvZiBjb21wdXRpbmcgaW52b2x2ZXMgd29yZHMgcmF0aGVyIHRoYW4gbnVtYmVycy4gRm9yIGV4YW1wbGUsIHNlYXJjaGluZyB0ZXh0IGFuZCBlbnJvbGxpbmcgc3R1ZGVudHMgYnkgbmFtZSBib3RoIG9wZXJhdGUgb24gd29yZHMuIFIgdW5kZXJzdGFuZHMgd29yZHMgLS0gdGhlIGNvbmNlcHQgb2YgKip0aGluZ3MgY29tcG9zZWQgb2YgbGV0dGVycyoqLiBIb3dldmVyLCB3aGVuIHdvcmtpbmcgd2l0aCB3b3Jkcywgd2UgbXVzdCBtYXJrIHRoZW0gd2l0aCBzcGVjaWFsIGNoYXJhY3RlcnMgdG8gcHJldmVudCBSIGZyb20gYmVjb21pbmcgY29uZnVzZWQgKHdlIHNlZSB3aGF0IHRoaXMgY29uZnVzaW9uIGxvb2tzIGxpa2UgaW4gYSBtb21lbnQpLgoKSW4gcHJvZ3JhbW1pbmcsIGEgdGhpbmcgY29tcG9zZWQgb2YgbGV0dGVycyBkb2Vzbid0IGhhdmUgdG8gYmUgYSByZWFsIHdvcmQgKGl0IGNvdWxkIGJlLCBmb3IgZXhhbXBsZSwgYSBwcm9kdWN0IGNvZGUgb3IgdXNlciBpZCksIHNvIHdlIGFjdHVhbGx5IGNhbGwgdGhlbSAqKnN0cmluZ3MqKi4gVG8gZGVub3RlIGEgKipzdHJpbmcqKiB3ZSBzdXJyb3VuZCBpdCB3aXRoIHF1b3RlIG1hcmtzLCBsaWtlIHRoaXM6CgpgYGB7ciBzdHJpbmdzMDF9CiJwbGF0byIKYGBgCgpUaGVyZSBhcmUgZnVuY3Rpb25zIHRoYXQgb3BlcmF0ZSBvbiBzdHJpbmdzLCBleGFjdGx5IGVxdWl2YWxlbnQgdG8gb25lcyBsaWtlIGBzcXJ0KClgIHRoYXQgb3BlcmF0ZSBvbiBudW1iZXJzLiBGb3IgZXhhbXBsZSwgUiBoYXMgYSBmdW5jdGlvbiBgbmNoYXIoKWAgdGhhdCBjb21wdXRlcyBob3cgbWFueSBjaGFyYWN0ZXJzIChpLmUuIGxldHRlcnMpIGFyZSBpbiBpdHMgc3RyaW5nIGFyZ3VtZW50LgoKYGBge3Igc3RyaW5nczAyfQpuY2hhcigicGxhdG8iKQpgYGAKClwKCiMjIyBDb2RlLWFsb25nIEV4ZXJjaXNlCgpXaGF0IGRvIHlvdSB0aGluayB3aWxsIGhhcHBlbiBpZiB5b3UgZ2l2ZSB0aGUgY29tbWFuZHMgYmVsb3c/IEVudGVyIHRoZW0gaW50byB0aGUgUlN0dWRpbyBjb25zb2xlIHRvIHNlZS4KCmBgYHtyIHN0cmluZ3MwMywgZXJyb3I9VFJVRX0KCm5raGFyKCJwbGF0byIpCgpzcXJ0KCJwbGF0byIpCmBgYAoKUmVtZW1iZXIgdGhhdCB0aGUgbGFuZ3VhZ2UgUiBpcyBhIHNldCBvZiB2b2NhYnVsYXJ5IGFuZCBncmFtbWFyIHJ1bGVzIHRoYXQgbXVzdCBiZSBmb2xsb3dlZCAqdmVyeSogc3RyaWN0bHkuIFRoZXJlIGlzIG5vIGZ1bmN0aW9uIGBua2hhcmAgaW4gUidzIHZvY2FidWxhcnksIG9ubHkgYG5jaGFyYC4gQW5kIGZ1bmN0aW9uIGBzcXJ0YCBvbmx5IHVuZGVyc3RhbmRzIGhvdyB0byB3b3JrIG9uIG51bWJlcnMsIG5vdCBvbiBzdHJpbmdzLgoKUiB3aWxsICoqbmV2ZXIqKiB3b3JrIG91dCB3aGF0IHlvdSBtZWFudCB3aGVuIHlvdSBkZXZpYXRlIGZyb20gaXRzIGdyYW1tYXIuIE5vIHByb2dyYW1taW5nIGxhbmd1YWdlIHdpbGwuIElmIHlvdSB2aW9sYXRlIGl0cyBydWxlcywgUiB3aWxsIHRocm93IGFuIGVycm9yLiBCdXQgdGhpcyBjYW4gYmUgdmVyeSBpbnN0cnVjdGl2ZS4gRW50ZXIgdGhlIGZvbGxvd2luZyBjb21tYW5kIGludG8gUlN0dWRpbyBhbmQgY2FyZWZ1bGx5IGNvbnNpZGVyIHRoZSBvdXRjb21lLiBXaGF0IGRvZXMgdGhpcyB0ZWxsIHlvdSBhYm91dCB0aGUgcnVsZXMgb2YgdGhlIFIgbGFuZ3VhZ2U/CgpgYGB7ciBjYXNlLCBlcnJvcj1UUlVFfQpOQ0hBUigicGxhdG8iKQpgYGAKCldlIGtub3cgdGhhdCBSIHVuZGVyc3RhbmRzIHRoZSBmdW5jdGlvbiBgbmNoYXJgIC0tIHdlIHNhdyBpdCB3b3JraW5nIGp1c3QgYSBmZXcgbW9tZW50cyBhZ28uIEJ1dCBub3cgaXQgc2F5cyBpdCBjb3VsZCBub3QgZmluZCB0aGF0IGZ1bmN0aW9uPyBUaGlzIGlzIGJlY2F1c2UsIHRvIFIsIGBuY2hhcmAgYW5kIGBOQ0hBUmAgYXJlIG5vdCB0aGUgc2FtZSB0aGluZy4gUiBpcyBhICoqY2FzZS1zZW5zaXRpdmUqKiBsYW5ndWFnZS4gVXBwZXItY2FzZSBhbmQgbG93ZXItY2FzZSBsZXR0ZXJzIGFyZSBjb21wbGV0ZWx5IGRpZmZlcmVudCBlbnRpdGllcyBpbiBSLiBXaGVuIGdpdmluZyBSIGNvbW1hbmRzIHlvdSBtdXN0IGFsd2F5cyBleGFjdGx5IG1hdGNoIGl0cyBleHBlY3RhdGlvbnMgYWJvdXQgdXBwZXIgYW5kIGxvd2VyIGNhc2UgKHdvb2YpLgoKXAoKIyMgU3RvcmluZyBSZXN1bHRzCgpJbWFnaW5lIHRoYXQgeW91IGhhdmUgdHdvIGxhcmdlIG51bWJlcnMgYW5kLCBmb3Igc29tZSBzb3VuZCBzY2llbnRpZmljIHJlYXNvbiwgeW91IHdpc2ggdG8gdGFrZSB0aGVpciByYXRpbyBhbmQgdGhlbiB0YWtlIHRoZSBzcXVhcmUgcm9vdCBvZiB0aGF0IHZhbHVlLiBMaWtlIHRoaXM6CgpgYGB7ciBzYXZpbmcgcmVzdWx0cyAwMX0KMTk4LjcgLyA2NC41CmBgYAoKYGBge3Igc2F2aW5nIHJlc3VsdHMgMDJ9CnNxcnQoMy4wODA2MikKYGBgCgpUaGlzIG9wZXJhdGlvbiBpcyByaXNreS4gUiBoYXMgZ2l2ZW4geW91IHRoZSByYXRpbyB0byBmaXZlIGFjY3VyYXRlIGRlY2ltYWwgcGxhY2VzLiBCdXQgeW91IG11c3QgdGhlbiBiZSAqdmVyeSBjYXJlZnVsKiB0byBjb3B5IGl0IGV4YWN0bHkgaW50byB0aGUgYHNxcnRgIGZ1bmN0aW9uLCBvciB5b3VyIGFuc3dlciB3aWxsIGJlIHdyb25nLiBFeHRyYXBvbGF0ZSB0aGlzIHRvIHRob3VzYW5kcyBvZiBkYXRhIG9wZXJhdGlvbnMgb24gYSBsYXJnZSBkYXRhIHNldCBhbmQgaXQgaXMgY2VydGFpbiB0aGF0IGVycm9ycyB3aWxsIGJlIG1hZGUuCgpJdCB3b3VsZCBiZSBtb3JlIGNvbnZlbmllbnQsIGFuZCBzYWZlciwgdG8gdGFrZSB0aGUgcmVzdWx0IFIgZ2F2ZSB5b3UgZnJvbSB0aGUgZmlyc3Qgc3RhdGVtZW50LCAqc3RvcmUgaXQgc29tZXdoZXJlLCBhbmQgdGhlbiBwYXNzIHRoZSBzdG9yZWQgZW50aXR5IHRvIGZ1bmN0aW9uIHNxcnQqLiBUaGlzIGlzLCBpbiBmYWN0LCBhIGZ1bmRhbWVudGFsIGFjdGlvbiBpbiBwcm9ncmFtbWluZzogKipXZSBjYW4gc3RvcmUgdmFsdWVzIGFzIG5hbWVkIGVudGl0aWVzIChjYWxsZWQgdmFyaWFibGVzKSBhbmQgdXNlIHRoZW0gd2hlbmV2ZXIgYW5kIHdoZXJldmVyIHdlIG5lZWQgdGhlbS4qKgoKSW4gUiwgdGhpcyAic3RvcmluZyIgaXMgcGVyZm9ybWVkIHdpdGggdGhlICoqXDwtIG9wZXJhdG9yKiogKGNhbGxlZCB0aGUgImFzc2lnbm1lbnQiIG9wZXJhdG9yKS4gVGhlIGFzc2lnbm1lbnQgb3BlcmF0b3IgaXMgZm9ybWVkIGJ5IHR5cGluZyBhIGxlZnQgYW5nbGUgYnJhY2tldCBhbmQgYSBoeXBoZW4uIEluIHRoZSBmb2xsb3dpbmcgY29kZSBleGFtcGxlLCB3ZSBkZW1vbnN0cmF0ZSB0aGUgYXNzaWdubWVudCBvcGVyYXRvci4gV2UgYWxzbyBkZW1vbnN0cmF0ZSAqKmNvbW1lbnRzKiouIEluIFIsIGFueSB0ZXh0IHRoYXQgaXMgcHJlZmFjZWQgd2l0aCBcIyBpcyBpZ25vcmVkIHJhdGhlciB0aGFuIGJlaW5nIHRyZWF0ZWQgYXMgYSBjb21tYW5kLiBJdCBpcyBqdXN0IHRleHQgdGhhdCB0aGUgcHJvZ3JhbW1lciBhZGRzIGZvciB0aGVpciBvd24gYmVuZWZpdC4KClwKCiMjIyBDb2RlLWFsb25nIEV4ZXJjaXNlCgpNYWtlIHN1cmUgeW91IGNhbiBkdXBsaWNhdGUgdGhpcyBjb2RlLCB3aXRoIHRoZSBzYW1lIHJlc3VsdHMsIGluIFJTdHVkaW8gKHlvdSBkb24ndCBuZWVkIHRvIHR5cGUgdGhlIGNvbW1lbnRzKS4KCmBgYHtyIHZhcmlhYmxlczAxfQojIFN0b3JlIHRoZSByZXN1bHQgb2YgdGhlIGRpdmlzaW9uIGluIGFuIGVudGl0eSAoYSB2YXJpYWJsZSkgbmFtZWQgcmF0aW8uIFdlCiMgYWx3YXlzIHVzZSBtZWFuaW5nZnVsIHZhcmlhYmxlIG5hbWVzLgpyYXRpbyA8LSAxOTguNyAvIDY0LjUgIAoKIyBUaGlzIHdpbGwgZGlzcGxheSB0aGUgdmFsdWUgb2YgdGhlIHZhcmlhYmxlIG5hbWVkIHJhdGlvLiBUaGF0J3Mgd2hhdCBSIGRvZXMKIyB3aGVuIHlvdSBlbnRlciBhIGxvbmUgdmFyaWFibGUgbmFtZS4KcmF0aW8gCgojIFRoaXMgd2lsbCBwYXNzIHRoZSB2YWx1ZSBvZiByYXRpbyBhcyB0aGUgYXJndW1lbnQgdG8gdGhlIHNxcnQgZnVuY3Rpb24uCnNxcnQocmF0aW8pICAKYGBgCgpcCgojIyBWYXJpYWJsZSBOYW1lcyBhbmQgVmFsdWVzCgpMb29rICoqdmVyeSBjYXJlZnVsbHkqKiBhdCB0aGUgdmFyaWFibGUgbmFtZSBvbiB0aGUgbGVmdCBoYW5kIHNpZGUgb2YgdGhlIGFzc2lnbm1lbnQgb3BlcmF0b3IgXDwtLiBJdCBpcyBhIHN0cmluZyBvZiBjaGFyYWN0ZXJzLCBidXQgKippdCBpcyBub3Qgc3Vycm91bmRlZCBieSBxdW90ZSBtYXJrcyoqLiBUaGlzIGlzIGhvdywgaW4gUiwgd2UgZGlzdGluZ3Vpc2ggc3RyaW5ncyAoYSB3b3JkIHRoaW5nIC0tIHJlbWVtYmVyLCBsaWtlICJwbGF0byIpIGZyb20gdmFyaWFibGUgbmFtZXMuCgpJbnNpZGUgb3VyIGNvbXB1dGVyLCB2YXJpYWJsZXMgYXJlIGltcGxlbWVudGVkIChjb25jZXB0dWFsbHkpIGFzIHNob3duIGJlbG93LiBBIGxvY2F0aW9uIGluIG1lbW9yeSBpcyAibmFtZWQiLiBXaGVuIHlvdSByZWZlciB0byB0aGUgbmFtZSwgdGhlIGNvbXB1dGVyIHN1cHBsaWVzIHdoYXRldmVyIHZhbHVlIGlzIHN0b3JlZCBhdCB0aGF0IGxvY2F0aW9uLgoKYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI1MCUiLCBmaWcuY2FwPSJIb3cgVmFyaWFibGVzIFdvcmsiLCBlY2hvID0gRkFMU0V9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1jb21wdXRlcl93aXRoX3ZhcmlhYmxlLnBuZyIpCmBgYAoKVGhpcyBtZWFucyB0aGF0IHRoZSB2YWx1ZSBvZiBhIHZhcmlhYmxlIGNhbiBjaGFuZ2Ugb3ZlciB0aW1lLiAoV2Ugd2lsbCBzZWUgbGF0ZXIgdGhhdCB0aGlzIHR1cm5zIG91dCB0byBiZSBleHRyZW1lbHkgdXNlZnVsLikKCmBgYHtyIHZhcmlhYmxlczAyfQojIFN0b3JlIHRoZSByZXN1bHQgb2YgdGhlIGRpdmlzaW9uIGluIGFuIGVudGl0eSBuYW1lZCByYXRpbwpyYXRpbyA8LSAxOTguNyAvIDY0LjUgIAoKIyBUaGlzIHdpbGwgZGlzcGxheSB0aGUgdmFsdWUgb2YgcmF0aW8uIFRoYXQncyB3aGF0IFIgZG9lcyB3aGVuIHlvdSBlbnRlciBhIGxvbmUKIyB2YXJpYWJsZSBuYW1lLgpyYXRpbyAgICAgICAgICAgICAgICAgIAoKIyBDaGFuZ2UgdGhlIHZhbHVlIHN0b3JlZCBpbiB0aGUgdmFyaWFibGUgbmFtZWQgcmF0aW8gYnkgYXNzaWduaW5nIGl0IHRoZSByZXN1bHQKIyBvZiBhIG5ldyBjb21tYW5kCnJhdGlvIDwtIDI1LjkgKiAxMi4xNSAgCgojIFNlZSB0aGUgY3VycmVudCB2YWx1ZQpyYXRpbyAgICAgICAgICAgICAgICAgIAoKYGBgCgpcCgojIyBDb21wbGV4IFRoaW5ncwoKT25lIG9mIHRoZSBncmVhdCBzdHJlbmd0aHMgb2YgUiBmb3IgZGF0YSBhbmFseXNpcyBpcyB0aGF0ICJ0aGluZ3MiIGluIFIgYXJlbid0IHJlc3RyaWN0ZWQgdG8gc2luZ2xlIG51bWJlcnMgb3Igc2luZ2xlIHN0cmluZ3MuIFRoaW5ncyBpbiBSIGNhbiBiZSAqKmNvbGxlY3Rpb25zKiogLS0gb3JkZXJlZCBzZXRzIG9mIG11bHRpcGxlIHRoaW5ncy4KClRvIGdldCBhIGNvbGxlY3Rpb24sIHdlIG11c3QgY3JlYXRlIGl0LCB1c2luZyB0aGUgYnVpbHQtaW4gZnVuY3Rpb24gYGMoKWAuIFRoZSBjIHN0YW5kcyBmb3IgKipjb21iaW5lKiouIFRoaXMgZnVuY3Rpb24gY29tYmluZXMgbXVsdGlwbGUgYXJndW1lbnRzIGludG8gYSBzaW5nbGUgY29sbGVjdGlvbiB0aGluZy4gSW4gUiB0aGlzIGtpbmQgb2YgY29sbGVjdGlvbiB0aGluZyBpcyBjYWxsZWQgYSAqKnZlY3RvcioqLgoKXAoKIyMjIENvZGUtYWxvbmcgRXhlcmNpc2UKCkVudGVyIHRoZXNlIHN0YXRlbWVudHMgaW50byBSU3R1ZGlvLCBhbmQgY2hlY2sgdGhhdCB5b3UgZ2V0IHRoZSBzYW1lIG91dHB1dC4KCmBgYHtyIHZlY3RvcnMsIGVycm9yID0gVFJVRX0KCiMgVG8gY29tYmluZSBlbGVtZW50cyBpbnRvIGEgdmVjdG9yLCBwYXNzIHRoZW0gdG8gZnVuY3Rpb24gYygpLCBhbmQgc2VwYXJhdGUKIyB0aGVtIHdpdGggY29tbWFzCnZlY3Rvcl9vZl9wcmltZXMgPC0gYygxLCA1LCA3LCAxMSkKCnZlY3Rvcl9vZl9wcmltZXMKCmFuaW1hbHMgPC0gYygiQXJtYWRpbGxvIiwgIkJ1ZmZhbG8iLCAiQ291Z2FyIikKCmFuaW1hbHMKCm1peHR1cmUgPC0gYygxLCAiQnVmZmFsbyIsIDQyKQoKbWl4dHVyZQpgYGAKCkxvb2sgdmVyeSBjYXJlZnVsbHkgYXQgdGhlIHRoaXJkIHZlY3RvciB2YXJpYWJsZSwgbWl4dHVyZS4gTm90ZSB0aGF0LCB3aGVuIGl0IGRpc3BsYXlzIHRoZSB2ZWN0b3IsIFIgaGFzIHB1dCBxdW90ZSBtYXJrcyBhcm91bmQgMSBhbmQgNDIuIFRoYXQgaXMsIFIgdGhpbmtzIHRoZXkgYXJlIHN0cmluZ3MgKGEgc2VyaWVzIG9mIGFscGhhbnVtZXJpYyBjaGFyYWN0ZXJzKSwgbm90IG51bWJlcnMuIEZyb20gdGhpcyB3ZSBzZWUgdGhhdDoKCjEuICBWZWN0b3JzIG11c3QgYmUgaG9tb2dlbmVvdXMuIFRoYXQgaXMsIGFsbCB0aGUgZWxlbWVudHMgaW4gdGhlIHZlY3RvciBtdXN0IGJlIHRoZSBzYW1lIGtpbmQgKHR5cGUpIG9mIHRoaW5nLgoKMi4gIElmIHlvdSBkb24ndCBmb2xsb3cgUidzIHJ1bGVzLCBpdCB3aWxsIHNvbWV0aW1lcyBqdXN0IGVuZm9yY2UgdGhlbSBvbiB5b3VyIGJlaGFsZi4gSGVyZSBpdCBzZWVzIHRoYXQgQnVmZmFsbyBpcyBkZWZpbml0ZWx5IGEgc3RyaW5nLiBJdCBrbm93cyB0aGF0IHZlY3RvciBlbGVtZW50cyBoYXZlIHRvIGJlIGhvbW9nZW5lb3VzLCBzbyBpdCBtYWtlcyAxIGFuZCA0MiBpbnRvIHN0cmluZ3MgIjEiIGFuZCAiNDIiLiBSIGlzIGJvc3N5IHRoaXMgd2F5LgoKKFRoZXJlIGFyZSBtb3JlIGNvbXBsZXggdGhpbmdzIGluIFIgdGhhdCBhbGxvdyBjb21iaW5hdGlvbnMgb2YgbnVtYmVycyBhbmQgc3RyaW5ncy4gR29vZ2xlICJSIGxpc3RzIiB0byBleHBsb3JlLikKCiMjIE9wZXJhdGluZyBvbiBWZWN0b3JzCgpUaGUgb3BlcmF0b3JzIGFuZCBmdW5jdGlvbnMgd2UgaGF2ZSB1c2VkIHNvIGZhciBvbiBzaW5nbGUgbnVtYmVycyBhbmQgc3RyaW5ncyAoZS5nLiBgc3FydGAsIGBuY2hhcmApIHdpbGwgYWxzbyB3b3JrIG9uIHZlY3RvcnMuIFdoZW4geW91IHVzZSB0aGlzIGtpbmQgb2YgZnVuY3Rpb24gb3Igb3BlcmF0b3Igd2l0aCBhIHZlY3RvciwgUiBhcHBsaWVzIGl0IHRvIGVhY2ggZWxlbWVudCBpbiB0dXJuLCBhbmQgcmV0dXJucyBhbGwgdGhlIHJlc3VsdHMuCgpcCgojIyMgQ29kZS1hbG9uZyBFeGVyY2lzZQoKRW50ZXIgdGhlc2Ugc3RhdGVtZW50cyBpbnRvIFJTdHVkaW8uCgpgYGB7ciB2ZWN0b3Igb3BlcmF0aW9uc30KcHJpbWVzIDwtIGMoMSwgNSwgNywgMTEpCgpwcmltZXMgKiAyCgpzcXJ0KHByaW1lcykKYGBgCgpcCgojIyMgV3JpdGUgWW91ciBPd24gQ29kZQoKRW50ZXIgYSBuZXcgY29tbWFuZCB0byBkaXZpZGUgYWxsIHRoZSB2YWx1ZXMgaW4gdmVjdG9yICoqcHJpbWVzKiogYnkgMi4gTWFrZSBzdXJlIHlvdSBnZXQgdGhlc2UgcmVzdWx0czoKCmBgYHtyIHZlY3RvciAyLCBlY2hvID0gRkFMU0V9CnByaW1lcy8yCmBgYAoKTm90ZSB0aGF0IHZlY3RvciBvcGVyYXRpb25zIHdvcmsgcmVnYXJkbGVzcyBvZiB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIGluIHRoZSB2ZWN0b3IuIFlvdSBjYW4gaGF2ZSAxLDAwMCwwMDAgZGF0YSB2YWx1ZXMgaW4geW91ciB2ZWN0b3IgYW5kIGl0IHN0aWxsIHJlcXVpcmVzIG9ubHkgb25lIGNvbW1hbmQgdG8gcHJvY2VzcyB0aGVtIGFsbC4KClwKCiMjIFdob2xlLVZlY3RvciBPcGVyYXRpb25zCgpUaGVyZSBhcmUgYWxzbyBmdW5jdGlvbnMgd2hpY2ggc3VtbWFyaXNlIHRoZSBjb250ZW50cyBvZiBhIHZlY3Rvci4gRm9yIGV4YW1wbGUsIFIgaGFzIGEgZnVuY3Rpb24gYG1lYW5gIHRoYXQgY29tcHV0ZXMgdGhlIG1hdGhlbWF0aWNhbCBhdmVyYWdlIG9mIHRoZSBlbGVtZW50cyBpbiBhIHZlY3RvciwgYW5kIGEgZnVuY3Rpb24gYHNkYCB0aGF0IGNvbXB1dGVzIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIGVsZW1lbnRzIGluIGEgdmVjdG9yLiBUaGVyZSBhcmUgaHVuZHJlZHMgb2Ygc3VjaCBmdW5jdGlvbnMgYXZhaWxhYmxlLCBhbmQgd2Ugd2lsbCBleHBsb3JlIG1hbnkgb2YgdGhlbSB0aHJvdWdob3V0IHRoaXMgbWluaS1jb3Vyc2UuCgpcCgojIyMgQ29kZS1hbG9uZyBFeGVyY2lzZQoKRW50ZXIgdGhlc2Ugc3RhdGVtZW50cyBpbnRvIFJTdHVkaW8uCgpgYGB7ciB2ZWN0b3Igc3VtbWFyeSBvcGVyYXRpb25zfQpleGFtX3Njb3Jlc192ZWN0b3IgPC0gYyg4MiwgNDMsIDk3LCA1NiwgNzgpICMgQ3JlYXRlIGFuIGV4YW1wbGUgZGF0YSB2ZWN0b3IKCm1lYW4oZXhhbV9zY29yZXNfdmVjdG9yKSAgIyBDb21wdXRlIHRoZSBtYXRoZW1hdGljYWwgbWVhbiBvZiB0aGUgZXhhbSBzY29yZXMKCnNkKGV4YW1fc2NvcmVzX3ZlY3RvcikgIyBDb21wdXRlIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIGV4YW0gc2NvcmVzCmBgYAoKXAoKIyMjIFdyaXRlIHlvdXIgb3duIGNvZGUKClRoZSBSIGZ1bmN0aW9ucyBgbWluYCBhbmQgYG1heGAgcmV0dXJuIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIHZhbHVlcyBvZiBhIHZlY3Rvci4gV3JpdGUgY29tbWFuZHMgdG8gdXNlIHRoZXNlIGZ1bmN0aW9ucyBvbiAqKmV4YW1fc2NvcmVzX3ZlY3RvcioqIGZyb20gdGhlIHByZXZpb3VzIGV4ZXJjaXNlLgoKTm90IGFsbCBSIGZ1bmN0aW9ucyBoYXZlIHN1Y2ggb2J2aW91cyBuYW1lcy4gVXNlIEdvb2dsZSBvciB5b3VyIGZhdm91cml0ZSBSIHRleHRib29rIHRvIGZpbmQgb3V0IHdoYXQgZnVuY3Rpb24gdG8gY2FsbCB0byBnZXQgKnRoZSBudW1iZXIgb2YgZWxlbWVudHMgaW4gYSB2ZWN0b3IqLiBUZXN0IHRoaXMgZnVuY3Rpb24gb24gKipleGFtX3Njb3Jlc192ZWN0b3IqKi4KClwKClwKCiMgRXZlbiBNb3JlIENvbXBsZXggVGhpbmdzCgpXZSBoYXZlIHNlZW4gdGhhdCBSIHVuZGVyc3RhbmRzIHNpbmdsZSBudW1iZXJzIG9yIHN0cmluZ3MsIGFuZCBjb2xsZWN0aW9ucyBvZiBudW1iZXJzIG9yIHN0cmluZ3MgKHZlY3RvcnMpLiBSIGFsc28gdW5kZXJzdGFuZHMgY29tcGxldGUgdGFibGVzIG9mIGRhdGEgKGluIHJvd3MgYW5kIGNvbHVtbnMsIGxpa2Ugc3ByZWFkc2hlZXRzIGFyZSBhcnJhbmdlZCkuIEluIGZhY3QsIG1vc3QgcmVhbCBkYXRhIGFuYWx5c2lzIGluIFIgb3BlcmF0ZXMgb24gdGFibGVzIG9mIGRhdGEuIFNvbWUgUiBmdW5jdGlvbnMgcmVxdWlyZSB5b3UgdG8gZmlyc3QgZXh0cmFjdCBhIHJvdyBvciBjb2x1bW4gZnJvbSB5b3VyIGRhdGEgdGFibGU7IG90aGVyIGZ1bmN0aW9ucyB3aWxsIHRha2UgYW4gZW50aXJlIHRhYmxlIGFuZCBvcGVyYXRlIG9uIGl0IGF0IG9uY2UgKGZvciBleGFtcGxlLCBtYW55IG9mIHRoZSBmdW5jdGlvbnMgdGhhdCBwZXJmb3JtIGluZmVyZW50aWFsIHN0YXRpc3RpY2FsIGFuYWx5c2VzIG9wZXJhdGUgb24gd2hvbGUgdGFibGVzKS4gSW4gbGF0ZXIgbW9kdWxlcywgd2Ugd2lsbCB1c2Ugc29tZSBvZiB0aGVzZSBmdW5jdGlvbnMuIEJ1dCBiZWZvcmUgd2UgZG8gdGhhdCwgdGhlcmUgaXMgb25lIG1vcmUgKip2ZXJ5IGltcG9ydGFudCoqIG1lY2hhbmljYWwgZmVhdHVyZSBvZiBSU3R1ZGlvLi4uCgpcCgojIyBTYXZpbmcgWW91ciBDb2RlCgpXZSBoYXZlIHR5cGVkIGEgbG90IG9mIFIgY29tbWFuZHMgaW50byB0aGUgY29uc29sZS4gV2hlbiB3ZSBjbG9zZSBSU3R1ZGlvLCAqKmFsbCB0aGF0IGNvZGUgd2lsbCBiZSBnb25lIGZvcmV2ZXIqKi4gSWYgd2Ugd2FudCB0byBkbyBhbnkgb2YgdGhpcyBhZ2Fpbiwgd2UgaGF2ZSB0byBzdGFydCBvdmVyIGZyb20gdGhlIGJlZ2lubmluZyBhbmQgdHlwZSBldmVyeXRoaW5nIGluIGFnYWluLiBUaGlzIGlzIHVuYWNjZXB0YWJsZS4gU28sIFJTdHVkaW8gbGV0cyB1cyB0eXBlIG91ciBjb2RlIGludG8gYSBmaWxlLCBzYXZlIHRoZSBmaWxlLCBhbmQgcmV0cmlldmUgdGhlIGNvZGUgd2hlbmV2ZXIgd2Ugd2FudCwgc28gdGhhdCB3ZSBjYW4gbW9kaWZ5IGl0IG9yIHNpbXBseSBydW4gaXQgYWdhaW4uCgpcCgojIyBVc2luZyBhIFNjcmlwdCBGaWxlCgoxXC4gRnJvbSB0aGUgbWVudSBhdCB0aGUgdG9wIG9mIHRoZSBSU3R1ZGlvIHNjcmVlbiBzZWxlY3QgRmlsZS1cPk5ldyBGaWxlIHRoZW4gY2xpY2sgb24gUiBTY3JpcHQuIChBbHRlcm5hdGl2ZWx5LCB5b3UgY2FuIHR5cGUgc2hpZnQrY3RybCtOIChXaW5kb3dzKSBvciBzaGlmdCtjbWQrTiAoTWFjKS4pCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjUwJSIsIGZpZy5jYXAgPSAiTWFraW5nIGFuIFIgRmlsZSIsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW1ha2Vfc2NyaXB0LnBuZyIpCmBgYAoKMlwuIFRoaXMgb3BlbnMgYSBuZXcgdW50aXRsZWQgZmlsZSBpbiBhbiBlZGl0aW5nIHBhbmUgaW4gdGhlIHVwcGVyIGxlZnQgb2YgdGhlIFJTdHVkaW8gc2NyZWVuLiBUaGUgY29uc29sZSBwYW5lIHdpbGwgYmUgcHVzaGVkIGRvd24gdG8gdGhlIGJvdHRvbSBoYWxmIG9mIHRoZSBzY3JlZW4uIFlvdSBjYW4gY2xpY2sgYW5kIGRyYWcgdGhlIGRpdmlkZXJzIGJldHdlZW4gdGhlIGZvdXIgcGFuZXMgdG8gY2hhbmdlIHRoZWlyIHNpemVzIGFzIHlvdSBwcmVmZXIuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAiMTAwJSIsIGZpZy5jYXAgPSAiTmV3IFNjcmlwdCIsIGZpZy5wb3MgPSAnSCcsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW5ld19zY3JpcHQucG5nIikKYGBgCgozXC4gRnJvbSB0aGUgbWFpbiBSU3R1ZGlvIG1lbnUgc2VsZWN0IEZpbGUtXD5TYXZlIEFzLi4gdG8gc2F2ZSB5b3VyIGZpbGUuIEFsd2F5cyBnaXZlIHlvdXIgZmlsZXMgZGVzY3JpcHRpdmUgbmFtZXMgdG8gbWFrZSBpdCBlYXN5IHRvIGZpbmQgdGhlIG9uZSB5b3Ugd2FudCBsYXRlci4KCjRcLiBZb3UgY2FuIHR5cGUgUiBjb21tYW5kcyBpbnRvIHRoZSBuZXcgZmlsZSAoaW4gdGhlIHVwcGVyIGxlZnQgcGFuZSkgZXhhY3RseSBhcyB5b3UgdHlwZWQgaW50byB0aGUgY29uc29sZS4KCjVcLiBFeGVjdXRpbmcgYSBjb21tYW5kIHRoYXQgaXMgdHlwZWQgaW50byBhIGZpbGUgd29ya3MgYSBsaXR0bGUgZGlmZmVyZW50bHkgdGhhbiBleGVjdXRpbmcgYSBjb21tYW5kIHRoYXQgaXMgdHlwZWQgaW50byB0aGUgY29uc29sZS4gVG8gZXhlY3V0ZSBhIHNpbmdsZSBsaW5lIG9mIGNvZGUgaW4gdGhlIGZpbGUsIGNsaWNrIHlvdXIgbW91c2UgY3Vyc29yIGFueXdoZXJlIG9uIHRoZSBsaW5lIG9mIGNvZGUuICoqRE8gTk9UIFNFTEVDVCBBTlkgQ0hBUkFDVEVSUy4gSE9MRCBUSEUgTU9VU0UgU1RJTEwgV0hJTEUgQ0xJQ0tJTkcqKi4gVGhlbiB0eXBlIGN0cmwrRW50ZXIgKFdpbmRvd3MpIG9yIGNtZCtFbnRlciAoTWFjKS4KCjZcLiBUbyBleGVjdXRlIG11bHRpcGxlIGxpbmVzIG9mIGNvZGUgaW4gdGhlIGZpbGUsIHNlbGVjdCBhbGwgdGhlIGNvZGUgeW91IHdhbnQgYnkgY2xpY2tpbmcgYW5kIGRyYWdnaW5nIHRoZSBtb3VzZSAoY3RybCtBIG9yIGNtZCtBIGZvciB0aGUgd2hvbGUgZmlsZSksIHRoZW4gdHlwZSBjdHJsK0VudGVyIG9yIGNtZCtFbnRlci4KCjdcLiBUaGUgb3V0cHV0IGZyb20geW91ciBjb2RlIHdpbGwgYmUgd3JpdHRlbiB0byB0aGUgY29uc29sZSwganVzdCBhcyB0aG91Z2ggeW91IGhhZCB0eXBlZCB0aGUgY29kZSB0aGVyZS4KCjhcLiBBZnRlciBlbnRlcmluZyBzb21lIGNvZGUgaW50byB5b3VyIGZpbGUsIHNhdmUgaXQgKHRoZSBwcm9ncmFtbWVyJ3MgbW90dG8gaXMgU2F2ZSBFYXJseSwgU2F2ZSBPZnRlbikuIFlvdSBjYW4gdGhlbiBzYWZlbHkgZXhpdCB0aGUgUlN0dWRpbyBwcm9ncmFtLgoKOVwuIEdvIHRvIHdoZXJldmVyIHlvdSBzYXZlZCB5b3VyIG5hbWVkIGNvZGUgZmlsZSAoaXQgd2lsbCBoYXZlIHN1ZmZpeCAuUikgYW5kIGRvdWJsZS1jbGljayBvbiBpdCB0byBvcGVuIGl0LiBUaGUgY29tcHV0ZXIgbWF5IGFzayB5b3Ugd2hhdCBwcm9ncmFtIHRvIHVzZSAtLSBzZWxlY3QgUlN0dWRpby4KCjEwXC4gVGhlIGZpbGUgd2lsbCBvcGVuIGluIFJTdHVkaW8gYW5kIHlvdSBjYW4gcnVuIGFsbCB5b3VyIGNvZGUgYWdhaW4gKHNlZSBpdGVtcyA1IGFuZCA2IGFib3ZlKSB3aXRob3V0IGhhdmluZyB0byByZXR5cGUgYW55dGhpbmcuCgpcCgojIyBBbiBFdmVuIEJldHRlciBTY3JpcHQgRmlsZQoKV2Ugd2lsbCBjb3ZlciBSTWFya2Rvd24gaW4gbW9yZSBkZXB0aCBpbiBNb2R1bGUgNi4KCkEgYmFzaWMgc2NyaXB0IGZpbGUgKG9mIHR5cGUgLlIpIHdpbGwgc3RvcmUgYW5kIHByZXNlcnZlIHlvdXIgY29kZS4gUlN0dWRpbyBhbHNvIHByb3ZpZGVzICoqUiBNYXJrZG93bioqIGZpbGVzIChvZiB0eXBlIC5SbWQpIHRoYXQgY2FuIGRvIG11Y2ggbW9yZS4gUiBNYXJrZG93biBpcyBhbiBleHRlbmRlZCBzY3JpcHQgZm9ybWF0IHRoYXQgYWxsb3dzIHlvdSB0byBlbWJlZCBSIGNvbW1hbmRzIGluIGZvcm1hdHRlZCB0ZXh0LiBSU3R1ZGlvIHByb2Nlc3NlcyBSIE1hcmtkb3duIGZpbGVzLCBwcm9kdWNpbmcgSFRNTCwgV29yZCBvciBwZGYgZm9ybWF0cy4gRHVyaW5nIHByb2Nlc3NpbmcgKHdoaWNoIGlzIGNhbGxlZCAqa25pdHRpbmcqKSBSU3R1ZGlvIHJ1bnMgYW55IGVtYmVkZGVkIFIgY29tbWFuZHMgYW5kICoqaW5zZXJ0cyB0aGUgcmVzdWx0cyBpbnRvIHRoZSBvdXRwdXQgZG9jdW1lbnQqKi4gWW91IGRvbid0IG5lZWQgdG8gcHJvY2VzcyB5b3VyIGRhdGEgaW4gUlN0dWRpbyBhbmQgdGhlbiBjb3B5L3Bhc3RlIHRoZSByZXN1bHRzIGludG8gYSBzZXBhcmF0ZSBXb3JkIGRvY3VtZW50LiBZb3UgY2FuIGluc2VydCB0aGUgY29kZSBkaXJlY3RseSBpbnRvIHlvdXIgdGV4dCBpbiBhbiBSIE1hcmtkb3duIGZpbGUsIGFuZCBpdCB3aWxsIGJlIGV4ZWN1dGVkIHdoZW4gUlN0dWRpbyBrbml0cy4gTGV0J3MgZ2l2ZSBpdCBhIHRyeToKCjFcLiBJbiBSU3R1ZGlvLCBjbGljayBvbiB0aGUgRmlsZSBtZW51LCBzZWxlY3QgTmV3IEZpbGUgYW5kLCBmcm9tIHRoZSBzdWJtZW51IHRoYXQgb3BlbnMsIGNsaWNrIG9uIFIgTWFya2Rvd24uCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjUwJSIsIGZpZy5jYXAgPSAiQ3JlYXRlIGFuIFIgTWFya2Rvd24gRmlsZSIsIGZpZy5wb3MgPSAiSCIsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW1ha2Vfcm1kLnBuZyIpCmBgYAoKMlwuIEEgZGlhbG9ndWUgYm94IHdpbGwgb3Blbiwgd2hlcmUgeW91IGhhdmUgYSBjaGFuY2UgdG8gZW50ZXIgYSB0aXRsZSBmb3IgeW91ciBkb2N1bWVudCBhbmQgdGhlIG5hbWUgb2YgdGhlIGF1dGhvci4gVGhlc2Ugd2lsbCBhcHBlYXIgYXQgdGhlIHRvcCBvZiB0aGUga25pdCBkb2N1bWVudC4gWW91IGNhbiBzZWxlY3QgdGhlIG91dHB1dCBmb3JtYXQuIExlYXZlIGl0IGFzIEhUTUwgZm9yIHRoaXMgZXhlcmNpc2UuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAiNzUlIiwgZmlnLnBvcyA9ICJIIiwgZmlnLmNhcCA9ICJSIE1hcmtkb3duIERpYWxvZ3VlIiwgZWNobyA9IEZBTFNFfQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtbWFya2Rvd25fZGlhbG9ndWUucG5nIikKYGBgCgozXC4gUlN0dWRpbyB3aWxsIGNyZWF0ZSBhIG5ldyBmaWxlIGFuZCBvcGVuIGl0IGluIGEgbmV3IHRhYi4gVGhlIGZpbGUgaXMgdW50aXRsZWQsIHNvIHNhdmUgaXQgYW5kIGdpdmUgaXQgYSBzZW5zaWJsZSBuYW1lLgoKYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmNhcCA9ICJBIE5ldyBSIE1hcmtkb3duIEZpbGUiLCBvdXQud2lkdGggPSAiMTAwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLnBvcyA9ICJIIn0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW1hcmtkb3duX3RlbXBsYXRlLnBuZyIpCmBgYAoKVGhlIGZpbGUgYWxyZWFkeSBjb250YWlucyBzb21lIHRleHQuIFRoaXMgaXMgc29tZSBzYW1wbGUgY29udGVudHMgdG8gZ2l2ZSB5b3UgYW4gaWRlYSBvZiB3aGF0IGFuIFIgTWFya2Rvd24gZmlsZSBsb29rcyBsaWtlLiBZb3Ugd2lsbCBub3RlIHRoYXQgdGhlIGZpbGUgaGFzIGFyZWFzIHdpdGggYSB3aGl0ZSBiYWNrZ3JvdW5kIGFuZCBhcmVhcyB3aXRoIGEgc2hhZGVkIGJhY2tncm91bmQuIFRoZSB3aGl0ZSBhcmVhcyBhcmUgcGxhaW4gdGV4dCwgdGhlIHNoYWRlZCBhcmVhcyBhcmUgUiBjb21tYW5kcy4gV2hlbiB0aGUgZmlsZSBpcyBrbml0LCB0aGF0IGNvZGUgd2lsbCBiZSBydW4sIGFuZCBpdHMgb3V0cHV0IGluc2VydGVkIGludG8gdGhlIHRleHQuIFRvIHNlZSB0aGlzIGluIGFjdGlvbiwgY2xpY2sgdGhlICoqS25pdCoqIGljb24gYXQgdGhlIHRvcCB0aGUgUlN0dWRpbyB0YWIuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwID0gIlRoZSBLbml0IEJ1dHRvbiIsIG91dC53aWR0aCA9ICI1MCUiLCBlY2hvID0gRkFMU0UsIGZpZy5wb3MgPSAiSCJ9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1tYXJrZG93bl9rbml0X2J1dHRvbi5wbmciKQpgYGAKClJTdHVkaW8gd2lsbCBwcm9kdWNlIGEgYmVhdXRpZnVsIEhUTUwgZG9jdW1lbnQgYW5kIG9wZW4gaXQgaW4gYSBsb2NhbCBicm93c2VyIHdpbmRvdy4gU2VlIGlmIHlvdSBjYW4gbWF0Y2ggdGhlIFIgY29kZSBzZWdtZW50cyBpbiB0aGUgUiBNYXJrZG93biBkb2N1bWVudCB0byB0aGUgb3V0cHV0IHRoYXQgYXBwZWFycyBpbiB0aGUgSFRNTCBwYWdlLgoKUiBNYXJrZG93biBpcyBhIHBvd2VyZnVsIHRvb2wgZm9yIGdlbmVyYXRpbmcgcmVzZWFyY2ggcmVwb3J0cyB3aGVuIGFuYWx5c2luZyBkYXRhIHdpdGggUi4gQXMgd2UgcHJvY2VlZCB0aHJvdWdoIHRoaXMgbWluaS1jb3Vyc2Ugd2Ugd2lsbCBleHBsb3JlIGFkZGl0aW9uYWwgZmVhdHVyZXMgb2YgUiBNYXJrZG93biwgYW5kIHlvdSBtYXkgd2lzaCB0byBjb25zaWRlciB1c2luZyBpdCBmb3IgeW91ciBvd24gY291cnNlIGFzc2lnbm1lbnRzLiBDaGVjayB3aXRoIHlvdXIgbGVjdHVyZXJzIHRvIHNlZSBpZiB0aGlzIGlzIHN1aXRhYmxlLgoKXAoKXAoKIyBDb25jbHVzaW9uCgpJbiB0aGlzIG1vZHVsZSB5b3UgaGF2ZSBjb25zaWRlcmVkIHRoZSBpbm5lciB3b3JraW5ncyBvZiB0aGUgY29tcHV0ZXIsIHdyaXR0ZW4gUiBjb21tYW5kcyBpbnRvIHRoZSBSU3R1ZGlvIERldmVsb3BtZW50IEVudmlyb25tZW50LCBtZXQgc29tZSBvZiB0aGUgdGhpbmdzIFIgdW5kZXJzdGFuZHMgKG51bWJlciwgc3RyaW5ncywgYW5kIHZlY3RvcnMpIGFuZCBzb21lIG9mIHRoZSBhY3Rpb25zIFIgY2FuIHBlcmZvcm0gKGZ1bmN0aW9ucykuIENvbmdyYXR1bGF0aW9ucy4KCiMjIFdoYXQncyBOZXh0CgpGaWxsIGluIHRoZSBtb2R1bGUgZmVlZGJhY2sgZm9ybSA8aHR0cHM6Ly90aW55dXJsLmNvbS9yNHNzcC1tb2R1bGUtZmI+LgoKSW4gb3VyIG5leHQgbW9kdWxlLCB3ZSB3aWxsIGxlYXJuIGhvdyB0byByZWFkIHJlYWwgZGF0YSBmaWxlcyBpbnRvIFIgYW5kIG1ha2UgcGxvdHMgYW5kIGZpZ3VyZXMgdGhhdCB5b3UgY2FuIHVzZSBpbiBhIHJlc2VhcmNoIHJlcG9ydC4gV2Ugd2lsbCBzdGFydCB3aXRoIHNpbXBsZSBwbG90cyB5b3UgY2FuIGNyZWF0ZSB1c2luZyBvbmx5IGJhc2UgUi4gVGhlbiB3ZSB3aWxsIGxlYXJuIHRvIHVzZSBhIHBvd2VyZnVsIGdyYXBoaWNzIGxpYnJhcnkgY2FsbGVkICoqZ2dwbG90KiogKHBhcnQgb2YgdGhlICoqdGlkeXZlcnNlKiogZmFtaWx5IG9mIFIgZXh0ZW5zaW9ucykuIFdpdGggZ2dwbG90IHlvdSBjYW4gbWFrZSBwdWJsaWNhdGlvbi1xdWFsaXR5IGdyYXBocyB3aXRoIG9ubHkgYSBmZXcgbGluZXMgb2YgUiBjb2RlLgoKCgoKCgoK