⇠ Workshop Home || Day 2 ⇢

Download course materials (.zip file) from here after 2nd June.

bit.ly/RforLinguists-201906

These packages should already be installed on the lab computers. Please make sure you have installed them on your laptop before tomorrow, if you are using one.

install.packages("tidyverse","ordinal","lme4")

1 Introduction: R and RStudio

This workshop is designed to introduce you to practical uses and issues in R and RStudio, aimed at linguists and psychologists (well, psycholinguists). In this first day, we will start with the fundamentals of interacting with the programs.

R is a programming language that we can use to tell the computer what to do. We can “speak” R to the computer a number of ways, e.g., through the command line (Terminal in Macs) or through the R app.

Before you can use R and RStudio, it’s important to understand what you’re looking at and where to find things.

1.1 R vs RStudio

1.1.1 What is the difference between R and RStudio?

R is the program and programming language that allows you to input commands and get the computer to do things. In order to interact with R, some people use a simple R interface, some people use the command line, and some people use RStudio.

RStudio is a GUI (Graphical User Interface) that allows you to interact with R and keep everything organised.

R interface Command line RStudio

We’ll be using RStudio because it is the easiest to use, with some point-and-click commands, but still with the full functionality and power of R. R runs in the background when you run RStudio, but RStudio takes care of that on its own so all you need to do is open RStudio.

1.1.2 What is going on in the RStudio window?

The RStudio interface has (up to) four panes that you can rearrange and customise to suit your needs. Here is the default configuration:

When you open RStudio for the first time, there may only be three panes.

1.1.2.1 The Console

The console is your direct line of communication with R. It operates a bit like a chat window (if you’re familiar with that) because you can type things into the console, hit ENTER, and R will do something (and sometimes, depending on what you type, it’ll respond). You know the console is listening and ready to accept a new command if you see a > on the left edge of the window on the lowest line of text.

1.1.2.2 Environment

The environment is a set of three tabs that effectively lets us see into “R’s brain” (thanks Danielle!). This window lets you see what variables you’ve created, what datasets are loaded in, what packages and libraries are loaded, among many other things. Right now, it’s empty.

If we click on Global Environment, we can see what packages have automatically be loaded into this R session. Once you load other packages in, you will see them here too.

logo

1.1.2.3 Files etc

The pane in the lower right has five tabs by default.

  1. Files
    • This tab will show you what files are in the folders you navigate to.
    • This is useful if you want to preview a dataset, open a script, or figure out where you saved something.
  2. Plots
    • This tab will display plots you generate from the console.
    • You can click Zoom to pop the graph out into a separate window and resize it.
    • You can click Export to save the plot as a PNG, PDF, EPS, etc.
  3. Packages
    • In this tab, you can see what packages have been downloaded and loaded.
  4. Help
    • This tab will let you look through the documentation and get tips on how to use different functions.
  5. Viewer
    • I’ve never used this.

1.2 Best practices

How do you keep all your related files organised?

Keeping your files organised will make your life infinitely easier and will help you ease back into using R if you come back to it after a hiatus. The RStudio interface will help with this, but there is no better foundation than good file management.

1.2.1 Your project folder

Danielle Turton and I suggest the following as a best practice:

  1. Create a folder with the name of your project.
    • If possible, do not use SPACES or SPECIAL CHARACTERS. These can cause issues across platforms.
    • If you want to separate words, use UNDERSCORES (_), HYPHENS (-), or CamelCase.
  2. Within your project folder, create three subfolders.
    • data: This is the place you’ll store all your datasets and spreadsheets.
    • graphs: This is the place you’ll save the outputs of your script.
    • scripts: This is the place you’ll save your R scripts and notebooks.
  3. Name all scripts, graphs, and datasets using the following templates:
    • YYYYMMDD-descriptive_name.R
    • YYYYMMDD-name_of_generating_script_or_dataset.PNG
    • YYYYMMDD-dataset_name_or_source.csv (or .txt)

1.2.2 Creating an .RProj

RStudio offers a neat feature called a project (file type .Rproj). A project keeps all your scripts and datasets handy and can save variables for use later, even if you quit and restart RStudio. This can be useful if you are running complex models, for instance.

To create a new project, click on the small triangle in the upper right corner of the RStudio window.

This will bring up a menu with a number of useful options, but right now, we want to create a New Project…

Since we have already created a folder (i.e., a directory) for our project, we can click on the Existing Directory option. If you haven’t created a folder for your project, you can create a new directory, but in this case you should still follow best practices for file organisation.

From this window, we can browse our computers for the location of the folder we’ve set up.

1.2.3 Troubleshooting

I have noticed that sometimes students whose computers are set up with a non-English language, particularly with a non-Latin alphabet, can run into problems with setting up these folders. It is important to instruct them to use only Latin characters for the folders that R and RStudio will access, as non-Latin characters use a type of encoding that not all programs can read.

2 Base R functionality

2.1 Scripts

Scripts will appear in the fourth pane (top left by default).

Scripts are simply text files, they are not R and they don’t do anything unless you perform specific actions on them. They’re a bit like instruction manuals, but R can only read them if you manually send the instructions to the console (more on this later).

2.1.1 What is the point of a script?

A script is a way to save your work so you only need to write the code once. Once you’ve written a script once, you can execute it as many times as you like, but you won’t need to write it again. You can copy and paste other people’s code into your script and tweak it to fit your needs. You can debug your code without having to type it in new each time. You can share your code with others, and you can leave comments to yourself in your code so that you can leave it sit for a while and then remember what you were doing when you come back to it.

2.1.2 How do you write a new script?

On all platforms: the green + symbol in the top left corner will let you create a new script.

On a Mac: command+shift+N
On a PC: Ctrl+Alt+I

The symbol # hides the text that follows on that line from R, that is, it “comments it out”. This lets you write comments to yourself and to anyone else who might read your code. You’ll want to do this so you can remember what you were doing (trust me, you will not remember) and so other people can replicate what you did (even if it’s just to help you debug your code later).

If you type print("Hello World!") (with a nice comment) and then hit ENTER in your console, you will see something like this:

> print("Hello World!") # this line will produce the text between the quotes

[1] "Hello World!"

If you type print("Hello World!") and hit ENTER in a script, you will see something like this:

print("Hello World!")  
 

(Note that nothing happens. There is no output. A script is just a text file.)

2.1.3 How do you use a script?

Open a new script and type print("Hello World!") into it. How do you get R to execute your code? There are a couple ways:

  • Click the Run button on the top right portion of the script pane.
    • This will run everything in your script.
  • Use a keyboard shortcut
    • To run only the line your cursor is on, Command+Enter
    • To run only the selected code, select some code and use Command+Enter
    • To run the entire script, Command+Shift+Enter

When you run a script, the text in the script is sent, line by line, to the console. Once in the console, R executes the code. You can watch the code progress in the console. If there is any text or numerical output, it will appear in the console. If there is a graphical output, it will appear in the Plots tab of the lower right pane (Files etc).

2.1.4 Saving in RStudio

Now that we’ve gone through the fundamentals of organisation and basic R operators, we can get into the more important task of reading data and writing output (i.e., saving our work).

Once you’ve created a project (.Rproj), you can open the project and it should open right to where you left off. This means your scripts will open as well, as long as you did not close them the last time you worked on the project. However, if you want to open a script that isn’t currrently open but does exist, you can do so in the Files tab of the lower right pane. Click on the name of the script, and it will open in a new tab of your scripts pane (top left by default).

However, it is still extremely important to save all your work, frequently. If you use GitHub, there is a way to link it to RStudio so that you can commit changes and interact with your repositories from within the RStudio interface.

2.2 R is a calculator

Its least unique function is to compute arithmetic. You probably don’t want to use R just to add sums, but you could do.

3 + 4

White space doesn’t matter for most things (so you can put spaces between numbers, operations, names).

3+4

Order of operations follows standard rules (BIDMAS / BODMAS / PEMDAS):

3*4^2

…compared to…

(3*4)^2

2.2.1 Try it for yourself

  1. Create a new script.
  2. Save and name the script appropriately. (YYYYMMDD-descriptive_name.R)
  3. In the script, enter the following code:

    print("Hello world!")
    3 + 4
    7^2
  4. Run the entire script.

Your console should end up looking like this:

> print("Hello world!")
[1] "Hello world!"
> 3 + 4
[1] 7
> 7^2
[1] 49
>

(In the rest of this document, instead of output starting with >, it may start with ##. This is due to how R compiles a script to an HTML document and does not change anything in the script, code, or contentful output.)

2.2.1.1 What does [1] mean?

The number in square brackets to the left of the output indicates the number of values that have been printed by index number. That is, if there are multiple outputs on one line, [1] will appear. If the seventh item in the output wraps around and appears on the second line, both [1] and [7] will appear. This is useful when trying to make sense of long lists of numbers, for instance.

Below, I saved two longer strings of text into one variable called longText. Then when it’s printed, it appears on two lines. The [1] indicates the first item in the list is the first item on the line and the [2] indicates the second item in the list is the first item that appears on that line.

longText <- c("i don't think we'll be able to fit this text on one line of the output console","so that it might wrap around and display on two lines")
print(longText)  

2.2.2 What is a variable?

One of the most important components of (almost) any programming language is a variable. A variable is an object that can be assigned a value, a list of values, a matrix of values, or something along those lines. A variable in R can be named almost anything with a few exceptions:

A variable name…

  • Cannot start with a number
  • Cannot contain white space (i.e., spaces, tabs, line breaks)
  • Can contain . or _ but cannot contain other non-alphanumeric characters
  • Should begin with a lowercase letter
  • Should be memorable and descriptive
  • Should not be too long or difficult to type
  • Should not be too vague or general

To assign a value (etc) to a variable, there are three possible operators: =, <-, or occasionally -> (the latter two look like arrows).

First we assign the value of 3 to the variable x. Notice that spaces between the numbers and the operator are optional. I like to use them to help see each component more clearly.

We can also use one of the arrow operators. The two characters that comprise the arrow cannot have space between them. They act as a single unit. For the leftward-facing arrow, the value(s) on the right are assigned to the variable on the left.

Now that we’ve assigned values to x and y, we can do things to them. Below, I demonstrate some basic arthimetic operators that allow R to act like a calculator.

Finally, the rightward-pointing arrow is used very rarely, but functions in a similar way to the other two assignment operators. The value(s) on the left are assigned to the variable on the right.

To assign more than one value to a variable, there are several functions we can use, but the most common and easiest is c(). To read more about the function c(), you can type c into the search bar in the help tab in the lower right pane, or you can input the following into your console:

?c

In short, this function combines a series of values into a vector or list.

c(1,2,3)
c("1","2","3")
c("one","two","three")
c(one,two,three)

Note that bare numbers are green and are output without quotation marks, numbers and words in quotation marks are output as such, but words without quotation marks produce an error. This is because R assumes that all words without quotation marks are variables, but we haven’t created variables named one, two, or three.

one = 1
two = 2
three = 3
c(one,two,three)

2.3 R is for interacting with data files

Dataset sleep:

head(sleep)
  • column 1 = how many extra hours of sleep were recorded
  • column 2 = which drug was administered
  • column 3 = which participant

We will talk in depth about how to interact with datasets tomorrow when we work with the tidyverse packages. However, base R has a number of useful functions and properties to understand that will make tidyverse make more sense, but also be more appealing.

3 Indicies

3.1 Finding the index of the value you want

What does this do?

sleep[1,]

How does sleep[2,] differ from sleep[1,]?

How does sleep[3,] differ from sleep[,3]?

4 Literate programming

Literate programming is a useful way to annotate your code or navigate someone else’s code. In short, it allows you to write prose, insert pictures, view output, and produce tables within your code. In particular, R markdown (.Rmd) files and R notebooks allow you to write R in a literate programming environment. In fact, this webpage was generated as an .Rmd file!

This section will briefly discuss why literate programming, and specifically .Rmd files, are useful to know about and learn to use.

4.1 Annotation

Why do we annotate code?

Fundamentally, code can be difficult to read. We are not computers, we forget what we were doing or trying to do, we lose our place. Annotating code is one way to help us remember what our though process was at the time of writing. It also allows other people to use, adapt, and debug our code. This increases replicability and allows more open, transparent science, too.

As mentioned earlier, we can leave comments in our code by writing text after a # symbol.

paste("Hello","world!") # the paste() function connects text values with one space.
[1] "Hello world!"
paste0("Hello"," ","world","!") # the paste0() function connects text values with no intervening character(s).
[1] "Hello world!"

But commenting code may only get you so far. It can be difficult to read, there is no formatting in case you want to make some text bold or more salient, and you can still lose your place in a long script.

This is where .Rmd files improve upon commenting.

4.2 Prose

In a .Rmd file, we can still comment code line-by-line, but we can also include longer (more visually pleasing) explanations of what we are doing and what we intend to do. This means you can leave yourself reminders! You can also indicate what doesn’t work (so that someone else may help), and leave notes to yourself or to your audience about your interpretations of the data. Most importantly, you can view output such as graphs in-line, which means they are saved adjacent to the code that produced them. This makes it much easier to return to an analysis or share it with someone who is not intimately familiar with your data.

4.2.1 Example

In this graph, I’m using the automatically available dataset called cars. The plot() function is moderately flexible, so I can just tell it what columns in cars I want for the x-axis and the y-axis, and it’ll generate a graph.

plot(cars$speed,cars$dist)

However, this graph is ugly and boring. I want to change the colour and shape of the points because I know my audience is actually interested in certain propterties of the graph and I want to make it as easy as possible for them to navigate it quickly.

Below, I’ve generated a graph that splits the data into four quadrants. I tried other numerical values for the horizontal and vertical divisions, but reducing the horizontal division meant the lower right (orange) quadrant became too sparse and shifting the vertical division to the left meant the upper left (blue) quadrant became too sparse. I have not tried increasing the vertical division, but I suspect it would also result in the lower right (orange) quandrant becoming too sparse.

plot(cars$speed,cars$dist,col="white") # generate the plot background at an appropriate size and scale
abline(h=41,lty="dotted",col="grey") # include the horizontal line
abline(v=15.5,lty="dotted",col="grey") # include the vertical line
lines(lowess(cars),type="l",lwd=2) # plot the black trend line
points(cars$speed[cars$speed<15.5&cars$dist<41],cars$dist[cars$speed<15.5&cars$dist<41],col="red", pch=15) # lower left quadrant
points(cars$speed[cars$speed>15.5&cars$dist<41],cars$dist[cars$speed>15.5&cars$dist<41],col="orange", pch=16) # lower right quadrant
points(cars$speed[cars$speed>15.5&cars$dist>41],cars$dist[cars$speed>15.5&cars$dist>41],col="green", pch=17) # upper right quadrant
points(cars$speed[cars$speed<15.5&cars$dist>41],cars$dist[cars$speed<15.5&cars$dist>41],col="blue", pch=18) # upper left quadrant

See how much clearer this is? There are still gaps in the explanation. I haven’t told you what pch=15 means or what it does. There is a lot of text and it’s difficult to read. These are things you can annotate and explain to yourself when you find and adapt other people’s code. Eventually, they’ll become second nature, and you won’t need to annotate everything, but at first, it can be helpful if you expect to forget what everything means by the next time you use your code.

  • pch is the point type. Search “pch” in the help tab or type ?pch into the console to learn more.
  • col lets you change the colour of the line or point. There are a large number of pre-named colours.
  • lty means “line type”. Typical values are “dashed”, “dotted”, or “solid”.
  • lwd means “line width”. It takes a numerical integer value.

4.3 R Notebooks

An R Notebook will allow you to easily create a document (e.g., an HTML document) that can be compiled for easy sharing or reporting analysis. It differs slightly from a regular .Rmd file, but can be easier to learn to use and update.

Create a new R Notebook by clicking the green + in the upper left corner and selecting “R Notebook”. It will automatically give you a little information about how to write, run, and compile the document. Make sure to save it with a short, descriptive name!

Here are links that contain good cheat sheets and tips for formatting an R Notebook:

4.3.1 Organising code

When you write your code, it should be kept mostly chronological. This way, the steps you take are in the correct order.

However, there are some circumstances where it makes more sense to go back and add code in the middle rather than at the end of a document. If you re-do a statistical analysis or want to compare two methods, those may be more coherent if placed adjacent in the document rather than in the order you performed them. This is especially the case if you learn a new technique and want to go back and re-do an older analysis. The same thing goes for graphs and other outputs.

If you are working directly in an R script (which I do not recommend if you can use an .Rmd or notebook instead), you can create section headings. To do so, you can type #### Section Title #### with at least four hashes on either side of the text, and then you will be able to navigate directly to that heading using the small orange hash symbol in the lower left corner of the scripts pane.

An R Notebook also allows you to create section headings and navigate between them in a similar way, but when you compile and save the document, the section headings are also visually salient.

# Heading 1
## Heading 2
### Heading 3
#### Heading 4

Furthermore, there are options for creating a table of contents for your notebook, which makes it even easier. Here is an example of what you might put in the document header to create a nice, simple table of contents for your notebook.

---
title: "Untitled R Notebook"
output: 
  html_notebook:
    toc: true
    toc_float: true
---

4.3.2 Sharing code

To share your code, you can upload the .Rmd or .R script(s) that you used to do your processing and analysis to any open science site. These include Open Science Framework (OSF), GitHub, or your own personal website. Since each file can automatically generate an HTML file, you can either copy and paste the contents or upload the HTML file directly for others to read your report without necessarily knowing any R or needing to download any files.

LS0tCnRpdGxlOiAiKipCYXNlIFIgRnVuY3Rpb25hbGl0eSBhbmQgUlN0dWRpbyoqIgphdXRob3I6ICJEciBMYXVyZW4gTSBBY2tlcm1hbiIKZGF0ZTogIjAzIEpVTiAyMDE5IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19mbG9hdDogCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgICAgY29sbGFwc2VkOiBmYWxzZQogICAgdGhlbWU6IHNhbmRzdG9uZQogICAgaGlnaGxpZ2h0OiBkZWZhdWx0Ci0tLQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQoKCiMgMS4gUiBhbmQgUlN0dWRpbyBpbnRlcmZhY2VzLCBSTWFya2Rvd24sIGFuZCBiZXN0IHByYWN0aWNlcwojICAgIC0gQmFzaWMgZnVuY3Rpb25hbGl0eSwgc2hvcnRjdXRzLCB3cml0aW5nIHNjcmlwdHMgYW5kIG5vdGVib29rcywgb3JnYW5pc2luZyBmaWxlcywgaW50ZXJmYWNpbmcgd2l0aCBHaXRIdWIKIyAyLiBEYXRhIGZyYW1lIG1hbmlwdWxhdGlvbiB1c2luZyBUaWR5dmVyc2UKIyAgICAtIFBpcGluZyBzeW50YXggYW5kIGNvZGUgcmVwbGljYWJpbGl0eQojICAgIC0gVGlkeXIsIERwbHlyLCByZWxhdGVkIHBhY2thZ2VzCiMgICAgLSBDbGVhbmluZywgY29tYmluaW5nLCBhbmQgcmVhcnJhbmdpbmcgZGF0YSBmcmFtZXMKIyAzLiBEYXRhIHZpc3VhbGlzYXRpb24gdXNpbmcgZ2dwbG90IGFuZCBiZXN0IHByYWN0aWNlcwojICAgIC0gU3RydWN0dXJlIGFuZCBzeW50YXggb2YgZ2dwbG90IGFuZCBnZW9tCiMgICAgLSBDdXN0b21pc2luZyBhbmQgY29tYmluaW5nIHBsb3RzCiMgICAgLSBEZXRlcm1pbmluZyB3aGF0IHBsb3QgaXMgYmVzdCBmb3IgeW91ciBkYXRhCiMgNC4gQmFzaWMgbGluZWFyIG1vZGVscyB3aXRob3V0IGFuZCB3aXRoIG1peGVkIGVmZmVjdHMgKGluY2x1ZGluZyBnYXVzc2lhbiwgYmlub21pYWwsIGFuZCBvcmRpbmFsKQojICAgIC0gYnVpbGRpbmcvc2VsZWN0aW5nIGFuIGFwcHJvcHJpYXRlIG1vZGVsLCBpbmNsdWRpbmcgcmFuZG9tIGVmZmVjdCBzdHJ1Y3R1cmVzCiMgICAgLSBtYXhpbWFsIHZzIHBhcnNpbW9uaW91cyBtb2RlbHMKIyAgICAtIHByYWN0aWNhbCB1c2Ugb2YgbG0oKSwgbG1lcigpLCBnbG0oKSwgZ2xtZXIoKSwgY2xtbSgpCiMgICAgLSBkdW1teSBjb2RpbmcgdnMgY29udHJhc3QgY29kaW5nCiMgICAgLSBpbnRlcnByZXRpbmcgdGhlIG91dHB1dApgYGAKW+KHoCBXb3Jrc2hvcCBIb21lXSguLi9pbmZvLmh0bWwpIHx8IFtEYXkgMiDih6JdKDIwMTkwNjA0LXRpZHl2ZXJzZS5odG1sKQoKRG93bmxvYWQgY291cnNlIG1hdGVyaWFscyAoLnppcCBmaWxlKSBmcm9tIFtoZXJlXShodHRwOi8vYml0Lmx5L1Jmb3JMaW5ndWlzdHMtMjAxOTA2KSAqYWZ0ZXIgMm5kIEp1bmUqLgoKWyoqYml0Lmx5L1Jmb3JMaW5ndWlzdHMtMjAxOTA2KipdKGh0dHA6Ly9iaXQubHkvUmZvckxpbmd1aXN0cy0yMDE5MDYpCgpUaGVzZSBwYWNrYWdlcyBzaG91bGQgYWxyZWFkeSBiZSBpbnN0YWxsZWQgb24gdGhlIGxhYiBjb21wdXRlcnMuIFBsZWFzZSBtYWtlIHN1cmUgeW91IGhhdmUgaW5zdGFsbGVkIHRoZW0gb24geW91ciBsYXB0b3AgYmVmb3JlICoqdG9tb3Jyb3cqKiwgaWYgeW91IGFyZSB1c2luZyBvbmUuCgpgYGB7ciBldmFsPUZBTFNFfQppbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiLCJvcmRpbmFsIiwibG1lNCIpCmBgYAoKIyBJbnRyb2R1Y3Rpb246IFIgYW5kIFJTdHVkaW8gCgpUaGlzIHdvcmtzaG9wIGlzIGRlc2lnbmVkIHRvIGludHJvZHVjZSB5b3UgdG8gcHJhY3RpY2FsIHVzZXMgYW5kIGlzc3VlcyBpbiBSIGFuZCBSU3R1ZGlvLCBhaW1lZCBhdCBsaW5ndWlzdHMgYW5kIHBzeWNob2xvZ2lzdHMgKHdlbGwsIHBzeWNob2xpbmd1aXN0cykuIEluIHRoaXMgZmlyc3QgZGF5LCB3ZSB3aWxsIHN0YXJ0IHdpdGggdGhlIGZ1bmRhbWVudGFscyBvZiBpbnRlcmFjdGluZyB3aXRoIHRoZSBwcm9ncmFtcy4KClIgaXMgYSBwcm9ncmFtbWluZyBsYW5ndWFnZSB0aGF0IHdlIGNhbiB1c2UgdG8gdGVsbCB0aGUgY29tcHV0ZXIgd2hhdCB0byBkby4gV2UgY2FuICJzcGVhayIgUiB0byB0aGUgY29tcHV0ZXIgYSBudW1iZXIgb2Ygd2F5cywgZS5nLiwgdGhyb3VnaCB0aGUgY29tbWFuZCBsaW5lIChUZXJtaW5hbCBpbiBNYWNzKSBvciB0aHJvdWdoIHRoZSBSIGFwcC4KCkJlZm9yZSB5b3UgY2FuIHVzZSBSIGFuZCBSU3R1ZGlvLCBpdCdzIGltcG9ydGFudCB0byB1bmRlcnN0YW5kIHdoYXQgeW91J3JlIGxvb2tpbmcgYXQgYW5kIHdoZXJlIHRvIGZpbmQgdGhpbmdzLgoKIyMgUiB2cyBSU3R1ZGlvIAoKIyMjIFdoYXQgaXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBSIGFuZCBSU3R1ZGlvPwoKKipSKiogaXMgdGhlIHByb2dyYW0gYW5kIHByb2dyYW1taW5nIGxhbmd1YWdlIHRoYXQgYWxsb3dzIHlvdSB0byBpbnB1dCBjb21tYW5kcyBhbmQgZ2V0IHRoZSBjb21wdXRlciB0byBkbyB0aGluZ3MuIEluIG9yZGVyIHRvIGludGVyYWN0IHdpdGggUiwgc29tZSBwZW9wbGUgdXNlIGEgc2ltcGxlIFIgaW50ZXJmYWNlLCBzb21lIHBlb3BsZSB1c2UgdGhlIGNvbW1hbmQgbGluZSwgYW5kIHNvbWUgcGVvcGxlIHVzZSBSU3R1ZGlvLgoKKipSU3R1ZGlvKiogaXMgYSBHVUkgKEdyYXBoaWNhbCBVc2VyIEludGVyZmFjZSkgdGhhdCBhbGxvd3MgeW91IHRvIGludGVyYWN0IHdpdGggUiBhbmQga2VlcCBldmVyeXRoaW5nIG9yZ2FuaXNlZC4KCiFbKlIgaW50ZXJmYWNlKl0oLi4vZ3VpL3ItaW50ZXJmYWNlLnBuZykKIVsqQ29tbWFuZCBsaW5lKl0oLi4vZ3VpL3Rlcm1pbmFsLnBuZykKIVsqUlN0dWRpbypdKC4uL2d1aS9yaWdodC1wYW5lbHMucG5nKQoKV2UnbGwgYmUgdXNpbmcgKipSU3R1ZGlvKiogYmVjYXVzZSBpdCBpcyB0aGUgZWFzaWVzdCB0byB1c2UsIHdpdGggc29tZSBwb2ludC1hbmQtY2xpY2sgY29tbWFuZHMsIGJ1dCBzdGlsbCB3aXRoIHRoZSBmdWxsIGZ1bmN0aW9uYWxpdHkgYW5kIHBvd2VyIG9mIFIuIFIgcnVucyBpbiB0aGUgYmFja2dyb3VuZCB3aGVuIHlvdSBydW4gUlN0dWRpbywgYnV0IFJTdHVkaW8gdGFrZXMgY2FyZSBvZiB0aGF0IG9uIGl0cyBvd24gc28gYWxsIHlvdSBuZWVkIHRvIGRvIGlzIG9wZW4gUlN0dWRpby4KCiMjIyBXaGF0IGlzIGdvaW5nIG9uIGluIHRoZSBSU3R1ZGlvIHdpbmRvdz8KClRoZSBSU3R1ZGlvIGludGVyZmFjZSBoYXMgKHVwIHRvKSBmb3VyIHBhbmVzIHRoYXQgeW91IGNhbiByZWFycmFuZ2UgYW5kIGN1c3RvbWlzZSB0byBzdWl0IHlvdXIgbmVlZHMuIEhlcmUgaXMgdGhlIGRlZmF1bHQgY29uZmlndXJhdGlvbjoKCiFbXSguLi9ndWkvY29uc29sZS5wbmcpCldoZW4geW91IG9wZW4gUlN0dWRpbyBmb3IgdGhlIGZpcnN0IHRpbWUsIHRoZXJlIG1heSBvbmx5IGJlIHRocmVlIHBhbmVzLgoKIyMjIyBUaGUgQ29uc29sZQoKVGhlIGNvbnNvbGUgaXMgeW91ciBkaXJlY3QgbGluZSBvZiBjb21tdW5pY2F0aW9uIHdpdGggUi4gSXQgb3BlcmF0ZXMgYSBiaXQgbGlrZSBhIGNoYXQgd2luZG93IChpZiB5b3UncmUgZmFtaWxpYXIgd2l0aCB0aGF0KSBiZWNhdXNlIHlvdSBjYW4gdHlwZSB0aGluZ3MgaW50byB0aGUgY29uc29sZSwgaGl0IGBFTlRFUmAsIGFuZCBSIHdpbGwgZG8gc29tZXRoaW5nIChhbmQgc29tZXRpbWVzLCBkZXBlbmRpbmcgb24gd2hhdCB5b3UgdHlwZSwgaXQnbGwgcmVzcG9uZCkuIFlvdSBrbm93IHRoZSBjb25zb2xlIGlzIGxpc3RlbmluZyBhbmQgcmVhZHkgdG8gYWNjZXB0IGEgbmV3IGNvbW1hbmQgaWYgeW91IHNlZSBhIGA+YCBvbiB0aGUgbGVmdCBlZGdlIG9mIHRoZSB3aW5kb3cgb24gdGhlIGxvd2VzdCBsaW5lIG9mIHRleHQuCgojIyMjIEVudmlyb25tZW50CgpUaGUgZW52aXJvbm1lbnQgaXMgYSBzZXQgb2YgdGhyZWUgdGFicyB0aGF0IGVmZmVjdGl2ZWx5IGxldHMgdXMgc2VlIGludG8gIlIncyBicmFpbiIgKHRoYW5rcyBEYW5pZWxsZSEpLiBUaGlzIHdpbmRvdyBsZXRzIHlvdSBzZWUgd2hhdCB2YXJpYWJsZXMgeW91J3ZlIGNyZWF0ZWQsIHdoYXQgZGF0YXNldHMgYXJlIGxvYWRlZCBpbiwgd2hhdCBwYWNrYWdlcyBhbmQgbGlicmFyaWVzIGFyZSBsb2FkZWQsIGFtb25nIG1hbnkgb3RoZXIgdGhpbmdzLiBSaWdodCBub3csIGl0J3MgZW1wdHkuCgpJZiB3ZSBjbGljayBvbiBgR2xvYmFsIEVudmlyb25tZW50YCwgd2UgY2FuIHNlZSB3aGF0IHBhY2thZ2VzIGhhdmUgYXV0b21hdGljYWxseSBiZSBsb2FkZWQgaW50byB0aGlzIFIgc2Vzc2lvbi4gT25jZSB5b3UgbG9hZCBvdGhlciBwYWNrYWdlcyBpbiwgeW91IHdpbGwgc2VlIHRoZW0gaGVyZSB0b28uCgpgYGB7ciwgZWNobz1GQUxTRX0KaHRtbHRvb2xzOjppbWcoc3JjID0ga25pdHI6OmltYWdlX3VyaSgiLi4vZ3VpL2dsb2JhbF9lbnZpcm9ubWVudC5wbmciKSwgCiAgICAgICAgICAgICAgIGFsdCA9ICdsb2dvJywgCiAgICAgICAgICAgICAgIHN0eWxlID0gJ3Bvc2l0aW9uOnJlbGF0aXZlOyB0b3A6MDsgcmlnaHQ6MDsgcGFkZGluZzoxMHB4OyB3aWR0aDo3MCUnKQpgYGAKCiMjIyMgRmlsZXMgZXRjCgpUaGUgcGFuZSBpbiB0aGUgbG93ZXIgcmlnaHQgaGFzIGZpdmUgdGFicyBieSBkZWZhdWx0LgoKMS4gKipGaWxlcyoqICAKICAgIC0gVGhpcyB0YWIgd2lsbCBzaG93IHlvdSB3aGF0IGZpbGVzIGFyZSBpbiB0aGUgZm9sZGVycyB5b3UgbmF2aWdhdGUgdG8uICAKICAgIC0gVGhpcyBpcyB1c2VmdWwgaWYgeW91IHdhbnQgdG8gcHJldmlldyBhIGRhdGFzZXQsIG9wZW4gYSBzY3JpcHQsIG9yIGZpZ3VyZSBvdXQgd2hlcmUgeW91IHNhdmVkIHNvbWV0aGluZy4gIAoyLiAqKlBsb3RzKiogIAogICAgLSBUaGlzIHRhYiB3aWxsIGRpc3BsYXkgcGxvdHMgeW91IGdlbmVyYXRlIGZyb20gdGhlIGNvbnNvbGUuICAKICAgIC0gWW91IGNhbiBjbGljayBgWm9vbWAgdG8gcG9wIHRoZSBncmFwaCBvdXQgaW50byBhIHNlcGFyYXRlIHdpbmRvdyBhbmQgcmVzaXplIGl0LiAgCiAgICAtIFlvdSBjYW4gY2xpY2sgYEV4cG9ydGAgdG8gc2F2ZSB0aGUgcGxvdCBhcyBhIFBORywgUERGLCBFUFMsIGV0Yy4gIAozLiAqKlBhY2thZ2VzKiogIAogICAgLSBJbiB0aGlzIHRhYiwgeW91IGNhbiBzZWUgd2hhdCBwYWNrYWdlcyBoYXZlIGJlZW4gZG93bmxvYWRlZCBhbmQgbG9hZGVkLgo0LiAqKkhlbHAqKiAgCiAgICAtIFRoaXMgdGFiIHdpbGwgbGV0IHlvdSBsb29rIHRocm91Z2ggdGhlIGRvY3VtZW50YXRpb24gYW5kIGdldCB0aXBzIG9uIGhvdyB0byB1c2UgZGlmZmVyZW50IGZ1bmN0aW9ucy4KNS4gKipWaWV3ZXIqKiAgCiAgICAtIEkndmUgbmV2ZXIgdXNlZCB0aGlzLiAgCgojIyBCZXN0IHByYWN0aWNlcyAKCkhvdyBkbyB5b3Uga2VlcCBhbGwgeW91ciByZWxhdGVkIGZpbGVzIG9yZ2FuaXNlZD8KCktlZXBpbmcgeW91ciBmaWxlcyBvcmdhbmlzZWQgd2lsbCBtYWtlIHlvdXIgbGlmZSBpbmZpbml0ZWx5IGVhc2llciBhbmQgd2lsbCBoZWxwIHlvdSBlYXNlIGJhY2sgaW50byB1c2luZyBSIGlmIHlvdSBjb21lIGJhY2sgdG8gaXQgYWZ0ZXIgYSBoaWF0dXMuIFRoZSBSU3R1ZGlvIGludGVyZmFjZSB3aWxsIGhlbHAgd2l0aCB0aGlzLCBidXQgdGhlcmUgaXMgbm8gYmV0dGVyIGZvdW5kYXRpb24gdGhhbiBnb29kIGZpbGUgbWFuYWdlbWVudC4KCiMjIyBZb3VyIHByb2plY3QgZm9sZGVyCgpbRGFuaWVsbGUgVHVydG9uXShodHRwczovL3d3dy5zdGFmZi5uY2wuYWMudWsvZGFuaWVsbGUudHVydG9uLykgYW5kIEkgc3VnZ2VzdCB0aGUgZm9sbG93aW5nIGFzIGEgYmVzdCBwcmFjdGljZToKCjEuIENyZWF0ZSBhIGZvbGRlciB3aXRoIHRoZSBuYW1lIG9mIHlvdXIgcHJvamVjdC4gIAogICAgLSBJZiBwb3NzaWJsZSwgZG8gbm90IHVzZSBTUEFDRVMgb3IgU1BFQ0lBTCBDSEFSQUNURVJTLiBUaGVzZSBjYW4gY2F1c2UgaXNzdWVzIGFjcm9zcyBwbGF0Zm9ybXMuICAKICAgIC0gSWYgeW91IHdhbnQgdG8gc2VwYXJhdGUgd29yZHMsIHVzZSBVTkRFUlNDT1JFUyAoXyksIEhZUEhFTlMgKC0pLCBvciBDYW1lbENhc2UuICAKMi4gV2l0aGluIHlvdXIgcHJvamVjdCBmb2xkZXIsIGNyZWF0ZSB0aHJlZSBzdWJmb2xkZXJzLiAgCiAgICAtICoqZGF0YSoqOiBUaGlzIGlzIHRoZSBwbGFjZSB5b3UnbGwgc3RvcmUgYWxsIHlvdXIgZGF0YXNldHMgYW5kIHNwcmVhZHNoZWV0cy4gIAogICAgLSAqKmdyYXBocyoqOiBUaGlzIGlzIHRoZSBwbGFjZSB5b3UnbGwgc2F2ZSB0aGUgb3V0cHV0cyBvZiB5b3VyIHNjcmlwdC4gIAogICAgLSAqKnNjcmlwdHMqKjogVGhpcyBpcyB0aGUgcGxhY2UgeW91J2xsIHNhdmUgeW91ciBSIHNjcmlwdHMgYW5kIG5vdGVib29rcy4gIAozLiBOYW1lIGFsbCBzY3JpcHRzLCBncmFwaHMsIGFuZCBkYXRhc2V0cyB1c2luZyB0aGUgZm9sbG93aW5nIHRlbXBsYXRlczogIAogICAgLSBZWVlZTU1ERC1kZXNjcmlwdGl2ZV9uYW1lLlIgIAogICAgLSBZWVlZTU1ERC1uYW1lX29mX2dlbmVyYXRpbmdfc2NyaXB0X29yX2RhdGFzZXQuUE5HICAKICAgIC0gWVlZWU1NREQtZGF0YXNldF9uYW1lX29yX3NvdXJjZS5jc3YgKG9yIC50eHQpICAKCiFbXSguLi9ndWkvZm9sZGVyLnBuZykKCiMjIyBDcmVhdGluZyBhbiAuUlByb2oKClJTdHVkaW8gb2ZmZXJzIGEgbmVhdCBmZWF0dXJlIGNhbGxlZCBhICpwcm9qZWN0KiAoZmlsZSB0eXBlIGAuUnByb2pgKS4gQSBwcm9qZWN0IGtlZXBzIGFsbCB5b3VyIHNjcmlwdHMgYW5kIGRhdGFzZXRzIGhhbmR5IGFuZCBjYW4gc2F2ZSB2YXJpYWJsZXMgZm9yIHVzZSBsYXRlciwgZXZlbiBpZiB5b3UgcXVpdCBhbmQgcmVzdGFydCBSU3R1ZGlvLiBUaGlzIGNhbiBiZSB1c2VmdWwgaWYgeW91IGFyZSBydW5uaW5nIGNvbXBsZXggbW9kZWxzLCBmb3IgaW5zdGFuY2UuCgpUbyBjcmVhdGUgYSBuZXcgcHJvamVjdCwgY2xpY2sgb24gdGhlIHNtYWxsIHRyaWFuZ2xlIGluIHRoZSB1cHBlciByaWdodCBjb3JuZXIgb2YgdGhlIFJTdHVkaW8gd2luZG93LgoKIVtdKC4uL2d1aS9uZXctcHJvamVjdC5wbmcpCgpUaGlzIHdpbGwgYnJpbmcgdXAgYSBtZW51IHdpdGggYSBudW1iZXIgb2YgdXNlZnVsIG9wdGlvbnMsIGJ1dCByaWdodCBub3csIHdlIHdhbnQgdG8gY3JlYXRlIGEgKk5ldyBQcm9qZWN0Li4uKgoKIVtdKC4uL2d1aS9leGlzdGluZy1kaXJlY3RvcnkucG5nKQoKU2luY2Ugd2UgaGF2ZSBhbHJlYWR5IGNyZWF0ZWQgYSBmb2xkZXIgKGkuZS4sIGEgZGlyZWN0b3J5KSBmb3Igb3VyIHByb2plY3QsIHdlIGNhbiBjbGljayBvbiB0aGUgKkV4aXN0aW5nIERpcmVjdG9yeSogb3B0aW9uLiBJZiB5b3UgaGF2ZW4ndCBjcmVhdGVkIGEgZm9sZGVyIGZvciB5b3VyIHByb2plY3QsIHlvdSBjYW4gY3JlYXRlIGEgbmV3IGRpcmVjdG9yeSwgYnV0IGluIHRoaXMgY2FzZSB5b3Ugc2hvdWxkIHN0aWxsIGZvbGxvdyBiZXN0IHByYWN0aWNlcyBmb3IgZmlsZSBvcmdhbmlzYXRpb24uCgohW10oLi4vZ3VpL2Jyb3dzZS5wbmcpCgpGcm9tIHRoaXMgd2luZG93LCB3ZSBjYW4gYnJvd3NlIG91ciBjb21wdXRlcnMgZm9yIHRoZSBsb2NhdGlvbiBvZiB0aGUgZm9sZGVyIHdlJ3ZlIHNldCB1cC4KCiMjIyBUcm91Ymxlc2hvb3RpbmcKCkkgaGF2ZSBub3RpY2VkIHRoYXQgc29tZXRpbWVzIHN0dWRlbnRzIHdob3NlIGNvbXB1dGVycyBhcmUgc2V0IHVwIHdpdGggYSBub24tRW5nbGlzaCBsYW5ndWFnZSwgcGFydGljdWxhcmx5IHdpdGggYSBub24tTGF0aW4gYWxwaGFiZXQsIGNhbiBydW4gaW50byBwcm9ibGVtcyB3aXRoIHNldHRpbmcgdXAgdGhlc2UgZm9sZGVycy4gSXQgaXMgaW1wb3J0YW50IHRvIGluc3RydWN0IHRoZW0gdG8gdXNlIG9ubHkgTGF0aW4gY2hhcmFjdGVycyBmb3IgdGhlIGZvbGRlcnMgdGhhdCBSIGFuZCBSU3R1ZGlvIHdpbGwgYWNjZXNzLCBhcyBub24tTGF0aW4gY2hhcmFjdGVycyB1c2UgYSB0eXBlIG9mIGVuY29kaW5nIHRoYXQgbm90IGFsbCBwcm9ncmFtcyBjYW4gcmVhZC4KCiMgQmFzZSBSIGZ1bmN0aW9uYWxpdHkgCgojIyBTY3JpcHRzCgpTY3JpcHRzIHdpbGwgYXBwZWFyIGluIHRoZSBmb3VydGggcGFuZSAodG9wIGxlZnQgYnkgZGVmYXVsdCkuIAoKIVtdKC4uL2d1aS9uZXctc2NyaXB0LnBuZykKClNjcmlwdHMgYXJlIHNpbXBseSB0ZXh0IGZpbGVzLCB0aGV5IGFyZSBub3QgUiBhbmQgdGhleSBkb24ndCBkbyBhbnl0aGluZyB1bmxlc3MgeW91IHBlcmZvcm0gc3BlY2lmaWMgYWN0aW9ucyBvbiB0aGVtLiBUaGV5J3JlIGEgYml0IGxpa2UgaW5zdHJ1Y3Rpb24gbWFudWFscywgYnV0IFIgY2FuIG9ubHkgcmVhZCB0aGVtIGlmIHlvdSBtYW51YWxseSBzZW5kIHRoZSBpbnN0cnVjdGlvbnMgdG8gdGhlIGNvbnNvbGUgKG1vcmUgb24gdGhpcyBsYXRlcikuCgojIyMgV2hhdCBpcyB0aGUgcG9pbnQgb2YgYSBzY3JpcHQ/CgoqKkEgc2NyaXB0IGlzIGEgd2F5IHRvIHNhdmUgeW91ciB3b3JrIHNvIHlvdSBvbmx5IG5lZWQgdG8gd3JpdGUgdGhlIGNvZGUgb25jZS4qKiBPbmNlIHlvdSd2ZSB3cml0dGVuIGEgc2NyaXB0IG9uY2UsIHlvdSBjYW4gZXhlY3V0ZSBpdCBhcyBtYW55IHRpbWVzIGFzIHlvdSBsaWtlLCBidXQgeW91IHdvbid0IG5lZWQgdG8gKndyaXRlKiBpdCBhZ2Fpbi4gWW91IGNhbiBjb3B5IGFuZCBwYXN0ZSBvdGhlciBwZW9wbGUncyBjb2RlIGludG8geW91ciBzY3JpcHQgYW5kIHR3ZWFrIGl0IHRvIGZpdCB5b3VyIG5lZWRzLiBZb3UgY2FuIGRlYnVnIHlvdXIgY29kZSB3aXRob3V0IGhhdmluZyB0byB0eXBlIGl0IGluIG5ldyBlYWNoIHRpbWUuIFlvdSBjYW4gc2hhcmUgeW91ciBjb2RlIHdpdGggb3RoZXJzLCBhbmQgeW91IGNhbiBsZWF2ZSBjb21tZW50cyB0byB5b3Vyc2VsZiBpbiB5b3VyIGNvZGUgc28gdGhhdCB5b3UgY2FuIGxlYXZlIGl0IHNpdCBmb3IgYSB3aGlsZSBhbmQgdGhlbiByZW1lbWJlciB3aGF0IHlvdSB3ZXJlIGRvaW5nIHdoZW4geW91IGNvbWUgYmFjayB0byBpdC4KCiMjIyBIb3cgZG8geW91IHdyaXRlIGEgbmV3IHNjcmlwdD8KCk9uIGFsbCBwbGF0Zm9ybXM6IHRoZSBncmVlbiArIHN5bWJvbCBpbiB0aGUgdG9wIGxlZnQgY29ybmVyIHdpbGwgbGV0IHlvdSBjcmVhdGUgYSBuZXcgc2NyaXB0LgoKT24gYSBNYWM6IGBjb21tYW5kYCtgc2hpZnRgK2BOYCAgCk9uIGEgUEM6ICBgQ3RybGArYEFsdGArYElgCgpUaGUgc3ltYm9sIGAjYCBoaWRlcyB0aGUgdGV4dCB0aGF0IGZvbGxvd3Mgb24gdGhhdCBsaW5lIGZyb20gUiwgdGhhdCBpcywgaXQgImNvbW1lbnRzIGl0IG91dCIuIFRoaXMgbGV0cyB5b3Ugd3JpdGUgY29tbWVudHMgdG8geW91cnNlbGYgYW5kIHRvIGFueW9uZSBlbHNlIHdobyBtaWdodCByZWFkIHlvdXIgY29kZS4gWW91J2xsIHdhbnQgdG8gZG8gdGhpcyBzbyB5b3UgY2FuIHJlbWVtYmVyIHdoYXQgeW91IHdlcmUgZG9pbmcgKCp0cnVzdCogbWUsIHlvdSB3aWxsIG5vdCByZW1lbWJlcikgYW5kIHNvIG90aGVyIHBlb3BsZSBjYW4gcmVwbGljYXRlIHdoYXQgeW91IGRpZCAoZXZlbiBpZiBpdCdzIGp1c3QgdG8gaGVscCB5b3UgZGVidWcgeW91ciBjb2RlIGxhdGVyKS4KCklmIHlvdSB0eXBlIGBwcmludCgiSGVsbG8gV29ybGQhIilgICh3aXRoIGEgbmljZSBjb21tZW50KSBhbmQgdGhlbiBoaXQgYEVOVEVSYCBpbiB5b3VyIGNvbnNvbGUsIHlvdSB3aWxsIHNlZSBzb21ldGhpbmcgbGlrZSB0aGlzOgoKYGBgCj4gcHJpbnQoIkhlbGxvIFdvcmxkISIpICMgdGhpcyBsaW5lIHdpbGwgcHJvZHVjZSB0aGUgdGV4dCBiZXR3ZWVuIHRoZSBxdW90ZXMKYGBgCmBbMV0gIkhlbGxvIFdvcmxkISJgCgpJZiB5b3UgdHlwZSBgcHJpbnQoIkhlbGxvIFdvcmxkISIpYCBhbmQgaGl0IGBFTlRFUmAgaW4gYSBzY3JpcHQsIHlvdSB3aWxsIHNlZSBzb21ldGhpbmcgbGlrZSB0aGlzOgoKYGBgCnByaW50KCJIZWxsbyBXb3JsZCEiKSAgCiAKYGBgCgooTm90ZSB0aGF0IG5vdGhpbmcgaGFwcGVucy4gVGhlcmUgaXMgbm8gb3V0cHV0LiBBIHNjcmlwdCBpcyBqdXN0IGEgdGV4dCBmaWxlLikKCiMjIyBIb3cgZG8geW91IHVzZSBhIHNjcmlwdD8gCgpPcGVuIGEgbmV3IHNjcmlwdCBhbmQgdHlwZSBgcHJpbnQoIkhlbGxvIFdvcmxkISIpYCBpbnRvIGl0LiBIb3cgZG8geW91IGdldCBSIHRvIGV4ZWN1dGUgeW91ciBjb2RlPyBUaGVyZSBhcmUgYSBjb3VwbGUgd2F5czogIAoKLSBDbGljayB0aGUgYFJ1bmAgYnV0dG9uIG9uIHRoZSB0b3AgcmlnaHQgcG9ydGlvbiBvZiB0aGUgc2NyaXB0IHBhbmUuCiAgICAtIFRoaXMgd2lsbCBydW4gZXZlcnl0aGluZyBpbiB5b3VyIHNjcmlwdC4KLSBVc2UgYSBrZXlib2FyZCBzaG9ydGN1dAogICAgLSBUbyBydW4gb25seSB0aGUgbGluZSB5b3VyIGN1cnNvciBpcyBvbiwgYENvbW1hbmRgK2BFbnRlcmAKICAgIC0gVG8gcnVuIG9ubHkgdGhlIHNlbGVjdGVkIGNvZGUsIHNlbGVjdCBzb21lIGNvZGUgYW5kIHVzZSBgQ29tbWFuZGArYEVudGVyYAogICAgLSBUbyBydW4gdGhlIGVudGlyZSBzY3JpcHQsIGBDb21tYW5kYCtgU2hpZnRgK2BFbnRlcmAKCldoZW4geW91IHJ1biBhIHNjcmlwdCwgdGhlIHRleHQgaW4gdGhlIHNjcmlwdCBpcyBzZW50LCBsaW5lIGJ5IGxpbmUsIHRvIHRoZSBjb25zb2xlLiBPbmNlIGluIHRoZSBjb25zb2xlLCBSIGV4ZWN1dGVzIHRoZSBjb2RlLiBZb3UgY2FuIHdhdGNoIHRoZSBjb2RlIHByb2dyZXNzIGluIHRoZSBjb25zb2xlLiBJZiB0aGVyZSBpcyBhbnkgdGV4dCBvciBudW1lcmljYWwgb3V0cHV0LCBpdCB3aWxsIGFwcGVhciBpbiB0aGUgY29uc29sZS4gSWYgdGhlcmUgaXMgYSBncmFwaGljYWwgb3V0cHV0LCBpdCB3aWxsIGFwcGVhciBpbiB0aGUgUGxvdHMgdGFiIG9mIHRoZSBsb3dlciByaWdodCBwYW5lIChGaWxlcyBldGMpLgoKIyMjIFNhdmluZyBpbiBSU3R1ZGlvCgpOb3cgdGhhdCB3ZSd2ZSBnb25lIHRocm91Z2ggdGhlIGZ1bmRhbWVudGFscyBvZiBvcmdhbmlzYXRpb24gYW5kIGJhc2ljIFIgb3BlcmF0b3JzLCB3ZSBjYW4gZ2V0IGludG8gdGhlIG1vcmUgaW1wb3J0YW50IHRhc2sgb2YgcmVhZGluZyBkYXRhIGFuZCB3cml0aW5nIG91dHB1dCAoaS5lLiwgc2F2aW5nIG91ciB3b3JrKS4KCk9uY2UgeW91J3ZlIGNyZWF0ZWQgYSBwcm9qZWN0ICguUnByb2opLCB5b3UgY2FuIG9wZW4gdGhlIHByb2plY3QgYW5kIGl0IHNob3VsZCBvcGVuIHJpZ2h0IHRvIHdoZXJlIHlvdSBsZWZ0IG9mZi4gVGhpcyBtZWFucyB5b3VyIHNjcmlwdHMgd2lsbCBvcGVuIGFzIHdlbGwsIGFzIGxvbmcgYXMgeW91IGRpZCBub3QgY2xvc2UgdGhlbSB0aGUgbGFzdCB0aW1lIHlvdSB3b3JrZWQgb24gdGhlIHByb2plY3QuIEhvd2V2ZXIsIGlmIHlvdSB3YW50IHRvIG9wZW4gYSBzY3JpcHQgdGhhdCBpc24ndCBjdXJycmVudGx5IG9wZW4gYnV0IGRvZXMgZXhpc3QsIHlvdSBjYW4gZG8gc28gaW4gdGhlIEZpbGVzIHRhYiBvZiB0aGUgbG93ZXIgcmlnaHQgcGFuZS4gQ2xpY2sgb24gdGhlIG5hbWUgb2YgdGhlIHNjcmlwdCwgYW5kIGl0IHdpbGwgb3BlbiBpbiBhIG5ldyB0YWIgb2YgeW91ciBzY3JpcHRzIHBhbmUgKHRvcCBsZWZ0IGJ5IGRlZmF1bHQpLgoKIVtdKC4uL2d1aS9uZXctc2NyaXB0LnBuZykKCkhvd2V2ZXIsIGl0IGlzIHN0aWxsIGV4dHJlbWVseSBpbXBvcnRhbnQgdG8gc2F2ZSBhbGwgeW91ciB3b3JrLCBmcmVxdWVudGx5LiBJZiB5b3UgdXNlIEdpdEh1YiwgdGhlcmUgaXMgYSB3YXkgdG8gbGluayBpdCB0byBSU3R1ZGlvIHNvIHRoYXQgeW91IGNhbiBjb21taXQgY2hhbmdlcyBhbmQgaW50ZXJhY3Qgd2l0aCB5b3VyIHJlcG9zaXRvcmllcyBmcm9tIHdpdGhpbiB0aGUgUlN0dWRpbyBpbnRlcmZhY2UuCgojIyBSIGlzIGEgY2FsY3VsYXRvcgoKSXRzIGxlYXN0IHVuaXF1ZSBmdW5jdGlvbiBpcyB0byBjb21wdXRlIGFyaXRobWV0aWMuIFlvdSBwcm9iYWJseSBkb24ndCB3YW50IHRvIHVzZSBSIGp1c3QgdG8gYWRkIHN1bXMsIGJ1dCB5b3UgY291bGQgZG8uCmBgYHtyfQozICsgNApgYGAKCldoaXRlIHNwYWNlIGRvZXNuJ3QgbWF0dGVyIGZvciBtb3N0IHRoaW5ncyAoc28geW91IGNhbiBwdXQgc3BhY2VzIGJldHdlZW4gbnVtYmVycywgb3BlcmF0aW9ucywgbmFtZXMpLgpgYGB7cn0KMys0CmBgYAoKT3JkZXIgb2Ygb3BlcmF0aW9ucyBmb2xsb3dzIHN0YW5kYXJkIHJ1bGVzIChCSURNQVMgLyBCT0RNQVMgLyBQRU1EQVMpOgpgYGB7cn0KMyo0XjIKYGBgCgrigKZjb21wYXJlZCB0b+KApgpgYGB7cn0KKDMqNCleMgpgYGAKCgojIyMgKipUcnkgaXQgZm9yIHlvdXJzZWxmKioKCjEuIENyZWF0ZSBhIG5ldyBzY3JpcHQuCjIuIFNhdmUgYW5kIG5hbWUgdGhlIHNjcmlwdCBhcHByb3ByaWF0ZWx5LiAoWVlZWU1NREQtZGVzY3JpcHRpdmVfbmFtZS5SKQozLiBJbiB0aGUgc2NyaXB0LCBlbnRlciB0aGUgZm9sbG93aW5nIGNvZGU6ICAKYGBgCnByaW50KCJIZWxsbyB3b3JsZCEiKQozICsgNAo3XjIKYGBgCjQuIFJ1biB0aGUgZW50aXJlIHNjcmlwdC4KCllvdXIgY29uc29sZSBzaG91bGQgZW5kIHVwIGxvb2tpbmcgbGlrZSB0aGlzOiAgCmBgYAo+IHByaW50KCJIZWxsbyB3b3JsZCEiKQpbMV0gIkhlbGxvIHdvcmxkISIKPiAzICsgNApbMV0gNwo+IDdeMgpbMV0gNDkKPgpgYGAKCihJbiB0aGUgcmVzdCBvZiB0aGlzIGRvY3VtZW50LCBpbnN0ZWFkIG9mIG91dHB1dCBzdGFydGluZyB3aXRoIGA+YCwgaXQgbWF5IHN0YXJ0IHdpdGggYCMjYC4gVGhpcyBpcyBkdWUgdG8gaG93IFIgY29tcGlsZXMgYSBzY3JpcHQgdG8gYW4gSFRNTCBkb2N1bWVudCBhbmQgZG9lcyBub3QgY2hhbmdlIGFueXRoaW5nIGluIHRoZSBzY3JpcHQsIGNvZGUsIG9yIGNvbnRlbnRmdWwgb3V0cHV0LikKCiMjIyMgV2hhdCBkb2VzIGBbMV1gIG1lYW4/CgpUaGUgbnVtYmVyIGluIHNxdWFyZSBicmFja2V0cyB0byB0aGUgbGVmdCBvZiB0aGUgb3V0cHV0IGluZGljYXRlcyB0aGUgbnVtYmVyIG9mIHZhbHVlcyB0aGF0IGhhdmUgYmVlbiBwcmludGVkIGJ5IGluZGV4IG51bWJlci4gVGhhdCBpcywgaWYgdGhlcmUgYXJlIG11bHRpcGxlIG91dHB1dHMgb24gb25lIGxpbmUsIFsxXSB3aWxsIGFwcGVhci4gSWYgdGhlIHNldmVudGggaXRlbSBpbiB0aGUgb3V0cHV0IHdyYXBzIGFyb3VuZCBhbmQgYXBwZWFycyBvbiB0aGUgc2Vjb25kIGxpbmUsIGJvdGggWzFdIGFuZCBbN10gd2lsbCBhcHBlYXIuIFRoaXMgaXMgdXNlZnVsIHdoZW4gdHJ5aW5nIHRvIG1ha2Ugc2Vuc2Ugb2YgbG9uZyBsaXN0cyBvZiBudW1iZXJzLCBmb3IgaW5zdGFuY2UuCgpCZWxvdywgSSBzYXZlZCB0d28gbG9uZ2VyIHN0cmluZ3Mgb2YgdGV4dCBpbnRvIG9uZSB2YXJpYWJsZSBjYWxsZWQgYGxvbmdUZXh0YC4gVGhlbiB3aGVuIGl0J3MgcHJpbnRlZCwgaXQgYXBwZWFycyBvbiB0d28gbGluZXMuIFRoZSBgWzFdYCBpbmRpY2F0ZXMgdGhlIGZpcnN0IGl0ZW0gaW4gdGhlIGxpc3QgaXMgdGhlIGZpcnN0IGl0ZW0gb24gdGhlIGxpbmUgYW5kIHRoZSBgWzJdYCBpbmRpY2F0ZXMgdGhlIHNlY29uZCBpdGVtIGluIHRoZSBsaXN0IGlzIHRoZSBmaXJzdCBpdGVtIHRoYXQgYXBwZWFycyBvbiB0aGF0IGxpbmUuCgpgYGB7ciBsb25ndGV4dH0KbG9uZ1RleHQgPC0gYygiaSBkb24ndCB0aGluayB3ZSdsbCBiZSBhYmxlIHRvIGZpdCB0aGlzIHRleHQgb24gb25lIGxpbmUgb2YgdGhlIG91dHB1dCBjb25zb2xlIiwic28gdGhhdCBpdCBtaWdodCB3cmFwIGFyb3VuZCBhbmQgZGlzcGxheSBvbiB0d28gbGluZXMiKQpwcmludChsb25nVGV4dCkgIApgYGAKCiMjIyBXaGF0IGlzIGEgdmFyaWFibGU/CgpPbmUgb2YgdGhlIG1vc3QgaW1wb3J0YW50IGNvbXBvbmVudHMgb2YgKGFsbW9zdCkgYW55IHByb2dyYW1taW5nIGxhbmd1YWdlIGlzIGEgKnZhcmlhYmxlKi4gQSB2YXJpYWJsZSBpcyBhbiBvYmplY3QgdGhhdCBjYW4gYmUgYXNzaWduZWQgYSB2YWx1ZSwgYSBsaXN0IG9mIHZhbHVlcywgYSBtYXRyaXggb2YgdmFsdWVzLCBvciBzb21ldGhpbmcgYWxvbmcgdGhvc2UgbGluZXMuIEEgdmFyaWFibGUgaW4gUiBjYW4gYmUgbmFtZWQgYWxtb3N0IGFueXRoaW5nIHdpdGggYSBmZXcgZXhjZXB0aW9uczoKCkEgdmFyaWFibGUgbmFtZeKApiAgCgotIENhbm5vdCBzdGFydCB3aXRoIGEgbnVtYmVyICAKLSBDYW5ub3QgY29udGFpbiB3aGl0ZSBzcGFjZSAoaS5lLiwgc3BhY2VzLCB0YWJzLCBsaW5lIGJyZWFrcykgIAotIENhbiBjb250YWluIGAuYCBvciBgX2AgYnV0IGNhbm5vdCBjb250YWluIG90aGVyIG5vbi1hbHBoYW51bWVyaWMgY2hhcmFjdGVycyAgCi0gU2hvdWxkIGJlZ2luIHdpdGggYSBsb3dlcmNhc2UgbGV0dGVyICAKLSBTaG91bGQgYmUgbWVtb3JhYmxlIGFuZCBkZXNjcmlwdGl2ZSAgCi0gU2hvdWxkIG5vdCBiZSB0b28gbG9uZyBvciBkaWZmaWN1bHQgdG8gdHlwZSAgCi0gU2hvdWxkIG5vdCBiZSB0b28gdmFndWUgb3IgZ2VuZXJhbCAgCgpUbyBhc3NpZ24gYSB2YWx1ZSAoZXRjKSB0byBhIHZhcmlhYmxlLCB0aGVyZSBhcmUgdGhyZWUgcG9zc2libGUgb3BlcmF0b3JzOiBgPWAsIGA8LWAsIG9yIG9jY2FzaW9uYWxseSBgLT5gICh0aGUgbGF0dGVyIHR3byBsb29rIGxpa2UgYXJyb3dzKS4KCkZpcnN0IHdlIGFzc2lnbiB0aGUgdmFsdWUgb2YgMyB0byB0aGUgdmFyaWFibGUgYHhgLiBOb3RpY2UgdGhhdCBzcGFjZXMgYmV0d2VlbiB0aGUgbnVtYmVycyBhbmQgdGhlIG9wZXJhdG9yIGFyZSBvcHRpb25hbC4gSSBsaWtlIHRvIHVzZSB0aGVtIHRvIGhlbHAgc2VlIGVhY2ggY29tcG9uZW50IG1vcmUgY2xlYXJseS4KCmBgYAoKYGBgCgpXZSBjYW4gYWxzbyB1c2Ugb25lIG9mIHRoZSBhcnJvdyBvcGVyYXRvcnMuIFRoZSB0d28gY2hhcmFjdGVycyB0aGF0IGNvbXByaXNlIHRoZSBhcnJvdyBjYW5ub3QgaGF2ZSBzcGFjZSBiZXR3ZWVuIHRoZW0uIFRoZXkgYWN0IGFzIGEgc2luZ2xlIHVuaXQuIEZvciB0aGUgbGVmdHdhcmQtZmFjaW5nIGFycm93LCB0aGUgdmFsdWUocykgb24gdGhlIHJpZ2h0IGFyZSBhc3NpZ25lZCB0byB0aGUgdmFyaWFibGUgb24gdGhlIGxlZnQuCgpgYGAKCmBgYAoKTm93IHRoYXQgd2UndmUgYXNzaWduZWQgdmFsdWVzIHRvIGB4YCBhbmQgYHlgLCB3ZSBjYW4gZG8gdGhpbmdzIHRvIHRoZW0uIEJlbG93LCBJIGRlbW9uc3RyYXRlIHNvbWUgYmFzaWMgYXJ0aGltZXRpYyBvcGVyYXRvcnMgdGhhdCBhbGxvdyBSIHRvIGFjdCBsaWtlIGEgY2FsY3VsYXRvci4KCmBgYAoKYGBgCgpGaW5hbGx5LCB0aGUgcmlnaHR3YXJkLXBvaW50aW5nIGFycm93IGlzIHVzZWQgdmVyeSByYXJlbHksIGJ1dCBmdW5jdGlvbnMgaW4gYSBzaW1pbGFyIHdheSB0byB0aGUgb3RoZXIgdHdvIGFzc2lnbm1lbnQgb3BlcmF0b3JzLiBUaGUgdmFsdWUocykgb24gdGhlIGxlZnQgYXJlIGFzc2lnbmVkIHRvIHRoZSB2YXJpYWJsZSBvbiB0aGUgcmlnaHQuCgpgYGAKCmBgYAoKVG8gYXNzaWduIG1vcmUgdGhhbiBvbmUgdmFsdWUgdG8gYSB2YXJpYWJsZSwgdGhlcmUgYXJlIHNldmVyYWwgZnVuY3Rpb25zIHdlIGNhbiB1c2UsIGJ1dCB0aGUgbW9zdCBjb21tb24gYW5kIGVhc2llc3QgaXMgYGMoKWAuIFRvIHJlYWQgbW9yZSBhYm91dCB0aGUgZnVuY3Rpb24gYGMoKWAsIHlvdSBjYW4gdHlwZSBgY2AgaW50byB0aGUgc2VhcmNoIGJhciBpbiB0aGUgaGVscCB0YWIgaW4gdGhlIGxvd2VyIHJpZ2h0IHBhbmUsICpvciogeW91IGNhbiBpbnB1dCB0aGUgZm9sbG93aW5nIGludG8geW91ciBjb25zb2xlOgpgYGB7cn0KP2MKYGBgCgpJbiBzaG9ydCwgdGhpcyBmdW5jdGlvbiAqY29tYmluZXMqIGEgc2VyaWVzIG9mIHZhbHVlcyBpbnRvIGEgdmVjdG9yIG9yIGxpc3QuCgpgYGB7ciwgbWVzc2FnZT1UUlVFLCBlcnJvcj1UUlVFfQpjKDEsMiwzKQpjKCIxIiwiMiIsIjMiKQpjKCJvbmUiLCJ0d28iLCJ0aHJlZSIpCmMob25lLHR3byx0aHJlZSkKYGBgCgpOb3RlIHRoYXQgYmFyZSBudW1iZXJzIGFyZSBncmVlbiBhbmQgYXJlIG91dHB1dCB3aXRob3V0IHF1b3RhdGlvbiBtYXJrcywgbnVtYmVycyBhbmQgd29yZHMgaW4gcXVvdGF0aW9uIG1hcmtzIGFyZSBvdXRwdXQgYXMgc3VjaCwgYnV0ICp3b3JkcyB3aXRob3V0IHF1b3RhdGlvbiBtYXJrcyBwcm9kdWNlIGFuIGVycm9yKi4gVGhpcyBpcyBiZWNhdXNlIFIgYXNzdW1lcyB0aGF0IGFsbCB3b3JkcyB3aXRob3V0IHF1b3RhdGlvbiBtYXJrcyBhcmUgdmFyaWFibGVzLCBidXQgd2UgaGF2ZW4ndCBjcmVhdGVkIHZhcmlhYmxlcyBuYW1lZCBgb25lYCwgYHR3b2AsIG9yIGB0aHJlZWAuCgpgYGB7cn0Kb25lID0gMQp0d28gPSAyCnRocmVlID0gMwpjKG9uZSx0d28sdGhyZWUpCmBgYAoKCiMjIFIgaXMgZm9yIGludGVyYWN0aW5nIHdpdGggZGF0YSBmaWxlcwoKPiBEYXRhc2V0IGBzbGVlcGA6CgpgYGB7cn0KaGVhZChzbGVlcCkKYGBgCgoqIGNvbHVtbiAxID0gaG93IG1hbnkgZXh0cmEgaG91cnMgb2Ygc2xlZXAgd2VyZSByZWNvcmRlZAoqIGNvbHVtbiAyID0gd2hpY2ggZHJ1ZyB3YXMgYWRtaW5pc3RlcmVkCiogY29sdW1uIDMgPSB3aGljaCBwYXJ0aWNpcGFudAoKV2Ugd2lsbCB0YWxrIGluIGRlcHRoIGFib3V0IGhvdyB0byBpbnRlcmFjdCB3aXRoIGRhdGFzZXRzICp0b21vcnJvdyogd2hlbiB3ZSB3b3JrIHdpdGggdGhlIGB0aWR5dmVyc2VgIHBhY2thZ2VzLiBIb3dldmVyLCBiYXNlIFIgaGFzIGEgbnVtYmVyIG9mIHVzZWZ1bCBmdW5jdGlvbnMgYW5kIHByb3BlcnRpZXMgdG8gdW5kZXJzdGFuZCB0aGF0IHdpbGwgbWFrZSBgdGlkeXZlcnNlYCBtYWtlIG1vcmUgc2Vuc2UsIGJ1dCBhbHNvIGJlIG1vcmUgYXBwZWFsaW5nLgoKIyBJbmRpY2llcyAKIyMgRmluZGluZyB0aGUgaW5kZXggb2YgdGhlIHZhbHVlIHlvdSB3YW50CgpXaGF0IGRvZXMgdGhpcyBkbz8KYGBge3J9CnNsZWVwWzEsXQpgYGAKCkhvdyBkb2VzIGBzbGVlcFsyLF1gIGRpZmZlciBmcm9tIGBzbGVlcFsxLF1gPwpgYGAKCmBgYAoKSG93IGRvZXMgYHNsZWVwWzMsXWAgZGlmZmVyIGZyb20gYHNsZWVwWywzXWA/CmBgYAoKYGBgCgoKCgoKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CiPigKZ3aGljaCBtYWtlcyBpdCBgZGF0YXNldFtyb3csY29sdW1uXWAKYGBgCgoKIyMgTmF2aWdhdGluZyBiaWdnZXIgZGF0YXNldHMKCkluIHlvdXIgc2NyaXB0IChvciwgaWYgeW91IGRvbid0IHRha2UgbXkgYWR2aWNlLCBpbiB5b3VyIGNvbnNvbGUpLCB5b3UgY2FuIG9wZW4gYW5kIG1hbmlwdWxhdGUgYSBkYXRhc2V0LgoKUmlnaHQgY2xpY2sgYW5kIHNhdmUgW3RoaXMgZmlsZV0oaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL1ZlcmJpbmdOb3Vucy9ub3RlYm9va3MvbWFzdGVyL2RhdGEvYmlub21pYWwtZGF0YS5jc3YpIHRvIHlvdXIgZm9sZGVyIG5hbWVkIGBkYXRhYC4KCmBgYHtyLCBlY2hvPUZBTFNFfQpkYXRhIDwtIHJlYWQuY3N2KCIuLi9kYXRhL2Jpbm9taWFsLWRhdGEuY3N2IikKYGBgCgpgYGB7ciwgZXJyb3I9VFJVRSwgZXZhbD1GQUxTRX0KZGF0YSA8LSByZWFkLmNzdigiZGF0YS9iaW5vbWlhbC1kYXRhLmNzdiIpCmBgYAoKTm93LCBpZiB5b3Ugd2FudCB0byB2aWV3IHRoZSBmaXJzdCBzaXggcm93cyBvZiB0aGUgZGF0YXNldCB0byBzZWUgd2hhdCB0eXBlcyBvZiB0aGluZ3MgYXJlIGluIGl0LCB5b3UgY2FuIHVzZSB0aGUgZnVuY3Rpb24gYGhlYWQoKWAuCgpgYGAKCmBgYAoKWW91IGNhbiBhbHNvIGxvb2sgYXQgdGhlIGJvdHRvbSBzaXggcm93cyB3aXRoIGB0YWlsKClgCgpgYGAKCmBgYAoKIyMjIEJhc2ljIHF1ZXJ5aW5nIGZ1bmN0aW9ucwoKSWYgd2Ugd2FudCB0byBmaW5kIG91dCB3aGF0IGVhY2ggb2YgdGhlIGV4cGVyaW1lbnRzIGFyZSBjYWxsZWQsIG9yIGhvdyBtYW55IGNvbmRpdGlvbnMgdGhlcmUgYXJlLCB3ZSBjYW4gdXNlIHRoZSBmdW5jdGlvbiBgdW5pcXVlKClgLiAKCk5vdGUgdGhhdCB3ZSBtdXN0IHNwZWNpZnkgd2hhdCB2YXJpYWJsZSBuYW1lIHdlJ3ZlIGdpdmVuIG91ciBkYXRhc2V0IChgZGF0YWApIGFuZCB3aGF0IGNvbHVtbiB3ZSB3YW50IHRvIHF1ZXJ5IChgZXhwZXJpbWVudGApLiBUaGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGRhdGFzZXQgYW5kIHRoZSBjb2x1bW4gaW4gdGhlIGRhdGFzZXQgaXMgc3BlY2lmaWVkIHdpdGggdGhlIGAkYCBvcGVyYXRvci4KCmBgYAoKYGBgCgpUaGVyZSBhcmUgdGhyZWUgZXhwZXJpbWVudHMsIGFuZCB0aGVpciBuYW1lcyBhcmUgYCJmaXJzdCJgLCBgInNlY29uZCJgLCBhbmQgYCJ0aGlyZCJgLiAKCklmIHdlIHdhbnQgdG8ga25vdyAqaG93IG1hbnkqIHVuaXF1ZSB2YWx1ZXMgdGhlcmUgYXJlIGluIGEgY29sdW1uLCB3ZSBjYW4gZW1iZWQgdGhlIGB1bmlxdWUoKWAgZnVuY3Rpb24gaW4gdGhlIGBsZW5ndGgoKWAgZnVuY3Rpb24uCgpgYGAKCmBgYAoKVGhlcmUgYXJlIHRocmVlIGRpZmZlcmVudCBleHBlcmltZW50cyBpbiB0aGlzIGRhdGFzZXQuCgpVc2UgYHN0cigpYCB0byBnZXQgYSBzdW1tYXJ5IG9mIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGRhdGFzZXQsIHdoaWNoIHdpbGwgYWxzbyBnaXZlIHlvdSB0aGlzIHR5cGUgb2YgaW5mb3JtYXRpb24uCmBgYAoKYGBgCgpZb3UgY2FuIGFsc28gdmlldyB0aGUgZGF0YXNldCBhcyBhIHNwcmVhZHNoZWV0IChhbHRob3VnaCBpdCBjYW4ndCBiZSBhbHRlcmVkKS4KYGBgCgpgYGAKCiMjIyBDZWxscyB3aXRoaW4gYSBkYXRhc2V0CgpGaW5hbGx5LCBpZiB3ZSB3YW50IHRvIGZpbmQgb3V0IGhvdyBtYW55IHVuaXF1ZSBpdGVtcyB0aGVyZSBhcmUgaW4gZXhwZXJpbWVudCAiZmlyc3QiIG9ubHksIHdlIGNhbiBzcGVjaWZ5IGEgc3Vic2V0IG9mIHRoZSBkYXRhc2V0IHVzaW5nIHNxdWFyZSBicmFja2V0cyBgW11gLiBCZWZvcmUgd2UgZG8gdGhhdCwgdGhvdWdoLCBsZXQncyBnbyB0aHJvdWdoIHdoYXQgdGhlIGFyZ3VtZW50cyBmb3IgdGhlIHNxdWFyZSBicmFja2V0cyBhcmUuCgpBbiAqKmluZGV4KiogcmVmZXJzIHRvIHRoZSBsb2NhdGlvbiBvZiBhbiBpdGVtIGluIGEgbGlzdCwgdmVjdG9yLCBvciBtYXRyaXguCgpJZiB5b3UgaGF2ZSBhIGxpc3QgdGhhdCBsb29rcyBsaWtlIHRoZSBvbmUgYmVsb3csICpncmVlbiogaXMgYXQgaW5kZXggYDRgIChpbiB0aGUgUiBwcm9ncmFtbWluZyBsYW5ndWFnZSkuCgpgWyJyZWQiLCAib3JhbmdlIiwgInllbGxvdyIsICJncmVlbiIsICJibHVlIiwgImluZGlnbyIsICJ2aW9sZXQiXWAKCklmIHlvdSBoYXZlIGEgbWF0cml4IGxpa2UgdGhlIG9uZSBiZWxvdywgeW91IG11c3Qgc3BlY2lmeSB0aGUgaW5kZXggb2YgdGhlIHJvdyBhbmQvb3IgY29sdW1uIChgW3Jvdyxjb2x1bW5dYCkuCgp8IGNvbG91ciB8IHdvcmRMZW5ndGggfCB3YXZlTGVuZ3RoTk0gfAp8LS0tLS0tLS18LS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLXwKfCByZWQgICAgfCAzICAgICAgICAgIHwgNzAwICAgICAgICB8Cnwgb3JhbmdlIHwgNiAgICAgICAgICB8IDYzMCAgICAgICAgfAp8IHllbGxvdyB8IDYgICAgICAgICAgfCA2MDAgICAgICAgIHwKfCBncmVlbiAgfCA1ICAgICAgICAgIHwgNTUwICAgICAgICB8CnwgYmx1ZSAgIHwgNCAgICAgICAgICB8IDQ3MCAgICAgICAgfAp8IGluZGlnbyB8IDYgICAgICAgICAgfCA0MjUgICAgICAgIHwKfCB2aW9sZXQgfCA2ICAgICAgICAgIHwgNDAwICAgICAgICB8CgpUaGUgbG9jYXRpb24gb2YgKmdyZWVuKiBpcyBpbiB0aGUgZm91cnRoIHJvdyBhbmQgdGhlIGZpcnN0IGNvbHVtbiwgc28gd2UgY2FuIGlkZW50aWZ5IGl0IGFzIGBbNCwxXWAuIElmIHdlIG9ubHkgc3BlY2lmeSB0aGUgcm93IChgWzQsXWApLCB3ZSB3aWxsIGdldCBldmVyeXRoaW5nIGluIHRoZSBmb3VydGggcm93IChgImdyZWVuIiwgNCwgNDcwYCkuIElmIHdlIG9ubHkgc3BlY2lmeSB0aGUgZmlyc3QgY29sdW1uLCB3ZSB3aWxsIGdldCBhIGxpc3Qgb2YgY29sb3VycywgbGlrZSB3ZSBkaWQgYWJvdmU6IAoKKGAicmVkIiwgIm9yYW5nZSIsICJ5ZWxsb3ciLCAiZ3JlZW4iLCAiYmx1ZSIsICJpbmRpZ28iLCAidmlvbGV0ImApCgpOb3csIGdvaW5nIGJhY2sgdG8gb3VyIGRhdGFzZXQsIGlmIHdlIHdhbnQgdG8gdmlldyB0aGUgY29udGVudCBvZiBvbmUgY29sdW1uLCBzdWNoIGFzIGBleHBlcmltZW50YCwgd2UgY2FuIHNwZWNpZnkgdGhhdCBjb2x1bW4gd2l0aCB0aGUgYCRgIG9wZXJhdG9yLiBCdXQgaWYgeW91IHdhbnQgdG8gdmlldyBhIHN1YnNldCBvZiBhIGNvbHVtbiwgd2UgY2FuIGFsc28gc3BlY2lmeSB3aGF0IGNyaXRlcmlhIHdlIHdhbnQgdG8gdmlldyAob3IgZG9uJ3Qgd2FudCB0byB2aWV3KS4KCkZvciBpbnN0YW5jZSwgaWYgd2Ugd2FudCB0byB2aWV3IG9ubHkgdGhlIHNlY29uZCBleHBlcmltZW50ICh3aGljaCBpcyBjYWxsZWQgYHNlY29uZGAgaW4gdGhlIGBleHBlcmltZW50YCBjb2x1bW4sIGhlbHBmdWxseSBlbm91Z2gpLCB3ZSBjYW4gdXNlIHRoZSBjb2RlIGJlbG93OgoKYGBgCgpgYGAKCkxldCdzIGJyZWFrIHRoZSBzeW50YXggb2YgdGhpcyBjb2RlIGRvd24uCgpGaXJzdCwgd2Ugd3JpdGUgYGRhdGFgIGJlY2F1c2Ugd2Ugd2FudCB0byBsb29rIHdpdGhpbiBvdXIgZGF0YXNldCB0aGF0IHdlJ3ZlIG5hbWVkICJkYXRhIi4gVGhlbiB3ZSBwdXQgaW4gdGhlIHNxdWFyZSBicmFja2V0cyBgW11gIGFmdGVyIGBkYXRhYCBiZWNhdXNlIHdlIHdhbnQgdG8gbG9vayBhdCBhIHN1YnNldCBvZiB0aGUgZGF0YXNldC4gSW5zaWRlIG9mIHRoZSBzcXVhcmUgYnJhY2tldHMsIHdlIHdhbnQgdG8gc3BlY2lmeSB3aGF0IGNvbHVtbiBoYXMgdGhlIGluZm9ybWF0aW9uIHRoYXQgd2UgY2FuIHVzZSBmb3IgaWRlbnRpZnlpbmcgdGhlIHRhcmdldCBzdWJzZXQuIERvIHRvIHRoYXQsIHdlIHdyaXRlIGBkYXRhJGV4cGVyaW1lbnRgIHRvIHNheSB0aGF0IHRoZSAiZXhwZXJpbWVudCJjb2x1bW4gaW4gImRhdGEiIGhhcyB0aGUgaW1wb3J0YW50IGluZm9ybWF0aW9uLCB0aGVuIGA9PWAgdG8gY2hlY2sgZWFjaCB2YWx1ZSB0byBzZWUgaWYgaXQncyB0aGUgc2FtZSBhcyBgInNlY29uZCJgLiBXZSBmaW5hbGx5IHB1dCBhIGNvbW1hIGAsYCBhcyB0aGUgbGFzdCBjaGFyYWN0ZXIgd2l0aGluIHRoZSBzcXVhcmUgYnJhY2tldHMgdG8gc3BlY2lmeSB3ZSB3YW50IHRvIHNlZSBhbGwgdGhlICpyb3dzKiB0aGF0IG1hdGNoIHRoZXNlIGNyaXRlcmlhIChyZW1lbWJlcjogYFtyb3csY29sdW1uXWApLgoKSSB3b24ndCBnbyBpbnRvIHRoaXMgbW9yZSBub3csIGJ1dCBgPT1gIGlzIGEgdmVyeSBkaWZmZXJlbnQgb3BlcmF0b3IgdG8gYD1gLiBXaGlsZSBgPWAgYXNzaWducyBhIHZhbHVlLCBgPT1gIGFza3Mgd2hldGhlciBvciBub3QgdHdvIHRoaW5ncyBhcmUgZXF1YWwuIFRoZSBvcHBvc2l0ZSBvZiBgPT1gIGlzIGAhPWAgKHByb25vdW5jZWQgImJhbmctZXF1YWxzIiBvciAibm90LWVxdWFsLXRvIikuCgpHb2luZyBiYWNrIHRvIHRoZSBgdW5pcXVlKClgIGZ1bmN0aW9uLCBpZiB3ZSB3YW50IHRvIHF1ZXJ5IGhvdyBtYW55IHVuaXF1ZSBpdGVtcyBhcmUgaW4gdGhlIHNlY29uZCBleHBlcmltZW50IG9ubHksIHdlIGNhbiB1c2UgdGhlIGZvbGxvd2luZyBjb2RlOgoKYGBge3J9Cmxlbmd0aCh1bmlxdWUoZGF0YSRpdGVtW2RhdGEkZXhwZXJpbWVudD09InNlY29uZCJdKSkKYGBgCgpUaGlzIG9ubHkgZGlmZmVycyBmcm9tIHRoZSBwcmV2aW91cyBleGFtcGxlIGluIGEgc21hbGwgbnVtYmVyIG9mIHdheXMuIEluc3RlYWQgb2YgcXVlcnlpbmcgYSB0d28gZGltZW5zaW9uYWwgbWF0cml4IChgZGF0YWAgaGFzIHJvd3MgYW5kIGNvbHVtbnMpLCB3ZSB3YW50IHRvIHF1ZXJ5IGEgb25lIGRpbWVuc2lvbmFsIHZlY3RvciAoYGl0ZW1gKSwgd2hpY2ggaXMgYSBzdWJzZXQgb2YgYGRhdGFgLiBUaGlzIGlzIHdoeSB0aGVyZSBpcyBubyBjb21tYSBhdCB0aGUgZW5kIG9mIHRoZSBleHByZXNzaW9uIGluIHRoZSBzcXVhcmUgYnJhY2tldHMuIFRoYXQgaXMsIHdlIHdhbnQgdG8gcXVlcnkgYSBzdWJzZXQgb2YgYSBzdWJzZXQsIHNvIHdlIHNwZWNpZnkgdGhlIGNvbHVtbiB3aXRoIG91ciB0YXJnZXQgaW5mb3JtYXRpb24gYW5kIHRoZSBjb2x1bW4gYW5kIHN1YnNldCBpbmZvcm1hdGlvbiBmb3IgdGhlIGNvbHVtbiB0aGF0IHdpbGwgaGVscCB1cyBuYXJyb3cgZG93biB3aGF0IHdlJ3JlIGxvb2tpbmcgYXQuIFRoZW4sIGJ5IHVzaW5nIGB1bmlxdWUoKWAsIHdlIHdvbid0IGNvdW50IG11bHRpcGxlIHRva2VucyBvZiBhbiBpdGVtLCBqdXN0IHRoZSB0eXBlIGNvdW50LiBGaW5hbGx5LCBieSB1c2luZyBgbGVuZ3RoKClgLCB3ZSBjYW4gZmluZCBvdXQgaG93IG1hbnkgdHlwZXMgdGhlcmUgYXJlLgoKSXQgc3RhcnRzIHRvIGxvb2sgbWVzc3kgYW5kIGhhcmQgdG8gcmVhZCBwcmV0dHkgcXVpY2tseSB0aG91Z2guIFtUb21vcnJvdydzIHR1dG9yaWFsXSgyMDE5MDYwNC10aWR5dmVyc2UuaHRtbCkgd2lsbCBpbnRyb2R1Y2UgeW91IHRvIGEgZGlmZmVyZW50IHdheSBvZiBkb2luZyB0aGlzIHRoYXQgaXMgZWFzaWVyIHRvIHJlYWQuCgpUcnkgdGhlc2Ugb24geW91ciBvd246CgpXaGF0IGFyZSBhbGwgdGhlIHVuaXF1ZSB2YWx1ZXMgaW4gYElEYD8KYGBgCgpgYGAKCldoYXQncyB0aGUgdmFsdWUgaW4gdGhlIGZpcnN0IHJvdywgdGhpcmQgY29sdW1uPwpgYGAKCmBgYAoKV2hhdCdzIHRoZSBmaXJzdCBlbGVtZW50IGluIHRoZSBjb2x1bW4gYElEYD8KCmBgYAoKYGBgCgojIyMgVGFiLWRlbGltaXRlZCBmaWxlcyAoLnR4dCkKClRhYiBkZWxpbWl0ZWQgZmlsZXMgdXNlIHdoaXRlIHNwYWNlIChzcGVjaWZpY2FsbHksIHRoZSB0YWIgY2hhcmFjdGVyLCB1bmljb2RlOiBVKzAwMDkgc29tZXRpbWVzIGNvZGVkIGFzIGBcdGApIHRvIHNlcGFyYXRlIGluZm9ybWF0aW9uIGluIGNvbHVtbnMgYW5kIGxpbmUgYnJlYWtzIChlaXRoZXIgImNhcnJpYWdlIHJldHVybiIgb3IgIm5ldyBsaW5lIiBjaGFyYWN0ZXJzLCBzb21ldGltZXMgY29kZWQgYXMgYFxyYCBhbmQgYFxuYCByZXNwZWN0aXZlbHkpLiBUaGlzIGNvdWxkIHJlc3VsdCBpbiBhIHRleHQgZmlsZSB0aGF0IGxvb2tzIHNvbWV0aGluZyBsaWtlIHRoaXM6CgpgYGB7ciwgZWNobz1GQUxTRX0KaHRtbHRvb2xzOjppbWcoc3JjID0ga25pdHI6OmltYWdlX3VyaSgiLi4vZ3VpL3R4dC5wbmciKSwgCiAgICAgICAgICAgICAgIGFsdCA9ICdsb2dvJywgCiAgICAgICAgICAgICAgIHN0eWxlID0gJ3Bvc2l0aW9uOnJlbGF0aXZlOyB0b3A6MDsgcmlnaHQ6MDsgcGFkZGluZzoxMHB4OyB3aWR0aDo2MCUnKQpgYGAKCgpOb3RlIGhvdyB0aGUgY29sdW1ucyBkb24ndCBuZWNlc3NhcmlseSBsaW5lIHVwIG5lYXRseS4gVGhpcyBpcyBiZWNhdXNlIHRoZSB0YWIgY2hhcmFjdGVyIGlzIG5vdCBhIGZpeGVkIHdpZHRoLCBidXQgcmF0aGVyIHJlZmVycyB0byBhIGxvY2F0aW9uIGFsb25nIHRoZSBob3Jpem9udGFsIGF4aXMgb2YgdGhlIHBhZ2UgKGF0IGxlYXN0IGluIHRoaXMgZmlsZSB0eXBlKS4gRm9yIGEgaHVtYW4sIHRoaXMgaXMgaGFyZGVyIHRvIHJlYWQgdGhhbiBhIHNwcmVhZHNoZWV0LCBidXQgZm9yIGEgY29tcHV0ZXIgaXQncyBlYXNpZXIuCgpJbXBvcnRhbnRseSwgdGV4dCBmaWxlcyBjYW4gYmUgZW5jb2RlZCBhcyBVVEYtOCAob3IgVVRGLTE2KSwgd2hpY2ggd2lsbCBhY2NvbW1vZGF0ZSBtb3N0IGNoYXJhY3RlcnMsIGV2ZW4gZnJvbSBvdGhlciBsYW5ndWFnZXMgYW5kIGFscGhhYmV0cy4gVGhleSBjYW4gYWxzbyBiZSBlbmNvZGVkIGFzIEFTQ0lJIChhIHZlcnkgYmFzaWMgZW5jb2RpbmcgdGhhdCBvbmx5IGFsbG93cyBhbHBoYW51bWVyaWMgTGF0aW4gY2hhcmFjdGVycyBhbmQgc29tZSBwdW5jdHVhdGlvbiksIG9yIGNlcnRhaW4gdHlwZXMgb2Ygb2xkIGVuY29kaW5ncyB0aGF0IGFyZSBub3QgY29tcGF0aWJsZSBhY3Jvc3MgcGxhdGZvcm1zLiBJbiBwYXJ0aWN1bGFyLCBNaWNyb3NvZnQgV29yZCB3aWxsICoqbm90KiogcHJvZHVjZSBhIHVzZWZ1bCBlbmNvZGluZy4gCgo+IERPIE5PVCBVU0UgTUlDUk9TT0ZUIFdPUkQgKE9SIFNJTUlMQVIpIFRPIEVESVQgQSBEQVRBU0VUICAKPiAqKlNFUklPVVNMWSwgRE8gTk9UIERPIElUKioKCk9uIFdpbmRvd3MsIFtOb3RlcGFkKytdKGh0dHBzOi8vbm90ZXBhZC1wbHVzLXBsdXMub3JnLykgaXMgb25lIG9mIHRoZSBiZXN0IHBsYWluIHRleHQgZWRpdG9ycywgYW5kIGl0J3MgZnJlZS4gT24gTWFjaW50b3NoLCBbQkJFZGl0XShodHRwczovL3d3dy5iYXJlYm9uZXMuY29tL3Byb2R1Y3RzL2JiZWRpdC8pIGlzIG15IHBlcnNvbmFsIGZhdm9yaXRlIHBsYWluIHRleHQgZWRpdG9yLiBGb3IgZXhhbXBsZSwgaW4gQkJFZGl0LCB5b3UgY2FuIGNoYW5nZSB0aGUgZW5jb2Rpbmcgb2YgYSBmaWxlIChpbiBjYXNlIHRoZSB3cm9uZyBvbmUgd2FzIGNob3NlbiBpbml0aWFsbHksIG9yIGluIGNhc2UgeW91IHdpc2ggdG8gZW5zdXJlIHlvdXIgZmlsZSBoYXMgYSBjb21wYXRpYmxlIGVuY29kaW5nKS4gSSByZWNvbW1lbmQgKipVVEYtOCoqLgoKYGBge3IsIGVjaG89RkFMU0V9Cmh0bWx0b29sczo6aW1nKHNyYyA9IGtuaXRyOjppbWFnZV91cmkoIi4uL2d1aS9lbmNvZGluZ3MucG5nIiksIAogICAgICAgICAgICAgICBhbHQgPSAnbG9nbycsIAogICAgICAgICAgICAgICBzdHlsZSA9ICdwb3NpdGlvbjpyZWxhdGl2ZTsgdG9wOjA7IHJpZ2h0OjA7IHBhZGRpbmc6MTBweDsgd2lkdGg6NDAlJykKYGBgCgpJdCBpcyBwb3NzaWJsZSB0byBjcmVhdGUgYSAudHh0IHRhYiBkZWxpbWl0ZWQgZmlsZSBieSBjb3B5aW5nIGFuZCBwYXN0aW5nIGEgc3ByZWFkc2hlZXQgKGUuZy4sIGZyb20gRXhjZWwgb3IgR29vZ2xlIFNoZWV0cykgaW50byBhIHBsYWluIHRleHQgZmlsZS4gVGhpcyBpcyBhbHNvIHVzZWZ1bCBpZiB5b3UgYXJlIG1vcmUgY29tZm9ydGFibGUgd2l0aCBzcHJlYWRzaGVldHMgdGhhbiBSIGF0IHRoZSBtb21lbnQsIGFsdGhvdWdoIHlvdSB3aWxsIHNvb24gZmluZCBSIHRvIGJlIGVhc2llciBhbmQgZmFzdGVyIHRoYW4gRXhjZWwgZm9yIG1vc3QgZGF0YSBvcmdhbmlzYXRpb24hCgpPbmNlIHlvdSBoYXZlIGNyZWF0ZWQgYW5kIHNhdmVkIHlvdXIgZGF0YXNldCBhcyBhIGAudHh0YCBmaWxlLCB5b3UgY2FuIGxvYWQgaXQgaW50byBSIGFuZCBzYXZlIGl0IHdpdGggYSB2YXJpYWJsZSBuYW1lIHVzaW5nIHRoZSBmb2xsb3dpbmcgY29kZToKCmBgYHtyLCBldmFsPUZBTFNFfQpkYXRhIDwtIHJlYWQuZGVsaW0oImRhdGEvMjAxODA5MDgtbXlfZGF0YV9maWxlLnR4dCIsIGhlYWRlcj1UUlVFLCBhcy5pcz1UUlVFKQpgYGAKClRoZSBmdW5jdGlvbiBgcmVhZC5kZWxpbSgpYCB0YWtlcyBzZXZlcmFsIGFyZ3VtZW50cywgYnV0IG9ubHkgb25lIGlzIG9ibGlnYXRvcnkuIFRoZSBiYXJlIG1pbmltdW0geW91IG11c3QgZ2l2ZSBpdCBpcyB0aGUgbmFtZSBvZiB5b3VyIGAudHh0YCBmaWxlLCB3aXRoaW4gcXVvdGF0aW9uIG1hcmtzIHRvIHNpZ25pZnkgaXQgaXMgYSBzdHJpbmcgb2YgY2hhcmFjdGVycyBhbmQgbm90IGEgdmFyaWFibGUgbmFtZS4gU2luY2Ugb3VyIGZvbGRlciBmb3Igc2F2aW5nIGRhdGFzZXRzIGlzIGNhbGxlZCAiZGF0YSIsIHdlIHByZWZhY2Ugb3VyIGRhdGFzZXQncyBuYW1lIHdpdGggYGRhdGFgIGFuZCBhIGAvYCB0byBpbmRpY2F0ZSB0aGF0IHRoZSB0YXJnZXQgZmlsZSBpcyBpbnNpZGUgdGhlIGZvbGRlciBjYWxsZWQgYGRhdGFgLiBUaGlzIGlzIGd1YXJhbnRlZWQgdG8gd29yayBvbiBhIE1hY2ludG9zaCBjb21wdXRlciwgYnV0IHlvdSBtYXkgbmVlZCB0byByZXBsYWNlIHRoZSBgL2AgY2hhcmFjdGVyIHdpdGggYSBgXGAgY2hhcmFjdGVyIGlmIHlvdSBhcmUgd29ya2luZyBvbiBhIFdpbmRvd3MgY29tcHV0ZXIuCgojIyMgQ29tbWEgc2VwYXJhdGVkIHZhbHVlcyAoLmNzdikKCkFub3RoZXIgdHlwZSBvZiBmaWxlIGlzIHRoZSBgLmNzdmAgb3IgImNvbW1hLXNlcGFyYXRlZCB2YWx1ZXMiIGZpbGUuIFRoaXMgdHlwZSBvZiBmaWxlIGlzIGZ1bmN0aW9uYWxseSBlcXVpdmFsZW50IHRvIGEgdGFiLWRlbGltaXRlZCBmaWxlLCBidXQgaW5zdGVhZCBvZiBlYWNoIHZhbHVlIGluIGEgcm93IGJlaW5nIHNlcGFyYXRlZCB3aXRoIHRhYnMsIHRoZXkgYXJlIHNlcGFyYXRlZCB3aXRoIGNvbW1hcy4gRnVydGhlcm1vcmUsIGEgLmNzdiBmaWxlIGNhbiBkaXN0aW5ndWlzaCBiZXR3ZWVuIHZhbHVlcyB0aGF0IGFyZSBzdXBwb3NlZCB0byBiZSB0ZXh0IGFuZCB2YWx1ZXMgdGhhdCBhcmUgbnVtZXJpYy4gSXQgdHlwaWNhbGx5IGRvZXMgdGhpcyBieSBwdXR0aW5nIHRleHQgaW4gcXVvdGF0aW9uIG1hcmtzLgoKYGBge3IsIGVjaG89RkFMU0V9Cmh0bWx0b29sczo6aW1nKHNyYyA9IGtuaXRyOjppbWFnZV91cmkoIi4uL2d1aS9jc3YucG5nIiksIAogICAgICAgICAgICAgICBhbHQgPSAnbG9nbycsIAogICAgICAgICAgICAgICBzdHlsZSA9ICdwb3NpdGlvbjpyZWxhdGl2ZTsgdG9wOjA7IHJpZ2h0OjA7IHBhZGRpbmc6MTBweDsgd2lkdGg6NjAlJykKYGBgCgpUaGlzIGtpbmQgb2YgZmlsZSBtaWdodCBiZSBnZW5lcmF0ZWQgYXV0b21hdGljYWxseSBieSB5b3VyIGRhdGEgZ2F0aGVyaW5nIHNvZnR3YXJlLCBvciB5b3UgY2FuIHNhdmUgYW4gRXhjZWwgc3ByZWFkc2hlZXQgKG9yIG1vc3Qgb3RoZXIga2luZHMgb2Ygc3ByZWFkc2hlZXRzKSBhcyBhIC5jc3YgZnJvbSB3aXRoaW4gdGhlIG5hdGl2ZSBwcm9ncmFtIGludGVyZmFjZS4gSW4gbWFueSB3YXlzLCB0aGUgLmNzdiBpcyBiZXR0ZXIgdGhhbiBhIHRhYiBkZWxpbWl0ZWQgZmlsZS4gRm9yIGluc3RhbmNlLCBpdCBpcyBsZXNzIGxpa2VseSB0byBoYXZlIHByb2JsZW1zIHdpdGggd2hpdGUgc3BhY2UgaWYsIHNheSwgb25lIG9mIHRoZSBjb2x1bW5zIGNvbnRhaW5zIHNlbnRlbmNlcyBvciBsb25nZXIgc3RyaW5ncyBvZiB0ZXh0LiBIb3dldmVyLCBiZWNhdXNlIHRoZSBjb21tYSBpcyB0aGUgZWxlbWVudCB0aGF0IHNlcGFyYXRlcyBlYWNoIHZhbHVlIGluIGEgY29sdW1uLCBhIC5jc3YgY2FuIHNvbWV0aW1lcyBoYXZlIGRpZmZpY3VsdHkgd2l0aCBwdW5jdHVhdGlvbiBpbiBzZW50ZW5jZXMuIFRoaXMgaXMgd2h5IGVuY2xvc2luZyBzdHJpbmdzIG9mIHRleHQgaW4gcXVvdGF0aW9uIG1hcmtzIGlzIGNydWNpYWwuIEl0IGluZGljYXRlcyB0aGF0IGFueSBjb21tYSB3aXRoaW4gcXVvdGF0aW9uIG1hcmtzIGlzIG1lYW50IHRvIGJlIHRyZWF0ZWQgYXMgdGV4dCBhbmQgbm90IHRoZSBzZXBhcmF0aW5nIG1hcmtlci4KCkEgLmNzdiBjYW4gYmUgbG9hZGVkIGludG8gUiBhcyBhIHZhcmlhYmxlIHVzaW5nIHRoZSBmb2xsb3dpbmcgY29kZToKCmBgYHtyLCBldmFsPUZBTFNFfQpkYXRhIDwtIHJlYWQuY3N2KCJkYXRhLzIwMTgwOTA4LW15X2RhdGFfZmlsZS5jc3YiLCBoZWFkZXI9VFJVRSwgYXMuaXM9VFJVRSkKYGBgCgpBcyBiZWZvcmUsIHRoZSBvbmx5IG9ibGlnYXRvcnkgYXJndW1lbnQgaXMgdGhlIG5hbWUgYW5kIGxvY2F0aW9uIG9mIHRoZSBmaWxlLiBIb3dldmVyLCBJIHByZWZlciB0byBzcGVjaWZ5IHRoYXQgdGhlIGZpcnN0IHJvdyBvZiB0aGUgZGF0YXNldCBpcyB0aGUgaGVhZGVyIHJvdywgYW5kIEkgYWxzbyBwcmVmZXIgdG8gc3BlY2lmeSBgYXMuaXM9VFJVRWAgc28gdGhhdCB0ZXh0IGlzIG5vdCBhdXRvbWF0aWNhbGx5IHRyZWF0ZWQgbGlrZSBhIG11bHRpLWxldmVsIGZhY3RvciAoYnV0IGluc3RlYWQsIGFzIHRleHQgY2hhcmFjdGVycykuCgojIyMgV2h5IG5vdCBFeGNlbD8gKC54bHMvLnhsc3gpCgpUaGVyZSBhcmUgd2F5cyB0byBsb2FkIEV4Y2VsIHNwcmVhZHNoZWV0cyBkaXJlY3RseSBpbnRvIFIsIGJ1dCB0aGVyZSBhcmUgbG90cyBvZiBnb29kIHJlYXNvbnMgKm5vdCogdG8uIEZpcnN0IG9mIGFsbCwgYW55IGZvcm1hdHRpbmcgdGhhdCB5b3Ugc2F2ZSBpbiB5b3VyIHNwcmVhZHNoZWV0IHdpbGwgbmVlZCB0byBiZSBmaWx0ZXJlZCBvdXQuIFRoaXMgbWVhbnMgdGhhdCBjb2xvdXItY29kaW5nLCBmb250cywgd3JhcHBpbmcgdGV4dCwgZGF0ZXMsIHRpbWVzLCBvciBhbnkgb3RoZXIgY2VsbC1zcGVjaWZpYyBmb3JtYXR0aW5nIHdpbGwgaGF2ZSB0byBiZSByZW1vdmVkLiBUaGlzIGNhbiB1bmludGVudGlvbmFsbHkgYWx0ZXIgdGhlIGRhdGEgKGZvciBpbnN0YW5jZSwgZGF0ZXMgbWF5IG5vdCBiZSBwcm9wZXJseSBjb252ZXJ0ZWQgdG8gaW50ZXJwcmV0YWJsZSB0ZXh0IG9yIG51bWJlcnMpLiBNb3Jlb3ZlciwgUiBjYW5ub3QgdGVsbCB5b3UgaWYgaXQgaGFzIG1pc2ludGVycHJldGVkIHNvbWV0aGluZyBmcm9tIGFuIEV4Y2VsIGZpbGUsIHNvIHlvdSB3b3VsZCBoYXZlIHRvIGdvIHRocm91Z2ggdGhlIGZpbGUgYW5kIGNoZWNrIGl0IGFueXdheSB0byBtYWtlIHN1cmUgeW91ciBjb2x1bW5zIGFuZCB2YWx1ZXMgaGF2ZSBiZWVuIGNvcnJlY3RseSBpbXBvcnRlZC4gRmluYWxseSwgYmVjYXVzZSBNaWNyb3NvZnQgRXhjZWwgKGAueGxzeGApIGZpbGVzIGFyZSBhIHByb3ByaWV0YXJ5IGJyYW5kIHRoYXQgY29udGludW91c2x5IHVwZGF0ZXMgYW5kIGNoYW5nZXMgdGhlIHByb2dyYW0gdXNlZCB0byBnZW5lcmF0ZSBzcHJlYWRzaGVldHMsIHRoZXJlIGlzIG5vIGd1YXJhbnRlZSB0aGF0IHlvdXIgb3BlcmF0aW5nIHN5c3RlbSB3aWxsIHVwbG9hZCB0aGUgZmlsZSB0aGUgc2FtZSB3YXkgc29tZW9uZSBlbHNlJ3Mgd2lsbCwgd2hpY2ggbWFrZXMgeW91ciBkYXRhIGxlc3MgcmVwbGljYWJsZS4gVG8gZ2l2ZSB5b3UgYW4gaWRlYSB3aGF0IHRoaXMgbWVhbnMsIGhlcmUgaXMgdGhlICJwbGFpbiB0ZXh0IiB2ZXJzaW9uIG9mIGFuIC54c2x4IHNwcmVhZHNoZWV0IGdlbmVyYXRlZCBieSBNaWNyb3NvZnQgRXhjZWwuCgohW10oLi4vZ3VpL3htbC5wbmcpCgpSYXRoZXIgdGhhbiB3b3JyeWluZyBhYm91dCBhbnkgb2YgdGhpcyBwb3RlbnRpYWwgY29tcGxpY2F0aW9ucywgaXQgaXMgZWFzeSB0byBzYXZlIHlvdXIgLnhsc3ggZmlsZSBhcyBhIC5jc3Ygb3IgcGFzdGUgdGhlIGNvbnRlbnQgaW50byBhIC50eHQgdGFiLWRlbGltaXRlZCBmaWxlLiBJdCB0YWtlcyB2ZXJ5IGxpdHRsZSB0aW1lLCB0aGUgZmlsZSBzaXplIHdpbGwgYmUgc21hbGxlciB0aGFuIGEgLnhsc3ggZmlsZSwgYW5kIHRoZSBkYXRhIGZpbGUgd2lsbCBiZSByZWFkYWJsZSBieSBzb2Z0d2FyZSB3ZWxsIGludG8gdGhlIGZ1dHVyZSwgZXZlbiBhZnRlciBFeGNlbCB1cGRhdGVzIGl0cyBmaWxlIGZvcm1hdHRpbmcgYWdhaW4uCgojIExpdGVyYXRlIHByb2dyYW1taW5nCgpMaXRlcmF0ZSBwcm9ncmFtbWluZyBpcyBhIHVzZWZ1bCB3YXkgdG8gYW5ub3RhdGUgeW91ciBjb2RlIG9yIG5hdmlnYXRlIHNvbWVvbmUgZWxzZSdzIGNvZGUuIEluIHNob3J0LCBpdCBhbGxvd3MgeW91IHRvIHdyaXRlIHByb3NlLCBpbnNlcnQgcGljdHVyZXMsIHZpZXcgb3V0cHV0LCBhbmQgcHJvZHVjZSB0YWJsZXMgd2l0aGluIHlvdXIgY29kZS4gSW4gcGFydGljdWxhciwgKipSIG1hcmtkb3duKiogKGAuUm1kYCkgZmlsZXMgYW5kICoqUiBub3RlYm9va3MqKiBhbGxvdyB5b3UgdG8gd3JpdGUgUiBpbiBhIGxpdGVyYXRlIHByb2dyYW1taW5nIGVudmlyb25tZW50LiBJbiBmYWN0LCB0aGlzIHdlYnBhZ2Ugd2FzIGdlbmVyYXRlZCBhcyBhbiAuUm1kIGZpbGUhCgpUaGlzIHNlY3Rpb24gd2lsbCBicmllZmx5IGRpc2N1c3Mgd2h5IGxpdGVyYXRlIHByb2dyYW1taW5nLCBhbmQgc3BlY2lmaWNhbGx5IC5SbWQgZmlsZXMsIGFyZSB1c2VmdWwgdG8ga25vdyBhYm91dCBhbmQgbGVhcm4gdG8gdXNlLgoKIyMgQW5ub3RhdGlvbgoKKipXaHkgZG8gd2UgYW5ub3RhdGUgY29kZT8qKiAgCgpGdW5kYW1lbnRhbGx5LCBjb2RlIGNhbiBiZSBkaWZmaWN1bHQgdG8gcmVhZC4gV2UgYXJlIG5vdCBjb21wdXRlcnMsIHdlIGZvcmdldCB3aGF0IHdlIHdlcmUgZG9pbmcgb3IgdHJ5aW5nIHRvIGRvLCB3ZSBsb3NlIG91ciBwbGFjZS4gQW5ub3RhdGluZyBjb2RlIGlzIG9uZSB3YXkgdG8gaGVscCB1cyByZW1lbWJlciB3aGF0IG91ciB0aG91Z2ggcHJvY2VzcyB3YXMgYXQgdGhlIHRpbWUgb2Ygd3JpdGluZy4gSXQgYWxzbyBhbGxvd3Mgb3RoZXIgcGVvcGxlIHRvIHVzZSwgYWRhcHQsIGFuZCBkZWJ1ZyBvdXIgY29kZS4gVGhpcyBpbmNyZWFzZXMgcmVwbGljYWJpbGl0eSBhbmQgYWxsb3dzIG1vcmUgb3BlbiwgdHJhbnNwYXJlbnQgc2NpZW5jZSwgdG9vLgoKQXMgbWVudGlvbmVkIGVhcmxpZXIsIHdlIGNhbiBsZWF2ZSBjb21tZW50cyBpbiBvdXIgY29kZSBieSB3cml0aW5nIHRleHQgYWZ0ZXIgYSBgI2Agc3ltYm9sLgoKYGBge3J9CnBhc3RlKCJIZWxsbyIsIndvcmxkISIpICMgdGhlIHBhc3RlKCkgZnVuY3Rpb24gY29ubmVjdHMgdGV4dCB2YWx1ZXMgd2l0aCBvbmUgc3BhY2UuCnBhc3RlMCgiSGVsbG8iLCIgIiwid29ybGQiLCIhIikgIyB0aGUgcGFzdGUwKCkgZnVuY3Rpb24gY29ubmVjdHMgdGV4dCB2YWx1ZXMgd2l0aCBubyBpbnRlcnZlbmluZyBjaGFyYWN0ZXIocykuCmBgYAoKQnV0IGNvbW1lbnRpbmcgY29kZSBtYXkgb25seSBnZXQgeW91IHNvIGZhci4gSXQgY2FuIGJlIGRpZmZpY3VsdCB0byByZWFkLCB0aGVyZSBpcyBubyBmb3JtYXR0aW5nIGluIGNhc2UgeW91IHdhbnQgdG8gbWFrZSBzb21lIHRleHQgYm9sZCBvciBtb3JlIHNhbGllbnQsIGFuZCB5b3UgY2FuIHN0aWxsIGxvc2UgeW91ciBwbGFjZSBpbiBhIGxvbmcgc2NyaXB0LgoKVGhpcyBpcyB3aGVyZSAuUm1kIGZpbGVzIGltcHJvdmUgdXBvbiBjb21tZW50aW5nLgoKIyMgUHJvc2UKCkluIGEgLlJtZCBmaWxlLCB3ZSBjYW4gc3RpbGwgY29tbWVudCBjb2RlIGxpbmUtYnktbGluZSwgYnV0IHdlIGNhbiBhbHNvIGluY2x1ZGUgbG9uZ2VyIChtb3JlIHZpc3VhbGx5IHBsZWFzaW5nKSBleHBsYW5hdGlvbnMgb2Ygd2hhdCB3ZSBhcmUgZG9pbmcgYW5kIHdoYXQgd2UgaW50ZW5kIHRvIGRvLiBUaGlzIG1lYW5zIHlvdSBjYW4gbGVhdmUgeW91cnNlbGYgcmVtaW5kZXJzISBZb3UgY2FuIGFsc28gaW5kaWNhdGUgd2hhdCBkb2Vzbid0IHdvcmsgKHNvIHRoYXQgc29tZW9uZSBlbHNlIG1heSBoZWxwKSwgYW5kIGxlYXZlIG5vdGVzIHRvIHlvdXJzZWxmIG9yIHRvIHlvdXIgYXVkaWVuY2UgYWJvdXQgeW91ciBpbnRlcnByZXRhdGlvbnMgb2YgdGhlIGRhdGEuIE1vc3QgaW1wb3J0YW50bHksIHlvdSBjYW4gdmlldyBvdXRwdXQgc3VjaCBhcyBncmFwaHMgaW4tbGluZSwgd2hpY2ggbWVhbnMgdGhleSBhcmUgc2F2ZWQgYWRqYWNlbnQgdG8gdGhlIGNvZGUgdGhhdCBwcm9kdWNlZCB0aGVtLiBUaGlzIG1ha2VzIGl0ICptdWNoKiBlYXNpZXIgdG8gcmV0dXJuIHRvIGFuIGFuYWx5c2lzIG9yIHNoYXJlIGl0IHdpdGggc29tZW9uZSB3aG8gaXMgbm90IGludGltYXRlbHkgZmFtaWxpYXIgd2l0aCB5b3VyIGRhdGEuCgojIyMgRXhhbXBsZQoKSW4gdGhpcyBncmFwaCwgSSdtIHVzaW5nIHRoZSBhdXRvbWF0aWNhbGx5IGF2YWlsYWJsZSBkYXRhc2V0IGNhbGxlZCBgY2Fyc2AuIFRoZSBgcGxvdCgpYCBmdW5jdGlvbiBpcyBtb2RlcmF0ZWx5IGZsZXhpYmxlLCBzbyBJIGNhbiBqdXN0IHRlbGwgaXQgd2hhdCBjb2x1bW5zIGluIGBjYXJzYCBJIHdhbnQgZm9yIHRoZSB4LWF4aXMgYW5kIHRoZSB5LWF4aXMsIGFuZCBpdCdsbCBnZW5lcmF0ZSBhIGdyYXBoLgoKYGBge3J9CnBsb3QoY2FycyRzcGVlZCxjYXJzJGRpc3QpCmBgYAoKSG93ZXZlciwgdGhpcyBncmFwaCBpcyB1Z2x5IGFuZCBib3JpbmcuIEkgd2FudCB0byBjaGFuZ2UgdGhlIGNvbG91ciBhbmQgc2hhcGUgb2YgdGhlIHBvaW50cyBiZWNhdXNlIEkga25vdyBteSBhdWRpZW5jZSBpcyBhY3R1YWxseSBpbnRlcmVzdGVkIGluIGNlcnRhaW4gcHJvcHRlcnRpZXMgb2YgdGhlIGdyYXBoIGFuZCBJIHdhbnQgdG8gbWFrZSBpdCBhcyBlYXN5IGFzIHBvc3NpYmxlIGZvciB0aGVtIHRvIG5hdmlnYXRlIGl0IHF1aWNrbHkuCgpCZWxvdywgSSd2ZSBnZW5lcmF0ZWQgYSBncmFwaCB0aGF0IHNwbGl0cyB0aGUgZGF0YSBpbnRvIGZvdXIgcXVhZHJhbnRzLiBJIHRyaWVkIG90aGVyIG51bWVyaWNhbCB2YWx1ZXMgZm9yIHRoZSBob3Jpem9udGFsIGFuZCB2ZXJ0aWNhbCBkaXZpc2lvbnMsIGJ1dCByZWR1Y2luZyB0aGUgaG9yaXpvbnRhbCBkaXZpc2lvbiBtZWFudCB0aGUgbG93ZXIgcmlnaHQgKG9yYW5nZSkgcXVhZHJhbnQgYmVjYW1lIHRvbyBzcGFyc2UgYW5kIHNoaWZ0aW5nIHRoZSB2ZXJ0aWNhbCBkaXZpc2lvbiB0byB0aGUgbGVmdCBtZWFudCB0aGUgdXBwZXIgbGVmdCAoYmx1ZSkgcXVhZHJhbnQgYmVjYW1lIHRvbyBzcGFyc2UuIEkgaGF2ZSBub3QgdHJpZWQgaW5jcmVhc2luZyB0aGUgdmVydGljYWwgZGl2aXNpb24sIGJ1dCBJIHN1c3BlY3QgaXQgd291bGQgYWxzbyByZXN1bHQgaW4gdGhlIGxvd2VyIHJpZ2h0IChvcmFuZ2UpIHF1YW5kcmFudCBiZWNvbWluZyB0b28gc3BhcnNlLgoKYGBge3J9CnBsb3QoY2FycyRzcGVlZCxjYXJzJGRpc3QsY29sPSJ3aGl0ZSIpICMgZ2VuZXJhdGUgdGhlIHBsb3QgYmFja2dyb3VuZCBhdCBhbiBhcHByb3ByaWF0ZSBzaXplIGFuZCBzY2FsZQphYmxpbmUoaD00MSxsdHk9ImRvdHRlZCIsY29sPSJncmV5IikgIyBpbmNsdWRlIHRoZSBob3Jpem9udGFsIGxpbmUKYWJsaW5lKHY9MTUuNSxsdHk9ImRvdHRlZCIsY29sPSJncmV5IikgIyBpbmNsdWRlIHRoZSB2ZXJ0aWNhbCBsaW5lCmxpbmVzKGxvd2VzcyhjYXJzKSx0eXBlPSJsIixsd2Q9MikgIyBwbG90IHRoZSBibGFjayB0cmVuZCBsaW5lCnBvaW50cyhjYXJzJHNwZWVkW2NhcnMkc3BlZWQ8MTUuNSZjYXJzJGRpc3Q8NDFdLGNhcnMkZGlzdFtjYXJzJHNwZWVkPDE1LjUmY2FycyRkaXN0PDQxXSxjb2w9InJlZCIsIHBjaD0xNSkgIyBsb3dlciBsZWZ0IHF1YWRyYW50CnBvaW50cyhjYXJzJHNwZWVkW2NhcnMkc3BlZWQ+MTUuNSZjYXJzJGRpc3Q8NDFdLGNhcnMkZGlzdFtjYXJzJHNwZWVkPjE1LjUmY2FycyRkaXN0PDQxXSxjb2w9Im9yYW5nZSIsIHBjaD0xNikgIyBsb3dlciByaWdodCBxdWFkcmFudApwb2ludHMoY2FycyRzcGVlZFtjYXJzJHNwZWVkPjE1LjUmY2FycyRkaXN0PjQxXSxjYXJzJGRpc3RbY2FycyRzcGVlZD4xNS41JmNhcnMkZGlzdD40MV0sY29sPSJncmVlbiIsIHBjaD0xNykgIyB1cHBlciByaWdodCBxdWFkcmFudApwb2ludHMoY2FycyRzcGVlZFtjYXJzJHNwZWVkPDE1LjUmY2FycyRkaXN0PjQxXSxjYXJzJGRpc3RbY2FycyRzcGVlZDwxNS41JmNhcnMkZGlzdD40MV0sY29sPSJibHVlIiwgcGNoPTE4KSAjIHVwcGVyIGxlZnQgcXVhZHJhbnQKYGBgCgpTZWUgaG93IG11Y2ggY2xlYXJlciB0aGlzIGlzPyBUaGVyZSBhcmUgc3RpbGwgZ2FwcyBpbiB0aGUgZXhwbGFuYXRpb24uIEkgaGF2ZW4ndCB0b2xkIHlvdSB3aGF0IGBwY2g9MTVgIG1lYW5zIG9yIHdoYXQgaXQgZG9lcy4gVGhlcmUgaXMgYSBsb3Qgb2YgdGV4dCBhbmQgaXQncyBkaWZmaWN1bHQgdG8gcmVhZC4gVGhlc2UgYXJlIHRoaW5ncyB5b3UgY2FuIGFubm90YXRlIGFuZCBleHBsYWluIHRvIHlvdXJzZWxmIHdoZW4geW91IGZpbmQgYW5kIGFkYXB0IG90aGVyIHBlb3BsZSdzIGNvZGUuIEV2ZW50dWFsbHksIHRoZXknbGwgYmVjb21lIHNlY29uZCBuYXR1cmUsIGFuZCB5b3Ugd29uJ3QgbmVlZCB0byBhbm5vdGF0ZSBldmVyeXRoaW5nLCBidXQgYXQgZmlyc3QsIGl0IGNhbiBiZSBoZWxwZnVsIGlmIHlvdSBleHBlY3QgdG8gZm9yZ2V0IHdoYXQgZXZlcnl0aGluZyBtZWFucyBieSB0aGUgbmV4dCB0aW1lIHlvdSB1c2UgeW91ciBjb2RlLgoKKiBgcGNoYCBpcyB0aGUgcG9pbnQgdHlwZS4gU2VhcmNoICJwY2giIGluIHRoZSBoZWxwIHRhYiBvciB0eXBlIGA/cGNoYCBpbnRvIHRoZSBjb25zb2xlIHRvIGxlYXJuIG1vcmUuCiogYGNvbGAgbGV0cyB5b3UgY2hhbmdlIHRoZSBjb2xvdXIgb2YgdGhlIGxpbmUgb3IgcG9pbnQuIFRoZXJlIGFyZSBbYSBsYXJnZSBudW1iZXIgb2YgcHJlLW5hbWVkIGNvbG91cnNdKGh0dHA6Ly9yZXNlYXJjaC5zdG93ZXJzLm9yZy9tY20vZWZnL1IvQ29sb3IvQ2hhcnQvKS4KKiBgbHR5YCBtZWFucyAibGluZSB0eXBlIi4gVHlwaWNhbCB2YWx1ZXMgYXJlICJkYXNoZWQiLCAiZG90dGVkIiwgb3IgInNvbGlkIi4KKiBgbHdkYCBtZWFucyAibGluZSB3aWR0aCIuIEl0IHRha2VzIGEgbnVtZXJpY2FsIGludGVnZXIgdmFsdWUuCgojIyBSIE5vdGVib29rcwoKQW4gUiBOb3RlYm9vayB3aWxsIGFsbG93IHlvdSB0byBlYXNpbHkgY3JlYXRlIGEgZG9jdW1lbnQgKGUuZy4sIGFuIEhUTUwgZG9jdW1lbnQpIHRoYXQgY2FuIGJlIGNvbXBpbGVkIGZvciBlYXN5IHNoYXJpbmcgb3IgcmVwb3J0aW5nIGFuYWx5c2lzLiBJdCBkaWZmZXJzIHNsaWdodGx5IGZyb20gYSByZWd1bGFyIC5SbWQgZmlsZSwgYnV0IGNhbiBiZSBlYXNpZXIgdG8gbGVhcm4gdG8gdXNlIGFuZCB1cGRhdGUuCgpDcmVhdGUgYSBuZXcgUiBOb3RlYm9vayBieSBjbGlja2luZyB0aGUgZ3JlZW4gYCtgIGluIHRoZSB1cHBlciBsZWZ0IGNvcm5lciBhbmQgc2VsZWN0aW5nICJSIE5vdGVib29rIi4gSXQgd2lsbCBhdXRvbWF0aWNhbGx5IGdpdmUgeW91IGEgbGl0dGxlIGluZm9ybWF0aW9uIGFib3V0IGhvdyB0byB3cml0ZSwgcnVuLCBhbmQgY29tcGlsZSB0aGUgZG9jdW1lbnQuIE1ha2Ugc3VyZSB0byBzYXZlIGl0IHdpdGggYSBzaG9ydCwgZGVzY3JpcHRpdmUgbmFtZSEKCkhlcmUgYXJlIGxpbmtzIHRoYXQgY29udGFpbiBnb29kIGNoZWF0IHNoZWV0cyBhbmQgdGlwcyBmb3IgZm9ybWF0dGluZyBhbiBSIE5vdGVib29rOiAgCgoqIFtPZmZpY2lhbCBSU3R1ZGlvIGRvY3VtZW50YXRpb24gYW5kIGd1aWRlXShodHRwczovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbS9yX25vdGVib29rcykgIAoqIFtPZmZpY2lhbCBSU3R1ZGlvIGNoZWF0IHNoZWV0XShodHRwczovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbS9sZXNzb24tMTUuaHRtbCkgIAoqIFtNb3JlIGRldGFpbGVkIGV4cGxhbmF0aW9uIG9mIGhvdyB0byB1c2UgUiBOb3RlYm9va3MgYW5kIFJtZCBmaWxlc10oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duL25vdGVib29rLmh0bWwpCgojIyMgT3JnYW5pc2luZyBjb2RlCgpXaGVuIHlvdSB3cml0ZSB5b3VyIGNvZGUsIGl0IHNob3VsZCBiZSBrZXB0IG1vc3RseSBjaHJvbm9sb2dpY2FsLiBUaGlzIHdheSwgdGhlIHN0ZXBzIHlvdSB0YWtlIGFyZSBpbiB0aGUgY29ycmVjdCBvcmRlci4KCkhvd2V2ZXIsIHRoZXJlIGFyZSBzb21lIGNpcmN1bXN0YW5jZXMgd2hlcmUgaXQgbWFrZXMgbW9yZSBzZW5zZSB0byBnbyBiYWNrIGFuZCBhZGQgY29kZSBpbiB0aGUgbWlkZGxlIHJhdGhlciB0aGFuIGF0IHRoZSBlbmQgb2YgYSBkb2N1bWVudC4gSWYgeW91IHJlLWRvIGEgc3RhdGlzdGljYWwgYW5hbHlzaXMgb3Igd2FudCB0byBjb21wYXJlIHR3byBtZXRob2RzLCB0aG9zZSBtYXkgYmUgbW9yZSBjb2hlcmVudCBpZiBwbGFjZWQgYWRqYWNlbnQgaW4gdGhlIGRvY3VtZW50IHJhdGhlciB0aGFuIGluIHRoZSBvcmRlciB5b3UgcGVyZm9ybWVkIHRoZW0uIFRoaXMgaXMgZXNwZWNpYWxseSB0aGUgY2FzZSBpZiB5b3UgbGVhcm4gYSBuZXcgdGVjaG5pcXVlIGFuZCB3YW50IHRvIGdvIGJhY2sgYW5kIHJlLWRvIGFuIG9sZGVyIGFuYWx5c2lzLiBUaGUgc2FtZSB0aGluZyBnb2VzIGZvciBncmFwaHMgYW5kIG90aGVyIG91dHB1dHMuCgpJZiB5b3UgYXJlIHdvcmtpbmcgZGlyZWN0bHkgaW4gYW4gUiBzY3JpcHQgKHdoaWNoIEkgZG8gbm90IHJlY29tbWVuZCBpZiB5b3UgY2FuIHVzZSBhbiAuUm1kIG9yIG5vdGVib29rIGluc3RlYWQpLCB5b3UgY2FuIGNyZWF0ZSBzZWN0aW9uIGhlYWRpbmdzLiBUbyBkbyBzbywgeW91IGNhbiB0eXBlIGAjIyMjIFNlY3Rpb24gVGl0bGUgIyMjI2Agd2l0aCBhdCBsZWFzdCBmb3VyIGhhc2hlcyBvbiBlaXRoZXIgc2lkZSBvZiB0aGUgdGV4dCwgYW5kIHRoZW4geW91IHdpbGwgYmUgYWJsZSB0byBuYXZpZ2F0ZSBkaXJlY3RseSB0byB0aGF0IGhlYWRpbmcgdXNpbmcgdGhlIHNtYWxsIG9yYW5nZSBoYXNoIHN5bWJvbCBpbiB0aGUgbG93ZXIgbGVmdCBjb3JuZXIgb2YgdGhlIHNjcmlwdHMgcGFuZS4KCkFuIFIgTm90ZWJvb2sgYWxzbyBhbGxvd3MgeW91IHRvIGNyZWF0ZSBzZWN0aW9uIGhlYWRpbmdzIGFuZCBuYXZpZ2F0ZSBiZXR3ZWVuIHRoZW0gaW4gYSBzaW1pbGFyIHdheSwgYnV0IHdoZW4geW91IGNvbXBpbGUgYW5kIHNhdmUgdGhlIGRvY3VtZW50LCB0aGUgc2VjdGlvbiBoZWFkaW5ncyBhcmUgYWxzbyB2aXN1YWxseSBzYWxpZW50LgoKYGBgCiMgSGVhZGluZyAxCiMjIEhlYWRpbmcgMgojIyMgSGVhZGluZyAzCiMjIyMgSGVhZGluZyA0CmBgYAoKRnVydGhlcm1vcmUsIHRoZXJlIGFyZSBvcHRpb25zIGZvciBjcmVhdGluZyBhIHRhYmxlIG9mIGNvbnRlbnRzIGZvciB5b3VyIG5vdGVib29rLCB3aGljaCBtYWtlcyBpdCBldmVuIGVhc2llci4gSGVyZSBpcyBhbiBleGFtcGxlIG9mIHdoYXQgeW91IG1pZ2h0IHB1dCBpbiB0aGUgZG9jdW1lbnQgaGVhZGVyIHRvIGNyZWF0ZSBhIG5pY2UsIHNpbXBsZSB0YWJsZSBvZiBjb250ZW50cyBmb3IgeW91ciBub3RlYm9vay4KCmBgYAotLS0KdGl0bGU6ICJVbnRpdGxlZCBSIE5vdGVib29rIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQotLS0KYGBgCgojIyMgU2hhcmluZyBjb2RlCgpUbyBzaGFyZSB5b3VyIGNvZGUsIHlvdSBjYW4gdXBsb2FkIHRoZSAuUm1kIG9yIC5SIHNjcmlwdChzKSB0aGF0IHlvdSB1c2VkIHRvIGRvIHlvdXIgcHJvY2Vzc2luZyBhbmQgYW5hbHlzaXMgdG8gYW55IG9wZW4gc2NpZW5jZSBzaXRlLiBUaGVzZSBpbmNsdWRlIFtPcGVuIFNjaWVuY2UgRnJhbWV3b3JrXShodHRwczovL29zZi5pby8pIChPU0YpLCBbR2l0SHViXShodHRwczovL2dpdGh1Yi5jb20vKSwgb3IgeW91ciBvd24gcGVyc29uYWwgd2Vic2l0ZS4gU2luY2UgZWFjaCBmaWxlIGNhbiBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlIGFuIEhUTUwgZmlsZSwgeW91IGNhbiBlaXRoZXIgY29weSBhbmQgcGFzdGUgdGhlIGNvbnRlbnRzIG9yIHVwbG9hZCB0aGUgSFRNTCBmaWxlIGRpcmVjdGx5IGZvciBvdGhlcnMgdG8gcmVhZCB5b3VyIHJlcG9ydCB3aXRob3V0IG5lY2Vzc2FyaWx5IGtub3dpbmcgYW55IFIgb3IgbmVlZGluZyB0byBkb3dubG9hZCBhbnkgZmlsZXMuCg==