As important as carrying out the data analysis of an investigation (main objective of this workshop), it is also important to communicate the results to an audience, and receive acknowledgement and comments about them. Usually that aspect is addressed at the end (as in the workshop book: chapter 22), but if we do so, we can leave behind results, graphs, et c., which at some point we have to find, organize and move to a final document. In this workshop we will be working from the beginning, with a format that allows us to use the R platform for data analysis and visualization, while producing documents that contain text, codes and products (results and graphs) of the workshop activities.
Creating a R Notebook
(R Notebook is a R Markdown document, but with some extra options, like a Preview)
Use the left-upper corner menu:

Select R Notebook.
Editing the document
The R Notebook has three types of content:
- an (optional) YAML header surrounded by - - -
- R code chunks surrounded by ```
- text mixed with simple text formatting
The YAML header is a metadata section of the document, and can be edited to include basic information of the document:

You can change (or eliminate) the title, author, and date. The output option is originally created by RStudio, and depends on the output format that you produce (html, pdf, Word). A R Markdown document (html_document) can be transformed into a R Notebook (html_notebook) and vice versa.
The text and other document features (web links, images) are edited or created using a R Markdown syntax.
Inserting R code chunks
A code chunk is simply a piece of R code by itself, embedded in a R Markdown document. The format is:

Inside the {r} you can write chunk options that control the behavior of the code output, when producing the final document.
Another way to create code chunks (including for other scripting languages) and select options, is using the
drop-menu.
Executing code chunks and controling output
Code in the notebook can be executed in different ways: Use the green triangle button on the toolbar of a code chunk that has the tool tip “Run Current Chunk”, or Ctrl + Shift + Enter (macOS: Cmd + Shift + Enter) to run the current chunk.
Press Ctrl + Enter (macOS: Cmd + Enter) to run just the current statement.
There are other ways to run a batch of chunks if you click the menu Run on the editor toolbar, such as “Run All”, “Run All Chunks Above”, and “Run All Chunks Below”.
In the previous section you learn how to control chunk output, with several options. You can also select the options using
.
Preview and Knit
To obtain a preview (not running codes) of the R Notebook, or in a different format (HTML, PDF, Word, with code output) you will use the following menu (if you start with a R Markdown document, instead of a R Notebook, you will see the word Knit, instead of Preview):

Producing a PDF document requires a LaTex version for your computer (usually requires more than 1 GB!).
Exercises
- Open a new R Notebook, and name it DayOneExercises??? (??? = your initials). Saving it will let you name it.
- Edit the YAML metadata information, including a title, your name and date.
- Write a short paragraph about your municipality, that includes text in different styles, a web link, and an image. Preview and edit as necessary.
- Write a code to calculate the surface of a geometric figure. Use the code chunk format and run it (you can start in a R Script, and later create a chunk in the document and copy de code). Run the chunk. Change output options for the chunk, and run again. When finish, preview the notebook.
Datasets
The first step in any data analysis is the creation of a dataset containing the information to be studied, in a format that meets your needs. In R, this task involves the following:
- Selecting a data structure to hold your data
- Entering or importing your data into the data structure
Data structures
R has a wide variety of objects for holding data, including scalars, vectors, matrices, arrays, data frames, and lists. They differ in terms of the type of data they can hold, how they’re created, their structural complexity, and the notation used to identify and access individual elements.
R data structures:
Vectors
Vectors are one-dimensional arrays that can hold numeric data, character data, or logical data. The combine function c(…) is used to form the vector.
a <- c(1, 2, 5, 3, 6, -2, 2.3)
a
b <- c("one", "two", "three")
b
c <- c(TRUE, TRUE, TRUE, FALSE, TRUE, FALSE)
c
# What happen if we combine different types of data?
Vectors may also be generated using the seq(…) function, when you want a sequence of numbers, evenly spaced by a specified interval.
d <- seq(3, 11, by = 0.7)
d
dd <- c(1:4, seq(2.1, 4.5, by = 1.1))
dd
# You can use operators (+, -, *, /, et c.) to create the vector; try them.
You can refer to elements of a vector using a numeric vector of positions within brackets. For example, a[c(2, 4)] refers to the second and fourth elements of vector e.
e <- c("k", "j", "h", "a", "c", "m")
e[3]
e[c(1, 3, 5)]
e[2:6]
# What happen if you use e[]?
We can do operations with vectors.
f <- c(1, 2, 3, 5, 7)
g <- c(2, 4, 6, 8, 10)
f + g
f / g
# What happen if vectors are of different length?
Matrices
A matrix is a two-dimensional array in which each element has the same mode (numeric, character, or logical). Matrices are created with the matrix() function. The general format is:
mymatrix <- matrix(vector, nrow=number_of_rows, ncol=number_of_columns,
byrow=logical_value,
dimnames=list(char_vector_rownames,
char_vector_colnames))
y <- matrix(1:20, nrow=5, ncol=4)
y
[,1] [,2] [,3] [,4]
[1,] 1 6 11 16
[2,] 2 7 12 17
[3,] 3 8 13 18
[4,] 4 9 14 19
[5,] 5 10 15 20
# What happen if we add byrow = TRUE ?
cells <- c(1,26,24,68,-3,0.3,110,17,2)
rnames <- c("Row1", "Row2", "Row3")
cnames <- c("Col1", "Col2", "Col3")
mymatrix <- matrix(cells, ncol=3, byrow=TRUE,
dimnames=list(rnames, cnames))
mymatrix
Col1 Col2 Col3
Row1 1 26 24.0
Row2 68 -3 0.3
Row3 110 17 2.0
# Multiply a matrix by a scalar (for example, to change units).
# Can you extract specific elements of a matrix? (Look back in vectors, and use the format [rows,columns])
# A matrix can be transposed (rows <-> columns) using t(...)
tmatrix <- t(mymatrix)
tmatrix
Row1 Row2 Row3
Col1 1 68.0 110
Col2 26 -3.0 17
Col3 24 0.3 2
Data frames
A data frame is more general than a matrix in that different columns can contain different modes of data (numeric, character, and so on). Data frames are the most common data structure you’ll deal with in R. A data frame is created with the data.frame() function:
mydata <- data.frame(col1, col2, col3,…)
where col1, col2, col3, and so on are column vectors of any type (such as character, numeric, or logical). Names for each column can be provided with the names function.
# Creating a matrix from vectors:
patientID <- c(1, 2, 3, 4)
age <- c(25, 34, 28, 52)
diabetes <- c("Type1", "Type2", "Type1", "Type1")
status <- c("Poor", "Improved", "Excellent", "Poor")
patientdata <- data.frame(patientID, age, diabetes, status)
patientdata
# Changing the names of the columns:
newpatientdata <- setNames(patientdata, c("ID","edad","DiabT","Estado"))
newpatientdata
There are several ways to select the elements of a data frame:
# Using the subscript notation (as in a matrix):
selectpatientdata <- patientdata[ ,1:2] # the blank for row index means that all rows are selected
selectpatientdata
# Using the columns' names:
selectpatientdata <- patientdata[,c("diabetes", "status")]
selectpatientdata
# Using the object$variable notation:
selectpatientdata <- patientdata$age
selectpatientdata
[1] 25 34 28 52
# Note that output is a vector
Factors
Categorical (nominal) and ordered categorical (ordinal) variables in R are called factors. Factors are crucial in R because they determine how data is analyzed and presented visually.
With categorical variables you can create cross-tabulations, using the table function:
table(patientdata$diabetes, patientdata$status)
The function factor(…) stores the categorical values as a vector of integers associated to each different value of the categorical variable, this is very important for data analysis:
statuslevel <- factor(status)
statuslevel
as.numeric(statuslevel)
Descriptive Statistics
R have a large number of ways to calculate descriptive statistics on the datasets, some are included in the basic installation, and others in packages that need download-installation (using install.packages) and load (activation) to the environment (using library).
Using summary
Let start using the basic procedures (function summary), with the mtcars dataset provided with your book’s code.
# create a data frame with the CSV file and make it available for the procedure
mtcars <- read.csv("mtcars.csv")
# create a list of variables to analyze
myvars <- c("mpg", "hp", "wt")
# use summary with the selected variables
summary(mtcars[myvars])
Using function and sapply
A more general way to calculate basic statistics is using the sapply procedure, with the syntax:
sapply(x, FUN, options))
where FUN is a simple system function (like mean(var), sd(var), et c.) or an user-defined function, with the following syntax:
myfunction <- function(arg1, arg2, … ){
statements
return(object)
}
# defining function
mystats <- function(x){
m <- mean(x)
n <- length(x)
s <- sd(x)
skew <- sum((x-m)^3/s^3)/n
kurt <- sum((x-m)^4/s^4)/n - 3
return(c(n=n, mean=m, stdev=s, skew=skew, kurtosis=kurt))
}
# arguments (variables) to use
myvars <- c("mpg", "hp", "wt")
# sapply function on dataset
sapply(mtcars[myvars], mystats)
Using aggregate
When you have variables that can be considered as factor, you can use the aggregate function to obtain basic statistics aggregating by such factors. The function has the following syntax:
aggregate(x, by, FUN)
#read data and attach object for easier use of the variables
mtcars <- read.csv('mtcars.csv')
attach(mtcars)
#calculate the mean of numeric variables, aggregated by cyl and gear as factors; missing values are removed
aggdata <- aggregate(mtcars[c('mpg','hp','wt')], by=list(cyl,gear), FUN = mean, na.rm = TRUE)
#set names for resulting data table - what happen if we skip this line of code?
aggdata <- setNames(aggdata, c("CYL","GEAR","mpg","hp","wt"))
aggdata
detach(mtcars) #why detach?
LS0tCnRpdGxlOiAiRGF5X09uZSIKYXV0aG9yOiAiRC5fUy5fRmVybsOhbmRlei1kZWwtVmlzbyIKZGF0ZTogIjcvMTcvMjAxOCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA1CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogJzUnCi0tLQojIyMgUgpSIGlzIGFuIG9wZW4tc291cmNlIHByb2dyYW1taW5nIGVudmlyb25tZW50LCBmb3Igc3RhdGlzdGljYWwgY29tcHV0aW5nIGFuZCBkYXRhIHZpc3VhbGl6YXRpb24sIGFtb25nIG90aGVyIGNhcGFiaWxpdGllcy4KCiMjIyNfRXhlcmNpc2VzXwoxLiBPcGVuIFIgKG5vIFJTdHVkaW8pOgogICsgdXNlIGl0IGFzIGEgc2NpZW50aWZpYyBjYWxjdWxhdG9yCiAgKyBhc3NpZ24gdmFsdWVzIG9yIGFyaXRobWV0aWMgKMK/IHggPSAzIG8geCA8LSAzID8pIGZvcm11bGFzIHRvIFIgb2JqZWN0cyAodmFyaWFibGVzKQogICsgZWRpdCBjYWxjdWxhdGlvbnMgYW5kIGZvcm11bGFzCjIuIExvb2sgdXAgUiBtZW51cwoKIyMjIyBleHRyYQpbV2h5IHVzZSBSP10oaHR0cHM6Ly9saXZlYm9vay5tYW5uaW5nLmNvbSMhL2Jvb2svci1pbi1hY3Rpb24tc2Vjb25kLWVkaXRpb24vY2hhcHRlci0xL3BvaW50LTI2MjMtMTItMjQtMCkKCiMjIyBSU3R1ZGlvClByb2dyYW1taW5nLCBlZGl0aW5nLCBwcm9qZWN0IG1hbmFnZW1lbnQsIGFuZCBvdGhlciBwcm9jZWR1cmVzIGluIFIsIGFyZSBtb3JlIGVhc3kgYW5kIGVmZmljaWVudCB1c2luZyBhbiBpbnRlZ3JhdGVkIGRldmVsb3BtZW50IGVudmlyb25tZW50IChJREUpLCBhbmQgdGhlIG1vc3QgdXNlZCBhbmQgdmVyc2F0aWxlIGlzIFtSU3R1ZGlvXShodHRwczovL3d3dy5jcy51dGV4YXMuZWR1L35jYW5uYXRhL2RhdGFWaXMvQ2xhc3MlMjBOb3Rlcy9HZXR0aW5nJTIwU3RhcnRlZCUyMHdpdGglMjBSU3R1ZGlvLnBkZikuCgojIyMjX0V4ZXJjaXNlc18KMS4gT3BlbiBSU3R1ZGlvOgogICsgYnJvd3NlIGFsbCB0aGUgY29tcG9uZW50cyBvZiB0aGUgaW50ZXJmYWNlCiAgKyBlc3RhYmxpc2ggYSBXb3JraW5nIERpcmVjdG9yeQogICsgY3JlYXRlIGEgUiBTY3JpcHQgKGNvbXBhcmUgd2l0aCB0aGUgUiBjb25zb2xlKQogICsgd3JpdGUgY29kZSB0byBjYWxjdWxhdGUgdGhlIGFyZWEgb2YgYSBnZW9tZXRyaWMgc3VyZmFjZSwgYW5kIHJ1biBpdAogICsgZXhwbG9yZSBvdGhlciB3aW5kb3dzIGFuZCBtZW51cyBvZiBSU3R1ZGlvCiAgKyBsb2FkIHBhY2thZ2VzOiBnZ3Bsb3QyLCBnZ3ZlcnNhCgojIyMjIGV4dHJhCltQYWNrYWdlc10oaHR0cHM6Ly9saXZlYm9vay5tYW5uaW5nLmNvbSMhL2Jvb2svci1pbi1hY3Rpb24tc2Vjb25kLWVkaXRpb24vY2hhcHRlci0xL3BvaW50LTI2MjQtOTMtMTEzLTApCgoqKioKCiMjIyBSIE1hcmtkb3duIChvciBbUiBOb3RlYm9va10oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duL25vdGVib29rLmh0bWwjdXNpbmctbm90ZWJvb2tzKSkKQXMgaW1wb3J0YW50IGFzIGNhcnJ5aW5nIG91dCB0aGUgZGF0YSBhbmFseXNpcyBvZiBhbiBpbnZlc3RpZ2F0aW9uIChtYWluIG9iamVjdGl2ZSBvZiB0aGlzIHdvcmtzaG9wKSwgaXQgaXMgYWxzbyBpbXBvcnRhbnQgdG8gY29tbXVuaWNhdGUgdGhlIHJlc3VsdHMgdG8gYW4gYXVkaWVuY2UsIGFuZCByZWNlaXZlIGFja25vd2xlZGdlbWVudCBhbmQgY29tbWVudHMgYWJvdXQgdGhlbS4gVXN1YWxseSB0aGF0IGFzcGVjdCBpcyBhZGRyZXNzZWQgYXQgdGhlIGVuZCAoYXMgaW4gdGhlIHdvcmtzaG9wIGJvb2s6IFtjaGFwdGVyIDIyXShodHRwczovL2xpdmVib29rLm1hbm5pbmcuY29tIyEvYm9vay9yLWluLWFjdGlvbi1zZWNvbmQtZWRpdGlvbi9jaGFwdGVyLTIyL3BvaW50LTI3NDYtMzgtMzgtMCkpLCBidXQgaWYgd2UgZG8gc28sIHdlIGNhbiBsZWF2ZSBiZWhpbmQgcmVzdWx0cywgZ3JhcGhzLCBldCBjLiwgd2hpY2ggYXQgc29tZSBwb2ludCB3ZSBoYXZlIHRvIGZpbmQsIG9yZ2FuaXplIGFuZCBtb3ZlIHRvIGEgZmluYWwgZG9jdW1lbnQuIEluIHRoaXMgd29ya3Nob3Agd2Ugd2lsbCBiZSB3b3JraW5nIGZyb20gdGhlIGJlZ2lubmluZywgd2l0aCBhIGZvcm1hdCB0aGF0IGFsbG93cyB1cyB0byB1c2UgdGhlIFIgcGxhdGZvcm0gZm9yIGRhdGEgYW5hbHlzaXMgYW5kIHZpc3VhbGl6YXRpb24sIHdoaWxlIHByb2R1Y2luZyBkb2N1bWVudHMgdGhhdCBjb250YWluIHRleHQsIGNvZGVzIGFuZCBwcm9kdWN0cyAocmVzdWx0cyBhbmQgZ3JhcGhzKSBvZiB0aGUgd29ya3Nob3AgYWN0aXZpdGllcy4KCiMjIyMgQ3JlYXRpbmcgYSBSIE5vdGVib29rCihSIE5vdGVib29rIGlzIGEgUiBNYXJrZG93biBkb2N1bWVudCwgYnV0IHdpdGggc29tZSBleHRyYSBvcHRpb25zLCBsaWtlIGEgX19QcmV2aWV3X18pCgpVc2UgdGhlIGxlZnQtdXBwZXIgY29ybmVyIG1lbnU6Cgo+IVtdKENyZWF0ZU5vdGVib29rLnBuZyl7I2lkIC5jbGFzcyB3aWR0aD0xMjAgaGVpZ2h0PTgwcHh9XAoKClNlbGVjdCBfX1IgTm90ZWJvb2tfXy4KCiMjIyMgRWRpdGluZyB0aGUgZG9jdW1lbnQKVGhlIFIgTm90ZWJvb2sgaGFzIHRocmVlIHR5cGVzIG9mIGNvbnRlbnQ6CgoqIGFuIChvcHRpb25hbCkgX19ZQU1MIGhlYWRlcl9fIHN1cnJvdW5kZWQgYnkgLSAtIC0KKiBSIF9fY29kZSBjaHVua3NfXyBzdXJyb3VuZGVkIGJ5IGBgYAoqIF9fdGV4dF9fIG1peGVkIHdpdGggc2ltcGxlIHRleHQgZm9ybWF0dGluZwoKVGhlIFlBTUwgaGVhZGVyIGlzIGEgbWV0YWRhdGEgc2VjdGlvbiBvZiB0aGUgZG9jdW1lbnQsIGFuZCBjYW4gYmUgZWRpdGVkIHRvIGluY2x1ZGUgYmFzaWMgaW5mb3JtYXRpb24gb2YgdGhlIGRvY3VtZW50OgoKPiFbXShZQU1MLnBuZyl7I2lkIC5jbGFzcyB3aWR0aD0xODAgaGVpZ2h0PTEyMHB4fVwKCgpZb3UgY2FuIGNoYW5nZSAob3IgZWxpbWluYXRlKSB0aGUgdGl0bGUsIGF1dGhvciwgYW5kIGRhdGUuICBUaGUgb3V0cHV0IG9wdGlvbiBpcyBvcmlnaW5hbGx5IGNyZWF0ZWQgYnkgUlN0dWRpbywgYW5kIGRlcGVuZHMgb24gdGhlIG91dHB1dCBmb3JtYXQgdGhhdCB5b3UgcHJvZHVjZSAoaHRtbCwgcGRmLCBXb3JkKS4gIEEgUiBNYXJrZG93biBkb2N1bWVudCAoaHRtbF9kb2N1bWVudCkgY2FuIGJlIHRyYW5zZm9ybWVkIGludG8gYSBSIE5vdGVib29rIChodG1sX25vdGVib29rKSBhbmQgX3ZpY2UgdmVyc2FfLiAKClRoZSB0ZXh0IGFuZCBvdGhlciBkb2N1bWVudCBmZWF0dXJlcyAod2ViIGxpbmtzLCBpbWFnZXMpIGFyZSBlZGl0ZWQgb3IgY3JlYXRlZCB1c2luZyBhIFtSIE1hcmtkb3duIHN5bnRheF0oaHR0cHM6Ly93d3cucnN0dWRpby5jb20vd3AtY29udGVudC91cGxvYWRzLzIwMTUvMDIvcm1hcmtkb3duLWNoZWF0c2hlZXQucGRmKS4KCiMjIyMgSW5zZXJ0aW5nIFIgY29kZSBjaHVua3MKQSBbY29kZSBjaHVua10oaHR0cHM6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20vbGVzc29uLTMuaHRtbCkgaXMgc2ltcGx5IGEgcGllY2Ugb2YgUiBjb2RlIGJ5IGl0c2VsZiwgZW1iZWRkZWQgaW4gYSBSIE1hcmtkb3duIGRvY3VtZW50LiBUaGUgZm9ybWF0IGlzOgoKPiFbXShjaHVuay5wbmcpeyNpZCAuY2xhc3Mgd2lkdGg9MTgwIGhlaWdodD0xMjBweH1cCgpJbnNpZGUgdGhlIHtyfSB5b3UgY2FuIHdyaXRlIFtjaHVuayBvcHRpb25zXShodHRwczovL2Jvb2tkb3duLm9yZy95aWh1aS9ybWFya2Rvd24vci1jb2RlLmh0bWwpIHRoYXQgY29udHJvbCB0aGUgYmVoYXZpb3Igb2YgdGhlIGNvZGUgb3V0cHV0LCB3aGVuIHByb2R1Y2luZyB0aGUgZmluYWwgZG9jdW1lbnQuCgpBbm90aGVyIHdheSB0byBjcmVhdGUgY29kZSBjaHVua3MgKGluY2x1ZGluZyBmb3Igb3RoZXIgc2NyaXB0aW5nIGxhbmd1YWdlcykgYW5kIHNlbGVjdCBvcHRpb25zLCBpcyB1c2luZyB0aGUgIVtdKGluc2VydGNodW5rLnBuZykgZHJvcC1tZW51LgoKIyMjIyBleHRyYQpbaW5saW5lIGNvZGVdKGh0dHBzOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tL2xlc3Nvbi00Lmh0bWwpCgojIyMjIEV4ZWN1dGluZyBjb2RlIGNodW5rcyBhbmQgY29udHJvbGluZyBvdXRwdXQgCjEuIFtDb2RlIGluIHRoZSBub3RlYm9vayBjYW4gYmUgZXhlY3V0ZWRdKGh0dHBzOi8vYm9va2Rvd24ub3JnL3lpaHVpL3JtYXJrZG93bi9ub3RlYm9vay5odG1sI3VzaW5nLW5vdGVib29rcykgaW4gZGlmZmVyZW50IHdheXM6ClVzZSB0aGUgZ3JlZW4gdHJpYW5nbGUgYnV0dG9uIG9uIHRoZSB0b29sYmFyIG9mIGEgY29kZSBjaHVuayB0aGF0IGhhcyB0aGUgdG9vbCB0aXAg4oCcUnVuIEN1cnJlbnQgQ2h1bmvigJ0sIG9yIEN0cmwgKyBTaGlmdCArIEVudGVyIChtYWNPUzogQ21kICsgU2hpZnQgKyBFbnRlcikgdG8gcnVuIHRoZSBjdXJyZW50IGNodW5rLgoKMi4gUHJlc3MgQ3RybCArIEVudGVyIChtYWNPUzogQ21kICsgRW50ZXIpIHRvIHJ1biBqdXN0IHRoZSBjdXJyZW50IHN0YXRlbWVudC4KCjMuIFRoZXJlIGFyZSBvdGhlciB3YXlzIHRvIHJ1biBhIGJhdGNoIG9mIGNodW5rcyBpZiB5b3UgY2xpY2sgdGhlIG1lbnUgUnVuIG9uIHRoZSBlZGl0b3IgdG9vbGJhciwgc3VjaCBhcyAiUnVuIEFsbCIsICJSdW4gQWxsIENodW5rcyBBYm92ZSIsIGFuZCAiUnVuIEFsbCBDaHVua3MgQmVsb3ciLgoKSW4gdGhlIHByZXZpb3VzIHNlY3Rpb24geW91IGxlYXJuIGhvdyB0byBjb250cm9sIGNodW5rIG91dHB1dCwgd2l0aCBzZXZlcmFsIG9wdGlvbnMuIFlvdSBjYW4gYWxzbyBzZWxlY3QgdGhlIG9wdGlvbnMgdXNpbmcgIVtdKG91dHB1dGNodW5rLnBuZykuCgojIyMjIFByZXZpZXcgYW5kIEtuaXQKVG8gb2J0YWluIGEgcHJldmlldyAobm90IHJ1bm5pbmcgY29kZXMpIG9mIHRoZSBSIE5vdGVib29rLCBvciBpbiBhIGRpZmZlcmVudCBmb3JtYXQgKEhUTUwsIFBERiwgV29yZCwgd2l0aCBjb2RlIG91dHB1dCkgeW91IHdpbGwgdXNlIHRoZSBmb2xsb3dpbmcgbWVudSAoaWYgeW91IHN0YXJ0IHdpdGggYSBSIE1hcmtkb3duIGRvY3VtZW50LCBpbnN0ZWFkIG9mIGEgUiBOb3RlYm9vaywgeW91IHdpbGwgc2VlIHRoZSB3b3JkIFtLbml0XShodHRwczovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbS9sZXNzb24tOS5odG1sKSwgaW5zdGVhZCBvZiBQcmV2aWV3KToKCj4hW10ocHJldmlld2tuaXQucG5nKXsjaWQgLmNsYXNzIHdpZHRoPTE4MCBoZWlnaHQ9MTIwcHh9XAoKClByb2R1Y2luZyBhIFBERiBkb2N1bWVudCByZXF1aXJlcyBhIF9MYVRleF8gdmVyc2lvbiBmb3IgeW91ciBjb21wdXRlciAodXN1YWxseSByZXF1aXJlcyBtb3JlIHRoYW4gMSBHQiEpLgoKCiMjIyMgZXh0cmFzCltUaW55VGV4XShodHRwczovL3lpaHVpLm5hbWUvdGlueXRleC8pICAKW1JQdWJzXShodHRwOi8vcnB1YnMuY29tLykKCgojIyMjX0V4ZXJjaXNlc18KCjEuIE9wZW4gYSBuZXcgUiBOb3RlYm9vaywgYW5kIG5hbWUgaXQgRGF5T25lRXhlcmNpc2VzPz8/ICg/Pz8gPSB5b3VyIGluaXRpYWxzKS4gU2F2aW5nIGl0IHdpbGwgbGV0IHlvdSBuYW1lIGl0LgoyLiBFZGl0IHRoZSBZQU1MIG1ldGFkYXRhIGluZm9ybWF0aW9uLCBpbmNsdWRpbmcgYSB0aXRsZSwgeW91ciBuYW1lIGFuZCBkYXRlLgozLiBXcml0ZSBhIHNob3J0IHBhcmFncmFwaCBhYm91dCB5b3VyIG11bmljaXBhbGl0eSwgdGhhdCBpbmNsdWRlcyB0ZXh0IGluIGRpZmZlcmVudCBzdHlsZXMsIGEgd2ViIGxpbmssIGFuZCBhbiBpbWFnZS4gUHJldmlldyBhbmQgZWRpdCBhcyBuZWNlc3NhcnkuCjQuIFdyaXRlIGEgY29kZSB0byBjYWxjdWxhdGUgdGhlIHN1cmZhY2Ugb2YgYSBnZW9tZXRyaWMgZmlndXJlLiAgVXNlIHRoZSBjb2RlIGNodW5rIGZvcm1hdCBhbmQgcnVuIGl0ICh5b3UgY2FuIHN0YXJ0IGluIGEgUiBTY3JpcHQsIGFuZCBsYXRlciBjcmVhdGUgYSBjaHVuayBpbiB0aGUgZG9jdW1lbnQgYW5kIGNvcHkgZGUgY29kZSkuICBSdW4gdGhlIGNodW5rLiBDaGFuZ2Ugb3V0cHV0IG9wdGlvbnMgZm9yIHRoZSBjaHVuaywgYW5kIHJ1biBhZ2Fpbi4gV2hlbiBmaW5pc2gsIHByZXZpZXcgdGhlIG5vdGVib29rLgoKKioqCgojIyMgRGF0YXNldHMKVGhlIGZpcnN0IHN0ZXAgaW4gYW55IGRhdGEgYW5hbHlzaXMgaXMgdGhlIGNyZWF0aW9uIG9mIGEgW2RhdGFzZXRdKGh0dHBzOi8vbGl2ZWJvb2subWFubmluZy5jb20jIS9ib29rL3ItaW4tYWN0aW9uLXNlY29uZC1lZGl0aW9uL2NoYXB0ZXItMi9wb2ludC0yNzU3LTEtMS0wKSBjb250YWluaW5nIHRoZSBpbmZvcm1hdGlvbiB0byBiZSBzdHVkaWVkLCBpbiBhIGZvcm1hdCB0aGF0IG1lZXRzIHlvdXIgbmVlZHMuIEluIFIsIHRoaXMgdGFzayBpbnZvbHZlcyB0aGUgZm9sbG93aW5nOgoKKiBTZWxlY3RpbmcgYSBkYXRhIHN0cnVjdHVyZSB0byBob2xkIHlvdXIgZGF0YQoqIEVudGVyaW5nIG9yIGltcG9ydGluZyB5b3VyIGRhdGEgaW50byB0aGUgZGF0YSBzdHJ1Y3R1cmUKCiMjIyMgRGF0YSBzdHJ1Y3R1cmVzClIgaGFzIGEgd2lkZSB2YXJpZXR5IG9mIG9iamVjdHMgZm9yIGhvbGRpbmcgZGF0YSwgaW5jbHVkaW5nIHNjYWxhcnMsIHZlY3RvcnMsIG1hdHJpY2VzLCBhcnJheXMsIGRhdGEgZnJhbWVzLCBhbmQgbGlzdHMuIFRoZXkgZGlmZmVyIGluIHRlcm1zIG9mIHRoZSB0eXBlIG9mIGRhdGEgdGhleSBjYW4gaG9sZCwgaG93IHRoZXnigJlyZSBjcmVhdGVkLCB0aGVpciBzdHJ1Y3R1cmFsIGNvbXBsZXhpdHksIGFuZCB0aGUgbm90YXRpb24gdXNlZCB0byBpZGVudGlmeSBhbmQgYWNjZXNzIGluZGl2aWR1YWwgZWxlbWVudHMuCgpbUiBkYXRhIHN0cnVjdHVyZXM6XShodHRwczovL2xpdmVib29rLm1hbm5pbmcuY29tIyEvYm9vay9yLWluLWFjdGlvbi1zZWNvbmQtZWRpdGlvbi9jaGFwdGVyLTIvcG9pbnQtMjYyNi0xOS0yNy0wKQoKKiBbdmVjdG9yXShodHRwczovL2xpdmVib29rLm1hbm5pbmcuY29tIyEvYm9vay9yLWluLWFjdGlvbi1zZWNvbmQtZWRpdGlvbi9jaGFwdGVyLTIvcG9pbnQtMjYyNy0yOC0zNi0wKQoqIFttYXRyaXhdKGh0dHBzOi8vbGl2ZWJvb2subWFubmluZy5jb20jIS9ib29rL3ItaW4tYWN0aW9uLXNlY29uZC1lZGl0aW9uL2NoYXB0ZXItMi9wb2ludC0yNjI4LTM3LTQ2LTApCiogW2RhdGEgZnJhbWVdKGh0dHBzOi8vbGl2ZWJvb2subWFubmluZy5jb20jIS9ib29rL3ItaW4tYWN0aW9uLXNlY29uZC1lZGl0aW9uL2NoYXB0ZXItMi9wb2ludC0yNjMwLTUzLTgyLTApCiogW2FycmF5XSggaHR0cHM6Ly9saXZlYm9vay5tYW5uaW5nLmNvbSMhL2Jvb2svci1pbi1hY3Rpb24tc2Vjb25kLWVkaXRpb24vY2hhcHRlci0yL3BvaW50LTI2MjktNDctNTItMCkKKiBbbGlzdF0oaHR0cHM6Ly9saXZlYm9vay5tYW5uaW5nLmNvbSMhL2Jvb2svci1pbi1hY3Rpb24tc2Vjb25kLWVkaXRpb24vY2hhcHRlci0yL3BvaW50LTI2MzItMTA3LTExNS0wKQoKKioqCgojIyMjIFZlY3RvcnMKW1ZlY3RvcnNdKGh0dHBzOi8vbGl2ZWJvb2subWFubmluZy5jb20jIS9ib29rL3ItaW4tYWN0aW9uLXNlY29uZC1lZGl0aW9uL2NoYXB0ZXItMi9wb2ludC0yNjI3LTI4LTM2LTApIGFyZSBvbmUtZGltZW5zaW9uYWwgYXJyYXlzIHRoYXQgY2FuIGhvbGQgbnVtZXJpYyBkYXRhLCBjaGFyYWN0ZXIgZGF0YSwgb3IgbG9naWNhbCBkYXRhLiBUaGUgY29tYmluZSBmdW5jdGlvbiBfX2MoLi4uKV9fIGlzIHVzZWQgdG8gZm9ybSB0aGUgdmVjdG9yLiAKYGBge3IgdmVjdG9yX2N9CmEgPC0gYygxLCAyLCA1LCAzLCA2LCAtMiwgMi4zKQphCgpiIDwtIGMoIm9uZSIsICJ0d28iLCAidGhyZWUiKQpiCgpjIDwtIGMoVFJVRSwgVFJVRSwgVFJVRSwgRkFMU0UsIFRSVUUsIEZBTFNFKQpjCgojIFdoYXQgaGFwcGVuIGlmIHdlIGNvbWJpbmUgZGlmZmVyZW50IHR5cGVzIG9mIGRhdGE/CmBgYAoKVmVjdG9ycyBtYXkgYWxzbyBiZSBnZW5lcmF0ZWQgdXNpbmcgdGhlIF9fc2VxKC4uLilfXyBmdW5jdGlvbiwgd2hlbiB5b3Ugd2FudCBhIHNlcXVlbmNlIG9mIG51bWJlcnMsIGV2ZW5seSBzcGFjZWQgYnkgYSBzcGVjaWZpZWQgaW50ZXJ2YWwuCmBgYHtyIHZlY3Rvcl9zZXF9CmQgPC0gc2VxKDMsIDExLCBieSA9IDAuNykKZAoKZGQgPC0gYygxOjQsIHNlcSgyLjEsIDQuNSwgYnkgPSAxLjEpKQpkZAoKIyBZb3UgY2FuIHVzZSBvcGVyYXRvcnMgKCssIC0sICosIC8sIGV0IGMuKSB0byBjcmVhdGUgdGhlIHZlY3RvcjsgdHJ5IHRoZW0uCmBgYAoKCllvdSBjYW4gcmVmZXIgdG8gZWxlbWVudHMgb2YgYSB2ZWN0b3IgdXNpbmcgYSBudW1lcmljIHZlY3RvciBvZiBwb3NpdGlvbnMgd2l0aGluIGJyYWNrZXRzLiBGb3IgZXhhbXBsZSwgYVtjKDIsIDQpXSByZWZlcnMgdG8gdGhlIHNlY29uZCBhbmQgZm91cnRoIGVsZW1lbnRzIG9mIHZlY3RvciBlLgpgYGB7ciB2ZWN0b3JfcmVmZXJ9CmUgPC0gYygiayIsICJqIiwgImgiLCAiYSIsICJjIiwgIm0iKQplWzNdCgplW2MoMSwgMywgNSldCgplWzI6Nl0KCiMgV2hhdCBoYXBwZW4gaWYgeW91IHVzZSBlW10/CmBgYAoKV2UgY2FuIGRvIG9wZXJhdGlvbnMgd2l0aCB2ZWN0b3JzLgpgYGB7ciB2ZWN0b3Jfb3Blcn0KZiA8LSBjKDEsIDIsIDMsIDUsIDcpCmcgPC0gYygyLCA0LCA2LCA4LCAxMCkKCmYgKyBnCgpmIC8gZwoKIyBXaGF0IGhhcHBlbiBpZiB2ZWN0b3JzIGFyZSBvZiBkaWZmZXJlbnQgbGVuZ3RoPwpgYGAKCioqKgoKIyMjIyBNYXRyaWNlcwpBIFttYXRyaXhdKCBodHRwczovL2xpdmVib29rLm1hbm5pbmcuY29tIyEvYm9vay9yLWluLWFjdGlvbi1zZWNvbmQtZWRpdGlvbi9jaGFwdGVyLTIvcG9pbnQtMjYyOC0zNy00Ni0wKSBpcyBhIHR3by1kaW1lbnNpb25hbCBhcnJheSBpbiB3aGljaCBlYWNoIGVsZW1lbnQgaGFzIHRoZSBzYW1lIG1vZGUgKG51bWVyaWMsIGNoYXJhY3Rlciwgb3IgbG9naWNhbCkuIE1hdHJpY2VzIGFyZSBjcmVhdGVkIHdpdGggdGhlIF9fbWF0cml4KClfXyBmdW5jdGlvbi4gVGhlIGdlbmVyYWwgZm9ybWF0IGlzOgoKPm15bWF0cml4IDwtIG1hdHJpeCh2ZWN0b3IsIG5yb3c9bnVtYmVyX29mX3Jvd3MsXCAKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7bmNvbD1udW1iZXJfb2ZfY29sdW1ucyxcCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwO2J5cm93PWxvZ2ljYWxfdmFsdWUsXAombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDtkaW1uYW1lcz1saXN0KGNoYXJfdmVjdG9yX3Jvd25hbWVzLFwKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Y2hhcl92ZWN0b3JfY29sbmFtZXMpKQoKYGBge3IgbWF0cml4fQp5IDwtIG1hdHJpeCgxOjIwLCBucm93PTUsIG5jb2w9NCkJCnkKIyBXaGF0IGhhcHBlbiBpZiB3ZSBhZGQgYnlyb3cgPSBUUlVFID8KCiMgWW91IGNhbiBwdXQgbmFtZXMgdG8gcm93cyBhbmQgY29sdW1uczoKY2VsbHMgICAgPC0gYygxLDI2LDI0LDY4LC0zLDAuMywxMTAsMTcsMikKcm5hbWVzICAgPC0gYygiUm93MSIsICJSb3cyIiwgIlJvdzMiKQpjbmFtZXMgICA8LSBjKCJDb2wxIiwgIkNvbDIiLCAiQ29sMyIpCm15bWF0cml4IDwtIG1hdHJpeChjZWxscywgbmNvbD0zLCBieXJvdz1UUlVFLAkKICAgICAgICAgICAgICAgICAgICAgZGltbmFtZXM9bGlzdChybmFtZXMsIGNuYW1lcykpCQpteW1hdHJpeAoKIyBNdWx0aXBseSBhIG1hdHJpeCBieSBhIHNjYWxhciAoZm9yIGV4YW1wbGUsIHRvIGNoYW5nZSB1bml0cykuCgojIENhbiB5b3UgZXh0cmFjdCBzcGVjaWZpYyBlbGVtZW50cyBvZiBhIG1hdHJpeD8gKExvb2sgYmFjayBpbiB2ZWN0b3JzLCBhbmQgdXNlIHRoZSBmb3JtYXQgW3Jvd3MsY29sdW1uc10pCgojIEEgbWF0cml4IGNhbiBiZSB0cmFuc3Bvc2VkIChyb3dzIDwtPiBjb2x1bW5zKSB1c2luZyB0KC4uLikKdG1hdHJpeCA8LSB0KG15bWF0cml4KQp0bWF0cml4CmBgYAoKKioqCgojIyMjIERhdGEgZnJhbWVzCkEgW2RhdGEgZnJhbWVdKGh0dHBzOi8vbGl2ZWJvb2subWFubmluZy5jb20jIS9ib29rL3ItaW4tYWN0aW9uLXNlY29uZC1lZGl0aW9uL2NoYXB0ZXItMi9wb2ludC0yNjMwLTUzLTgyLTApIGlzIG1vcmUgZ2VuZXJhbCB0aGFuIGEgbWF0cml4IGluIHRoYXQgZGlmZmVyZW50IGNvbHVtbnMgY2FuIGNvbnRhaW4gZGlmZmVyZW50IG1vZGVzIG9mIGRhdGEgKG51bWVyaWMsIGNoYXJhY3RlciwgYW5kIHNvIG9uKS4gRGF0YSBmcmFtZXMgYXJlIHRoZSBtb3N0IGNvbW1vbiBkYXRhIHN0cnVjdHVyZSB5b3XigJlsbCBkZWFsIHdpdGggaW4gUi4KQSBkYXRhIGZyYW1lIGlzIGNyZWF0ZWQgd2l0aCB0aGUgX19kYXRhLmZyYW1lKClfXyBmdW5jdGlvbjoKCj5teWRhdGEgPC0gZGF0YS5mcmFtZShjb2wxLCBjb2wyLCBjb2wzLC4uLikKCndoZXJlIGNvbDEsIGNvbDIsIGNvbDMsIGFuZCBzbyBvbiBhcmUgY29sdW1uIHZlY3RvcnMgb2YgYW55IHR5cGUgKHN1Y2ggYXMgY2hhcmFjdGVyLCBudW1lcmljLCBvciBsb2dpY2FsKS4gTmFtZXMgZm9yIGVhY2ggY29sdW1uIGNhbiBiZSBwcm92aWRlZCB3aXRoIHRoZSBfX25hbWVzX18gZnVuY3Rpb24uCgpgYGB7ciBkYXRhZnJhbWV9CiMgQ3JlYXRpbmcgYSBtYXRyaXggZnJvbSB2ZWN0b3JzOgpwYXRpZW50SUQgPC0gYygxLCAyLCAzLCA0KQphZ2UgPC0gYygyNSwgMzQsIDI4LCA1MikKZGlhYmV0ZXMgPC0gYygiVHlwZTEiLCAiVHlwZTIiLCAiVHlwZTEiLCAiVHlwZTEiKQpzdGF0dXMgPC0gYygiUG9vciIsICJJbXByb3ZlZCIsICJFeGNlbGxlbnQiLCAiUG9vciIpCnBhdGllbnRkYXRhIDwtIGRhdGEuZnJhbWUocGF0aWVudElELCBhZ2UsIGRpYWJldGVzLCBzdGF0dXMpCnBhdGllbnRkYXRhCgojIENoYW5naW5nIHRoZSBuYW1lcyBvZiB0aGUgY29sdW1uczoKbmV3cGF0aWVudGRhdGEgPC0gc2V0TmFtZXMocGF0aWVudGRhdGEsIGMoIklEIiwiZWRhZCIsIkRpYWJUIiwiRXN0YWRvIikpCm5ld3BhdGllbnRkYXRhCmBgYAoKVGhlcmUgYXJlIHNldmVyYWwgd2F5cyB0byBzZWxlY3QgdGhlIGVsZW1lbnRzIG9mIGEgZGF0YSBmcmFtZToKYGBge3IgZGF0YWZyYW1lX3NlbGVjdH0KIyBVc2luZyB0aGUgc3Vic2NyaXB0IG5vdGF0aW9uIChhcyBpbiBhIG1hdHJpeCk6CnNlbGVjdHBhdGllbnRkYXRhIDwtIHBhdGllbnRkYXRhWyAsMToyXSAgIyB0aGUgYmxhbmsgZm9yIHJvdyBpbmRleCBtZWFucyB0aGF0IGFsbCByb3dzIGFyZSBzZWxlY3RlZApzZWxlY3RwYXRpZW50ZGF0YQoKIyBVc2luZyB0aGUgY29sdW1ucycgbmFtZXM6CnNlbGVjdHBhdGllbnRkYXRhIDwtIHBhdGllbnRkYXRhWyxjKCJkaWFiZXRlcyIsICJzdGF0dXMiKV0Kc2VsZWN0cGF0aWVudGRhdGEKCiMgVXNpbmcgdGhlIG9iamVjdCR2YXJpYWJsZSBub3RhdGlvbjoKc2VsZWN0cGF0aWVudGRhdGEgPC0gcGF0aWVudGRhdGEkYWdlCnNlbGVjdHBhdGllbnRkYXRhICAgIyBOb3RlIHRoYXQgdGhlIG91dHB1dCBpcyBhIHZlY3RvcgpgYGAKCiMjIyMjIEZhY3RvcnMKQ2F0ZWdvcmljYWwgKG5vbWluYWwpIGFuZCBvcmRlcmVkIGNhdGVnb3JpY2FsIChvcmRpbmFsKSB2YXJpYWJsZXMgaW4gUiBhcmUgY2FsbGVkIFtmYWN0b3JzXShodHRwczovL2xpdmVib29rLm1hbm5pbmcuY29tIyEvYm9vay9yLWluLWFjdGlvbi1zZWNvbmQtZWRpdGlvbi9jaGFwdGVyLTIvcG9pbnQtMjYzMS04Ny0xMDYtMCkuIEZhY3RvcnMgYXJlIGNydWNpYWwgaW4gUiBiZWNhdXNlIHRoZXkgZGV0ZXJtaW5lIGhvdyBkYXRhIGlzIGFuYWx5emVkIGFuZCBwcmVzZW50ZWQgdmlzdWFsbHkuCgpXaXRoIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyB5b3UgY2FuIGNyZWF0ZSBjcm9zcy10YWJ1bGF0aW9ucywgdXNpbmcgdGhlIF9fdGFibGVfXyBmdW5jdGlvbjoKYGBge3IgY3Jvc3NfdGFifQp0YWJsZShwYXRpZW50ZGF0YSRkaWFiZXRlcywgcGF0aWVudGRhdGEkc3RhdHVzKQpgYGAKClRoZSBmdW5jdGlvbiBfX2ZhY3RvciguLi4pX18gc3RvcmVzIHRoZSBjYXRlZ29yaWNhbCB2YWx1ZXMgYXMgYSB2ZWN0b3Igb2YgaW50ZWdlcnMgYXNzb2NpYXRlZCB0byBlYWNoIGRpZmZlcmVudCB2YWx1ZSBvZiB0aGUgY2F0ZWdvcmljYWwgdmFyaWFibGUsIHRoaXMgaXMgdmVyeSBpbXBvcnRhbnQgZm9yIGRhdGEgYW5hbHlzaXM6IApgYGB7ciBmYWN0b3J9CnN0YXR1c2xldmVsIDwtIGZhY3RvcihzdGF0dXMpCnN0YXR1c2xldmVsCmFzLm51bWVyaWMoc3RhdHVzbGV2ZWwpCmBgYAoKKioqCgojIyMgRGF0YSBpbnB1dApSIHByb3ZpZGVzIGEgd2lkZSByYW5nZSBvZiB0b29scyBmb3IgaW1wb3J0aW5nIGRhdGEsIGFuZCBjcmVhdGUgZGF0YSBmcmFtZXMuIFRoZSBkZWZpbml0aXZlIGd1aWRlIGZvciBpbXBvcnRpbmcgZGF0YSBpbiBSIGlzIHRoZSBSIERhdGEgSW1wb3J0L0V4cG9ydCBtYW51YWwgYXZhaWxhYmxlIGF0IGh0dHA6Ly9tbmcuYnovdXJ3bi4gIApXZSBhcmUgY29uc2lkZXJpbmcgZm91ciB0b29scyB0byBpbnB1dCBkYXRhIGZvciBhbmFseXNlczoKCisgbWFudWFsbHkgKGFuZCBlZGl0aW5nKQorIHJlYWRpbmcgdGV4dCBmaWxlIHdpdGggY29tbWEgc2VwYXJhdGVkIHZhbHVlcyAocmVhZC5jc3YpCisgaW1wb3J0IEV4Y2VsIGZpbGVzIHVzaW5nIHRoZSAhW10oaW1wb3J0ZGF0YXNldC5wbmcpeyNpZCAuY2xhc3Mgd2lkdGg9MTAwIGhlaWdodD02MHB4fSBtZW51LCBpbiB0aGUgRW52aXJvbm1lbnQgdGFiICh1c3VhbGx5IHVwcGVyLXJpZ2h0IGNvbXBvbmVudCBvZiBSU3R1ZGlvKQorIGxvYWQgLlJkYXRhICgpIGZpbGVzIHVzaW5nIHRoZSBfX2xvYWRfXyBmdW5jdGlvbgoKT25jZSBjcmVhdGVkIGEgZGF0YSBmcmFtZSwgeW91IGNhbiBlZGl0IGl0IHVzaW5nIHRoZSBwYWNrYWdlIChyZWFsbHkgYW4gQWRkaW4pIFtfX2VkaXREYXRhX19dKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9lZGl0RGF0YS92aWduZXR0ZXMvZWRpdERhdGEuaHRtbCkuCgojIyMjIyBNYW51YWxseQpZb3UgY2FuIGVudGVyIChvciBwYXN0ZSkgZGF0YSBpbnRvIHRoZSBSU3R1ZGlvIHNjcmlwdCBlZGl0b3IgKG9yIGNodW5rKSB3aXRoIGNvbHVtbiBuYW1lcywgYW5kIHZhbHVlcyAobnVtZXJpYyBvZiBjaGFyYWN0ZXIpIGluIGEgdGFibGUgc3R5bGUgZm9ybWF0LCBhbmQgdXNpbmcgdGhlIGZvbGxvd2luZyBjb2RlOgpgYGB7ciBkYXRhaW5fTWFudWFsfQpteWRhdGEgPC0gcmVhZC50YWJsZShoZWFkZXI9VFJVRSwgdGV4dCA9ICIKYWdlIGdlbmRlciB3ZWlnaHQKMjUgbSAxNjYKMzAgZiAxMTUKMTggZiAxMjAKIikKbXlkYXRhCmBgYAoKIyMjIyMgUmVhZGluZyBDU1YgZmlsZXMKQ1NWIGZpbGVzIGFyZSB0ZXh0IGZpbGVzIHdoZXJlIHZhbHVlcyBpbiBlYWNoIGxpbmUgYXJlIHNlcGFyYXRlZCBieSBjb21tYXMgKGkuZS4gMSwyLDMsNSw3LDExKS4gIFRoZSBmaWxlIGNhbiBiZSBjcmVhdGVkIHdpdGggYW55IHRleHQgZWRpdG9yIG9yIGV4cG9ydGVkIGZyb20gYSBzcHJlYWRzaGVldCBhcHBsaWNhdGlvbiAoRXhjZWwsIGZvciBleGFtcGxlKS4gIFRvIHJlYWQgYSBDU1YgZmlsZSB1c2UgdGhlIGZvbGxvd2luZyBiYXNpYyBjb2RlOgpgYGB7ciBkYXRhaW5fY3N2fQpob25leW1vb25kYXRhIDwtIHJlYWQuY3N2KCdob25leW1vb24uY3N2JywgaGVhZGVyID0gVFJVRSkKaG9uZXltb29uZGF0YQpgYGAKCiMjIyMjIEltcG9ydCBkYXRhIGZyb20gRXhjZWwgZmlsZQpSU3R1ZGlvIHByb3ZpZGVzIGEgbWVudSBkcml2ZW4gdG9vbCB0byBpbXBvcnQgZGF0YSBmcm9tIGFuIEV4Y2VsIGZpbGUgKGFuZCBvdGhlciB0eXBlcywgdG9vKS4gIEl0IHJlcXVpcmVzIHRoYXQgeW91IGhhdmUgaW5zdGFsbGVkIGFuZCBhY3RpdmF0ZSB0aGUgX19yZWFkeGxfXyBwYWNrYWdlLiAgVXNlIHRoZSBtZW51IF9fSW1wb3J0IERhdGFzZXRfXywgc2VsZWN0IHRoZSBfRmlsZV8sIHNlbGVjdCB0aGUgX1NoZWV0XyB3aXRoIHRoZSBkYXRhIHlvdSBhcmUgaW50ZXJlc3RlZCBpbiwgYW5kIGNoZWNrIF9GaXJzdCBSb3cgYXMgTmFtZXNfIGlmIHRoYXQgaXMgdGhlIGNhc2UuCgohW10oaW1wb3J0ZXhjZWwucG5nKXsjaWQgLmNsYXNzIHdpZHRoPTUwMCBoZWlnaHQ9MzIwcHh9XAoKVGhlc2UgbWVudSBhY3Rpb25zIHdpbGwgZ2VuZXJhdGUgYSBjb2RlIHRoYXQgeW91IGNhbiB1c2UgaW5zaWRlIHlvdXIgcHJvY2VkdXJlLgpgYGB7ciBkYXRhaW5fZXhjZWx9CmxpYnJhcnkocmVhZHhsKQpob25leW1vb24gPC0gcmVhZF9leGNlbCgiaG9uZXltb29uLnhsc3giLCAKICAgIHNoZWV0ID0gIlNoZWV0MSIpClZpZXcoaG9uZXltb29uKQpgYGAKCiMjIyMjUmRhdGEgZmlsZXMKU2V2ZXJhbCBkYXRhIGZpbGVzIGNhbiBiZSBpbnRlZ3JhdGVkIGluIG9uZSBzeXN0ZW0gZmlsZSAoLlJkYXRhKSB1c2luZyB0aGUgX19zYXZlX18gZnVuY3Rpb24sCmBgYHtyIHNhdmVfcmRhdGF9CnNhdmUobXlkYXRhLCBob25leW1vb24sIGZpbGUgPSAicmZpbGUuUmRhdGEiKQpgYGAKYW5kIHVzZSB0aGVtIGFzIGlucHV0IGxhdGVyIHdpdGggdGhlIF9fbG9hZF9fIGZ1bmN0aW9uOgpgYGB7ciBsb2FkX3JkYXRhfQpsb2FkKCJyZmlsZS5SZGF0YSIpCm15ZGF0YQpob25leW1vb24KYGBgClBhY2tpbmcgYW5kIGxvYWRpbmcgdGhlIGRhdGEgaW4gUmRhdGEgbWF5IGJlIHVzZWZ1bCB3aGVuIHdvcmtpbmcgaW4gYSBwcm9qZWN0IHdpdGggc2V2ZXJhbCBkYXRhIGZyYW1lcywgYW5kIG5lZWQgdG8gZGlzdHJpYnV0ZSBhbmQgcmV1c2UgdGhlbSBlYXNpbHksIHByZXNlcnZpbmcgb3JpZ2luYWwgZGF0YSAobGlrZSB0ZWFjaGluZyBhIHdvcmtzaG9wISkuCgoqKioKCiMjI0Rlc2NyaXB0aXZlIFN0YXRpc3RpY3MKUiBoYXZlIGEgbGFyZ2UgbnVtYmVyIG9mIHdheXMgdG8gY2FsY3VsYXRlIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3Mgb24gdGhlIGRhdGFzZXRzLCBzb21lIGFyZSBpbmNsdWRlZCBpbiB0aGUgYmFzaWMgaW5zdGFsbGF0aW9uLCBhbmQgb3RoZXJzIGluIHBhY2thZ2VzIHRoYXQgbmVlZCBkb3dubG9hZC1pbnN0YWxsYXRpb24gKHVzaW5nIF9faW5zdGFsbC5wYWNrYWdlc19fKSBhbmQgbG9hZCAoYWN0aXZhdGlvbikgdG8gdGhlIGVudmlyb25tZW50ICh1c2luZyBfX2xpYnJhcnlfXykuCgojIyMjI1VzaW5nIHN1bW1hcnkKTGV0IHN0YXJ0IHVzaW5nIHRoZSBiYXNpYyBwcm9jZWR1cmVzIChmdW5jdGlvbiBfX3N1bW1hcnlfXyksIHdpdGggdGhlIFttdGNhcnNdKGh0dHBzOi8vc3RhdC5ldGh6LmNoL1ItbWFudWFsL1ItZGV2ZWwvbGlicmFyeS9kYXRhc2V0cy9odG1sL210Y2Fycy5odG1sKSBkYXRhc2V0IHByb3ZpZGVkIHdpdGggeW91ciBib29rJ3MgY29kZS4KYGBge3IgYmFzaWNfc3RhdHNfc3VtbWFyeX0KIyBjcmVhdGUgYSBkYXRhIGZyYW1lIHdpdGggdGhlIENTViBmaWxlIGFuZCBtYWtlIGl0IGF2YWlsYWJsZSBmb3IgdGhlIHByb2NlZHVyZQptdGNhcnMgPC0gcmVhZC5jc3YoIm10Y2Fycy5jc3YiKQojIGNyZWF0ZSBhIGxpc3Qgb2YgdmFyaWFibGVzIHRvIGFuYWx5emUKbXl2YXJzIDwtIGMoIm1wZyIsICJocCIsICJ3dCIpCgojIHVzZSBzdW1tYXJ5IHdpdGggdGhlIHNlbGVjdGVkIHZhcmlhYmxlcwpzdW1tYXJ5KG10Y2Fyc1tteXZhcnNdKQpgYGAKCiMjIyMjVXNpbmcgZnVuY3Rpb24gYW5kIHNhcHBseQpBIG1vcmUgZ2VuZXJhbCB3YXkgdG8gY2FsY3VsYXRlIGJhc2ljIHN0YXRpc3RpY3MgaXMgdXNpbmcgdGhlIF9fc2FwcGx5X18gcHJvY2VkdXJlLCB3aXRoIHRoZSBzeW50YXg6Cgo+c2FwcGx5KHgsIEZVTiwgb3B0aW9ucykpCgp3aGVyZSBfRlVOXyBpcyBhIHNpbXBsZSBzeXN0ZW0gZnVuY3Rpb24gKGxpa2UgbWVhbihfdmFyXyksIHNkKF92YXJfKSwgZXQgYy4pIG9yIGFuIHVzZXItZGVmaW5lZCBfX2Z1bmN0aW9uX18sIHdpdGggdGhlIGZvbGxvd2luZyBzeW50YXg6Cgo+bXlmdW5jdGlvbiA8LSBmdW5jdGlvbihhcmcxLCBhcmcyLCAuLi4gKXtcCnN0YXRlbWVudHNcCnJldHVybihvYmplY3QpXAp9CgpgYGB7ciBiYXNpY19zdGF0c19zYXBwbHlfZnVuY3Rpb259CiMgZGVmaW5pbmcgZnVuY3Rpb24KbXlzdGF0cyA8LSBmdW5jdGlvbih4KXsKICAgICAgICAgICAgICAgIG0gPC0gbWVhbih4KQogICAgICAgICAgICAgICAgbiA8LSBsZW5ndGgoeCkKICAgICAgICAgICAgICAgIHMgPC0gc2QoeCkKICAgICAgICAgICAgICAgIHNrZXcgPC0gc3VtKCh4LW0pXjMvc14zKS9uCiAgICAgICAgICAgICAgICBrdXJ0IDwtIHN1bSgoeC1tKV40L3NeNCkvbiAtIDMKICAgICAgICAgICAgICAgIHJldHVybihjKG49biwgbWVhbj1tLCBzdGRldj1zLCBza2V3PXNrZXcsIGt1cnRvc2lzPWt1cnQpKQp9CiMgYXJndW1lbnRzICh2YXJpYWJsZXMpIHRvIHVzZQpteXZhcnMgPC0gYygibXBnIiwgImhwIiwgInd0IikKIyBzYXBwbHkgZnVuY3Rpb24gb24gZGF0YXNldApzYXBwbHkobXRjYXJzW215dmFyc10sIG15c3RhdHMpCmBgYAoKIyMjIyNVc2luZyBhZ2dyZWdhdGUKV2hlbiB5b3UgaGF2ZSB2YXJpYWJsZXMgdGhhdCBjYW4gYmUgY29uc2lkZXJlZCBhcyBmYWN0b3IsIHlvdSBjYW4gdXNlIHRoZSBhZ2dyZWdhdGUgZnVuY3Rpb24gdG8gb2J0YWluIGJhc2ljIHN0YXRpc3RpY3MgYWdncmVnYXRpbmcgYnkgc3VjaCBmYWN0b3JzLiAgVGhlIGZ1bmN0aW9uIGhhcyB0aGUgZm9sbG93aW5nIHN5bnRheDoKCj5hZ2dyZWdhdGUoeCwgYnksIEZVTikKCmBgYHtyIGJhc2ljX3N0YXRzX2FnZ3JlZ2F0ZX0KI3JlYWQgZGF0YSBhbmQgYXR0YWNoIG9iamVjdCBmb3IgZWFzaWVyIHVzZSBvZiB0aGUgdmFyaWFibGVzCm10Y2FycyA8LSByZWFkLmNzdignbXRjYXJzLmNzdicpCmF0dGFjaChtdGNhcnMpCgojY2FsY3VsYXRlIHRoZSBtZWFuIG9mIG51bWVyaWMgdmFyaWFibGVzLCBhZ2dyZWdhdGVkIGJ5IGN5bCBhbmQgZ2VhciBhcyBmYWN0b3JzOyBtaXNzaW5nIHZhbHVlcyBhcmUgcmVtb3ZlZAphZ2dkYXRhIDwtIGFnZ3JlZ2F0ZShtdGNhcnNbYygnbXBnJywnaHAnLCd3dCcpXSwgYnk9bGlzdChjeWwsZ2VhciksIEZVTiA9IG1lYW4sIG5hLnJtID0gVFJVRSkKCiNzZXQgbmFtZXMgZm9yIHJlc3VsdGluZyBkYXRhIHRhYmxlIC0gd2hhdCBoYXBwZW4gaWYgd2Ugc2tpcCB0aGlzIGxpbmUgb2YgY29kZT8KYWdnZGF0YSA8LSBzZXROYW1lcyhhZ2dkYXRhLCBjKCJDWUwiLCJHRUFSIiwibXBnIiwiaHAiLCJ3dCIpKQoKYWdnZGF0YQpkZXRhY2gobXRjYXJzKSAgI3doeSBkZXRhY2g/CmBgYAoK