Associated material

Zoom notes: Zoom notes 01 - Introducing R and RStudio

Readings:

Before we start

This web site provides two kinds of materials – module notes and zoom notes. The module pages cover the content of each online session in detail. They often provide additional in-depth discussion and examples. You can use the module notes to revise and extend lesson content on your own at any time. The zoom notes contain an outline of the material covered in each module and coding exercises that you can work through after the lesson to solidify your understanding and build your skills. We can work through these exercises together in each week’s face to face practical session.

At the top right hand corner of each notes page is a “Code” button. This toggles showing/hiding the code used to create the page as an Rmarkdown file (we cover Rmarkdown more in-depth in module/zoom notes 4). When working through the zoom notes, you can use this button to hide the exercise solutions if you prefer to tackle them first on your own.


Introduction

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

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

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

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

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



The Tools

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

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 (which is itself written in a programming language, of course) that knows how to translate from the human-friendly programming language into actions on the computer. These are called Development Environments, because this is where people develop software.

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). As of writing, the current version of R is 4.2.2. If you already have an earlier version of R installed, consider upgrading to the latest version by running the latest installer.


Then install RStudio from https://posit.co/products/open-source/rstudio/. Install the Free version; it does everything that you need. Modern scientists must be comfortable installing software on their own computers. This is a good opportunity for you to practice this important skill, and we encourage you to try it. If you need any help, ask us.


How to Talk to a Computer

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

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

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


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 characters shown below into the Console pane, followed by the Enter key.

    4 + 5

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

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

To get information about a function type ? followed by the name of the function (e.g. ?mean) into the console. This will display the function’s manual page in the lower-right pane (the Help tab).

Manual page. Type ?mean into the console.

Manual page. Type ?mean into the console.


The manual page explains what the function does, what the function inputs are and what the function returns. Most manual pages also provide some code examples.

For more ways to find documentation see https://datacarpentry.org/R-ecology-lesson/00-before-we-start.html#Seeking_help


More things: Words

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

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

"plato"

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

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


Code-along Exercise

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


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

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

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

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

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

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


Storing Results

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

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

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

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

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


Code-along Exercise

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

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

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

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


Variable Names and Values

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

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

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 Script File

Making an R Script 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 Tab

New Script Tab

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

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

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

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

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

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

9. Go to wherever you saved your named code file (it will have suffix .R) Double-click on it and it should open in RStudio. If it opens in something else (e.g. Word or Notepad), this just means that your machine is not configured to associate .R files with RStudio. In this case, right-click on the file, select Open With, and then RStudio. (We see a more convenient workflow in a moment.)

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


Using Projects in RStudio

An RStudio project is a folder, created from inside RStudio, that contains related script files, data files, and RStudio metadata files which ensure R code runs correctly and efficiently. Most experienced R developers always organise their work into projects. This is logically similar to organising your regular computer files into folders – it keeps related material bundled together, making it easier to work with.

Typically, creating a project is the first step in R development. When a project is initially created, it contains only the RStudio metadata files. Then data files are added by simply moving them into folder like any other file. Script files and output files are added to the project from inside RStudio as the work progresses. At all times, all the related content for the project is tidily contained in the project folder for easy location and use.

Creating a Project in RStudio

1. From the main menu select File -> New Project

2. In the resulting pop-up window, select New Directory, then New Project, to navigate to the Create New Project dialogue box.

3. THIS IS THE TRICKY PART. The Create New Project dialogue has a text box, followed by a Browse button. Counterintuitively, you have to do the Browse button first. Click Browse and navigate to where you want your project folder to be created. Only then, click in the Directory Name text box and type a name for your project folder. Be sure to make this name descriptive – it is awkward to change the name of a project after it is created. Click the Create Project button to finish. RStudio will refresh as it navigates to your new empty project.

4. Quit out of RStudio, and navigate to the directory where you created your project. You will find a new folder labelled with the project name you chose.

5. Open the project folder. It will contain a folder called .Rproj.user and a file called .Rhistory. These are RStudio metadata files – leave them alone. (You may need to turn on hidden files in Windows Explorer or the Mac Finder to see these files.) It also contains a file with the project name and suffix .Rproj.

6. When you open the project in RStudio (we see how in a moment) the project folder will be its working directory. That is, RStudio will be “looking at” this folder. It will be able to access any files in this folder; when you generate output files, they will be written to this folder. To illustrate this, I have placed an Excel file into my new project folder, and we will see how it appears to RStudio. You can place files in your project folder by copy/paste, moving in the Finder, or creating new files, exactly as you work with files in the ordinary way for your operating system.

7. Double click on the .Rproj file in your project folder. This automatically opens your project in RStudio and sets the working directory (what RStudio can “see”) correctly. Note that the Files tab in the lower right pane shows the contents of the project folder, including the added spreadsheet file.

8. When working with R we recommend that you create a new project for every module of work. The exact level of detail that defines a “module of work” will become part of your professional style. We further recommend that you ALWAYS begin working on any RStudio project by double-clicking on the .Rproj file. Do not open RStudio directly and then wander around looking for your project.

For a detailed discussion of advanced RStudio project organisation and use, see R for Data Science - Workflow: Projects (https://r4ds.had.co.nz/workflow-projects.html)

An Even Better Script File

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

We will cover RMarkdown (and its next-generation version Quarto) in depth in Module 4, but we introduce the process briefly here:

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

Create an R Markdown File

Create an R Markdown File

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

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 sample contents to illustrate how R Markdown works. You will note that the file has areas with a white background and areas with a shaded background. The white areas are plain text, the shaded areas are R code When the file is knit, that code will be run, and its output inserted into the text. To see this in action, click the Knit icon at the top the RStudio tab.

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

In this week’s hands-on session we will continue to build our R skills, working together through the exercises in the Zoom notes for this module. (If you prefer, go ahead and try them on your own.) You can also use the hands-on sessions to get help with any coursework, projects, or other R questions you may have.

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

LS0tCnRpdGxlOiAiSW50cm9kdWNpbmcgUiBhbmQgUlN0dWRpbyIKZGF0ZTogIlNlbWVzdGVyIDIsIDIwMjMiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGZpZy5wYXRoID0gImZpZ3VyZXMvMDEvIiwgIyB1c2Ugb25seSBmb3Igc2luZ2xlIFJtZCBmaWxlcwogIGNvbGxhcHNlID0gVFJVRSwKICBlY2hvID0gVFJVRQopCgoKYGBgCgoKPiAjIyMjIEFzc29jaWF0ZWQgbWF0ZXJpYWwKPgo+IFpvb20gbm90ZXM6IFtab29tIG5vdGVzIDAxIC0gSW50cm9kdWNpbmcgUiBhbmQgUlN0dWRpb10oem9vbV9ub3Rlc18wMV9pbnRyby5odG1sKQo+IAo+IFJlYWRpbmdzOgo+Cj4gLSBbUiBmb3IgRGF0YSBTY2llbmNlIC0gQ2hhcHRlciAxXShodHRwczovL3I0ZHMuaGFkLmNvLm56L2ludHJvZHVjdGlvbi5odG1sKQo+IC0gW1IgZm9yIERhdGEgU2NpZW5jZSAtIENoYXB0ZXIgNF0oaHR0cHM6Ly9yNGRzLmhhZC5jby5uei93b3JrZmxvdy1iYXNpY3MuaHRtKQoKIyMjIyBCZWZvcmUgd2Ugc3RhcnQKClRoaXMgd2ViIHNpdGUgcHJvdmlkZXMgdHdvIGtpbmRzIG9mIG1hdGVyaWFscyAtLSBtb2R1bGUgbm90ZXMgYW5kIHpvb20gbm90ZXMuIFRoZSBtb2R1bGUgcGFnZXMgY292ZXIgdGhlIGNvbnRlbnQgb2YgZWFjaCBvbmxpbmUgc2Vzc2lvbiBpbiBkZXRhaWwuIFRoZXkgb2Z0ZW4gcHJvdmlkZSBhZGRpdGlvbmFsIGluLWRlcHRoIGRpc2N1c3Npb24gYW5kIGV4YW1wbGVzLiBZb3UgY2FuIHVzZSB0aGUgbW9kdWxlIG5vdGVzIHRvIHJldmlzZSBhbmQgZXh0ZW5kIGxlc3NvbiBjb250ZW50IG9uIHlvdXIgb3duIGF0IGFueSB0aW1lLiBUaGUgem9vbSBub3RlcyBjb250YWluIGFuIG91dGxpbmUgb2YgdGhlIG1hdGVyaWFsIGNvdmVyZWQgaW4gZWFjaCBtb2R1bGUgYW5kIGNvZGluZyBleGVyY2lzZXMgdGhhdCB5b3UgY2FuIHdvcmsgdGhyb3VnaCBhZnRlciB0aGUgbGVzc29uIHRvIHNvbGlkaWZ5IHlvdXIgdW5kZXJzdGFuZGluZyBhbmQgYnVpbGQgeW91ciBza2lsbHMuIFdlIGNhbiAgd29yayB0aHJvdWdoIHRoZXNlIGV4ZXJjaXNlcyB0b2dldGhlciBpbiBlYWNoIHdlZWsncyBmYWNlIHRvIGZhY2UgcHJhY3RpY2FsIHNlc3Npb24uIAoKQXQgdGhlIHRvcCByaWdodCBoYW5kIGNvcm5lciBvZiBlYWNoIG5vdGVzIHBhZ2UgaXMgYSAiQ29kZSIgYnV0dG9uLiBUaGlzIHRvZ2dsZXMgc2hvd2luZy9oaWRpbmcgdGhlIGNvZGUgdXNlZCB0byBjcmVhdGUgdGhlIHBhZ2UgYXMgYW4gUm1hcmtkb3duIGZpbGUgKHdlIGNvdmVyIFJtYXJrZG93biBtb3JlIGluLWRlcHRoIGluIFttb2R1bGVdKDA0LWNvbW11bmljYXRlLmh0bWwpL1t6b29tIG5vdGVzXSh6b29tX25vdGVzXzA0X2NvbW11bmljYXRlLmh0bWwpIDQpLiBXaGVuIHdvcmtpbmcgdGhyb3VnaCB0aGUgem9vbSBub3RlcywgeW91IGNhbiB1c2UgdGhpcyBidXR0b24gdG8gaGlkZSB0aGUgZXhlcmNpc2Ugc29sdXRpb25zIGlmIHlvdSBwcmVmZXIgdG8gdGFja2xlIHRoZW0gZmlyc3Qgb24geW91ciBvd24uCgpcCgojIEludHJvZHVjdGlvbgoKQWR2YW5jZXMgaW4gY29tcHV0aW5nIGFuZCBzZW5zaW5nIHRlY2hub2xvZ2llcyBtZWFuIHRoYXQgbW9kZXJuIHNjaWVudGlmaWMgcmVzZWFyY2ggb2Z0ZW4gaW52b2x2ZXMgdmVyeSBsYXJnZSBkYXRhIHNldHMuIFRoZXJlIGFyZSBub3cgbWFueSBjb21wdXRlciBzb2Z0d2FyZSB0b29scyBhdmFpbGFibGUgdG8gd29yayB3aXRoIGJpZyBkYXRhLCBhbmQgc2NpZW50aXN0cyBmcm9tIGFsbCBkaXNjaXBsaW5lcyBuZWVkIHRvIGJlIGFibGUgdG8gdXNlIHRoZW0uCgpJbiB0aGlzIG1pbmktY291cnNlLCB3ZSB3aWxsIGhlbHAgeW91IGxlYXJuIHRvIHVzZSBvbmUgb2YgdGhlIG1vc3QgaW50ZXJlc3RpbmcgKGFuZCBwb3B1bGFyKSBvZiB0aGVzZSB0b29scyAtLSB0aGUgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UgUi4gUiBpcyBhIHNwZWNpYWwtcHVycG9zZSBvcGVuLXNvdXJjZSBsYW5ndWFnZSBmb3Igc3RhdGlzdGljcyBhbmQgZGF0YSBhbmFseXNpcy4gSW5jcmVhc2luZ2x5LCBSIGlzIHRoZSBwcmVmZXJyZWQgdG9vbCBmb3IgYW5hbHlzaW5nIGFuZCBwcmVzZW50aW5nIGRhdGEgZm9yIHN0dWRlbnQgcmVzZWFyY2ggcHJvamVjdHMuCgpJbiB0aGlzIG1vZHVsZSwgd2Ugc2hvdyB5b3UgaG93IHRvIGdldCBzdGFydGVkIHdpdGggUi4gV2Ugd2lsbCBub3QgYXNzdW1lIHRoYXQgeW91IGhhdmUgYW55IHByaW9yIGNvbXB1dGVyIHByb2dyYW1taW5nIGV4cGVyaWVuY2UuIEluIGZhY3QsIGlmIHlvdSBoYXZlIHByb2dyYW1tZWQgYmVmb3JlIGluIGEgbGFuZ3VhZ2UgbGlrZSBKYXZhIG9yIEMsIGJlIGF3YXJlIHRoYXQgUiBpcywgaW4gbWFueSByZXNwZWN0cywgdmVyeSBkaWZmZXJlbnQgZnJvbSB0aG9zZSBsYW5ndWFnZXMgLS0gc28ga2VlcCBhbiBvcGVuIG1pbmQuCgpXZSB3aWxsIGJlZ2luIGJ5IGV4cGxhaW5pbmcgdGhlIGRpZmZlcmVudCBzb2Z0d2FyZSB0b29scyB5b3UgbmVlZCwgYW5kIGhvdyB0byBnZXQgdGhlbSBvbnRvIHlvdXIgb3duIGNvbXB1dGVycy4gVGhlbiB3ZSB3aWxsIGRpc2N1c3MgdGhlIGJhc2ljIG1lY2hhbmljcyBvZiB0aGVzZSB0b29scy4gVGhyb3VnaG91dCB0aGlzIGhhbmRvdXQgKGFuZCBhbGwgbWF0ZXJpYWxzIGZvciB0aGlzIG1pbmktY291cnNlKSB0aGVyZSBhcmUgY29kZSBleGFtcGxlcyBhbmQgUiBleGVyY2lzZXMgdGhhdCB5b3Ugc2hvdWxkIHdvcmsgdGhyb3VnaCBjYXJlZnVsbHkgb24gdGhlIGNvbXB1dGVyLiBUaGlzIHdpbGwgcHJlcGFyZSB5b3UgdG8gdXNlIFIgZm9yIHlvdXIgaW4tY291cnNlIHJlc2VhcmNoIHByb2plY3RzIGxhdGVyIGluIHRoZSBzZW1lc3Rlci4KClRoaXMgaGFuZG91dCBpcyBkZXNpZ25lZCB0byBiZSByZWFkIGluIGNvbmp1bmN0aW9uIHdpdGggQ2hhcHRlciAxOiBJbnRyb2R1Y3Rpb24gb2YgW1IgZm9yIERhdGEgU2NpZW5jZV0oaHR0cHM6Ly9yNGRzLmhhZC5jby5ueikuCgpcCgpcCgojIyBUaGUgVG9vbHMKCldlIHRoaW5rIG9mIGNvbXB1dGVycyBhcyBzdG9yaW5nIHJpY2ggbWVhbmluZ2Z1bCBkYXRhIChtb3N0bHkgY2F0IHZpZGVvcykuIEFjdHVhbGx5LCB3aGF0IGNvbXB1dGVycyByZWFsbHkgY29udGFpbiBhcmUgbWlsbGlvbnMgb2YgdGlueSBsaXR0bGUgc3RvcmFnZSB1bml0cywgZWFjaCBvZiB3aGljaCBlaXRoZXIgaG9sZHMgYW4gZWxlY3RyaWNhbCBjaGFyZ2UgKHVzdWFsbHkgY2FsbGVkIGEgMSkgb3IgaG9sZHMgbm90aGluZyAodXN1YWxseSBjYWxsZWQgYSAwKS4gUmVhbGx5LiBUaGF0J3MgaXQuIFRoYXQncyBhbGwgdGhlcmUgaXMuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwPSJXaGF0J3MgaW5zaWRlIHRoZSBjb21wdXRlciIsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNTAlIn0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLWNvbXB1dGVyLnBuZyIgKQpgYGAKCkFsbCBvZiB0aGUgYW1hemluZyB0aGluZ3MgdGhhdCBjb21wdXRlcnMgZG8gaGFwcGVuIHRocm91Z2ggZXh0cmVtZWx5IGNvbXBsaWNhdGVkIG1hbmlwdWxhdGlvbiBvZiBhbGwgdGhvc2UgMHMgYW5kIDFzLlRoaXMgaW52b2x2ZXMgYSBsb3Qgb2YgbWF0aHMgYW5kIGEgbG90IG9mIGVsZWN0cm9uaWNzLCBhbmQgaXMgdmVyeSwgdmVyeSBjb25mdXNpbmcuIFNvIHRoYXQgY29tcHV0ZXIgdXNlcnMgZG9uJ3QgaGF2ZSB0byB0aGluayBhYm91dCBhbGwgdGhlc2UgMHMgYW5kIDFzLCBjb21wdXRlciBzY2llbnRpc3RzIGhhdmUgZGV2ZWxvcGVkICoqcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzKiosIHdoaWNoIGFyZSBzeW1ib2xpYyBzeXN0ZW1zIHRoYXQgd2UgY2FuIHVzZSB0byBleHByZXNzIHdoYXQgd2Ugd2FudCB0byBoYXBwZW4gaW5zaWRlIHRoZSBtYWNoaW5lLiBQcm9ncmFtbWluZyBsYW5ndWFnZXMgYXJlIGRlc2lnbmVkIHRvIGJlIHNpbWlsYXIgdG8gaHVtYW4gbGFuZ3VhZ2VzLCBzbyB0aGV5IGFyZSBlYXN5IGZvciB1cyB0byB3b3JrIHdpdGguIE92ZXIgdGhlIGxhc3QgNjAgeWVhcnMgbWFueSBzdWNoIGxhbmd1YWdlcyBoYXZlIGJlZW4gZGV2ZWxvcGVkOiBGT1JUUkFOLCBCQVNJQywgQywgSmF2YSwgUHl0aG9uLCBldGMuLCBhbmQgdGhlIG9uZSB3ZSBhcmUgdXNpbmcgaW4gdGhpcyBtaW5pLWNvdXJzZSwgUi4gRWFjaCBwcm9ncmFtbWluZyBsYW5ndWFnZSBoYXMgYSB2b2NhYnVsYXJ5IGFuZCBhIGdyYW1tYXIgKGp1c3QgbGlrZSBodW1hbiBsYW5ndWFnZXMpIHdoaWNoIG11c3QgYmUgZm9sbG93ZWQgKipleGFjdGx5KiogKHRoZXkgYXJlLCBpbiBmYWN0LCBtdWNoIHN0cmljdGVyIGFib3V0IHRoaXMgdGhhbiBodW1hbiBsYW5ndWFnZXMpLgoKVG8gY29tbXVuaWNhdGUgd2l0aCB5b3VyIGNvbXB1dGVyIHVzaW5nIGEgcHJvZ3JhbSBsYW5ndWFnZSwgeW91IG5lZWQgYSBzcGVjaWFsIGNvbXB1dGVyIHByb2dyYW0gKHdoaWNoIGlzIGl0c2VsZiB3cml0dGVuIGluIGEgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UsIG9mIGNvdXJzZSkgdGhhdCBrbm93cyBob3cgdG8gdHJhbnNsYXRlIGZyb20gdGhlIGh1bWFuLWZyaWVuZGx5IHByb2dyYW1taW5nIGxhbmd1YWdlIGludG8gYWN0aW9ucyBvbiB0aGUgY29tcHV0ZXIuIFRoZXNlIGFyZSBjYWxsZWQgKipEZXZlbG9wbWVudCBFbnZpcm9ubWVudHMqKiwgYmVjYXVzZSB0aGlzIGlzIHdoZXJlIHBlb3BsZSBkZXZlbG9wIHNvZnR3YXJlLgoKYGBge3IsIGZpZy5jYXAgPSAiQWxsIFRoZSBQYXJ0cyIsIGVjaG89RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSIxMDAlIn0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLWxhbmd1YWdlX2lkZV9tYWNoaW5lLnBuZyIpCmBgYAoKVGhlIG1vc3QgcG9wdWxhciBkZXZlbG9wbWVudCBlbnZpcm9ubWVudCBmb3IgUiBpcyBhIHByb2dyYW0gY2FsbGVkICoqUlN0dWRpbyoqLgoKQm90aCBSIGFuZCBSU3R1ZGlvIGFyZSBpbnN0YWxsZWQgb24gdGhlIGNvbXB1dGVycyBpbiB0aGUgT3RhZ28gVW5pdmVyc2l0eSBjb21wdXRlciBsYWJzLiBZb3UgY2FuIHdvcmsgdGhyb3VnaCB0aGlzIGRvY3VtZW50IG9uIHRob3NlIG1hY2hpbmVzLgoKWW91IGNhbiBhbHNvIGluc3RhbGwgdGhlIFIgbGFuZ3VhZ2UgYW5kIHRoZSBSU3R1ZGlvIHByb2dyYW0gb24geW91ciBvd24gcGVyc29uYWwgY29tcHV0ZXJzLiBUaGVzZSBhcmUgY29tcGxldGVseSBvcGVuLXNvdXJjZSwgZnJlZSwgYW5kIHNhZmUuCgpGaXJzdCwgaW5zdGFsbCBSIGZyb20gPGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL2Jpbi93aW5kb3dzL2Jhc2UvPiAoZm9yIFdpbmRvd3MgbWFjaGluZXMpIG9yIDxodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy9iaW4vbWFjb3N4Lz4gKGZvciBNYWMgT1MgbWFjaGluZXMpLiBBcyBvZiB3cml0aW5nLCB0aGUgY3VycmVudCB2ZXJzaW9uIG9mIFIgaXMgNC4yLjIuIElmIHlvdSBhbHJlYWR5IGhhdmUgYW4gZWFybGllciB2ZXJzaW9uIG9mIFIgaW5zdGFsbGVkLCBjb25zaWRlciB1cGdyYWRpbmcgdG8gdGhlIGxhdGVzdCB2ZXJzaW9uIGJ5IHJ1bm5pbmcgdGhlIGxhdGVzdCBpbnN0YWxsZXIuCgpcCgpUaGVuIGluc3RhbGwgUlN0dWRpbyBmcm9tIDxodHRwczovL3Bvc2l0LmNvL3Byb2R1Y3RzL29wZW4tc291cmNlL3JzdHVkaW8vPi4gSW5zdGFsbCB0aGUgRnJlZSB2ZXJzaW9uOyBpdCBkb2VzIGV2ZXJ5dGhpbmcgdGhhdCB5b3UgbmVlZC4gTW9kZXJuIHNjaWVudGlzdHMgbXVzdCBiZSBjb21mb3J0YWJsZSBpbnN0YWxsaW5nIHNvZnR3YXJlIG9uIHRoZWlyIG93biBjb21wdXRlcnMuIFRoaXMgaXMgYSBnb29kIG9wcG9ydHVuaXR5IGZvciB5b3UgdG8gcHJhY3RpY2UgdGhpcyBpbXBvcnRhbnQgc2tpbGwsIGFuZCB3ZSBlbmNvdXJhZ2UgeW91IHRvIHRyeSBpdC4gSWYgeW91IG5lZWQgYW55IGhlbHAsIGFzayB1cy4KClwKCiMjIEhvdyB0byBUYWxrIHRvIGEgQ29tcHV0ZXIKCldoZW4gcHJvZ3JhbW1pbmcgYSBjb21wdXRlciB5b3UgbXVzdCBhbHdheXMgcmVtZW1iZXIgb25lIHZlcnkgaW1wb3J0YW50IGZhY3Q6IENvbXB1dGVycyBBcmUgU3R1cGlkLgoKUmVhbGx5LiBUaGUgY29tcHV0ZXIgInVuZGVyc3RhbmRzIiBvbmx5IGEgdmVyeSBzbWFsbCBhbmQgKnN0cmljdGx5IGxpbWl0ZWQqIHNldCBvZiBjb21tYW5kcyAodGhlIGdyYW1tYXIgYW5kIHZvY2FidWxhcnkgb2YgYSBwcm9ncmFtbWluZyBsYW5ndWFnZSkuIElmIHlvdSBkZXZpYXRlIGZyb20gdGhpcyBzZXQgb2YgY29tbWFuZHMgKmluIGFueSB3YXkqLCB0aGUgY29tcHV0ZXIgY2Fubm90IGZpZ3VyZSBvdXQgd2hhdCB5b3UgbWVhbi4gSXQgaXMgYmVzdCB0byB0aGluayBvZiB5b3VyIGNvbXB1dGVyIGFzIGEgd2VsbC1tZWFuaW5nLCB3ZWxsLXRyYWluZWQsIGJ1dCBub3QgcGFydGljdWxhcmx5IGJyaWdodCBkb2cuIEl0IHdhbnRzIHRvIGRvIGFzIGl0IGlzIHRvbGQsIGJ1dCBpZiB5b3UgdXNlIGEgY29tbWFuZCBpdCBkb2Vzbid0IGtub3csIGl0IGNhbid0IGZpZ3VyZSBvdXQgd2hhdCB5b3UgaW50ZW5kLiBCZSBuaWNlIHRvIHlvdXIgY29tcHV0ZXIgLS0gZG9uJ3QgY29uZnVzZSBpdC4KCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5jYXAgPSAiQ29uZnVzZWQgRG9nIiwgZWNobyA9IEZBTFNFfQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtZG9nLmpwZyIpCmBgYAoKPCEtLSBJbWFnZTogaHR0cHM6Ly9pbWdmbGlwLmNvbS9tZW1ldGVtcGxhdGUvMTE2MjM1NTY4L2NvbmZ1c2VkLWRvZyAtLT4KClwKClwKCiMgVXNpbmcgUlN0dWRpbwoKUlN0dWRpbyBpcyBhIHByb2dyYW0gdGhhdCBjYW4gYWNjZXB0IFIgc3RhdGVtZW50cyBhbmQgY29udmV5IHRoZW0gdG8gdGhlIG1hY2hpbmUuIEluIFJTdHVkaW8sIHlvdSB0eXBlIGluIGFuIFIgY29tbWFuZCwgaXQgaXMgZXhlY3V0ZWQgYnkgdGhlIG1hY2hpbmUsIGFuZCBSU3R1ZGlvIGNhbiBkaXNwbGF5IHRoZSByZXN1bHRzIG9mIHRoZSBjb21tYW5kLCBpZiBhbnkuCgpJbiB0aGUgZmlyc3QgaW5zdGFuY2UsIGp1c3QgdG8gbWFrZSBzdXJlIFIgYW5kIFJTdHVkaW8gYXJlIHdvcmtpbmcgY29ycmVjdGx5LCB3ZSB3aWxsIHR5cGUgYSBmZXcgUiBjb21tYW5kcyBkaXJlY3RseSBpbnRvIFJTdHVkaW8gYW5kIGV4ZWN1dGUgdGhlbSBpbiByZWFsIHRpbWUgKHNlZSBiZWxvdykuIExhdGVyLCB3ZSB3aWxsIHNlZSBob3cgdG8gc3RvcmUgYSBzZXQgb2YgUiBjb21tYW5kcyBpbiBhIGZpbGUgc28gdGhhdCB3ZSBjYW4gcnVuIHRoZW0gcmVwZWF0ZWRseSB3aXRob3V0IGhhdmluZyB0byByZXR5cGUuCgpcCgojIyBQYXJ0cyBvZiBSU3R1ZGlvCgpUaGUgUlN0dWRpbyBpbnRlcmZhY2UgaXMgZGl2aWRlZCBpbnRvIHNlcGFyYXRlICoqcGFuZXMqKi4gSW4gaXRzIGRlZmF1bHQgY29uZmlndXJhdGlvbiB3aGVuIGl0IGZpcnN0IG9wZW5zLCBSU3R1ZGlvIHdpbGwgaGF2ZSB0aHJlZSBwYW5lcywgZWFjaCBvZiB3aGljaCBoYXMgbXVsdGlwbGUgdGFicy4gT24gdGhlIGxlZnQgaXMgdGhlIENvbnNvbGUgcGFuZS4gVGhpcyBpcyB3aGVyZSB3ZSB3aWxsIGVudGVyIG91ciBmaXJzdCBSIGNvbW1hbmRzLiBBdCB0aGUgdXBwZXIgcmlnaHQgaXMgdGhlIEVudmlyb25tZW50IHBhbmUuIFRoaXMgaXMgd2hlcmUgd2Ugd2lsbCBzZWUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHN0YXRlIG9mIG91ciBwcm9ncmFtLiBBdCB0aGUgbG93ZXIgcmlnaHQgaXMgdGhlIEZpbGVzIHBhbmUuIEhlcmUgd2UgY2FuIG5hdmlnYXRlIGFtb25nIGZpbGVzIG9uIG91ciBjb21wdXRlci4gQnV0IG1vcmUgdXNlZnVsbHksIHRoZSBGaWxlcyBwYW5lIGNvbnRhaW5zIGEgdGFiIGxhYmVsbGVkIFBsb3RzLiBXZSB3aWxsIHN3aXRjaCB0byB0aGlzIHRhYiB0byBzZWUgZ3JhcGhzIHRoYXQgd2UgZHJhdyB3aXRoIFIuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwID0gIlJTdHVkaW8iLCBlY2hvID0gRkFMU0UsIGZpZy5wb3MgPSAiSCIsIG91dC53aWR0aD0iMTAwJSIsIG91dC5leHRyYSA9ICdzdHlsZT0iYm9yZGVyOjFweCBzb2xpZCBibGFjayInfQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtUlN0dWRpby5wbmciKQpgYGAKClwKCiMgUGFydHMgb2YgdGhlIFIgUHJvZ3JhbW1pbmcgTGFuZ3VhZ2UKClByb2dyYW1taW5nIGxhbmd1YWdlcyBoYXZlIGJlZW4gZGVzaWduZWQgdG8gbWltaWMgaHVtYW4gbGFuZ3VhZ2VzLiBUaGVyZWZvcmUgbW9zdCBvZiB0aGVtIGhhdmUgKip0aGluZ3MqKiAobGlrZSBub3VucykgYW5kICoqYWN0aW9ucyoqIChsaWtlIHZlcmJzKS4gUHJvZ3JhbW1pbmcgaXMganVzdCBleHBsYWluaW5nIHRvIHRoZSBjb21wdXRlciBpbiB3YXlzIGl0IGNhbiB1bmRlcnN0YW5kLCB3aGF0ICphY3Rpb25zKiB0byBwZXJmb3JtIG9uIHNwZWNpZmljICp0aGluZ3MqLiBSIHVuZGVyc3RhbmRzIG1hbnkga2luZHMgb2YgdGhpbmdzIGFuZCBtYW55LCBtYW55IGtpbmRzIG9mIGFjdGlvbnMuIFdlIGFyZSBnb2luZyB0byBzdGFydCB3aXRoIHRoZSB2ZXJ5IHNpbXBsZXN0IGNhc2UsIGp1c3QgdG8gcHJhY3RpY2UgaW50ZXJhY3Rpbmcgd2l0aCBSU3R1ZGlvIChpLmUuLCBnaXZpbmcgaXQgUiBjb21tYW5kcyB0byBjb252ZXkgdG8gdGhlIGNvbXB1dGVyIGZvciB1cykuCgpcCgojIyBOdW1iZXJzIGFuZCBtYXRoZW1hdGljYWwgb3BlcmF0b3JzCgpSIHVuZGVyc3RhbmRzIG51bWJlcnMgKHRoaW5ncyBsaWtlIDggYW5kIDMuMTQxNTkpIGFuZCBtYXRoZW1hdGljYWwgb3BlcmF0b3JzIChhY3Rpb25zIGxpa2UgKyBhbmQgLSkuIFdlIHdpbGwgdHlwZSBzb21lIG51bWJlcnMgYW5kIG1hdGhlbWF0aWNhbCBvcGVyYXRvcnMgaW50byBSU3R1ZGlvIGFuZCBzZWUgaG93IHRoZSBjb21wdXRlciByZXNwb25kcy4KClwKCiMjIyBDb2RlLWFsb25nIEV4ZXJjaXNlCgoxLiAgTGF1bmNoIFJTdHVkaW8uIElmIHlvdSBoYXZlIGluc3RhbGxlZCBSIGFuZCBSU3R1ZGlvIG9uIHlvdXIgb3duIG1hY2hpbmUsIHlvdSBzaG91bGQgaGF2ZSBhIERlc2t0b3AgKFdpbmRvd3MpIG9yIERvY2sgKE1hYyBPUykgaWNvbiB0aGF0IHlvdSBjYW4gY2xpY2sgdG8gbGF1bmNoIFJTdHVkaW8uIElmIG5vdCwgc2VhcmNoIHRocm91Z2ggdGhlIFByb2dyYW1zIHN0YXJ0LXVwIG1lbnUgKFdpbmRvd3MpIG9yIEFwcGxpY2F0aW9ucyAoTWFjIE9TKS4gVXNlcnMgb2YgdGhlIFZpcnR1YWwgU3R1ZGVudCBEZXNrdG9wIGZvbGxvdyA8aHR0cHM6Ly9ibG9ncy5vdGFnby5hYy5uei9zdHVkZW50aXQvc3R1ZGVudC1kZXNrdG9wL3N0dWRlbnQtZGVza3RvcC1vd24tZGV2aWNlLz4gZm9yIGhvdyB0byBhY2Nlc3MgaXQgZnJvbSB5b3VyIGNvbXB1dGVyLgoKMi4gIFRoZSBDb25zb2xlIHBhbmUgb24gdGhlIGxlZnQgd2lsbCBjb250YWluIHNvbWUgZXhwbGFuYXRvcnkgdGV4dC4gQXQgdGhlIGJvdHRvbSBvZiB0aGUgdGV4dCBpcyBhIHJpZ2h0IGFuZ2xlIGJyYWNrZXQgKipcPioqLiBUaGF0IGlzIHdoZXJlIHlvdSB3aWxsIGJlZ2luIHR5cGluZy4gVGhlcmUgd2lsbCBiZSBhIHNtYWxsLCBmbGFzaGluZywgdmVydGljYWwgbGluZSBiZXNpZGUgdGhlIGFuZ2xlIGJyYWNrZXQuIChJZiB5b3UgZG9uJ3QgaGF2ZSB0aGUgZmxhc2hpbmcgdmVydGljYWwgbGluZSwgY2xpY2sgeW91ciBtb3VzZSBiZXNpZGUgYW5kIHNsaWdodGx5IHRvIHRoZSByaWdodCBvZiB0aGUgYW5nbGUgYnJhY2tldC4pCgozLiAgVHlwZSB0aGUgY2hhcmFjdGVycyBzaG93biBiZWxvdyBpbnRvIHRoZSBDb25zb2xlIHBhbmUsIGZvbGxvd2VkIGJ5IHRoZSA8a2JkPkVudGVyPC9rYmQ+IGtleS4KCiAgICAqKjQgKyA1KioKCklmIGV2ZXJ5dGhpbmcgaXMgd29ya2luZyBhcyBpdCBzaG91bGQsIHlvdXIgc2NyZWVuIHNob3VsZCBsb29rIGxpa2UgdGhpcyAodGhlIGNvbnRlbnRzIG9mIHRoZSBGaWxlcyBwYW5lIG1heSBiZSBkaWZmZXJlbnQpOgoKYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSAiMTAwJSIsIGZpZy5wb3M9IkgiLCBmaWcuY2FwID0gIkZpcnN0IFIgQ29tbWFuZCIsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLWZpcnN0X2NvbW1hbmQucG5nIikKYGBgCgpZb3UgaGF2ZSBnaXZlbiBSIHR3byAqKnRoaW5ncyoqOiB0aGUgbnVtYmVyIDQgYW5kIHRoZSBudW1iZXIgNS4gWW91IGhhdmUgYXNrZWQgUiB0byBwZXJmb3JtIGFuICoqYWN0aW9uKiogb24gdGhvc2UgdGhpbmdzOiBhZGRpdGlvbi4gUiBoYXMgZG9uZSBzbywgYW5kIFJTdHVkaW8gaGFzIGRpc3BsYXllZCB0aGUgcmVzdWx0IChpbiB0aGlzIGNhc2UsIHRoZSB2YWx1ZSA5KS4gSXQgaGFzIGFsc28gcHJpbnRlZCBbMV0gb24gdGhlIGNvbnNvbGUgc2NyZWVuLiBUaGlzIGlzIFJTdHVkaW8gdHJ5aW5nIHRvIGhlbHAgeW91LiBBcyB5b3VyIFIgY29tbWFuZHMgYmVjb21lIG1vcmUgY29tcGxpY2F0ZWQsIHlvdSB3aWxsIGVuZCB1cCB3aXRoIG1hbnkgcmVzdWx0cyByYXRoZXIgdGhhbiBqdXN0IG9uZS4gUlN0dWRpbyBwcmludHMgdGhlc2UgbnVtYmVycyBhdCB0aGUgc3RhcnQgb2Ygb3V0cHV0IGxpbmVzIHRvIGhlbHAgeW91IGNvdW50IHlvdXIgcmVzdWx0cy4gSXQncyBub3QgcmVhbGx5IG5lY2Vzc2FyeSB3aGVuIHlvdSBvbmx5IGhhdmUgb25lIHJlc3VsdCwgYnV0IHRoYXQncyBqdXN0IGhvdyBSU3R1ZGlvIGJlaGF2ZXMgKHdlIHJlZmVyIHlvdSBhZ2FpbiB0byB0aGUgcGljdHVyZSBvZiB0aGUgd2VsbC1tZWFuaW5nIGRvZ2dvIGFib3ZlKS4KCkZvciB0aGUgcmVtYWluZGVyIG9mIHRoaXMgZG9jdW1lbnQsIHdlIHdpbGwgbm90IHNob3cgeW91IHBpY3R1cmVzIG9mIHRoZSB3aG9sZSBzY3JlZW4gZWFjaCB0aW1lIHdlIGVudGVyIGFuIFIgY29tbWFuZC4gUmF0aGVyLCB3ZSB3aWxsIGRpc3BsYXkgd2hhdCB5b3Ugc2hvdWxkIHR5cGUgYW5kIHdoYXQgb3V0cHV0IHlvdSBzaG91bGQgZ2V0IGxpa2UgdGhpczoKCmBgYHtyIGZpcnN0X2NvbW1hbmR9CjQgKyA1CmBgYAoKNC4gIEV4cGxvcmUgbW9yZSBvZiBSJ3MgbWF0aGVtYXRpY2FsIG9wZXJhdG9ycy4gRm9yIGRpdmlzaW9uIHVzZSAvIGFuZCBmb3IgbXVsdGlwbGljYXRpb24gdXNlIFwqLiBFbnRlciBlYWNoIG9mIHRoZXNlIFIgY29tbWFuZHMgaW50byB0aGUgY29uc29sZSBhbmQgY29uZmlybSB0aGF0IHlvdSByZWNlaXZlIHRoZSBleHBlY3RlZCBvdXRwdXQuCgpgYGB7ciBtb3JlIG1hdGhzLCBldmFsID0gRkFMU0V9CjEwIC8gOAoKOCAqIDEyCgo2IC0gMTIgKyAoMyAqIDcuNCkKYGBgCgpcCgojIyBNb3JlIGFjdGlvbnM6IEZ1bmN0aW9uIGNhbGxzIGluIFIKClIgc3ludGF4IChncmFtbWFyKSBtaW1pY3MgbWF0aGVtYXRpY2FsIGVxdWF0aW9uIHN5bnRheCBpbiBzb21lIHJlc3BlY3RzLiBBcyB3ZSBkZW5vdGUgYSBmdW5jdGlvbiBmKHgpIHVzaW5nIHJvdW5kIGJyYWNrZXRzIGluIGFuIGVxdWF0aW9uLCBzbyBkbyB3ZSBkZW5vdGUgdGhlIGFwcGxpY2F0aW9uIG9mIGEgZnVuY3Rpb24gaW4gUi4gUiBrbm93cyBtYW55IHVzZWZ1bCBmdW5jdGlvbnMuIEZvciBleGFtcGxlIGBzcXJ0KClgICwgd2hpY2ggY29tcHV0ZXMgdGhlIHNxdWFyZSByb290IG9mIGEgbnVtYmVyLCBhbmQgYGFicygpYCB3aGljaCBjb21wdXRlcyB0aGUgYWJzb2x1dGUgdmFsdWUgb2YgYSBudW1iZXIuIFRvIGFwcGx5IG9uZSBvZiB0aGVzZSBmdW5jdGlvbnMsIHdlIHR5cGUgdGhlIG5hbWUsIGFuZCBwbGFjZSB0aGUgdmFsdWUgd2Ugd2lzaCB0byBvcGVyYXRlIG9uICh0aGUgKiphcmd1bWVudCoqKSBpbnNpZGUgdGhlIHJvdW5kIGJyYWNrZXRzLgoKIyMjIENvZGUtYWxvbmcgRXhlcmNpc2UKClRyeSB0aGVzZSBleGFtcGxlczoKCmBgYHtyIGFwcGx5aW5nIGZ1bmN0aW9uc30KYWJzKC00MikKCnNxcnQoMjAwKQoKYGBgCgojIyBHZXR0aW5nIEhlbHAKClRvIGdldCBpbmZvcm1hdGlvbiBhYm91dCBhIGZ1bmN0aW9uIHR5cGUgYD9gIGZvbGxvd2VkIGJ5IHRoZSBuYW1lIG9mIHRoZSBmdW5jdGlvbiAoZS5nLiBgP21lYW5gKSBpbnRvIHRoZSBjb25zb2xlLiBUaGlzIHdpbGwgZGlzcGxheSB0aGUgZnVuY3Rpb24ncyBtYW51YWwgcGFnZSBpbiB0aGUgbG93ZXItcmlnaHQgcGFuZSAodGhlIEhlbHAgdGFiKS4gCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwID0gIk1hbnVhbCBwYWdlLiBUeXBlID9tZWFuIGludG8gdGhlIGNvbnNvbGUuIiwgZWNobyA9IEZBTFNFLCBmaWcucG9zID0gIkgiLCBvdXQud2lkdGg9IjgwJSIsIG91dC5leHRyYSA9ICdzdHlsZT0iYm9yZGVyOjFweCBzb2xpZCBibGFjayInfQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtaGVscF9wYWdlLnBuZyIpCmBgYAoKXAoKVGhlIG1hbnVhbCBwYWdlIGV4cGxhaW5zIHdoYXQgdGhlIGZ1bmN0aW9uIGRvZXMsIHdoYXQgdGhlIGZ1bmN0aW9uIGlucHV0cyBhcmUgYW5kIHdoYXQgdGhlIGZ1bmN0aW9uIHJldHVybnMuIE1vc3QgbWFudWFsIHBhZ2VzIGFsc28gcHJvdmlkZSBzb21lIGNvZGUgZXhhbXBsZXMuCgpGb3IgbW9yZSB3YXlzIHRvIGZpbmQgZG9jdW1lbnRhdGlvbiBzZWUgPGh0dHBzOi8vZGF0YWNhcnBlbnRyeS5vcmcvUi1lY29sb2d5LWxlc3Nvbi8wMC1iZWZvcmUtd2Utc3RhcnQuaHRtbCNTZWVraW5nX2hlbHA+CgpcCgojIyBNb3JlIHRoaW5nczogV29yZHMKCkxvdHMgb2YgY29tcHV0aW5nIGludm9sdmVzIHdvcmRzIHJhdGhlciB0aGFuIG51bWJlcnMuIEZvciBleGFtcGxlLCBzZWFyY2hpbmcgdGV4dCBhbmQgZW5yb2xsaW5nIHN0dWRlbnRzIGJ5IG5hbWUgYm90aCBvcGVyYXRlIG9uIHdvcmRzLiBSIHVuZGVyc3RhbmRzIHdvcmRzIC0tIHRoZSBjb25jZXB0IG9mICoqdGhpbmdzIGNvbXBvc2VkIG9mIGxldHRlcnMqKi4gSG93ZXZlciwgd2hlbiB3b3JraW5nIHdpdGggd29yZHMsIHdlIG11c3QgbWFyayB0aGVtIHdpdGggc3BlY2lhbCBjaGFyYWN0ZXJzIHRvIHByZXZlbnQgUiBmcm9tIGJlY29taW5nIGNvbmZ1c2VkICh3ZSBzZWUgd2hhdCB0aGlzIGNvbmZ1c2lvbiBsb29rcyBsaWtlIGluIGEgbW9tZW50KS4KCkluIHByb2dyYW1taW5nLCBhIHRoaW5nIGNvbXBvc2VkIG9mIGxldHRlcnMgZG9lc24ndCBoYXZlIHRvIGJlIGEgcmVhbCB3b3JkIChpdCBjb3VsZCBiZSwgZm9yIGV4YW1wbGUsIGEgcHJvZHVjdCBjb2RlIG9yIHVzZXIgaWQpLCBzbyB3ZSBhY3R1YWxseSBjYWxsIHRoZW0gKipzdHJpbmdzKiouIFRvIGRlbm90ZSBhICoqc3RyaW5nKiogd2Ugc3Vycm91bmQgaXQgd2l0aCBxdW90ZSBtYXJrcywgbGlrZSB0aGlzOgoKYGBge3Igc3RyaW5nczAxLCBldmFsID0gRkFMU0V9CiJwbGF0byIKYGBgCgpUaGVyZSBhcmUgZnVuY3Rpb25zIHRoYXQgb3BlcmF0ZSBvbiBzdHJpbmdzLCBleGFjdGx5IGVxdWl2YWxlbnQgdG8gb25lcyBsaWtlIGBzcXJ0KClgIHRoYXQgb3BlcmF0ZSBvbiBudW1iZXJzLiBGb3IgZXhhbXBsZSwgUiBoYXMgYSBmdW5jdGlvbiBgbmNoYXIoKWAgdGhhdCBjb21wdXRlcyBob3cgbWFueSBjaGFyYWN0ZXJzIChpLmUuIGxldHRlcnMpIGFyZSBpbiBpdHMgc3RyaW5nIGFyZ3VtZW50LgoKYGBge3Igc3RyaW5nczAyfQpuY2hhcigicGxhdG8iKQpgYGAKClwKCiMjIyBDb2RlLWFsb25nIEV4ZXJjaXNlCgpXaGF0IGRvIHlvdSB0aGluayB3aWxsIGhhcHBlbiBpZiB5b3UgZ2l2ZSB0aGUgY29tbWFuZHMgYmVsb3c/IEVudGVyIHRoZW0gaW50byB0aGUgUlN0dWRpbyBjb25zb2xlIHRvIHNlZS4KCmBgYHtyIHN0cmluZ3MwMywgZXJyb3I9VFJVRX0KCm5raGFyKCJwbGF0byIpCgpzcXJ0KCJwbGF0byIpCmBgYAoKUmVtZW1iZXIgdGhhdCB0aGUgbGFuZ3VhZ2UgUiBpcyBhIHNldCBvZiB2b2NhYnVsYXJ5IGFuZCBncmFtbWFyIHJ1bGVzIHRoYXQgbXVzdCBiZSBmb2xsb3dlZCAqdmVyeSogc3RyaWN0bHkuIFRoZXJlIGlzIG5vIGZ1bmN0aW9uIGBua2hhcmAgaW4gUidzIHZvY2FidWxhcnksIG9ubHkgYG5jaGFyYC4gQW5kIGZ1bmN0aW9uIGBzcXJ0YCBvbmx5IHVuZGVyc3RhbmRzIGhvdyB0byB3b3JrIG9uIG51bWJlcnMsIG5vdCBvbiBzdHJpbmdzLgoKUiB3aWxsICoqbmV2ZXIqKiB3b3JrIG91dCB3aGF0IHlvdSBtZWFudCB3aGVuIHlvdSBkZXZpYXRlIGZyb20gaXRzIGdyYW1tYXIuIE5vIHByb2dyYW1taW5nIGxhbmd1YWdlIHdpbGwuIElmIHlvdSB2aW9sYXRlIGl0cyBydWxlcywgUiB3aWxsIHRocm93IGFuIGVycm9yLiBCdXQgdGhpcyBjYW4gYmUgdmVyeSBpbnN0cnVjdGl2ZS4gRW50ZXIgdGhlIGZvbGxvd2luZyBjb21tYW5kIGludG8gUlN0dWRpbyBhbmQgY2FyZWZ1bGx5IGNvbnNpZGVyIHRoZSBvdXRjb21lLiBXaGF0IGRvZXMgdGhpcyB0ZWxsIHlvdSBhYm91dCB0aGUgcnVsZXMgb2YgdGhlIFIgbGFuZ3VhZ2U/CgpgYGB7ciBjYXNlLCBlcnJvcj1UUlVFfQpOQ0hBUigicGxhdG8iKQpgYGAKCldlIGtub3cgdGhhdCBSIHVuZGVyc3RhbmRzIHRoZSBmdW5jdGlvbiBgbmNoYXJgIC0tIHdlIHNhdyBpdCB3b3JraW5nIGp1c3QgYSBmZXcgbW9tZW50cyBhZ28uIEJ1dCBub3cgaXQgc2F5cyBpdCBjb3VsZCBub3QgZmluZCB0aGF0IGZ1bmN0aW9uPyBUaGlzIGlzIGJlY2F1c2UsIHRvIFIsIGBuY2hhcmAgYW5kIGBOQ0hBUmAgYXJlIG5vdCB0aGUgc2FtZSB0aGluZy4gUiBpcyBhICoqY2FzZS1zZW5zaXRpdmUqKiBsYW5ndWFnZS4gVXBwZXItY2FzZSBhbmQgbG93ZXItY2FzZSBsZXR0ZXJzIGFyZSBjb21wbGV0ZWx5IGRpZmZlcmVudCBlbnRpdGllcyBpbiBSLiBXaGVuIGdpdmluZyBSIGNvbW1hbmRzIHlvdSBtdXN0IGFsd2F5cyBleGFjdGx5IG1hdGNoIGl0cyBleHBlY3RhdGlvbnMgYWJvdXQgdXBwZXIgYW5kIGxvd2VyIGNhc2UgKHdvb2YpLgoKXAoKIyMgU3RvcmluZyBSZXN1bHRzCgpJbWFnaW5lIHRoYXQgeW91IGhhdmUgdHdvIGxhcmdlIG51bWJlcnMgYW5kLCBmb3Igc29tZSBzb3VuZCBzY2llbnRpZmljIHJlYXNvbiwgeW91IHdpc2ggdG8gdGFrZSB0aGVpciByYXRpbyBhbmQgdGhlbiB0YWtlIHRoZSBzcXVhcmUgcm9vdCBvZiB0aGF0IHZhbHVlLiBMaWtlIHRoaXM6CgpgYGB7ciBzYXZpbmcgcmVzdWx0cyAwMX0KMTk4LjcgLyA2NC41CmBgYAoKYGBge3Igc2F2aW5nIHJlc3VsdHMgMDJ9CnNxcnQoMy4wODA2MikKYGBgCgpUaGlzIG9wZXJhdGlvbiBpcyByaXNreS4gUiBoYXMgZ2l2ZW4geW91IHRoZSByYXRpbyB0byBmaXZlIGFjY3VyYXRlIGRlY2ltYWwgcGxhY2VzLiBCdXQgeW91IG11c3QgdGhlbiBiZSAqdmVyeSBjYXJlZnVsKiB0byBjb3B5IHRoYXQgdmFsdWUgZXhhY3RseSBpbnRvIHRoZSBgc3FydGAgZnVuY3Rpb24sIG9yIHlvdXIgYW5zd2VyIHdpbGwgYmUgd3JvbmcuIEV4dHJhcG9sYXRlIHRoaXMgdG8gdGhvdXNhbmRzIG9mIGRhdGEgb3BlcmF0aW9ucyBvbiBhIGxhcmdlIGRhdGEgc2V0IGFuZCBpdCBpcyBjZXJ0YWluIHRoYXQgZXJyb3JzIHdpbGwgYmUgbWFkZS4KCkl0IHdvdWxkIGJlIG1vcmUgY29udmVuaWVudCwgYW5kIHNhZmVyLCB0byB0YWtlIHRoZSByZXN1bHQgUiBnYXZlIHlvdSBmcm9tIHRoZSBmaXJzdCBzdGF0ZW1lbnQsICpzdG9yZSBpdCBzb21ld2hlcmUsIGFuZCB0aGVuIHBhc3MgdGhlIHN0b3JlZCBlbnRpdHkgdG8gZnVuY3Rpb24gc3FydCouIFRoaXMgaXMsIGluIGZhY3QsIGEgZnVuZGFtZW50YWwgYWN0aW9uIGluIHByb2dyYW1taW5nOiAqKldlIGNhbiBzdG9yZSB2YWx1ZXMgYXMgbmFtZWQgZW50aXRpZXMgKGNhbGxlZCB2YXJpYWJsZXMpIGFuZCB1c2UgdGhlbSB3aGVuZXZlciBhbmQgd2hlcmV2ZXIgd2UgbmVlZCB0aGVtLioqCgpJbiBSLCB0aGlzICJzdG9yaW5nIiBpcyBwZXJmb3JtZWQgd2l0aCB0aGUgKipcPC0gb3BlcmF0b3IqKiAoY2FsbGVkIHRoZSAiYXNzaWdubWVudCIgb3BlcmF0b3IpLiBUaGUgYXNzaWdubWVudCBvcGVyYXRvciBpcyBmb3JtZWQgYnkgdHlwaW5nIGEgbGVmdCBhbmdsZSBicmFja2V0IGFuZCBhIGh5cGhlbi4gSW4gdGhlIGZvbGxvd2luZyBjb2RlIGV4YW1wbGUsIHdlIGRlbW9uc3RyYXRlIHRoZSBhc3NpZ25tZW50IG9wZXJhdG9yLiBXZSBhbHNvIGRlbW9uc3RyYXRlICoqY29tbWVudHMqKi4gSW4gUiwgYW55IHRleHQgdGhhdCBpcyBwcmVmYWNlZCB3aXRoIFwjIGlzIGlnbm9yZWQgcmF0aGVyIHRoYW4gYmVpbmcgdHJlYXRlZCBhcyBhIGNvbW1hbmQuIEl0IGlzIGp1c3QgdGV4dCB0aGF0IHRoZSBwcm9ncmFtbWVyIGFkZHMgZm9yIHRoZWlyIG93biBiZW5lZml0LgoKXAoKIyMjIENvZGUtYWxvbmcgRXhlcmNpc2UKCk1ha2Ugc3VyZSB5b3UgY2FuIGR1cGxpY2F0ZSB0aGlzIGNvZGUsIHdpdGggdGhlIHNhbWUgcmVzdWx0cywgaW4gUlN0dWRpbyAoeW91IGRvbid0IG5lZWQgdG8gdHlwZSB0aGUgY29tbWVudHMpLgoKYGBge3IgdmFyaWFibGVzMDF9CiMgU3RvcmUgdGhlIHJlc3VsdCBvZiB0aGUgZGl2aXNpb24gaW4gYW4gZW50aXR5IChhIHZhcmlhYmxlKSBuYW1lZCByYXRpby4gV2UKIyBhbHdheXMgdXNlIG1lYW5pbmdmdWwgdmFyaWFibGUgbmFtZXMuCnJhdGlvIDwtIDE5OC43IC8gNjQuNSAgCgojIFRoaXMgd2lsbCBkaXNwbGF5IHRoZSB2YWx1ZSBvZiB0aGUgdmFyaWFibGUgbmFtZWQgcmF0aW8uIFRoYXQncyB3aGF0IFIgZG9lcwojIHdoZW4geW91IGVudGVyIGEgbG9uZSB2YXJpYWJsZSBuYW1lLgpyYXRpbyAKCiMgVGhpcyB3aWxsIHBhc3MgdGhlIHZhbHVlIG9mIHJhdGlvIGFzIHRoZSBhcmd1bWVudCB0byB0aGUgc3FydCBmdW5jdGlvbi4Kc3FydChyYXRpbykgIApgYGAKClwKCiMjIFZhcmlhYmxlIE5hbWVzIGFuZCBWYWx1ZXMKCkxvb2sgKip2ZXJ5IGNhcmVmdWxseSoqIGF0IHRoZSB2YXJpYWJsZSBuYW1lIG9uIHRoZSBsZWZ0IGhhbmQgc2lkZSBvZiB0aGUgYXNzaWdubWVudCBvcGVyYXRvciBcPC0uIEl0IGlzIGEgc3RyaW5nIG9mIGNoYXJhY3RlcnMsIGJ1dCAqKml0IGlzIG5vdCBzdXJyb3VuZGVkIGJ5IHF1b3RlIG1hcmtzKiouIFRoaXMgaXMgaG93LCBpbiBSLCB3ZSBkaXN0aW5ndWlzaCBzdHJpbmdzIChhIHdvcmQgdGhpbmcgLS0gcmVtZW1iZXIsIGxpa2UgInBsYXRvIikgZnJvbSB2YXJpYWJsZSBuYW1lcy4KCkluc2lkZSBvdXIgY29tcHV0ZXIsIHZhcmlhYmxlcyBhcmUgaW1wbGVtZW50ZWQgKGNvbmNlcHR1YWxseSkgYXMgc2hvd24gYmVsb3cuIEEgbG9jYXRpb24gaW4gbWVtb3J5IGlzICJuYW1lZCIuIFdoZW4geW91IHJlZmVyIHRvIHRoZSBuYW1lLCB0aGUgY29tcHV0ZXIgc3VwcGxpZXMgd2hhdGV2ZXIgdmFsdWUgaXMgc3RvcmVkIGF0IHRoYXQgbG9jYXRpb24uCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjUwJSIsIGZpZy5jYXA9IkhvdyBWYXJpYWJsZXMgV29yayIsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLWNvbXB1dGVyX3dpdGhfdmFyaWFibGUucG5nIikKYGBgCgpUaGlzIG1lYW5zIHRoYXQgdGhlIHZhbHVlIG9mIGEgdmFyaWFibGUgY2FuIGNoYW5nZSBvdmVyIHRpbWUuIChXZSB3aWxsIHNlZSBsYXRlciB0aGF0IHRoaXMgdHVybnMgb3V0IHRvIGJlIGV4dHJlbWVseSB1c2VmdWwuKQoKYGBge3IgdmFyaWFibGVzMDJ9CiMgU3RvcmUgdGhlIHJlc3VsdCBvZiB0aGUgZGl2aXNpb24gaW4gYW4gZW50aXR5IG5hbWVkIHJhdGlvCnJhdGlvIDwtIDE5OC43IC8gNjQuNSAgCgojIFRoaXMgd2lsbCBkaXNwbGF5IHRoZSB2YWx1ZSBvZiByYXRpby4gVGhhdCdzIHdoYXQgUiBkb2VzIHdoZW4geW91IGVudGVyIGEgbG9uZQojIHZhcmlhYmxlIG5hbWUuCnJhdGlvICAgICAgICAgICAgICAgICAgCgojIENoYW5nZSB0aGUgdmFsdWUgc3RvcmVkIGluIHRoZSB2YXJpYWJsZSBuYW1lZCByYXRpbyBieSBhc3NpZ25pbmcgaXQgdGhlIHJlc3VsdAojIG9mIGEgbmV3IGNvbW1hbmQKcmF0aW8gPC0gMjUuOSAqIDEyLjE1ICAKCiMgU2VlIHRoZSBjdXJyZW50IHZhbHVlCnJhdGlvICAgICAgICAgICAgICAgICAgCgpgYGAKClwKCiMjIENvbXBsZXggVGhpbmdzCgpPbmUgb2YgdGhlIGdyZWF0IHN0cmVuZ3RocyBvZiBSIGZvciBkYXRhIGFuYWx5c2lzIGlzIHRoYXQgInRoaW5ncyIgaW4gUiBhcmVuJ3QgcmVzdHJpY3RlZCB0byBzaW5nbGUgbnVtYmVycyBvciBzaW5nbGUgc3RyaW5ncy4gVGhpbmdzIGluIFIgY2FuIGJlICoqY29sbGVjdGlvbnMqKiAtLSBvcmRlcmVkIHNldHMgb2YgbXVsdGlwbGUgdGhpbmdzLgoKVG8gZ2V0IGEgY29sbGVjdGlvbiwgd2UgbXVzdCBjcmVhdGUgaXQsIHVzaW5nIHRoZSBidWlsdC1pbiBmdW5jdGlvbiBgYygpYC4gVGhlIGMgc3RhbmRzIGZvciAqKmNvbWJpbmUqKi4gVGhpcyBmdW5jdGlvbiBjb21iaW5lcyBtdWx0aXBsZSBhcmd1bWVudHMgaW50byBhIHNpbmdsZSBjb2xsZWN0aW9uIHRoaW5nLiBJbiBSIHRoaXMga2luZCBvZiBjb2xsZWN0aW9uIHRoaW5nIGlzIGNhbGxlZCBhICoqdmVjdG9yKiouCgpcCgojIyMgQ29kZS1hbG9uZyBFeGVyY2lzZQoKRW50ZXIgdGhlc2Ugc3RhdGVtZW50cyBpbnRvIFJTdHVkaW8sIGFuZCBjaGVjayB0aGF0IHlvdSBnZXQgdGhlIHNhbWUgb3V0cHV0LgoKYGBge3IgdmVjdG9ycywgZXJyb3IgPSBUUlVFfQoKIyBUbyBjb21iaW5lIGVsZW1lbnRzIGludG8gYSB2ZWN0b3IsIHBhc3MgdGhlbSB0byBmdW5jdGlvbiBjKCksIGFuZCBzZXBhcmF0ZQojIHRoZW0gd2l0aCBjb21tYXMKdmVjdG9yX29mX3ByaW1lcyA8LSBjKDEsIDUsIDcsIDExKQoKdmVjdG9yX29mX3ByaW1lcwoKYW5pbWFscyA8LSBjKCJBcm1hZGlsbG8iLCAiQnVmZmFsbyIsICJDb3VnYXIiKQoKYW5pbWFscwoKbWl4dHVyZSA8LSBjKDEsICJCdWZmYWxvIiwgNDIpCgptaXh0dXJlCmBgYAoKTG9vayB2ZXJ5IGNhcmVmdWxseSBhdCB0aGUgdGhpcmQgdmVjdG9yIHZhcmlhYmxlLCBtaXh0dXJlLiBOb3RlIHRoYXQsIHdoZW4gaXQgZGlzcGxheXMgdGhlIHZlY3RvciwgUiBoYXMgcHV0IHF1b3RlIG1hcmtzIGFyb3VuZCAxIGFuZCA0Mi4gVGhhdCBpcywgUiB0aGlua3MgdGhleSBhcmUgc3RyaW5ncyAoYSBzZXJpZXMgb2YgYWxwaGFudW1lcmljIGNoYXJhY3RlcnMpLCBub3QgbnVtYmVycy4gRnJvbSB0aGlzIHdlIHNlZSB0aGF0OgoKMS4gIFZlY3RvcnMgbXVzdCBiZSBob21vZ2VuZW91cy4gVGhhdCBpcywgYWxsIHRoZSBlbGVtZW50cyBpbiB0aGUgdmVjdG9yIG11c3QgYmUgdGhlIHNhbWUga2luZCAodHlwZSkgb2YgdGhpbmcuCgoyLiAgSWYgeW91IGRvbid0IGZvbGxvdyBSJ3MgcnVsZXMsIGl0IHdpbGwgc29tZXRpbWVzIGp1c3QgZW5mb3JjZSB0aGVtIG9uIHlvdXIgYmVoYWxmLiBIZXJlIGl0IHNlZXMgdGhhdCBCdWZmYWxvIGlzIGRlZmluaXRlbHkgYSBzdHJpbmcuIEl0IGtub3dzIHRoYXQgdmVjdG9yIGVsZW1lbnRzIGhhdmUgdG8gYmUgaG9tb2dlbmVvdXMsIHNvIGl0IG1ha2VzIDEgYW5kIDQyIGludG8gc3RyaW5ncyAiMSIgYW5kICI0MiIuIFIgaXMgYm9zc3kgdGhpcyB3YXkuCgooVGhlcmUgYXJlIG1vcmUgY29tcGxleCB0aGluZ3MgaW4gUiB0aGF0IGFsbG93IGNvbWJpbmF0aW9ucyBvZiBudW1iZXJzIGFuZCBzdHJpbmdzLiBHb29nbGUgIlIgbGlzdHMiIHRvIGV4cGxvcmUuKQoKIyMgT3BlcmF0aW5nIG9uIFZlY3RvcnMKClRoZSBvcGVyYXRvcnMgYW5kIGZ1bmN0aW9ucyB3ZSBoYXZlIHVzZWQgc28gZmFyIG9uIHNpbmdsZSBudW1iZXJzIGFuZCBzdHJpbmdzIChlLmcuIGBzcXJ0YCwgYG5jaGFyYCkgd2lsbCBhbHNvIHdvcmsgb24gdmVjdG9ycy4gV2hlbiB5b3UgdXNlIHRoaXMga2luZCBvZiBmdW5jdGlvbiBvciBvcGVyYXRvciB3aXRoIGEgdmVjdG9yLCBSIGFwcGxpZXMgaXQgdG8gZWFjaCBlbGVtZW50IGluIHR1cm4sIGFuZCByZXR1cm5zIGFsbCB0aGUgcmVzdWx0cy4KClwKCiMjIyBDb2RlLWFsb25nIEV4ZXJjaXNlCgpFbnRlciB0aGVzZSBzdGF0ZW1lbnRzIGludG8gUlN0dWRpby4KCmBgYHtyIHZlY3RvciBvcGVyYXRpb25zfQpwcmltZXMgPC0gYygxLCA1LCA3LCAxMSkKCnByaW1lcyAqIDIKCnNxcnQocHJpbWVzKQpgYGAKClwKCiMjIyBXcml0ZSBZb3VyIE93biBDb2RlCgpFbnRlciBhIG5ldyBjb21tYW5kIHRvIGRpdmlkZSBhbGwgdGhlIHZhbHVlcyBpbiB2ZWN0b3IgKipwcmltZXMqKiBieSAyLiBNYWtlIHN1cmUgeW91IGdldCB0aGVzZSByZXN1bHRzOgoKYGBge3IgdmVjdG9yIDIsIGVjaG8gPSBGQUxTRX0KcHJpbWVzLzIKYGBgCgpOb3RlIHRoYXQgdmVjdG9yIG9wZXJhdGlvbnMgd29yayByZWdhcmRsZXNzIG9mIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgaW4gdGhlIHZlY3Rvci4gWW91IGNhbiBoYXZlIDEsMDAwLDAwMCBkYXRhIHZhbHVlcyBpbiB5b3VyIHZlY3RvciBhbmQgaXQgc3RpbGwgcmVxdWlyZXMgb25seSBvbmUgY29tbWFuZCB0byBwcm9jZXNzIHRoZW0gYWxsLgoKXAoKIyMgV2hvbGUtVmVjdG9yIE9wZXJhdGlvbnMKClRoZXJlIGFyZSBhbHNvIGZ1bmN0aW9ucyB3aGljaCBzdW1tYXJpc2UgdGhlIGNvbnRlbnRzIG9mIGEgdmVjdG9yLiBGb3IgZXhhbXBsZSwgUiBoYXMgYSBmdW5jdGlvbiBgbWVhbmAgdGhhdCBjb21wdXRlcyB0aGUgbWF0aGVtYXRpY2FsIGF2ZXJhZ2Ugb2YgdGhlIGVsZW1lbnRzIGluIGEgdmVjdG9yLCBhbmQgYSBmdW5jdGlvbiBgc2RgIHRoYXQgY29tcHV0ZXMgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgZWxlbWVudHMgaW4gYSB2ZWN0b3IuIFRoZXJlIGFyZSBodW5kcmVkcyBvZiBzdWNoIGZ1bmN0aW9ucyBhdmFpbGFibGUsIGFuZCB3ZSB3aWxsIGV4cGxvcmUgbWFueSBvZiB0aGVtIHRocm91Z2hvdXQgdGhpcyBtaW5pLWNvdXJzZS4KClwKCiMjIyBDb2RlLWFsb25nIEV4ZXJjaXNlCgpFbnRlciB0aGVzZSBzdGF0ZW1lbnRzIGludG8gUlN0dWRpby4KCmBgYHtyIHZlY3RvciBzdW1tYXJ5IG9wZXJhdGlvbnN9CmV4YW1fc2NvcmVzX3ZlY3RvciA8LSBjKDgyLCA0MywgOTcsIDU2LCA3OCkgIyBDcmVhdGUgYW4gZXhhbXBsZSBkYXRhIHZlY3RvcgoKbWVhbihleGFtX3Njb3Jlc192ZWN0b3IpICAjIENvbXB1dGUgdGhlIG1hdGhlbWF0aWNhbCBtZWFuIG9mIHRoZSBleGFtIHNjb3JlcwoKc2QoZXhhbV9zY29yZXNfdmVjdG9yKSAjIENvbXB1dGUgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgZXhhbSBzY29yZXMKYGBgCgpcCgojIyMgV3JpdGUgeW91ciBvd24gY29kZQoKVGhlIFIgZnVuY3Rpb25zIGBtaW5gIGFuZCBgbWF4YCByZXR1cm4gdGhlIG1pbmltdW0gYW5kIG1heGltdW0gdmFsdWVzIG9mIGEgdmVjdG9yLiBXcml0ZSBjb21tYW5kcyB0byB1c2UgdGhlc2UgZnVuY3Rpb25zIG9uICoqZXhhbV9zY29yZXNfdmVjdG9yKiogZnJvbSB0aGUgcHJldmlvdXMgZXhlcmNpc2UuCgpOb3QgYWxsIFIgZnVuY3Rpb25zIGhhdmUgc3VjaCBvYnZpb3VzIG5hbWVzLiBVc2UgR29vZ2xlIG9yIHlvdXIgZmF2b3VyaXRlIFIgdGV4dGJvb2sgdG8gZmluZCBvdXQgd2hhdCBmdW5jdGlvbiB0byBjYWxsIHRvIGdldCAqdGhlIG51bWJlciBvZiBlbGVtZW50cyBpbiBhIHZlY3RvciouIFRlc3QgdGhpcyBmdW5jdGlvbiBvbiAqKmV4YW1fc2NvcmVzX3ZlY3RvcioqLgoKXAoKXAoKIyMgRXZlbiBNb3JlIENvbXBsZXggVGhpbmdzCgpXZSBoYXZlIHNlZW4gdGhhdCBSIHVuZGVyc3RhbmRzIHNpbmdsZSBudW1iZXJzIG9yIHN0cmluZ3MsIGFuZCBjb2xsZWN0aW9ucyBvZiBudW1iZXJzIG9yIHN0cmluZ3MgKHZlY3RvcnMpLiBSIGFsc28gdW5kZXJzdGFuZHMgY29tcGxldGUgdGFibGVzIG9mIGRhdGEgKGluIHJvd3MgYW5kIGNvbHVtbnMsIGxpa2Ugc3ByZWFkc2hlZXRzIGFyZSBhcnJhbmdlZCkuIEluIGZhY3QsIG1vc3QgcmVhbCBkYXRhIGFuYWx5c2lzIGluIFIgb3BlcmF0ZXMgb24gdGFibGVzIG9mIGRhdGEuIFNvbWUgUiBmdW5jdGlvbnMgcmVxdWlyZSB5b3UgdG8gZmlyc3QgZXh0cmFjdCBhIHJvdyBvciBjb2x1bW4gZnJvbSB5b3VyIGRhdGEgdGFibGU7IG90aGVyIGZ1bmN0aW9ucyB3aWxsIHRha2UgYW4gZW50aXJlIHRhYmxlIGFuZCBvcGVyYXRlIG9uIGl0IGF0IG9uY2UgKGZvciBleGFtcGxlLCBtYW55IG9mIHRoZSBmdW5jdGlvbnMgdGhhdCBwZXJmb3JtIGluZmVyZW50aWFsIHN0YXRpc3RpY2FsIGFuYWx5c2VzIG9wZXJhdGUgb24gd2hvbGUgdGFibGVzKS4gSW4gbGF0ZXIgbW9kdWxlcywgd2Ugd2lsbCB1c2Ugc29tZSBvZiB0aGVzZSBmdW5jdGlvbnMuIEJ1dCBiZWZvcmUgd2UgZG8gdGhhdCwgdGhlcmUgaXMgb25lIG1vcmUgKip2ZXJ5IGltcG9ydGFudCoqIG1lY2hhbmljYWwgZmVhdHVyZSBvZiBSU3R1ZGlvLi4uCgpcCgojIFNhdmluZyBZb3VyIENvZGUKCldlIGhhdmUgdHlwZWQgYSBsb3Qgb2YgUiBjb21tYW5kcyBpbnRvIHRoZSBjb25zb2xlLiBXaGVuIHdlIGNsb3NlIFJTdHVkaW8sICoqYWxsIHRoYXQgY29kZSB3aWxsIGJlIGdvbmUgZm9yZXZlcioqLiBJZiB3ZSB3YW50IHRvIGRvIGFueSBvZiB0aGlzIGFnYWluLCB3ZSBoYXZlIHRvIHN0YXJ0IG92ZXIgZnJvbSB0aGUgYmVnaW5uaW5nIGFuZCB0eXBlIGV2ZXJ5dGhpbmcgaW4gYWdhaW4uIFRoaXMgaXMgdW5hY2NlcHRhYmxlLiBTbywgUlN0dWRpbyBsZXRzIHVzIHR5cGUgb3VyIGNvZGUgaW50byBhIGZpbGUsIHNhdmUgdGhlIGZpbGUsIGFuZCByZXRyaWV2ZSB0aGUgY29kZSB3aGVuZXZlciB3ZSB3YW50LCBzbyB0aGF0IHdlIGNhbiBtb2RpZnkgaXQgb3Igc2ltcGx5IHJ1biBpdCBhZ2Fpbi4KClwKCiMjIFVzaW5nIGEgU2NyaXB0IEZpbGUKCjFcLiBGcm9tIHRoZSBtZW51IGF0IHRoZSB0b3Agb2YgdGhlIFJTdHVkaW8gc2NyZWVuIHNlbGVjdCBGaWxlLVw+TmV3IEZpbGUgdGhlbiBjbGljayBvbiBSIFNjcmlwdC4gKEFsdGVybmF0aXZlbHksIHlvdSBjYW4gdHlwZSBzaGlmdCtjdHJsK04gKFdpbmRvd3MpIG9yIHNoaWZ0K2NtZCtOIChNYWMpLikKCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNTAlIiwgb3V0LmV4dHJhID0gJ3N0eWxlPSJib3JkZXI6MXB4IHNvbGlkIGJsYWNrIicsIGZpZy5jYXAgPSAiTWFraW5nIGFuIFIgU2NyaXB0IEZpbGUiLCBlY2hvID0gRkFMU0V9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1tYWtlX3NjcmlwdC5wbmciKQpgYGAKCjJcLiBUaGlzIG9wZW5zIGEgbmV3IHVudGl0bGVkIGZpbGUgaW4gYW4gZWRpdGluZyBwYW5lIGluIHRoZSB1cHBlciBsZWZ0IG9mIHRoZSBSU3R1ZGlvIHNjcmVlbi4gVGhlIGNvbnNvbGUgcGFuZSB3aWxsIGJlIHB1c2hlZCBkb3duIHRvIHRoZSBib3R0b20gaGFsZiBvZiB0aGUgc2NyZWVuLiBZb3UgY2FuIGNsaWNrIGFuZCBkcmFnIHRoZSBkaXZpZGVycyBiZXR3ZWVuIHRoZSBmb3VyIHBhbmVzIHRvIGNoYW5nZSB0aGVpciBzaXplcyBhcyB5b3UgcHJlZmVyLgoKYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoID0gIjEwMCUiLCBvdXQuZXh0cmEgPSAnc3R5bGU9ImJvcmRlcjoxcHggc29saWQgYmxhY2siJywgZmlnLmNhcCA9ICJOZXcgU2NyaXB0IFRhYiIsIGZpZy5wb3MgPSAnSCcsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW5ld19zY3JpcHQucG5nIikKYGBgCgozXC4gRnJvbSB0aGUgbWFpbiBSU3R1ZGlvIG1lbnUgc2VsZWN0IEZpbGUtXD5TYXZlIEFzLi4gdG8gc2F2ZSB5b3VyIGZpbGUuIEFsd2F5cyBnaXZlIHlvdXIgZmlsZXMgZGVzY3JpcHRpdmUgbmFtZXMgdG8gbWFrZSBpdCBlYXN5IHRvIGZpbmQgdGhlIG9uZSB5b3Ugd2FudCBsYXRlci4KCjRcLiBZb3UgY2FuIHR5cGUgUiBjb21tYW5kcyBpbnRvIHRoZSBuZXcgZmlsZSAoaW4gdGhlIHVwcGVyIGxlZnQgcGFuZSkgZXhhY3RseSBhcyB5b3UgdHlwZWQgaW50byB0aGUgY29uc29sZS4KCjVcLiBFeGVjdXRpbmcgYSBjb21tYW5kIHRoYXQgaXMgdHlwZWQgaW50byBhIGZpbGUgd29ya3MgYSBsaXR0bGUgZGlmZmVyZW50bHkgdGhhbiBleGVjdXRpbmcgYSBjb21tYW5kIHRoYXQgaXMgdHlwZWQgaW50byB0aGUgY29uc29sZS4gVG8gZXhlY3V0ZSBhIHNpbmdsZSBsaW5lIG9mIGNvZGUgaW4gdGhlIGZpbGUsIGNsaWNrIHlvdXIgbW91c2UgY3Vyc29yIGFueXdoZXJlIG9uIHRoZSBsaW5lIG9mIGNvZGUuICoqRE8gTk9UIFNFTEVDVCBBTlkgQ0hBUkFDVEVSUy4gSE9MRCBUSEUgTU9VU0UgU1RJTEwgV0hJTEUgQ0xJQ0tJTkcqKi4gVGhlbiB0eXBlIGN0cmwrRW50ZXIgKFdpbmRvd3MpIG9yIGNtZCtFbnRlciAoTWFjKS4KCjZcLiBUbyBleGVjdXRlIG11bHRpcGxlIGxpbmVzIG9mIGNvZGUgaW4gdGhlIGZpbGUsIHNlbGVjdCBhbGwgdGhlIGNvZGUgeW91IHdhbnQgYnkgY2xpY2tpbmcgYW5kIGRyYWdnaW5nIHRoZSBtb3VzZSAoY3RybCtBIG9yIGNtZCtBIGZvciB0aGUgd2hvbGUgZmlsZSksIHRoZW4gdHlwZSBjdHJsK0VudGVyIG9yIGNtZCtFbnRlci4KCjdcLiBUaGUgb3V0cHV0IGZyb20geW91ciBjb2RlIHdpbGwgYmUgd3JpdHRlbiB0byB0aGUgY29uc29sZSwganVzdCBhcyB0aG91Z2ggeW91IGhhZCB0eXBlZCB0aGUgY29kZSB0aGVyZS4KCjhcLiBBZnRlciBlbnRlcmluZyBzb21lIGNvZGUgaW50byB5b3VyIGZpbGUsIHNhdmUgaXQgKHRoZSBwcm9ncmFtbWVyJ3MgbW90dG8gaXMgU2F2ZSBFYXJseSwgU2F2ZSBPZnRlbikuIFlvdSBjYW4gdGhlbiBzYWZlbHkgZXhpdCB0aGUgUlN0dWRpbyBwcm9ncmFtLgoKOVwuIEdvIHRvIHdoZXJldmVyIHlvdSBzYXZlZCB5b3VyIG5hbWVkIGNvZGUgZmlsZSAoaXQgd2lsbCBoYXZlIHN1ZmZpeCAuUikgRG91YmxlLWNsaWNrIG9uIGl0IGFuZCBpdCBzaG91bGQgb3BlbiBpbiBSU3R1ZGlvLiBJZiBpdCBvcGVucyBpbiBzb21ldGhpbmcgZWxzZSAoZS5nLiBXb3JkIG9yIE5vdGVwYWQpLCB0aGlzIGp1c3QgbWVhbnMgdGhhdCB5b3VyIG1hY2hpbmUgaXMgbm90IGNvbmZpZ3VyZWQgdG8gYXNzb2NpYXRlIC5SIGZpbGVzIHdpdGggUlN0dWRpby4gSW4gdGhpcyBjYXNlLCAqKnJpZ2h0LWNsaWNrKiogb24gdGhlIGZpbGUsIHNlbGVjdCBPcGVuIFdpdGgsIGFuZCB0aGVuIFJTdHVkaW8uIChXZSBzZWUgYSBtb3JlIGNvbnZlbmllbnQgd29ya2Zsb3cgaW4gYSBtb21lbnQuKQoKMTBcLiBXaGVuIHRoZSBmaWxlIGlzIG9wZW4gaW4gUlN0dWRpbyB5b3UgY2FuIHJ1biBhbGwgeW91ciBjb2RlIGFnYWluIChzZWUgaXRlbXMgNSBhbmQgNiBhYm92ZSkgd2l0aG91dCBoYXZpbmcgdG8gcmV0eXBlIGFueXRoaW5nLgoKXAoKIyMgVXNpbmcgUHJvamVjdHMgaW4gUlN0dWRpbwoKQW4gUlN0dWRpbyAqKnByb2plY3QqKiBpcyBhIGZvbGRlciwgY3JlYXRlZCBmcm9tIGluc2lkZSBSU3R1ZGlvLCB0aGF0IGNvbnRhaW5zIHJlbGF0ZWQgc2NyaXB0IGZpbGVzLCBkYXRhIGZpbGVzLCBhbmQgUlN0dWRpbyAqKm1ldGFkYXRhKiogZmlsZXMgd2hpY2ggZW5zdXJlIFIgY29kZSBydW5zIGNvcnJlY3RseSBhbmQgZWZmaWNpZW50bHkuIE1vc3QgZXhwZXJpZW5jZWQgUiBkZXZlbG9wZXJzICphbHdheXMqIG9yZ2FuaXNlIHRoZWlyIHdvcmsgaW50byBwcm9qZWN0cy4gVGhpcyBpcyBsb2dpY2FsbHkgc2ltaWxhciB0byBvcmdhbmlzaW5nIHlvdXIgcmVndWxhciBjb21wdXRlciBmaWxlcyBpbnRvIGZvbGRlcnMgLS0gaXQga2VlcHMgcmVsYXRlZCBtYXRlcmlhbCBidW5kbGVkIHRvZ2V0aGVyLCBtYWtpbmcgaXQgZWFzaWVyIHRvIHdvcmsgd2l0aC4KClR5cGljYWxseSwgY3JlYXRpbmcgYSBwcm9qZWN0IGlzIHRoZSAqZmlyc3QqIHN0ZXAgaW4gUiBkZXZlbG9wbWVudC4gV2hlbiBhIHByb2plY3QgaXMgaW5pdGlhbGx5IGNyZWF0ZWQsIGl0IGNvbnRhaW5zIG9ubHkgdGhlIFJTdHVkaW8gbWV0YWRhdGEgZmlsZXMuIFRoZW4gZGF0YSBmaWxlcyBhcmUgYWRkZWQgYnkgc2ltcGx5IG1vdmluZyB0aGVtIGludG8gZm9sZGVyIGxpa2UgYW55IG90aGVyIGZpbGUuIFNjcmlwdCBmaWxlcyBhbmQgb3V0cHV0IGZpbGVzIGFyZSBhZGRlZCB0byB0aGUgcHJvamVjdCBmcm9tIGluc2lkZSBSU3R1ZGlvIGFzIHRoZSB3b3JrIHByb2dyZXNzZXMuIEF0IGFsbCB0aW1lcywgYWxsIHRoZSByZWxhdGVkIGNvbnRlbnQgZm9yIHRoZSBwcm9qZWN0IGlzIHRpZGlseSBjb250YWluZWQgaW4gdGhlIHByb2plY3QgZm9sZGVyIGZvciBlYXN5IGxvY2F0aW9uIGFuZCB1c2UuCgojIyMgQ3JlYXRpbmcgYSBQcm9qZWN0IGluIFJTdHVkaW8KCjFcLiBGcm9tIHRoZSBtYWluIG1lbnUgc2VsZWN0IEZpbGUgLT4gTmV3IFByb2plY3QKCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNTAlIiwgb3V0LmV4dHJhID0gJ3N0eWxlPSJib3JkZXI6MXB4IHNvbGlkIGJsYWNrIicsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW5ld19wcm9qZWN0XzAxLnBuZyIpCmBgYAoKCjJcLiBJbiB0aGUgcmVzdWx0aW5nIHBvcC11cCB3aW5kb3csIHNlbGVjdCBOZXcgRGlyZWN0b3J5LCB0aGVuIE5ldyBQcm9qZWN0LCB0byBuYXZpZ2F0ZSB0byB0aGUgQ3JlYXRlIE5ldyBQcm9qZWN0IGRpYWxvZ3VlIGJveC4KCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjUwJSIsIG91dC5leHRyYSA9ICdzdHlsZT0iYm9yZGVyOjFweCBzb2xpZCBibGFjayInLCBlY2hvID0gRkFMU0V9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1uZXdfcHJvamVjdF8wMi5wbmciKQpgYGAKCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNTAlIiwgb3V0LmV4dHJhID0gJ3N0eWxlPSJib3JkZXI6MXB4IHNvbGlkIGJsYWNrIicsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW5ld19wcm9qZWN0XzAzLnBuZyIpCmBgYAoKYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI1MCUiLCBvdXQuZXh0cmEgPSAnc3R5bGU9ImJvcmRlcjoxcHggc29saWQgYmxhY2siJywgZWNobyA9IEZBTFNFfQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtbmV3X3Byb2plY3RfMDQucG5nIikKYGBgCgozXC4gKipUSElTIElTIFRIRSBUUklDS1kgUEFSVC4qKiBUaGUgQ3JlYXRlIE5ldyBQcm9qZWN0IGRpYWxvZ3VlIGhhcyBhIHRleHQgYm94LCBmb2xsb3dlZCBieSBhIEJyb3dzZSBidXR0b24uIENvdW50ZXJpbnR1aXRpdmVseSwgeW91IGhhdmUgdG8gZG8gdGhlIEJyb3dzZSBidXR0b24gKmZpcnN0Ki4gQ2xpY2sgQnJvd3NlIGFuZCBuYXZpZ2F0ZSAqKnRvIHdoZXJlIHlvdSB3YW50IHlvdXIgcHJvamVjdCBmb2xkZXIgdG8gYmUgY3JlYXRlZCoqLiBPbmx5IHRoZW4sIGNsaWNrIGluIHRoZSBEaXJlY3RvcnkgTmFtZSB0ZXh0IGJveCBhbmQgdHlwZSBhIG5hbWUgZm9yIHlvdXIgcHJvamVjdCBmb2xkZXIuIEJlIHN1cmUgdG8gbWFrZSB0aGlzIG5hbWUgZGVzY3JpcHRpdmUgLS0gaXQgaXMgYXdrd2FyZCB0byBjaGFuZ2UgdGhlIG5hbWUgb2YgYSBwcm9qZWN0IGFmdGVyIGl0IGlzIGNyZWF0ZWQuIENsaWNrIHRoZSBDcmVhdGUgUHJvamVjdCBidXR0b24gdG8gZmluaXNoLiBSU3R1ZGlvIHdpbGwgcmVmcmVzaCBhcyBpdCBuYXZpZ2F0ZXMgdG8geW91ciBuZXcgZW1wdHkgcHJvamVjdC4KCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNTAlIiwgb3V0LmV4dHJhID0gJ3N0eWxlPSJib3JkZXI6MXB4IHNvbGlkIGJsYWNrIicsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW5ld19wcm9qZWN0XzA1LnBuZyIpCmBgYAoKNFwuIFF1aXQgb3V0IG9mIFJTdHVkaW8sIGFuZCBuYXZpZ2F0ZSB0byB0aGUgZGlyZWN0b3J5IHdoZXJlIHlvdSBjcmVhdGVkIHlvdXIgcHJvamVjdC4gWW91IHdpbGwgZmluZCBhIG5ldyBmb2xkZXIgbGFiZWxsZWQgd2l0aCB0aGUgcHJvamVjdCBuYW1lIHlvdSBjaG9zZS4KCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNTAlIiwgb3V0LmV4dHJhID0gJ3N0eWxlPSJib3JkZXI6MXB4IHNvbGlkIGJsYWNrIicsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW5ld19wcm9qZWN0XzA2LnBuZyIpCmBgYAoKNVwuIE9wZW4gdGhlIHByb2plY3QgZm9sZGVyLiBJdCB3aWxsIGNvbnRhaW4gYSBmb2xkZXIgY2FsbGVkIC5ScHJvai51c2VyIGFuZCBhIGZpbGUgY2FsbGVkIC5SaGlzdG9yeS4gVGhlc2UgYXJlIFJTdHVkaW8gbWV0YWRhdGEgZmlsZXMgLS0gbGVhdmUgdGhlbSBhbG9uZS4gKFlvdSBtYXkgbmVlZCB0byB0dXJuIG9uIGhpZGRlbiBmaWxlcyBpbiBXaW5kb3dzIEV4cGxvcmVyIG9yIHRoZSBNYWMgRmluZGVyIHRvIHNlZSB0aGVzZSBmaWxlcy4pIEl0IGFsc28gY29udGFpbnMgYSBmaWxlIHdpdGggdGhlIHByb2plY3QgbmFtZSBhbmQgc3VmZml4IC5ScHJvai4KCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNTAlIiwgb3V0LmV4dHJhID0gJ3N0eWxlPSJib3JkZXI6MXB4IHNvbGlkIGJsYWNrIicsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW5ld19wcm9qZWN0XzA3LnBuZyIpCmBgYAoKNlwuIFdoZW4geW91IG9wZW4gdGhlIHByb2plY3QgaW4gUlN0dWRpbyAod2Ugc2VlIGhvdyBpbiBhIG1vbWVudCkgdGhlIHByb2plY3QgZm9sZGVyIHdpbGwgYmUgaXRzICoqd29ya2luZyBkaXJlY3RvcnkqKi4gVGhhdCBpcywgUlN0dWRpbyB3aWxsIGJlICJsb29raW5nIGF0IiB0aGlzIGZvbGRlci4gSXQgd2lsbCBiZSBhYmxlIHRvIGFjY2VzcyBhbnkgZmlsZXMgaW4gdGhpcyBmb2xkZXI7IHdoZW4geW91IGdlbmVyYXRlIG91dHB1dCBmaWxlcywgdGhleSB3aWxsIGJlIHdyaXR0ZW4gdG8gdGhpcyBmb2xkZXIuIFRvIGlsbHVzdHJhdGUgdGhpcywgSSBoYXZlIHBsYWNlZCBhbiBFeGNlbCBmaWxlIGludG8gbXkgbmV3IHByb2plY3QgZm9sZGVyLCBhbmQgd2Ugd2lsbCBzZWUgaG93IGl0IGFwcGVhcnMgdG8gUlN0dWRpby4gWW91IGNhbiBwbGFjZSBmaWxlcyBpbiB5b3VyIHByb2plY3QgZm9sZGVyIGJ5IGNvcHkvcGFzdGUsIG1vdmluZyBpbiB0aGUgRmluZGVyLCBvciBjcmVhdGluZyBuZXcgZmlsZXMsIGV4YWN0bHkgYXMgeW91IHdvcmsgd2l0aCBmaWxlcyBpbiB0aGUgb3JkaW5hcnkgd2F5IGZvciB5b3VyIG9wZXJhdGluZyBzeXN0ZW0uCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjUwJSIsIG91dC5leHRyYSA9ICdzdHlsZT0iYm9yZGVyOjFweCBzb2xpZCBibGFjayInLCBlY2hvID0gRkFMU0V9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1uZXdfcHJvamVjdF8wOC5wbmciKQpgYGAKCjdcLiBEb3VibGUgY2xpY2sgb24gdGhlIC5ScHJvaiBmaWxlIGluIHlvdXIgcHJvamVjdCBmb2xkZXIuIFRoaXMgYXV0b21hdGljYWxseSBvcGVucyB5b3VyIHByb2plY3QgaW4gUlN0dWRpbyBhbmQgc2V0cyB0aGUgd29ya2luZyBkaXJlY3RvcnkgKHdoYXQgUlN0dWRpbyBjYW4gInNlZSIpIGNvcnJlY3RseS4gTm90ZSB0aGF0IHRoZSBGaWxlcyB0YWIgaW4gdGhlIGxvd2VyIHJpZ2h0IHBhbmUgc2hvd3MgdGhlIGNvbnRlbnRzIG9mIHRoZSBwcm9qZWN0IGZvbGRlciwgaW5jbHVkaW5nIHRoZSBhZGRlZCBzcHJlYWRzaGVldCBmaWxlLgoKYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI1MCUiLCBvdXQuZXh0cmEgPSAnc3R5bGU9ImJvcmRlcjoxcHggc29saWQgYmxhY2siJywgZWNobyA9IEZBTFNFfQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtbmV3X3Byb2plY3RfMDkucG5nIikKYGBgCgo4XC4gV2hlbiB3b3JraW5nIHdpdGggUiB3ZSByZWNvbW1lbmQgdGhhdCB5b3UgY3JlYXRlIGEgbmV3IHByb2plY3QgZm9yIGV2ZXJ5IG1vZHVsZSBvZiB3b3JrLiBUaGUgZXhhY3QgbGV2ZWwgb2YgZGV0YWlsIHRoYXQgZGVmaW5lcyBhICJtb2R1bGUgb2Ygd29yayIgd2lsbCBiZWNvbWUgcGFydCBvZiB5b3VyIHByb2Zlc3Npb25hbCBzdHlsZS4gV2UgZnVydGhlciByZWNvbW1lbmQgdGhhdCB5b3UgKipBTFdBWVMqKiBiZWdpbiB3b3JraW5nIG9uIGFueSBSU3R1ZGlvIHByb2plY3QgYnkgZG91YmxlLWNsaWNraW5nIG9uIHRoZSAuUnByb2ogZmlsZS4gRG8gbm90IG9wZW4gUlN0dWRpbyBkaXJlY3RseSBhbmQgdGhlbiB3YW5kZXIgYXJvdW5kIGxvb2tpbmcgZm9yIHlvdXIgcHJvamVjdC4gCgpGb3IgYSBkZXRhaWxlZCBkaXNjdXNzaW9uIG9mIGFkdmFuY2VkIFJTdHVkaW8gcHJvamVjdCBvcmdhbmlzYXRpb24gYW5kIHVzZSwgc2VlIFtSIGZvciBEYXRhIFNjaWVuY2UgLSBXb3JrZmxvdzogUHJvamVjdHMgKGh0dHBzOi8vcjRkcy5oYWQuY28ubnovd29ya2Zsb3ctcHJvamVjdHMuaHRtbCldKGh0dHBzOi8vcjRkcy5oYWQuY28ubnovd29ya2Zsb3ctcHJvamVjdHMuaHRtbCkgCgoKIyMgQW4gRXZlbiBCZXR0ZXIgU2NyaXB0IEZpbGUKCkEgYmFzaWMgc2NyaXB0IGZpbGUgKG9mIHR5cGUgLlIpIHdpbGwgc3RvcmUgYW5kIHByZXNlcnZlIHlvdXIgY29kZS4gUlN0dWRpbyBhbHNvIHByb3ZpZGVzICoqUiBNYXJrZG93bioqIGZpbGVzIChvZiB0eXBlIC5SbWQpIHRoYXQgY2FuIGRvIG11Y2ggbW9yZS4gUiBNYXJrZG93biBpcyBhbiBleHRlbmRlZCBzY3JpcHQgZm9ybWF0IHRoYXQgYWxsb3dzIHlvdSB0byBlbWJlZCBSIGNvbW1hbmRzIGluIGZvcm1hdHRlZCB0ZXh0LiBSU3R1ZGlvIHByb2Nlc3NlcyBSIE1hcmtkb3duIGZpbGVzLCBwcm9kdWNpbmcgSFRNTCwgV29yZCwgb3IgcGRmIG91dHB1dCBmaWxlcy4gRHVyaW5nIHByb2Nlc3NpbmcgKHdoaWNoIGlzIGNhbGxlZCAqa25pdHRpbmcqKSBSU3R1ZGlvIHJ1bnMgYW55IGVtYmVkZGVkIFIgY29tbWFuZHMgYW5kICoqaW5zZXJ0cyB0aGUgcmVzdWx0cyBpbnRvIHRoZSBvdXRwdXQgZG9jdW1lbnQqKi4gWW91IGRvbid0IG5lZWQgdG8gcHJvY2VzcyB5b3VyIGRhdGEgaW4gUlN0dWRpbyBhbmQgdGhlbiBjb3B5L3Bhc3RlIHRoZSByZXN1bHRzIGludG8gYSBzZXBhcmF0ZSBXb3JkIGRvY3VtZW50LiBZb3UgY2FuIGluc2VydCB0aGUgY29kZSBkaXJlY3RseSBpbnRvIHlvdXIgdGV4dCBpbiBhbiBSIE1hcmtkb3duIGZpbGUsIGFuZCBpdCB3aWxsIGJlIGV4ZWN1dGVkIHdoZW4gUlN0dWRpbyBrbml0cy4gCgpXZSB3aWxsIGNvdmVyIFJNYXJrZG93biAoYW5kIGl0cyBuZXh0LWdlbmVyYXRpb24gdmVyc2lvbiBRdWFydG8pIGluIGRlcHRoIGluIFtNb2R1bGUgNF0oMDQtY29tbXVuaWNhdGUuaHRtbCksIGJ1dCB3ZSBpbnRyb2R1Y2UgdGhlIHByb2Nlc3MgYnJpZWZseSBoZXJlOgoKMVwuIEluIFJTdHVkaW8sIGNsaWNrIG9uIHRoZSBGaWxlIG1lbnUsIHNlbGVjdCBOZXcgRmlsZSBhbmQsIGZyb20gdGhlIHN1Ym1lbnUgdGhhdCBvcGVucywgY2xpY2sgb24gUiBNYXJrZG93bi4KCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNTAlIiwgZmlnLmNhcCA9ICJDcmVhdGUgYW4gUiBNYXJrZG93biBGaWxlIiwgZmlnLnBvcyA9ICJIIiwgZWNobyA9IEZBTFNFfQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtbWFrZV9ybWQucG5nIikKYGBgCgoyXC4gQSBkaWFsb2d1ZSBib3ggd2lsbCBvcGVuLCB3aGVyZSB5b3UgZW50ZXIgYSB0aXRsZSBmb3IgeW91ciBkb2N1bWVudCwgdGhlIG5hbWUgb2YgdGhlIGF1dGhvciBhbmQgdGhlIGRvY3VtZW50IGRhdGUgKHNldCB0byB0aGUgY3VycmVudCBkYXRlIGJ5IGRlZmF1bHQpLiBUaGVzZSB3aWxsIGFwcGVhciBhdCB0aGUgdG9wIG9mIHRoZSBrbml0IGRvY3VtZW50LiBZb3UgY2FuIHNlbGVjdCB0aGUgb3V0cHV0IGZvcm1hdC4gTGVhdmUgaXQgYXMgSFRNTCBmb3IgdGhpcyBleGVyY2lzZS4KCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aCA9ICI3NSUiLCBmaWcucG9zID0gIkgiLCBmaWcuY2FwID0gIlIgTWFya2Rvd24gRGlhbG9ndWUiLCBlY2hvID0gRkFMU0V9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1tYXJrZG93bl9kaWFsb2d1ZS5wbmciKQpgYGAKCjNcLiBSU3R1ZGlvIHdpbGwgY3JlYXRlIGEgbmV3IGZpbGUgYW5kIG9wZW4gaXQgaW4gYSBuZXcgdGFiLiBUaGUgZmlsZSBpcyB1bnRpdGxlZCwgc28gc2F2ZSBpdCBhbmQgZ2l2ZSBpdCBhIHNlbnNpYmxlIG5hbWUuCgpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwID0gIkEgTmV3IFIgTWFya2Rvd24gRmlsZSIsIG91dC53aWR0aCA9ICIxMDAlIiwgZWNobyA9IEZBTFNFLCBmaWcucG9zID0gIkgifQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDEtbWFya2Rvd25fdGVtcGxhdGUucG5nIikKYGBgCgpUaGUgZmlsZSBhbHJlYWR5IGNvbnRhaW5zIHNvbWUgdGV4dC4gVGhpcyBpcyBzYW1wbGUgY29udGVudHMgdG8gaWxsdXN0cmF0ZSBob3cgUiBNYXJrZG93biB3b3Jrcy4gWW91IHdpbGwgbm90ZSB0aGF0IHRoZSBmaWxlIGhhcyBhcmVhcyB3aXRoIGEgd2hpdGUgYmFja2dyb3VuZCBhbmQgYXJlYXMgd2l0aCBhIHNoYWRlZCBiYWNrZ3JvdW5kLiBUaGUgd2hpdGUgYXJlYXMgYXJlIHBsYWluIHRleHQsIHRoZSBzaGFkZWQgYXJlYXMgYXJlIFIgY29kZSBXaGVuIHRoZSBmaWxlIGlzIGtuaXQsIHRoYXQgY29kZSB3aWxsIGJlIHJ1biwgYW5kIGl0cyBvdXRwdXQgaW5zZXJ0ZWQgaW50byB0aGUgdGV4dC4gVG8gc2VlIHRoaXMgaW4gYWN0aW9uLCBjbGljayB0aGUgKipLbml0KiogaWNvbiBhdCB0aGUgdG9wIHRoZSBSU3R1ZGlvIHRhYi4KCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5jYXAgPSAiVGhlIEtuaXQgQnV0dG9uIiwgb3V0LndpZHRoID0gIjUwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLnBvcyA9ICJIIn0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzAxLW1hcmtkb3duX2tuaXRfYnV0dG9uLnBuZyIpCmBgYAoKUlN0dWRpbyB3aWxsIHByb2R1Y2UgYSBiZWF1dGlmdWwgSFRNTCBkb2N1bWVudCBhbmQgb3BlbiBpdCBpbiBhIGxvY2FsIGJyb3dzZXIgd2luZG93LiBTZWUgaWYgeW91IGNhbiBtYXRjaCB0aGUgUiBjb2RlIHNlZ21lbnRzIGluIHRoZSBSIE1hcmtkb3duIGRvY3VtZW50IHRvIHRoZSBvdXRwdXQgdGhhdCBhcHBlYXJzIGluIHRoZSBIVE1MIHBhZ2UuCgpSIE1hcmtkb3duIGlzIGEgcG93ZXJmdWwgdG9vbCBmb3IgZ2VuZXJhdGluZyByZXNlYXJjaCByZXBvcnRzIHdoZW4gYW5hbHlzaW5nIGRhdGEgd2l0aCBSLiBBcyB3ZSBwcm9jZWVkIHRocm91Z2ggdGhpcyBtaW5pLWNvdXJzZSB3ZSB3aWxsIGV4cGxvcmUgYWRkaXRpb25hbCBmZWF0dXJlcyBvZiBSIE1hcmtkb3duLCBhbmQgeW91IG1heSB3aXNoIHRvIGNvbnNpZGVyIHVzaW5nIGl0IGZvciB5b3VyIG93biBjb3Vyc2UgYXNzaWdubWVudHMuIENoZWNrIHdpdGggeW91ciBsZWN0dXJlcnMgdG8gc2VlIGlmIHRoaXMgaXMgc3VpdGFibGUuCgpcCgoKXAoKIyBDb25jbHVzaW9uCgpJbiB0aGlzIG1vZHVsZSB5b3UgaGF2ZSBjb25zaWRlcmVkIHRoZSBpbm5lciB3b3JraW5ncyBvZiB0aGUgY29tcHV0ZXIsIHdyaXR0ZW4gUiBjb21tYW5kcyBpbnRvIHRoZSBSU3R1ZGlvIERldmVsb3BtZW50IEVudmlyb25tZW50LCBtZXQgc29tZSBvZiB0aGUgdGhpbmdzIFIgdW5kZXJzdGFuZHMgKG51bWJlciwgc3RyaW5ncywgYW5kIHZlY3RvcnMpIGFuZCBzb21lIG9mIHRoZSBhY3Rpb25zIFIgY2FuIHBlcmZvcm0gKGZ1bmN0aW9ucykuIENvbmdyYXR1bGF0aW9ucy4KCiMjIFdoYXQncyBOZXh0CgpJbiB0aGlzIHdlZWsncyBoYW5kcy1vbiBzZXNzaW9uIHdlIHdpbGwgY29udGludWUgdG8gYnVpbGQgb3VyIFIgc2tpbGxzLCB3b3JraW5nIHRvZ2V0aGVyIHRocm91Z2ggdGhlIGV4ZXJjaXNlcyBpbiB0aGUgWm9vbSBub3RlcyBmb3IgdGhpcyBtb2R1bGUuIChJZiB5b3UgcHJlZmVyLCBnbyBhaGVhZCBhbmQgdHJ5IHRoZW0gb24geW91ciBvd24uKSBZb3UgY2FuIGFsc28gdXNlIHRoZSBoYW5kcy1vbiBzZXNzaW9ucyB0byBnZXQgaGVscCB3aXRoIGFueSBjb3Vyc2V3b3JrLCBwcm9qZWN0cywgb3Igb3RoZXIgUiBxdWVzdGlvbnMgeW91IG1heSBoYXZlLgoKSW4gb3VyIG5leHQgbW9kdWxlLCB3ZSB3aWxsIGxlYXJuIGhvdyB0byByZWFkIGRhdGEgZmlsZXMgaW50byBSIGFuZCBtYWtlIHBsb3RzIGFuZCBmaWd1cmVzIHRoYXQgeW91IGNhbiB1c2UgaW4gYSByZXNlYXJjaCByZXBvcnQuIFdlIHdpbGwgc3RhcnQgd2l0aCBzaW1wbGUgcGxvdHMgeW91IGNhbiBjcmVhdGUgdXNpbmcgb25seSBiYXNlIFIuIFRoZW4gd2Ugd2lsbCBsZWFybiB0byB1c2UgYSBwb3dlcmZ1bCBncmFwaGljcyBsaWJyYXJ5IGNhbGxlZCAqKmdncGxvdCoqIChwYXJ0IG9mIHRoZSAqKnRpZHl2ZXJzZSoqIGZhbWlseSBvZiBSIGV4dGVuc2lvbnMpLiBXaXRoIGdncGxvdCB5b3UgY2FuIG1ha2UgcHVibGljYXRpb24tcXVhbGl0eSBncmFwaHMgd2l0aCBvbmx5IGEgZmV3IGxpbmVzIG9mIFIgY29kZS4KCgoKCgoKCg==