R Markdown
R Markdown is a tool for literate programming. Literate programming is a paradigm where execuatable code blocks are mixed with an explanation of how the code works. Although it’s possible to achieve some degree of literate programming by just including comments in your code, tools like R Markdown and Jupyter notebooks allow programmers to include richer content (like images and clickable hyperlinks) in their explanatory content.
Viewing R Markdown in RStudio
This document is itself an R Markdown Notebook. To download it, go to this page.

Right click on the Raw
button and select Save link as ...
. Save the notebook somewhere where you can find it. In R Studio, click the Open button or select the Open File
option from the File
menu. Navigate to the place where you saved the file and open it.
When you load the notebook into the editor pane of RStudio, you see the Markdown document markup, which isn’t that easy to read. However, you can render the Markdown in a viewer pane.
Drop down the little gear icon to the right of the Preview
button and select Preview in Viewer Pant
. If necessary, click the Preview
button. You should see the pretty version of the text in the Viewer pane at the right.

When viewing an R Markdown notebook, the editor pane and Viewer pane are expanded to make them easier to see and the Environment and Console panes are collapsed. If you want to expand them to see what’s going on there, click on the expand icon at the right of their header.
Running code in an R Markdown notebook
To execute a code chunk, click on the Run
button (triangle) at the right of the chunk, or place the cursor in the chunk and hold Command
+Shift
then press Return
on Mac or hold Ctrl
+Shift
then press Enter
on Windows. To execute a single line, place the cursor on the line and press Command
Return
(Ctrl
Enter
) without pressing the Shift
key.
When you execute code within the notebook, the results appear beneath the code. Try executing this example.
animal <- c("frog", "spider", "worm", "bee")
animal[1]
If configured correctly, R Markdown can also execute chunks of Python code:
string = 'hey dude!'
print(string)
and console commands:
ls *.Rmd
The type of command is indicated after the triple backticks above the code block.
Separate chunks of R code “remember”" what’s in the environment from the execution of a previous chunk. If I’ve previously run the chunk above that assigns values to animal
, I can recall a value when I run this chunk:
animal[3]
You can edit the code in a chunk and re-run it to see the effect of your changes. (If you are used to Jupyter notebooks, this behavior is similar to the behavior of code cells in a notebook.)
To clear the output of one or all chunks, go to the Edit
menu and select Clear Output
or Clear All Output
.
To add a new chunk, click the Insert
button on the toolbar and select R
.
To refresh the preview of the code in the Viewer pane, click the Preview
button again.
R data structures
R has a number of data structures that vary by the kinds of things that can be stored in them and their dimensionality (1 dimensional, 2 dimensional, etc.). We’ll learn about four: vectors, lists, data frames, and tibbles.
Vectors
A vector is a one-dimensional data structure consisting of items of the same mode. In R, all data structures are “one based” (counting starts with one) as opposed to “zero-based” languages like Python.
Here’s how to assign values to a vector using the “construct” function:
animal <- c("frog", "spider", "worm", "bee")
Expand the Environment pane so that you can see the values in the vector. Note: in R, it is conventional to use double quotes to define string literals, although single quotes are allowed.
You can also create a vector of numbers:
myNumbers <- c(1, 3, 6, 10, 15)
When you create a sequence using the colon notation, the result is a vector that is the same as if you used the construct function:
firstVector <- 1:5
secondVector <- c(1:5)
firstVector
secondVector
To find the number of items in a vector, use the length()
function:
length(animal)
To append another item to a vector, include the previous vector in the construct function:
animal <- c(animal,"monkey")
animal
length(animal)
To replace a particular item, reference it by its index:
animal[2] <- "arachnid"
You can refer to part of a vector using a subvector reference like this:
animal[2:4]
The items in the vector that you are extracting are specified by the sequence you put in the square brackets. (Aside for Python users: unlike Python slices, the last number in the sequence is included in the subvector. Also remember that that the first item in the vector is 1, not 0 as in Python.)
You can explicitly construct the sequence of items by listing the item numbers. You can also assign the sequence to a variable and specifiy the items to be extracted with it.
animal[c(4, 1, 3)]
indexSequence <- 4:1
animal[indexSequence]
One somewhat surprising thing about R is that individual items are actually vectors with lengths of one. The result is the same whether the item is assigned directly to a variable or assigned by the construct function.
thingOne <- c("thing")
thingTwo <- "thing"
thingOne
thingOne[1]
thingTwo
thingTwo[1]
length(thingOne)
length(thingOne[1])
length(thingTwo)
R has two built-in values to indicate that something is wrong: NA
and NULL
.
NA
is used for missing values. It is an indicator that a value is missing and it can be assigned to a vector as a value. It has a length of one and you can think of it as a sort of empty item.
animal[2] <- NA
animal
NULL
is used to indicate that there is no value. It can’t be assigned to a vector as a value. It has a length of zero and and you can think of it as the case of an item that isn’t there.
animal[3] <- NULL
animal
Lists
A list is also a one-dimensional data structure, like a vector. However, the items in a list can be heterogeneous (different modes of items). In the example above, the list contains two character strings, one number, and one vector.
Assuming that the animal
vector is in your environment, the following command will create the list diagrammed above:
thing <- list(fruitKind="apple", euler=2.71828, vectorData=animal, curse="!@#$%")
Notice that in this list I’ve assigned the items to the list by name. (It is also possbile to assign names to vector items but that is less common.)
Because the list is complicated, the items composing it are not shown in the Environment pane. To see all of the list’s parts, I can either click on the thing
entry in the Environment pane, or issue the command:
View(thing)
When I view the list, the description opens as a new tabl in the same pane as the editor.
Items in a list can viewed by either their position or their name. In contrast to vectors, the index is put in double square brackets.
thing[[3]]
thing[["euler"]]
A commonly used shorthand method for referring to list items by their names is by separating the list from the name by a dollar sign:
thing$euler
thing$vectorData
Factors
A factor is a data structure for categorizing data. Its origin comes from experimental design terminology. In an experiment, each category into which an experimental trial can fall is called a level. A factor consists of all of the possible levels that are used to group trials based on that factor. Here is an example of an experiment where plants were grown in wet or dry soil:
wet |
25 |
wet |
21 |
dry |
14 |
wet |
13 |
dry |
10 |
wet |
18 |
We can create a vector containing all of the water conditions and another vector containing the heights:
waterConditions <- c("wet", "wet", "dry", "wet", "dry", "wet")
height <- c(25, 21, 14, 13, 10, 18)
waterConditions
height
To convert the weatherConditions
vector into a factor, use the factor()
function:
waterFactor <- factor(waterConditions)
waterFactor
When we run the code chunk above, we can see two ways that waterFactor
is different from waterConditions
:
- the
waterFactor
items are not in quotation marks
- below the list of items is a summary of the levels, showing that there are only two different categories into which the experimental trials can be grouped.
We can also see by looking at the Environment pane that waterConditions
is identified as a vector of character strings, while waterFactor
is identified as a Factor with two levels.
Factors are stored and processed more efficiently than characters and play a special role as grouping variables in statistical tests that require the data to be placed into categorical groups.
Data frames
Data frames are two dimensional data structures and are one of the most widely used data types in R. One can think of a data frame as a table with rows and columns, with the top row containing column headers that are names describing what’s in the columns.
It is helpful to think of a data frame as a sort of combination of lists and vectors. The values in a particular column are like a vector, with the column header for that column containing the vector’s name. The set of columns is like a list whose items are vectors.
We can actually create a data frame by first constructing a vector for each column:
group <- c("reptile", "arachnid", "annelid", "insect") # vector of strings
animal <- c("frog", "spider", "worm", "bee")
numberLegs <- c(4,8,0,6) # vector of numbers
then loading the vectors into the data frame:
organismInfo <- data.frame(group, animal, numberLegs)
organismInfo
By default, R will use the name of each vector as the name for the column in the data frame. Expand the Environment pane to see what happened when you created the vectors and data frame, and click on the data frame listing to see its structure.
We can refer to a particular cell in the table by listing its row followed by its column in brackets, like this:
organismInfo[2,1]
Because the columns of a data frame behave somewhat like list items, the notation for referring to list items by name (dollar sign followed by name) can also be used to refer to columns in a data frame:
organismInfo$animal
and items in that column can be referred to by their position from the top of the column:
organismInfo$animal[4]
One thing that you may have noticed is that when we list values in the data frame that came from the vector of character strings, they are not in quotes and have levels listed below them. This is because when character data vectors are loaded into a data frame, they are automatically converted to factors. We can see this by asking about the class of the objects we have been working with:
class(organismInfo)
class(organismInfo$animal)
class(organismInfo$numberLegs)
We can also see that the values of the factor are actually not stored as strings, but as numbers:
organismInfo[2,1]
class(organismInfo[2,1])
mode(organismInfo[2,1])
By storing the factors as numbers, they can be ordered. The order of the factors is important in some analyses.
Tibbles
More recently, the use of R has expanded far beyond statistics, so automatically trasforming character data into a form that is optimal for statistics (i.e. factors) is no longer necessarily desirable in every case. Another two-dimensional data structure, called a tibble, was developed to broaden the use of data frames. When data are read into a tibble, there is never a conversion of data types (strings remain strings).
Tibbles are not part of the standard R distribution, so to use them you need to load a library called tidyverse
. You can create a tibble using the tibble()
function:
library(tidyverse)
organismTibble <- tibble(group, animal, numberLegs)
organismTibble
If you compare the output of the organismTibble
tibble with the output of the organismInfo
data frame, the column type listed below the column header is chr
for the tibble and fctr
for the data frame. So we can see that when the vectors were loaded into the tibble, their class was NOT changed.
class(organismTibble)
class(organismTibble$animal)
class(organismTibble$numberLegs)
The class of the tibble is listed as both tbl
(tibble) and data.frame
(data frame) because a tibble is considered a special kind of data frame. You can also see that the animal column remained characters and was not converted to a factor as was the case when we created the data frame.
Applying functions
A function is like a machine that transforms what we put into it into something different that comes out. We pass arguments into the function and the function returns values.
There are many built-in functions in R. For example, I can take the square root of a number by passing it into the sqrt()
function.
x <- 2
sqrt(x)
In this case, I passed a single numeric value into the function and got out a single value. However, recall that in R a variable containing a single value is the same as a vector with a length of one. What that means is that for many functions, I can pass in a vector containing many items and the function will be applied to every item in the vector. The output returned from the function is also a vector whose items are in the same order as the input vector.
sqrt(organismInfo$numberLegs)
Other functions may expect a vector input, but output only a single number. The mean()
function takes the average of the items in a vector and returns a single value.
mean(organismInfo$numberLegs)
R differs from some other languages like Python in that it can automatically perform functions on an entire vector of values without requiring that the code iterate through each item in the vector.
Here is another example using the nchar()
function that counts the number of characters in a string:
# list the words in the animal column
organismTibble$animal
# list the count of characters in each word in the column
nchar(organismTibble$animal)
LS0tDQp0aXRsZTogIkxlc3NvbiAyOiBEYXRhIHN0cnVjdHVyZXMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIFIgTWFya2Rvd24NCg0KKlIgTWFya2Rvd24qIGlzIGEgdG9vbCBmb3IgKmxpdGVyYXRlIHByb2dyYW1taW5nKi4gTGl0ZXJhdGUgcHJvZ3JhbW1pbmcgaXMgYSBwYXJhZGlnbSB3aGVyZSBleGVjdWF0YWJsZSBjb2RlIGJsb2NrcyBhcmUgbWl4ZWQgd2l0aCBhbiBleHBsYW5hdGlvbiBvZiBob3cgdGhlIGNvZGUgd29ya3MuICBBbHRob3VnaCBpdCdzIHBvc3NpYmxlIHRvIGFjaGlldmUgc29tZSBkZWdyZWUgb2YgbGl0ZXJhdGUgcHJvZ3JhbW1pbmcgYnkganVzdCBpbmNsdWRpbmcgY29tbWVudHMgaW4geW91ciBjb2RlLCB0b29scyBsaWtlIFIgTWFya2Rvd24gYW5kIEp1cHl0ZXIgbm90ZWJvb2tzIGFsbG93IHByb2dyYW1tZXJzIHRvIGluY2x1ZGUgcmljaGVyIGNvbnRlbnQgKGxpa2UgaW1hZ2VzIGFuZCBjbGlja2FibGUgaHlwZXJsaW5rcykgaW4gdGhlaXIgZXhwbGFuYXRvcnkgY29udGVudC4gIA0KDQojIyBWaWV3aW5nIFIgTWFya2Rvd24gaW4gUlN0dWRpbw0KDQpUaGlzIGRvY3VtZW50IGlzIGl0c2VsZiBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFRvIGRvd25sb2FkIGl0LCBnbyB0byBbdGhpcyBwYWdlXShodHRwczovL2dpdGh1Yi5jb20vSGVhcmRMaWJyYXJ5L2RpZ2l0YWwtc2Nob2xhcnNoaXAvYmxvYi9tYXN0ZXIvY29kZS9yL2xlc3NvbjIuUm1kKS4NCg0KIVtdKGh0dHBzOi8vZ2l0aHViLmNvbS9IZWFyZExpYnJhcnkvZGlnaXRhbC1zY2hvbGFyc2hpcC9yYXcvZ2gtcGFnZXMvc2NyaXB0L3IvaW1hZ2VzL3ItbWFya2Rvd24tbm90ZWJvb2stZG93bmxvYWQucG5nKSANCg0KUmlnaHQgY2xpY2sgb24gdGhlIGBSYXdgIGJ1dHRvbiBhbmQgc2VsZWN0IGBTYXZlIGxpbmsgYXMgLi4uYC4gU2F2ZSB0aGUgbm90ZWJvb2sgc29tZXdoZXJlIHdoZXJlIHlvdSBjYW4gZmluZCBpdC4gIEluIFIgU3R1ZGlvLCBjbGljayB0aGUgT3BlbiBidXR0b24gb3Igc2VsZWN0IHRoZSBgT3BlbiBGaWxlYCBvcHRpb24gZnJvbSB0aGUgYEZpbGVgIG1lbnUuIE5hdmlnYXRlIHRvIHRoZSBwbGFjZSB3aGVyZSB5b3Ugc2F2ZWQgdGhlIGZpbGUgYW5kIG9wZW4gaXQuDQoNCldoZW4geW91IGxvYWQgdGhlIG5vdGVib29rIGludG8gdGhlIGVkaXRvciBwYW5lIG9mIFJTdHVkaW8sIHlvdSBzZWUgdGhlIE1hcmtkb3duIGRvY3VtZW50IG1hcmt1cCwgd2hpY2ggaXNuJ3QgdGhhdCBlYXN5IHRvIHJlYWQuICBIb3dldmVyLCB5b3UgY2FuIHJlbmRlciB0aGUgTWFya2Rvd24gaW4gYSB2aWV3ZXIgcGFuZS4gIA0KDQohW1NlbGVjdGluZyBQcmV2aWV3IGluIFZpZXdlciBQYW5lXShodHRwczovL2dpdGh1Yi5jb20vSGVhcmRMaWJyYXJ5L2RpZ2l0YWwtc2Nob2xhcnNoaXAvcmF3L2doLXBhZ2VzL3NjcmlwdC9yL2ltYWdlcy9wcmV2aWV3LWluLXZpZXdlci5wbmcpIA0KDQpEcm9wIGRvd24gdGhlIGxpdHRsZSBnZWFyIGljb24gdG8gdGhlIHJpZ2h0IG9mIHRoZSBgUHJldmlld2AgYnV0dG9uIGFuZCBzZWxlY3QgYFByZXZpZXcgaW4gVmlld2VyIFBhbnRgLiAgSWYgbmVjZXNzYXJ5LCBjbGljayB0aGUgYFByZXZpZXdgIGJ1dHRvbi4gIFlvdSBzaG91bGQgc2VlIHRoZSBwcmV0dHkgdmVyc2lvbiBvZiB0aGUgdGV4dCBpbiB0aGUgVmlld2VyIHBhbmUgYXQgdGhlIHJpZ2h0LiAgDQoNCjxpbWcgc3JjPSJodHRwczovL2dpdGh1Yi5jb20vSGVhcmRMaWJyYXJ5L2RpZ2l0YWwtc2Nob2xhcnNoaXAvcmF3L2doLXBhZ2VzL3NjcmlwdC9yL2ltYWdlcy9jbGljay10by1leHBhbmQucG5nIiBzdHlsZT0iYm9yZGVyOjFweCBzb2xpZCBibGFjayIgLz4NCg0KV2hlbiB2aWV3aW5nIGFuIFIgTWFya2Rvd24gbm90ZWJvb2ssIHRoZSBlZGl0b3IgcGFuZSBhbmQgVmlld2VyIHBhbmUgYXJlIGV4cGFuZGVkIHRvIG1ha2UgdGhlbSBlYXNpZXIgdG8gc2VlIGFuZCB0aGUgRW52aXJvbm1lbnQgYW5kIENvbnNvbGUgcGFuZXMgYXJlIGNvbGxhcHNlZC4gIElmIHlvdSB3YW50IHRvIGV4cGFuZCB0aGVtIHRvIHNlZSB3aGF0J3MgZ29pbmcgb24gdGhlcmUsIGNsaWNrIG9uIHRoZSBleHBhbmQgaWNvbiBhdCB0aGUgcmlnaHQgb2YgdGhlaXIgaGVhZGVyLg0KDQojIyBSdW5uaW5nIGNvZGUgaW4gYW4gUiBNYXJrZG93biBub3RlYm9vaw0KDQpUbyBleGVjdXRlIGEgY29kZSBjaHVuaywgY2xpY2sgb24gdGhlIGBSdW5gIGJ1dHRvbiAodHJpYW5nbGUpIGF0IHRoZSByaWdodCBvZiB0aGUgY2h1bmssIG9yIHBsYWNlIHRoZSBjdXJzb3IgaW4gdGhlIGNodW5rIGFuZCBob2xkIGBDb21tYW5kYCtgU2hpZnRgIHRoZW4gcHJlc3MgYFJldHVybmAgb24gTWFjIG9yIGhvbGQgYEN0cmxgK2BTaGlmdGAgdGhlbiBwcmVzcyBgRW50ZXJgIG9uIFdpbmRvd3MuICBUbyBleGVjdXRlIGEgc2luZ2xlIGxpbmUsIHBsYWNlIHRoZSBjdXJzb3Igb24gdGhlIGxpbmUgYW5kIHByZXNzIGBDb21tYW5kYCBgUmV0dXJuYCAoYEN0cmxgIGBFbnRlcmApIHdpdGhvdXQgcHJlc3NpbmcgdGhlIGBTaGlmdGAga2V5LiAgDQoNCldoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gVHJ5IGV4ZWN1dGluZyB0aGlzIGV4YW1wbGUuDQoNCmBgYHtyfQ0KYW5pbWFsIDwtIGMoImZyb2ciLCAic3BpZGVyIiwgIndvcm0iLCAiYmVlIikNCmFuaW1hbFsxXQ0KYGBgDQoNCklmIGNvbmZpZ3VyZWQgY29ycmVjdGx5LCBSIE1hcmtkb3duIGNhbiBhbHNvIGV4ZWN1dGUgY2h1bmtzIG9mIFB5dGhvbiBjb2RlOg0KDQpgYGB7cHl0aG9ufQ0Kc3RyaW5nID0gJ2hleSBkdWRlIScNCnByaW50KHN0cmluZykNCmBgYA0KDQphbmQgY29uc29sZSBjb21tYW5kczoNCg0KYGBge2Jhc2h9DQpscyAqLlJtZA0KYGBgDQoNClRoZSB0eXBlIG9mIGNvbW1hbmQgaXMgaW5kaWNhdGVkIGFmdGVyIHRoZSB0cmlwbGUgYmFja3RpY2tzIGFib3ZlIHRoZSBjb2RlIGJsb2NrLiAgDQoNClNlcGFyYXRlIGNodW5rcyBvZiBSIGNvZGUgInJlbWVtYmVyIiIgd2hhdCdzIGluIHRoZSBlbnZpcm9ubWVudCBmcm9tIHRoZSBleGVjdXRpb24gb2YgYSBwcmV2aW91cyBjaHVuay4gIElmIEkndmUgcHJldmlvdXNseSBydW4gdGhlIGNodW5rIGFib3ZlIHRoYXQgYXNzaWducyB2YWx1ZXMgdG8gYGFuaW1hbGAsIEkgY2FuIHJlY2FsbCBhIHZhbHVlIHdoZW4gSSBydW4gdGhpcyBjaHVuazoNCg0KYGBge3J9DQphbmltYWxbM10NCmBgYA0KDQpZb3UgY2FuIGVkaXQgdGhlIGNvZGUgaW4gYSBjaHVuayBhbmQgcmUtcnVuIGl0IHRvIHNlZSB0aGUgZWZmZWN0IG9mIHlvdXIgY2hhbmdlcy4gKElmIHlvdSBhcmUgdXNlZCB0byBKdXB5dGVyIG5vdGVib29rcywgdGhpcyBiZWhhdmlvciBpcyBzaW1pbGFyIHRvIHRoZSBiZWhhdmlvciBvZiBjb2RlIGNlbGxzIGluIGEgbm90ZWJvb2suKQ0KDQpUbyBjbGVhciB0aGUgb3V0cHV0IG9mIG9uZSBvciBhbGwgY2h1bmtzLCBnbyB0byB0aGUgYEVkaXRgIG1lbnUgYW5kIHNlbGVjdCBgQ2xlYXIgT3V0cHV0YCBvciBgQ2xlYXIgQWxsIE91dHB1dGAuDQoNClRvIGFkZCBhIG5ldyBjaHVuaywgY2xpY2sgdGhlIGBJbnNlcnRgIGJ1dHRvbiBvbiB0aGUgdG9vbGJhciBhbmQgc2VsZWN0IGBSYC4NCg0KVG8gcmVmcmVzaCB0aGUgcHJldmlldyBvZiB0aGUgY29kZSBpbiB0aGUgVmlld2VyIHBhbmUsIGNsaWNrIHRoZSBgUHJldmlld2AgYnV0dG9uIGFnYWluLg0KDQojIFIgZGF0YSBiYXNpY3MNCg0KIyMgQ2F0ZWdvcml6aW5nIG9iamVjdHMgaW4gUg0KDQpUaGVyZSBhcmUgdHdvIG1haW4gd2F5cyBvZiBjYXRlZ29yaXppbmcgb2JqZWN0cyBpbiBSLiAgT2JoZWN0cyBjYW4gYmUgY2F0ZWdvcml6ZWQgYnkgdGhlaXIgbW9kZSwgd2hpY2ggcmVwcmVzZW50cyBob3cgdGhleSBhcmUgc3RvcmVkLiAgQ29tbW9uIG1vZGVzIGFyZTogbnVtZXJpYywgY2hhcmFjdGVyLCBsaXN0LCBhbmQgZnVuY3Rpb25zLiBXZSBjYW4gZmluZCB0aGUgbW9kZSBvZiBhbiBvYmplY3QgdXNpbmcgdGhlIGBtb2RlKClgIGZ1bmN0aW9uOg0KDQpgYGB7cn0NCnBldCA8LSAicm92ZXIiDQpwaWUgPC0gMy4xNDE1OQ0KYW5pbWFsIDwtIGMoImZyb2ciLCAic3BpZGVyIiwgIndvcm0iLCAiYmVlIikNCm1vZGUocGV0KQ0KbW9kZShwaWUpDQptb2RlKGFuaW1hbCkNCmBgYA0KDQpPYmplY3RzIGNhbiBhbHNvIGJlIGNoYXJhY3Rlcml6ZWQgYnkgdGhlaXIgY2xhc3MsIHdoaWNoIGRldGVybWluZXMgaG93IFIgd2lsbCBwcm9jZXNzIHRob3NlIG9iamVjdHMuICANCg0KIyMgU2VxdWVuY2VzDQoNCllvdSBjYW4gZ2VuZXJhdGUgYSBzZXF1ZW5jZSBvZiBudW1iZXJzIGxpa2UgdGhpczoNCg0KYGBge3J9DQoxOjUNCmBgYA0KDQpVc2luZyB0aGlzIHNpbXBsZSBub3RhdGlvbiB0aGUgc2VxdWVuY2Ugc3RlcHMgYnkgb25lcy4gIFlvdSBjYW4gaGF2ZSB0aGUgc2VxdWVuY2UgY291bnQgZG93biBieSBwdXR0aW5nIHRoZSBsYXJnZXIgbnVtYmVyIGluIGZyb250IG9mIHRoZSBjb2xvbjoNCg0KYGBge3J9DQoxMDotMg0KYGBgDQoNCklmIHlvdSBhcmUgdXNlZCB0byBQeXRob24sIHlvdSBzaG91bGQgbm90aWNlIHRoYXQgdGhlIHNlcXVlbmNlIGRvZXMgbm90IGVuZCBhdCBvbmUgdmFsdWUgYmVmb3JlIHRoZSBmaW5hbCBudW1iZXIgYXMgaXQgZG9lcyBpbiBQeXRob24gcmFuZ2VzLg0KDQojIFIgZGF0YSBzdHJ1Y3R1cmVzDQoNClIgaGFzIGEgbnVtYmVyIG9mIGRhdGEgc3RydWN0dXJlcyB0aGF0IHZhcnkgYnkgdGhlIGtpbmRzIG9mIHRoaW5ncyB0aGF0IGNhbiBiZSBzdG9yZWQgaW4gdGhlbSBhbmQgdGhlaXIgZGltZW5zaW9uYWxpdHkgKDEgZGltZW5zaW9uYWwsIDIgZGltZW5zaW9uYWwsIGV0Yy4pLiAgV2UnbGwgbGVhcm4gYWJvdXQgZm91cjogdmVjdG9ycywgbGlzdHMsIGRhdGEgZnJhbWVzLCBhbmQgdGliYmxlcy4NCg0KIyMgVmVjdG9ycw0KDQohW0RpYWdyYW0gb2YgYSB2ZWN0b3JdKGh0dHBzOi8vaGVhcmRsaWJyYXJ5LmdpdGh1Yi5pby9kaWdpdGFsLXNjaG9sYXJzaGlwL3NjcmlwdC9yL2ltYWdlcy92ZWN0b3ItZGlhZ3JhbS5wbmcpDQoNCkEgKnZlY3RvciogaXMgYSBvbmUtZGltZW5zaW9uYWwgZGF0YSBzdHJ1Y3R1cmUgY29uc2lzdGluZyBvZiBpdGVtcyBvZiB0aGUgc2FtZSBtb2RlLiAgSW4gUiwgYWxsIGRhdGEgc3RydWN0dXJlcyBhcmUgIm9uZSBiYXNlZCIgKGNvdW50aW5nIHN0YXJ0cyB3aXRoIG9uZSkgYXMgb3Bwb3NlZCB0byAiemVyby1iYXNlZCIgbGFuZ3VhZ2VzIGxpa2UgUHl0aG9uLg0KDQpIZXJlJ3MgaG93IHRvIGFzc2lnbiB2YWx1ZXMgdG8gYSB2ZWN0b3IgdXNpbmcgdGhlICJjb25zdHJ1Y3QiIGZ1bmN0aW9uOg0KDQpgYGB7cn0NCmFuaW1hbCA8LSBjKCJmcm9nIiwgInNwaWRlciIsICJ3b3JtIiwgImJlZSIpDQpgYGANCg0KRXhwYW5kIHRoZSBFbnZpcm9ubWVudCBwYW5lIHNvIHRoYXQgeW91IGNhbiBzZWUgdGhlIHZhbHVlcyBpbiB0aGUgdmVjdG9yLiAgTm90ZTogaW4gUiwgaXQgaXMgY29udmVudGlvbmFsIHRvIHVzZSBkb3VibGUgcXVvdGVzIHRvIGRlZmluZSBzdHJpbmcgbGl0ZXJhbHMsIGFsdGhvdWdoIHNpbmdsZSBxdW90ZXMgYXJlIGFsbG93ZWQuIA0KDQpZb3UgY2FuIGFsc28gY3JlYXRlIGEgdmVjdG9yIG9mIG51bWJlcnM6DQoNCmBgYHtyfQ0KbXlOdW1iZXJzIDwtIGMoMSwgMywgNiwgMTAsIDE1KQ0KYGBgDQoNCldoZW4geW91IGNyZWF0ZSBhIHNlcXVlbmNlIHVzaW5nIHRoZSBjb2xvbiBub3RhdGlvbiwgdGhlIHJlc3VsdCBpcyBhIHZlY3RvciB0aGF0IGlzIHRoZSBzYW1lIGFzIGlmIHlvdSB1c2VkIHRoZSBjb25zdHJ1Y3QgZnVuY3Rpb246DQoNCmBgYHtyfQ0KZmlyc3RWZWN0b3IgPC0gMTo1DQpzZWNvbmRWZWN0b3IgPC0gYygxOjUpDQoNCmZpcnN0VmVjdG9yDQpzZWNvbmRWZWN0b3INCmBgYA0KDQpUbyBmaW5kIHRoZSBudW1iZXIgb2YgaXRlbXMgaW4gYSB2ZWN0b3IsIHVzZSB0aGUgYGxlbmd0aCgpYCBmdW5jdGlvbjoNCg0KYGBge3J9DQpsZW5ndGgoYW5pbWFsKQ0KYGBgDQoNCg0KVG8gYXBwZW5kIGFub3RoZXIgaXRlbSB0byBhIHZlY3RvciwgaW5jbHVkZSB0aGUgcHJldmlvdXMgdmVjdG9yIGluIHRoZSBjb25zdHJ1Y3QgZnVuY3Rpb246DQoNCmBgYHtyfQ0KYW5pbWFsIDwtIGMoYW5pbWFsLCJtb25rZXkiKQ0KDQphbmltYWwNCmxlbmd0aChhbmltYWwpDQpgYGANCg0KVG8gcmVwbGFjZSBhIHBhcnRpY3VsYXIgaXRlbSwgcmVmZXJlbmNlIGl0IGJ5IGl0cyBpbmRleDoNCg0KYGBge3J9DQphbmltYWxbMl0gPC0gImFyYWNobmlkIg0KYGBgDQoNCllvdSBjYW4gcmVmZXIgdG8gcGFydCBvZiBhIHZlY3RvciB1c2luZyBhIHN1YnZlY3RvciByZWZlcmVuY2UgbGlrZSB0aGlzOg0KDQpgYGB7cn0NCmFuaW1hbFsyOjRdDQpgYGANCg0KVGhlIGl0ZW1zIGluIHRoZSB2ZWN0b3IgdGhhdCB5b3UgYXJlIGV4dHJhY3RpbmcgYXJlIHNwZWNpZmllZCBieSB0aGUgc2VxdWVuY2UgeW91IHB1dCBpbiB0aGUgc3F1YXJlIGJyYWNrZXRzLiAgKEFzaWRlIGZvciBQeXRob24gdXNlcnM6IHVubGlrZSBQeXRob24gc2xpY2VzLCB0aGUgbGFzdCBudW1iZXIgaW4gdGhlIHNlcXVlbmNlIGlzIGluY2x1ZGVkIGluIHRoZSBzdWJ2ZWN0b3IuICBBbHNvIHJlbWVtYmVyIHRoYXQgdGhhdCB0aGUgZmlyc3QgaXRlbSBpbiB0aGUgdmVjdG9yIGlzIDEsIG5vdCAwIGFzIGluIFB5dGhvbi4pDQoNCllvdSBjYW4gZXhwbGljaXRseSBjb25zdHJ1Y3QgdGhlIHNlcXVlbmNlIG9mIGl0ZW1zIGJ5IGxpc3RpbmcgdGhlIGl0ZW0gbnVtYmVycy4gIFlvdSBjYW4gYWxzbyBhc3NpZ24gdGhlIHNlcXVlbmNlIHRvIGEgdmFyaWFibGUgYW5kIHNwZWNpZml5IHRoZSBpdGVtcyB0byBiZSBleHRyYWN0ZWQgd2l0aCBpdC4NCg0KYGBge3J9DQphbmltYWxbYyg0LCAxLCAzKV0NCmluZGV4U2VxdWVuY2UgPC0gNDoxDQphbmltYWxbaW5kZXhTZXF1ZW5jZV0NCmBgYA0KDQpPbmUgc29tZXdoYXQgc3VycHJpc2luZyB0aGluZyBhYm91dCBSIGlzIHRoYXQgaW5kaXZpZHVhbCBpdGVtcyBhcmUgYWN0dWFsbHkgdmVjdG9ycyB3aXRoIGxlbmd0aHMgb2Ygb25lLiBUaGUgcmVzdWx0IGlzIHRoZSBzYW1lIHdoZXRoZXIgdGhlIGl0ZW0gaXMgYXNzaWduZWQgZGlyZWN0bHkgdG8gYSB2YXJpYWJsZSBvciBhc3NpZ25lZCBieSB0aGUgY29uc3RydWN0IGZ1bmN0aW9uLiAgDQoNCmBgYHtyfQ0KdGhpbmdPbmUgPC0gYygidGhpbmciKQ0KdGhpbmdUd28gPC0gInRoaW5nIg0KDQp0aGluZ09uZQ0KdGhpbmdPbmVbMV0NCnRoaW5nVHdvDQp0aGluZ1R3b1sxXQ0KDQpsZW5ndGgodGhpbmdPbmUpDQpsZW5ndGgodGhpbmdPbmVbMV0pDQpsZW5ndGgodGhpbmdUd28pDQpgYGANCg0KUiBoYXMgdHdvIGJ1aWx0LWluIHZhbHVlcyB0byBpbmRpY2F0ZSB0aGF0IHNvbWV0aGluZyBpcyB3cm9uZzogYE5BYCBhbmQgYE5VTExgLiAgDQoNCmBOQWAgaXMgdXNlZCBmb3IgbWlzc2luZyB2YWx1ZXMuICBJdCBpcyBhbiBpbmRpY2F0b3IgdGhhdCBhIHZhbHVlIGlzIG1pc3NpbmcgYW5kIGl0IGNhbiBiZSBhc3NpZ25lZCB0byBhIHZlY3RvciBhcyBhIHZhbHVlLiAgSXQgaGFzIGEgbGVuZ3RoIG9mIG9uZSBhbmQgeW91IGNhbiB0aGluayBvZiBpdCBhcyBhIHNvcnQgb2YgZW1wdHkgaXRlbS4gDQoNCmBgYHtyfQ0KYW5pbWFsWzJdIDwtIE5BDQphbmltYWwNCmBgYA0KDQpgTlVMTGAgaXMgdXNlZCB0byBpbmRpY2F0ZSB0aGF0IHRoZXJlIGlzIG5vIHZhbHVlLiAgSXQgY2FuJ3QgYmUgYXNzaWduZWQgdG8gYSB2ZWN0b3IgYXMgYSB2YWx1ZS4gIEl0IGhhcyBhIGxlbmd0aCBvZiB6ZXJvIGFuZCBhbmQgeW91IGNhbiB0aGluayBvZiBpdCBhcyB0aGUgY2FzZSBvZiBhbiBpdGVtIHRoYXQgaXNuJ3QgdGhlcmUuDQoNCmBgYHtyfQ0KYW5pbWFsWzNdIDwtIE5VTEwNCmFuaW1hbA0KYGBgDQoNCiMjIExpc3RzDQoNCiFbRGlhZ3JhbSBvZiBhIGxpc3RdKGh0dHBzOi8vaGVhcmRsaWJyYXJ5LmdpdGh1Yi5pby9kaWdpdGFsLXNjaG9sYXJzaGlwL3NjcmlwdC9yL2ltYWdlcy9saXN0LWRpYWdyYW0ucG5nKQ0KDQpBICpsaXN0KiBpcyBhbHNvIGEgb25lLWRpbWVuc2lvbmFsIGRhdGEgc3RydWN0dXJlLCBsaWtlIGEgdmVjdG9yLiBIb3dldmVyLCB0aGUgaXRlbXMgaW4gYSBsaXN0IGNhbiBiZSBoZXRlcm9nZW5lb3VzIChkaWZmZXJlbnQgbW9kZXMgb2YgaXRlbXMpLiAgSW4gdGhlIGV4YW1wbGUgYWJvdmUsIHRoZSBsaXN0IGNvbnRhaW5zIHR3byBjaGFyYWN0ZXIgc3RyaW5ncywgb25lIG51bWJlciwgYW5kIG9uZSB2ZWN0b3IuIA0KDQpBc3N1bWluZyB0aGF0IHRoZSBgYW5pbWFsYCB2ZWN0b3IgaXMgaW4geW91ciBlbnZpcm9ubWVudCwgIHRoZSBmb2xsb3dpbmcgY29tbWFuZCB3aWxsIGNyZWF0ZSB0aGUgbGlzdCBkaWFncmFtbWVkIGFib3ZlOg0KDQpgYGB7cn0NCnRoaW5nIDwtIGxpc3QoZnJ1aXRLaW5kPSJhcHBsZSIsIGV1bGVyPTIuNzE4MjgsIHZlY3RvckRhdGE9YW5pbWFsLCBjdXJzZT0iIUAjJCUiKQ0KYGBgDQoNCk5vdGljZSB0aGF0IGluIHRoaXMgbGlzdCBJJ3ZlIGFzc2lnbmVkIHRoZSBpdGVtcyB0byB0aGUgbGlzdCBieSBuYW1lLiAoSXQgaXMgYWxzbyBwb3NzYmlsZSB0byBhc3NpZ24gbmFtZXMgdG8gdmVjdG9yIGl0ZW1zIGJ1dCB0aGF0IGlzIGxlc3MgY29tbW9uLikNCg0KQmVjYXVzZSB0aGUgbGlzdCBpcyBjb21wbGljYXRlZCwgdGhlIGl0ZW1zIGNvbXBvc2luZyBpdCBhcmUgbm90IHNob3duIGluIHRoZSBFbnZpcm9ubWVudCBwYW5lLiAgVG8gc2VlIGFsbCBvZiB0aGUgbGlzdCdzIHBhcnRzLCBJIGNhbiBlaXRoZXIgY2xpY2sgb24gdGhlIGB0aGluZ2AgZW50cnkgaW4gdGhlIEVudmlyb25tZW50IHBhbmUsIG9yIGlzc3VlIHRoZSBjb21tYW5kOg0KDQpgYGB7cn0NClZpZXcodGhpbmcpDQpgYGANCg0KV2hlbiBJIHZpZXcgdGhlIGxpc3QsIHRoZSBkZXNjcmlwdGlvbiBvcGVucyBhcyBhIG5ldyB0YWJsIGluIHRoZSBzYW1lIHBhbmUgYXMgdGhlIGVkaXRvci4NCg0KSXRlbXMgaW4gYSBsaXN0IGNhbiB2aWV3ZWQgYnkgZWl0aGVyIHRoZWlyIHBvc2l0aW9uIG9yIHRoZWlyIG5hbWUuICBJbiBjb250cmFzdCB0byB2ZWN0b3JzLCB0aGUgaW5kZXggaXMgcHV0IGluIGRvdWJsZSBzcXVhcmUgYnJhY2tldHMuDQoNCmBgYHtyfQ0KdGhpbmdbWzNdXQ0KdGhpbmdbWyJldWxlciJdXQ0KYGBgDQoNCkEgY29tbW9ubHkgdXNlZCBzaG9ydGhhbmQgbWV0aG9kIGZvciByZWZlcnJpbmcgdG8gbGlzdCBpdGVtcyBieSB0aGVpciBuYW1lcyBpcyBieSBzZXBhcmF0aW5nIHRoZSBsaXN0IGZyb20gdGhlIG5hbWUgYnkgYSBkb2xsYXIgc2lnbjoNCg0KYGBge3J9DQp0aGluZyRldWxlcg0KdGhpbmckdmVjdG9yRGF0YQ0KYGBgDQoNCiMjIEZhY3RvcnMNCg0KQSAqZmFjdG9yKiBpcyBhIGRhdGEgc3RydWN0dXJlIGZvciBjYXRlZ29yaXppbmcgZGF0YS4gSXRzIG9yaWdpbiBjb21lcyBmcm9tIGV4cGVyaW1lbnRhbCBkZXNpZ24gdGVybWlub2xvZ3kuICBJbiBhbiBleHBlcmltZW50LCBlYWNoIGNhdGVnb3J5IGludG8gd2hpY2ggYW4gZXhwZXJpbWVudGFsIHRyaWFsIGNhbiBmYWxsIGlzIGNhbGxlZCBhICpsZXZlbCouIEEgZmFjdG9yIGNvbnNpc3RzIG9mIGFsbCBvZiB0aGUgcG9zc2libGUgbGV2ZWxzIHRoYXQgYXJlIHVzZWQgdG8gZ3JvdXAgdHJpYWxzIGJhc2VkIG9uIHRoYXQgZmFjdG9yLiBIZXJlIGlzIGFuIGV4YW1wbGUgb2YgYW4gZXhwZXJpbWVudCB3aGVyZSBwbGFudHMgd2VyZSBncm93biBpbiB3ZXQgb3IgZHJ5IHNvaWw6DQoNCnwgd2F0ZXIgZmFjdG9yIHwgaGVpZ2h0IChjbSkgfA0KfC0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS18DQp8IHdldCAgICAgICAgICB8IDI1ICAgICAgICAgIHwNCnwgd2V0ICAgICAgICAgIHwgMjEgICAgICAgICAgfA0KfCBkcnkgICAgICAgICAgfCAxNCAgICAgICAgICB8DQp8IHdldCAgICAgICAgICB8IDEzICAgICAgICAgIHwNCnwgZHJ5ICAgICAgICAgIHwgMTAgICAgICAgICAgfA0KfCB3ZXQgICAgICAgICAgfCAxOCAgICAgICAgICB8DQoNCldlIGNhbiBjcmVhdGUgYSB2ZWN0b3IgY29udGFpbmluZyBhbGwgb2YgdGhlIHdhdGVyIGNvbmRpdGlvbnMgYW5kIGFub3RoZXIgdmVjdG9yIGNvbnRhaW5pbmcgdGhlIGhlaWdodHM6DQoNCmBgYHtyfQ0Kd2F0ZXJDb25kaXRpb25zIDwtIGMoIndldCIsICJ3ZXQiLCAiZHJ5IiwgIndldCIsICJkcnkiLCAid2V0IikNCmhlaWdodCA8LSBjKDI1LCAyMSwgMTQsIDEzLCAxMCwgMTgpDQoNCndhdGVyQ29uZGl0aW9ucw0KaGVpZ2h0DQpgYGANCg0KVG8gY29udmVydCB0aGUgYHdlYXRoZXJDb25kaXRpb25zYCB2ZWN0b3IgaW50byBhIGZhY3RvciwgdXNlIHRoZSBgZmFjdG9yKClgIGZ1bmN0aW9uOg0KDQpgYGB7cn0NCndhdGVyRmFjdG9yIDwtIGZhY3Rvcih3YXRlckNvbmRpdGlvbnMpDQoNCndhdGVyRmFjdG9yDQpgYGANCg0KV2hlbiB3ZSBydW4gdGhlIGNvZGUgY2h1bmsgYWJvdmUsIHdlIGNhbiBzZWUgdHdvIHdheXMgdGhhdCBgd2F0ZXJGYWN0b3JgIGlzIGRpZmZlcmVudCBmcm9tIGB3YXRlckNvbmRpdGlvbnNgOg0KDQotIHRoZSBgd2F0ZXJGYWN0b3JgIGl0ZW1zIGFyZSBub3QgaW4gcXVvdGF0aW9uIG1hcmtzDQotIGJlbG93IHRoZSBsaXN0IG9mIGl0ZW1zIGlzIGEgc3VtbWFyeSBvZiB0aGUgbGV2ZWxzLCBzaG93aW5nIHRoYXQgdGhlcmUgYXJlIG9ubHkgdHdvIGRpZmZlcmVudCBjYXRlZ29yaWVzIGludG8gd2hpY2ggdGhlIGV4cGVyaW1lbnRhbCB0cmlhbHMgY2FuIGJlIGdyb3VwZWQuDQoNCiFbRmFjdG9yIHZzLiB2ZWN0b3IgaW4gdGhlIEVudmlyb25tZW50XShodHRwczovL2hlYXJkbGlicmFyeS5naXRodWIuaW8vZGlnaXRhbC1zY2hvbGFyc2hpcC9zY3JpcHQvci9pbWFnZXMvZmFjdG9yLXZzLXZlY3Rvci5wbmcpDQoNCldlIGNhbiBhbHNvIHNlZSBieSBsb29raW5nIGF0IHRoZSBFbnZpcm9ubWVudCBwYW5lIHRoYXQgYHdhdGVyQ29uZGl0aW9uc2AgaXMgaWRlbnRpZmllZCBhcyBhIHZlY3RvciBvZiBjaGFyYWN0ZXIgc3RyaW5ncywgd2hpbGUgYHdhdGVyRmFjdG9yYCBpcyBpZGVudGlmaWVkIGFzIGEgRmFjdG9yIHdpdGggdHdvIGxldmVscy4gIA0KDQpGYWN0b3JzIGFyZSBzdG9yZWQgYW5kIHByb2Nlc3NlZCBtb3JlIGVmZmljaWVudGx5IHRoYW4gY2hhcmFjdGVycyBhbmQgcGxheSBhIHNwZWNpYWwgcm9sZSBhcyAqZ3JvdXBpbmcgdmFyaWFibGVzKiBpbiBzdGF0aXN0aWNhbCB0ZXN0cyB0aGF0IHJlcXVpcmUgdGhlIGRhdGEgdG8gYmUgcGxhY2VkIGludG8gY2F0ZWdvcmljYWwgZ3JvdXBzLg0KDQojIyBEYXRhIGZyYW1lcw0KDQohW1N0cnVjdHVyZSBvZiBhIGRhdGEgZnJhbWVdKGh0dHBzOi8vaGVhcmRsaWJyYXJ5LmdpdGh1Yi5pby9kaWdpdGFsLXNjaG9sYXJzaGlwL3NjcmlwdC9yL2ltYWdlcy9kYXRhLWZyYW1lLWRpYWdyYW0ucG5nKQ0KDQoqRGF0YSBmcmFtZXMqIGFyZSB0d28gZGltZW5zaW9uYWwgZGF0YSBzdHJ1Y3R1cmVzIGFuZCBhcmUgb25lIG9mIHRoZSBtb3N0IHdpZGVseSB1c2VkIGRhdGEgdHlwZXMgaW4gUi4gT25lIGNhbiB0aGluayBvZiBhIGRhdGEgZnJhbWUgYXMgYSB0YWJsZSB3aXRoIHJvd3MgYW5kIGNvbHVtbnMsIHdpdGggdGhlIHRvcCByb3cgY29udGFpbmluZyBjb2x1bW4gaGVhZGVycyB0aGF0IGFyZSBuYW1lcyBkZXNjcmliaW5nIHdoYXQncyBpbiB0aGUgY29sdW1ucy4NCg0KSXQgaXMgaGVscGZ1bCB0byB0aGluayBvZiBhIGRhdGEgZnJhbWUgYXMgYSBzb3J0IG9mIGNvbWJpbmF0aW9uIG9mIGxpc3RzIGFuZCB2ZWN0b3JzLiBUaGUgdmFsdWVzIGluIGEgcGFydGljdWxhciBjb2x1bW4gYXJlIGxpa2UgYSB2ZWN0b3IsIHdpdGggdGhlIGNvbHVtbiBoZWFkZXIgZm9yIHRoYXQgY29sdW1uIGNvbnRhaW5pbmcgdGhlIHZlY3RvcidzIG5hbWUuIFRoZSBzZXQgb2YgY29sdW1ucyBpcyBsaWtlIGEgbGlzdCB3aG9zZSBpdGVtcyBhcmUgdmVjdG9ycy4NCg0KV2UgY2FuIGFjdHVhbGx5IGNyZWF0ZSBhIGRhdGEgZnJhbWUgYnkgZmlyc3QgY29uc3RydWN0aW5nIGEgdmVjdG9yIGZvciBlYWNoIGNvbHVtbjoNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyZXB0aWxlIiwgImFyYWNobmlkIiwgImFubmVsaWQiLCAiaW5zZWN0IikgICMgdmVjdG9yIG9mIHN0cmluZ3MNCmFuaW1hbCA8LSBjKCJmcm9nIiwgInNwaWRlciIsICJ3b3JtIiwgImJlZSIpDQpudW1iZXJMZWdzIDwtIGMoNCw4LDAsNikgICMgdmVjdG9yIG9mIG51bWJlcnMNCmBgYA0KDQp0aGVuIGxvYWRpbmcgdGhlIHZlY3RvcnMgaW50byB0aGUgZGF0YSBmcmFtZToNCg0KYGBge3J9DQpvcmdhbmlzbUluZm8gPC0gZGF0YS5mcmFtZShncm91cCwgYW5pbWFsLCBudW1iZXJMZWdzKQ0KDQpvcmdhbmlzbUluZm8NCmBgYA0KDQpCeSBkZWZhdWx0LCBSIHdpbGwgdXNlIHRoZSBuYW1lIG9mIGVhY2ggdmVjdG9yIGFzIHRoZSBuYW1lIGZvciB0aGUgY29sdW1uIGluIHRoZSBkYXRhIGZyYW1lLiBFeHBhbmQgdGhlIEVudmlyb25tZW50IHBhbmUgdG8gc2VlIHdoYXQgaGFwcGVuZWQgd2hlbiB5b3UgY3JlYXRlZCB0aGUgdmVjdG9ycyBhbmQgZGF0YSBmcmFtZSwgYW5kIGNsaWNrIG9uIHRoZSBkYXRhIGZyYW1lIGxpc3RpbmcgdG8gc2VlIGl0cyBzdHJ1Y3R1cmUuDQoNCldlIGNhbiByZWZlciB0byBhIHBhcnRpY3VsYXIgY2VsbCBpbiB0aGUgdGFibGUgYnkgbGlzdGluZyBpdHMgcm93IGZvbGxvd2VkIGJ5IGl0cyBjb2x1bW4gaW4gYnJhY2tldHMsIGxpa2UgdGhpczoNCg0KYGBge3J9DQpvcmdhbmlzbUluZm9bMiwxXQ0KYGBgDQoNCkJlY2F1c2UgdGhlIGNvbHVtbnMgb2YgYSBkYXRhIGZyYW1lIGJlaGF2ZSBzb21ld2hhdCBsaWtlIGxpc3QgaXRlbXMsIHRoZSBub3RhdGlvbiBmb3IgcmVmZXJyaW5nIHRvIGxpc3QgaXRlbXMgYnkgbmFtZSAoZG9sbGFyIHNpZ24gZm9sbG93ZWQgYnkgbmFtZSkgY2FuIGFsc28gYmUgdXNlZCB0byByZWZlciB0byBjb2x1bW5zIGluIGEgZGF0YSBmcmFtZToNCg0KYGBge3J9DQpvcmdhbmlzbUluZm8kYW5pbWFsDQpgYGANCg0KYW5kIGl0ZW1zIGluIHRoYXQgY29sdW1uIGNhbiBiZSByZWZlcnJlZCB0byBieSB0aGVpciBwb3NpdGlvbiBmcm9tIHRoZSB0b3Agb2YgdGhlIGNvbHVtbjoNCg0KYGBge3J9DQpvcmdhbmlzbUluZm8kYW5pbWFsWzRdDQpgYGANCg0KT25lIHRoaW5nIHRoYXQgeW91IG1heSBoYXZlIG5vdGljZWQgaXMgdGhhdCB3aGVuIHdlIGxpc3QgdmFsdWVzIGluIHRoZSBkYXRhIGZyYW1lIHRoYXQgY2FtZSBmcm9tIHRoZSB2ZWN0b3Igb2YgY2hhcmFjdGVyIHN0cmluZ3MsIHRoZXkgYXJlIG5vdCBpbiBxdW90ZXMgYW5kIGhhdmUgbGV2ZWxzIGxpc3RlZCBiZWxvdyB0aGVtLiAgVGhpcyBpcyBiZWNhdXNlIHdoZW4gY2hhcmFjdGVyIGRhdGEgdmVjdG9ycyBhcmUgbG9hZGVkIGludG8gYSBkYXRhIGZyYW1lLCB0aGV5IGFyZSBhdXRvbWF0aWNhbGx5IGNvbnZlcnRlZCB0byBmYWN0b3JzLiAgV2UgY2FuIHNlZSB0aGlzIGJ5IGFza2luZyBhYm91dCB0aGUgY2xhc3Mgb2YgdGhlIG9iamVjdHMgd2UgaGF2ZSBiZWVuIHdvcmtpbmcgd2l0aDoNCg0KYGBge3J9DQpjbGFzcyhvcmdhbmlzbUluZm8pDQpjbGFzcyhvcmdhbmlzbUluZm8kYW5pbWFsKQ0KY2xhc3Mob3JnYW5pc21JbmZvJG51bWJlckxlZ3MpDQpgYGANCg0KV2UgY2FuIGFsc28gc2VlIHRoYXQgdGhlIHZhbHVlcyBvZiB0aGUgZmFjdG9yIGFyZSBhY3R1YWxseSBub3Qgc3RvcmVkIGFzIHN0cmluZ3MsIGJ1dCBhcyBudW1iZXJzOg0KDQpgYGB7cn0NCm9yZ2FuaXNtSW5mb1syLDFdDQpjbGFzcyhvcmdhbmlzbUluZm9bMiwxXSkNCm1vZGUob3JnYW5pc21JbmZvWzIsMV0pDQpgYGANCg0KQnkgc3RvcmluZyB0aGUgZmFjdG9ycyBhcyBudW1iZXJzLCB0aGV5IGNhbiBiZSBvcmRlcmVkLiAgVGhlIG9yZGVyIG9mIHRoZSBmYWN0b3JzIGlzIGltcG9ydGFudCBpbiBzb21lIGFuYWx5c2VzLg0KDQojIyBUaWJibGVzDQoNCk1vcmUgcmVjZW50bHksIHRoZSB1c2Ugb2YgUiBoYXMgZXhwYW5kZWQgZmFyIGJleW9uZCBzdGF0aXN0aWNzLCBzbyBhdXRvbWF0aWNhbGx5IHRyYXNmb3JtaW5nIGNoYXJhY3RlciBkYXRhIGludG8gYSBmb3JtIHRoYXQgaXMgb3B0aW1hbCBmb3Igc3RhdGlzdGljcyAoaS5lLiBmYWN0b3JzKSBpcyBubyBsb25nZXIgbmVjZXNzYXJpbHkgZGVzaXJhYmxlIGluIGV2ZXJ5IGNhc2UuIEFub3RoZXIgdHdvLWRpbWVuc2lvbmFsIGRhdGEgc3RydWN0dXJlLCBjYWxsZWQgYSB0aWJibGUsIHdhcyBkZXZlbG9wZWQgdG8gYnJvYWRlbiB0aGUgdXNlIG9mIGRhdGEgZnJhbWVzLiBXaGVuIGRhdGEgYXJlIHJlYWQgaW50byBhIHRpYmJsZSwgdGhlcmUgaXMgbmV2ZXIgYSBjb252ZXJzaW9uIG9mIGRhdGEgdHlwZXMgKHN0cmluZ3MgcmVtYWluIHN0cmluZ3MpLiANCg0KVGliYmxlcyBhcmUgbm90IHBhcnQgb2YgdGhlIHN0YW5kYXJkIFIgZGlzdHJpYnV0aW9uLCBzbyB0byB1c2UgdGhlbSB5b3UgbmVlZCB0byBsb2FkIGEgbGlicmFyeSBjYWxsZWQgYHRpZHl2ZXJzZWAuICBZb3UgY2FuIGNyZWF0ZSBhIHRpYmJsZSB1c2luZyB0aGUgYHRpYmJsZSgpYCBmdW5jdGlvbjoNCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCm9yZ2FuaXNtVGliYmxlIDwtIHRpYmJsZShncm91cCwgYW5pbWFsLCBudW1iZXJMZWdzKQ0KDQpvcmdhbmlzbVRpYmJsZQ0KYGBgDQoNCklmIHlvdSBjb21wYXJlIHRoZSBvdXRwdXQgb2YgdGhlIGBvcmdhbmlzbVRpYmJsZWAgdGliYmxlIHdpdGggdGhlIG91dHB1dCBvZiB0aGUgYG9yZ2FuaXNtSW5mb2AgZGF0YSBmcmFtZSwgdGhlIGNvbHVtbiB0eXBlIGxpc3RlZCBiZWxvdyB0aGUgY29sdW1uIGhlYWRlciBpcyBgY2hyYCBmb3IgdGhlIHRpYmJsZSBhbmQgYGZjdHJgIGZvciB0aGUgZGF0YSBmcmFtZS4gIFNvIHdlIGNhbiBzZWUgdGhhdCB3aGVuIHRoZSB2ZWN0b3JzIHdlcmUgbG9hZGVkIGludG8gdGhlIHRpYmJsZSwgdGhlaXIgY2xhc3Mgd2FzIE5PVCBjaGFuZ2VkLiAgDQoNCmBgYHtyfQ0KY2xhc3Mob3JnYW5pc21UaWJibGUpDQpjbGFzcyhvcmdhbmlzbVRpYmJsZSRhbmltYWwpDQpjbGFzcyhvcmdhbmlzbVRpYmJsZSRudW1iZXJMZWdzKQ0KYGBgDQoNClRoZSBjbGFzcyBvZiB0aGUgdGliYmxlIGlzIGxpc3RlZCBhcyBib3RoIGB0YmxgICh0aWJibGUpIGFuZCBgZGF0YS5mcmFtZWAgKGRhdGEgZnJhbWUpIGJlY2F1c2UgYSB0aWJibGUgaXMgY29uc2lkZXJlZCBhIHNwZWNpYWwga2luZCBvZiBkYXRhIGZyYW1lLiBZb3UgY2FuIGFsc28gc2VlIHRoYXQgdGhlIGFuaW1hbCBjb2x1bW4gcmVtYWluZWQgY2hhcmFjdGVycyBhbmQgd2FzIG5vdCBjb252ZXJ0ZWQgdG8gYSBmYWN0b3IgYXMgd2FzIHRoZSBjYXNlIHdoZW4gd2UgY3JlYXRlZCB0aGUgZGF0YSBmcmFtZS4NCg0KIyBBcHBseWluZyBmdW5jdGlvbnMNCg0KQSBmdW5jdGlvbiBpcyBsaWtlIGEgbWFjaGluZSB0aGF0IHRyYW5zZm9ybXMgd2hhdCB3ZSBwdXQgaW50byBpdCBpbnRvIHNvbWV0aGluZyBkaWZmZXJlbnQgdGhhdCBjb21lcyBvdXQuICBXZSBwYXNzICphcmd1bWVudHMqIGludG8gdGhlIGZ1bmN0aW9uIGFuZCB0aGUgZnVuY3Rpb24gcmV0dXJucyB2YWx1ZXMuDQoNCiFbTnlrYW1wIERRLCAiRnVuY3Rpb24gbWFjaGluZSBmLiIgRnJvbaBNYXRoIEluc2lnaHQuoGh0dHA6Ly9tYXRoaW5zaWdodC5vcmcvaW1hZ2UvZnVuY3Rpb25fbWFjaGluZV9mICBDQyBCWS1OQy1TQV0oaHR0cHM6Ly9tYXRoaW5zaWdodC5vcmcvbWVkaWEvaW1hZ2UvaW1hZ2UvZnVuY3Rpb25fbWFjaGluZV9mLnBuZykNCg0KVGhlcmUgYXJlIG1hbnkgYnVpbHQtaW4gZnVuY3Rpb25zIGluIFIuIEZvciBleGFtcGxlLCBJIGNhbiB0YWtlIHRoZSBzcXVhcmUgcm9vdCBvZiBhIG51bWJlciBieSBwYXNzaW5nIGl0IGludG8gdGhlIGBzcXJ0KClgIGZ1bmN0aW9uLiANCg0KYGBge3J9DQp4IDwtIDINCnNxcnQoeCkNCmBgYA0KSW4gdGhpcyBjYXNlLCBJIHBhc3NlZCBhIHNpbmdsZSBudW1lcmljIHZhbHVlIGludG8gdGhlIGZ1bmN0aW9uIGFuZCBnb3Qgb3V0IGEgc2luZ2xlIHZhbHVlLiAgSG93ZXZlciwgcmVjYWxsIHRoYXQgaW4gUiBhIHZhcmlhYmxlIGNvbnRhaW5pbmcgYSBzaW5nbGUgdmFsdWUgaXMgdGhlIHNhbWUgYXMgYSB2ZWN0b3Igd2l0aCBhIGxlbmd0aCBvZiBvbmUuICBXaGF0IHRoYXQgbWVhbnMgaXMgdGhhdCBmb3IgbWFueSBmdW5jdGlvbnMsIEkgY2FuIHBhc3MgaW4gYSB2ZWN0b3IgY29udGFpbmluZyBtYW55IGl0ZW1zIGFuZCB0aGUgZnVuY3Rpb24gd2lsbCBiZSBhcHBsaWVkIHRvIGV2ZXJ5IGl0ZW0gaW4gdGhlIHZlY3Rvci4gIFRoZSBvdXRwdXQgcmV0dXJuZWQgZnJvbSB0aGUgZnVuY3Rpb24gaXMgYWxzbyBhIHZlY3RvciB3aG9zZSBpdGVtcyBhcmUgaW4gdGhlIHNhbWUgb3JkZXIgYXMgdGhlIGlucHV0IHZlY3Rvci4NCg0KYGBge3J9DQpzcXJ0KG9yZ2FuaXNtSW5mbyRudW1iZXJMZWdzKQ0KYGBgDQoNCk90aGVyIGZ1bmN0aW9ucyBtYXkgZXhwZWN0IGEgdmVjdG9yIGlucHV0LCBidXQgb3V0cHV0IG9ubHkgYSBzaW5nbGUgbnVtYmVyLiBUaGUgYG1lYW4oKWAgZnVuY3Rpb24gdGFrZXMgdGhlIGF2ZXJhZ2Ugb2YgdGhlIGl0ZW1zIGluIGEgdmVjdG9yIGFuZCByZXR1cm5zIGEgc2luZ2xlIHZhbHVlLg0KDQpgYGB7cn0NCm1lYW4ob3JnYW5pc21JbmZvJG51bWJlckxlZ3MpDQpgYGANCg0KUiBkaWZmZXJzIGZyb20gc29tZSBvdGhlciBsYW5ndWFnZXMgbGlrZSBQeXRob24gaW4gdGhhdCBpdCBjYW4gYXV0b21hdGljYWxseSBwZXJmb3JtIGZ1bmN0aW9ucyBvbiBhbiBlbnRpcmUgdmVjdG9yIG9mIHZhbHVlcyB3aXRob3V0IHJlcXVpcmluZyB0aGF0IHRoZSBjb2RlIGl0ZXJhdGUgdGhyb3VnaCBlYWNoIGl0ZW0gaW4gdGhlIHZlY3Rvci4NCg0KSGVyZSBpcyBhbm90aGVyIGV4YW1wbGUgdXNpbmcgdGhlIGBuY2hhcigpYCBmdW5jdGlvbiB0aGF0IGNvdW50cyB0aGUgbnVtYmVyIG9mIGNoYXJhY3RlcnMgaW4gYSBzdHJpbmc6DQoNCmBgYHtyfQ0KIyBsaXN0IHRoZSB3b3JkcyBpbiB0aGUgYW5pbWFsIGNvbHVtbg0Kb3JnYW5pc21UaWJibGUkYW5pbWFsDQoNCiMgbGlzdCB0aGUgY291bnQgb2YgY2hhcmFjdGVycyBpbiBlYWNoIHdvcmQgaW4gdGhlIGNvbHVtbg0KbmNoYXIob3JnYW5pc21UaWJibGUkYW5pbWFsKQ0KYGBgDQoNCg==