Associated material

Zoom notes: Zoom notes 01 - Introducing R and RStudio

Readings:

Before we start

This course is designed with two components - the module and the zoom notes. The module content provides more explanation and background so that you can work through it on your own if you wish. The zoom notes content provides the structure for the content that will be delivered in the online sessions. Both sets of content are complementary to each other.

At the top right hand corner of both the module and zoom notes pages is a “code” button. This can be used to toggle seeing/hiding the code or to download the code that that created the page as an Rmarkdown file (we cover Rmarkdown more in-depth in module/zoom notes 6).


Introduction

Advances in computing and sensing technologies mean that modern scientific research often involves very large data sets. There are now many computer software tools available to work with big data, and scientists from all disciplines need to be able to use them.

In this mini-course, we will help you learn to use one of the most interesting (and popular) of these tools – the programming language R. R is a special-purpose open-source language for statistics and data analysis. Increasingly, R is the preferred tool for analysing and presenting data for student research projects.

In this module, we show you how to get started with R. We will not assume that you have any prior computer programming experience. In fact, if you have programmed before in a language like Java or C, be aware that R is, in many respects, very different from those languages – so keep an open mind.

We will begin by explaining the different software tools you need, and how to get them onto your own computers, if you wish to do so. Then we will discuss the basic mechanics of these tools. Throughout this handout (and all materials for this mini-course) there are code examples and R exercises that you should work through carefully on the computer. This will prepare you to use R for your in-course research projects later in the semester.

This handout is designed to be read in conjunction with Chapter 1: Introduction of R for Data Science.



The Tools

We think of computers as storing rich meaningful data (mostly cat videos). Actually, what computers really contain are millions of tiny little storage units, each of which either holds an electrical charge (usually called a 1) or holds nothing (usually called a 0). Really. That’s it. That’s all there is.

What's inside the computer

What’s inside the computer

All of the amazing things that computers do happen through extremely complicated manipulation of all those 0s and 1s.This involves a lot of maths and a lot of electronics, and is very, very confusing. So that computer users don’t have to think about all these 0s and 1s, computer scientists have developed programming languages, which are symbolic systems that we can use to express what we want to happen inside the machine. Programming languages are designed to be similar to human languages, so they are easy for us to work with. Over the last 60 years many such languages have been developed: FORTRAN, BASIC, C, Java, Python, etc., and the one we are using in this mini-course, R. Each programming language has a vocabulary and a grammar (just like human languages) which must be followed exactly (they are, in fact, much stricter about this than human languages).

To communicate with your computer using a program language, you need a special computer program (previously written in a programming language, of course) that knows how to translate from the human-friendly programming language into actions on the computer. These are called Development Environments, because this is where people develop software.

All The Parts

All The Parts

The most popular development environment for R is a program called RStudio.

Both R and RStudio are installed on the computers in the Otago University computer labs. You can work through this document on those machines.

You can also install the R language and the RStudio program on your own personal computers. These are completely open-source, free, and safe.

First, install R from https://cran.r-project.org/bin/windows/base/ (for Windows machines) or https://cran.r-project.org/bin/macosx/ (for Mac OS machines). Then install RStudio from https://rstudio.com/products/rstudio/download/. Modern scientists need to be comfortable installing software on their own computers. This is a good opportunity for you to practice this important skill, and we encourage you to try it. If you need any help, ask us.



How to Talk to a Computer

When programming a computer you must always remember one very important fact: Computers Are Stupid.

Really. The computer “understands” only a very small and strictly limited set of commands (the grammar and vocabulary of a programming language). If you deviate from this set of commands in any way, the computer cannot figure out what you mean. It is best to think of your computer as a well-meaning, well-trained, but not particularly bright dog. It wants to do as it is told, but if you use a command it doesn’t know, it can’t figure out what you intend. Be nice to your computer – don’t confuse it.

Confused Dog

Confused Dog



Using RStudio

RStudio is a program that can accept R statements and convey them to the machine. In RStudio, you type in an R command, it is executed by the machine, and RStudio can display the results of the command, if any.

In the first instance, just to make sure R and RStudio are working correctly, we will type a few R commands directly into RStudio and execute them in real time (see below). Later, we will see how to store a set of R commands in a file so that we can run them repeatedly without having to retype.


Parts of RStudio

The RStudio interface is divided into separate panes. As you become more comfortable with RStudio, you may wish to reorganise the locations of the different panes. In its default configuration when it first opens, RStudio will have three panes, each of which has multiple tabs. On the left is the Console pane. This is where we will enter our first R commands. At the upper right is the Environment pane. This is where we will see information about the state of our program. At the lower right is the Files pane. Here we can navigate among files on our computer. But more usefully, the Files pane contains a tab labelled Plots. We will switch to this tab to see graphs that we draw with R.

RStudio

RStudio

Using Projects in RStudio

RStudio projects are a great way of compartmentalising analyses. In R for Data Science - Workflow: Projects (https://r4ds.had.co.nz/workflow-projects.html) chapter it discusses some good practices and configurations to help you work with RStudio effectively.

It is highly recommended to read this chapter and implement the suggested configuration changes.



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

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

  2. 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.)

  3. Type the following characters into the Console pane, followed by the Enter key.

If everything is working as it should, your screen should look like this (the contents of the Files pane may be different):

First R Command

First R Command

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
  1. Explore more of R’s mathematical operators. For division use / and for multiplication use *. Enter each of these R commands into the console and confirm that you receive the expected output.
10 / 8

8 * 12

6 - 12 + (3 * 7.4)


More actions: Function calls in R

R syntax (grammar) mimics mathematical equation syntax in some respects. As we denote a function f(x) using round brackets in an equation, so do we denote the application of a function in R. R knows many useful functions. For example sqrt() , which computes the square root of a number, and abs() which computes the absolute value of a number. To apply one of these functions, we type the name, and place the value we wish to operate on (the argument) inside the round brackets.

Code-along Exercise

Try these examples:

abs(-42)
#> [1] 42

sqrt(200)
#> [1] 14.14214

Getting Help

Often you’ll need help for a specific function, such as mean(), you can search the help documentation using ? in front of the function name to do this (e.g. ?mean) and this will bring up the manual page. It provides information about what does, what the arguments are, and even provides some examples that can be copy-pasted and run to give an example of what it does.

The ? is not the only way to find out how to run a function – for more examples of how to find help refer to https://datacarpentry.org/R-ecology-lesson/00-before-we-start.html#Seeking_help


More things: Words

Lots of computing involves words rather than numbers. For example, searching text and enrolling students by name both operate on words. R understands words – the concept of things composed of letters. However, when working with words, we must mark them with special characters to prevent R from becoming confused (we see what this confusion looks like in a moment).

In programming, a thing composed of letters doesn’t have to be a real word (it could be, for example, a product code or user id), so we actually call them strings. To denote a string we surround it with quote marks, like this:

"plato"
#> [1] "plato"

There are functions that operate on strings, exactly equivalent to ones like sqrt() that operate on numbers. For example, R has a function nchar() that computes how many characters (i.e. letters) are in its string argument.

nchar("plato")
#> [1] 5


Code-along Exercise

What do you think will happen if you give the commands below? Enter them into the RStudio console to see.


nkhar("plato")
#> Error in nkhar("plato"): could not find function "nkhar"

sqrt("plato")
#> Error in sqrt("plato"): non-numeric argument to mathematical function

Remember that the language R is a set of vocabulary and grammar rules that must be followed very strictly. There is no function nkhar in R’s vocabulary, only nchar. And function sqrt only understands how to work on numbers, not on strings.

R will never work out what you meant when you deviate from its grammar. No programming language will. If you violate its rules, R will throw an error. But this can be very instructive. Enter the following command into RStudio and carefully consider the outcome. What does this tell you about the rules of the R language?

NCHAR("plato")
#> Error in NCHAR("plato"): could not find function "NCHAR"

We know that R understands the function nchar – we saw it working just a few moments ago. But now it says it could not find that function? This is because, to R, nchar and NCHAR are not the same thing. R is a case-sensitive language. Upper-case and lower-case letters are completely different entities in R. When giving R commands you must always exactly match its expectations about upper and lower case (woof).


Storing Results

Imagine that you have two large numbers and, for some sound scientific reason, you wish to take their ratio and then take the square root of that value. Like this:

198.7 / 64.5
#> [1] 3.08062
sqrt(3.08062)
#> [1] 1.75517

This operation is risky. R has given you the ratio to five accurate decimal places. But you must then be very careful to copy it exactly into the sqrt function, or your answer will be wrong. Extrapolate this to thousands of data operations on a large data set and it is certain that errors will be made.

It would be more convenient, and safer, to take the result R gave you from the first statement, store it somewhere, and then pass the stored entity to function sqrt. This is, in fact, a fundamental action in programming: We can store values as named entities (called variables) and use them whenever and wherever we need them.

In R, this “storing” is performed with the <- operator (called the “assignment” operator). The assignment operator is formed by typing a left angle bracket and a hyphen. In the following code example, we demonstrate the assignment operator. We also demonstrate comments. In R, any text that is prefaced with # is ignored rather than being treated as a command. It is just text that the programmer adds for their own benefit.


Code-along Exercise

Make sure you can duplicate this code, with the same results, in RStudio (you don’t need to type the comments).

# Store the result of the division in an entity (a variable) named ratio. We
# always use meaningful variable names.
ratio <- 198.7 / 64.5  

# This will display the value of the variable named ratio. That's what R does
# when you enter a lone variable name.
ratio 
#> [1] 3.08062

# This will pass the value of ratio as the argument to the sqrt function.
sqrt(ratio)  
#> [1] 1.75517


Variable Names and Values

Look very carefully at the variable name on the left hand side of the assignment operator <-. It is a string of characters, but it is not surrounded by quote marks. This is how, in R, we distinguish strings (a word thing – remember, like “plato”) from variable names.

Inside our computer, variables are implemented (conceptually) as shown below. A location in memory is “named”. When you refer to the name, the computer supplies whatever value is stored at that location.

How Variables Work

How Variables Work

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:

  1. Vectors must be homogeneous. That is, all the elements in the vector must be the same kind (type) of thing.

  2. 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).)

Making an R File

Making an R File

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.

New Script

New Script

3. From the main RStudio menu select File->Save As.. to save your file. Always give your files descriptive names to make it easy to find the one you want later.

4. You can type R commands into the new file (in the upper left pane) exactly as you typed into the console.

5. Executing a command that is typed into a file works a little differently than executing a command that is typed into the console. To execute a single line of code in the file, click your mouse cursor anywhere on the line of code. DO NOT SELECT ANY CHARACTERS. HOLD THE MOUSE STILL WHILE CLICKING. Then type ctrl+Enter (Windows) or cmd+Enter (Mac).

6. To execute multiple lines of code in the file, select all the code you want by clicking and dragging the mouse (ctrl+A or cmd+A for the whole file), then type ctrl+Enter or cmd+Enter.

7. The output from your code will be written to the console, just as though you had typed the code there.

8. After entering some code into your file, save it (the programmer’s motto is Save Early, Save Often). You can then safely exit the RStudio program.

9. Go to wherever you saved your named code file (it will have suffix .R) and double-click on it to open it. The computer may ask you what program to use – select RStudio.

10. The file will open in RStudio and you can run all your code again (see items 5 and 6 above) without having to retype anything.


An Even Better Script File

We will cover RMarkdown in more depth in Module 6.

A basic script file (of type .R) will store and preserve your code. RStudio also provides R Markdown files (of type .Rmd) that can do much more. R Markdown is an extended script format that allows you to embed R commands in formatted text. RStudio processes R Markdown files, producing HTML, Word or pdf formats. During processing (which is called knitting) RStudio runs any embedded R commands and inserts the results into the output document. You don’t need to process your data in RStudio and then copy/paste the results into a separate Word document. You can insert the code directly into your text in an R Markdown file, and it will be executed when RStudio knits. Let’s give it a try:

1. In RStudio, click on the File menu, select New File and, from the submenu that opens, click on R Markdown.

Create an R Markdown File

Create an R Markdown File

2. A dialogue box will open, where you have a chance to enter a title for your document and the name of the author. These will appear at the top of the knit document. You can select the output format. Leave it as HTML for this exercise.

R Markdown Dialogue

R Markdown Dialogue

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.

A New R Markdown File

A New R Markdown File

The file already contains some text. This is some sample contents to give you an idea of what an R Markdown file looks like. You will note that the file has areas with a white background and areas with a shaded background. The white areas are plain text, the shaded areas are R commands. When the file is knit, that code will be run, and its output inserted into the text. To see this in action, click the Knit icon at the top the RStudio tab.

The Knit Button

The Knit Button

RStudio will produce a beautiful HTML document and open it in a local browser window. See if you can match the R code segments in the R Markdown document to the output that appears in the HTML page.

R Markdown is a powerful tool for generating research reports when analysing data with R. As we proceed through this mini-course we will explore additional features of R Markdown, and you may wish to consider using it for your own course assignments. Check with your lecturers to see if this is suitable.



Conclusion

In this module you have considered the inner workings of the computer, written R commands into the RStudio Development Environment, met some of the things R understands (number, strings, and vectors) and some of the actions R can perform (functions). Congratulations.

What’s Next

Fill in the module feedback form https://tinyurl.com/r4ssp-module-fb.

In our next module, we will learn how to read real data files into R and make plots and figures that you can use in a research report. We will start with simple plots you can create using only base R. Then we will learn to use a powerful graphics library called ggplot (part of the tidyverse family of R extensions). With ggplot you can make publication-quality graphs with only a few lines of R code.

LS0tCnRpdGxlOiAiSW50cm9kdWNpbmcgUiBhbmQgUlN0dWRpbyIKZGF0ZTogIlNlbWVzdGVyIDIsIDIwMjIiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93Ci0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoa25pdHIpCgprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgY29tbWVudCA9ICIjPiIsCiAgZmlnLnBhdGggPSAiZmlndXJlcy8wMS8iLCAjIHVzZSBvbmx5IGZvciBzaW5nbGUgUm1kIGZpbGVzCiAgY29sbGFwc2UgPSBUUlVFLAogIGVjaG8gPSBUUlVFCikKCgpgYGAKCgo+ICMjIyMgQXNzb2NpYXRlZCBtYXRlcmlhbAo+Cj4gWm9vbSBub3RlczogW1pvb20gbm90ZXMgMDEgLSBJbnRyb2R1Y2luZyBSIGFuZCBSU3R1ZGlvXSh6b29tX25vdGVzXzAxLmh0bWwpCj4gCj4gUmVhZGluZ3M6Cj4KPiAtIFtSIGZvciBEYXRhIFNjaWVuY2UgLSBDaGFwdGVyIDFdKGh0dHBzOi8vcjRkcy5oYWQuY28ubnovaW50cm9kdWN0aW9uLmh0bWwpCj4gLSBbUiBmb3IgRGF0YSBTY2llbmNlIC0gQ2hhcHRlciA0XShodHRwczovL3I0ZHMuaGFkLmNvLm56L3dvcmtmbG93LWJhc2ljcy5odG0pCgojIyMjIEJlZm9yZSB3ZSBzdGFydAoKVGhpcyBjb3Vyc2UgaXMgZGVzaWduZWQgd2l0aCB0d28gY29tcG9uZW50cyAtIHRoZSBtb2R1bGUgYW5kIHRoZSB6b29tIG5vdGVzLiBUaGUgbW9kdWxlIGNvbnRlbnQgcHJvdmlkZXMgbW9yZSBleHBsYW5hdGlvbiBhbmQgYmFja2dyb3VuZCBzbyB0aGF0IHlvdSBjYW4gd29yayB0aHJvdWdoIGl0IG9uIHlvdXIgb3duIGlmIHlvdSB3aXNoLiBUaGUgem9vbSBub3RlcyBjb250ZW50IHByb3ZpZGVzIHRoZSBzdHJ1Y3R1cmUgZm9yIHRoZSBjb250ZW50IHRoYXQgd2lsbCBiZSBkZWxpdmVyZWQgaW4gdGhlIG9ubGluZSBzZXNzaW9ucy4gQm90aCBzZXRzIG9mIGNvbnRlbnQgYXJlIGNvbXBsZW1lbnRhcnkgdG8gZWFjaCBvdGhlci4KCkF0IHRoZSB0b3AgcmlnaHQgaGFuZCBjb3JuZXIgb2YgYm90aCB0aGUgbW9kdWxlIGFuZCB6b29tIG5vdGVzIHBhZ2VzIGlzIGEgImNvZGUiIGJ1dHRvbi4gVGhpcyBjYW4gYmUgdXNlZCB0byB0b2dnbGUgc2VlaW5nL2hpZGluZyB0aGUgY29kZSBvciB0byBkb3dubG9hZCB0aGUgY29kZSB0aGF0IHRoYXQgY3JlYXRlZCB0aGUgcGFnZSBhcyBhbiBSbWFya2Rvd24gZmlsZSAod2UgY292ZXIgUm1hcmtkb3duIG1vcmUgaW4tZGVwdGggaW4gW21vZHVsZV0oMDYtY29tbXVuaWNhdGUuaHRtbCkvW3pvb20gbm90ZXNdKHpvb21fbm90ZXNfMDYuaHRtbCkgNikuCgoKCgoKClwKCiMgSW50cm9kdWN0aW9uCgpBZHZhbmNlcyBpbiBjb21wdXRpbmcgYW5kIHNlbnNpbmcgdGVjaG5vbG9naWVzIG1lYW4gdGhhdCBtb2Rlcm4gc2NpZW50aWZpYyByZXNlYXJjaCBvZnRlbiBpbnZvbHZlcyB2ZXJ5IGxhcmdlIGRhdGEgc2V0cy4gVGhlcmUgYXJlIG5vdyBtYW55IGNvbXB1dGVyIHNvZnR3YXJlIHRvb2xzIGF2YWlsYWJsZSB0byB3b3JrIHdpdGggYmlnIGRhdGEsIGFuZCBzY2llbnRpc3RzIGZyb20gYWxsIGRpc2NpcGxpbmVzIG5lZWQgdG8gYmUgYWJsZSB0byB1c2UgdGhlbS4KCkluIHRoaXMgbWluaS1jb3Vyc2UsIHdlIHdpbGwgaGVscCB5b3UgbGVhcm4gdG8gdXNlIG9uZSBvZiB0aGUgbW9zdCBpbnRlcmVzdGluZyAoYW5kIHBvcHVsYXIpIG9mIHRoZXNlIHRvb2xzIC0tIHRoZSBwcm9ncmFtbWluZyBsYW5ndWFnZSBSLiBSIGlzIGEgc3BlY2lhbC1wdXJwb3NlIG9wZW4tc291cmNlIGxhbmd1YWdlIGZvciBzdGF0aXN0aWNzIGFuZCBkYXRhIGFuYWx5c2lzLiBJbmNyZWFzaW5nbHksIFIgaXMgdGhlIHByZWZlcnJlZCB0b29sIGZvciBhbmFseXNpbmcgYW5kIHByZXNlbnRpbmcgZGF0YSBmb3Igc3R1ZGVudCByZXNlYXJjaCBwcm9qZWN0cy4KCkluIHRoaXMgbW9kdWxlLCB3ZSBzaG93IHlvdSBob3cgdG8gZ2V0IHN0YXJ0ZWQgd2l0aCBSLiBXZSB3aWxsIG5vdCBhc3N1bWUgdGhhdCB5b3UgaGF2ZSBhbnkgcHJpb3IgY29tcHV0ZXIgcHJvZ3JhbW1pbmcgZXhwZXJpZW5jZS4gSW4gZmFjdCwgaWYgeW91IGhhdmUgcHJvZ3JhbW1lZCBiZWZvcmUgaW4gYSBsYW5ndWFnZSBsaWtlIEphdmEgb3IgQywgYmUgYXdhcmUgdGhhdCBSIGlzLCBpbiBtYW55IHJlc3BlY3RzLCB2ZXJ5IGRpZmZlcmVudCBmcm9tIHRob3NlIGxhbmd1YWdlcyAtLSBzbyBrZWVwIGFuIG9wZW4gbWluZC4KCldlIHdpbGwgYmVnaW4gYnkgZXhwbGFpbmluZyB0aGUgZGlmZmVyZW50IHNvZnR3YXJlIHRvb2xzIHlvdSBuZWVkLCBhbmQgaG93IHRvIGdldCB0aGVtIG9udG8geW91ciBvd24gY29tcHV0ZXJzLCBpZiB5b3Ugd2lzaCB0byBkbyBzby4gVGhlbiB3ZSB3aWxsIGRpc2N1c3MgdGhlIGJhc2ljIG1lY2hhbmljcyBvZiB0aGVzZSB0b29scy4gVGhyb3VnaG91dCB0aGlzIGhhbmRvdXQgKGFuZCBhbGwgbWF0ZXJpYWxzIGZvciB0aGlzIG1pbmktY291cnNlKSB0aGVyZSBhcmUgY29kZSBleGFtcGxlcyBhbmQgUiBleGVyY2lzZXMgdGhhdCB5b3Ugc2hvdWxkIHdvcmsgdGhyb3VnaCBjYXJlZnVsbHkgb24gdGhlIGNvbXB1dGVyLiBUaGlzIHdpbGwgcHJlcGFyZSB5b3UgdG8gdXNlIFIgZm9yIHlvdXIgaW4tY291cnNlIHJlc2VhcmNoIHByb2plY3RzIGxhdGVyIGluIHRoZSBzZW1lc3Rlci4KClRoaXMgaGFuZG91dCBpcyBkZXNpZ25lZCB0byBiZSByZWFkIGluIGNvbmp1bmN0aW9uIHdpdGggQ2hhcHRlciAxOiBJbnRyb2R1Y3Rpb24gb2YgW1IgZm9yIERhdGEgU2NpZW5jZV0oaHR0cHM6Ly9yNGRzLmhhZC5jby5ueikuCgpcCgpcCgojIyBUaGUgVG9vbHMKCldlIHRoaW5rIG9mIGNvbXB1dGVycyBhcyBzdG9yaW5nIHJpY2ggbWVhbmluZ2Z1bCBkYXRhIChtb3N0bHkgY2F0IHZpZGVvcykuIEFjdHVhbGx5LCB3aGF0IGNvbXB1dGVycyByZWFsbHkgY29udGFpbiBhcmUgbWlsbGlvbnMgb2YgdGlueSBsaXR0bGUgc3RvcmFnZSB1bml0cywgZWFjaCBvZiB3aGljaCBlaXRoZXIgaG9sZHMgYW4gZWxlY3RyaWNhbCBjaGFyZ2UgKHVzdWFsbHkgY2FsbGVkIGEgMSkgb3IgaG9sZHMgbm90aGluZyAodXN1YWxseSBjYWxsZWQgYSAwKS4gUmVhbGx5LiBUaGF0J3MgaXQuIFRoYXQncyBhbGwgdGhlcmUgaXMuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwPSJXaGF0J3MgaW5zaWRlIHRoZSBjb21wdXRlciIsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNTAlIn0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLWNvbXB1dGVyLnBuZyIgKQpgYGAKCkFsbCBvZiB0aGUgYW1hemluZyB0aGluZ3MgdGhhdCBjb21wdXRlcnMgZG8gaGFwcGVuIHRocm91Z2ggZXh0cmVtZWx5IGNvbXBsaWNhdGVkIG1hbmlwdWxhdGlvbiBvZiBhbGwgdGhvc2UgMHMgYW5kIDFzLlRoaXMgaW52b2x2ZXMgYSBsb3Qgb2YgbWF0aHMgYW5kIGEgbG90IG9mIGVsZWN0cm9uaWNzLCBhbmQgaXMgdmVyeSwgdmVyeSBjb25mdXNpbmcuIFNvIHRoYXQgY29tcHV0ZXIgdXNlcnMgZG9uJ3QgaGF2ZSB0byB0aGluayBhYm91dCBhbGwgdGhlc2UgMHMgYW5kIDFzLCBjb21wdXRlciBzY2llbnRpc3RzIGhhdmUgZGV2ZWxvcGVkICoqcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzKiosIHdoaWNoIGFyZSBzeW1ib2xpYyBzeXN0ZW1zIHRoYXQgd2UgY2FuIHVzZSB0byBleHByZXNzIHdoYXQgd2Ugd2FudCB0byBoYXBwZW4gaW5zaWRlIHRoZSBtYWNoaW5lLiBQcm9ncmFtbWluZyBsYW5ndWFnZXMgYXJlIGRlc2lnbmVkIHRvIGJlIHNpbWlsYXIgdG8gaHVtYW4gbGFuZ3VhZ2VzLCBzbyB0aGV5IGFyZSBlYXN5IGZvciB1cyB0byB3b3JrIHdpdGguIE92ZXIgdGhlIGxhc3QgNjAgeWVhcnMgbWFueSBzdWNoIGxhbmd1YWdlcyBoYXZlIGJlZW4gZGV2ZWxvcGVkOiBGT1JUUkFOLCBCQVNJQywgQywgSmF2YSwgUHl0aG9uLCBldGMuLCBhbmQgdGhlIG9uZSB3ZSBhcmUgdXNpbmcgaW4gdGhpcyBtaW5pLWNvdXJzZSwgUi4gRWFjaCBwcm9ncmFtbWluZyBsYW5ndWFnZSBoYXMgYSB2b2NhYnVsYXJ5IGFuZCBhIGdyYW1tYXIgKGp1c3QgbGlrZSBodW1hbiBsYW5ndWFnZXMpIHdoaWNoIG11c3QgYmUgZm9sbG93ZWQgKipleGFjdGx5KiogKHRoZXkgYXJlLCBpbiBmYWN0LCBtdWNoIHN0cmljdGVyIGFib3V0IHRoaXMgdGhhbiBodW1hbiBsYW5ndWFnZXMpLgoKVG8gY29tbXVuaWNhdGUgd2l0aCB5b3VyIGNvbXB1dGVyIHVzaW5nIGEgcHJvZ3JhbSBsYW5ndWFnZSwgeW91IG5lZWQgYSBzcGVjaWFsIGNvbXB1dGVyIHByb2dyYW0gKHByZXZpb3VzbHkgd3JpdHRlbiBpbiBhIHByb2dyYW1taW5nIGxhbmd1YWdlLCBvZiBjb3Vyc2UpIHRoYXQga25vd3MgaG93IHRvIHRyYW5zbGF0ZSBmcm9tIHRoZSBodW1hbi1mcmllbmRseSBwcm9ncmFtbWluZyBsYW5ndWFnZSBpbnRvIGFjdGlvbnMgb24gdGhlIGNvbXB1dGVyLiBUaGVzZSBhcmUgY2FsbGVkICoqRGV2ZWxvcG1lbnQgRW52aXJvbm1lbnRzKiosIGJlY2F1c2UgdGhpcyBpcyB3aGVyZSBwZW9wbGUgZGV2ZWxvcCBzb2Z0d2FyZS4KCmBgYHtyLCBmaWcuY2FwID0gIkFsbCBUaGUgUGFydHMiLCBlY2hvPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iMTAwJSJ9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1sYW5ndWFnZV9pZGVfbWFjaGluZS5wbmciKQpgYGAKClRoZSBtb3N0IHBvcHVsYXIgZGV2ZWxvcG1lbnQgZW52aXJvbm1lbnQgZm9yIFIgaXMgYSBwcm9ncmFtIGNhbGxlZCAqKlJTdHVkaW8qKi4KCkJvdGggUiBhbmQgUlN0dWRpbyBhcmUgaW5zdGFsbGVkIG9uIHRoZSBjb21wdXRlcnMgaW4gdGhlIE90YWdvIFVuaXZlcnNpdHkgY29tcHV0ZXIgbGFicy4gWW91IGNhbiB3b3JrIHRocm91Z2ggdGhpcyBkb2N1bWVudCBvbiB0aG9zZSBtYWNoaW5lcy4KCllvdSBjYW4gYWxzbyBpbnN0YWxsIHRoZSBSIGxhbmd1YWdlIGFuZCB0aGUgUlN0dWRpbyBwcm9ncmFtIG9uIHlvdXIgb3duIHBlcnNvbmFsIGNvbXB1dGVycy4gVGhlc2UgYXJlIGNvbXBsZXRlbHkgb3Blbi1zb3VyY2UsIGZyZWUsIGFuZCBzYWZlLgoKRmlyc3QsIGluc3RhbGwgUiBmcm9tIDxodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy9iaW4vd2luZG93cy9iYXNlLz4gKGZvciBXaW5kb3dzIG1hY2hpbmVzKSBvciA8aHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvYmluL21hY29zeC8+IChmb3IgTWFjIE9TIG1hY2hpbmVzKS4gVGhlbiBpbnN0YWxsIFJTdHVkaW8gZnJvbSA8aHR0cHM6Ly9yc3R1ZGlvLmNvbS9wcm9kdWN0cy9yc3R1ZGlvL2Rvd25sb2FkLz4uIE1vZGVybiBzY2llbnRpc3RzIG5lZWQgdG8gYmUgY29tZm9ydGFibGUgaW5zdGFsbGluZyBzb2Z0d2FyZSBvbiB0aGVpciBvd24gY29tcHV0ZXJzLiBUaGlzIGlzIGEgZ29vZCBvcHBvcnR1bml0eSBmb3IgeW91IHRvIHByYWN0aWNlIHRoaXMgaW1wb3J0YW50IHNraWxsLCBhbmQgd2UgZW5jb3VyYWdlIHlvdSB0byB0cnkgaXQuIElmIHlvdSBuZWVkIGFueSBoZWxwLCBhc2sgdXMuCgpcCgpcCgojIyBIb3cgdG8gVGFsayB0byBhIENvbXB1dGVyCgpXaGVuIHByb2dyYW1taW5nIGEgY29tcHV0ZXIgeW91IG11c3QgYWx3YXlzIHJlbWVtYmVyIG9uZSB2ZXJ5IGltcG9ydGFudCBmYWN0OiBDb21wdXRlcnMgQXJlIFN0dXBpZC4KClJlYWxseS4gVGhlIGNvbXB1dGVyICJ1bmRlcnN0YW5kcyIgb25seSBhIHZlcnkgc21hbGwgYW5kICpzdHJpY3RseSBsaW1pdGVkKiBzZXQgb2YgY29tbWFuZHMgKHRoZSBncmFtbWFyIGFuZCB2b2NhYnVsYXJ5IG9mIGEgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UpLiBJZiB5b3UgZGV2aWF0ZSBmcm9tIHRoaXMgc2V0IG9mIGNvbW1hbmRzICppbiBhbnkgd2F5KiwgdGhlIGNvbXB1dGVyIGNhbm5vdCBmaWd1cmUgb3V0IHdoYXQgeW91IG1lYW4uIEl0IGlzIGJlc3QgdG8gdGhpbmsgb2YgeW91ciBjb21wdXRlciBhcyBhIHdlbGwtbWVhbmluZywgd2VsbC10cmFpbmVkLCBidXQgbm90IHBhcnRpY3VsYXJseSBicmlnaHQgZG9nLiBJdCB3YW50cyB0byBkbyBhcyBpdCBpcyB0b2xkLCBidXQgaWYgeW91IHVzZSBhIGNvbW1hbmQgaXQgZG9lc24ndCBrbm93LCBpdCBjYW4ndCBmaWd1cmUgb3V0IHdoYXQgeW91IGludGVuZC4gQmUgbmljZSB0byB5b3VyIGNvbXB1dGVyIC0tIGRvbid0IGNvbmZ1c2UgaXQuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwID0gIkNvbmZ1c2VkIERvZyIsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLWRvZy5qcGciKQpgYGAKCjwhLS0gSW1hZ2U6IGh0dHBzOi8vaW1nZmxpcC5jb20vbWVtZXRlbXBsYXRlLzExNjIzNTU2OC9jb25mdXNlZC1kb2cgLS0+CgpcCgpcCgojIFVzaW5nIFJTdHVkaW8KClJTdHVkaW8gaXMgYSBwcm9ncmFtIHRoYXQgY2FuIGFjY2VwdCBSIHN0YXRlbWVudHMgYW5kIGNvbnZleSB0aGVtIHRvIHRoZSBtYWNoaW5lLiBJbiBSU3R1ZGlvLCB5b3UgdHlwZSBpbiBhbiBSIGNvbW1hbmQsIGl0IGlzIGV4ZWN1dGVkIGJ5IHRoZSBtYWNoaW5lLCBhbmQgUlN0dWRpbyBjYW4gZGlzcGxheSB0aGUgcmVzdWx0cyBvZiB0aGUgY29tbWFuZCwgaWYgYW55LgoKSW4gdGhlIGZpcnN0IGluc3RhbmNlLCBqdXN0IHRvIG1ha2Ugc3VyZSBSIGFuZCBSU3R1ZGlvIGFyZSB3b3JraW5nIGNvcnJlY3RseSwgd2Ugd2lsbCB0eXBlIGEgZmV3IFIgY29tbWFuZHMgZGlyZWN0bHkgaW50byBSU3R1ZGlvIGFuZCBleGVjdXRlIHRoZW0gaW4gcmVhbCB0aW1lIChzZWUgYmVsb3cpLiBMYXRlciwgd2Ugd2lsbCBzZWUgaG93IHRvIHN0b3JlIGEgc2V0IG9mIFIgY29tbWFuZHMgaW4gYSBmaWxlIHNvIHRoYXQgd2UgY2FuIHJ1biB0aGVtIHJlcGVhdGVkbHkgd2l0aG91dCBoYXZpbmcgdG8gcmV0eXBlLgoKXAoKIyMgUGFydHMgb2YgUlN0dWRpbwoKVGhlIFJTdHVkaW8gaW50ZXJmYWNlIGlzIGRpdmlkZWQgaW50byBzZXBhcmF0ZSAqKnBhbmVzKiouIEFzIHlvdSBiZWNvbWUgbW9yZSBjb21mb3J0YWJsZSB3aXRoIFJTdHVkaW8sIHlvdSBtYXkgd2lzaCB0byByZW9yZ2FuaXNlIHRoZSBsb2NhdGlvbnMgb2YgdGhlIGRpZmZlcmVudCBwYW5lcy4gSW4gaXRzIGRlZmF1bHQgY29uZmlndXJhdGlvbiB3aGVuIGl0IGZpcnN0IG9wZW5zLCBSU3R1ZGlvIHdpbGwgaGF2ZSB0aHJlZSBwYW5lcywgZWFjaCBvZiB3aGljaCBoYXMgbXVsdGlwbGUgdGFicy4gT24gdGhlIGxlZnQgaXMgdGhlIENvbnNvbGUgcGFuZS4gVGhpcyBpcyB3aGVyZSB3ZSB3aWxsIGVudGVyIG91ciBmaXJzdCBSIGNvbW1hbmRzLiBBdCB0aGUgdXBwZXIgcmlnaHQgaXMgdGhlIEVudmlyb25tZW50IHBhbmUuIFRoaXMgaXMgd2hlcmUgd2Ugd2lsbCBzZWUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHN0YXRlIG9mIG91ciBwcm9ncmFtLiBBdCB0aGUgbG93ZXIgcmlnaHQgaXMgdGhlIEZpbGVzIHBhbmUuIEhlcmUgd2UgY2FuIG5hdmlnYXRlIGFtb25nIGZpbGVzIG9uIG91ciBjb21wdXRlci4gQnV0IG1vcmUgdXNlZnVsbHksIHRoZSBGaWxlcyBwYW5lIGNvbnRhaW5zIGEgdGFiIGxhYmVsbGVkIFBsb3RzLiBXZSB3aWxsIHN3aXRjaCB0byB0aGlzIHRhYiB0byBzZWUgZ3JhcGhzIHRoYXQgd2UgZHJhdyB3aXRoIFIuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwID0gIlJTdHVkaW8iLCBlY2hvID0gRkFMU0UsIGZpZy5wb3MgPSAiSCIsIG91dC53aWR0aD0iMTAwJSJ9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1SU3R1ZGlvLnBuZyIpCmBgYAoKIyMjIFVzaW5nIFByb2plY3RzIGluIFJTdHVkaW8KClJTdHVkaW8gcHJvamVjdHMgYXJlIGEgZ3JlYXQgd2F5IG9mIGNvbXBhcnRtZW50YWxpc2luZyBhbmFseXNlcy4gSW4gW1IgZm9yIERhdGEgU2NpZW5jZSAtIFdvcmtmbG93OiBQcm9qZWN0cyAoaHR0cHM6Ly9yNGRzLmhhZC5jby5uei93b3JrZmxvdy1wcm9qZWN0cy5odG1sKV0oaHR0cHM6Ly9yNGRzLmhhZC5jby5uei93b3JrZmxvdy1wcm9qZWN0cy5odG1sKSBjaGFwdGVyIGl0IGRpc2N1c3NlcyBzb21lIGdvb2QgcHJhY3RpY2VzIGFuZCBjb25maWd1cmF0aW9ucyB0byBoZWxwIHlvdSB3b3JrIHdpdGggUlN0dWRpbyBlZmZlY3RpdmVseS4KCkl0IGlzIGhpZ2hseSByZWNvbW1lbmRlZCB0byByZWFkIHRoaXMgY2hhcHRlciBhbmQgaW1wbGVtZW50IHRoZSBzdWdnZXN0ZWQgY29uZmlndXJhdGlvbiBjaGFuZ2VzLgoKXAoKXAoKIyBQYXJ0cyBvZiB0aGUgUiBQcm9ncmFtbWluZyBMYW5ndWFnZQoKUHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzIGhhdmUgYmVlbiBkZXNpZ25lZCB0byBtaW1pYyBodW1hbiBsYW5ndWFnZXMuIFRoZXJlZm9yZSBtb3N0IG9mIHRoZW0gaGF2ZSAqKnRoaW5ncyoqIChsaWtlIG5vdW5zKSBhbmQgKiphY3Rpb25zKiogKGxpa2UgdmVyYnMpLiBQcm9ncmFtbWluZyBpcyBqdXN0IGV4cGxhaW5pbmcgdG8gdGhlIGNvbXB1dGVyIGluIHdheXMgaXQgY2FuIHVuZGVyc3RhbmQsIHdoYXQgKmFjdGlvbnMqIHRvIHBlcmZvcm0gb24gc3BlY2lmaWMgKnRoaW5ncyouIFIgdW5kZXJzdGFuZHMgbWFueSBraW5kcyBvZiB0aGluZ3MgYW5kIG1hbnksIG1hbnkga2luZHMgb2YgYWN0aW9ucy4gV2UgYXJlIGdvaW5nIHRvIHN0YXJ0IHdpdGggdGhlIHZlcnkgc2ltcGxlc3QgY2FzZSwganVzdCB0byBwcmFjdGljZSBpbnRlcmFjdGluZyB3aXRoIFJTdHVkaW8gKGkuZS4sIGdpdmluZyBpdCBSIGNvbW1hbmRzIHRvIGNvbnZleSB0byB0aGUgY29tcHV0ZXIgZm9yIHVzKS4KClwKCiMjIE51bWJlcnMgYW5kIG1hdGhlbWF0aWNhbCBvcGVyYXRvcnMKClIgdW5kZXJzdGFuZHMgbnVtYmVycyAodGhpbmdzIGxpa2UgOCBhbmQgMy4xNDE1OSkgYW5kIG1hdGhlbWF0aWNhbCBvcGVyYXRvcnMgKGFjdGlvbnMgbGlrZSArIGFuZCAtKS4gV2Ugd2lsbCB0eXBlIHNvbWUgbnVtYmVycyBhbmQgbWF0aGVtYXRpY2FsIG9wZXJhdG9ycyBpbnRvIFJTdHVkaW8gYW5kIHNlZSBob3cgdGhlIGNvbXB1dGVyIHJlc3BvbmRzLgoKXAoKIyMjIENvZGUtYWxvbmcgRXhlcmNpc2UKCjEuICBMYXVuY2ggUlN0dWRpby4gSWYgeW91IGhhdmUgaW5zdGFsbGVkIFIgYW5kIFJTdHVkaW8gb24geW91ciBvd24gbWFjaGluZSwgeW91IHNob3VsZCBoYXZlIGEgRGVza3RvcCAoV2luZG93cykgb3IgRG9jayAoTWFjIE9TKSBpY29uIHRoYXQgeW91IGNhbiBjbGljayB0byBsYXVuY2ggUlN0dWRpby4gSWYgbm90LCBzZWFyY2ggdGhyb3VnaCB0aGUgUHJvZ3JhbXMgc3RhcnQtdXAgbWVudSAoV2luZG93cykgb3IgQXBwbGljYXRpb25zIChNYWMgT1MpLiBVc2VycyBvZiB0aGUgVmlydHVhbCBTdHVkZW50IERlc2t0b3AgZm9sbG93IDxodHRwczovL2Jsb2dzLm90YWdvLmFjLm56L3N0dWRlbnRpdC9zdHVkZW50LWRlc2t0b3Avc3R1ZGVudC1kZXNrdG9wLW93bi1kZXZpY2UvPiBmb3IgaG93IHRvIGFjY2VzcyBpdCBmcm9tIHlvdXIgY29tcHV0ZXIuCgoyLiAgVGhlIENvbnNvbGUgcGFuZSBvbiB0aGUgbGVmdCB3aWxsIGNvbnRhaW4gc29tZSBleHBsYW5hdG9yeSB0ZXh0LiBBdCB0aGUgYm90dG9tIG9mIHRoZSB0ZXh0IGlzIGEgcmlnaHQgYW5nbGUgYnJhY2tldCAqKlw+KiouIFRoYXQgaXMgd2hlcmUgeW91IHdpbGwgYmVnaW4gdHlwaW5nLiBUaGVyZSB3aWxsIGJlIGEgc21hbGwsIGZsYXNoaW5nLCB2ZXJ0aWNhbCBsaW5lIGJlc2lkZSB0aGUgYW5nbGUgYnJhY2tldC4gKElmIHlvdSBkb24ndCBoYXZlIHRoZSBmbGFzaGluZyB2ZXJ0aWNhbCBsaW5lLCBjbGljayB5b3VyIG1vdXNlIGJlc2lkZSBhbmQgc2xpZ2h0bHkgdG8gdGhlIHJpZ2h0IG9mIHRoZSBhbmdsZSBicmFja2V0LikKCjMuICBUeXBlIHRoZSBmb2xsb3dpbmcgY2hhcmFjdGVycyBpbnRvIHRoZSBDb25zb2xlIHBhbmUsIGZvbGxvd2VkIGJ5IHRoZSA8a2JkPkVudGVyPC9rYmQ+IGtleS4KClteMV06IAoKKio0ICsgNSoqCgpJZiBldmVyeXRoaW5nIGlzIHdvcmtpbmcgYXMgaXQgc2hvdWxkLCB5b3VyIHNjcmVlbiBzaG91bGQgbG9vayBsaWtlIHRoaXMgKHRoZSBjb250ZW50cyBvZiB0aGUgRmlsZXMgcGFuZSBtYXkgYmUgZGlmZmVyZW50KToKCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0gIjEwMCUiLCBmaWcucG9zPSJIIiwgZmlnLmNhcCA9ICJGaXJzdCBSIENvbW1hbmQiLCBlY2hvID0gRkFMU0V9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1maXJzdF9jb21tYW5kLnBuZyIpCmBgYAoKWW91IGhhdmUgZ2l2ZW4gUiB0d28gKip0aGluZ3MqKjogdGhlIG51bWJlciA0IGFuZCB0aGUgbnVtYmVyIDUuIFlvdSBoYXZlIGFza2VkIFIgdG8gcGVyZm9ybSBhbiAqKmFjdGlvbioqIG9uIHRob3NlIHRoaW5nczogYWRkaXRpb24uIFIgaGFzIGRvbmUgc28sIGFuZCBSU3R1ZGlvIGhhcyBkaXNwbGF5ZWQgdGhlIHJlc3VsdCAoaW4gdGhpcyBjYXNlLCB0aGUgdmFsdWUgOSkuIEl0IGhhcyBhbHNvIHByaW50ZWQgWzFdIG9uIHRoZSBjb25zb2xlIHNjcmVlbi4gVGhpcyBpcyBSU3R1ZGlvIHRyeWluZyB0byBoZWxwIHlvdS4gQXMgeW91ciBSIGNvbW1hbmRzIGJlY29tZSBtb3JlIGNvbXBsaWNhdGVkLCB5b3Ugd2lsbCBlbmQgdXAgd2l0aCBtYW55IHJlc3VsdHMgcmF0aGVyIHRoYW4ganVzdCBvbmUuIFJTdHVkaW8gcHJpbnRzIHRoZXNlIG51bWJlcnMgYXQgdGhlIHN0YXJ0IG9mIG91dHB1dCBsaW5lcyB0byBoZWxwIHlvdSBjb3VudCB5b3VyIHJlc3VsdHMuIEl0J3Mgbm90IHJlYWxseSBuZWNlc3Nhcnkgd2hlbiB5b3Ugb25seSBoYXZlIG9uZSByZXN1bHQsIGJ1dCB0aGF0J3MganVzdCBob3cgUlN0dWRpbyBiZWhhdmVzICh3ZSByZWZlciB5b3UgYWdhaW4gdG8gdGhlIHBpY3R1cmUgb2YgdGhlIHdlbGwtbWVhbmluZyBkb2dnbyBhYm92ZSkuCgpGb3IgdGhlIHJlbWFpbmRlciBvZiB0aGlzIGRvY3VtZW50LCB3ZSB3aWxsIG5vdCBzaG93IHlvdSBwaWN0dXJlcyBvZiB0aGUgd2hvbGUgc2NyZWVuIGVhY2ggdGltZSB3ZSBlbnRlciBhbiBSIGNvbW1hbmQuIFJhdGhlciwgd2Ugd2lsbCBkaXNwbGF5IHdoYXQgeW91IHNob3VsZCB0eXBlIGFuZCB3aGF0IG91dHB1dCB5b3Ugc2hvdWxkIGdldCBsaWtlIHRoaXM6CgpgYGB7ciBmaXJzdF9jb21tYW5kfQo0ICsgNQpgYGAKCjQuICBFeHBsb3JlIG1vcmUgb2YgUidzIG1hdGhlbWF0aWNhbCBvcGVyYXRvcnMuIEZvciBkaXZpc2lvbiB1c2UgLyBhbmQgZm9yIG11bHRpcGxpY2F0aW9uIHVzZSBcKi4gRW50ZXIgZWFjaCBvZiB0aGVzZSBSIGNvbW1hbmRzIGludG8gdGhlIGNvbnNvbGUgYW5kIGNvbmZpcm0gdGhhdCB5b3UgcmVjZWl2ZSB0aGUgZXhwZWN0ZWQgb3V0cHV0LgoKYGBge3IgbW9yZSBtYXRocywgZXZhbCA9IEZBTFNFfQoxMCAvIDgKCjggKiAxMgoKNiAtIDEyICsgKDMgKiA3LjQpCmBgYAoKXAoKIyMgTW9yZSBhY3Rpb25zOiBGdW5jdGlvbiBjYWxscyBpbiBSCgpSIHN5bnRheCAoZ3JhbW1hcikgbWltaWNzIG1hdGhlbWF0aWNhbCBlcXVhdGlvbiBzeW50YXggaW4gc29tZSByZXNwZWN0cy4gQXMgd2UgZGVub3RlIGEgZnVuY3Rpb24gZih4KSB1c2luZyByb3VuZCBicmFja2V0cyBpbiBhbiBlcXVhdGlvbiwgc28gZG8gd2UgZGVub3RlIHRoZSBhcHBsaWNhdGlvbiBvZiBhIGZ1bmN0aW9uIGluIFIuIFIga25vd3MgbWFueSB1c2VmdWwgZnVuY3Rpb25zLiBGb3IgZXhhbXBsZSBgc3FydCgpYCAsIHdoaWNoIGNvbXB1dGVzIHRoZSBzcXVhcmUgcm9vdCBvZiBhIG51bWJlciwgYW5kIGBhYnMoKWAgd2hpY2ggY29tcHV0ZXMgdGhlIGFic29sdXRlIHZhbHVlIG9mIGEgbnVtYmVyLiBUbyBhcHBseSBvbmUgb2YgdGhlc2UgZnVuY3Rpb25zLCB3ZSB0eXBlIHRoZSBuYW1lLCBhbmQgcGxhY2UgdGhlIHZhbHVlIHdlIHdpc2ggdG8gb3BlcmF0ZSBvbiAqKih0aGUgYXJndW1lbnQpKiogaW5zaWRlIHRoZSByb3VuZCBicmFja2V0cy4KCiMjIyBDb2RlLWFsb25nIEV4ZXJjaXNlCgpUcnkgdGhlc2UgZXhhbXBsZXM6CgpgYGB7ciBhcHBseWluZyBmdW5jdGlvbnN9CmFicygtNDIpCgpzcXJ0KDIwMCkKCmBgYAoKIyMgR2V0dGluZyBIZWxwCgpPZnRlbiB5b3UnbGwgbmVlZCBoZWxwIGZvciBhIHNwZWNpZmljIGZ1bmN0aW9uLCBzdWNoIGFzIGBtZWFuKClgLCB5b3UgY2FuIHNlYXJjaCB0aGUgaGVscCBkb2N1bWVudGF0aW9uIHVzaW5nIGA/YCBpbiBmcm9udCBvZiB0aGUgZnVuY3Rpb24gbmFtZSB0byBkbyB0aGlzIChlLmcuIGA/bWVhbmApIGFuZCB0aGlzIHdpbGwgYnJpbmcgdXAgdGhlIG1hbnVhbCBwYWdlLiBJdCBwcm92aWRlcyBpbmZvcm1hdGlvbiBhYm91dCB3aGF0IGRvZXMsIHdoYXQgdGhlIGFyZ3VtZW50cyBhcmUsIGFuZCBldmVuIHByb3ZpZGVzIHNvbWUgZXhhbXBsZXMgdGhhdCBjYW4gYmUgY29weS1wYXN0ZWQgYW5kIHJ1biB0byBnaXZlIGFuIGV4YW1wbGUgb2Ygd2hhdCBpdCBkb2VzLgoKVGhlIGA/YCBpcyBub3QgdGhlIG9ubHkgd2F5IHRvIGZpbmQgb3V0IGhvdyB0byBydW4gYSBmdW5jdGlvbiAtLSBmb3IgbW9yZSBleGFtcGxlcyBvZiBob3cgdG8gZmluZCBoZWxwIHJlZmVyIHRvIDxodHRwczovL2RhdGFjYXJwZW50cnkub3JnL1ItZWNvbG9neS1sZXNzb24vMDAtYmVmb3JlLXdlLXN0YXJ0Lmh0bWwjU2Vla2luZ19oZWxwPgoKClwKCiMjIE1vcmUgdGhpbmdzOiBXb3JkcwoKTG90cyBvZiBjb21wdXRpbmcgaW52b2x2ZXMgd29yZHMgcmF0aGVyIHRoYW4gbnVtYmVycy4gRm9yIGV4YW1wbGUsIHNlYXJjaGluZyB0ZXh0IGFuZCBlbnJvbGxpbmcgc3R1ZGVudHMgYnkgbmFtZSBib3RoIG9wZXJhdGUgb24gd29yZHMuIFIgdW5kZXJzdGFuZHMgd29yZHMgLS0gdGhlIGNvbmNlcHQgb2YgKip0aGluZ3MgY29tcG9zZWQgb2YgbGV0dGVycyoqLiBIb3dldmVyLCB3aGVuIHdvcmtpbmcgd2l0aCB3b3Jkcywgd2UgbXVzdCBtYXJrIHRoZW0gd2l0aCBzcGVjaWFsIGNoYXJhY3RlcnMgdG8gcHJldmVudCBSIGZyb20gYmVjb21pbmcgY29uZnVzZWQgKHdlIHNlZSB3aGF0IHRoaXMgY29uZnVzaW9uIGxvb2tzIGxpa2UgaW4gYSBtb21lbnQpLgoKSW4gcHJvZ3JhbW1pbmcsIGEgdGhpbmcgY29tcG9zZWQgb2YgbGV0dGVycyBkb2Vzbid0IGhhdmUgdG8gYmUgYSByZWFsIHdvcmQgKGl0IGNvdWxkIGJlLCBmb3IgZXhhbXBsZSwgYSBwcm9kdWN0IGNvZGUgb3IgdXNlciBpZCksIHNvIHdlIGFjdHVhbGx5IGNhbGwgdGhlbSAqKnN0cmluZ3MqKi4gVG8gZGVub3RlIGEgKipzdHJpbmcqKiB3ZSBzdXJyb3VuZCBpdCB3aXRoIHF1b3RlIG1hcmtzLCBsaWtlIHRoaXM6CgpgYGB7ciBzdHJpbmdzMDF9CiJwbGF0byIKYGBgCgpUaGVyZSBhcmUgZnVuY3Rpb25zIHRoYXQgb3BlcmF0ZSBvbiBzdHJpbmdzLCBleGFjdGx5IGVxdWl2YWxlbnQgdG8gb25lcyBsaWtlIGBzcXJ0KClgIHRoYXQgb3BlcmF0ZSBvbiBudW1iZXJzLiBGb3IgZXhhbXBsZSwgUiBoYXMgYSBmdW5jdGlvbiBgbmNoYXIoKWAgdGhhdCBjb21wdXRlcyBob3cgbWFueSBjaGFyYWN0ZXJzIChpLmUuIGxldHRlcnMpIGFyZSBpbiBpdHMgc3RyaW5nIGFyZ3VtZW50LgoKYGBge3Igc3RyaW5nczAyfQpuY2hhcigicGxhdG8iKQpgYGAKClwKCiMjIyBDb2RlLWFsb25nIEV4ZXJjaXNlCgpXaGF0IGRvIHlvdSB0aGluayB3aWxsIGhhcHBlbiBpZiB5b3UgZ2l2ZSB0aGUgY29tbWFuZHMgYmVsb3c/IEVudGVyIHRoZW0gaW50byB0aGUgUlN0dWRpbyBjb25zb2xlIHRvIHNlZS4KCmBgYHtyIHN0cmluZ3MwMywgZXJyb3I9VFJVRX0KCm5raGFyKCJwbGF0byIpCgpzcXJ0KCJwbGF0byIpCmBgYAoKUmVtZW1iZXIgdGhhdCB0aGUgbGFuZ3VhZ2UgUiBpcyBhIHNldCBvZiB2b2NhYnVsYXJ5IGFuZCBncmFtbWFyIHJ1bGVzIHRoYXQgbXVzdCBiZSBmb2xsb3dlZCAqdmVyeSogc3RyaWN0bHkuIFRoZXJlIGlzIG5vIGZ1bmN0aW9uIGBua2hhcmAgaW4gUidzIHZvY2FidWxhcnksIG9ubHkgYG5jaGFyYC4gQW5kIGZ1bmN0aW9uIGBzcXJ0YCBvbmx5IHVuZGVyc3RhbmRzIGhvdyB0byB3b3JrIG9uIG51bWJlcnMsIG5vdCBvbiBzdHJpbmdzLgoKUiB3aWxsICoqbmV2ZXIqKiB3b3JrIG91dCB3aGF0IHlvdSBtZWFudCB3aGVuIHlvdSBkZXZpYXRlIGZyb20gaXRzIGdyYW1tYXIuIE5vIHByb2dyYW1taW5nIGxhbmd1YWdlIHdpbGwuIElmIHlvdSB2aW9sYXRlIGl0cyBydWxlcywgUiB3aWxsIHRocm93IGFuIGVycm9yLiBCdXQgdGhpcyBjYW4gYmUgdmVyeSBpbnN0cnVjdGl2ZS4gRW50ZXIgdGhlIGZvbGxvd2luZyBjb21tYW5kIGludG8gUlN0dWRpbyBhbmQgY2FyZWZ1bGx5IGNvbnNpZGVyIHRoZSBvdXRjb21lLiBXaGF0IGRvZXMgdGhpcyB0ZWxsIHlvdSBhYm91dCB0aGUgcnVsZXMgb2YgdGhlIFIgbGFuZ3VhZ2U/CgpgYGB7ciBjYXNlLCBlcnJvcj1UUlVFfQpOQ0hBUigicGxhdG8iKQpgYGAKCldlIGtub3cgdGhhdCBSIHVuZGVyc3RhbmRzIHRoZSBmdW5jdGlvbiBgbmNoYXJgIC0tIHdlIHNhdyBpdCB3b3JraW5nIGp1c3QgYSBmZXcgbW9tZW50cyBhZ28uIEJ1dCBub3cgaXQgc2F5cyBpdCBjb3VsZCBub3QgZmluZCB0aGF0IGZ1bmN0aW9uPyBUaGlzIGlzIGJlY2F1c2UsIHRvIFIsIGBuY2hhcmAgYW5kIGBOQ0hBUmAgYXJlIG5vdCB0aGUgc2FtZSB0aGluZy4gUiBpcyBhICoqY2FzZS1zZW5zaXRpdmUqKiBsYW5ndWFnZS4gVXBwZXItY2FzZSBhbmQgbG93ZXItY2FzZSBsZXR0ZXJzIGFyZSBjb21wbGV0ZWx5IGRpZmZlcmVudCBlbnRpdGllcyBpbiBSLiBXaGVuIGdpdmluZyBSIGNvbW1hbmRzIHlvdSBtdXN0IGFsd2F5cyBleGFjdGx5IG1hdGNoIGl0cyBleHBlY3RhdGlvbnMgYWJvdXQgdXBwZXIgYW5kIGxvd2VyIGNhc2UgKHdvb2YpLgoKXAoKIyMgU3RvcmluZyBSZXN1bHRzCgpJbWFnaW5lIHRoYXQgeW91IGhhdmUgdHdvIGxhcmdlIG51bWJlcnMgYW5kLCBmb3Igc29tZSBzb3VuZCBzY2llbnRpZmljIHJlYXNvbiwgeW91IHdpc2ggdG8gdGFrZSB0aGVpciByYXRpbyBhbmQgdGhlbiB0YWtlIHRoZSBzcXVhcmUgcm9vdCBvZiB0aGF0IHZhbHVlLiBMaWtlIHRoaXM6CgpgYGB7ciBzYXZpbmcgcmVzdWx0cyAwMX0KMTk4LjcgLyA2NC41CmBgYAoKYGBge3Igc2F2aW5nIHJlc3VsdHMgMDJ9CnNxcnQoMy4wODA2MikKYGBgCgpUaGlzIG9wZXJhdGlvbiBpcyByaXNreS4gUiBoYXMgZ2l2ZW4geW91IHRoZSByYXRpbyB0byBmaXZlIGFjY3VyYXRlIGRlY2ltYWwgcGxhY2VzLiBCdXQgeW91IG11c3QgdGhlbiBiZSAqdmVyeSBjYXJlZnVsKiB0byBjb3B5IGl0IGV4YWN0bHkgaW50byB0aGUgYHNxcnRgIGZ1bmN0aW9uLCBvciB5b3VyIGFuc3dlciB3aWxsIGJlIHdyb25nLiBFeHRyYXBvbGF0ZSB0aGlzIHRvIHRob3VzYW5kcyBvZiBkYXRhIG9wZXJhdGlvbnMgb24gYSBsYXJnZSBkYXRhIHNldCBhbmQgaXQgaXMgY2VydGFpbiB0aGF0IGVycm9ycyB3aWxsIGJlIG1hZGUuCgpJdCB3b3VsZCBiZSBtb3JlIGNvbnZlbmllbnQsIGFuZCBzYWZlciwgdG8gdGFrZSB0aGUgcmVzdWx0IFIgZ2F2ZSB5b3UgZnJvbSB0aGUgZmlyc3Qgc3RhdGVtZW50LCAqc3RvcmUgaXQgc29tZXdoZXJlLCBhbmQgdGhlbiBwYXNzIHRoZSBzdG9yZWQgZW50aXR5IHRvIGZ1bmN0aW9uIHNxcnQqLiBUaGlzIGlzLCBpbiBmYWN0LCBhIGZ1bmRhbWVudGFsIGFjdGlvbiBpbiBwcm9ncmFtbWluZzogKipXZSBjYW4gc3RvcmUgdmFsdWVzIGFzIG5hbWVkIGVudGl0aWVzIChjYWxsZWQgdmFyaWFibGVzKSBhbmQgdXNlIHRoZW0gd2hlbmV2ZXIgYW5kIHdoZXJldmVyIHdlIG5lZWQgdGhlbS4qKgoKSW4gUiwgdGhpcyAic3RvcmluZyIgaXMgcGVyZm9ybWVkIHdpdGggdGhlICoqXDwtIG9wZXJhdG9yKiogKGNhbGxlZCB0aGUgImFzc2lnbm1lbnQiIG9wZXJhdG9yKS4gVGhlIGFzc2lnbm1lbnQgb3BlcmF0b3IgaXMgZm9ybWVkIGJ5IHR5cGluZyBhIGxlZnQgYW5nbGUgYnJhY2tldCBhbmQgYSBoeXBoZW4uIEluIHRoZSBmb2xsb3dpbmcgY29kZSBleGFtcGxlLCB3ZSBkZW1vbnN0cmF0ZSB0aGUgYXNzaWdubWVudCBvcGVyYXRvci4gV2UgYWxzbyBkZW1vbnN0cmF0ZSAqKmNvbW1lbnRzKiouIEluIFIsIGFueSB0ZXh0IHRoYXQgaXMgcHJlZmFjZWQgd2l0aCBcIyBpcyBpZ25vcmVkIHJhdGhlciB0aGFuIGJlaW5nIHRyZWF0ZWQgYXMgYSBjb21tYW5kLiBJdCBpcyBqdXN0IHRleHQgdGhhdCB0aGUgcHJvZ3JhbW1lciBhZGRzIGZvciB0aGVpciBvd24gYmVuZWZpdC4KClwKCiMjIyBDb2RlLWFsb25nIEV4ZXJjaXNlCgpNYWtlIHN1cmUgeW91IGNhbiBkdXBsaWNhdGUgdGhpcyBjb2RlLCB3aXRoIHRoZSBzYW1lIHJlc3VsdHMsIGluIFJTdHVkaW8gKHlvdSBkb24ndCBuZWVkIHRvIHR5cGUgdGhlIGNvbW1lbnRzKS4KCmBgYHtyIHZhcmlhYmxlczAxfQojIFN0b3JlIHRoZSByZXN1bHQgb2YgdGhlIGRpdmlzaW9uIGluIGFuIGVudGl0eSAoYSB2YXJpYWJsZSkgbmFtZWQgcmF0aW8uIFdlCiMgYWx3YXlzIHVzZSBtZWFuaW5nZnVsIHZhcmlhYmxlIG5hbWVzLgpyYXRpbyA8LSAxOTguNyAvIDY0LjUgIAoKIyBUaGlzIHdpbGwgZGlzcGxheSB0aGUgdmFsdWUgb2YgdGhlIHZhcmlhYmxlIG5hbWVkIHJhdGlvLiBUaGF0J3Mgd2hhdCBSIGRvZXMKIyB3aGVuIHlvdSBlbnRlciBhIGxvbmUgdmFyaWFibGUgbmFtZS4KcmF0aW8gCgojIFRoaXMgd2lsbCBwYXNzIHRoZSB2YWx1ZSBvZiByYXRpbyBhcyB0aGUgYXJndW1lbnQgdG8gdGhlIHNxcnQgZnVuY3Rpb24uCnNxcnQocmF0aW8pICAKYGBgCgpcCgojIyBWYXJpYWJsZSBOYW1lcyBhbmQgVmFsdWVzCgpMb29rICoqdmVyeSBjYXJlZnVsbHkqKiBhdCB0aGUgdmFyaWFibGUgbmFtZSBvbiB0aGUgbGVmdCBoYW5kIHNpZGUgb2YgdGhlIGFzc2lnbm1lbnQgb3BlcmF0b3IgXDwtLiBJdCBpcyBhIHN0cmluZyBvZiBjaGFyYWN0ZXJzLCBidXQgKippdCBpcyBub3Qgc3Vycm91bmRlZCBieSBxdW90ZSBtYXJrcyoqLiBUaGlzIGlzIGhvdywgaW4gUiwgd2UgZGlzdGluZ3Vpc2ggc3RyaW5ncyAoYSB3b3JkIHRoaW5nIC0tIHJlbWVtYmVyLCBsaWtlICJwbGF0byIpIGZyb20gdmFyaWFibGUgbmFtZXMuCgpJbnNpZGUgb3VyIGNvbXB1dGVyLCB2YXJpYWJsZXMgYXJlIGltcGxlbWVudGVkIChjb25jZXB0dWFsbHkpIGFzIHNob3duIGJlbG93LiBBIGxvY2F0aW9uIGluIG1lbW9yeSBpcyAibmFtZWQiLiBXaGVuIHlvdSByZWZlciB0byB0aGUgbmFtZSwgdGhlIGNvbXB1dGVyIHN1cHBsaWVzIHdoYXRldmVyIHZhbHVlIGlzIHN0b3JlZCBhdCB0aGF0IGxvY2F0aW9uLgoKYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI1MCUiLCBmaWcuY2FwPSJIb3cgVmFyaWFibGVzIFdvcmsiLCBlY2hvID0gRkFMU0V9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1jb21wdXRlcl93aXRoX3ZhcmlhYmxlLnBuZyIpCmBgYAoKVGhpcyBtZWFucyB0aGF0IHRoZSB2YWx1ZSBvZiBhIHZhcmlhYmxlIGNhbiBjaGFuZ2Ugb3ZlciB0aW1lLiAoV2Ugd2lsbCBzZWUgbGF0ZXIgdGhhdCB0aGlzIHR1cm5zIG91dCB0byBiZSBleHRyZW1lbHkgdXNlZnVsLikKCmBgYHtyIHZhcmlhYmxlczAyfQojIFN0b3JlIHRoZSByZXN1bHQgb2YgdGhlIGRpdmlzaW9uIGluIGFuIGVudGl0eSBuYW1lZCByYXRpbwpyYXRpbyA8LSAxOTguNyAvIDY0LjUgIAoKIyBUaGlzIHdpbGwgZGlzcGxheSB0aGUgdmFsdWUgb2YgcmF0aW8uIFRoYXQncyB3aGF0IFIgZG9lcyB3aGVuIHlvdSBlbnRlciBhIGxvbmUKIyB2YXJpYWJsZSBuYW1lLgpyYXRpbyAgICAgICAgICAgICAgICAgIAoKIyBDaGFuZ2UgdGhlIHZhbHVlIHN0b3JlZCBpbiB0aGUgdmFyaWFibGUgbmFtZWQgcmF0aW8gYnkgYXNzaWduaW5nIGl0IHRoZSByZXN1bHQKIyBvZiBhIG5ldyBjb21tYW5kCnJhdGlvIDwtIDI1LjkgKiAxMi4xNSAgCgojIFNlZSB0aGUgY3VycmVudCB2YWx1ZQpyYXRpbyAgICAgICAgICAgICAgICAgIAoKYGBgCgpcCgojIyBDb21wbGV4IFRoaW5ncwoKT25lIG9mIHRoZSBncmVhdCBzdHJlbmd0aHMgb2YgUiBmb3IgZGF0YSBhbmFseXNpcyBpcyB0aGF0ICJ0aGluZ3MiIGluIFIgYXJlbid0IHJlc3RyaWN0ZWQgdG8gc2luZ2xlIG51bWJlcnMgb3Igc2luZ2xlIHN0cmluZ3MuIFRoaW5ncyBpbiBSIGNhbiBiZSAqKmNvbGxlY3Rpb25zKiogLS0gb3JkZXJlZCBzZXRzIG9mIG11bHRpcGxlIHRoaW5ncy4KClRvIGdldCBhIGNvbGxlY3Rpb24sIHdlIG11c3QgY3JlYXRlIGl0LCB1c2luZyB0aGUgYnVpbHQtaW4gZnVuY3Rpb24gYGMoKWAuIFRoZSBjIHN0YW5kcyBmb3IgKipjb21iaW5lKiouIFRoaXMgZnVuY3Rpb24gY29tYmluZXMgbXVsdGlwbGUgYXJndW1lbnRzIGludG8gYSBzaW5nbGUgY29sbGVjdGlvbiB0aGluZy4gSW4gUiB0aGlzIGtpbmQgb2YgY29sbGVjdGlvbiB0aGluZyBpcyBjYWxsZWQgYSAqKnZlY3RvcioqLgoKXAoKIyMjIENvZGUtYWxvbmcgRXhlcmNpc2UKCkVudGVyIHRoZXNlIHN0YXRlbWVudHMgaW50byBSU3R1ZGlvLCBhbmQgY2hlY2sgdGhhdCB5b3UgZ2V0IHRoZSBzYW1lIG91dHB1dC4KCmBgYHtyIHZlY3RvcnMsIGVycm9yID0gVFJVRX0KCiMgVG8gY29tYmluZSBlbGVtZW50cyBpbnRvIGEgdmVjdG9yLCBwYXNzIHRoZW0gdG8gZnVuY3Rpb24gYygpLCBhbmQgc2VwYXJhdGUKIyB0aGVtIHdpdGggY29tbWFzCnZlY3Rvcl9vZl9wcmltZXMgPC0gYygxLCA1LCA3LCAxMSkKCnZlY3Rvcl9vZl9wcmltZXMKCmFuaW1hbHMgPC0gYygiQXJtYWRpbGxvIiwgIkJ1ZmZhbG8iLCAiQ291Z2FyIikKCmFuaW1hbHMKCm1peHR1cmUgPC0gYygxLCAiQnVmZmFsbyIsIDQyKQoKbWl4dHVyZQpgYGAKCkxvb2sgdmVyeSBjYXJlZnVsbHkgYXQgdGhlIHRoaXJkIHZlY3RvciB2YXJpYWJsZSwgbWl4dHVyZS4gTm90ZSB0aGF0LCB3aGVuIGl0IGRpc3BsYXlzIHRoZSB2ZWN0b3IsIFIgaGFzIHB1dCBxdW90ZSBtYXJrcyBhcm91bmQgMSBhbmQgNDIuIFRoYXQgaXMsIFIgdGhpbmtzIHRoZXkgYXJlIHN0cmluZ3MgKGEgc2VyaWVzIG9mIGFscGhhbnVtZXJpYyBjaGFyYWN0ZXJzKSwgbm90IG51bWJlcnMuIEZyb20gdGhpcyB3ZSBzZWUgdGhhdDoKCjEuICBWZWN0b3JzIG11c3QgYmUgaG9tb2dlbmVvdXMuIFRoYXQgaXMsIGFsbCB0aGUgZWxlbWVudHMgaW4gdGhlIHZlY3RvciBtdXN0IGJlIHRoZSBzYW1lIGtpbmQgKHR5cGUpIG9mIHRoaW5nLgoKMi4gIElmIHlvdSBkb24ndCBmb2xsb3cgUidzIHJ1bGVzLCBpdCB3aWxsIHNvbWV0aW1lcyBqdXN0IGVuZm9yY2UgdGhlbSBvbiB5b3VyIGJlaGFsZi4gSGVyZSBpdCBzZWVzIHRoYXQgQnVmZmFsbyBpcyBkZWZpbml0ZWx5IGEgc3RyaW5nLiBJdCBrbm93cyB0aGF0IHZlY3RvciBlbGVtZW50cyBoYXZlIHRvIGJlIGhvbW9nZW5lb3VzLCBzbyBpdCBtYWtlcyAxIGFuZCA0MiBpbnRvIHN0cmluZ3MgIjEiIGFuZCAiNDIiLiBSIGlzIGJvc3N5IHRoaXMgd2F5LgoKKFRoZXJlIGFyZSBtb3JlIGNvbXBsZXggdGhpbmdzIGluIFIgdGhhdCBhbGxvdyBjb21iaW5hdGlvbnMgb2YgbnVtYmVycyBhbmQgc3RyaW5ncy4gR29vZ2xlICJSIGxpc3RzIiB0byBleHBsb3JlLikKCiMjIE9wZXJhdGluZyBvbiBWZWN0b3JzCgpUaGUgb3BlcmF0b3JzIGFuZCBmdW5jdGlvbnMgd2UgaGF2ZSB1c2VkIHNvIGZhciBvbiBzaW5nbGUgbnVtYmVycyBhbmQgc3RyaW5ncyAoZS5nLiBgc3FydGAsIGBuY2hhcmApIHdpbGwgYWxzbyB3b3JrIG9uIHZlY3RvcnMuIFdoZW4geW91IHVzZSB0aGlzIGtpbmQgb2YgZnVuY3Rpb24gb3Igb3BlcmF0b3Igd2l0aCBhIHZlY3RvciwgUiBhcHBsaWVzIGl0IHRvIGVhY2ggZWxlbWVudCBpbiB0dXJuLCBhbmQgcmV0dXJucyBhbGwgdGhlIHJlc3VsdHMuCgpcCgojIyMgQ29kZS1hbG9uZyBFeGVyY2lzZQoKRW50ZXIgdGhlc2Ugc3RhdGVtZW50cyBpbnRvIFJTdHVkaW8uCgpgYGB7ciB2ZWN0b3Igb3BlcmF0aW9uc30KcHJpbWVzIDwtIGMoMSwgNSwgNywgMTEpCgpwcmltZXMgKiAyCgpzcXJ0KHByaW1lcykKYGBgCgpcCgojIyMgV3JpdGUgWW91ciBPd24gQ29kZQoKRW50ZXIgYSBuZXcgY29tbWFuZCB0byBkaXZpZGUgYWxsIHRoZSB2YWx1ZXMgaW4gdmVjdG9yICoqcHJpbWVzKiogYnkgMi4gTWFrZSBzdXJlIHlvdSBnZXQgdGhlc2UgcmVzdWx0czoKCmBgYHtyIHZlY3RvciAyLCBlY2hvID0gRkFMU0V9CnByaW1lcy8yCmBgYAoKTm90ZSB0aGF0IHZlY3RvciBvcGVyYXRpb25zIHdvcmsgcmVnYXJkbGVzcyBvZiB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIGluIHRoZSB2ZWN0b3IuIFlvdSBjYW4gaGF2ZSAxLDAwMCwwMDAgZGF0YSB2YWx1ZXMgaW4geW91ciB2ZWN0b3IgYW5kIGl0IHN0aWxsIHJlcXVpcmVzIG9ubHkgb25lIGNvbW1hbmQgdG8gcHJvY2VzcyB0aGVtIGFsbC4KClwKCiMjIFdob2xlLVZlY3RvciBPcGVyYXRpb25zCgpUaGVyZSBhcmUgYWxzbyBmdW5jdGlvbnMgd2hpY2ggc3VtbWFyaXNlIHRoZSBjb250ZW50cyBvZiBhIHZlY3Rvci4gRm9yIGV4YW1wbGUsIFIgaGFzIGEgZnVuY3Rpb24gYG1lYW5gIHRoYXQgY29tcHV0ZXMgdGhlIG1hdGhlbWF0aWNhbCBhdmVyYWdlIG9mIHRoZSBlbGVtZW50cyBpbiBhIHZlY3RvciwgYW5kIGEgZnVuY3Rpb24gYHNkYCB0aGF0IGNvbXB1dGVzIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIGVsZW1lbnRzIGluIGEgdmVjdG9yLiBUaGVyZSBhcmUgaHVuZHJlZHMgb2Ygc3VjaCBmdW5jdGlvbnMgYXZhaWxhYmxlLCBhbmQgd2Ugd2lsbCBleHBsb3JlIG1hbnkgb2YgdGhlbSB0aHJvdWdob3V0IHRoaXMgbWluaS1jb3Vyc2UuCgpcCgojIyMgQ29kZS1hbG9uZyBFeGVyY2lzZQoKRW50ZXIgdGhlc2Ugc3RhdGVtZW50cyBpbnRvIFJTdHVkaW8uCgpgYGB7ciB2ZWN0b3Igc3VtbWFyeSBvcGVyYXRpb25zfQpleGFtX3Njb3Jlc192ZWN0b3IgPC0gYyg4MiwgNDMsIDk3LCA1NiwgNzgpICMgQ3JlYXRlIGFuIGV4YW1wbGUgZGF0YSB2ZWN0b3IKCm1lYW4oZXhhbV9zY29yZXNfdmVjdG9yKSAgIyBDb21wdXRlIHRoZSBtYXRoZW1hdGljYWwgbWVhbiBvZiB0aGUgZXhhbSBzY29yZXMKCnNkKGV4YW1fc2NvcmVzX3ZlY3RvcikgIyBDb21wdXRlIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIGV4YW0gc2NvcmVzCmBgYAoKXAoKIyMjIFdyaXRlIHlvdXIgb3duIGNvZGUKClRoZSBSIGZ1bmN0aW9ucyBgbWluYCBhbmQgYG1heGAgcmV0dXJuIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIHZhbHVlcyBvZiBhIHZlY3Rvci4gV3JpdGUgY29tbWFuZHMgdG8gdXNlIHRoZXNlIGZ1bmN0aW9ucyBvbiAqKmV4YW1fc2NvcmVzX3ZlY3RvcioqIGZyb20gdGhlIHByZXZpb3VzIGV4ZXJjaXNlLgoKTm90IGFsbCBSIGZ1bmN0aW9ucyBoYXZlIHN1Y2ggb2J2aW91cyBuYW1lcy4gVXNlIEdvb2dsZSBvciB5b3VyIGZhdm91cml0ZSBSIHRleHRib29rIHRvIGZpbmQgb3V0IHdoYXQgZnVuY3Rpb24gdG8gY2FsbCB0byBnZXQgKnRoZSBudW1iZXIgb2YgZWxlbWVudHMgaW4gYSB2ZWN0b3IqLiBUZXN0IHRoaXMgZnVuY3Rpb24gb24gKipleGFtX3Njb3Jlc192ZWN0b3IqKi4KClwKClwKCiMgRXZlbiBNb3JlIENvbXBsZXggVGhpbmdzCgpXZSBoYXZlIHNlZW4gdGhhdCBSIHVuZGVyc3RhbmRzIHNpbmdsZSBudW1iZXJzIG9yIHN0cmluZ3MsIGFuZCBjb2xsZWN0aW9ucyBvZiBudW1iZXJzIG9yIHN0cmluZ3MgKHZlY3RvcnMpLiBSIGFsc28gdW5kZXJzdGFuZHMgY29tcGxldGUgdGFibGVzIG9mIGRhdGEgKGluIHJvd3MgYW5kIGNvbHVtbnMsIGxpa2Ugc3ByZWFkc2hlZXRzIGFyZSBhcnJhbmdlZCkuIEluIGZhY3QsIG1vc3QgcmVhbCBkYXRhIGFuYWx5c2lzIGluIFIgb3BlcmF0ZXMgb24gdGFibGVzIG9mIGRhdGEuIFNvbWUgUiBmdW5jdGlvbnMgcmVxdWlyZSB5b3UgdG8gZmlyc3QgZXh0cmFjdCBhIHJvdyBvciBjb2x1bW4gZnJvbSB5b3VyIGRhdGEgdGFibGU7IG90aGVyIGZ1bmN0aW9ucyB3aWxsIHRha2UgYW4gZW50aXJlIHRhYmxlIGFuZCBvcGVyYXRlIG9uIGl0IGF0IG9uY2UgKGZvciBleGFtcGxlLCBtYW55IG9mIHRoZSBmdW5jdGlvbnMgdGhhdCBwZXJmb3JtIGluZmVyZW50aWFsIHN0YXRpc3RpY2FsIGFuYWx5c2VzIG9wZXJhdGUgb24gd2hvbGUgdGFibGVzKS4gSW4gbGF0ZXIgbW9kdWxlcywgd2Ugd2lsbCB1c2Ugc29tZSBvZiB0aGVzZSBmdW5jdGlvbnMuIEJ1dCBiZWZvcmUgd2UgZG8gdGhhdCwgdGhlcmUgaXMgb25lIG1vcmUgKip2ZXJ5IGltcG9ydGFudCoqIG1lY2hhbmljYWwgZmVhdHVyZSBvZiBSU3R1ZGlvLi4uCgpcCgojIyBTYXZpbmcgWW91ciBDb2RlCgpXZSBoYXZlIHR5cGVkIGEgbG90IG9mIFIgY29tbWFuZHMgaW50byB0aGUgY29uc29sZS4gV2hlbiB3ZSBjbG9zZSBSU3R1ZGlvLCAqKmFsbCB0aGF0IGNvZGUgd2lsbCBiZSBnb25lIGZvcmV2ZXIqKi4gSWYgd2Ugd2FudCB0byBkbyBhbnkgb2YgdGhpcyBhZ2Fpbiwgd2UgaGF2ZSB0byBzdGFydCBvdmVyIGZyb20gdGhlIGJlZ2lubmluZyBhbmQgdHlwZSBldmVyeXRoaW5nIGluIGFnYWluLiBUaGlzIGlzIHVuYWNjZXB0YWJsZS4gU28sIFJTdHVkaW8gbGV0cyB1cyB0eXBlIG91ciBjb2RlIGludG8gYSBmaWxlLCBzYXZlIHRoZSBmaWxlLCBhbmQgcmV0cmlldmUgdGhlIGNvZGUgd2hlbmV2ZXIgd2Ugd2FudCwgc28gdGhhdCB3ZSBjYW4gbW9kaWZ5IGl0IG9yIHNpbXBseSBydW4gaXQgYWdhaW4uCgpcCgojIyBVc2luZyBhIFNjcmlwdCBGaWxlCgoxXC4gRnJvbSB0aGUgbWVudSBhdCB0aGUgdG9wIG9mIHRoZSBSU3R1ZGlvIHNjcmVlbiBzZWxlY3QgRmlsZS1cPk5ldyBGaWxlIHRoZW4gY2xpY2sgb24gUiBTY3JpcHQuIChBbHRlcm5hdGl2ZWx5LCB5b3UgY2FuIHR5cGUgc2hpZnQrY3RybCtOIChXaW5kb3dzKSBvciBzaGlmdCtjbWQrTiAoTWFjKS4pCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjUwJSIsIGZpZy5jYXAgPSAiTWFraW5nIGFuIFIgRmlsZSIsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW1ha2Vfc2NyaXB0LnBuZyIpCmBgYAoKMlwuIFRoaXMgb3BlbnMgYSBuZXcgdW50aXRsZWQgZmlsZSBpbiBhbiBlZGl0aW5nIHBhbmUgaW4gdGhlIHVwcGVyIGxlZnQgb2YgdGhlIFJTdHVkaW8gc2NyZWVuLiBUaGUgY29uc29sZSBwYW5lIHdpbGwgYmUgcHVzaGVkIGRvd24gdG8gdGhlIGJvdHRvbSBoYWxmIG9mIHRoZSBzY3JlZW4uIFlvdSBjYW4gY2xpY2sgYW5kIGRyYWcgdGhlIGRpdmlkZXJzIGJldHdlZW4gdGhlIGZvdXIgcGFuZXMgdG8gY2hhbmdlIHRoZWlyIHNpemVzIGFzIHlvdSBwcmVmZXIuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAiMTAwJSIsIGZpZy5jYXAgPSAiTmV3IFNjcmlwdCIsIGZpZy5wb3MgPSAnSCcsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW5ld19zY3JpcHQucG5nIikKYGBgCgozXC4gRnJvbSB0aGUgbWFpbiBSU3R1ZGlvIG1lbnUgc2VsZWN0IEZpbGUtXD5TYXZlIEFzLi4gdG8gc2F2ZSB5b3VyIGZpbGUuIEFsd2F5cyBnaXZlIHlvdXIgZmlsZXMgZGVzY3JpcHRpdmUgbmFtZXMgdG8gbWFrZSBpdCBlYXN5IHRvIGZpbmQgdGhlIG9uZSB5b3Ugd2FudCBsYXRlci4KCjRcLiBZb3UgY2FuIHR5cGUgUiBjb21tYW5kcyBpbnRvIHRoZSBuZXcgZmlsZSAoaW4gdGhlIHVwcGVyIGxlZnQgcGFuZSkgZXhhY3RseSBhcyB5b3UgdHlwZWQgaW50byB0aGUgY29uc29sZS4KCjVcLiBFeGVjdXRpbmcgYSBjb21tYW5kIHRoYXQgaXMgdHlwZWQgaW50byBhIGZpbGUgd29ya3MgYSBsaXR0bGUgZGlmZmVyZW50bHkgdGhhbiBleGVjdXRpbmcgYSBjb21tYW5kIHRoYXQgaXMgdHlwZWQgaW50byB0aGUgY29uc29sZS4gVG8gZXhlY3V0ZSBhIHNpbmdsZSBsaW5lIG9mIGNvZGUgaW4gdGhlIGZpbGUsIGNsaWNrIHlvdXIgbW91c2UgY3Vyc29yIGFueXdoZXJlIG9uIHRoZSBsaW5lIG9mIGNvZGUuICoqRE8gTk9UIFNFTEVDVCBBTlkgQ0hBUkFDVEVSUy4gSE9MRCBUSEUgTU9VU0UgU1RJTEwgV0hJTEUgQ0xJQ0tJTkcqKi4gVGhlbiB0eXBlIGN0cmwrRW50ZXIgKFdpbmRvd3MpIG9yIGNtZCtFbnRlciAoTWFjKS4KCjZcLiBUbyBleGVjdXRlIG11bHRpcGxlIGxpbmVzIG9mIGNvZGUgaW4gdGhlIGZpbGUsIHNlbGVjdCBhbGwgdGhlIGNvZGUgeW91IHdhbnQgYnkgY2xpY2tpbmcgYW5kIGRyYWdnaW5nIHRoZSBtb3VzZSAoY3RybCtBIG9yIGNtZCtBIGZvciB0aGUgd2hvbGUgZmlsZSksIHRoZW4gdHlwZSBjdHJsK0VudGVyIG9yIGNtZCtFbnRlci4KCjdcLiBUaGUgb3V0cHV0IGZyb20geW91ciBjb2RlIHdpbGwgYmUgd3JpdHRlbiB0byB0aGUgY29uc29sZSwganVzdCBhcyB0aG91Z2ggeW91IGhhZCB0eXBlZCB0aGUgY29kZSB0aGVyZS4KCjhcLiBBZnRlciBlbnRlcmluZyBzb21lIGNvZGUgaW50byB5b3VyIGZpbGUsIHNhdmUgaXQgKHRoZSBwcm9ncmFtbWVyJ3MgbW90dG8gaXMgU2F2ZSBFYXJseSwgU2F2ZSBPZnRlbikuIFlvdSBjYW4gdGhlbiBzYWZlbHkgZXhpdCB0aGUgUlN0dWRpbyBwcm9ncmFtLgoKOVwuIEdvIHRvIHdoZXJldmVyIHlvdSBzYXZlZCB5b3VyIG5hbWVkIGNvZGUgZmlsZSAoaXQgd2lsbCBoYXZlIHN1ZmZpeCAuUikgYW5kIGRvdWJsZS1jbGljayBvbiBpdCB0byBvcGVuIGl0LiBUaGUgY29tcHV0ZXIgbWF5IGFzayB5b3Ugd2hhdCBwcm9ncmFtIHRvIHVzZSAtLSBzZWxlY3QgUlN0dWRpby4KCjEwXC4gVGhlIGZpbGUgd2lsbCBvcGVuIGluIFJTdHVkaW8gYW5kIHlvdSBjYW4gcnVuIGFsbCB5b3VyIGNvZGUgYWdhaW4gKHNlZSBpdGVtcyA1IGFuZCA2IGFib3ZlKSB3aXRob3V0IGhhdmluZyB0byByZXR5cGUgYW55dGhpbmcuCgpcCgojIyBBbiBFdmVuIEJldHRlciBTY3JpcHQgRmlsZQoKV2Ugd2lsbCBjb3ZlciBSTWFya2Rvd24gaW4gbW9yZSBkZXB0aCBpbiBNb2R1bGUgNi4KCkEgYmFzaWMgc2NyaXB0IGZpbGUgKG9mIHR5cGUgLlIpIHdpbGwgc3RvcmUgYW5kIHByZXNlcnZlIHlvdXIgY29kZS4gUlN0dWRpbyBhbHNvIHByb3ZpZGVzICoqUiBNYXJrZG93bioqIGZpbGVzIChvZiB0eXBlIC5SbWQpIHRoYXQgY2FuIGRvIG11Y2ggbW9yZS4gUiBNYXJrZG93biBpcyBhbiBleHRlbmRlZCBzY3JpcHQgZm9ybWF0IHRoYXQgYWxsb3dzIHlvdSB0byBlbWJlZCBSIGNvbW1hbmRzIGluIGZvcm1hdHRlZCB0ZXh0LiBSU3R1ZGlvIHByb2Nlc3NlcyBSIE1hcmtkb3duIGZpbGVzLCBwcm9kdWNpbmcgSFRNTCwgV29yZCBvciBwZGYgZm9ybWF0cy4gRHVyaW5nIHByb2Nlc3NpbmcgKHdoaWNoIGlzIGNhbGxlZCAqa25pdHRpbmcqKSBSU3R1ZGlvIHJ1bnMgYW55IGVtYmVkZGVkIFIgY29tbWFuZHMgYW5kICoqaW5zZXJ0cyB0aGUgcmVzdWx0cyBpbnRvIHRoZSBvdXRwdXQgZG9jdW1lbnQqKi4gWW91IGRvbid0IG5lZWQgdG8gcHJvY2VzcyB5b3VyIGRhdGEgaW4gUlN0dWRpbyBhbmQgdGhlbiBjb3B5L3Bhc3RlIHRoZSByZXN1bHRzIGludG8gYSBzZXBhcmF0ZSBXb3JkIGRvY3VtZW50LiBZb3UgY2FuIGluc2VydCB0aGUgY29kZSBkaXJlY3RseSBpbnRvIHlvdXIgdGV4dCBpbiBhbiBSIE1hcmtkb3duIGZpbGUsIGFuZCBpdCB3aWxsIGJlIGV4ZWN1dGVkIHdoZW4gUlN0dWRpbyBrbml0cy4gTGV0J3MgZ2l2ZSBpdCBhIHRyeToKCjFcLiBJbiBSU3R1ZGlvLCBjbGljayBvbiB0aGUgRmlsZSBtZW51LCBzZWxlY3QgTmV3IEZpbGUgYW5kLCBmcm9tIHRoZSBzdWJtZW51IHRoYXQgb3BlbnMsIGNsaWNrIG9uIFIgTWFya2Rvd24uCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjUwJSIsIGZpZy5jYXAgPSAiQ3JlYXRlIGFuIFIgTWFya2Rvd24gRmlsZSIsIGZpZy5wb3MgPSAiSCIsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW1ha2Vfcm1kLnBuZyIpCmBgYAoKMlwuIEEgZGlhbG9ndWUgYm94IHdpbGwgb3Blbiwgd2hlcmUgeW91IGhhdmUgYSBjaGFuY2UgdG8gZW50ZXIgYSB0aXRsZSBmb3IgeW91ciBkb2N1bWVudCBhbmQgdGhlIG5hbWUgb2YgdGhlIGF1dGhvci4gVGhlc2Ugd2lsbCBhcHBlYXIgYXQgdGhlIHRvcCBvZiB0aGUga25pdCBkb2N1bWVudC4gWW91IGNhbiBzZWxlY3QgdGhlIG91dHB1dCBmb3JtYXQuIExlYXZlIGl0IGFzIEhUTUwgZm9yIHRoaXMgZXhlcmNpc2UuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAiNzUlIiwgZmlnLnBvcyA9ICJIIiwgZmlnLmNhcCA9ICJSIE1hcmtkb3duIERpYWxvZ3VlIiwgZWNobyA9IEZBTFNFfQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtbWFya2Rvd25fZGlhbG9ndWUucG5nIikKYGBgCgozXC4gUlN0dWRpbyB3aWxsIGNyZWF0ZSBhIG5ldyBmaWxlIGFuZCBvcGVuIGl0IGluIGEgbmV3IHRhYi4gVGhlIGZpbGUgaXMgdW50aXRsZWQsIHNvIHNhdmUgaXQgYW5kIGdpdmUgaXQgYSBzZW5zaWJsZSBuYW1lLgoKYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmNhcCA9ICJBIE5ldyBSIE1hcmtkb3duIEZpbGUiLCBvdXQud2lkdGggPSAiMTAwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLnBvcyA9ICJIIn0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW1hcmtkb3duX3RlbXBsYXRlLnBuZyIpCmBgYAoKVGhlIGZpbGUgYWxyZWFkeSBjb250YWlucyBzb21lIHRleHQuIFRoaXMgaXMgc29tZSBzYW1wbGUgY29udGVudHMgdG8gZ2l2ZSB5b3UgYW4gaWRlYSBvZiB3aGF0IGFuIFIgTWFya2Rvd24gZmlsZSBsb29rcyBsaWtlLiBZb3Ugd2lsbCBub3RlIHRoYXQgdGhlIGZpbGUgaGFzIGFyZWFzIHdpdGggYSB3aGl0ZSBiYWNrZ3JvdW5kIGFuZCBhcmVhcyB3aXRoIGEgc2hhZGVkIGJhY2tncm91bmQuIFRoZSB3aGl0ZSBhcmVhcyBhcmUgcGxhaW4gdGV4dCwgdGhlIHNoYWRlZCBhcmVhcyBhcmUgUiBjb21tYW5kcy4gV2hlbiB0aGUgZmlsZSBpcyBrbml0LCB0aGF0IGNvZGUgd2lsbCBiZSBydW4sIGFuZCBpdHMgb3V0cHV0IGluc2VydGVkIGludG8gdGhlIHRleHQuIFRvIHNlZSB0aGlzIGluIGFjdGlvbiwgY2xpY2sgdGhlICoqS25pdCoqIGljb24gYXQgdGhlIHRvcCB0aGUgUlN0dWRpbyB0YWIuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwID0gIlRoZSBLbml0IEJ1dHRvbiIsIG91dC53aWR0aCA9ICI1MCUiLCBlY2hvID0gRkFMU0UsIGZpZy5wb3MgPSAiSCJ9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1tYXJrZG93bl9rbml0X2J1dHRvbi5wbmciKQpgYGAKClJTdHVkaW8gd2lsbCBwcm9kdWNlIGEgYmVhdXRpZnVsIEhUTUwgZG9jdW1lbnQgYW5kIG9wZW4gaXQgaW4gYSBsb2NhbCBicm93c2VyIHdpbmRvdy4gU2VlIGlmIHlvdSBjYW4gbWF0Y2ggdGhlIFIgY29kZSBzZWdtZW50cyBpbiB0aGUgUiBNYXJrZG93biBkb2N1bWVudCB0byB0aGUgb3V0cHV0IHRoYXQgYXBwZWFycyBpbiB0aGUgSFRNTCBwYWdlLgoKUiBNYXJrZG93biBpcyBhIHBvd2VyZnVsIHRvb2wgZm9yIGdlbmVyYXRpbmcgcmVzZWFyY2ggcmVwb3J0cyB3aGVuIGFuYWx5c2luZyBkYXRhIHdpdGggUi4gQXMgd2UgcHJvY2VlZCB0aHJvdWdoIHRoaXMgbWluaS1jb3Vyc2Ugd2Ugd2lsbCBleHBsb3JlIGFkZGl0aW9uYWwgZmVhdHVyZXMgb2YgUiBNYXJrZG93biwgYW5kIHlvdSBtYXkgd2lzaCB0byBjb25zaWRlciB1c2luZyBpdCBmb3IgeW91ciBvd24gY291cnNlIGFzc2lnbm1lbnRzLiBDaGVjayB3aXRoIHlvdXIgbGVjdHVyZXJzIHRvIHNlZSBpZiB0aGlzIGlzIHN1aXRhYmxlLgoKXAoKXAoKIyBDb25jbHVzaW9uCgpJbiB0aGlzIG1vZHVsZSB5b3UgaGF2ZSBjb25zaWRlcmVkIHRoZSBpbm5lciB3b3JraW5ncyBvZiB0aGUgY29tcHV0ZXIsIHdyaXR0ZW4gUiBjb21tYW5kcyBpbnRvIHRoZSBSU3R1ZGlvIERldmVsb3BtZW50IEVudmlyb25tZW50LCBtZXQgc29tZSBvZiB0aGUgdGhpbmdzIFIgdW5kZXJzdGFuZHMgKG51bWJlciwgc3RyaW5ncywgYW5kIHZlY3RvcnMpIGFuZCBzb21lIG9mIHRoZSBhY3Rpb25zIFIgY2FuIHBlcmZvcm0gKGZ1bmN0aW9ucykuIENvbmdyYXR1bGF0aW9ucy4KCiMjIFdoYXQncyBOZXh0CgpGaWxsIGluIHRoZSBtb2R1bGUgZmVlZGJhY2sgZm9ybSA8aHR0cHM6Ly90aW55dXJsLmNvbS9yNHNzcC1tb2R1bGUtZmI+LgoKSW4gb3VyIG5leHQgbW9kdWxlLCB3ZSB3aWxsIGxlYXJuIGhvdyB0byByZWFkIHJlYWwgZGF0YSBmaWxlcyBpbnRvIFIgYW5kIG1ha2UgcGxvdHMgYW5kIGZpZ3VyZXMgdGhhdCB5b3UgY2FuIHVzZSBpbiBhIHJlc2VhcmNoIHJlcG9ydC4gV2Ugd2lsbCBzdGFydCB3aXRoIHNpbXBsZSBwbG90cyB5b3UgY2FuIGNyZWF0ZSB1c2luZyBvbmx5IGJhc2UgUi4gVGhlbiB3ZSB3aWxsIGxlYXJuIHRvIHVzZSBhIHBvd2VyZnVsIGdyYXBoaWNzIGxpYnJhcnkgY2FsbGVkICoqZ2dwbG90KiogKHBhcnQgb2YgdGhlICoqdGlkeXZlcnNlKiogZmFtaWx5IG9mIFIgZXh0ZW5zaW9ucykuIFdpdGggZ2dwbG90IHlvdSBjYW4gbWFrZSBwdWJsaWNhdGlvbi1xdWFsaXR5IGdyYXBocyB3aXRoIG9ubHkgYSBmZXcgbGluZXMgb2YgUiBjb2RlLgoKCgoKCgoK