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. 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 (which is itself 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). As of writing, the current version of R is 4.2.2. If you
already have an earlier version of R installed, consider upgrading to
the latest version by running the latest installer.
Then install RStudio from https://posit.co/products/open-source/rstudio/. Install
the Free version; it does everything that you need. Modern scientists
must 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. 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 characters shown below into the Console pane, followed
by the Enter key.
4 + 5
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
To get information about a function type ?
followed by
the name of the function (e.g. ?mean
) into the console.
This will display the function’s manual page in the lower-right pane
(the Help tab).
The manual page explains what the function does, what the function
inputs are and what the function returns. Most manual pages also provide
some code examples.
For more ways to find documentation see 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"
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 that
value 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) Double-click on it and it should open in RStudio. If it opens in
something else (e.g. Word or Notepad), this just means that your machine
is not configured to associate .R files with RStudio. In this case,
right-click on the file, select Open With, and then
RStudio. (We see a more convenient workflow in a moment.)
10. When the file is open in RStudio you can run all your code again
(see items 5 and 6 above) without having to retype anything.
Using Projects in RStudio
An RStudio project is a folder, created from inside
RStudio, that contains related script files, data files, and RStudio
metadata files which ensure R code runs correctly and
efficiently. Most experienced R developers always organise
their work into projects. This is logically similar to organising your
regular computer files into folders – it keeps related material bundled
together, making it easier to work with.
Typically, creating a project is the first step in R
development. When a project is initially created, it contains only the
RStudio metadata files. Then data files are added by simply moving them
into folder like any other file. Script files and output files are added
to the project from inside RStudio as the work progresses. At all times,
all the related content for the project is tidily contained in the
project folder for easy location and use.
Creating a Project in RStudio
1. From the main menu select File -> New Project
2. In the resulting pop-up window, select New Directory, then New
Project, to navigate to the Create New Project dialogue box.
3. THIS IS THE TRICKY PART. The Create New Project
dialogue has a text box, followed by a Browse button.
Counterintuitively, you have to do the Browse button first.
Click Browse and navigate to where you want your project folder
to be created. Only then, click in the Directory Name text box
and type a name for your project folder. Be sure to make this name
descriptive – it is awkward to change the name of a project after it is
created. Click the Create Project button to finish. RStudio will refresh
as it navigates to your new empty project.
4. Quit out of RStudio, and navigate to the directory where you
created your project. You will find a new folder labelled with the
project name you chose.
5. Open the project folder. It will contain a folder called
.Rproj.user and a file called .Rhistory. These are RStudio metadata
files – leave them alone. (You may need to turn on hidden files in
Windows Explorer or the Mac Finder to see these files.) It also contains
a file with the project name and suffix .Rproj.
6. When you open the project in RStudio (we see how in a moment) the
project folder will be its working directory. That is,
RStudio will be “looking at” this folder. It will be able to access any
files in this folder; when you generate output files, they will be
written to this folder. To illustrate this, I have placed an Excel file
into my new project folder, and we will see how it appears to RStudio.
You can place files in your project folder by copy/paste, moving in the
Finder, or creating new files, exactly as you work with files in the
ordinary way for your operating system.
7. Double click on the .Rproj file in your project folder. This
automatically opens your project in RStudio and sets the working
directory (what RStudio can “see”) correctly. Note that the Files tab in
the lower right pane shows the contents of the project folder, including
the added spreadsheet file.
8. When working with R we recommend that you create a new project for
every module of work. The exact level of detail that defines a “module
of work” will become part of your professional style. We further
recommend that you ALWAYS begin working on any RStudio
project by double-clicking on the .Rproj file. Do not open RStudio
directly and then wander around looking for your project.
For a detailed discussion of advanced RStudio project organisation
and use, see R
for Data Science - Workflow: Projects
(https://r4ds.had.co.nz/workflow-projects.html)
An Even Better Script File
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 output files. 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.
We will cover RMarkdown (and its next-generation version Quarto) in
depth in Module 4, but we introduce
the process briefly here:
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 enter a title for your
document, the name of the author and the document date (set to the
current date by default). 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 sample contents to
illustrate how R Markdown works. 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 code 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
In this week’s hands-on session we will continue to build our R
skills, working together through the exercises in the Zoom notes for
this module. (If you prefer, go ahead and try them on your own.) You can
also use the hands-on sessions to get help with any coursework,
projects, or other R questions you may have.
In our next module, we will learn how to read 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.
LS0tCnRpdGxlOiAiSW50cm9kdWNpbmcgUiBhbmQgUlN0dWRpbyIKZGF0ZTogIlNlbWVzdGVyIDIsIDIwMjMiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGZpZy5wYXRoID0gImZpZ3VyZXMvMDEvIiwgIyB1c2Ugb25seSBmb3Igc2luZ2xlIFJtZCBmaWxlcwogIGNvbGxhcHNlID0gVFJVRSwKICBlY2hvID0gVFJVRQopCgoKYGBgCgoKPiAjIyMjIEFzc29jaWF0ZWQgbWF0ZXJpYWwKPgo+IFpvb20gbm90ZXM6IFtab29tIG5vdGVzIDAxIC0gSW50cm9kdWNpbmcgUiBhbmQgUlN0dWRpb10oem9vbV9ub3Rlc18wMV9pbnRyby5odG1sKQo+IAo+IFJlYWRpbmdzOgo+Cj4gLSBbUiBmb3IgRGF0YSBTY2llbmNlIC0gQ2hhcHRlciAxXShodHRwczovL3I0ZHMuaGFkLmNvLm56L2ludHJvZHVjdGlvbi5odG1sKQo+IC0gW1IgZm9yIERhdGEgU2NpZW5jZSAtIENoYXB0ZXIgNF0oaHR0cHM6Ly9yNGRzLmhhZC5jby5uei93b3JrZmxvdy1iYXNpY3MuaHRtKQoKIyMjIyBCZWZvcmUgd2Ugc3RhcnQKClRoaXMgd2ViIHNpdGUgcHJvdmlkZXMgdHdvIGtpbmRzIG9mIG1hdGVyaWFscyAtLSBtb2R1bGUgbm90ZXMgYW5kIHpvb20gbm90ZXMuIFRoZSBtb2R1bGUgcGFnZXMgY292ZXIgdGhlIGNvbnRlbnQgb2YgZWFjaCBvbmxpbmUgc2Vzc2lvbiBpbiBkZXRhaWwuIFRoZXkgb2Z0ZW4gcHJvdmlkZSBhZGRpdGlvbmFsIGluLWRlcHRoIGRpc2N1c3Npb24gYW5kIGV4YW1wbGVzLiBZb3UgY2FuIHVzZSB0aGUgbW9kdWxlIG5vdGVzIHRvIHJldmlzZSBhbmQgZXh0ZW5kIGxlc3NvbiBjb250ZW50IG9uIHlvdXIgb3duIGF0IGFueSB0aW1lLiBUaGUgem9vbSBub3RlcyBjb250YWluIGFuIG91dGxpbmUgb2YgdGhlIG1hdGVyaWFsIGNvdmVyZWQgaW4gZWFjaCBtb2R1bGUgYW5kIGNvZGluZyBleGVyY2lzZXMgdGhhdCB5b3UgY2FuIHdvcmsgdGhyb3VnaCBhZnRlciB0aGUgbGVzc29uIHRvIHNvbGlkaWZ5IHlvdXIgdW5kZXJzdGFuZGluZyBhbmQgYnVpbGQgeW91ciBza2lsbHMuIFdlIGNhbiAgd29yayB0aHJvdWdoIHRoZXNlIGV4ZXJjaXNlcyB0b2dldGhlciBpbiBlYWNoIHdlZWsncyBmYWNlIHRvIGZhY2UgcHJhY3RpY2FsIHNlc3Npb24uIAoKQXQgdGhlIHRvcCByaWdodCBoYW5kIGNvcm5lciBvZiBlYWNoIG5vdGVzIHBhZ2UgaXMgYSAiQ29kZSIgYnV0dG9uLiBUaGlzIHRvZ2dsZXMgc2hvd2luZy9oaWRpbmcgdGhlIGNvZGUgdXNlZCB0byBjcmVhdGUgdGhlIHBhZ2UgYXMgYW4gUm1hcmtkb3duIGZpbGUgKHdlIGNvdmVyIFJtYXJrZG93biBtb3JlIGluLWRlcHRoIGluIFttb2R1bGVdKDA0LWNvbW11bmljYXRlLmh0bWwpL1t6b29tIG5vdGVzXSh6b29tX25vdGVzXzA0X2NvbW11bmljYXRlLmh0bWwpIDQpLiBXaGVuIHdvcmtpbmcgdGhyb3VnaCB0aGUgem9vbSBub3RlcywgeW91IGNhbiB1c2UgdGhpcyBidXR0b24gdG8gaGlkZSB0aGUgZXhlcmNpc2Ugc29sdXRpb25zIGlmIHlvdSBwcmVmZXIgdG8gdGFja2xlIHRoZW0gZmlyc3Qgb24geW91ciBvd24uCgpcCgojIEludHJvZHVjdGlvbgoKQWR2YW5jZXMgaW4gY29tcHV0aW5nIGFuZCBzZW5zaW5nIHRlY2hub2xvZ2llcyBtZWFuIHRoYXQgbW9kZXJuIHNjaWVudGlmaWMgcmVzZWFyY2ggb2Z0ZW4gaW52b2x2ZXMgdmVyeSBsYXJnZSBkYXRhIHNldHMuIFRoZXJlIGFyZSBub3cgbWFueSBjb21wdXRlciBzb2Z0d2FyZSB0b29scyBhdmFpbGFibGUgdG8gd29yayB3aXRoIGJpZyBkYXRhLCBhbmQgc2NpZW50aXN0cyBmcm9tIGFsbCBkaXNjaXBsaW5lcyBuZWVkIHRvIGJlIGFibGUgdG8gdXNlIHRoZW0uCgpJbiB0aGlzIG1pbmktY291cnNlLCB3ZSB3aWxsIGhlbHAgeW91IGxlYXJuIHRvIHVzZSBvbmUgb2YgdGhlIG1vc3QgaW50ZXJlc3RpbmcgKGFuZCBwb3B1bGFyKSBvZiB0aGVzZSB0b29scyAtLSB0aGUgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UgUi4gUiBpcyBhIHNwZWNpYWwtcHVycG9zZSBvcGVuLXNvdXJjZSBsYW5ndWFnZSBmb3Igc3RhdGlzdGljcyBhbmQgZGF0YSBhbmFseXNpcy4gSW5jcmVhc2luZ2x5LCBSIGlzIHRoZSBwcmVmZXJyZWQgdG9vbCBmb3IgYW5hbHlzaW5nIGFuZCBwcmVzZW50aW5nIGRhdGEgZm9yIHN0dWRlbnQgcmVzZWFyY2ggcHJvamVjdHMuCgpJbiB0aGlzIG1vZHVsZSwgd2Ugc2hvdyB5b3UgaG93IHRvIGdldCBzdGFydGVkIHdpdGggUi4gV2Ugd2lsbCBub3QgYXNzdW1lIHRoYXQgeW91IGhhdmUgYW55IHByaW9yIGNvbXB1dGVyIHByb2dyYW1taW5nIGV4cGVyaWVuY2UuIEluIGZhY3QsIGlmIHlvdSBoYXZlIHByb2dyYW1tZWQgYmVmb3JlIGluIGEgbGFuZ3VhZ2UgbGlrZSBKYXZhIG9yIEMsIGJlIGF3YXJlIHRoYXQgUiBpcywgaW4gbWFueSByZXNwZWN0cywgdmVyeSBkaWZmZXJlbnQgZnJvbSB0aG9zZSBsYW5ndWFnZXMgLS0gc28ga2VlcCBhbiBvcGVuIG1pbmQuCgpXZSB3aWxsIGJlZ2luIGJ5IGV4cGxhaW5pbmcgdGhlIGRpZmZlcmVudCBzb2Z0d2FyZSB0b29scyB5b3UgbmVlZCwgYW5kIGhvdyB0byBnZXQgdGhlbSBvbnRvIHlvdXIgb3duIGNvbXB1dGVycy4gVGhlbiB3ZSB3aWxsIGRpc2N1c3MgdGhlIGJhc2ljIG1lY2hhbmljcyBvZiB0aGVzZSB0b29scy4gVGhyb3VnaG91dCB0aGlzIGhhbmRvdXQgKGFuZCBhbGwgbWF0ZXJpYWxzIGZvciB0aGlzIG1pbmktY291cnNlKSB0aGVyZSBhcmUgY29kZSBleGFtcGxlcyBhbmQgUiBleGVyY2lzZXMgdGhhdCB5b3Ugc2hvdWxkIHdvcmsgdGhyb3VnaCBjYXJlZnVsbHkgb24gdGhlIGNvbXB1dGVyLiBUaGlzIHdpbGwgcHJlcGFyZSB5b3UgdG8gdXNlIFIgZm9yIHlvdXIgaW4tY291cnNlIHJlc2VhcmNoIHByb2plY3RzIGxhdGVyIGluIHRoZSBzZW1lc3Rlci4KClRoaXMgaGFuZG91dCBpcyBkZXNpZ25lZCB0byBiZSByZWFkIGluIGNvbmp1bmN0aW9uIHdpdGggQ2hhcHRlciAxOiBJbnRyb2R1Y3Rpb24gb2YgW1IgZm9yIERhdGEgU2NpZW5jZV0oaHR0cHM6Ly9yNGRzLmhhZC5jby5ueikuCgpcCgpcCgojIyBUaGUgVG9vbHMKCldlIHRoaW5rIG9mIGNvbXB1dGVycyBhcyBzdG9yaW5nIHJpY2ggbWVhbmluZ2Z1bCBkYXRhIChtb3N0bHkgY2F0IHZpZGVvcykuIEFjdHVhbGx5LCB3aGF0IGNvbXB1dGVycyByZWFsbHkgY29udGFpbiBhcmUgbWlsbGlvbnMgb2YgdGlueSBsaXR0bGUgc3RvcmFnZSB1bml0cywgZWFjaCBvZiB3aGljaCBlaXRoZXIgaG9sZHMgYW4gZWxlY3RyaWNhbCBjaGFyZ2UgKHVzdWFsbHkgY2FsbGVkIGEgMSkgb3IgaG9sZHMgbm90aGluZyAodXN1YWxseSBjYWxsZWQgYSAwKS4gUmVhbGx5LiBUaGF0J3MgaXQuIFRoYXQncyBhbGwgdGhlcmUgaXMuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwPSJXaGF0J3MgaW5zaWRlIHRoZSBjb21wdXRlciIsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNTAlIn0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLWNvbXB1dGVyLnBuZyIgKQpgYGAKCkFsbCBvZiB0aGUgYW1hemluZyB0aGluZ3MgdGhhdCBjb21wdXRlcnMgZG8gaGFwcGVuIHRocm91Z2ggZXh0cmVtZWx5IGNvbXBsaWNhdGVkIG1hbmlwdWxhdGlvbiBvZiBhbGwgdGhvc2UgMHMgYW5kIDFzLlRoaXMgaW52b2x2ZXMgYSBsb3Qgb2YgbWF0aHMgYW5kIGEgbG90IG9mIGVsZWN0cm9uaWNzLCBhbmQgaXMgdmVyeSwgdmVyeSBjb25mdXNpbmcuIFNvIHRoYXQgY29tcHV0ZXIgdXNlcnMgZG9uJ3QgaGF2ZSB0byB0aGluayBhYm91dCBhbGwgdGhlc2UgMHMgYW5kIDFzLCBjb21wdXRlciBzY2llbnRpc3RzIGhhdmUgZGV2ZWxvcGVkICoqcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzKiosIHdoaWNoIGFyZSBzeW1ib2xpYyBzeXN0ZW1zIHRoYXQgd2UgY2FuIHVzZSB0byBleHByZXNzIHdoYXQgd2Ugd2FudCB0byBoYXBwZW4gaW5zaWRlIHRoZSBtYWNoaW5lLiBQcm9ncmFtbWluZyBsYW5ndWFnZXMgYXJlIGRlc2lnbmVkIHRvIGJlIHNpbWlsYXIgdG8gaHVtYW4gbGFuZ3VhZ2VzLCBzbyB0aGV5IGFyZSBlYXN5IGZvciB1cyB0byB3b3JrIHdpdGguIE92ZXIgdGhlIGxhc3QgNjAgeWVhcnMgbWFueSBzdWNoIGxhbmd1YWdlcyBoYXZlIGJlZW4gZGV2ZWxvcGVkOiBGT1JUUkFOLCBCQVNJQywgQywgSmF2YSwgUHl0aG9uLCBldGMuLCBhbmQgdGhlIG9uZSB3ZSBhcmUgdXNpbmcgaW4gdGhpcyBtaW5pLWNvdXJzZSwgUi4gRWFjaCBwcm9ncmFtbWluZyBsYW5ndWFnZSBoYXMgYSB2b2NhYnVsYXJ5IGFuZCBhIGdyYW1tYXIgKGp1c3QgbGlrZSBodW1hbiBsYW5ndWFnZXMpIHdoaWNoIG11c3QgYmUgZm9sbG93ZWQgKipleGFjdGx5KiogKHRoZXkgYXJlLCBpbiBmYWN0LCBtdWNoIHN0cmljdGVyIGFib3V0IHRoaXMgdGhhbiBodW1hbiBsYW5ndWFnZXMpLgoKVG8gY29tbXVuaWNhdGUgd2l0aCB5b3VyIGNvbXB1dGVyIHVzaW5nIGEgcHJvZ3JhbSBsYW5ndWFnZSwgeW91IG5lZWQgYSBzcGVjaWFsIGNvbXB1dGVyIHByb2dyYW0gKHdoaWNoIGlzIGl0c2VsZiB3cml0dGVuIGluIGEgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UsIG9mIGNvdXJzZSkgdGhhdCBrbm93cyBob3cgdG8gdHJhbnNsYXRlIGZyb20gdGhlIGh1bWFuLWZyaWVuZGx5IHByb2dyYW1taW5nIGxhbmd1YWdlIGludG8gYWN0aW9ucyBvbiB0aGUgY29tcHV0ZXIuIFRoZXNlIGFyZSBjYWxsZWQgKipEZXZlbG9wbWVudCBFbnZpcm9ubWVudHMqKiwgYmVjYXVzZSB0aGlzIGlzIHdoZXJlIHBlb3BsZSBkZXZlbG9wIHNvZnR3YXJlLgoKYGBge3IsIGZpZy5jYXAgPSAiQWxsIFRoZSBQYXJ0cyIsIGVjaG89RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSIxMDAlIn0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLWxhbmd1YWdlX2lkZV9tYWNoaW5lLnBuZyIpCmBgYAoKVGhlIG1vc3QgcG9wdWxhciBkZXZlbG9wbWVudCBlbnZpcm9ubWVudCBmb3IgUiBpcyBhIHByb2dyYW0gY2FsbGVkICoqUlN0dWRpbyoqLgoKQm90aCBSIGFuZCBSU3R1ZGlvIGFyZSBpbnN0YWxsZWQgb24gdGhlIGNvbXB1dGVycyBpbiB0aGUgT3RhZ28gVW5pdmVyc2l0eSBjb21wdXRlciBsYWJzLiBZb3UgY2FuIHdvcmsgdGhyb3VnaCB0aGlzIGRvY3VtZW50IG9uIHRob3NlIG1hY2hpbmVzLgoKWW91IGNhbiBhbHNvIGluc3RhbGwgdGhlIFIgbGFuZ3VhZ2UgYW5kIHRoZSBSU3R1ZGlvIHByb2dyYW0gb24geW91ciBvd24gcGVyc29uYWwgY29tcHV0ZXJzLiBUaGVzZSBhcmUgY29tcGxldGVseSBvcGVuLXNvdXJjZSwgZnJlZSwgYW5kIHNhZmUuCgpGaXJzdCwgaW5zdGFsbCBSIGZyb20gPGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL2Jpbi93aW5kb3dzL2Jhc2UvPiAoZm9yIFdpbmRvd3MgbWFjaGluZXMpIG9yIDxodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy9iaW4vbWFjb3N4Lz4gKGZvciBNYWMgT1MgbWFjaGluZXMpLiBBcyBvZiB3cml0aW5nLCB0aGUgY3VycmVudCB2ZXJzaW9uIG9mIFIgaXMgNC4yLjIuIElmIHlvdSBhbHJlYWR5IGhhdmUgYW4gZWFybGllciB2ZXJzaW9uIG9mIFIgaW5zdGFsbGVkLCBjb25zaWRlciB1cGdyYWRpbmcgdG8gdGhlIGxhdGVzdCB2ZXJzaW9uIGJ5IHJ1bm5pbmcgdGhlIGxhdGVzdCBpbnN0YWxsZXIuCgpcCgpUaGVuIGluc3RhbGwgUlN0dWRpbyBmcm9tIDxodHRwczovL3Bvc2l0LmNvL3Byb2R1Y3RzL29wZW4tc291cmNlL3JzdHVkaW8vPi4gSW5zdGFsbCB0aGUgRnJlZSB2ZXJzaW9uOyBpdCBkb2VzIGV2ZXJ5dGhpbmcgdGhhdCB5b3UgbmVlZC4gTW9kZXJuIHNjaWVudGlzdHMgbXVzdCBiZSBjb21mb3J0YWJsZSBpbnN0YWxsaW5nIHNvZnR3YXJlIG9uIHRoZWlyIG93biBjb21wdXRlcnMuIFRoaXMgaXMgYSBnb29kIG9wcG9ydHVuaXR5IGZvciB5b3UgdG8gcHJhY3RpY2UgdGhpcyBpbXBvcnRhbnQgc2tpbGwsIGFuZCB3ZSBlbmNvdXJhZ2UgeW91IHRvIHRyeSBpdC4gSWYgeW91IG5lZWQgYW55IGhlbHAsIGFzayB1cy4KClwKCiMjIEhvdyB0byBUYWxrIHRvIGEgQ29tcHV0ZXIKCldoZW4gcHJvZ3JhbW1pbmcgYSBjb21wdXRlciB5b3UgbXVzdCBhbHdheXMgcmVtZW1iZXIgb25lIHZlcnkgaW1wb3J0YW50IGZhY3Q6IENvbXB1dGVycyBBcmUgU3R1cGlkLgoKUmVhbGx5LiBUaGUgY29tcHV0ZXIgInVuZGVyc3RhbmRzIiBvbmx5IGEgdmVyeSBzbWFsbCBhbmQgKnN0cmljdGx5IGxpbWl0ZWQqIHNldCBvZiBjb21tYW5kcyAodGhlIGdyYW1tYXIgYW5kIHZvY2FidWxhcnkgb2YgYSBwcm9ncmFtbWluZyBsYW5ndWFnZSkuIElmIHlvdSBkZXZpYXRlIGZyb20gdGhpcyBzZXQgb2YgY29tbWFuZHMgKmluIGFueSB3YXkqLCB0aGUgY29tcHV0ZXIgY2Fubm90IGZpZ3VyZSBvdXQgd2hhdCB5b3UgbWVhbi4gSXQgaXMgYmVzdCB0byB0aGluayBvZiB5b3VyIGNvbXB1dGVyIGFzIGEgd2VsbC1tZWFuaW5nLCB3ZWxsLXRyYWluZWQsIGJ1dCBub3QgcGFydGljdWxhcmx5IGJyaWdodCBkb2cuIEl0IHdhbnRzIHRvIGRvIGFzIGl0IGlzIHRvbGQsIGJ1dCBpZiB5b3UgdXNlIGEgY29tbWFuZCBpdCBkb2Vzbid0IGtub3csIGl0IGNhbid0IGZpZ3VyZSBvdXQgd2hhdCB5b3UgaW50ZW5kLiBCZSBuaWNlIHRvIHlvdXIgY29tcHV0ZXIgLS0gZG9uJ3QgY29uZnVzZSBpdC4KCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5jYXAgPSAiQ29uZnVzZWQgRG9nIiwgZWNobyA9IEZBTFNFfQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtZG9nLmpwZyIpCmBgYAoKPCEtLSBJbWFnZTogaHR0cHM6Ly9pbWdmbGlwLmNvbS9tZW1ldGVtcGxhdGUvMTE2MjM1NTY4L2NvbmZ1c2VkLWRvZyAtLT4KClwKClwKCiMgVXNpbmcgUlN0dWRpbwoKUlN0dWRpbyBpcyBhIHByb2dyYW0gdGhhdCBjYW4gYWNjZXB0IFIgc3RhdGVtZW50cyBhbmQgY29udmV5IHRoZW0gdG8gdGhlIG1hY2hpbmUuIEluIFJTdHVkaW8sIHlvdSB0eXBlIGluIGFuIFIgY29tbWFuZCwgaXQgaXMgZXhlY3V0ZWQgYnkgdGhlIG1hY2hpbmUsIGFuZCBSU3R1ZGlvIGNhbiBkaXNwbGF5IHRoZSByZXN1bHRzIG9mIHRoZSBjb21tYW5kLCBpZiBhbnkuCgpJbiB0aGUgZmlyc3QgaW5zdGFuY2UsIGp1c3QgdG8gbWFrZSBzdXJlIFIgYW5kIFJTdHVkaW8gYXJlIHdvcmtpbmcgY29ycmVjdGx5LCB3ZSB3aWxsIHR5cGUgYSBmZXcgUiBjb21tYW5kcyBkaXJlY3RseSBpbnRvIFJTdHVkaW8gYW5kIGV4ZWN1dGUgdGhlbSBpbiByZWFsIHRpbWUgKHNlZSBiZWxvdykuIExhdGVyLCB3ZSB3aWxsIHNlZSBob3cgdG8gc3RvcmUgYSBzZXQgb2YgUiBjb21tYW5kcyBpbiBhIGZpbGUgc28gdGhhdCB3ZSBjYW4gcnVuIHRoZW0gcmVwZWF0ZWRseSB3aXRob3V0IGhhdmluZyB0byByZXR5cGUuCgpcCgojIyBQYXJ0cyBvZiBSU3R1ZGlvCgpUaGUgUlN0dWRpbyBpbnRlcmZhY2UgaXMgZGl2aWRlZCBpbnRvIHNlcGFyYXRlICoqcGFuZXMqKi4gSW4gaXRzIGRlZmF1bHQgY29uZmlndXJhdGlvbiB3aGVuIGl0IGZpcnN0IG9wZW5zLCBSU3R1ZGlvIHdpbGwgaGF2ZSB0aHJlZSBwYW5lcywgZWFjaCBvZiB3aGljaCBoYXMgbXVsdGlwbGUgdGFicy4gT24gdGhlIGxlZnQgaXMgdGhlIENvbnNvbGUgcGFuZS4gVGhpcyBpcyB3aGVyZSB3ZSB3aWxsIGVudGVyIG91ciBmaXJzdCBSIGNvbW1hbmRzLiBBdCB0aGUgdXBwZXIgcmlnaHQgaXMgdGhlIEVudmlyb25tZW50IHBhbmUuIFRoaXMgaXMgd2hlcmUgd2Ugd2lsbCBzZWUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHN0YXRlIG9mIG91ciBwcm9ncmFtLiBBdCB0aGUgbG93ZXIgcmlnaHQgaXMgdGhlIEZpbGVzIHBhbmUuIEhlcmUgd2UgY2FuIG5hdmlnYXRlIGFtb25nIGZpbGVzIG9uIG91ciBjb21wdXRlci4gQnV0IG1vcmUgdXNlZnVsbHksIHRoZSBGaWxlcyBwYW5lIGNvbnRhaW5zIGEgdGFiIGxhYmVsbGVkIFBsb3RzLiBXZSB3aWxsIHN3aXRjaCB0byB0aGlzIHRhYiB0byBzZWUgZ3JhcGhzIHRoYXQgd2UgZHJhdyB3aXRoIFIuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwID0gIlJTdHVkaW8iLCBlY2hvID0gRkFMU0UsIGZpZy5wb3MgPSAiSCIsIG91dC53aWR0aD0iMTAwJSIsIG91dC5leHRyYSA9ICdzdHlsZT0iYm9yZGVyOjFweCBzb2xpZCBibGFjayInfQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtUlN0dWRpby5wbmciKQpgYGAKClwKCiMgUGFydHMgb2YgdGhlIFIgUHJvZ3JhbW1pbmcgTGFuZ3VhZ2UKClByb2dyYW1taW5nIGxhbmd1YWdlcyBoYXZlIGJlZW4gZGVzaWduZWQgdG8gbWltaWMgaHVtYW4gbGFuZ3VhZ2VzLiBUaGVyZWZvcmUgbW9zdCBvZiB0aGVtIGhhdmUgKip0aGluZ3MqKiAobGlrZSBub3VucykgYW5kICoqYWN0aW9ucyoqIChsaWtlIHZlcmJzKS4gUHJvZ3JhbW1pbmcgaXMganVzdCBleHBsYWluaW5nIHRvIHRoZSBjb21wdXRlciBpbiB3YXlzIGl0IGNhbiB1bmRlcnN0YW5kLCB3aGF0ICphY3Rpb25zKiB0byBwZXJmb3JtIG9uIHNwZWNpZmljICp0aGluZ3MqLiBSIHVuZGVyc3RhbmRzIG1hbnkga2luZHMgb2YgdGhpbmdzIGFuZCBtYW55LCBtYW55IGtpbmRzIG9mIGFjdGlvbnMuIFdlIGFyZSBnb2luZyB0byBzdGFydCB3aXRoIHRoZSB2ZXJ5IHNpbXBsZXN0IGNhc2UsIGp1c3QgdG8gcHJhY3RpY2UgaW50ZXJhY3Rpbmcgd2l0aCBSU3R1ZGlvIChpLmUuLCBnaXZpbmcgaXQgUiBjb21tYW5kcyB0byBjb252ZXkgdG8gdGhlIGNvbXB1dGVyIGZvciB1cykuCgpcCgojIyBOdW1iZXJzIGFuZCBtYXRoZW1hdGljYWwgb3BlcmF0b3JzCgpSIHVuZGVyc3RhbmRzIG51bWJlcnMgKHRoaW5ncyBsaWtlIDggYW5kIDMuMTQxNTkpIGFuZCBtYXRoZW1hdGljYWwgb3BlcmF0b3JzIChhY3Rpb25zIGxpa2UgKyBhbmQgLSkuIFdlIHdpbGwgdHlwZSBzb21lIG51bWJlcnMgYW5kIG1hdGhlbWF0aWNhbCBvcGVyYXRvcnMgaW50byBSU3R1ZGlvIGFuZCBzZWUgaG93IHRoZSBjb21wdXRlciByZXNwb25kcy4KClwKCiMjIyBDb2RlLWFsb25nIEV4ZXJjaXNlCgoxLiAgTGF1bmNoIFJTdHVkaW8uIElmIHlvdSBoYXZlIGluc3RhbGxlZCBSIGFuZCBSU3R1ZGlvIG9uIHlvdXIgb3duIG1hY2hpbmUsIHlvdSBzaG91bGQgaGF2ZSBhIERlc2t0b3AgKFdpbmRvd3MpIG9yIERvY2sgKE1hYyBPUykgaWNvbiB0aGF0IHlvdSBjYW4gY2xpY2sgdG8gbGF1bmNoIFJTdHVkaW8uIElmIG5vdCwgc2VhcmNoIHRocm91Z2ggdGhlIFByb2dyYW1zIHN0YXJ0LXVwIG1lbnUgKFdpbmRvd3MpIG9yIEFwcGxpY2F0aW9ucyAoTWFjIE9TKS4gVXNlcnMgb2YgdGhlIFZpcnR1YWwgU3R1ZGVudCBEZXNrdG9wIGZvbGxvdyA8aHR0cHM6Ly9ibG9ncy5vdGFnby5hYy5uei9zdHVkZW50aXQvc3R1ZGVudC1kZXNrdG9wL3N0dWRlbnQtZGVza3RvcC1vd24tZGV2aWNlLz4gZm9yIGhvdyB0byBhY2Nlc3MgaXQgZnJvbSB5b3VyIGNvbXB1dGVyLgoKMi4gIFRoZSBDb25zb2xlIHBhbmUgb24gdGhlIGxlZnQgd2lsbCBjb250YWluIHNvbWUgZXhwbGFuYXRvcnkgdGV4dC4gQXQgdGhlIGJvdHRvbSBvZiB0aGUgdGV4dCBpcyBhIHJpZ2h0IGFuZ2xlIGJyYWNrZXQgKipcPioqLiBUaGF0IGlzIHdoZXJlIHlvdSB3aWxsIGJlZ2luIHR5cGluZy4gVGhlcmUgd2lsbCBiZSBhIHNtYWxsLCBmbGFzaGluZywgdmVydGljYWwgbGluZSBiZXNpZGUgdGhlIGFuZ2xlIGJyYWNrZXQuIChJZiB5b3UgZG9uJ3QgaGF2ZSB0aGUgZmxhc2hpbmcgdmVydGljYWwgbGluZSwgY2xpY2sgeW91ciBtb3VzZSBiZXNpZGUgYW5kIHNsaWdodGx5IHRvIHRoZSByaWdodCBvZiB0aGUgYW5nbGUgYnJhY2tldC4pCgozLiAgVHlwZSB0aGUgY2hhcmFjdGVycyBzaG93biBiZWxvdyBpbnRvIHRoZSBDb25zb2xlIHBhbmUsIGZvbGxvd2VkIGJ5IHRoZSA8a2JkPkVudGVyPC9rYmQ+IGtleS4KCiAgICAqKjQgKyA1KioKCklmIGV2ZXJ5dGhpbmcgaXMgd29ya2luZyBhcyBpdCBzaG91bGQsIHlvdXIgc2NyZWVuIHNob3VsZCBsb29rIGxpa2UgdGhpcyAodGhlIGNvbnRlbnRzIG9mIHRoZSBGaWxlcyBwYW5lIG1heSBiZSBkaWZmZXJlbnQpOgoKYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSAiMTAwJSIsIGZpZy5wb3M9IkgiLCBmaWcuY2FwID0gIkZpcnN0IFIgQ29tbWFuZCIsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLWZpcnN0X2NvbW1hbmQucG5nIikKYGBgCgpZb3UgaGF2ZSBnaXZlbiBSIHR3byAqKnRoaW5ncyoqOiB0aGUgbnVtYmVyIDQgYW5kIHRoZSBudW1iZXIgNS4gWW91IGhhdmUgYXNrZWQgUiB0byBwZXJmb3JtIGFuICoqYWN0aW9uKiogb24gdGhvc2UgdGhpbmdzOiBhZGRpdGlvbi4gUiBoYXMgZG9uZSBzbywgYW5kIFJTdHVkaW8gaGFzIGRpc3BsYXllZCB0aGUgcmVzdWx0IChpbiB0aGlzIGNhc2UsIHRoZSB2YWx1ZSA5KS4gSXQgaGFzIGFsc28gcHJpbnRlZCBbMV0gb24gdGhlIGNvbnNvbGUgc2NyZWVuLiBUaGlzIGlzIFJTdHVkaW8gdHJ5aW5nIHRvIGhlbHAgeW91LiBBcyB5b3VyIFIgY29tbWFuZHMgYmVjb21lIG1vcmUgY29tcGxpY2F0ZWQsIHlvdSB3aWxsIGVuZCB1cCB3aXRoIG1hbnkgcmVzdWx0cyByYXRoZXIgdGhhbiBqdXN0IG9uZS4gUlN0dWRpbyBwcmludHMgdGhlc2UgbnVtYmVycyBhdCB0aGUgc3RhcnQgb2Ygb3V0cHV0IGxpbmVzIHRvIGhlbHAgeW91IGNvdW50IHlvdXIgcmVzdWx0cy4gSXQncyBub3QgcmVhbGx5IG5lY2Vzc2FyeSB3aGVuIHlvdSBvbmx5IGhhdmUgb25lIHJlc3VsdCwgYnV0IHRoYXQncyBqdXN0IGhvdyBSU3R1ZGlvIGJlaGF2ZXMgKHdlIHJlZmVyIHlvdSBhZ2FpbiB0byB0aGUgcGljdHVyZSBvZiB0aGUgd2VsbC1tZWFuaW5nIGRvZ2dvIGFib3ZlKS4KCkZvciB0aGUgcmVtYWluZGVyIG9mIHRoaXMgZG9jdW1lbnQsIHdlIHdpbGwgbm90IHNob3cgeW91IHBpY3R1cmVzIG9mIHRoZSB3aG9sZSBzY3JlZW4gZWFjaCB0aW1lIHdlIGVudGVyIGFuIFIgY29tbWFuZC4gUmF0aGVyLCB3ZSB3aWxsIGRpc3BsYXkgd2hhdCB5b3Ugc2hvdWxkIHR5cGUgYW5kIHdoYXQgb3V0cHV0IHlvdSBzaG91bGQgZ2V0IGxpa2UgdGhpczoKCmBgYHtyIGZpcnN0X2NvbW1hbmR9CjQgKyA1CmBgYAoKNC4gIEV4cGxvcmUgbW9yZSBvZiBSJ3MgbWF0aGVtYXRpY2FsIG9wZXJhdG9ycy4gRm9yIGRpdmlzaW9uIHVzZSAvIGFuZCBmb3IgbXVsdGlwbGljYXRpb24gdXNlIFwqLiBFbnRlciBlYWNoIG9mIHRoZXNlIFIgY29tbWFuZHMgaW50byB0aGUgY29uc29sZSBhbmQgY29uZmlybSB0aGF0IHlvdSByZWNlaXZlIHRoZSBleHBlY3RlZCBvdXRwdXQuCgpgYGB7ciBtb3JlIG1hdGhzLCBldmFsID0gRkFMU0V9CjEwIC8gOAoKOCAqIDEyCgo2IC0gMTIgKyAoMyAqIDcuNCkKYGBgCgpcCgojIyBNb3JlIGFjdGlvbnM6IEZ1bmN0aW9uIGNhbGxzIGluIFIKClIgc3ludGF4IChncmFtbWFyKSBtaW1pY3MgbWF0aGVtYXRpY2FsIGVxdWF0aW9uIHN5bnRheCBpbiBzb21lIHJlc3BlY3RzLiBBcyB3ZSBkZW5vdGUgYSBmdW5jdGlvbiBmKHgpIHVzaW5nIHJvdW5kIGJyYWNrZXRzIGluIGFuIGVxdWF0aW9uLCBzbyBkbyB3ZSBkZW5vdGUgdGhlIGFwcGxpY2F0aW9uIG9mIGEgZnVuY3Rpb24gaW4gUi4gUiBrbm93cyBtYW55IHVzZWZ1bCBmdW5jdGlvbnMuIEZvciBleGFtcGxlIGBzcXJ0KClgICwgd2hpY2ggY29tcHV0ZXMgdGhlIHNxdWFyZSByb290IG9mIGEgbnVtYmVyLCBhbmQgYGFicygpYCB3aGljaCBjb21wdXRlcyB0aGUgYWJzb2x1dGUgdmFsdWUgb2YgYSBudW1iZXIuIFRvIGFwcGx5IG9uZSBvZiB0aGVzZSBmdW5jdGlvbnMsIHdlIHR5cGUgdGhlIG5hbWUsIGFuZCBwbGFjZSB0aGUgdmFsdWUgd2Ugd2lzaCB0byBvcGVyYXRlIG9uICh0aGUgKiphcmd1bWVudCoqKSBpbnNpZGUgdGhlIHJvdW5kIGJyYWNrZXRzLgoKIyMjIENvZGUtYWxvbmcgRXhlcmNpc2UKClRyeSB0aGVzZSBleGFtcGxlczoKCmBgYHtyIGFwcGx5aW5nIGZ1bmN0aW9uc30KYWJzKC00MikKCnNxcnQoMjAwKQoKYGBgCgojIyBHZXR0aW5nIEhlbHAKClRvIGdldCBpbmZvcm1hdGlvbiBhYm91dCBhIGZ1bmN0aW9uIHR5cGUgYD9gIGZvbGxvd2VkIGJ5IHRoZSBuYW1lIG9mIHRoZSBmdW5jdGlvbiAoZS5nLiBgP21lYW5gKSBpbnRvIHRoZSBjb25zb2xlLiBUaGlzIHdpbGwgZGlzcGxheSB0aGUgZnVuY3Rpb24ncyBtYW51YWwgcGFnZSBpbiB0aGUgbG93ZXItcmlnaHQgcGFuZSAodGhlIEhlbHAgdGFiKS4gCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwID0gIk1hbnVhbCBwYWdlLiBUeXBlID9tZWFuIGludG8gdGhlIGNvbnNvbGUuIiwgZWNobyA9IEZBTFNFLCBmaWcucG9zID0gIkgiLCBvdXQud2lkdGg9IjgwJSIsIG91dC5leHRyYSA9ICdzdHlsZT0iYm9yZGVyOjFweCBzb2xpZCBibGFjayInfQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtaGVscF9wYWdlLnBuZyIpCmBgYAoKXAoKVGhlIG1hbnVhbCBwYWdlIGV4cGxhaW5zIHdoYXQgdGhlIGZ1bmN0aW9uIGRvZXMsIHdoYXQgdGhlIGZ1bmN0aW9uIGlucHV0cyBhcmUgYW5kIHdoYXQgdGhlIGZ1bmN0aW9uIHJldHVybnMuIE1vc3QgbWFudWFsIHBhZ2VzIGFsc28gcHJvdmlkZSBzb21lIGNvZGUgZXhhbXBsZXMuCgpGb3IgbW9yZSB3YXlzIHRvIGZpbmQgZG9jdW1lbnRhdGlvbiBzZWUgPGh0dHBzOi8vZGF0YWNhcnBlbnRyeS5vcmcvUi1lY29sb2d5LWxlc3Nvbi8wMC1iZWZvcmUtd2Utc3RhcnQuaHRtbCNTZWVraW5nX2hlbHA+CgpcCgojIyBNb3JlIHRoaW5nczogV29yZHMKCkxvdHMgb2YgY29tcHV0aW5nIGludm9sdmVzIHdvcmRzIHJhdGhlciB0aGFuIG51bWJlcnMuIEZvciBleGFtcGxlLCBzZWFyY2hpbmcgdGV4dCBhbmQgZW5yb2xsaW5nIHN0dWRlbnRzIGJ5IG5hbWUgYm90aCBvcGVyYXRlIG9uIHdvcmRzLiBSIHVuZGVyc3RhbmRzIHdvcmRzIC0tIHRoZSBjb25jZXB0IG9mICoqdGhpbmdzIGNvbXBvc2VkIG9mIGxldHRlcnMqKi4gSG93ZXZlciwgd2hlbiB3b3JraW5nIHdpdGggd29yZHMsIHdlIG11c3QgbWFyayB0aGVtIHdpdGggc3BlY2lhbCBjaGFyYWN0ZXJzIHRvIHByZXZlbnQgUiBmcm9tIGJlY29taW5nIGNvbmZ1c2VkICh3ZSBzZWUgd2hhdCB0aGlzIGNvbmZ1c2lvbiBsb29rcyBsaWtlIGluIGEgbW9tZW50KS4KCkluIHByb2dyYW1taW5nLCBhIHRoaW5nIGNvbXBvc2VkIG9mIGxldHRlcnMgZG9lc24ndCBoYXZlIHRvIGJlIGEgcmVhbCB3b3JkIChpdCBjb3VsZCBiZSwgZm9yIGV4YW1wbGUsIGEgcHJvZHVjdCBjb2RlIG9yIHVzZXIgaWQpLCBzbyB3ZSBhY3R1YWxseSBjYWxsIHRoZW0gKipzdHJpbmdzKiouIFRvIGRlbm90ZSBhICoqc3RyaW5nKiogd2Ugc3Vycm91bmQgaXQgd2l0aCBxdW90ZSBtYXJrcywgbGlrZSB0aGlzOgoKYGBge3Igc3RyaW5nczAxLCBldmFsID0gRkFMU0V9CiJwbGF0byIKYGBgCgpUaGVyZSBhcmUgZnVuY3Rpb25zIHRoYXQgb3BlcmF0ZSBvbiBzdHJpbmdzLCBleGFjdGx5IGVxdWl2YWxlbnQgdG8gb25lcyBsaWtlIGBzcXJ0KClgIHRoYXQgb3BlcmF0ZSBvbiBudW1iZXJzLiBGb3IgZXhhbXBsZSwgUiBoYXMgYSBmdW5jdGlvbiBgbmNoYXIoKWAgdGhhdCBjb21wdXRlcyBob3cgbWFueSBjaGFyYWN0ZXJzIChpLmUuIGxldHRlcnMpIGFyZSBpbiBpdHMgc3RyaW5nIGFyZ3VtZW50LgoKYGBge3Igc3RyaW5nczAyfQpuY2hhcigicGxhdG8iKQpgYGAKClwKCiMjIyBDb2RlLWFsb25nIEV4ZXJjaXNlCgpXaGF0IGRvIHlvdSB0aGluayB3aWxsIGhhcHBlbiBpZiB5b3UgZ2l2ZSB0aGUgY29tbWFuZHMgYmVsb3c/IEVudGVyIHRoZW0gaW50byB0aGUgUlN0dWRpbyBjb25zb2xlIHRvIHNlZS4KCmBgYHtyIHN0cmluZ3MwMywgZXJyb3I9VFJVRX0KCm5raGFyKCJwbGF0byIpCgpzcXJ0KCJwbGF0byIpCmBgYAoKUmVtZW1iZXIgdGhhdCB0aGUgbGFuZ3VhZ2UgUiBpcyBhIHNldCBvZiB2b2NhYnVsYXJ5IGFuZCBncmFtbWFyIHJ1bGVzIHRoYXQgbXVzdCBiZSBmb2xsb3dlZCAqdmVyeSogc3RyaWN0bHkuIFRoZXJlIGlzIG5vIGZ1bmN0aW9uIGBua2hhcmAgaW4gUidzIHZvY2FidWxhcnksIG9ubHkgYG5jaGFyYC4gQW5kIGZ1bmN0aW9uIGBzcXJ0YCBvbmx5IHVuZGVyc3RhbmRzIGhvdyB0byB3b3JrIG9uIG51bWJlcnMsIG5vdCBvbiBzdHJpbmdzLgoKUiB3aWxsICoqbmV2ZXIqKiB3b3JrIG91dCB3aGF0IHlvdSBtZWFudCB3aGVuIHlvdSBkZXZpYXRlIGZyb20gaXRzIGdyYW1tYXIuIE5vIHByb2dyYW1taW5nIGxhbmd1YWdlIHdpbGwuIElmIHlvdSB2aW9sYXRlIGl0cyBydWxlcywgUiB3aWxsIHRocm93IGFuIGVycm9yLiBCdXQgdGhpcyBjYW4gYmUgdmVyeSBpbnN0cnVjdGl2ZS4gRW50ZXIgdGhlIGZvbGxvd2luZyBjb21tYW5kIGludG8gUlN0dWRpbyBhbmQgY2FyZWZ1bGx5IGNvbnNpZGVyIHRoZSBvdXRjb21lLiBXaGF0IGRvZXMgdGhpcyB0ZWxsIHlvdSBhYm91dCB0aGUgcnVsZXMgb2YgdGhlIFIgbGFuZ3VhZ2U/CgpgYGB7ciBjYXNlLCBlcnJvcj1UUlVFfQpOQ0hBUigicGxhdG8iKQpgYGAKCldlIGtub3cgdGhhdCBSIHVuZGVyc3RhbmRzIHRoZSBmdW5jdGlvbiBgbmNoYXJgIC0tIHdlIHNhdyBpdCB3b3JraW5nIGp1c3QgYSBmZXcgbW9tZW50cyBhZ28uIEJ1dCBub3cgaXQgc2F5cyBpdCBjb3VsZCBub3QgZmluZCB0aGF0IGZ1bmN0aW9uPyBUaGlzIGlzIGJlY2F1c2UsIHRvIFIsIGBuY2hhcmAgYW5kIGBOQ0hBUmAgYXJlIG5vdCB0aGUgc2FtZSB0aGluZy4gUiBpcyBhICoqY2FzZS1zZW5zaXRpdmUqKiBsYW5ndWFnZS4gVXBwZXItY2FzZSBhbmQgbG93ZXItY2FzZSBsZXR0ZXJzIGFyZSBjb21wbGV0ZWx5IGRpZmZlcmVudCBlbnRpdGllcyBpbiBSLiBXaGVuIGdpdmluZyBSIGNvbW1hbmRzIHlvdSBtdXN0IGFsd2F5cyBleGFjdGx5IG1hdGNoIGl0cyBleHBlY3RhdGlvbnMgYWJvdXQgdXBwZXIgYW5kIGxvd2VyIGNhc2UgKHdvb2YpLgoKXAoKIyMgU3RvcmluZyBSZXN1bHRzCgpJbWFnaW5lIHRoYXQgeW91IGhhdmUgdHdvIGxhcmdlIG51bWJlcnMgYW5kLCBmb3Igc29tZSBzb3VuZCBzY2llbnRpZmljIHJlYXNvbiwgeW91IHdpc2ggdG8gdGFrZSB0aGVpciByYXRpbyBhbmQgdGhlbiB0YWtlIHRoZSBzcXVhcmUgcm9vdCBvZiB0aGF0IHZhbHVlLiBMaWtlIHRoaXM6CgpgYGB7ciBzYXZpbmcgcmVzdWx0cyAwMX0KMTk4LjcgLyA2NC41CmBgYAoKYGBge3Igc2F2aW5nIHJlc3VsdHMgMDJ9CnNxcnQoMy4wODA2MikKYGBgCgpUaGlzIG9wZXJhdGlvbiBpcyByaXNreS4gUiBoYXMgZ2l2ZW4geW91IHRoZSByYXRpbyB0byBmaXZlIGFjY3VyYXRlIGRlY2ltYWwgcGxhY2VzLiBCdXQgeW91IG11c3QgdGhlbiBiZSAqdmVyeSBjYXJlZnVsKiB0byBjb3B5IHRoYXQgdmFsdWUgZXhhY3RseSBpbnRvIHRoZSBgc3FydGAgZnVuY3Rpb24sIG9yIHlvdXIgYW5zd2VyIHdpbGwgYmUgd3JvbmcuIEV4dHJhcG9sYXRlIHRoaXMgdG8gdGhvdXNhbmRzIG9mIGRhdGEgb3BlcmF0aW9ucyBvbiBhIGxhcmdlIGRhdGEgc2V0IGFuZCBpdCBpcyBjZXJ0YWluIHRoYXQgZXJyb3JzIHdpbGwgYmUgbWFkZS4KCkl0IHdvdWxkIGJlIG1vcmUgY29udmVuaWVudCwgYW5kIHNhZmVyLCB0byB0YWtlIHRoZSByZXN1bHQgUiBnYXZlIHlvdSBmcm9tIHRoZSBmaXJzdCBzdGF0ZW1lbnQsICpzdG9yZSBpdCBzb21ld2hlcmUsIGFuZCB0aGVuIHBhc3MgdGhlIHN0b3JlZCBlbnRpdHkgdG8gZnVuY3Rpb24gc3FydCouIFRoaXMgaXMsIGluIGZhY3QsIGEgZnVuZGFtZW50YWwgYWN0aW9uIGluIHByb2dyYW1taW5nOiAqKldlIGNhbiBzdG9yZSB2YWx1ZXMgYXMgbmFtZWQgZW50aXRpZXMgKGNhbGxlZCB2YXJpYWJsZXMpIGFuZCB1c2UgdGhlbSB3aGVuZXZlciBhbmQgd2hlcmV2ZXIgd2UgbmVlZCB0aGVtLioqCgpJbiBSLCB0aGlzICJzdG9yaW5nIiBpcyBwZXJmb3JtZWQgd2l0aCB0aGUgKipcPC0gb3BlcmF0b3IqKiAoY2FsbGVkIHRoZSAiYXNzaWdubWVudCIgb3BlcmF0b3IpLiBUaGUgYXNzaWdubWVudCBvcGVyYXRvciBpcyBmb3JtZWQgYnkgdHlwaW5nIGEgbGVmdCBhbmdsZSBicmFja2V0IGFuZCBhIGh5cGhlbi4gSW4gdGhlIGZvbGxvd2luZyBjb2RlIGV4YW1wbGUsIHdlIGRlbW9uc3RyYXRlIHRoZSBhc3NpZ25tZW50IG9wZXJhdG9yLiBXZSBhbHNvIGRlbW9uc3RyYXRlICoqY29tbWVudHMqKi4gSW4gUiwgYW55IHRleHQgdGhhdCBpcyBwcmVmYWNlZCB3aXRoIFwjIGlzIGlnbm9yZWQgcmF0aGVyIHRoYW4gYmVpbmcgdHJlYXRlZCBhcyBhIGNvbW1hbmQuIEl0IGlzIGp1c3QgdGV4dCB0aGF0IHRoZSBwcm9ncmFtbWVyIGFkZHMgZm9yIHRoZWlyIG93biBiZW5lZml0LgoKXAoKIyMjIENvZGUtYWxvbmcgRXhlcmNpc2UKCk1ha2Ugc3VyZSB5b3UgY2FuIGR1cGxpY2F0ZSB0aGlzIGNvZGUsIHdpdGggdGhlIHNhbWUgcmVzdWx0cywgaW4gUlN0dWRpbyAoeW91IGRvbid0IG5lZWQgdG8gdHlwZSB0aGUgY29tbWVudHMpLgoKYGBge3IgdmFyaWFibGVzMDF9CiMgU3RvcmUgdGhlIHJlc3VsdCBvZiB0aGUgZGl2aXNpb24gaW4gYW4gZW50aXR5IChhIHZhcmlhYmxlKSBuYW1lZCByYXRpby4gV2UKIyBhbHdheXMgdXNlIG1lYW5pbmdmdWwgdmFyaWFibGUgbmFtZXMuCnJhdGlvIDwtIDE5OC43IC8gNjQuNSAgCgojIFRoaXMgd2lsbCBkaXNwbGF5IHRoZSB2YWx1ZSBvZiB0aGUgdmFyaWFibGUgbmFtZWQgcmF0aW8uIFRoYXQncyB3aGF0IFIgZG9lcwojIHdoZW4geW91IGVudGVyIGEgbG9uZSB2YXJpYWJsZSBuYW1lLgpyYXRpbyAKCiMgVGhpcyB3aWxsIHBhc3MgdGhlIHZhbHVlIG9mIHJhdGlvIGFzIHRoZSBhcmd1bWVudCB0byB0aGUgc3FydCBmdW5jdGlvbi4Kc3FydChyYXRpbykgIApgYGAKClwKCiMjIFZhcmlhYmxlIE5hbWVzIGFuZCBWYWx1ZXMKCkxvb2sgKip2ZXJ5IGNhcmVmdWxseSoqIGF0IHRoZSB2YXJpYWJsZSBuYW1lIG9uIHRoZSBsZWZ0IGhhbmQgc2lkZSBvZiB0aGUgYXNzaWdubWVudCBvcGVyYXRvciBcPC0uIEl0IGlzIGEgc3RyaW5nIG9mIGNoYXJhY3RlcnMsIGJ1dCAqKml0IGlzIG5vdCBzdXJyb3VuZGVkIGJ5IHF1b3RlIG1hcmtzKiouIFRoaXMgaXMgaG93LCBpbiBSLCB3ZSBkaXN0aW5ndWlzaCBzdHJpbmdzIChhIHdvcmQgdGhpbmcgLS0gcmVtZW1iZXIsIGxpa2UgInBsYXRvIikgZnJvbSB2YXJpYWJsZSBuYW1lcy4KCkluc2lkZSBvdXIgY29tcHV0ZXIsIHZhcmlhYmxlcyBhcmUgaW1wbGVtZW50ZWQgKGNvbmNlcHR1YWxseSkgYXMgc2hvd24gYmVsb3cuIEEgbG9jYXRpb24gaW4gbWVtb3J5IGlzICJuYW1lZCIuIFdoZW4geW91IHJlZmVyIHRvIHRoZSBuYW1lLCB0aGUgY29tcHV0ZXIgc3VwcGxpZXMgd2hhdGV2ZXIgdmFsdWUgaXMgc3RvcmVkIGF0IHRoYXQgbG9jYXRpb24uCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjUwJSIsIGZpZy5jYXA9IkhvdyBWYXJpYWJsZXMgV29yayIsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLWNvbXB1dGVyX3dpdGhfdmFyaWFibGUucG5nIikKYGBgCgpUaGlzIG1lYW5zIHRoYXQgdGhlIHZhbHVlIG9mIGEgdmFyaWFibGUgY2FuIGNoYW5nZSBvdmVyIHRpbWUuIChXZSB3aWxsIHNlZSBsYXRlciB0aGF0IHRoaXMgdHVybnMgb3V0IHRvIGJlIGV4dHJlbWVseSB1c2VmdWwuKQoKYGBge3IgdmFyaWFibGVzMDJ9CiMgU3RvcmUgdGhlIHJlc3VsdCBvZiB0aGUgZGl2aXNpb24gaW4gYW4gZW50aXR5IG5hbWVkIHJhdGlvCnJhdGlvIDwtIDE5OC43IC8gNjQuNSAgCgojIFRoaXMgd2lsbCBkaXNwbGF5IHRoZSB2YWx1ZSBvZiByYXRpby4gVGhhdCdzIHdoYXQgUiBkb2VzIHdoZW4geW91IGVudGVyIGEgbG9uZQojIHZhcmlhYmxlIG5hbWUuCnJhdGlvICAgICAgICAgICAgICAgICAgCgojIENoYW5nZSB0aGUgdmFsdWUgc3RvcmVkIGluIHRoZSB2YXJpYWJsZSBuYW1lZCByYXRpbyBieSBhc3NpZ25pbmcgaXQgdGhlIHJlc3VsdAojIG9mIGEgbmV3IGNvbW1hbmQKcmF0aW8gPC0gMjUuOSAqIDEyLjE1ICAKCiMgU2VlIHRoZSBjdXJyZW50IHZhbHVlCnJhdGlvICAgICAgICAgICAgICAgICAgCgpgYGAKClwKCiMjIENvbXBsZXggVGhpbmdzCgpPbmUgb2YgdGhlIGdyZWF0IHN0cmVuZ3RocyBvZiBSIGZvciBkYXRhIGFuYWx5c2lzIGlzIHRoYXQgInRoaW5ncyIgaW4gUiBhcmVuJ3QgcmVzdHJpY3RlZCB0byBzaW5nbGUgbnVtYmVycyBvciBzaW5nbGUgc3RyaW5ncy4gVGhpbmdzIGluIFIgY2FuIGJlICoqY29sbGVjdGlvbnMqKiAtLSBvcmRlcmVkIHNldHMgb2YgbXVsdGlwbGUgdGhpbmdzLgoKVG8gZ2V0IGEgY29sbGVjdGlvbiwgd2UgbXVzdCBjcmVhdGUgaXQsIHVzaW5nIHRoZSBidWlsdC1pbiBmdW5jdGlvbiBgYygpYC4gVGhlIGMgc3RhbmRzIGZvciAqKmNvbWJpbmUqKi4gVGhpcyBmdW5jdGlvbiBjb21iaW5lcyBtdWx0aXBsZSBhcmd1bWVudHMgaW50byBhIHNpbmdsZSBjb2xsZWN0aW9uIHRoaW5nLiBJbiBSIHRoaXMga2luZCBvZiBjb2xsZWN0aW9uIHRoaW5nIGlzIGNhbGxlZCBhICoqdmVjdG9yKiouCgpcCgojIyMgQ29kZS1hbG9uZyBFeGVyY2lzZQoKRW50ZXIgdGhlc2Ugc3RhdGVtZW50cyBpbnRvIFJTdHVkaW8sIGFuZCBjaGVjayB0aGF0IHlvdSBnZXQgdGhlIHNhbWUgb3V0cHV0LgoKYGBge3IgdmVjdG9ycywgZXJyb3IgPSBUUlVFfQoKIyBUbyBjb21iaW5lIGVsZW1lbnRzIGludG8gYSB2ZWN0b3IsIHBhc3MgdGhlbSB0byBmdW5jdGlvbiBjKCksIGFuZCBzZXBhcmF0ZQojIHRoZW0gd2l0aCBjb21tYXMKdmVjdG9yX29mX3ByaW1lcyA8LSBjKDEsIDUsIDcsIDExKQoKdmVjdG9yX29mX3ByaW1lcwoKYW5pbWFscyA8LSBjKCJBcm1hZGlsbG8iLCAiQnVmZmFsbyIsICJDb3VnYXIiKQoKYW5pbWFscwoKbWl4dHVyZSA8LSBjKDEsICJCdWZmYWxvIiwgNDIpCgptaXh0dXJlCmBgYAoKTG9vayB2ZXJ5IGNhcmVmdWxseSBhdCB0aGUgdGhpcmQgdmVjdG9yIHZhcmlhYmxlLCBtaXh0dXJlLiBOb3RlIHRoYXQsIHdoZW4gaXQgZGlzcGxheXMgdGhlIHZlY3RvciwgUiBoYXMgcHV0IHF1b3RlIG1hcmtzIGFyb3VuZCAxIGFuZCA0Mi4gVGhhdCBpcywgUiB0aGlua3MgdGhleSBhcmUgc3RyaW5ncyAoYSBzZXJpZXMgb2YgYWxwaGFudW1lcmljIGNoYXJhY3RlcnMpLCBub3QgbnVtYmVycy4gRnJvbSB0aGlzIHdlIHNlZSB0aGF0OgoKMS4gIFZlY3RvcnMgbXVzdCBiZSBob21vZ2VuZW91cy4gVGhhdCBpcywgYWxsIHRoZSBlbGVtZW50cyBpbiB0aGUgdmVjdG9yIG11c3QgYmUgdGhlIHNhbWUga2luZCAodHlwZSkgb2YgdGhpbmcuCgoyLiAgSWYgeW91IGRvbid0IGZvbGxvdyBSJ3MgcnVsZXMsIGl0IHdpbGwgc29tZXRpbWVzIGp1c3QgZW5mb3JjZSB0aGVtIG9uIHlvdXIgYmVoYWxmLiBIZXJlIGl0IHNlZXMgdGhhdCBCdWZmYWxvIGlzIGRlZmluaXRlbHkgYSBzdHJpbmcuIEl0IGtub3dzIHRoYXQgdmVjdG9yIGVsZW1lbnRzIGhhdmUgdG8gYmUgaG9tb2dlbmVvdXMsIHNvIGl0IG1ha2VzIDEgYW5kIDQyIGludG8gc3RyaW5ncyAiMSIgYW5kICI0MiIuIFIgaXMgYm9zc3kgdGhpcyB3YXkuCgooVGhlcmUgYXJlIG1vcmUgY29tcGxleCB0aGluZ3MgaW4gUiB0aGF0IGFsbG93IGNvbWJpbmF0aW9ucyBvZiBudW1iZXJzIGFuZCBzdHJpbmdzLiBHb29nbGUgIlIgbGlzdHMiIHRvIGV4cGxvcmUuKQoKIyMgT3BlcmF0aW5nIG9uIFZlY3RvcnMKClRoZSBvcGVyYXRvcnMgYW5kIGZ1bmN0aW9ucyB3ZSBoYXZlIHVzZWQgc28gZmFyIG9uIHNpbmdsZSBudW1iZXJzIGFuZCBzdHJpbmdzIChlLmcuIGBzcXJ0YCwgYG5jaGFyYCkgd2lsbCBhbHNvIHdvcmsgb24gdmVjdG9ycy4gV2hlbiB5b3UgdXNlIHRoaXMga2luZCBvZiBmdW5jdGlvbiBvciBvcGVyYXRvciB3aXRoIGEgdmVjdG9yLCBSIGFwcGxpZXMgaXQgdG8gZWFjaCBlbGVtZW50IGluIHR1cm4sIGFuZCByZXR1cm5zIGFsbCB0aGUgcmVzdWx0cy4KClwKCiMjIyBDb2RlLWFsb25nIEV4ZXJjaXNlCgpFbnRlciB0aGVzZSBzdGF0ZW1lbnRzIGludG8gUlN0dWRpby4KCmBgYHtyIHZlY3RvciBvcGVyYXRpb25zfQpwcmltZXMgPC0gYygxLCA1LCA3LCAxMSkKCnByaW1lcyAqIDIKCnNxcnQocHJpbWVzKQpgYGAKClwKCiMjIyBXcml0ZSBZb3VyIE93biBDb2RlCgpFbnRlciBhIG5ldyBjb21tYW5kIHRvIGRpdmlkZSBhbGwgdGhlIHZhbHVlcyBpbiB2ZWN0b3IgKipwcmltZXMqKiBieSAyLiBNYWtlIHN1cmUgeW91IGdldCB0aGVzZSByZXN1bHRzOgoKYGBge3IgdmVjdG9yIDIsIGVjaG8gPSBGQUxTRX0KcHJpbWVzLzIKYGBgCgpOb3RlIHRoYXQgdmVjdG9yIG9wZXJhdGlvbnMgd29yayByZWdhcmRsZXNzIG9mIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgaW4gdGhlIHZlY3Rvci4gWW91IGNhbiBoYXZlIDEsMDAwLDAwMCBkYXRhIHZhbHVlcyBpbiB5b3VyIHZlY3RvciBhbmQgaXQgc3RpbGwgcmVxdWlyZXMgb25seSBvbmUgY29tbWFuZCB0byBwcm9jZXNzIHRoZW0gYWxsLgoKXAoKIyMgV2hvbGUtVmVjdG9yIE9wZXJhdGlvbnMKClRoZXJlIGFyZSBhbHNvIGZ1bmN0aW9ucyB3aGljaCBzdW1tYXJpc2UgdGhlIGNvbnRlbnRzIG9mIGEgdmVjdG9yLiBGb3IgZXhhbXBsZSwgUiBoYXMgYSBmdW5jdGlvbiBgbWVhbmAgdGhhdCBjb21wdXRlcyB0aGUgbWF0aGVtYXRpY2FsIGF2ZXJhZ2Ugb2YgdGhlIGVsZW1lbnRzIGluIGEgdmVjdG9yLCBhbmQgYSBmdW5jdGlvbiBgc2RgIHRoYXQgY29tcHV0ZXMgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgZWxlbWVudHMgaW4gYSB2ZWN0b3IuIFRoZXJlIGFyZSBodW5kcmVkcyBvZiBzdWNoIGZ1bmN0aW9ucyBhdmFpbGFibGUsIGFuZCB3ZSB3aWxsIGV4cGxvcmUgbWFueSBvZiB0aGVtIHRocm91Z2hvdXQgdGhpcyBtaW5pLWNvdXJzZS4KClwKCiMjIyBDb2RlLWFsb25nIEV4ZXJjaXNlCgpFbnRlciB0aGVzZSBzdGF0ZW1lbnRzIGludG8gUlN0dWRpby4KCmBgYHtyIHZlY3RvciBzdW1tYXJ5IG9wZXJhdGlvbnN9CmV4YW1fc2NvcmVzX3ZlY3RvciA8LSBjKDgyLCA0MywgOTcsIDU2LCA3OCkgIyBDcmVhdGUgYW4gZXhhbXBsZSBkYXRhIHZlY3RvcgoKbWVhbihleGFtX3Njb3Jlc192ZWN0b3IpICAjIENvbXB1dGUgdGhlIG1hdGhlbWF0aWNhbCBtZWFuIG9mIHRoZSBleGFtIHNjb3JlcwoKc2QoZXhhbV9zY29yZXNfdmVjdG9yKSAjIENvbXB1dGUgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgZXhhbSBzY29yZXMKYGBgCgpcCgojIyMgV3JpdGUgeW91ciBvd24gY29kZQoKVGhlIFIgZnVuY3Rpb25zIGBtaW5gIGFuZCBgbWF4YCByZXR1cm4gdGhlIG1pbmltdW0gYW5kIG1heGltdW0gdmFsdWVzIG9mIGEgdmVjdG9yLiBXcml0ZSBjb21tYW5kcyB0byB1c2UgdGhlc2UgZnVuY3Rpb25zIG9uICoqZXhhbV9zY29yZXNfdmVjdG9yKiogZnJvbSB0aGUgcHJldmlvdXMgZXhlcmNpc2UuCgpOb3QgYWxsIFIgZnVuY3Rpb25zIGhhdmUgc3VjaCBvYnZpb3VzIG5hbWVzLiBVc2UgR29vZ2xlIG9yIHlvdXIgZmF2b3VyaXRlIFIgdGV4dGJvb2sgdG8gZmluZCBvdXQgd2hhdCBmdW5jdGlvbiB0byBjYWxsIHRvIGdldCAqdGhlIG51bWJlciBvZiBlbGVtZW50cyBpbiBhIHZlY3RvciouIFRlc3QgdGhpcyBmdW5jdGlvbiBvbiAqKmV4YW1fc2NvcmVzX3ZlY3RvcioqLgoKXAoKXAoKIyMgRXZlbiBNb3JlIENvbXBsZXggVGhpbmdzCgpXZSBoYXZlIHNlZW4gdGhhdCBSIHVuZGVyc3RhbmRzIHNpbmdsZSBudW1iZXJzIG9yIHN0cmluZ3MsIGFuZCBjb2xsZWN0aW9ucyBvZiBudW1iZXJzIG9yIHN0cmluZ3MgKHZlY3RvcnMpLiBSIGFsc28gdW5kZXJzdGFuZHMgY29tcGxldGUgdGFibGVzIG9mIGRhdGEgKGluIHJvd3MgYW5kIGNvbHVtbnMsIGxpa2Ugc3ByZWFkc2hlZXRzIGFyZSBhcnJhbmdlZCkuIEluIGZhY3QsIG1vc3QgcmVhbCBkYXRhIGFuYWx5c2lzIGluIFIgb3BlcmF0ZXMgb24gdGFibGVzIG9mIGRhdGEuIFNvbWUgUiBmdW5jdGlvbnMgcmVxdWlyZSB5b3UgdG8gZmlyc3QgZXh0cmFjdCBhIHJvdyBvciBjb2x1bW4gZnJvbSB5b3VyIGRhdGEgdGFibGU7IG90aGVyIGZ1bmN0aW9ucyB3aWxsIHRha2UgYW4gZW50aXJlIHRhYmxlIGFuZCBvcGVyYXRlIG9uIGl0IGF0IG9uY2UgKGZvciBleGFtcGxlLCBtYW55IG9mIHRoZSBmdW5jdGlvbnMgdGhhdCBwZXJmb3JtIGluZmVyZW50aWFsIHN0YXRpc3RpY2FsIGFuYWx5c2VzIG9wZXJhdGUgb24gd2hvbGUgdGFibGVzKS4gSW4gbGF0ZXIgbW9kdWxlcywgd2Ugd2lsbCB1c2Ugc29tZSBvZiB0aGVzZSBmdW5jdGlvbnMuIEJ1dCBiZWZvcmUgd2UgZG8gdGhhdCwgdGhlcmUgaXMgb25lIG1vcmUgKip2ZXJ5IGltcG9ydGFudCoqIG1lY2hhbmljYWwgZmVhdHVyZSBvZiBSU3R1ZGlvLi4uCgpcCgojIFNhdmluZyBZb3VyIENvZGUKCldlIGhhdmUgdHlwZWQgYSBsb3Qgb2YgUiBjb21tYW5kcyBpbnRvIHRoZSBjb25zb2xlLiBXaGVuIHdlIGNsb3NlIFJTdHVkaW8sICoqYWxsIHRoYXQgY29kZSB3aWxsIGJlIGdvbmUgZm9yZXZlcioqLiBJZiB3ZSB3YW50IHRvIGRvIGFueSBvZiB0aGlzIGFnYWluLCB3ZSBoYXZlIHRvIHN0YXJ0IG92ZXIgZnJvbSB0aGUgYmVnaW5uaW5nIGFuZCB0eXBlIGV2ZXJ5dGhpbmcgaW4gYWdhaW4uIFRoaXMgaXMgdW5hY2NlcHRhYmxlLiBTbywgUlN0dWRpbyBsZXRzIHVzIHR5cGUgb3VyIGNvZGUgaW50byBhIGZpbGUsIHNhdmUgdGhlIGZpbGUsIGFuZCByZXRyaWV2ZSB0aGUgY29kZSB3aGVuZXZlciB3ZSB3YW50LCBzbyB0aGF0IHdlIGNhbiBtb2RpZnkgaXQgb3Igc2ltcGx5IHJ1biBpdCBhZ2Fpbi4KClwKCiMjIFVzaW5nIGEgU2NyaXB0IEZpbGUKCjFcLiBGcm9tIHRoZSBtZW51IGF0IHRoZSB0b3Agb2YgdGhlIFJTdHVkaW8gc2NyZWVuIHNlbGVjdCBGaWxlLVw+TmV3IEZpbGUgdGhlbiBjbGljayBvbiBSIFNjcmlwdC4gKEFsdGVybmF0aXZlbHksIHlvdSBjYW4gdHlwZSBzaGlmdCtjdHJsK04gKFdpbmRvd3MpIG9yIHNoaWZ0K2NtZCtOIChNYWMpLikKCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNTAlIiwgb3V0LmV4dHJhID0gJ3N0eWxlPSJib3JkZXI6MXB4IHNvbGlkIGJsYWNrIicsIGZpZy5jYXAgPSAiTWFraW5nIGFuIFIgU2NyaXB0IEZpbGUiLCBlY2hvID0gRkFMU0V9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1tYWtlX3NjcmlwdC5wbmciKQpgYGAKCjJcLiBUaGlzIG9wZW5zIGEgbmV3IHVudGl0bGVkIGZpbGUgaW4gYW4gZWRpdGluZyBwYW5lIGluIHRoZSB1cHBlciBsZWZ0IG9mIHRoZSBSU3R1ZGlvIHNjcmVlbi4gVGhlIGNvbnNvbGUgcGFuZSB3aWxsIGJlIHB1c2hlZCBkb3duIHRvIHRoZSBib3R0b20gaGFsZiBvZiB0aGUgc2NyZWVuLiBZb3UgY2FuIGNsaWNrIGFuZCBkcmFnIHRoZSBkaXZpZGVycyBiZXR3ZWVuIHRoZSBmb3VyIHBhbmVzIHRvIGNoYW5nZSB0aGVpciBzaXplcyBhcyB5b3UgcHJlZmVyLgoKYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoID0gIjEwMCUiLCBvdXQuZXh0cmEgPSAnc3R5bGU9ImJvcmRlcjoxcHggc29saWQgYmxhY2siJywgZmlnLmNhcCA9ICJOZXcgU2NyaXB0IFRhYiIsIGZpZy5wb3MgPSAnSCcsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW5ld19zY3JpcHQucG5nIikKYGBgCgozXC4gRnJvbSB0aGUgbWFpbiBSU3R1ZGlvIG1lbnUgc2VsZWN0IEZpbGUtXD5TYXZlIEFzLi4gdG8gc2F2ZSB5b3VyIGZpbGUuIEFsd2F5cyBnaXZlIHlvdXIgZmlsZXMgZGVzY3JpcHRpdmUgbmFtZXMgdG8gbWFrZSBpdCBlYXN5IHRvIGZpbmQgdGhlIG9uZSB5b3Ugd2FudCBsYXRlci4KCjRcLiBZb3UgY2FuIHR5cGUgUiBjb21tYW5kcyBpbnRvIHRoZSBuZXcgZmlsZSAoaW4gdGhlIHVwcGVyIGxlZnQgcGFuZSkgZXhhY3RseSBhcyB5b3UgdHlwZWQgaW50byB0aGUgY29uc29sZS4KCjVcLiBFeGVjdXRpbmcgYSBjb21tYW5kIHRoYXQgaXMgdHlwZWQgaW50byBhIGZpbGUgd29ya3MgYSBsaXR0bGUgZGlmZmVyZW50bHkgdGhhbiBleGVjdXRpbmcgYSBjb21tYW5kIHRoYXQgaXMgdHlwZWQgaW50byB0aGUgY29uc29sZS4gVG8gZXhlY3V0ZSBhIHNpbmdsZSBsaW5lIG9mIGNvZGUgaW4gdGhlIGZpbGUsIGNsaWNrIHlvdXIgbW91c2UgY3Vyc29yIGFueXdoZXJlIG9uIHRoZSBsaW5lIG9mIGNvZGUuICoqRE8gTk9UIFNFTEVDVCBBTlkgQ0hBUkFDVEVSUy4gSE9MRCBUSEUgTU9VU0UgU1RJTEwgV0hJTEUgQ0xJQ0tJTkcqKi4gVGhlbiB0eXBlIGN0cmwrRW50ZXIgKFdpbmRvd3MpIG9yIGNtZCtFbnRlciAoTWFjKS4KCjZcLiBUbyBleGVjdXRlIG11bHRpcGxlIGxpbmVzIG9mIGNvZGUgaW4gdGhlIGZpbGUsIHNlbGVjdCBhbGwgdGhlIGNvZGUgeW91IHdhbnQgYnkgY2xpY2tpbmcgYW5kIGRyYWdnaW5nIHRoZSBtb3VzZSAoY3RybCtBIG9yIGNtZCtBIGZvciB0aGUgd2hvbGUgZmlsZSksIHRoZW4gdHlwZSBjdHJsK0VudGVyIG9yIGNtZCtFbnRlci4KCjdcLiBUaGUgb3V0cHV0IGZyb20geW91ciBjb2RlIHdpbGwgYmUgd3JpdHRlbiB0byB0aGUgY29uc29sZSwganVzdCBhcyB0aG91Z2ggeW91IGhhZCB0eXBlZCB0aGUgY29kZSB0aGVyZS4KCjhcLiBBZnRlciBlbnRlcmluZyBzb21lIGNvZGUgaW50byB5b3VyIGZpbGUsIHNhdmUgaXQgKHRoZSBwcm9ncmFtbWVyJ3MgbW90dG8gaXMgU2F2ZSBFYXJseSwgU2F2ZSBPZnRlbikuIFlvdSBjYW4gdGhlbiBzYWZlbHkgZXhpdCB0aGUgUlN0dWRpbyBwcm9ncmFtLgoKOVwuIEdvIHRvIHdoZXJldmVyIHlvdSBzYXZlZCB5b3VyIG5hbWVkIGNvZGUgZmlsZSAoaXQgd2lsbCBoYXZlIHN1ZmZpeCAuUikgRG91YmxlLWNsaWNrIG9uIGl0IGFuZCBpdCBzaG91bGQgb3BlbiBpbiBSU3R1ZGlvLiBJZiBpdCBvcGVucyBpbiBzb21ldGhpbmcgZWxzZSAoZS5nLiBXb3JkIG9yIE5vdGVwYWQpLCB0aGlzIGp1c3QgbWVhbnMgdGhhdCB5b3VyIG1hY2hpbmUgaXMgbm90IGNvbmZpZ3VyZWQgdG8gYXNzb2NpYXRlIC5SIGZpbGVzIHdpdGggUlN0dWRpby4gSW4gdGhpcyBjYXNlLCAqKnJpZ2h0LWNsaWNrKiogb24gdGhlIGZpbGUsIHNlbGVjdCBPcGVuIFdpdGgsIGFuZCB0aGVuIFJTdHVkaW8uIChXZSBzZWUgYSBtb3JlIGNvbnZlbmllbnQgd29ya2Zsb3cgaW4gYSBtb21lbnQuKQoKMTBcLiBXaGVuIHRoZSBmaWxlIGlzIG9wZW4gaW4gUlN0dWRpbyB5b3UgY2FuIHJ1biBhbGwgeW91ciBjb2RlIGFnYWluIChzZWUgaXRlbXMgNSBhbmQgNiBhYm92ZSkgd2l0aG91dCBoYXZpbmcgdG8gcmV0eXBlIGFueXRoaW5nLgoKXAoKIyMgVXNpbmcgUHJvamVjdHMgaW4gUlN0dWRpbwoKQW4gUlN0dWRpbyAqKnByb2plY3QqKiBpcyBhIGZvbGRlciwgY3JlYXRlZCBmcm9tIGluc2lkZSBSU3R1ZGlvLCB0aGF0IGNvbnRhaW5zIHJlbGF0ZWQgc2NyaXB0IGZpbGVzLCBkYXRhIGZpbGVzLCBhbmQgUlN0dWRpbyAqKm1ldGFkYXRhKiogZmlsZXMgd2hpY2ggZW5zdXJlIFIgY29kZSBydW5zIGNvcnJlY3RseSBhbmQgZWZmaWNpZW50bHkuIE1vc3QgZXhwZXJpZW5jZWQgUiBkZXZlbG9wZXJzICphbHdheXMqIG9yZ2FuaXNlIHRoZWlyIHdvcmsgaW50byBwcm9qZWN0cy4gVGhpcyBpcyBsb2dpY2FsbHkgc2ltaWxhciB0byBvcmdhbmlzaW5nIHlvdXIgcmVndWxhciBjb21wdXRlciBmaWxlcyBpbnRvIGZvbGRlcnMgLS0gaXQga2VlcHMgcmVsYXRlZCBtYXRlcmlhbCBidW5kbGVkIHRvZ2V0aGVyLCBtYWtpbmcgaXQgZWFzaWVyIHRvIHdvcmsgd2l0aC4KClR5cGljYWxseSwgY3JlYXRpbmcgYSBwcm9qZWN0IGlzIHRoZSAqZmlyc3QqIHN0ZXAgaW4gUiBkZXZlbG9wbWVudC4gV2hlbiBhIHByb2plY3QgaXMgaW5pdGlhbGx5IGNyZWF0ZWQsIGl0IGNvbnRhaW5zIG9ubHkgdGhlIFJTdHVkaW8gbWV0YWRhdGEgZmlsZXMuIFRoZW4gZGF0YSBmaWxlcyBhcmUgYWRkZWQgYnkgc2ltcGx5IG1vdmluZyB0aGVtIGludG8gZm9sZGVyIGxpa2UgYW55IG90aGVyIGZpbGUuIFNjcmlwdCBmaWxlcyBhbmQgb3V0cHV0IGZpbGVzIGFyZSBhZGRlZCB0byB0aGUgcHJvamVjdCBmcm9tIGluc2lkZSBSU3R1ZGlvIGFzIHRoZSB3b3JrIHByb2dyZXNzZXMuIEF0IGFsbCB0aW1lcywgYWxsIHRoZSByZWxhdGVkIGNvbnRlbnQgZm9yIHRoZSBwcm9qZWN0IGlzIHRpZGlseSBjb250YWluZWQgaW4gdGhlIHByb2plY3QgZm9sZGVyIGZvciBlYXN5IGxvY2F0aW9uIGFuZCB1c2UuCgojIyMgQ3JlYXRpbmcgYSBQcm9qZWN0IGluIFJTdHVkaW8KCjFcLiBGcm9tIHRoZSBtYWluIG1lbnUgc2VsZWN0IEZpbGUgLT4gTmV3IFByb2plY3QKCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNTAlIiwgb3V0LmV4dHJhID0gJ3N0eWxlPSJib3JkZXI6MXB4IHNvbGlkIGJsYWNrIicsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW5ld19wcm9qZWN0XzAxLnBuZyIpCmBgYAoKCjJcLiBJbiB0aGUgcmVzdWx0aW5nIHBvcC11cCB3aW5kb3csIHNlbGVjdCBOZXcgRGlyZWN0b3J5LCB0aGVuIE5ldyBQcm9qZWN0LCB0byBuYXZpZ2F0ZSB0byB0aGUgQ3JlYXRlIE5ldyBQcm9qZWN0IGRpYWxvZ3VlIGJveC4KCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjUwJSIsIG91dC5leHRyYSA9ICdzdHlsZT0iYm9yZGVyOjFweCBzb2xpZCBibGFjayInLCBlY2hvID0gRkFMU0V9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1uZXdfcHJvamVjdF8wMi5wbmciKQpgYGAKCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNTAlIiwgb3V0LmV4dHJhID0gJ3N0eWxlPSJib3JkZXI6MXB4IHNvbGlkIGJsYWNrIicsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW5ld19wcm9qZWN0XzAzLnBuZyIpCmBgYAoKYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI1MCUiLCBvdXQuZXh0cmEgPSAnc3R5bGU9ImJvcmRlcjoxcHggc29saWQgYmxhY2siJywgZWNobyA9IEZBTFNFfQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtbmV3X3Byb2plY3RfMDQucG5nIikKYGBgCgozXC4gKipUSElTIElTIFRIRSBUUklDS1kgUEFSVC4qKiBUaGUgQ3JlYXRlIE5ldyBQcm9qZWN0IGRpYWxvZ3VlIGhhcyBhIHRleHQgYm94LCBmb2xsb3dlZCBieSBhIEJyb3dzZSBidXR0b24uIENvdW50ZXJpbnR1aXRpdmVseSwgeW91IGhhdmUgdG8gZG8gdGhlIEJyb3dzZSBidXR0b24gKmZpcnN0Ki4gQ2xpY2sgQnJvd3NlIGFuZCBuYXZpZ2F0ZSAqKnRvIHdoZXJlIHlvdSB3YW50IHlvdXIgcHJvamVjdCBmb2xkZXIgdG8gYmUgY3JlYXRlZCoqLiBPbmx5IHRoZW4sIGNsaWNrIGluIHRoZSBEaXJlY3RvcnkgTmFtZSB0ZXh0IGJveCBhbmQgdHlwZSBhIG5hbWUgZm9yIHlvdXIgcHJvamVjdCBmb2xkZXIuIEJlIHN1cmUgdG8gbWFrZSB0aGlzIG5hbWUgZGVzY3JpcHRpdmUgLS0gaXQgaXMgYXdrd2FyZCB0byBjaGFuZ2UgdGhlIG5hbWUgb2YgYSBwcm9qZWN0IGFmdGVyIGl0IGlzIGNyZWF0ZWQuIENsaWNrIHRoZSBDcmVhdGUgUHJvamVjdCBidXR0b24gdG8gZmluaXNoLiBSU3R1ZGlvIHdpbGwgcmVmcmVzaCBhcyBpdCBuYXZpZ2F0ZXMgdG8geW91ciBuZXcgZW1wdHkgcHJvamVjdC4KCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNTAlIiwgb3V0LmV4dHJhID0gJ3N0eWxlPSJib3JkZXI6MXB4IHNvbGlkIGJsYWNrIicsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW5ld19wcm9qZWN0XzA1LnBuZyIpCmBgYAoKNFwuIFF1aXQgb3V0IG9mIFJTdHVkaW8sIGFuZCBuYXZpZ2F0ZSB0byB0aGUgZGlyZWN0b3J5IHdoZXJlIHlvdSBjcmVhdGVkIHlvdXIgcHJvamVjdC4gWW91IHdpbGwgZmluZCBhIG5ldyBmb2xkZXIgbGFiZWxsZWQgd2l0aCB0aGUgcHJvamVjdCBuYW1lIHlvdSBjaG9zZS4KCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNTAlIiwgb3V0LmV4dHJhID0gJ3N0eWxlPSJib3JkZXI6MXB4IHNvbGlkIGJsYWNrIicsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW5ld19wcm9qZWN0XzA2LnBuZyIpCmBgYAoKNVwuIE9wZW4gdGhlIHByb2plY3QgZm9sZGVyLiBJdCB3aWxsIGNvbnRhaW4gYSBmb2xkZXIgY2FsbGVkIC5ScHJvai51c2VyIGFuZCBhIGZpbGUgY2FsbGVkIC5SaGlzdG9yeS4gVGhlc2UgYXJlIFJTdHVkaW8gbWV0YWRhdGEgZmlsZXMgLS0gbGVhdmUgdGhlbSBhbG9uZS4gKFlvdSBtYXkgbmVlZCB0byB0dXJuIG9uIGhpZGRlbiBmaWxlcyBpbiBXaW5kb3dzIEV4cGxvcmVyIG9yIHRoZSBNYWMgRmluZGVyIHRvIHNlZSB0aGVzZSBmaWxlcy4pIEl0IGFsc28gY29udGFpbnMgYSBmaWxlIHdpdGggdGhlIHByb2plY3QgbmFtZSBhbmQgc3VmZml4IC5ScHJvai4KCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNTAlIiwgb3V0LmV4dHJhID0gJ3N0eWxlPSJib3JkZXI6MXB4IHNvbGlkIGJsYWNrIicsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW5ld19wcm9qZWN0XzA3LnBuZyIpCmBgYAoKNlwuIFdoZW4geW91IG9wZW4gdGhlIHByb2plY3QgaW4gUlN0dWRpbyAod2Ugc2VlIGhvdyBpbiBhIG1vbWVudCkgdGhlIHByb2plY3QgZm9sZGVyIHdpbGwgYmUgaXRzICoqd29ya2luZyBkaXJlY3RvcnkqKi4gVGhhdCBpcywgUlN0dWRpbyB3aWxsIGJlICJsb29raW5nIGF0IiB0aGlzIGZvbGRlci4gSXQgd2lsbCBiZSBhYmxlIHRvIGFjY2VzcyBhbnkgZmlsZXMgaW4gdGhpcyBmb2xkZXI7IHdoZW4geW91IGdlbmVyYXRlIG91dHB1dCBmaWxlcywgdGhleSB3aWxsIGJlIHdyaXR0ZW4gdG8gdGhpcyBmb2xkZXIuIFRvIGlsbHVzdHJhdGUgdGhpcywgSSBoYXZlIHBsYWNlZCBhbiBFeGNlbCBmaWxlIGludG8gbXkgbmV3IHByb2plY3QgZm9sZGVyLCBhbmQgd2Ugd2lsbCBzZWUgaG93IGl0IGFwcGVhcnMgdG8gUlN0dWRpby4gWW91IGNhbiBwbGFjZSBmaWxlcyBpbiB5b3VyIHByb2plY3QgZm9sZGVyIGJ5IGNvcHkvcGFzdGUsIG1vdmluZyBpbiB0aGUgRmluZGVyLCBvciBjcmVhdGluZyBuZXcgZmlsZXMsIGV4YWN0bHkgYXMgeW91IHdvcmsgd2l0aCBmaWxlcyBpbiB0aGUgb3JkaW5hcnkgd2F5IGZvciB5b3VyIG9wZXJhdGluZyBzeXN0ZW0uCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjUwJSIsIG91dC5leHRyYSA9ICdzdHlsZT0iYm9yZGVyOjFweCBzb2xpZCBibGFjayInLCBlY2hvID0gRkFMU0V9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1uZXdfcHJvamVjdF8wOC5wbmciKQpgYGAKCjdcLiBEb3VibGUgY2xpY2sgb24gdGhlIC5ScHJvaiBmaWxlIGluIHlvdXIgcHJvamVjdCBmb2xkZXIuIFRoaXMgYXV0b21hdGljYWxseSBvcGVucyB5b3VyIHByb2plY3QgaW4gUlN0dWRpbyBhbmQgc2V0cyB0aGUgd29ya2luZyBkaXJlY3RvcnkgKHdoYXQgUlN0dWRpbyBjYW4gInNlZSIpIGNvcnJlY3RseS4gTm90ZSB0aGF0IHRoZSBGaWxlcyB0YWIgaW4gdGhlIGxvd2VyIHJpZ2h0IHBhbmUgc2hvd3MgdGhlIGNvbnRlbnRzIG9mIHRoZSBwcm9qZWN0IGZvbGRlciwgaW5jbHVkaW5nIHRoZSBhZGRlZCBzcHJlYWRzaGVldCBmaWxlLgoKYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI1MCUiLCBvdXQuZXh0cmEgPSAnc3R5bGU9ImJvcmRlcjoxcHggc29saWQgYmxhY2siJywgZWNobyA9IEZBTFNFfQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtbmV3X3Byb2plY3RfMDkucG5nIikKYGBgCgo4XC4gV2hlbiB3b3JraW5nIHdpdGggUiB3ZSByZWNvbW1lbmQgdGhhdCB5b3UgY3JlYXRlIGEgbmV3IHByb2plY3QgZm9yIGV2ZXJ5IG1vZHVsZSBvZiB3b3JrLiBUaGUgZXhhY3QgbGV2ZWwgb2YgZGV0YWlsIHRoYXQgZGVmaW5lcyBhICJtb2R1bGUgb2Ygd29yayIgd2lsbCBiZWNvbWUgcGFydCBvZiB5b3VyIHByb2Zlc3Npb25hbCBzdHlsZS4gV2UgZnVydGhlciByZWNvbW1lbmQgdGhhdCB5b3UgKipBTFdBWVMqKiBiZWdpbiB3b3JraW5nIG9uIGFueSBSU3R1ZGlvIHByb2plY3QgYnkgZG91YmxlLWNsaWNraW5nIG9uIHRoZSAuUnByb2ogZmlsZS4gRG8gbm90IG9wZW4gUlN0dWRpbyBkaXJlY3RseSBhbmQgdGhlbiB3YW5kZXIgYXJvdW5kIGxvb2tpbmcgZm9yIHlvdXIgcHJvamVjdC4gCgpGb3IgYSBkZXRhaWxlZCBkaXNjdXNzaW9uIG9mIGFkdmFuY2VkIFJTdHVkaW8gcHJvamVjdCBvcmdhbmlzYXRpb24gYW5kIHVzZSwgc2VlIFtSIGZvciBEYXRhIFNjaWVuY2UgLSBXb3JrZmxvdzogUHJvamVjdHMgKGh0dHBzOi8vcjRkcy5oYWQuY28ubnovd29ya2Zsb3ctcHJvamVjdHMuaHRtbCldKGh0dHBzOi8vcjRkcy5oYWQuY28ubnovd29ya2Zsb3ctcHJvamVjdHMuaHRtbCkgCgoKIyMgQW4gRXZlbiBCZXR0ZXIgU2NyaXB0IEZpbGUKCkEgYmFzaWMgc2NyaXB0IGZpbGUgKG9mIHR5cGUgLlIpIHdpbGwgc3RvcmUgYW5kIHByZXNlcnZlIHlvdXIgY29kZS4gUlN0dWRpbyBhbHNvIHByb3ZpZGVzICoqUiBNYXJrZG93bioqIGZpbGVzIChvZiB0eXBlIC5SbWQpIHRoYXQgY2FuIGRvIG11Y2ggbW9yZS4gUiBNYXJrZG93biBpcyBhbiBleHRlbmRlZCBzY3JpcHQgZm9ybWF0IHRoYXQgYWxsb3dzIHlvdSB0byBlbWJlZCBSIGNvbW1hbmRzIGluIGZvcm1hdHRlZCB0ZXh0LiBSU3R1ZGlvIHByb2Nlc3NlcyBSIE1hcmtkb3duIGZpbGVzLCBwcm9kdWNpbmcgSFRNTCwgV29yZCwgb3IgcGRmIG91dHB1dCBmaWxlcy4gRHVyaW5nIHByb2Nlc3NpbmcgKHdoaWNoIGlzIGNhbGxlZCAqa25pdHRpbmcqKSBSU3R1ZGlvIHJ1bnMgYW55IGVtYmVkZGVkIFIgY29tbWFuZHMgYW5kICoqaW5zZXJ0cyB0aGUgcmVzdWx0cyBpbnRvIHRoZSBvdXRwdXQgZG9jdW1lbnQqKi4gWW91IGRvbid0IG5lZWQgdG8gcHJvY2VzcyB5b3VyIGRhdGEgaW4gUlN0dWRpbyBhbmQgdGhlbiBjb3B5L3Bhc3RlIHRoZSByZXN1bHRzIGludG8gYSBzZXBhcmF0ZSBXb3JkIGRvY3VtZW50LiBZb3UgY2FuIGluc2VydCB0aGUgY29kZSBkaXJlY3RseSBpbnRvIHlvdXIgdGV4dCBpbiBhbiBSIE1hcmtkb3duIGZpbGUsIGFuZCBpdCB3aWxsIGJlIGV4ZWN1dGVkIHdoZW4gUlN0dWRpbyBrbml0cy4gCgpXZSB3aWxsIGNvdmVyIFJNYXJrZG93biAoYW5kIGl0cyBuZXh0LWdlbmVyYXRpb24gdmVyc2lvbiBRdWFydG8pIGluIGRlcHRoIGluIFtNb2R1bGUgNF0oMDQtY29tbXVuaWNhdGUuaHRtbCksIGJ1dCB3ZSBpbnRyb2R1Y2UgdGhlIHByb2Nlc3MgYnJpZWZseSBoZXJlOgoKMVwuIEluIFJTdHVkaW8sIGNsaWNrIG9uIHRoZSBGaWxlIG1lbnUsIHNlbGVjdCBOZXcgRmlsZSBhbmQsIGZyb20gdGhlIHN1Ym1lbnUgdGhhdCBvcGVucywgY2xpY2sgb24gUiBNYXJrZG93bi4KCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNTAlIiwgZmlnLmNhcCA9ICJDcmVhdGUgYW4gUiBNYXJrZG93biBGaWxlIiwgZmlnLnBvcyA9ICJIIiwgZWNobyA9IEZBTFNFfQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtbWFrZV9ybWQucG5nIikKYGBgCgoyXC4gQSBkaWFsb2d1ZSBib3ggd2lsbCBvcGVuLCB3aGVyZSB5b3UgZW50ZXIgYSB0aXRsZSBmb3IgeW91ciBkb2N1bWVudCwgdGhlIG5hbWUgb2YgdGhlIGF1dGhvciBhbmQgdGhlIGRvY3VtZW50IGRhdGUgKHNldCB0byB0aGUgY3VycmVudCBkYXRlIGJ5IGRlZmF1bHQpLiBUaGVzZSB3aWxsIGFwcGVhciBhdCB0aGUgdG9wIG9mIHRoZSBrbml0IGRvY3VtZW50LiBZb3UgY2FuIHNlbGVjdCB0aGUgb3V0cHV0IGZvcm1hdC4gTGVhdmUgaXQgYXMgSFRNTCBmb3IgdGhpcyBleGVyY2lzZS4KCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aCA9ICI3NSUiLCBmaWcucG9zID0gIkgiLCBmaWcuY2FwID0gIlIgTWFya2Rvd24gRGlhbG9ndWUiLCBlY2hvID0gRkFMU0V9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1tYXJrZG93bl9kaWFsb2d1ZS5wbmciKQpgYGAKCjNcLiBSU3R1ZGlvIHdpbGwgY3JlYXRlIGEgbmV3IGZpbGUgYW5kIG9wZW4gaXQgaW4gYSBuZXcgdGFiLiBUaGUgZmlsZSBpcyB1bnRpdGxlZCwgc28gc2F2ZSBpdCBhbmQgZ2l2ZSBpdCBhIHNlbnNpYmxlIG5hbWUuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwID0gIkEgTmV3IFIgTWFya2Rvd24gRmlsZSIsIG91dC53aWR0aCA9ICIxMDAlIiwgZWNobyA9IEZBTFNFLCBmaWcucG9zID0gIkgifQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtbWFya2Rvd25fdGVtcGxhdGUucG5nIikKYGBgCgpUaGUgZmlsZSBhbHJlYWR5IGNvbnRhaW5zIHNvbWUgdGV4dC4gVGhpcyBpcyBzYW1wbGUgY29udGVudHMgdG8gaWxsdXN0cmF0ZSBob3cgUiBNYXJrZG93biB3b3Jrcy4gWW91IHdpbGwgbm90ZSB0aGF0IHRoZSBmaWxlIGhhcyBhcmVhcyB3aXRoIGEgd2hpdGUgYmFja2dyb3VuZCBhbmQgYXJlYXMgd2l0aCBhIHNoYWRlZCBiYWNrZ3JvdW5kLiBUaGUgd2hpdGUgYXJlYXMgYXJlIHBsYWluIHRleHQsIHRoZSBzaGFkZWQgYXJlYXMgYXJlIFIgY29kZSBXaGVuIHRoZSBmaWxlIGlzIGtuaXQsIHRoYXQgY29kZSB3aWxsIGJlIHJ1biwgYW5kIGl0cyBvdXRwdXQgaW5zZXJ0ZWQgaW50byB0aGUgdGV4dC4gVG8gc2VlIHRoaXMgaW4gYWN0aW9uLCBjbGljayB0aGUgKipLbml0KiogaWNvbiBhdCB0aGUgdG9wIHRoZSBSU3R1ZGlvIHRhYi4KCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5jYXAgPSAiVGhlIEtuaXQgQnV0dG9uIiwgb3V0LndpZHRoID0gIjUwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLnBvcyA9ICJIIn0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW1hcmtkb3duX2tuaXRfYnV0dG9uLnBuZyIpCmBgYAoKUlN0dWRpbyB3aWxsIHByb2R1Y2UgYSBiZWF1dGlmdWwgSFRNTCBkb2N1bWVudCBhbmQgb3BlbiBpdCBpbiBhIGxvY2FsIGJyb3dzZXIgd2luZG93LiBTZWUgaWYgeW91IGNhbiBtYXRjaCB0aGUgUiBjb2RlIHNlZ21lbnRzIGluIHRoZSBSIE1hcmtkb3duIGRvY3VtZW50IHRvIHRoZSBvdXRwdXQgdGhhdCBhcHBlYXJzIGluIHRoZSBIVE1MIHBhZ2UuCgpSIE1hcmtkb3duIGlzIGEgcG93ZXJmdWwgdG9vbCBmb3IgZ2VuZXJhdGluZyByZXNlYXJjaCByZXBvcnRzIHdoZW4gYW5hbHlzaW5nIGRhdGEgd2l0aCBSLiBBcyB3ZSBwcm9jZWVkIHRocm91Z2ggdGhpcyBtaW5pLWNvdXJzZSB3ZSB3aWxsIGV4cGxvcmUgYWRkaXRpb25hbCBmZWF0dXJlcyBvZiBSIE1hcmtkb3duLCBhbmQgeW91IG1heSB3aXNoIHRvIGNvbnNpZGVyIHVzaW5nIGl0IGZvciB5b3VyIG93biBjb3Vyc2UgYXNzaWdubWVudHMuIENoZWNrIHdpdGggeW91ciBsZWN0dXJlcnMgdG8gc2VlIGlmIHRoaXMgaXMgc3VpdGFibGUuCgpcCgoKXAoKIyBDb25jbHVzaW9uCgpJbiB0aGlzIG1vZHVsZSB5b3UgaGF2ZSBjb25zaWRlcmVkIHRoZSBpbm5lciB3b3JraW5ncyBvZiB0aGUgY29tcHV0ZXIsIHdyaXR0ZW4gUiBjb21tYW5kcyBpbnRvIHRoZSBSU3R1ZGlvIERldmVsb3BtZW50IEVudmlyb25tZW50LCBtZXQgc29tZSBvZiB0aGUgdGhpbmdzIFIgdW5kZXJzdGFuZHMgKG51bWJlciwgc3RyaW5ncywgYW5kIHZlY3RvcnMpIGFuZCBzb21lIG9mIHRoZSBhY3Rpb25zIFIgY2FuIHBlcmZvcm0gKGZ1bmN0aW9ucykuIENvbmdyYXR1bGF0aW9ucy4KCiMjIFdoYXQncyBOZXh0CgpJbiB0aGlzIHdlZWsncyBoYW5kcy1vbiBzZXNzaW9uIHdlIHdpbGwgY29udGludWUgdG8gYnVpbGQgb3VyIFIgc2tpbGxzLCB3b3JraW5nIHRvZ2V0aGVyIHRocm91Z2ggdGhlIGV4ZXJjaXNlcyBpbiB0aGUgWm9vbSBub3RlcyBmb3IgdGhpcyBtb2R1bGUuIChJZiB5b3UgcHJlZmVyLCBnbyBhaGVhZCBhbmQgdHJ5IHRoZW0gb24geW91ciBvd24uKSBZb3UgY2FuIGFsc28gdXNlIHRoZSBoYW5kcy1vbiBzZXNzaW9ucyB0byBnZXQgaGVscCB3aXRoIGFueSBjb3Vyc2V3b3JrLCBwcm9qZWN0cywgb3Igb3RoZXIgUiBxdWVzdGlvbnMgeW91IG1heSBoYXZlLgoKSW4gb3VyIG5leHQgbW9kdWxlLCB3ZSB3aWxsIGxlYXJuIGhvdyB0byByZWFkIGRhdGEgZmlsZXMgaW50byBSIGFuZCBtYWtlIHBsb3RzIGFuZCBmaWd1cmVzIHRoYXQgeW91IGNhbiB1c2UgaW4gYSByZXNlYXJjaCByZXBvcnQuIFdlIHdpbGwgc3RhcnQgd2l0aCBzaW1wbGUgcGxvdHMgeW91IGNhbiBjcmVhdGUgdXNpbmcgb25seSBiYXNlIFIuIFRoZW4gd2Ugd2lsbCBsZWFybiB0byB1c2UgYSBwb3dlcmZ1bCBncmFwaGljcyBsaWJyYXJ5IGNhbGxlZCAqKmdncGxvdCoqIChwYXJ0IG9mIHRoZSAqKnRpZHl2ZXJzZSoqIGZhbWlseSBvZiBSIGV4dGVuc2lvbnMpLiBXaXRoIGdncGxvdCB5b3UgY2FuIG1ha2UgcHVibGljYXRpb24tcXVhbGl0eSBncmFwaHMgd2l0aCBvbmx5IGEgZmV3IGxpbmVzIG9mIFIgY29kZS4KCgoKCgoKCg==