R Scripts
Running R code using the console (bottom left in figure below) is a
great place to start, but has its limitations. Each time you want to
execute a set of commands, you have to re-enter them at the command
line. Complex commands are potentially subject to typographical errors,
necessitating that they be re-entered correctly. Repeating a set of
operations requires re-entering the code stream. To give yourself more
room to work, it’s a great idea to use the R script editor.
A script is simply a text file containing a set of commands and
comments. The script can be saved and used later to re-execute the saved
commands. The script can also be edited so you can execute a modified
version of the commands.
You can open a new empty script by clicking the New File icon in the
upper left of the main RStudio toolbar. This icon looks like a white
square with a white plus sign in a green circle. Clicking the icon opens
the New File Menu. Click the “R Script” option and the script editor
will open with an empty script. Your R Studio should look similar to
below (image source: R for Data
Science)
RStudio
R Scripts are basically text files with a .R extension that houses
your code and comments. You write your code. Execute that code from your
R script. Results are produced in your R console window. In this class,
we won’t be using regular R Scripts for homework assignments. Instead,
we’ll be using R
Markdown.
R Markdown documents take script files to a new level by allowing you
to mix R commands with explanatory text. Think of an R Markdown document
as an R script on steroids. Your R Markdown source document is compiled
into an output report evaluating the R commands in the source document
to produce easily reproducible results in an aesthetically pleasing
form. It combines code, results from the code, and narrative text
explaining the results to produce beautiful documents and academic
reports.
Still not convinced that R Markdown is useful? Check out Nikhil
Kaza’s thorough description of why
we should use R Markdown.
R Markdown
R Markdown is a simple formatting syntax for authoring html, pdf, and
Microsoft Word documents in RStudio. For each R related assignment, you
will upload onto Canvas two documents:
- An R Markdown document, which has an .Rmd extension
- A knitted
.html, .pdf or
.docx file
These documents will provide us an easy-to-read document to grade;
more importantly, you will get to practice (1) writing scripts, (2)
keeping track of the analyses you run, and (3) organizing your output in
a reader-friendly manner. When you submit these documents on Canvas,
do not combine them into a zipped compressed folder.
They should be two separate files.
To be clear, R is a programming language. RStudio is an application.
R Markdown is a markup syntax to convert R script and text into a pdf or
html document. It allows for presentation-ready documents that show
commands and results in a seamless flow. When you write R code and embed
it in presentation documents created using R Markdown, you are forced to
explicitly state the steps you took to do your research.
In RStudio, install the packages knitr and
rmarkdown using the install.packages()
command. Type the following in your RConsole window after
>
install.packages("knitr")
##
## The downloaded binary packages are in
## /var/folders/hs/zvzkdz_12yj_drz4g6sm8h_00000gq/T//RtmpoSIzGH/downloaded_packages
install.packages("rmarkdown")
##
## The downloaded binary packages are in
## /var/folders/hs/zvzkdz_12yj_drz4g6sm8h_00000gq/T//RtmpoSIzGH/downloaded_packages
Once you’ve installed these packages, you don’t need to install them
any more in the future. You also do not need to load them in at any time
using library().
Creating and saving an R Markdown
To create a new .Rmd file in RStudio, select File ->
New File -> R Markdown. A window should pop up. Type in “Assignment
1” next to Title and your name next to Author. Leave
everything else alone and click OK. A new window in the top left of your
RStudio console should pop up containing your new R Markdown file.
RStudio Interface
If you are using your personal computer for this guide, it’s best to
set up a clean and efficient file management structure. File management
is key to preventing R programming frustration. Here are some tips.
-Set up a clear and understandable hierarchical file system for this
class on your hard drive. For example, create a class folder (SPH 215).
Within this class folder, create the folder Assignments. Within the
Assignments folder, create separate folders for each Assignment
(e.g. Assignment 1, Assignment 2, …). Don’t work from your Desktop. Or
from the Downloads folder. Or some randomly named folder that you will
have a hard time finding a month, week or day from now. -Keep all your
files that are related to a lab or assignment in one folder. That is,
don’t have an Assignment 3 folder that contains data files specific to
Assignment 1. Keep everything in one folder, including the R Markdown
for that assignment or lab.
Using the basic guidelines above, save your R Markdown file into an
appropriate folder on your hard drive by clicking on File and then Save
from the RStudio menu.
To open an .Rmd file in RStudio, select File -> Open
File and navigate to the folder you saved the assignment template in and
select the file. You should see the R Markdown file pop up on the top
left portion of your RStudio interface
Authoring an R Markdown document
R Markdown documents contain 3 major components:
- A YAML header surrounded by - - -
- Chunks of R code surrounded by ```
- Text mixed with simple text formatting using the Markdown
syntax
R Code Chunks
When answering an assignment question, you’ll have the following
sequence of components in your R Markdown document: Question, R code
answering the question, comment describing what the code is doing, and
your text to explain the results. Let’s say you have the following
question in one of your assignments.
Question 1
1+1
1. What is the result of the operation above?
Assignments will ask you to write R code to accomplish a data
analysis task. You present and execute your R code inside R code chunks.
R chunks start with {r} and end with, and you insert your R
code in between. To designate 1+1 as R code, it will look
like the following in your R Markdown document.
```{r}
1+1
```
All code inside a chunk will be executed when knitting the markdown
file (i.e. the html file will show your code and its result). This means
that your R code must reside inside an R code chunk in order for it to
be processed as R code (otherwise R Markdown will think it is text).
This also means that nothing but executable code (or comments, which
we’ll get to next) should be inside a chunk.
We will ask you to annotate your R code so that we (and you) know
what is being done in that line of code. You designate annotations or
comments in R code using the # symbol. In programming,
comments are bits of text that are not interpreted as computer
instructions—they aren’t code, they’re just notes about the code! Since
computer code can be opaque and difficult to understand, we use comments
to help write down the meaning and purpose of our code. While a computer
is able to understand the code, comments are there to help people
understand it. This is particularly important when someone else will be
looking at your work—whether that person is a collaborator, or is simply
a future version of you (e.g., when you need to come back and fix
something and so need to remember what you were even thinking).
Comments should be clear, concise, and helpful—they should provide
information that is not otherwise present or “obvious” in the code
itself. So, to annotate the above line of code 1+1, you add
in your R code chunk:
```{r}
#this adds one plus one
1+1
```
You put your comments after the #.
The first line of the chunk has {r} which basically
states that everything inside the chunk will be in R code. Next to the
r, we can give the chunk a name, such as:
```{r q1chunk1}
#this adds one plus one
1+1
```
Here, we named the chunk q1chunk1 which indicates this
is question 1, chunk 1. You can name the chunk whatever you like (jimbo,
samantha, tony). The chunk name is not required; however, it is good
practice to give each chunk a unique name (we’ll see its value later
when we talk about knitting).
In the R Markdown you created and saved, you will notice the
following R code chunk after the YAML.
```{r}
knitr::opts_chunk$set(echo = TRUE)
```
The above code establishes global options for every R chunk code in
your R Markdown file. These options alter the way R results are spit out
in your formatted knitted document. I suggest adding the following
global options in every R Markdown assignment file.
```{r}
knitr::opts_chunk$set(warning=FALSE, message = FALSE)
```
The above code hides non error messages for every single R code chunk
in your file. These non error messages are unnecessary for the purposes
of this class. Other chunk options can be found here.
You can also set options for individual chunks. These are local
options - local to that chunk - and won’t be applied to other chunks in
your file. For example, you can add the options
warning=TRUE and message=TRUE to an individual
R code chunk as follows to show the messages for the R code in that
chunk. Notice that each argument is separated by a comma.
```{r q1chunk1, warning = TRUE, message = TRUE}
1+1
```
Text
In addition to R code, assignments will ask you to write text to
explain results. Going back to our example question from above:
Question 1
1+1
1. What is the result of the operation above?
You would type in your R Markdown document the following:
```{r q1chunk1,}
#this code adds one plus one
1+1
```
My analysis yields the number 2
The question and text explaining the result reside outside of the R
chunk. There is nothing special about the text in terms of its format or
placement.
Separating code one chunk at a time
Do not put all of your code for an entire assignment or even a single
question in one single chunk. For example, let’s say you see the
following in your homework assignment.
Question 1
1+1
2+2
Run each line of code above. What are the results?
Instead of including both lines of code in one chunk like as
follows
Question 1
```{r q1chunk1}
#this code adds one plus one
1+1
#this code adds two plus two
2+2
```
One plus one equals 2. Two plus two equals 4
Break it up and add text after each to explain the result.
Question 1
```{r q1chunk1}
#this code adds one plus one
1+1
```
One plus one equals 2.
```{r q1chunk2}
#this code adds two plus two
2+2
```
Two plus two equals 4
Think of writing a script as similar to writing an essay. You don’t
write an essay in one single paragraph. You break it up into several
paragraphs, where paragraph breaks are used to separate major points and
ideas. On the other end of the spectrum, do not break up every single
line of code like you would not break up every single sentence into
their own paragraphs in an essay. Break up your code where it makes
sense.
Always test each chunk
After you write code in a chunk, you’ll need to test the code to make
sure it is running properly. In other words, rather than writing all the
code and then running it at the end of the assignment, run the chunks
one at a time. To elaborate, let’s say the first question in an
assignment asks you to add one plus one. In your R Markdown document,
type in the following to answer this question.
```{r q1chunk1,}
#this code adds one plus one
1+1
```
One plus one equals 2
Run that code chunk to make sure it works (you should get 2!).
Then proceed to the next question. Let me emphasize: Do
not write all of your code answering every question in the assignment
and run it at the very end. Routinely TEST, Test, and test your
code to make sure it runs properly.
There are a number of ways to run code in R Markdown. First, you can
click your mouse in the R code chunk you want to run and click on
located at the top of the R Markdown window
and select Run Current Chunk.
Second, you can place your mouse cursor in the R code chunk and click
on
located on the right
corner of the chunk. See Figure below.
Running Chunks
In each R chunk, pressing the button
will run all previous R chunks. See Figure below.

Third, you can highlight partly or entirely a line of code and select
Code from the R Studio menu and select (among many options)
Run Selected Lines(s). This can also be accomplished by
highlighting lines of code and pressing Command+Return on a Mac and
Ctrl+Enter on a PC.
Note that when you run an R code chunk for the very first time ever,
its output will be embedded within your R Markdown document as shown
below
Output within R Markdown Document
This will also be true when you plot graphs and maps. When you are
testing your code, you might want to have the code results shown in your
RStudio Console (the bottom left window) and plots/maps shown in the
Plots window (bottom right window). To get RStudio to do this, select
the “Tools” menu and select “Global Options”. Select “R Markdown” from
the left-hand side and deselect the check box “Show output inline for
all R Markdown documents”. The output from your code should now be shown
in the console or Plots window.
R Markdown Options
Knitting an R Markdown document
In addition to the R Markdown Rmd file, you will need to submit its
knitted result. Knitting puts an assignment’s main
components - code, output, and text - in a nicely formatted document.
You can create three types of knitted documents: html, Microsoft Word,
and a pdf. I recommend knitting to an html file because it is the
easiest of the three options. Go back to the YAML example I showed
above. output: html_document tells R to produce an html
document. If you want to knit to a pdf, you’ll need to do some extra
package installing. See here.
kni To Knit your document click
, which will be located at the top of the upper left
R Markdown window. Note that you can select your document type when
knitting by clicking the pull down menu next to
and selecting your document
choice (default is html).
Click to Knit
When you start knitting, you will notice that a new window on the
bottom left will appear in place of the console. The window will show
the progress in your knitting. R is going through each R code chunk one
at a time. The percentages you will see will be based on the proportion
of your R Markdown file that R has successfully knitted. See Figure
below.
Knitting Progress Window
If it has a problem knitting, R will stop at the chunk that contains
the problem. You can determine the offending place in your R Markdown
file two ways. First, in the R Markdown tab in the bottom left window,
if you click on “Output” located at the top right corner of this window,
you will see the R Markdown progress window, the error in red, and where
R Markdown stopped. Carefully read the description of the error, which
will contain the R code chunk name and sometimes the lines containing
the problem in your R Markdown file. This is where it is useful for
naming your chunks. You can go to your offending chunk and see what may
be the problem. For example, the figure below shows knitting was stopped
because the object xyz was not created in the R Markdown
file. You can go to the chunk named q2chunk2 to remedy the
issue.
Knitting Stopped by an Error
The other way to find where R Markdown is having trouble is by
clicking on Issues also located at the top right corner of the
R Markdown window. The error will give you something similar to what you
found in the Output window, but instead of a chunk, it will tell you the
specific line in your R Markdown file that this error is located. Go to
that line in your R Markdown file and see what is the issue. For example
the error is located in line 34.
Knitting Stopped by an Error in the Issues
Screen
Hopefully, the error statement reveals why you were not able to knit.
If it is not illuminating (uh oh), you’ll need to figure out what you
did wrong. See the Having problems knitting? section
below.
Note that when you are knitting, progress and any errors will be
shown not in the regular R console window, but in a special R Markdown
window. To toggle back to the Console (and back to the R Markdown
window), just click on the Console (or R Markdown) tab as shown
below.
Console Tab
If you encounter no errors, a preview of your knitted document will
pop up in a new window and the .html (or .pdf
or .docx) file will be saved in the folder where your Rmd
file resides. I recommend not waiting till the very end of an
assignment to knit. When you finish one question, knit your
document to see if everything is working properly. If it is working for
that question, move on to the next question.
Let’s be clear. There are two things you’ll have to deal with: (1)
Making sure the R code is working correctly to get the results you need
in order to answer the question (2) Making sure the code is working
correctly to knit a final document. These two issues may be related (if
your R code is producing an error, R Markdown will not knit), but
sometimes they are not. So, check both your R code and your knitting
results often. And absolutely do not wait till the last minute
to knit. Knit as often as possible.
When you’re satisfied with the end product, submit your
.Rmd document and a knitted document on Canvas.
Having problems knitting?
-A major source of error for most new R Markdown users is that they
call up a data object in their R Markdown file that has not been created
within the R Markdown file. Treat the R Markdown as its own separate
system - even if you’ve created an object through the R Console, and you
can see it sitting in your Environment window, R Markdown won’t
recognize it because it was not created within the R Markdown
document.
To be clear, let’s say you typed directly in the R console the
following code:
myobject <- 2
You see the object myobject pop up in your Environment
window in the top right window. Let’s say you write in your R Markdown
file the code:
```{r}
myobject*10
```
You then click on
to
knit. You will get an error because R will not be able to knit
because myobject was not created within the R Markdown.
Both lines of code should be in the R Markdown file as follows:
```{r}
myobject <- 2
myobject*10
```
Once again, treat the R Markdown file as a self-contained,
stand alone script. This is an important concept to understand
because many students get tripped up on it when first starting out.
- Are you trying to bring in a data file that is not located in the
directory your R Markdown is pointed to? Remember, don’t scatter your
data files for an assignment across different folders. Keep them in -
one folder - the folder where your R Markdown document resides. To find
your current working directory, type in
getwd() in your
console and press enter. To set your working directory, type in -
setwd("folder") in your R Markdown and replace “folder””
with the entire path you want R to point to. You can
also set your working directory by clicking on Session -> Set Working
Directory -> Choose - Directory from the top menu.
- Do you have an
install.packages() in your R Markdown
script? Take it out! You only need to do it once - and never inside an R
Markdown script.
- Do you have a
View() command in your R Markdown script?
Take it out! Sometimes R Markdown will have problems when trying to view
an R data object.
- Are you using functions for a package that you need to load into R
and haven’t loaded it in your R Markdown using
library().
If so, load it in R Markdown!
- If you change a piece of code somewhere in the middle because you
caught an error, make sure that change is reflected throughout the code.
For example, let’s say you decide to rename the object
hisobject to herobject. There may be code later on in
the document that uses hisobject. So, you’ll need to change
every line of code in your R Markdown that uses
hisobject to now use herobject.
- SPELLING, Spelling, spelling. Check your spelling. You created an
object named hisobject, but you use it later in the file as
hsobject. R will tell you that hsobject is not found.
You use the function -
read_cvs() as opposed to the correct
function read_csv().
- R is case sensitive. The object Money is different from
money.
- R functions are sometimes finicky about spaces. They are also
finicky about quotes. Some functions require quotes, others don’t.
- Make sure that when you use brackets, parentheses or quotes, they
should start and end with one. It is very rare that you will use a left
parentheses and not close it with a right parentheses.
- As I mentioned above, don’t wait till the last minute to knit. Knit
after every question. Repeat it again: Knit after every question.
- The first place to check when you get a knitting error is the
specific chunk or line that the error is pointing to.
- As I mentioned above, check if your R code works one chunk at a
time.
- Having problem with a line of R code?
- Did you install the appropriate package?
- Did you load in the appropriate library?
- Are you using the right function?
- Did you specify all the function’s arguments correctly?
- Still having problems? Break up your code line by line or even
argument by argument to find the error? For example, let’s say you have
4 lines of code that are connected together - i.e. line 4 depends on
line 3, line 3 depends on line 2, and so on
line 1 code
line 2 code
line 3 code
line 4 code
If you get an error, run line 1 first. No error? Run line 1 and 2. No
error? Keep going until you find the offending line.
- If you have a Mac and you are getting an error when knitting, you
may need to download the most recent version of XQuartz, which can be
downloaded here
- If you’re still stuck, more than likely someone else also had a
similar problem in the past. So, ask a classmate. If your classmate is
also stuck, use Google and it might help you out.
Summary
The proper workflow for each assignment will be as follows
- Go through the week’s reading and lab guide and make sure you
understand the material.
- Create a folder on your hard drive that is specific to the
assignment (e.g. Assignment 1, Assignment 2, etc.).
- Create an R Markdown assignment file. Save it in the appropriate
assignment folder on your hard drive.
- Download any data needed for the assignment into the same folder.
For most assignments, I will upload the assignment data on GitHub, which
you can directly link to in R, so you won’t have to download data. Some
files will be located on Canvas.
- In the R Markdown document, answer the first assignment
question.
- Most of the questions will ask you to run code. Show that code in R
Markdown chunks. Bottom line: Any code you used to get a result should
be in your assignment. Otherwise, you will get points off, and for 1.
some questions, get all points off.
- Break up your code into different chunks where it makes sense. For
some questions, you might include all code for a question in one single
chunk. For other questions, you might break up the code into 1. several
chunks.
- Make sure your code works. Run code one chunk at a time to make sure
it is working. Note that there are multiple ways to get to an answer in
R. We will not grade on how efficient your code is unless stated 1. so
in the question.
- Most of the questions will ask you to explain your results. Write
your explanations outside of the R code chunks. Please - please
- take these interpretation questions seriously. This is a not a
programming or Data Science course - you may have taken 40 hours to
produce super elegant code to answer a question, but your results won’t
be worth much to anyone if you can’t properly interpret them.
- After you’ve completed the first question, knit to an
.html, .pdf or .docx file. Make
sure it knits properly. If it does not, examine the error, and fix the
problem.
- If you’re satisfied with your code and its results for the first
question, and the document properly knitted, move on to the next
question. Repeat steps 5 and 6.
- Once you’ve completed all questions and successfully knitted, submit
the
.Rmd and the knitted files on Canvas before the
designated due time.
- Smile, pat yourself on the back, and go for a walk, run, or bike
ride. Or just sit outside and enjoy nature.
Grading
This course isn’t about grading or metrics. It’s about learning the
material. But if you’d like to get full credit for each assignment, you
will need to:
- Show the correct results for a given question (e.g. map, table,
statistics).
- Show the code producing the results.
- Provide comments explaining what the code is doing.
- Provide correct written answers.
Any response requiring a data analysis task must be supported by code
you generate to produce your result. Just examining your various objects
in the “Environment” section of R Studio is insufficient—you must use
scripted commands. Because there are typically multiple ways to get an
answer, we will not grade you on the efficiency of your code. You can
ask for help from the TA and work with other students. However, you must
submit your own assignments.
Also note: all code used to produce your results must be shown in
your HTML file (e.g., do not use echo=FALSE or
include=FALSE as options anywhere. Well, mostly anywhere -
we’ll get to some cases where they are useful to include). Other pieces
of advice:
- We will not grade on how efficient your code is unless stated so in
the question. We will never take points off for accomplishing things
differently than expected as long as it produces the correct result.
However, if the answer is incorrect and your code indicates
little effort (e.g. blank or a few lines of code that yield
nothing) or is completely incomprehensible (e.g. 20 lines of mish mash),
expect few to no points.
- You must submit both an
.Rmd and its knitted
(.html, .pdf or .docx) file. If
you don’t, we will take significant points off.
Other things to know
- Please spell-check your assignment before handing it in (Edit ->
Check Spelling from the top menu bar).
- The default editor settings are to insert matching parentheses and
quotes; if you find that this intrudes on your workflow, you can disable
it via Tools -> Global Options -> Code then uncheck Insert -
matching parens/quotes.
- We expect you to work together. Two heads are better than one, and
four heads are better than two
- We expect you to ask for help if you get stuck (and you will be
stuck a lot–we know, because we always get stuck and work
through problems too!). We can’t read minds, so if you don’t
tell us that you are confused, we won’t know. We are always
happy to help!
- You should try and solve problems before you ask for help.
- Trying includes an Internet search (a crucial skill!). And maybe
even a dabble into ChatGPT if you dare.
- All homework should be submitted on Canvas.
Getting R Markdown Help
Whenever you are editing R Markdown documents in RStudio, you can
display an R Markdown cheat sheet by going to Help -> Cheatsheets
-> R Markdown Cheat Sheet. A basic introduction to R Markdown can
also be found in Chapter 21 in R for Data Science. R Studio
has a quick introduction
to R Markdown. We’ve put together some additional R tips here in the likely case that you get stuck. And,
of course, there is good ole Google. Use it to get help.
LS0tCnRpdGxlOiAiQXNzaWdubWVudHMiCi0tLQoKIyMjIyBBbGwgY3JlZGl0IGdvZXMgdG8gTm9saSBCcmF6aWwgYW5kIGhpcyBbQ1JEIDIzMCB3ZWJzaXRlXShodHRwczovL2NyZDIzMC5naXRodWIuaW8vaW5kZXguaHRtbCkgZm9yIHRoaXMgc2VjdGlvbgoKXAoKIyBSIFNjcmlwdHMKUnVubmluZyBSIGNvZGUgdXNpbmcgdGhlIGNvbnNvbGUgKGJvdHRvbSBsZWZ0IGluIGZpZ3VyZSBiZWxvdykgaXMgYSBncmVhdCBwbGFjZSB0byBzdGFydCwgYnV0IGhhcyBpdHMgbGltaXRhdGlvbnMuIEVhY2ggdGltZSB5b3Ugd2FudCB0byBleGVjdXRlIGEgc2V0IG9mIGNvbW1hbmRzLCB5b3UgaGF2ZSB0byByZS1lbnRlciB0aGVtIGF0IHRoZSBjb21tYW5kIGxpbmUuIENvbXBsZXggY29tbWFuZHMgYXJlIHBvdGVudGlhbGx5IHN1YmplY3QgdG8gdHlwb2dyYXBoaWNhbCBlcnJvcnMsIG5lY2Vzc2l0YXRpbmcgdGhhdCB0aGV5IGJlIHJlLWVudGVyZWQgY29ycmVjdGx5LiBSZXBlYXRpbmcgYSBzZXQgb2Ygb3BlcmF0aW9ucyByZXF1aXJlcyByZS1lbnRlcmluZyB0aGUgY29kZSBzdHJlYW0uIFRvIGdpdmUgeW91cnNlbGYgbW9yZSByb29tIHRvIHdvcmssIGl04oCZcyBhIGdyZWF0IGlkZWEgdG8gdXNlIHRoZSBSIHNjcmlwdCBlZGl0b3IuCgpBIHNjcmlwdCBpcyBzaW1wbHkgYSB0ZXh0IGZpbGUgY29udGFpbmluZyBhIHNldCBvZiBjb21tYW5kcyBhbmQgY29tbWVudHMuIFRoZSBzY3JpcHQgY2FuIGJlIHNhdmVkIGFuZCB1c2VkIGxhdGVyIHRvIHJlLWV4ZWN1dGUgdGhlIHNhdmVkIGNvbW1hbmRzLiBUaGUgc2NyaXB0IGNhbiBhbHNvIGJlIGVkaXRlZCBzbyB5b3UgY2FuIGV4ZWN1dGUgYSBtb2RpZmllZCB2ZXJzaW9uIG9mIHRoZSBjb21tYW5kcy4KCllvdSBjYW4gb3BlbiBhIG5ldyBlbXB0eSBzY3JpcHQgYnkgY2xpY2tpbmcgdGhlIE5ldyBGaWxlIGljb24gaW4gdGhlIHVwcGVyIGxlZnQgb2YgdGhlIG1haW4gUlN0dWRpbyB0b29sYmFyLiBUaGlzIGljb24gbG9va3MgbGlrZSBhIHdoaXRlIHNxdWFyZSB3aXRoIGEgd2hpdGUgcGx1cyBzaWduIGluIGEgZ3JlZW4gY2lyY2xlLiBDbGlja2luZyB0aGUgaWNvbiBvcGVucyB0aGUgTmV3IEZpbGUgTWVudS4gQ2xpY2sgdGhlIOKAnFIgU2NyaXB04oCdIG9wdGlvbiBhbmQgdGhlIHNjcmlwdCBlZGl0b3Igd2lsbCBvcGVuIHdpdGggYW4gZW1wdHkgc2NyaXB0LiBZb3VyIFIgU3R1ZGlvIHNob3VsZCBsb29rIHNpbWlsYXIgdG8gYmVsb3cgKGltYWdlIHNvdXJjZTogW1IgZm9yIERhdGEgU2NpZW5jZV0oaHR0cHM6Ly9yNGRzLmhhZC5jby5uei93b3JrZmxvdy1zY3JpcHRzLmh0bWwpKQoKIVtSU3R1ZGlvXShyc3R1ZGlvZWRpdG9yLnBuZykKClwKClIgU2NyaXB0cyBhcmUgYmFzaWNhbGx5IHRleHQgZmlsZXMgd2l0aCBhIC5SIGV4dGVuc2lvbiB0aGF0IGhvdXNlcyB5b3VyIGNvZGUgYW5kIGNvbW1lbnRzLiBZb3Ugd3JpdGUgeW91ciBjb2RlLiBFeGVjdXRlIHRoYXQgY29kZSBmcm9tIHlvdXIgUiBzY3JpcHQuIFJlc3VsdHMgYXJlIHByb2R1Y2VkIGluIHlvdXIgUiBjb25zb2xlIHdpbmRvdy4gSW4gdGhpcyBjbGFzcywgd2Ugd29u4oCZdCBiZSB1c2luZyByZWd1bGFyIFIgU2NyaXB0cyBmb3IgaG9tZXdvcmsgYXNzaWdubWVudHMuIEluc3RlYWQsIHdl4oCZbGwgYmUgdXNpbmcgW1IgTWFya2Rvd25dKGh0dHBzOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tLykuCgpSIE1hcmtkb3duIGRvY3VtZW50cyB0YWtlIHNjcmlwdCBmaWxlcyB0byBhIG5ldyBsZXZlbCBieSBhbGxvd2luZyB5b3UgdG8gbWl4IFIgY29tbWFuZHMgd2l0aCBleHBsYW5hdG9yeSB0ZXh0LiBUaGluayBvZiBhbiBSIE1hcmtkb3duIGRvY3VtZW50IGFzIGFuIFIgc2NyaXB0IG9uIHN0ZXJvaWRzLiBZb3VyIFIgTWFya2Rvd24gc291cmNlIGRvY3VtZW50IGlzIGNvbXBpbGVkIGludG8gYW4gb3V0cHV0IHJlcG9ydCBldmFsdWF0aW5nIHRoZSBSIGNvbW1hbmRzIGluIHRoZSBzb3VyY2UgZG9jdW1lbnQgdG8gcHJvZHVjZSBlYXNpbHkgcmVwcm9kdWNpYmxlIHJlc3VsdHMgaW4gYW4gYWVzdGhldGljYWxseSBwbGVhc2luZyBmb3JtLiBJdCBjb21iaW5lcyBjb2RlLCByZXN1bHRzIGZyb20gdGhlIGNvZGUsIGFuZCBuYXJyYXRpdmUgdGV4dCBleHBsYWluaW5nIHRoZSByZXN1bHRzIHRvIHByb2R1Y2UgYmVhdXRpZnVsIGRvY3VtZW50cyBhbmQgYWNhZGVtaWMgcmVwb3J0cy4KClN0aWxsIG5vdCBjb252aW5jZWQgdGhhdCBSIE1hcmtkb3duIGlzIHVzZWZ1bD8gQ2hlY2sgb3V0IE5pa2hpbCBLYXph4oCZcyB0aG9yb3VnaCBkZXNjcmlwdGlvbiBvZiBbd2h5IHdlIHNob3VsZCB1c2UgUiBNYXJrZG93bl0oaHR0cHM6Ly9ua2F6YS5naXRodWIuaW8vaW50cm8yUmJvb2svd2h5LXVzZS1yLW1hcmtkb3duLmh0bWwpLgoKXAoKIyBSIE1hcmtkb3duCgpSIE1hcmtkb3duIGlzIGEgc2ltcGxlIGZvcm1hdHRpbmcgc3ludGF4IGZvciBhdXRob3JpbmcgaHRtbCwgcGRmLCBhbmQgTWljcm9zb2Z0IFdvcmQgZG9jdW1lbnRzIGluIFJTdHVkaW8uIEZvciBlYWNoIFIgcmVsYXRlZCBhc3NpZ25tZW50LCB5b3Ugd2lsbCB1cGxvYWQgb250byBDYW52YXMgdHdvIGRvY3VtZW50czoKCjEuIEFuIFIgTWFya2Rvd24gZG9jdW1lbnQsIHdoaWNoIGhhcyBhbiAuUm1kIGV4dGVuc2lvbgoxLiBBIGtuaXR0ZWQgYC5odG1sYCwgYC5wZGZgIG9yIGAuZG9jeGAgZmlsZQoKVGhlc2UgZG9jdW1lbnRzIHdpbGwgcHJvdmlkZSB1cyBhbiBlYXN5LXRvLXJlYWQgZG9jdW1lbnQgdG8gZ3JhZGU7IG1vcmUgaW1wb3J0YW50bHksIHlvdSB3aWxsIGdldCB0byBwcmFjdGljZSAoMSkgd3JpdGluZyBzY3JpcHRzLCAoMikga2VlcGluZyB0cmFjayBvZiB0aGUgYW5hbHlzZXMgeW91IHJ1biwgYW5kICgzKSBvcmdhbml6aW5nIHlvdXIgb3V0cHV0IGluIGEgcmVhZGVyLWZyaWVuZGx5IG1hbm5lci4gV2hlbiB5b3Ugc3VibWl0IHRoZXNlIGRvY3VtZW50cyBvbiBDYW52YXMsICoqZG8gbm90IGNvbWJpbmUgdGhlbSBpbnRvIGEgemlwcGVkIGNvbXByZXNzZWQgZm9sZGVyKiouIFRoZXkgc2hvdWxkIGJlIHR3byBzZXBhcmF0ZSBmaWxlcy4KClRvIGJlIGNsZWFyLCBSIGlzIGEgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UuIFJTdHVkaW8gaXMgYW4gYXBwbGljYXRpb24uIFIgTWFya2Rvd24gaXMgYSBtYXJrdXAgc3ludGF4IHRvIGNvbnZlcnQgUiBzY3JpcHQgYW5kIHRleHQgaW50byBhIHBkZiBvciBodG1sIGRvY3VtZW50LiBJdCBhbGxvd3MgZm9yIHByZXNlbnRhdGlvbi1yZWFkeSBkb2N1bWVudHMgdGhhdCBzaG93IGNvbW1hbmRzIGFuZCByZXN1bHRzIGluIGEgc2VhbWxlc3MgZmxvdy4gV2hlbiB5b3Ugd3JpdGUgUiBjb2RlIGFuZCBlbWJlZCBpdCBpbiBwcmVzZW50YXRpb24gZG9jdW1lbnRzIGNyZWF0ZWQgdXNpbmcgUiBNYXJrZG93biwgeW91IGFyZSBmb3JjZWQgdG8gZXhwbGljaXRseSBzdGF0ZSB0aGUgc3RlcHMgeW91IHRvb2sgdG8gZG8geW91ciByZXNlYXJjaC4KCkluIFJTdHVkaW8sIGluc3RhbGwgdGhlIHBhY2thZ2VzICoqa25pdHIqKiBhbmQgKipybWFya2Rvd24qKiB1c2luZyB0aGUgYGluc3RhbGwucGFja2FnZXMoKWAgY29tbWFuZC4gVHlwZSB0aGUgZm9sbG93aW5nIGluIHlvdXIgUkNvbnNvbGUgd2luZG93IGFmdGVyIGA+YAoKYGBge3IgaW5zdGFsbHBhY2thZ2VzfQppbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpCmluc3RhbGwucGFja2FnZXMoInJtYXJrZG93biIpCmBgYAoKXAoKT25jZSB5b3XigJl2ZSBpbnN0YWxsZWQgdGhlc2UgcGFja2FnZXMsIHlvdSBkb27igJl0IG5lZWQgdG8gaW5zdGFsbCB0aGVtIGFueSBtb3JlIGluIHRoZSBmdXR1cmUuIFlvdSBhbHNvIGRvIG5vdCBuZWVkIHRvIGxvYWQgdGhlbSBpbiBhdCBhbnkgdGltZSB1c2luZyBgbGlicmFyeSgpYC4KClwKCiMgQ3JlYXRpbmcgYW5kIHNhdmluZyBhbiBSIE1hcmtkb3duCgpUbyBjcmVhdGUgYSBuZXcgYC5SbWRgIGZpbGUgaW4gUlN0dWRpbywgc2VsZWN0IEZpbGUgLT4gTmV3IEZpbGUgLT4gUiBNYXJrZG93bi4gQSB3aW5kb3cgc2hvdWxkIHBvcCB1cC4gVHlwZSBpbiDigJxBc3NpZ25tZW50IDHigJ0gbmV4dCB0byAqVGl0bGUqIGFuZCB5b3VyIG5hbWUgbmV4dCB0byAqQXV0aG9yKi4gTGVhdmUgZXZlcnl0aGluZyBlbHNlIGFsb25lIGFuZCBjbGljayBPSy4gQSBuZXcgd2luZG93IGluIHRoZSB0b3AgbGVmdCBvZiB5b3VyIFJTdHVkaW8gY29uc29sZSBzaG91bGQgcG9wIHVwIGNvbnRhaW5pbmcgeW91ciBuZXcgUiBNYXJrZG93biBmaWxlLgoKIVtSU3R1ZGlvIEludGVyZmFjZV0ocnN0dWRpb2ludGVyZmFjZS5wbmcpCgpcCgpJZiB5b3UgYXJlIHVzaW5nIHlvdXIgcGVyc29uYWwgY29tcHV0ZXIgZm9yIHRoaXMgZ3VpZGUsIGl04oCZcyBiZXN0IHRvIHNldCB1cCBhIGNsZWFuIGFuZCBlZmZpY2llbnQgZmlsZSBtYW5hZ2VtZW50IHN0cnVjdHVyZS4gRmlsZSBtYW5hZ2VtZW50IGlzIGtleSB0byBwcmV2ZW50aW5nIFIgcHJvZ3JhbW1pbmcgZnJ1c3RyYXRpb24uIEhlcmUgYXJlIHNvbWUgdGlwcy4KCi1TZXQgdXAgYSBjbGVhciBhbmQgdW5kZXJzdGFuZGFibGUgaGllcmFyY2hpY2FsIGZpbGUgc3lzdGVtIGZvciB0aGlzIGNsYXNzIG9uIHlvdXIgaGFyZCBkcml2ZS4gRm9yIGV4YW1wbGUsIGNyZWF0ZSBhIGNsYXNzIGZvbGRlciAoU1BIIDIxNSkuIFdpdGhpbiB0aGlzIGNsYXNzIGZvbGRlciwgY3JlYXRlIHRoZSBmb2xkZXIgQXNzaWdubWVudHMuIFdpdGhpbiB0aGUgQXNzaWdubWVudHMgZm9sZGVyLCBjcmVhdGUgc2VwYXJhdGUgZm9sZGVycyBmb3IgZWFjaCBBc3NpZ25tZW50IChlLmcuIEFzc2lnbm1lbnQgMSwgQXNzaWdubWVudCAyLCDigKYpLiBEb27igJl0IHdvcmsgZnJvbSB5b3VyIERlc2t0b3AuIE9yIGZyb20gdGhlIERvd25sb2FkcyBmb2xkZXIuIE9yIHNvbWUgcmFuZG9tbHkgbmFtZWQgZm9sZGVyIHRoYXQgeW91IHdpbGwgaGF2ZSBhIGhhcmQgdGltZSBmaW5kaW5nIGEgbW9udGgsIHdlZWsgb3IgZGF5IGZyb20gbm93LiAKLUtlZXAgYWxsIHlvdXIgZmlsZXMgdGhhdCBhcmUgcmVsYXRlZCB0byBhIGxhYiBvciBhc3NpZ25tZW50IGluIG9uZSBmb2xkZXIuIFRoYXQgaXMsIGRvbuKAmXQgaGF2ZSBhbiBBc3NpZ25tZW50IDMgZm9sZGVyIHRoYXQgY29udGFpbnMgZGF0YSBmaWxlcyBzcGVjaWZpYyB0byBBc3NpZ25tZW50IDEuIEtlZXAgZXZlcnl0aGluZyBpbiBvbmUgZm9sZGVyLCBpbmNsdWRpbmcgdGhlIFIgTWFya2Rvd24gZm9yIHRoYXQgYXNzaWdubWVudCBvciBsYWIuCgpVc2luZyB0aGUgYmFzaWMgZ3VpZGVsaW5lcyBhYm92ZSwgc2F2ZSB5b3VyIFIgTWFya2Rvd24gZmlsZSBpbnRvIGFuIGFwcHJvcHJpYXRlIGZvbGRlciBvbiB5b3VyIGhhcmQgZHJpdmUgYnkgY2xpY2tpbmcgb24gRmlsZSBhbmQgdGhlbiBTYXZlIGZyb20gdGhlIFJTdHVkaW8gbWVudS4KClRvIG9wZW4gYW4gYC5SbWRgIGZpbGUgaW4gUlN0dWRpbywgc2VsZWN0IEZpbGUgLT4gT3BlbiBGaWxlIGFuZCBuYXZpZ2F0ZSB0byB0aGUgZm9sZGVyIHlvdSBzYXZlZCB0aGUgYXNzaWdubWVudCB0ZW1wbGF0ZSBpbiBhbmQgc2VsZWN0IHRoZSBmaWxlLiBZb3Ugc2hvdWxkIHNlZSB0aGUgUiBNYXJrZG93biBmaWxlIHBvcCB1cCBvbiB0aGUgdG9wIGxlZnQgcG9ydGlvbiBvZiB5b3VyIFJTdHVkaW8gaW50ZXJmYWNlCgpcCgojIEF1dGhvcmluZyBhbiBSIE1hcmtkb3duIGRvY3VtZW50CgpSIE1hcmtkb3duIGRvY3VtZW50cyBjb250YWluIDMgbWFqb3IgY29tcG9uZW50czoKCjEuIEEgWUFNTCBoZWFkZXIgc3Vycm91bmRlZCBieSAtIC0gLQoxLiBDaHVua3Mgb2YgUiBjb2RlIHN1cnJvdW5kZWQgYnkgYGBgCjEuIFRleHQgbWl4ZWQgd2l0aCBzaW1wbGUgdGV4dCBmb3JtYXR0aW5nIHVzaW5nIHRoZSBNYXJrZG93biBzeW50YXgKClwKCiMjIFlBTUwgaGVhZGVyCgpUaGUgWUFNTCBoZWFkZXIgY29udHJvbHMgaG93IFIgTWFya2Rvd24gcmVuZGVycyB5b3VyIGAuUm1kYCBmaWxlLiBBIFlBTUwgaGVhZGVyIGlzIGEgc2VjdGlvbiBvZiBrZXk6dmFsdWUgcGFpcnMgc3Vycm91bmRlZCBieSAtIC0gLSBtYXJrcyBhbmQgaXMgYWx3YXlzIGxvY2F0ZWQgYXQgdGhlIHRvcCBvZiB5b3VyIFJtZCBmaWxlLgoKSW4gdGhlIGFzc2lnbm1lbnTigJlzIFlBTUwsIGFkZCB5b3VyIG5hbWUsIGFzc2lnbm1lbnQgbnVtYmVyLCBhbmQgdGhlIGRhdGUuIFRoZXNlIGFyZSB0aGUgb25seSBuZWNlc3NhcnkgaXRlbXMsIGJ1dCB5b3UgY2FuIGNoYW5nZSBvdGhlciBvcHRpb25zLCBtb3N0IG9mIHdoaWNoIGFyZSBkZXRhaWxlZCBbaGVyZV0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duL2h0bWwtZG9jdW1lbnQuaHRtbCkuIFlvdXIgWUFNTCB3aWxsIGdlbmVyYWxseSBsb29rIGxpa2UgdGhlIGZvbGxvd2luZy4KCmBgYHt5YW1sfQotLS0KdGl0bGU6ICJBc3NpZ25tZW50IFtpbnNlcnQgbnVtYmVyIGhlcmVdIgpzdWJ0aXRsZTogU1BIIDIxNQphdXRob3I6IFlvdXIgZnVsbCBuYW1lIGhlcmUKZGF0ZTogQXNzaWdubWVudCBkdWUgZGF0ZQpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogY29zbW8KLS0tCgpgYGAKClwKCiMjIFIgQ29kZSBDaHVua3MKCldoZW4gYW5zd2VyaW5nIGFuIGFzc2lnbm1lbnQgcXVlc3Rpb24sIHlvdeKAmWxsIGhhdmUgdGhlIGZvbGxvd2luZyBzZXF1ZW5jZSBvZiBjb21wb25lbnRzIGluIHlvdXIgUiBNYXJrZG93biBkb2N1bWVudDogUXVlc3Rpb24sIFIgY29kZSBhbnN3ZXJpbmcgdGhlIHF1ZXN0aW9uLCBjb21tZW50IGRlc2NyaWJpbmcgd2hhdCB0aGUgY29kZSBpcyBkb2luZywgYW5kIHlvdXIgdGV4dCB0byBleHBsYWluIHRoZSByZXN1bHRzLiBMZXTigJlzIHNheSB5b3UgaGF2ZSB0aGUgZm9sbG93aW5nIHF1ZXN0aW9uIGluIG9uZSBvZiB5b3VyIGFzc2lnbm1lbnRzLgoKYGBge3ExfQpRdWVzdGlvbiAxCgoxKzEKCjEuIFdoYXQgaXMgdGhlIHJlc3VsdCBvZiB0aGUgb3BlcmF0aW9uIGFib3ZlPwpgYGAKClwKCkFzc2lnbm1lbnRzIHdpbGwgYXNrIHlvdSB0byB3cml0ZSBSIGNvZGUgdG8gYWNjb21wbGlzaCBhIGRhdGEgYW5hbHlzaXMgdGFzay4gWW91IHByZXNlbnQgYW5kIGV4ZWN1dGUgeW91ciBSIGNvZGUgaW5zaWRlIFIgY29kZSBjaHVua3MuIFIgY2h1bmtzIHN0YXJ0IHdpdGggYGBge3J9IGFuZCBlbmQgd2l0aCBgYGAsIGFuZCB5b3UgaW5zZXJ0IHlvdXIgUiBjb2RlIGluIGJldHdlZW4uIFRvIGRlc2lnbmF0ZSBgMSsxYCBhcyBSIGNvZGUsIGl0IHdpbGwgbG9vayBsaWtlIHRoZSBmb2xsb3dpbmcgaW4geW91ciBSIE1hcmtkb3duIGRvY3VtZW50LgoKYGBge3IgcTIsIHJlc3VsdHM9J2FzaXMnLCBlY2hvPUZBTFNFfQpjYXQoImBgYGBtYXJrZG93blxuIiwKICAgICJgYGB7cn1cbiIsCiAgICAiMSsxXG4iLAogICAgImBgYFxuIiwKICAgICJgYGBgIiwgc2VwID0gIiIpCmBgYAoKXAoKQWxsIGNvZGUgaW5zaWRlIGEgY2h1bmsgd2lsbCBiZSBleGVjdXRlZCB3aGVuIGtuaXR0aW5nIHRoZSBtYXJrZG93biBmaWxlIChpLmUuIHRoZSBodG1sIGZpbGUgd2lsbCBzaG93IHlvdXIgY29kZSBhbmQgaXRzIHJlc3VsdCkuIFRoaXMgbWVhbnMgdGhhdCB5b3VyIFIgY29kZSBtdXN0IHJlc2lkZSBpbnNpZGUgYW4gUiBjb2RlIGNodW5rIGluIG9yZGVyIGZvciBpdCB0byBiZSBwcm9jZXNzZWQgYXMgUiBjb2RlIChvdGhlcndpc2UgUiBNYXJrZG93biB3aWxsIHRoaW5rIGl0IGlzIHRleHQpLiBUaGlzIGFsc28gbWVhbnMgdGhhdCBub3RoaW5nIGJ1dCBleGVjdXRhYmxlIGNvZGUgKG9yIGNvbW1lbnRzLCB3aGljaCB3ZeKAmWxsIGdldCB0byBuZXh0KSBzaG91bGQgYmUgaW5zaWRlIGEgY2h1bmsuCgpXZSB3aWxsIGFzayB5b3UgdG8gYW5ub3RhdGUgeW91ciBSIGNvZGUgc28gdGhhdCB3ZSAoYW5kIHlvdSkga25vdyB3aGF0IGlzIGJlaW5nIGRvbmUgaW4gdGhhdCBsaW5lIG9mIGNvZGUuIFlvdSBkZXNpZ25hdGUgYW5ub3RhdGlvbnMgb3IgY29tbWVudHMgaW4gUiBjb2RlIHVzaW5nIHRoZSBgI2Agc3ltYm9sLiBJbiBwcm9ncmFtbWluZywgY29tbWVudHMgYXJlIGJpdHMgb2YgdGV4dCB0aGF0IGFyZSBub3QgaW50ZXJwcmV0ZWQgYXMgY29tcHV0ZXIgaW5zdHJ1Y3Rpb25z4oCUdGhleSBhcmVu4oCZdCBjb2RlLCB0aGV54oCZcmUganVzdCBub3RlcyBhYm91dCB0aGUgY29kZSEgU2luY2UgY29tcHV0ZXIgY29kZSBjYW4gYmUgb3BhcXVlIGFuZCBkaWZmaWN1bHQgdG8gdW5kZXJzdGFuZCwgd2UgdXNlIGNvbW1lbnRzIHRvIGhlbHAgd3JpdGUgZG93biB0aGUgbWVhbmluZyBhbmQgcHVycG9zZSBvZiBvdXIgY29kZS4gV2hpbGUgYSBjb21wdXRlciBpcyBhYmxlIHRvIHVuZGVyc3RhbmQgdGhlIGNvZGUsIGNvbW1lbnRzIGFyZSB0aGVyZSB0byBoZWxwIHBlb3BsZSB1bmRlcnN0YW5kIGl0LiBUaGlzIGlzIHBhcnRpY3VsYXJseSBpbXBvcnRhbnQgd2hlbiBzb21lb25lIGVsc2Ugd2lsbCBiZSBsb29raW5nIGF0IHlvdXIgd29ya+KAlHdoZXRoZXIgdGhhdCBwZXJzb24gaXMgYSBjb2xsYWJvcmF0b3IsIG9yIGlzIHNpbXBseSBhIGZ1dHVyZSB2ZXJzaW9uIG9mIHlvdSAoZS5nLiwgd2hlbiB5b3UgbmVlZCB0byBjb21lIGJhY2sgYW5kIGZpeCBzb21ldGhpbmcgYW5kIHNvIG5lZWQgdG8gcmVtZW1iZXIgd2hhdCB5b3Ugd2VyZSBldmVuIHRoaW5raW5nKS4KCkNvbW1lbnRzIHNob3VsZCBiZSBjbGVhciwgY29uY2lzZSwgYW5kIGhlbHBmdWzigJR0aGV5IHNob3VsZCBwcm92aWRlIGluZm9ybWF0aW9uIHRoYXQgaXMgbm90IG90aGVyd2lzZSBwcmVzZW50IG9yIOKAnG9idmlvdXPigJ0gaW4gdGhlIGNvZGUgaXRzZWxmLiBTbywgdG8gYW5ub3RhdGUgdGhlIGFib3ZlIGxpbmUgb2YgY29kZSBgMSsxYCwgeW91IGFkZCBpbiB5b3VyIFIgY29kZSBjaHVuazoKCmBgYHtyIHEzLCByZXN1bHRzPSdhc2lzJywgZWNobz1GQUxTRX0KY2F0KCJgYGBgbWFya2Rvd25cbiIsCiAgICAiYGBge3J9XG4iLAogICAgIiN0aGlzIGFkZHMgb25lIHBsdXMgb25lXG4iLAogICAgIjErMVxuIiwKICAgICJgYGBcbiIsCiAgICAiYGBgYCIsIHNlcCA9ICIiKQpgYGAKClwKCllvdSBwdXQgeW91ciBjb21tZW50cyBhZnRlciB0aGUgYCNgLgoKVGhlIGZpcnN0IGxpbmUgb2YgdGhlIGNodW5rIGhhcyBge3J9YCB3aGljaCBiYXNpY2FsbHkgc3RhdGVzIHRoYXQgZXZlcnl0aGluZyBpbnNpZGUgdGhlIGNodW5rIHdpbGwgYmUgaW4gUiBjb2RlLiBOZXh0IHRvIHRoZSBgcmAsIHdlIGNhbiBnaXZlIHRoZSBjaHVuayBhIG5hbWUsIHN1Y2ggYXM6CgpgYGB7ciBxNCwgcmVzdWx0cz0nYXNpcycsIGVjaG89RkFMU0V9CmNhdCgiYGBgYG1hcmtkb3duXG4iLAogICAgImBgYHtyIHExY2h1bmsxfVxuIiwKICAgICIjdGhpcyBhZGRzIG9uZSBwbHVzIG9uZVxuIiwKICAgICIxKzFcbiIsCiAgICAiYGBgXG4iLAogICAgImBgYGAiLCBzZXAgPSAiIikKYGBgCgpcCgpIZXJlLCB3ZSBuYW1lZCB0aGUgY2h1bmsgYHExY2h1bmsxYCB3aGljaCBpbmRpY2F0ZXMgdGhpcyBpcyBxdWVzdGlvbiAxLCBjaHVuayAxLiBZb3UgY2FuIG5hbWUgdGhlIGNodW5rIHdoYXRldmVyIHlvdSBsaWtlIChqaW1ibywgc2FtYW50aGEsIHRvbnkpLiBUaGUgY2h1bmsgbmFtZSBpcyBub3QgcmVxdWlyZWQ7IGhvd2V2ZXIsIGl0IGlzIGdvb2QgcHJhY3RpY2UgdG8gZ2l2ZSBlYWNoIGNodW5rIGEgdW5pcXVlIG5hbWUgKHdl4oCZbGwgc2VlIGl0cyB2YWx1ZSBsYXRlciB3aGVuIHdlIHRhbGsgYWJvdXQga25pdHRpbmcpLgoKSW4gdGhlIFIgTWFya2Rvd24geW91IGNyZWF0ZWQgYW5kIHNhdmVkLCB5b3Ugd2lsbCBub3RpY2UgdGhlIGZvbGxvd2luZyBSIGNvZGUgY2h1bmsgYWZ0ZXIgdGhlIFlBTUwuCmBgYHtyIHE1LCByZXN1bHRzPSdhc2lzJywgZWNobz1GQUxTRX0KY2F0KCJgYGBgbWFya2Rvd25cbiIsCiAgICAiYGBge3J9XG4iLAogICAgImtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSlcbiIsCiAgICAiYGBgXG4iLAogICAgImBgYGAiLCBzZXAgPSAiIikKYGBgCgpcCgpUaGUgYWJvdmUgY29kZSBlc3RhYmxpc2hlcyBnbG9iYWwgb3B0aW9ucyBmb3IgZXZlcnkgUiBjaHVuayBjb2RlIGluIHlvdXIgUiBNYXJrZG93biBmaWxlLiBUaGVzZSBvcHRpb25zIGFsdGVyIHRoZSB3YXkgUiByZXN1bHRzIGFyZSBzcGl0IG91dCBpbiB5b3VyIGZvcm1hdHRlZCBrbml0dGVkIGRvY3VtZW50LiBJIHN1Z2dlc3QgYWRkaW5nIHRoZSBmb2xsb3dpbmcgZ2xvYmFsIG9wdGlvbnMgaW4gZXZlcnkgUiBNYXJrZG93biBhc3NpZ25tZW50IGZpbGUuCgpgYGB7ciBxNiwgcmVzdWx0cz0nYXNpcycsIGVjaG89RkFMU0V9CmNhdCgiYGBgYG1hcmtkb3duXG4iLAogICAgImBgYHtyfVxuIiwKICAgICJrbml0cjo6b3B0c19jaHVuayRzZXQod2FybmluZz1GQUxTRSwgbWVzc2FnZSA9IEZBTFNFKVxuIiwKICAgICJgYGBcbiIsCiAgICAiYGBgYCIsIHNlcCA9ICIiKQpgYGAKClwKClRoZSBhYm92ZSBjb2RlIGhpZGVzIG5vbiBlcnJvciBtZXNzYWdlcyBmb3IgZXZlcnkgc2luZ2xlIFIgY29kZSBjaHVuayBpbiB5b3VyIGZpbGUuIFRoZXNlIG5vbiBlcnJvciBtZXNzYWdlcyBhcmUgdW5uZWNlc3NhcnkgZm9yIHRoZSBwdXJwb3NlcyBvZiB0aGlzIGNsYXNzLiBPdGhlciBjaHVuayBvcHRpb25zIGNhbiBiZSBmb3VuZCBbaGVyZV0oaHR0cHM6Ly9yNGRzLmhhZC5jby5uei9yLW1hcmtkb3duLmh0bWwjY2h1bmstb3B0aW9ucykuIAoKWW91IGNhbiBhbHNvIHNldCBvcHRpb25zIGZvciBpbmRpdmlkdWFsIGNodW5rcy4gVGhlc2UgYXJlIGxvY2FsIG9wdGlvbnMgLSBsb2NhbCB0byB0aGF0IGNodW5rIC0gYW5kIHdvbuKAmXQgYmUgYXBwbGllZCB0byBvdGhlciBjaHVua3MgaW4geW91ciBmaWxlLiBGb3IgZXhhbXBsZSwgeW91IGNhbiBhZGQgdGhlIG9wdGlvbnMgYHdhcm5pbmc9VFJVRWAgYW5kIGBtZXNzYWdlPVRSVUVgIHRvIGFuIGluZGl2aWR1YWwgUiBjb2RlIGNodW5rIGFzIGZvbGxvd3MgdG8gc2hvdyB0aGUgbWVzc2FnZXMgZm9yIHRoZSBSIGNvZGUgaW4gdGhhdCBjaHVuay4gTm90aWNlIHRoYXQgZWFjaCBhcmd1bWVudCBpcyBzZXBhcmF0ZWQgYnkgYSBjb21tYS4KCmBgYHtyIHE3LCByZXN1bHRzPSdhc2lzJywgZWNobz1GQUxTRX0KY2F0KCJgYGBgbWFya2Rvd25cbiIsCiAgICAiYGBge3IgcTFjaHVuazEsIHdhcm5pbmcgPSBUUlVFLCBtZXNzYWdlID0gVFJVRX1cbiIsCiAgICAiMSsxXG4iLAogICAgImBgYFxuIiwKICAgICJgYGBgIiwgc2VwID0gIiIpCmBgYAoKXAoKIyMgVGV4dCAKCkluIGFkZGl0aW9uIHRvIFIgY29kZSwgYXNzaWdubWVudHMgd2lsbCBhc2sgeW91IHRvIHdyaXRlIHRleHQgdG8gZXhwbGFpbiByZXN1bHRzLiBHb2luZyBiYWNrIHRvIG91ciBleGFtcGxlIHF1ZXN0aW9uIGZyb20gYWJvdmU6CmBgYHtxOH0KUXVlc3Rpb24gMQoKMSsxCgoxLiBXaGF0IGlzIHRoZSByZXN1bHQgb2YgdGhlIG9wZXJhdGlvbiBhYm92ZT8KYGBgCgpcCgpZb3Ugd291bGQgdHlwZSBpbiB5b3VyIFIgTWFya2Rvd24gZG9jdW1lbnQgdGhlIGZvbGxvd2luZzoKYGBge3IgcTksIHJlc3VsdHM9J2FzaXMnLCBlY2hvPUZBTFNFfQpjYXQoImBgYGBtYXJrZG93blxuIiwKICAgICJgYGB7ciBxMWNodW5rMSx9XG4iLAogICAgIiN0aGlzIGNvZGUgYWRkcyBvbmUgcGx1cyBvbmVcbiIsCiAgICAiMSsxXG4iLAogICAgImBgYFxuIiwKICAgICJcbiIsCiAgICAiTXkgYW5hbHlzaXMgeWllbGRzIHRoZSBudW1iZXIgMlxuIiwKICAgICJgYGBgIiwgc2VwID0gIiIpCmBgYAoKXAoKVGhlIHF1ZXN0aW9uIGFuZCB0ZXh0IGV4cGxhaW5pbmcgdGhlIHJlc3VsdCByZXNpZGUgb3V0c2lkZSBvZiB0aGUgUiBjaHVuay4gVGhlcmUgaXMgbm90aGluZyBzcGVjaWFsIGFib3V0IHRoZSB0ZXh0IGluIHRlcm1zIG9mIGl0cyBmb3JtYXQgb3IgcGxhY2VtZW50LgoKXAoKIyMgU2VwYXJhdGluZyBjb2RlIG9uZSBjaHVuayBhdCBhIHRpbWUKCkRvIG5vdCBwdXQgYWxsIG9mIHlvdXIgY29kZSBmb3IgYW4gZW50aXJlIGFzc2lnbm1lbnQgb3IgZXZlbiBhIHNpbmdsZSBxdWVzdGlvbiBpbiBvbmUgc2luZ2xlIGNodW5rLiBGb3IgZXhhbXBsZSwgbGV04oCZcyBzYXkgeW91IHNlZSB0aGUgZm9sbG93aW5nIGluIHlvdXIgaG9tZXdvcmsgYXNzaWdubWVudC4KCmBgYHtxMTB9ClF1ZXN0aW9uIDEKCjErMQoKMisyCgpSdW4gZWFjaCBsaW5lIG9mIGNvZGUgYWJvdmUuICBXaGF0IGFyZSB0aGUgcmVzdWx0cz8KYGBgCgpcCgpJbnN0ZWFkIG9mIGluY2x1ZGluZyBib3RoIGxpbmVzIG9mIGNvZGUgaW4gb25lIGNodW5rIGxpa2UgYXMgZm9sbG93cwpgYGB7ciBxMTEsIHJlc3VsdHM9J2FzaXMnLCBlY2hvPUZBTFNFfQpjYXQoImBgYGBtYXJrZG93blxuIiwKICAgICJRdWVzdGlvbiAxXG4iLAogICAgIlxuIiwKICAgICJgYGB7ciBxMWNodW5rMX1cbiIsCiAgICAiI3RoaXMgY29kZSBhZGRzIG9uZSBwbHVzIG9uZVxuIiwKICAgICIxKzFcbiIsCiAgICAiXG4iLAogICAgIiN0aGlzIGNvZGUgYWRkcyB0d28gcGx1cyB0d29cbiIsCiAgICAiMisyXG4iLAogICAgImBgYFxuIiwKICAgICJcbiIsCiAgICAiT25lIHBsdXMgb25lIGVxdWFscyAyLiBUd28gcGx1cyB0d28gZXF1YWxzIDRcbiIsCiAgICAiYGBgYCIsIHNlcCA9ICIiKQpgYGAKClwKCkJyZWFrIGl0IHVwIGFuZCBhZGQgdGV4dCBhZnRlciBlYWNoIHRvIGV4cGxhaW4gdGhlIHJlc3VsdC4KYGBge3IgcTEyLCByZXN1bHRzPSdhc2lzJywgZWNobz1GQUxTRX0KY2F0KCJgYGBgbWFya2Rvd25cbiIsCiAgICAiUXVlc3Rpb24gMVxuIiwKICAgICJcbiIsCiAgICAiYGBge3IgcTFjaHVuazF9XG4iLAogICAgIiN0aGlzIGNvZGUgYWRkcyBvbmUgcGx1cyBvbmVcbiIsCiAgICAiMSsxXG4iLAogICAgImBgYFxuIiwKICAgICJcbiIsCiAgICAiT25lIHBsdXMgb25lIGVxdWFscyAyLlxuIiwKICAgICJcbiIsCiAgICAiYGBge3IgcTFjaHVuazJ9XG4iLAogICAgIiN0aGlzIGNvZGUgYWRkcyB0d28gcGx1cyB0d29cbiIsCiAgICAiMisyXG4iLAogICAgImBgYFxuIiwKICAgICJcbiIsCiAgICAiVHdvIHBsdXMgdHdvIGVxdWFscyA0XG4iLAogICAgImBgYGAiLCBzZXAgPSAiIikKYGBgCgpcCgpUaGluayBvZiB3cml0aW5nIGEgc2NyaXB0IGFzIHNpbWlsYXIgdG8gd3JpdGluZyBhbiBlc3NheS4gWW91IGRvbuKAmXQgd3JpdGUgYW4gZXNzYXkgaW4gb25lIHNpbmdsZSBwYXJhZ3JhcGguIFlvdSBicmVhayBpdCB1cCBpbnRvIHNldmVyYWwgcGFyYWdyYXBocywgd2hlcmUgcGFyYWdyYXBoIGJyZWFrcyBhcmUgdXNlZCB0byBzZXBhcmF0ZSBtYWpvciBwb2ludHMgYW5kIGlkZWFzLiBPbiB0aGUgb3RoZXIgZW5kIG9mIHRoZSBzcGVjdHJ1bSwgZG8gbm90IGJyZWFrIHVwIGV2ZXJ5IHNpbmdsZSBsaW5lIG9mIGNvZGUgbGlrZSB5b3Ugd291bGQgbm90IGJyZWFrIHVwIGV2ZXJ5IHNpbmdsZSBzZW50ZW5jZSBpbnRvIHRoZWlyIG93biBwYXJhZ3JhcGhzIGluIGFuIGVzc2F5LiBCcmVhayB1cCB5b3VyIGNvZGUgd2hlcmUgaXQgbWFrZXMgc2Vuc2UuCgpcCgojIyBBbHdheXMgdGVzdCBlYWNoIGNodW5rCkFmdGVyIHlvdSB3cml0ZSBjb2RlIGluIGEgY2h1bmssIHlvdeKAmWxsIG5lZWQgdG8gdGVzdCB0aGUgY29kZSB0byBtYWtlIHN1cmUgaXQgaXMgcnVubmluZyBwcm9wZXJseS4gSW4gb3RoZXIgd29yZHMsIHJhdGhlciB0aGFuIHdyaXRpbmcgYWxsIHRoZSBjb2RlIGFuZCB0aGVuIHJ1bm5pbmcgaXQgYXQgdGhlIGVuZCBvZiB0aGUgYXNzaWdubWVudCwgcnVuIHRoZSBjaHVua3Mgb25lIGF0IGEgdGltZS4gVG8gZWxhYm9yYXRlLCBsZXTigJlzIHNheSB0aGUgZmlyc3QgcXVlc3Rpb24gaW4gYW4gYXNzaWdubWVudCBhc2tzIHlvdSB0byBhZGQgb25lIHBsdXMgb25lLiBJbiB5b3VyIFIgTWFya2Rvd24gZG9jdW1lbnQsIHR5cGUgaW4gdGhlIGZvbGxvd2luZyB0byBhbnN3ZXIgdGhpcyBxdWVzdGlvbi4KCmBgYHtyIHExMywgcmVzdWx0cz0nYXNpcycsIGVjaG89RkFMU0V9CmNhdCgiYGBgYG1hcmtkb3duXG4iLAogICAgImBgYHtyIHExY2h1bmsxLH1cbiIsCiAgICAiI3RoaXMgY29kZSBhZGRzIG9uZSBwbHVzIG9uZVxuIiwKICAgICIxKzFcbiIsCiAgICAiYGBgXG4iLAogICAgIlxuIiwKICAgICJPbmUgcGx1cyBvbmUgZXF1YWxzIDJcbiIsCiAgICAiYGBgYCIsIHNlcCA9ICIiKQpgYGAKClwKClJ1biB0aGF0IGNvZGUgY2h1bmsgdG8gbWFrZSBzdXJlIGl0IHdvcmtzICh5b3Ugc2hvdWxkIGdldCAyISkuICpUaGVuKiBwcm9jZWVkIHRvIHRoZSBuZXh0IHF1ZXN0aW9uLiBMZXQgbWUgZW1waGFzaXplOiAqKkRvIG5vdCB3cml0ZSBhbGwgb2YgeW91ciBjb2RlIGFuc3dlcmluZyBldmVyeSBxdWVzdGlvbiBpbiB0aGUgYXNzaWdubWVudCBhbmQgcnVuIGl0IGF0IHRoZSB2ZXJ5IGVuZC4qKiBSb3V0aW5lbHkgVEVTVCwgVGVzdCwgYW5kIHRlc3QgeW91ciBjb2RlIHRvIG1ha2Ugc3VyZSBpdCBydW5zIHByb3Blcmx5LgoKVGhlcmUgYXJlIGEgbnVtYmVyIG9mIHdheXMgdG8gcnVuIGNvZGUgaW4gUiBNYXJrZG93bi4gRmlyc3QsIHlvdSBjYW4gY2xpY2sgeW91ciBtb3VzZSBpbiB0aGUgUiBjb2RlIGNodW5rIHlvdSB3YW50IHRvIHJ1biBhbmQgY2xpY2sgb24gIVtydW5dKHJ1bi5wbmcpIGxvY2F0ZWQgYXQgdGhlIHRvcCBvZiB0aGUgUiBNYXJrZG93biB3aW5kb3cgYW5kIHNlbGVjdCAqUnVuIEN1cnJlbnQgQ2h1bmsuKgoKU2Vjb25kLCB5b3UgY2FuIHBsYWNlIHlvdXIgbW91c2UgY3Vyc29yIGluIHRoZSBSIGNvZGUgY2h1bmsgYW5kIGNsaWNrIG9uICFbcnVuYnV0dG9uXShydW5idXR0b24ucG5nKSBsb2NhdGVkIG9uIHRoZSByaWdodCBjb3JuZXIgb2YgdGhlIGNodW5rLiBTZWUgRmlndXJlIGJlbG93LgoKIVtSdW5uaW5nIENodW5rc10oY2h1bmsyLnBuZykKClwKCkluIGVhY2ggUiBjaHVuaywgcHJlc3NpbmcgdGhlIGJ1dHRvbiAhW3JjaHVua2J1dHRvbl0ocmNodW5rYnV0dG9uLnBuZykgd2lsbCBydW4gYWxsIHByZXZpb3VzIFIgY2h1bmtzLiBTZWUgRmlndXJlIGJlbG93LgohW1J1bm5pbmcgUHJlY2VkaW5nIENodW5rc10oY2h1bms0LnBuZykKClwKClRoaXJkLCB5b3UgY2FuIGhpZ2hsaWdodCBwYXJ0bHkgb3IgZW50aXJlbHkgYSBsaW5lIG9mIGNvZGUgYW5kIHNlbGVjdCAqQ29kZSogZnJvbSB0aGUgUiBTdHVkaW8gbWVudSBhbmQgc2VsZWN0IChhbW9uZyBtYW55IG9wdGlvbnMpICpSdW4gU2VsZWN0ZWQgTGluZXMocykqLiAqKlRoaXMgY2FuIGFsc28gYmUgYWNjb21wbGlzaGVkIGJ5IGhpZ2hsaWdodGluZyBsaW5lcyBvZiBjb2RlIGFuZCBwcmVzc2luZyBDb21tYW5kK1JldHVybiBvbiBhIE1hYyBhbmQgQ3RybCtFbnRlciBvbiBhIFBDLioqCgpOb3RlIHRoYXQgd2hlbiB5b3UgcnVuIGFuIFIgY29kZSBjaHVuayBmb3IgdGhlIHZlcnkgZmlyc3QgdGltZSBldmVyLCBpdHMgb3V0cHV0IHdpbGwgYmUgZW1iZWRkZWQgd2l0aGluIHlvdXIgUiBNYXJrZG93biBkb2N1bWVudCBhcyBzaG93biBiZWxvdwoKXAoKIVtPdXRwdXQgd2l0aGluIFIgTWFya2Rvd24gRG9jdW1lbnRdKHJvdXRwdXQuanBlZykgCgpcCgpUaGlzIHdpbGwgYWxzbyBiZSB0cnVlIHdoZW4geW91IHBsb3QgZ3JhcGhzIGFuZCBtYXBzLiBXaGVuIHlvdSBhcmUgdGVzdGluZyB5b3VyIGNvZGUsIHlvdSBtaWdodCB3YW50IHRvIGhhdmUgdGhlIGNvZGUgcmVzdWx0cyBzaG93biBpbiB5b3VyIFJTdHVkaW8gQ29uc29sZSAodGhlIGJvdHRvbSBsZWZ0IHdpbmRvdykgYW5kIHBsb3RzL21hcHMgc2hvd24gaW4gdGhlIFBsb3RzIHdpbmRvdyAoYm90dG9tIHJpZ2h0IHdpbmRvdykuIFRvIGdldCBSU3R1ZGlvIHRvIGRvIHRoaXMsIHNlbGVjdCB0aGUg4oCcVG9vbHPigJ0gbWVudSBhbmQgc2VsZWN0IOKAnEdsb2JhbCBPcHRpb25z4oCdLiBTZWxlY3Qg4oCcUiBNYXJrZG93buKAnSBmcm9tIHRoZSBsZWZ0LWhhbmQgc2lkZSBhbmQgZGVzZWxlY3QgdGhlIGNoZWNrIGJveCDigJxTaG93IG91dHB1dCBpbmxpbmUgZm9yIGFsbCBSIE1hcmtkb3duIGRvY3VtZW50c+KAnS4gVGhlIG91dHB1dCBmcm9tIHlvdXIgY29kZSBzaG91bGQgbm93IGJlIHNob3duIGluIHRoZSBjb25zb2xlIG9yIFBsb3RzIHdpbmRvdy4KClwKCiFbUiBNYXJrZG93biBPcHRpb25zXShSbWFya2Rvd25vcHRpb25zLmpwZWcpIAoKXAoKIyBLbml0dGluZyBhbiBSIE1hcmtkb3duIGRvY3VtZW50CgoKSW4gYWRkaXRpb24gdG8gdGhlIFIgTWFya2Rvd24gUm1kIGZpbGUsIHlvdSB3aWxsIG5lZWQgdG8gc3VibWl0IGl0cyAqKmtuaXR0ZWQqKiByZXN1bHQuIEtuaXR0aW5nIHB1dHMgYW4gYXNzaWdubWVudOKAmXMgbWFpbiBjb21wb25lbnRzIC0gY29kZSwgb3V0cHV0LCBhbmQgdGV4dCAtIGluIGEgbmljZWx5IGZvcm1hdHRlZCBkb2N1bWVudC4gWW91IGNhbiBjcmVhdGUgdGhyZWUgdHlwZXMgb2Yga25pdHRlZCBkb2N1bWVudHM6IGh0bWwsIE1pY3Jvc29mdCBXb3JkLCBhbmQgYSBwZGYuIEkgcmVjb21tZW5kIGtuaXR0aW5nIHRvIGFuIGh0bWwgZmlsZSBiZWNhdXNlIGl0IGlzIHRoZSBlYXNpZXN0IG9mIHRoZSB0aHJlZSBvcHRpb25zLiBHbyBiYWNrIHRvIHRoZSBZQU1MIGV4YW1wbGUgSSBzaG93ZWQgYWJvdmUuICpvdXRwdXQ6IGh0bWxfZG9jdW1lbnQqIHRlbGxzIFIgdG8gcHJvZHVjZSBhbiBodG1sIGRvY3VtZW50LiBJZiB5b3Ugd2FudCB0byBrbml0IHRvIGEgcGRmLCB5b3XigJlsbCBuZWVkIHRvIGRvIHNvbWUgZXh0cmEgcGFja2FnZSBpbnN0YWxsaW5nLiBTZWUgW2hlcmVdKGh0dHBzOi8vYm9va2Rvd24ub3JnL3lpaHVpL3JtYXJrZG93bi9pbnN0YWxsYXRpb24uaHRtbCkuCmtuaQpUbyBLbml0IHlvdXIgZG9jdW1lbnQgY2xpY2sgIVtrbml0YnV0dG9uXShrbml0YnV0dG9uLnBuZyksIHdoaWNoIHdpbGwgYmUgbG9jYXRlZCBhdCB0aGUgdG9wIG9mIHRoZSB1cHBlciBsZWZ0IFIgTWFya2Rvd24gd2luZG93LiBOb3RlIHRoYXQgeW91IGNhbiBzZWxlY3QgeW91ciBkb2N1bWVudCB0eXBlIHdoZW4ga25pdHRpbmcgYnkgY2xpY2tpbmcgdGhlIHB1bGwgZG93biBtZW51IG5leHQgdG8gIVtrbml0YnV0dG9uXShrbml0YnV0dG9uLnBuZykgYW5kIHNlbGVjdGluZyB5b3VyIGRvY3VtZW50IGNob2ljZSAoZGVmYXVsdCBpcyBodG1sKS4KClwKCiFbQ2xpY2sgdG8gS25pdF0oY2xpY2t0b2tuaXQucG5nKSAKClwKCldoZW4geW91IHN0YXJ0IGtuaXR0aW5nLCB5b3Ugd2lsbCBub3RpY2UgdGhhdCBhIG5ldyB3aW5kb3cgb24gdGhlIGJvdHRvbSBsZWZ0IHdpbGwgYXBwZWFyIGluIHBsYWNlIG9mIHRoZSBjb25zb2xlLiBUaGUgd2luZG93IHdpbGwgc2hvdyB0aGUgcHJvZ3Jlc3MgaW4geW91ciBrbml0dGluZy4gUiBpcyBnb2luZyB0aHJvdWdoIGVhY2ggUiBjb2RlIGNodW5rIG9uZSBhdCBhIHRpbWUuIFRoZSBwZXJjZW50YWdlcyB5b3Ugd2lsbCBzZWUgd2lsbCBiZSBiYXNlZCBvbiB0aGUgcHJvcG9ydGlvbiBvZiB5b3VyIFIgTWFya2Rvd24gZmlsZSB0aGF0IFIgaGFzIHN1Y2Nlc3NmdWxseSBrbml0dGVkLiBTZWUgRmlndXJlIGJlbG93LgoKIVtLbml0dGluZyBQcm9ncmVzcyBXaW5kb3ddKGtuaXRwcm9nLnBuZykgCgpcCgpJZiBpdCBoYXMgYSBwcm9ibGVtIGtuaXR0aW5nLCBSIHdpbGwgc3RvcCBhdCB0aGUgY2h1bmsgdGhhdCBjb250YWlucyB0aGUgcHJvYmxlbS4gWW91IGNhbiBkZXRlcm1pbmUgdGhlIG9mZmVuZGluZyBwbGFjZSBpbiB5b3VyIFIgTWFya2Rvd24gZmlsZSB0d28gd2F5cy4gRmlyc3QsIGluIHRoZSBSIE1hcmtkb3duIHRhYiBpbiB0aGUgYm90dG9tIGxlZnQgd2luZG93LCBpZiB5b3UgY2xpY2sgb24g4oCcT3V0cHV04oCdIGxvY2F0ZWQgYXQgdGhlIHRvcCByaWdodCBjb3JuZXIgb2YgdGhpcyB3aW5kb3csIHlvdSB3aWxsIHNlZSB0aGUgUiBNYXJrZG93biBwcm9ncmVzcyB3aW5kb3csIHRoZSBlcnJvciBpbiByZWQsIGFuZCB3aGVyZSBSIE1hcmtkb3duIHN0b3BwZWQuIENhcmVmdWxseSByZWFkIHRoZSBkZXNjcmlwdGlvbiBvZiB0aGUgZXJyb3IsIHdoaWNoIHdpbGwgY29udGFpbiB0aGUgUiBjb2RlIGNodW5rIG5hbWUgYW5kIHNvbWV0aW1lcyB0aGUgbGluZXMgY29udGFpbmluZyB0aGUgcHJvYmxlbSBpbiB5b3VyIFIgTWFya2Rvd24gZmlsZS4gVGhpcyBpcyB3aGVyZSBpdCBpcyB1c2VmdWwgZm9yIG5hbWluZyB5b3VyIGNodW5rcy4gWW91IGNhbiBnbyB0byB5b3VyIG9mZmVuZGluZyBjaHVuayBhbmQgc2VlIHdoYXQgbWF5IGJlIHRoZSBwcm9ibGVtLiBGb3IgZXhhbXBsZSwgdGhlIGZpZ3VyZSBiZWxvdyBzaG93cyBrbml0dGluZyB3YXMgc3RvcHBlZCBiZWNhdXNlIHRoZSBvYmplY3QgYHh5emAgd2FzIG5vdCBjcmVhdGVkIGluIHRoZSBSIE1hcmtkb3duIGZpbGUuIFlvdSBjYW4gZ28gdG8gdGhlIGNodW5rIG5hbWVkIGBxMmNodW5rMmAgdG8gcmVtZWR5IHRoZSBpc3N1ZS4KCiFbS25pdHRpbmcgU3RvcHBlZCBieSBhbiBFcnJvcl0oa25pdGVycm9yLnBuZykgCgpcCgpUaGUgb3RoZXIgd2F5IHRvIGZpbmQgd2hlcmUgUiBNYXJrZG93biBpcyBoYXZpbmcgdHJvdWJsZSBpcyBieSBjbGlja2luZyBvbiAqSXNzdWVzKiBhbHNvIGxvY2F0ZWQgYXQgdGhlIHRvcCByaWdodCBjb3JuZXIgb2YgdGhlIFIgTWFya2Rvd24gd2luZG93LiBUaGUgZXJyb3Igd2lsbCBnaXZlIHlvdSBzb21ldGhpbmcgc2ltaWxhciB0byB3aGF0IHlvdSBmb3VuZCBpbiB0aGUgT3V0cHV0IHdpbmRvdywgYnV0IGluc3RlYWQgb2YgYSBjaHVuaywgaXQgd2lsbCB0ZWxsIHlvdSB0aGUgc3BlY2lmaWMgbGluZSBpbiB5b3VyIFIgTWFya2Rvd24gZmlsZSB0aGF0IHRoaXMgZXJyb3IgaXMgbG9jYXRlZC4gR28gdG8gdGhhdCBsaW5lIGluIHlvdXIgUiBNYXJrZG93biBmaWxlIGFuZCBzZWUgd2hhdCBpcyB0aGUgaXNzdWUuIEZvciBleGFtcGxlIHRoZSBlcnJvciBpcyBsb2NhdGVkIGluIGxpbmUgMzQuCgohW0tuaXR0aW5nIFN0b3BwZWQgYnkgYW4gRXJyb3IgaW4gdGhlIElzc3VlcyBTY3JlZW5dKGtuaXRlcnJvcjIucG5nKSAKClwKCkhvcGVmdWxseSwgdGhlIGVycm9yIHN0YXRlbWVudCByZXZlYWxzIHdoeSB5b3Ugd2VyZSBub3QgYWJsZSB0byBrbml0LiBJZiBpdCBpcyBub3QgaWxsdW1pbmF0aW5nICh1aCBvaCksIHlvdeKAmWxsIG5lZWQgdG8gZmlndXJlIG91dCB3aGF0IHlvdSBkaWQgd3JvbmcuIFNlZSB0aGUgKipIYXZpbmcgcHJvYmxlbXMga25pdHRpbmc/Kiogc2VjdGlvbiBiZWxvdy4KCk5vdGUgdGhhdCB3aGVuIHlvdSBhcmUga25pdHRpbmcsIHByb2dyZXNzIGFuZCBhbnkgZXJyb3JzIHdpbGwgYmUgc2hvd24gbm90IGluIHRoZSByZWd1bGFyIFIgY29uc29sZSB3aW5kb3csIGJ1dCBpbiBhIHNwZWNpYWwgUiBNYXJrZG93biB3aW5kb3cuIFRvIHRvZ2dsZSBiYWNrIHRvIHRoZSBDb25zb2xlIChhbmQgYmFjayB0byB0aGUgUiBNYXJrZG93biB3aW5kb3cpLCBqdXN0IGNsaWNrIG9uIHRoZSBDb25zb2xlIChvciBSIE1hcmtkb3duKSB0YWIgYXMgc2hvd24gYmVsb3cuCgohW0NvbnNvbGUgVGFiXShjb25zb2xldGFiLnBuZykKClwKCklmIHlvdSBlbmNvdW50ZXIgbm8gZXJyb3JzLCBhIHByZXZpZXcgb2YgeW91ciBrbml0dGVkIGRvY3VtZW50IHdpbGwgcG9wIHVwIGluIGEgbmV3IHdpbmRvdyBhbmQgdGhlIGAuaHRtbGAgKG9yIGAucGRmYCBvciBgLmRvY3hgKSBmaWxlIHdpbGwgYmUgc2F2ZWQgaW4gdGhlIGZvbGRlciB3aGVyZSB5b3VyIFJtZCBmaWxlIHJlc2lkZXMuICoqSSByZWNvbW1lbmQgbm90IHdhaXRpbmcgdGlsbCB0aGUgdmVyeSBlbmQgb2YgYW4gYXNzaWdubWVudCB0byBrbml0LioqIFdoZW4geW91IGZpbmlzaCBvbmUgcXVlc3Rpb24sIGtuaXQgeW91ciBkb2N1bWVudCB0byBzZWUgaWYgZXZlcnl0aGluZyBpcyB3b3JraW5nIHByb3Blcmx5LiBJZiBpdCBpcyB3b3JraW5nIGZvciB0aGF0IHF1ZXN0aW9uLCBtb3ZlIG9uIHRvIHRoZSBuZXh0IHF1ZXN0aW9uLgoKTGV04oCZcyBiZSBjbGVhci4gVGhlcmUgYXJlIHR3byB0aGluZ3MgeW914oCZbGwgaGF2ZSB0byBkZWFsIHdpdGg6ICgxKSBNYWtpbmcgc3VyZSB0aGUgUiBjb2RlIGlzIHdvcmtpbmcgY29ycmVjdGx5IHRvIGdldCB0aGUgcmVzdWx0cyB5b3UgbmVlZCBpbiBvcmRlciB0byBhbnN3ZXIgdGhlIHF1ZXN0aW9uICgyKSBNYWtpbmcgc3VyZSB0aGUgY29kZSBpcyB3b3JraW5nIGNvcnJlY3RseSB0byBrbml0IGEgZmluYWwgZG9jdW1lbnQuIFRoZXNlIHR3byBpc3N1ZXMgbWF5IGJlIHJlbGF0ZWQgKGlmIHlvdXIgUiBjb2RlIGlzIHByb2R1Y2luZyBhbiBlcnJvciwgUiBNYXJrZG93biB3aWxsIG5vdCBrbml0KSwgYnV0IHNvbWV0aW1lcyB0aGV5IGFyZSBub3QuIFNvLCBjaGVjayBib3RoIHlvdXIgUiBjb2RlIGFuZCB5b3VyIGtuaXR0aW5nIHJlc3VsdHMgb2Z0ZW4uICoqQW5kIGFic29sdXRlbHkgZG8gbm90IHdhaXQgdGlsbCB0aGUgbGFzdCBtaW51dGUgdG8ga25pdC4gS25pdCBhcyBvZnRlbiBhcyBwb3NzaWJsZS4qKgoKV2hlbiB5b3XigJlyZSBzYXRpc2ZpZWQgd2l0aCB0aGUgZW5kIHByb2R1Y3QsIHN1Ym1pdCB5b3VyIGAuUm1kYCBkb2N1bWVudCBhbmQgYSBrbml0dGVkIGRvY3VtZW50IG9uIENhbnZhcy4KClwKCiMgSGF2aW5nIHByb2JsZW1zIGtuaXR0aW5nPwoKLUEgbWFqb3Igc291cmNlIG9mIGVycm9yIGZvciBtb3N0IG5ldyBSIE1hcmtkb3duIHVzZXJzIGlzIHRoYXQgdGhleSBjYWxsIHVwIGEgZGF0YSBvYmplY3QgaW4gdGhlaXIgUiBNYXJrZG93biBmaWxlIHRoYXQgaGFzIG5vdCBiZWVuIGNyZWF0ZWQgd2l0aGluIHRoZSBSIE1hcmtkb3duIGZpbGUuIFRyZWF0IHRoZSBSIE1hcmtkb3duIGFzIGl0cyBvd24gc2VwYXJhdGUgc3lzdGVtIC0gZXZlbiBpZiB5b3XigJl2ZSBjcmVhdGVkIGFuIG9iamVjdCB0aHJvdWdoIHRoZSBSIENvbnNvbGUsIGFuZCB5b3UgY2FuIHNlZSBpdCBzaXR0aW5nIGluIHlvdXIgRW52aXJvbm1lbnQgd2luZG93LCBSIE1hcmtkb3duIHdvbuKAmXQgcmVjb2duaXplIGl0IGJlY2F1c2UgaXQgd2FzIG5vdCBjcmVhdGVkIHdpdGhpbiB0aGUgUiBNYXJrZG93biBkb2N1bWVudC4KClRvIGJlIGNsZWFyLCBsZXTigJlzIHNheSB5b3UgdHlwZWQgZGlyZWN0bHkgaW4gdGhlIFIgY29uc29sZSB0aGUgZm9sbG93aW5nIGNvZGU6CmBgYHtyIHAxfQpteW9iamVjdCA8LSAyCmBgYAoKXAoKWW91IHNlZSB0aGUgb2JqZWN0IGBteW9iamVjdGAgcG9wIHVwIGluIHlvdXIgRW52aXJvbm1lbnQgd2luZG93IGluIHRoZSB0b3AgcmlnaHQgd2luZG93LiBMZXTigJlzIHNheSB5b3Ugd3JpdGUgaW4geW91ciBSIE1hcmtkb3duIGZpbGUgdGhlIGNvZGU6CgpgYGB7ciBwMiwgcmVzdWx0cz0nYXNpcycsIGVjaG89RkFMU0V9CmNhdCgiYGBgYG1hcmtkb3duXG4iLAogICAgImBgYHtyfVxuIiwKICAgICJteW9iamVjdCoxMFxuIiwKICAgICJgYGBcbiIsCiAgICAiYGBgYCIsIHNlcCA9ICIiKQpgYGAKClwKCllvdSB0aGVuIGNsaWNrIG9uICFba25pdGJ1dHRvbl0oa25pdGJ1dHRvbi5wbmcpIHRvIGtuaXQuIFlvdSB3aWxsIGdldCBhbiBlcnJvciBiZWNhdXNlIFIgd2lsbCBub3QgYmUgYWJsZSB0byBrbml0ICoqYmVjYXVzZSBteW9iamVjdCB3YXMgbm90IGNyZWF0ZWQgd2l0aGluIHRoZSBSIE1hcmtkb3duKiouIEJvdGggbGluZXMgb2YgY29kZSBzaG91bGQgYmUgaW4gdGhlIFIgTWFya2Rvd24gZmlsZSBhcyBmb2xsb3dzOgpgYGB7ciBwMywgcmVzdWx0cz0nYXNpcycsIGVjaG89RkFMU0V9CmNhdCgiYGBgYG1hcmtkb3duXG4iLAogICAgImBgYHtyfVxuIiwKICAgICJteW9iamVjdCA8LSAyXG4iLAogICAgIlxuIiwKICAgICJteW9iamVjdCoxMFxuIiwKICAgICJgYGBcbiIsCiAgICAiYGBgYCIsIHNlcCA9ICIiKQpgYGAKClwKCk9uY2UgYWdhaW4sICoqdHJlYXQgdGhlIFIgTWFya2Rvd24gZmlsZSBhcyBhIHNlbGYtY29udGFpbmVkLCBzdGFuZCBhbG9uZSBzY3JpcHQqKi4gVGhpcyBpcyBhbiBpbXBvcnRhbnQgY29uY2VwdCB0byB1bmRlcnN0YW5kIGJlY2F1c2UgbWFueSBzdHVkZW50cyBnZXQgdHJpcHBlZCB1cCBvbiBpdCB3aGVuIGZpcnN0IHN0YXJ0aW5nIG91dC4KCi0gQXJlIHlvdSB0cnlpbmcgdG8gYnJpbmcgaW4gYSBkYXRhIGZpbGUgdGhhdCBpcyBub3QgbG9jYXRlZCBpbiB0aGUgZGlyZWN0b3J5IHlvdXIgUiBNYXJrZG93biBpcyBwb2ludGVkIHRvPyBSZW1lbWJlciwgZG9u4oCZdCBzY2F0dGVyIHlvdXIgZGF0YSBmaWxlcyBmb3IgYW4gYXNzaWdubWVudCBhY3Jvc3MgZGlmZmVyZW50IGZvbGRlcnMuIEtlZXAgdGhlbSBpbiAtIG9uZSBmb2xkZXIgLSB0aGUgZm9sZGVyIHdoZXJlIHlvdXIgUiBNYXJrZG93biBkb2N1bWVudCByZXNpZGVzLiBUbyBmaW5kIHlvdXIgY3VycmVudCB3b3JraW5nIGRpcmVjdG9yeSwgdHlwZSBpbiBgZ2V0d2QoKWAgaW4geW91ciBjb25zb2xlIGFuZCBwcmVzcyBlbnRlci4gVG8gc2V0IHlvdXIgd29ya2luZyBkaXJlY3RvcnksIHR5cGUgaW4gLSBgc2V0d2QoImZvbGRlciIpYCBpbiB5b3VyIFIgTWFya2Rvd24gYW5kIHJlcGxhY2Ug4oCcZm9sZGVy4oCd4oCdIHdpdGggdGhlICoqZW50aXJlKiogcGF0aCB5b3Ugd2FudCBSIHRvIHBvaW50IHRvLiBZb3UgY2FuIGFsc28gc2V0IHlvdXIgd29ya2luZyBkaXJlY3RvcnkgYnkgY2xpY2tpbmcgb24gU2Vzc2lvbiAtPiBTZXQgV29ya2luZyBEaXJlY3RvcnkgLT4gQ2hvb3NlIC0gRGlyZWN0b3J5IGZyb20gdGhlIHRvcCBtZW51LgotIERvIHlvdSBoYXZlIGFuIGBpbnN0YWxsLnBhY2thZ2VzKClgIGluIHlvdXIgUiBNYXJrZG93biBzY3JpcHQ/IFRha2UgaXQgb3V0ISBZb3Ugb25seSBuZWVkIHRvIGRvIGl0IG9uY2UgLSBhbmQgbmV2ZXIgaW5zaWRlIGFuIFIgTWFya2Rvd24gc2NyaXB0LgotIERvIHlvdSBoYXZlIGEgYFZpZXcoKWAgY29tbWFuZCBpbiB5b3VyIFIgTWFya2Rvd24gc2NyaXB0PyBUYWtlIGl0IG91dCEgU29tZXRpbWVzIFIgTWFya2Rvd24gd2lsbCBoYXZlIHByb2JsZW1zIHdoZW4gdHJ5aW5nIHRvIHZpZXcgYW4gUiBkYXRhIG9iamVjdC4KLSBBcmUgeW91IHVzaW5nIGZ1bmN0aW9ucyBmb3IgYSBwYWNrYWdlIHRoYXQgeW91IG5lZWQgdG8gbG9hZCBpbnRvIFIgYW5kIGhhdmVu4oCZdCBsb2FkZWQgaXQgaW4geW91ciBSIE1hcmtkb3duIHVzaW5nIGBsaWJyYXJ5KClgLiBJZiBzbywgbG9hZCBpdCBpbiBSIE1hcmtkb3duIQotIElmIHlvdSBjaGFuZ2UgYSBwaWVjZSBvZiBjb2RlIHNvbWV3aGVyZSBpbiB0aGUgbWlkZGxlIGJlY2F1c2UgeW91IGNhdWdodCBhbiBlcnJvciwgbWFrZSBzdXJlIHRoYXQgY2hhbmdlIGlzIHJlZmxlY3RlZCB0aHJvdWdob3V0IHRoZSBjb2RlLiBGb3IgZXhhbXBsZSwgbGV04oCZcyBzYXkgeW91IGRlY2lkZSB0byByZW5hbWUgdGhlIG9iamVjdCAqaGlzb2JqZWN0KiB0byAqaGVyb2JqZWN0Ki4gVGhlcmUgbWF5IGJlIGNvZGUgbGF0ZXIgb24gaW4gdGhlIGRvY3VtZW50IHRoYXQgdXNlcyAqaGlzb2JqZWN0Ki4gU28sIHlvdeKAmWxsIG5lZWQgdG8gY2hhbmdlICoqZXZlcnkqKiBsaW5lIG9mIGNvZGUgaW4geW91ciBSIE1hcmtkb3duIHRoYXQgdXNlcyAqaGlzb2JqZWN0KiB0byBub3cgdXNlICpoZXJvYmplY3QqLgotIFNQRUxMSU5HLCBTcGVsbGluZywgc3BlbGxpbmcuIENoZWNrIHlvdXIgc3BlbGxpbmcuIFlvdSBjcmVhdGVkIGFuIG9iamVjdCBuYW1lZCAqaGlzb2JqZWN0KiwgYnV0IHlvdSB1c2UgaXQgbGF0ZXIgaW4gdGhlIGZpbGUgYXMgKmhzb2JqZWN0LiogUiB3aWxsIHRlbGwgeW91IHRoYXQgKmhzb2JqZWN0KiBpcyBub3QgZm91bmQuIFlvdSB1c2UgdGhlIGZ1bmN0aW9uIC0gYHJlYWRfY3ZzKClgIGFzIG9wcG9zZWQgdG8gdGhlIGNvcnJlY3QgZnVuY3Rpb24gYHJlYWRfY3N2KClgLgotIFIgaXMgY2FzZSBzZW5zaXRpdmUuIFRoZSBvYmplY3QgKk1vbmV5KiBpcyBkaWZmZXJlbnQgZnJvbSAqbW9uZXkqLgotIFIgZnVuY3Rpb25zIGFyZSBzb21ldGltZXMgZmluaWNreSBhYm91dCBzcGFjZXMuIFRoZXkgYXJlIGFsc28gZmluaWNreSBhYm91dCBxdW90ZXMuIFNvbWUgZnVuY3Rpb25zIHJlcXVpcmUgcXVvdGVzLCBvdGhlcnMgZG9u4oCZdC4KLSBNYWtlIHN1cmUgdGhhdCB3aGVuIHlvdSB1c2UgYnJhY2tldHMsIHBhcmVudGhlc2VzIG9yIHF1b3RlcywgdGhleSBzaG91bGQgc3RhcnQgYW5kIGVuZCB3aXRoIG9uZS4gSXQgaXMgdmVyeSByYXJlIHRoYXQgeW91IHdpbGwgdXNlIGEgbGVmdCBwYXJlbnRoZXNlcyBhbmQgbm90IGNsb3NlIGl0IHdpdGggYSByaWdodCBwYXJlbnRoZXNlcy4KLSBBcyBJIG1lbnRpb25lZCBhYm92ZSwgZG9u4oCZdCB3YWl0IHRpbGwgdGhlIGxhc3QgbWludXRlIHRvIGtuaXQuIEtuaXQgYWZ0ZXIgZXZlcnkgcXVlc3Rpb24uIFJlcGVhdCBpdCBhZ2FpbjogS25pdCBhZnRlciBldmVyeSBxdWVzdGlvbi4KLSBUaGUgZmlyc3QgcGxhY2UgdG8gY2hlY2sgd2hlbiB5b3UgZ2V0IGEga25pdHRpbmcgZXJyb3IgaXMgdGhlIHNwZWNpZmljIGNodW5rIG9yIGxpbmUgdGhhdCB0aGUgZXJyb3IgaXMgcG9pbnRpbmcgdG8uCi0gQXMgSSBtZW50aW9uZWQgYWJvdmUsIGNoZWNrIGlmIHlvdXIgUiBjb2RlIHdvcmtzIG9uZSBjaHVuayBhdCBhIHRpbWUuCi0gSGF2aW5nIHByb2JsZW0gd2l0aCBhIGxpbmUgb2YgUiBjb2RlPwogIC0gRGlkIHlvdSBpbnN0YWxsIHRoZSBhcHByb3ByaWF0ZSBwYWNrYWdlPwogIC0gRGlkIHlvdSBsb2FkIGluIHRoZSBhcHByb3ByaWF0ZSBsaWJyYXJ5PwogIC0gQXJlIHlvdSB1c2luZyB0aGUgcmlnaHQgZnVuY3Rpb24/CiAgLSBEaWQgeW91IHNwZWNpZnkgYWxsIHRoZSBmdW5jdGlvbuKAmXMgYXJndW1lbnRzIGNvcnJlY3RseT8KLSBTdGlsbCBoYXZpbmcgcHJvYmxlbXM/IEJyZWFrIHVwIHlvdXIgY29kZSBsaW5lIGJ5IGxpbmUgb3IgZXZlbiBhcmd1bWVudCBieSBhcmd1bWVudCB0byBmaW5kIHRoZSBlcnJvcj8gRm9yIGV4YW1wbGUsIGxldOKAmXMgc2F5IHlvdSBoYXZlIDQgbGluZXMgb2YgY29kZSB0aGF0IGFyZSBjb25uZWN0ZWQgdG9nZXRoZXIgLSBpLmUuIGxpbmUgNCBkZXBlbmRzIG9uIGxpbmUgMywgbGluZSAzIGRlcGVuZHMgb24gbGluZSAyLCBhbmQgc28gb24KYGBge3A0fQpsaW5lIDEgY29kZQpsaW5lIDIgY29kZQpsaW5lIDMgY29kZQpsaW5lIDQgY29kZQpgYGAKCklmIHlvdSBnZXQgYW4gZXJyb3IsIHJ1biBsaW5lIDEgZmlyc3QuIE5vIGVycm9yPyBSdW4gbGluZSAxIGFuZCAyLiBObyBlcnJvcj8gS2VlcCBnb2luZyB1bnRpbCB5b3UgZmluZCB0aGUgb2ZmZW5kaW5nIGxpbmUuCgotIElmIHlvdSBoYXZlIGEgTWFjIGFuZCB5b3UgYXJlIGdldHRpbmcgYW4gZXJyb3Igd2hlbiBrbml0dGluZywgeW91IG1heSBuZWVkIHRvIGRvd25sb2FkIHRoZSBtb3N0IHJlY2VudCB2ZXJzaW9uIG9mIFhRdWFydHosIHdoaWNoIGNhbiBiZSBkb3dubG9hZGVkIFtoZXJlXShodHRwOi8veHF1YXJ0ei5tYWNvc2ZvcmdlLm9yZy8pCi0gSWYgeW914oCZcmUgc3RpbGwgc3R1Y2ssIG1vcmUgdGhhbiBsaWtlbHkgc29tZW9uZSBlbHNlIGFsc28gaGFkIGEgc2ltaWxhciBwcm9ibGVtIGluIHRoZSBwYXN0LiBTbywgYXNrIGEgY2xhc3NtYXRlLiBJZiB5b3VyIGNsYXNzbWF0ZSBpcyBhbHNvIHN0dWNrLCB1c2UgR29vZ2xlIGFuZCBpdCBtaWdodCBoZWxwIHlvdSBvdXQuCgpcCgojIFN1bW1hcnkKClRoZSBwcm9wZXIgd29ya2Zsb3cgZm9yIGVhY2ggYXNzaWdubWVudCB3aWxsIGJlIGFzIGZvbGxvd3MKCjEuIEdvIHRocm91Z2ggdGhlIHdlZWvigJlzIHJlYWRpbmcgYW5kIGxhYiBndWlkZSBhbmQgbWFrZSBzdXJlIHlvdSB1bmRlcnN0YW5kIHRoZSBtYXRlcmlhbC4KMS4gQ3JlYXRlIGEgZm9sZGVyIG9uIHlvdXIgaGFyZCBkcml2ZSB0aGF0IGlzIHNwZWNpZmljIHRvIHRoZSBhc3NpZ25tZW50IChlLmcuIEFzc2lnbm1lbnQgMSwgQXNzaWdubWVudCAyLCBldGMuKS4KMS4gQ3JlYXRlIGFuIFIgTWFya2Rvd24gYXNzaWdubWVudCBmaWxlLiBTYXZlIGl0IGluIHRoZSBhcHByb3ByaWF0ZSBhc3NpZ25tZW50IGZvbGRlciBvbiB5b3VyIGhhcmQgZHJpdmUuCjEuIERvd25sb2FkIGFueSBkYXRhIG5lZWRlZCBmb3IgdGhlIGFzc2lnbm1lbnQgaW50byB0aGUgc2FtZSBmb2xkZXIuIEZvciBtb3N0IGFzc2lnbm1lbnRzLCBJIHdpbGwgdXBsb2FkIHRoZSBhc3NpZ25tZW50IGRhdGEgb24gR2l0SHViLCB3aGljaCB5b3UgY2FuIGRpcmVjdGx5IGxpbmsgdG8gaW4gUiwgc28geW91IHdvbuKAmXQgaGF2ZSB0byBkb3dubG9hZCBkYXRhLiBTb21lIGZpbGVzIHdpbGwgYmUgbG9jYXRlZCBvbiBDYW52YXMuCjEuIEluIHRoZSBSIE1hcmtkb3duIGRvY3VtZW50LCBhbnN3ZXIgdGhlIGZpcnN0IGFzc2lnbm1lbnQgcXVlc3Rpb24uCi0gTW9zdCBvZiB0aGUgcXVlc3Rpb25zIHdpbGwgYXNrIHlvdSB0byBydW4gY29kZS4gU2hvdyB0aGF0IGNvZGUgaW4gUiBNYXJrZG93biBjaHVua3MuIEJvdHRvbSBsaW5lOiBBbnkgY29kZSB5b3UgdXNlZCB0byBnZXQgYSByZXN1bHQgc2hvdWxkIGJlIGluIHlvdXIgYXNzaWdubWVudC4gT3RoZXJ3aXNlLCB5b3Ugd2lsbCBnZXQgcG9pbnRzIG9mZiwgYW5kIGZvciAxLiBzb21lIHF1ZXN0aW9ucywgZ2V0IGFsbCBwb2ludHMgb2ZmLgogIC0gQnJlYWsgdXAgeW91ciBjb2RlIGludG8gZGlmZmVyZW50IGNodW5rcyB3aGVyZSBpdCBtYWtlcyBzZW5zZS4gRm9yIHNvbWUgcXVlc3Rpb25zLCB5b3UgbWlnaHQgaW5jbHVkZSBhbGwgY29kZSBmb3IgYSBxdWVzdGlvbiBpbiBvbmUgc2luZ2xlIGNodW5rLiBGb3Igb3RoZXIgcXVlc3Rpb25zLCB5b3UgbWlnaHQgYnJlYWsgdXAgdGhlIGNvZGUgaW50byAxLiBzZXZlcmFsIGNodW5rcy4KICAtIE1ha2Ugc3VyZSB5b3VyIGNvZGUgd29ya3MuIFJ1biBjb2RlIG9uZSBjaHVuayBhdCBhIHRpbWUgdG8gbWFrZSBzdXJlIGl0IGlzIHdvcmtpbmcuIE5vdGUgdGhhdCB0aGVyZSBhcmUgbXVsdGlwbGUgd2F5cyB0byBnZXQgdG8gYW4gYW5zd2VyIGluIFIuIFdlIHdpbGwgbm90IGdyYWRlIG9uIGhvdyBlZmZpY2llbnQgeW91ciBjb2RlIGlzIHVubGVzcyBzdGF0ZWQgMS4gc28gaW4gdGhlIHF1ZXN0aW9uLgotIE1vc3Qgb2YgdGhlIHF1ZXN0aW9ucyB3aWxsIGFzayB5b3UgdG8gZXhwbGFpbiB5b3VyIHJlc3VsdHMuIFdyaXRlIHlvdXIgZXhwbGFuYXRpb25zIG91dHNpZGUgb2YgdGhlIFIgY29kZSBjaHVua3MuIFBsZWFzZSAtICpwbGVhc2UqIC0gdGFrZSB0aGVzZSBpbnRlcnByZXRhdGlvbiBxdWVzdGlvbnMgc2VyaW91c2x5LiBUaGlzIGlzIGEgbm90IGEgcHJvZ3JhbW1pbmcgb3IgRGF0YSBTY2llbmNlIGNvdXJzZSAtIHlvdSBtYXkgaGF2ZSB0YWtlbiA0MCBob3VycyB0byBwcm9kdWNlIHN1cGVyIGVsZWdhbnQgY29kZSB0byBhbnN3ZXIgYSBxdWVzdGlvbiwgYnV0IHlvdXIgcmVzdWx0cyB3b27igJl0IGJlIHdvcnRoIG11Y2ggdG8gYW55b25lIGlmIHlvdSBjYW7igJl0IHByb3Blcmx5IGludGVycHJldCB0aGVtLgoxLiBBZnRlciB5b3XigJl2ZSBjb21wbGV0ZWQgdGhlIGZpcnN0IHF1ZXN0aW9uLCBrbml0IHRvIGFuIGAuaHRtbGAsIGAucGRmYCBvciBgLmRvY3hgIGZpbGUuIE1ha2Ugc3VyZSBpdCBrbml0cyBwcm9wZXJseS4gSWYgaXQgZG9lcyBub3QsIGV4YW1pbmUgdGhlIGVycm9yLCBhbmQgZml4IHRoZSBwcm9ibGVtLgoxLiBJZiB5b3XigJlyZSBzYXRpc2ZpZWQgd2l0aCB5b3VyIGNvZGUgYW5kIGl0cyByZXN1bHRzIGZvciB0aGUgZmlyc3QgcXVlc3Rpb24sIGFuZCB0aGUgZG9jdW1lbnQgcHJvcGVybHkga25pdHRlZCwgbW92ZSBvbiB0byB0aGUgbmV4dCBxdWVzdGlvbi4gUmVwZWF0IHN0ZXBzIDUgYW5kIDYuCjEuIE9uY2UgeW914oCZdmUgY29tcGxldGVkIGFsbCBxdWVzdGlvbnMgYW5kIHN1Y2Nlc3NmdWxseSBrbml0dGVkLCBzdWJtaXQgdGhlIGAuUm1kYCBhbmQgdGhlIGtuaXR0ZWQgZmlsZXMgb24gQ2FudmFzIGJlZm9yZSB0aGUgZGVzaWduYXRlZCBkdWUgdGltZS4KMS4gU21pbGUsIHBhdCB5b3Vyc2VsZiBvbiB0aGUgYmFjaywgYW5kIGdvIGZvciBhIHdhbGssIHJ1biwgb3IgYmlrZSByaWRlLiBPciBqdXN0IHNpdCBvdXRzaWRlIGFuZCBlbmpveSBuYXR1cmUuCgpcCgojIEdyYWRpbmcKClRoaXMgY291cnNlIGlzbid0IGFib3V0IGdyYWRpbmcgb3IgbWV0cmljcy4gSXQncyBhYm91dCBsZWFybmluZyB0aGUgbWF0ZXJpYWwuIEJ1dCBpZiB5b3UnZCBsaWtlIHRvIGdldCBmdWxsIGNyZWRpdCBmb3IgZWFjaCBhc3NpZ25tZW50LCB5b3Ugd2lsbCBuZWVkIHRvOgoKMS4gU2hvdyB0aGUgY29ycmVjdCByZXN1bHRzIGZvciBhIGdpdmVuIHF1ZXN0aW9uIChlLmcuIG1hcCwgdGFibGUsIHN0YXRpc3RpY3MpLgoxLiBTaG93IHRoZSBjb2RlIHByb2R1Y2luZyB0aGUgcmVzdWx0cy4KMS4gUHJvdmlkZSBjb21tZW50cyBleHBsYWluaW5nIHdoYXQgdGhlIGNvZGUgaXMgZG9pbmcuCjEuIFByb3ZpZGUgY29ycmVjdCB3cml0dGVuIGFuc3dlcnMuCgpBbnkgcmVzcG9uc2UgcmVxdWlyaW5nIGEgZGF0YSBhbmFseXNpcyB0YXNrIG11c3QgYmUgc3VwcG9ydGVkIGJ5IGNvZGUgeW91IGdlbmVyYXRlIHRvIHByb2R1Y2UgeW91ciByZXN1bHQuIEp1c3QgZXhhbWluaW5nIHlvdXIgdmFyaW91cyBvYmplY3RzIGluIHRoZSDigJxFbnZpcm9ubWVudOKAnSBzZWN0aW9uIG9mIFIgU3R1ZGlvIGlzIGluc3VmZmljaWVudOKAlHlvdSBtdXN0IHVzZSBzY3JpcHRlZCBjb21tYW5kcy4gQmVjYXVzZSB0aGVyZSBhcmUgdHlwaWNhbGx5IG11bHRpcGxlIHdheXMgdG8gZ2V0IGFuIGFuc3dlciwgd2Ugd2lsbCBub3QgZ3JhZGUgeW91IG9uIHRoZSBlZmZpY2llbmN5IG9mIHlvdXIgY29kZS4gWW91IGNhbiBhc2sgZm9yIGhlbHAgZnJvbSB0aGUgVEEgYW5kIHdvcmsgd2l0aCBvdGhlciBzdHVkZW50cy4gSG93ZXZlciwgeW91IG11c3Qgc3VibWl0IHlvdXIgb3duIGFzc2lnbm1lbnRzLgoKQWxzbyBub3RlOiBhbGwgY29kZSB1c2VkIHRvIHByb2R1Y2UgeW91ciByZXN1bHRzIG11c3QgYmUgc2hvd24gaW4geW91ciBIVE1MIGZpbGUgKGUuZy4sIGRvIG5vdCB1c2UgYGVjaG89RkFMU0VgIG9yIGBpbmNsdWRlPUZBTFNFYCBhcyBvcHRpb25zIGFueXdoZXJlLiBXZWxsLCBtb3N0bHkgYW55d2hlcmUgLSB3ZeKAmWxsIGdldCB0byBzb21lIGNhc2VzIHdoZXJlIHRoZXkgYXJlIHVzZWZ1bCB0byBpbmNsdWRlKS4gT3RoZXIgcGllY2VzIG9mIGFkdmljZToKCi0gV2Ugd2lsbCBub3QgZ3JhZGUgb24gaG93IGVmZmljaWVudCB5b3VyIGNvZGUgaXMgdW5sZXNzIHN0YXRlZCBzbyBpbiB0aGUgcXVlc3Rpb24uIFdlIHdpbGwgbmV2ZXIgdGFrZSBwb2ludHMgb2ZmIGZvciBhY2NvbXBsaXNoaW5nIHRoaW5ncyBkaWZmZXJlbnRseSB0aGFuIGV4cGVjdGVkIGFzIGxvbmcgYXMgaXQgcHJvZHVjZXMgdGhlIGNvcnJlY3QgcmVzdWx0LiBIb3dldmVyLCBpZiB0aGUgYW5zd2VyIGlzICppbmNvcnJlY3QqIGFuZCB5b3VyIGNvZGUgaW5kaWNhdGVzICpsaXR0bGUgZWZmb3J0KiAoZS5nLiBibGFuayBvciBhIGZldyBsaW5lcyBvZiBjb2RlIHRoYXQgeWllbGQgbm90aGluZykgb3IgaXMgY29tcGxldGVseSBpbmNvbXByZWhlbnNpYmxlIChlLmcuIDIwIGxpbmVzIG9mIG1pc2ggbWFzaCksIGV4cGVjdCBmZXcgdG8gbm8gcG9pbnRzLgotIFlvdSBtdXN0IHN1Ym1pdCBib3RoIGFuIGAuUm1kYCBhbmQgaXRzIGtuaXR0ZWQgKGAuaHRtbGAsIGAucGRmYCBvciBgLmRvY3hgKSBmaWxlLiBJZiB5b3UgZG9u4oCZdCwgd2Ugd2lsbCB0YWtlIHNpZ25pZmljYW50IHBvaW50cyBvZmYuCgpcCgojIE90aGVyIHRoaW5ncyB0byBrbm93CgotIFBsZWFzZSBzcGVsbC1jaGVjayB5b3VyIGFzc2lnbm1lbnQgYmVmb3JlIGhhbmRpbmcgaXQgaW4gKEVkaXQgLT4gQ2hlY2sgU3BlbGxpbmcgZnJvbSB0aGUgdG9wIG1lbnUgYmFyKS4KLSBUaGUgZGVmYXVsdCBlZGl0b3Igc2V0dGluZ3MgYXJlIHRvIGluc2VydCBtYXRjaGluZyBwYXJlbnRoZXNlcyBhbmQgcXVvdGVzOyBpZiB5b3UgZmluZCB0aGF0IHRoaXMgaW50cnVkZXMgb24geW91ciB3b3JrZmxvdywgeW91IGNhbiBkaXNhYmxlIGl0IHZpYSBUb29scyAtPiBHbG9iYWwgT3B0aW9ucyAtPiBDb2RlIHRoZW4gdW5jaGVjayBJbnNlcnQgLSBtYXRjaGluZyBwYXJlbnMvcXVvdGVzLgotIFdlIGV4cGVjdCB5b3UgdG8gd29yayB0b2dldGhlci4gVHdvIGhlYWRzIGFyZSBiZXR0ZXIgdGhhbiBvbmUsIGFuZCBmb3VyIGhlYWRzIGFyZSBiZXR0ZXIgdGhhbiB0d28KLSBXZSBleHBlY3QgeW91IHRvIGFzayBmb3IgaGVscCBpZiB5b3UgZ2V0IHN0dWNrIChhbmQgeW91IHdpbGwgYmUgc3R1Y2sgYSBsb3QtLSoqd2Uga25vdywgYmVjYXVzZSB3ZSBhbHdheXMgZ2V0IHN0dWNrIGFuZCB3b3JrIHRocm91Z2ggcHJvYmxlbXMgdG9vISoqKS4gV2UgY2Fu4oCZdCByZWFkIG1pbmRzLCBzbyBpZiB5b3UgZG9u4oCZdCB0ZWxsIHVzIHRoYXQgeW91IGFyZSBjb25mdXNlZCwgd2Ugd29u4oCZdCBrbm93LiAqKldlIGFyZSBhbHdheXMgaGFwcHkgdG8gaGVscCEqKgotIFlvdSBzaG91bGQgdHJ5IGFuZCBzb2x2ZSBwcm9ibGVtcyBiZWZvcmUgeW91IGFzayBmb3IgaGVscC4KLSBUcnlpbmcgaW5jbHVkZXMgYW4gSW50ZXJuZXQgc2VhcmNoIChhIGNydWNpYWwgc2tpbGwhKS4gQW5kIG1heWJlIGV2ZW4gYSBkYWJibGUgaW50byBDaGF0R1BUIGlmIHlvdSBkYXJlLgotIEFsbCBob21ld29yayBzaG91bGQgYmUgc3VibWl0dGVkIG9uIENhbnZhcy4KClwKCiMgR2V0dGluZyBSIE1hcmtkb3duIEhlbHAKCldoZW5ldmVyIHlvdSBhcmUgZWRpdGluZyBSIE1hcmtkb3duIGRvY3VtZW50cyBpbiBSU3R1ZGlvLCB5b3UgY2FuIGRpc3BsYXkgYW4gUiBNYXJrZG93biBjaGVhdCBzaGVldCBieSBnb2luZyB0byBIZWxwIC0+IENoZWF0c2hlZXRzIC0+IFIgTWFya2Rvd24gQ2hlYXQgU2hlZXQuIEEgYmFzaWMgaW50cm9kdWN0aW9uIHRvIFIgTWFya2Rvd24gY2FuIGFsc28gYmUgZm91bmQgaW4gQ2hhcHRlciAyMSBpbiBbUiBmb3IgRGF0YSBTY2llbmNlXShodHRwOi8vcjRkcy5oYWQuY28ubnovaW5kZXguaHRtbCkuIFIgU3R1ZGlvIGhhcyBhIHF1aWNrIFtpbnRyb2R1Y3Rpb25dKGh0dHBzOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tL2F1dGhvcmluZ19xdWlja190b3VyLmh0bWwpIHRvIFIgTWFya2Rvd24uIFdl4oCZdmUgcHV0IHRvZ2V0aGVyIHNvbWUgYWRkaXRpb25hbCBSIHRpcHMgW2hlcmVdKFJfaGVscC5odG1sKSBpbiB0aGUgbGlrZWx5IGNhc2UgdGhhdCB5b3UgZ2V0IHN0dWNrLiBBbmQsIG9mIGNvdXJzZSwgdGhlcmUgaXMgZ29vZCBvbGUgR29vZ2xlLiBVc2UgaXQgdG8gZ2V0IGhlbHAuCg==