R features
Well-developed and effective programming
language – R is a simple yet powerful language specifically
designed for data analysis and statistical computing.
Efficient data handling and storage – R provides
robust structures for handling and storing large datasets
efficiently.
Rich set of operators – R includes a variety of
operators for performing calculations on arrays, lists, vectors, and
matrices.
Comprehensive tools for data analysis – R offers
numerous built-in functions and packages that support a wide range of
data analysis tasks.
Advanced graphical capabilities – R supports
both basic and advanced graphical techniques for data visualization,
aiding in better interpretation of results.
Extensive packages for advanced applications – R
has a vast collection of packages for data mining, machine learning, and
big data analytics, making it highly suitable for modern data science
workflows.
R Environment Workspace Description

R Script/File – This is where users write and
save their R code. It allows you to edit, run, and manage reusable
scripts for analysis and automation.
Environment – Displays the current workspace,
including all the variables, data frames, functions, and loaded objects
that are active in your session.
History – Keeps a record of all the R commands
executed during the session, allowing users to review and reuse previous
commands easily.
Console – The command-line interface where users
can directly enter and execute R commands and immediately see the output
or results.
Files – Provides access to the directory
structure of your computer so that you can browse, open, or manage files
and folders.
Plots – Displays visual output generated from
data visualizations, such as graphs and charts created using R’s
plotting functions.
Packages – Shows the list of R packages
installed and loaded in the session. Users can install new packages or
load/unload existing ones from here.
Help – Offers documentation and help for R
functions, packages, and commands. Users can search for and view
detailed descriptions, usage, and examples.
The step-by-step instructions to download and install R programming
and RStudio:
Step 1: Download and Install R
Go to the CRAN R Project Website https://cran.r-project.org ,
Choose your Operating System : Click on “Download R for Windows”,
“Download R for macOS”, or “Download R for Linux” depending on your
system.
Download the R Installer: For Windows: Click “base” > then
click “Download R x.x.x for Windows” (e.g., R 4.3.1). For macOS: Click
the link for the latest .pkg installer
Run the Installer: Open the downloaded file, Follow the
instructions to install R (default settings are usually fine)
Step 2: Download and Install RStudio
Go to the RStudio Website https://posit.co/download/rstudio-desktop/ ,Download
RStudio Desktop (Free).
Click on “Download RStudio Desktop for [Your OS]”. It will
redirect you to the appropriate installer for Windows, macOS, or
Linux
Install RStudio
Run the downloaded installer: Follow the on-screen
instructions.
Packages and Libraries
R provides access to a vast ecosystem of packages, with more than
7,769 packages available through CRAN (Comprehensive R Archive Network).
These packages extend R’s functionality and support a wide range of
tasks in data science and statistical computing. Some of the key
capabilities offered by R packages include:
Data visualization: Tools for creating charts,
graphs, and interactive plots (e.g., ggplot2, plotly).
Data statistics and exploration: Functions to
summarize, explore, and understand data distributions and
relationships.
Data transformation: Utilities for cleaning,
reshaping, and manipulating data (e.g., dplyr, tidyr).
Outlier detection: Methods for identifying and
handling anomalies in data.
Feature selection: Techniques to select important
variables that contribute most to prediction or classification.
Dimension reduction: Tools like PCA (Principal
Component Analysis) to reduce the number of variables while preserving
data structure.
Classification: Algorithms for supervised learning
and assigning data to categories (e.g., decision trees, SVM).
Clustering: Unsupervised learning techniques for
grouping similar data points (e.g., k-means, hierarchical
clustering).
Regression validation: Tools to evaluate the
performance of regression models.
Classification validation: Functions to assess
accuracy, precision, recall, and F1-score of classification models.
Clustering validation: Metrics to validate the
quality and effectiveness of clustering results (e.g., silhouette
score).
Installing and Loading Packages in R Using RStudio GUI
Open RStudio: Start by opening the RStudio application on your
computer.
Install a Package Using the GUI: Go to the “Packages” tab in the
bottom-right pane.
Click on the “Install” button (usually at the top left of the
“Packages” tab). A dialog box will appear. In the “Packages” field, type
the name of the package you want to install (e.g., ggplot2). Make sure
the checkbox “Install dependencies” is selected.
Click the “Install” button. RStudio will now download and install
the package from CRAN.
Load a Package Using the GUI: After installation, stay in the
“Packages” tab. Find the installed package in the list (e.g., ggplot2).
Tick the checkbox next to the package name to load it into your R
session.
Steps to Install and Load Packages in R
- Installing a Package: To install a package in R,
you use the install.packages() function. This step downloads the package
from CRAN and installs it on your system.
Example: install.packages(“ggplot2”)
This command installs the ggplot2 package, which is widely used for
data visualization.
- Loading a Package : Once a package is installed,
you need to load it into your current R session using the library( )
function.
Example: library(ggplot2)
This command loads the ggplot2 package so that you can use its
functions.
- Check if a Package is Already Installed : You can
check if a package is already installed using the require() function or
by checking the installed packages list.
Example: require(ggplot2)
If the package is not installed, require() will return FALSE.
- Install and Load Multiple Packages You can install
and load multiple packages using a vector and a loop.
Example:
packages <- c("dplyr", "tidyr", "ggplot2")
install.packages(packages) # Install all
lapply(packages, library, character.only = TRUE) # Load all
- Viewing Installed Packages : You can view all
installed packages using:
installed.packages()
- Update Packages (Optional) : To update all
installed packages:
update.packages()
Certainly! Here’s a detailed explanation of the basic data
types in R, with proper sentences and examples for each:
Basic Data Types in R
R is a powerful programming language used for statistical computing
and data analysis. It supports several basic data
types, which are fundamental for handling and manipulating
data. These data types include: numeric,
integer, complex, character
(string), and logical (boolean).
1. Numeric
- The numeric data type represents real
numbers (i.e., numbers with decimal points).
- It is the default type for numbers in R unless specified
otherwise.
Example:
x <- 3.14
class(x) # Output: "numeric"
[1] "numeric"
Here, x
is a numeric variable storing the value
3.14.
2. Integer
- An integer is a whole number (without a decimal
point).
- In R, you must use an
L
suffix to
explicitly define an integer.
Example:
y <- 10L
class(y) # Output: "integer"
[1] "integer"
The L
tells R to treat 10
as an integer
rather than a numeric (which would be a double).
3. Complex
- The complex data type represents complex
numbers, which have both a real and imaginary part (e.g., 1 +
2i).
- Useful in mathematical computations involving complex
arithmetic.
Example:
z <- 2 + 3i
class(z) # Output: "complex"
[1] "complex"
Here, z
is a complex number with a real part
2
and an imaginary part 3i
.
4. Character (String)
- The character data type is used to store
text or string values, such as words, phrases, or any
sequence of characters.
- Character data must be enclosed in either single
'
or
double "
quotes.
Example:
name <- "Srinivas"
class(name) # Output: "character"
[1] "character"
Here, "Srinivas"
is a character string.
5. Logical (Boolean)
- The logical data type stores TRUE
or FALSE values.
- This type is often used in conditions, comparisons, and filtering
data.
Example:
is_senior <- TRUE
class(is_senior) # Output: "logical"
[1] "logical"
age <- 25
age > 30 # Output: FALSE
[1] FALSE
Here, is_senior
is a logical variable. The expression
age > 30
also returns a logical value.
Summary Table
Numeric |
Decimal or floating-point numbers |
x <- 5.6 |
Integer |
Whole numbers with L suffix |
y <- 100L |
Complex |
Numbers with real + imaginary parts |
z <- 3 + 4i |
Character |
Text or strings |
name <- "R User" |
Logical |
Boolean values (TRUE or FALSE ) |
flag <- FALSE |
Arithmetic Operators in R
R provides a set of arithmetic operators that are used to perform
basic mathematical operations on numeric values, vectors, or variables.
These operators include addition,
subtraction, multiplication,
division, modulus, and
exponentiation.
1. Addition (+
)
The +
operator is used to add two or more numbers.
Example:
a <- 10
b <- 5
result <- a + b
print(result) # Output: 15
[1] 15
In this example, 10 and 5 are added to get 15.
2. Subtraction (-
)
The -
operator is used to subtract one number from
another.
Example:
a <- 10
b <- 5
result <- a - b
print(result) # Output: 5
[1] 5
Here, 5 is subtracted from 10 to get 5.
3. Multiplication (*
)
The *
operator is used to multiply numbers.
Example:
a <- 10
b <- 5
result <- a * b
print(result) # Output: 50
[1] 50
The multiplication of 10 and 5 results in 50.
4. Division (/
)
The /
operator is used to divide one number by
another.
Example:
a <- 10
b <- 5
result <- a / b
print(result) # Output: 2
[1] 2
Here, 10 divided by 5 gives the result 2.
5. Modulus (%%
)
The %%
operator gives the remainder
when one number is divided by another.
Example:
a <- 10
b <- 3
result <- a %% b
print(result) # Output: 1
[1] 1
When 10 is divided by 3, the remainder is 1.
6. Exponentiation (^
)
The ^
operator is used to raise a number to the power of
another.
Example:
a <- 2
b <- 3
result <- a ^ b
print(result) # Output: 8
[1] 8
In this case, 2 raised to the power of 3 equals 8.
Summary Table
+ |
Addition |
5 + 3 |
8 |
- |
Subtraction |
5 - 3 |
2 |
* |
Multiplication |
5 * 3 |
15 |
/ |
Division |
6 / 3 |
2 |
%% |
Modulus (remainder) |
10 %% 3 |
1 |
^ |
Exponentiation |
2 ^ 4 |
16 |
These arithmetic operators are frequently used in mathematical
computations, statistical analysis, and data manipulation tasks in
R.
Relational Operators in R
Relational operators in R are used to compare two values or
expressions. The result of a relational operation is always a
logical value: either TRUE
or
FALSE
. These are essential for decision-making and
conditional programming.
1. <
(Less than)
This operator checks whether the value on the left is less than the
value on the right.
Example:
a <- 10
b <- 20
c <- a < b
print(c) # Output: TRUE
[1] TRUE
Explanation: Since 10 is less than 20, the result is
TRUE
.
2. >
(Greater than)
Checks if the value on the left is greater than the value on the
right.
Example:
a <- 10
b <- 20
c <- a > b
print(c) # Output: FALSE
[1] FALSE
Explanation: 10 is not greater than 20, so the result is
FALSE
.
3. <=
(Less than or equal to)
Checks if the left-hand side is less than or equal to the right-hand
side.
Example:
a <- 10
b <- 10
c <- a <= b
print(c) # Output: TRUE
[1] TRUE
Explanation: 10 is equal to 10, so it satisfies the condition.
4. >=
(Greater than or equal to)
Checks if the value on the left is greater than or equal to the one
on the right.
Example:
a <- 15
b <- 10
c <- a >= b
print(c) # Output: TRUE
[1] TRUE
Explanation: 15 is greater than 10, so the result is
TRUE
.
5. ==
(Equal to)
Tests whether two values are equal.
Example:
a <- 10
b <- 10
c <- a == b
print(c) # Output: TRUE
[1] TRUE
Explanation: Both values are equal, so it returns
TRUE
.
6. !=
(Not equal to)
Checks if the two values are not equal.
Example:
a <- 10
b <- 20
c <- a != b
print(c) # Output: TRUE
[1] TRUE
Explanation: 10 and 20 are not equal, so the result is
TRUE
.
Summary Table
< |
Less than |
10 < 20 |
TRUE |
> |
Greater than |
10 > 20 |
FALSE |
<= |
Less than or equal to |
10 <= 10 |
TRUE |
>= |
Greater than or equal to |
15 >= 10 |
TRUE |
== |
Equal to |
10 == 10 |
TRUE |
!= |
Not equal to |
10 != 20 |
TRUE |
These relational operators are particularly useful in if-else
conditions, filtering data, and loop
control in R programming.
Logical Operators in R
Logical operators are used to combine or modify logical values
(TRUE
or FALSE
) in R. They are especially
useful in conditional statements, data
filtering, and vectorized operations.
1. !
(Logical NOT)
This operator reverses the logical state of its operand. If a
condition is TRUE
, applying !
will make it
FALSE
, and vice versa.
Example:
x <- TRUE
result <- !x
print(result) # Output: FALSE
[1] FALSE
Explanation: The value of x
is
TRUE
. The !
operator flips it to
FALSE
.
2. &
(Element-wise Logical AND)
This operator performs a logical AND element by
element on two logical vectors. It returns TRUE
if
both elements are TRUE
.
Example:
a <- c(TRUE, FALSE, TRUE)
b <- c(TRUE, TRUE, FALSE)
result <- a & b
print(result) # Output: TRUE FALSE FALSE
[1] TRUE FALSE FALSE
Explanation: It checks each corresponding pair:
TRUE & TRUE
→ TRUE
FALSE & TRUE
→ FALSE
TRUE & FALSE
→ FALSE
3. &&
(Logical AND – evaluates only first
element)
This operator also performs logical AND, but only on the
first element of each operand. It is often used in control
structures like if
statements.
Used for scalar (single logical) comparisons.
It only checks the first element of each logical vector.
If your vector has more than one element, you’ll get an error or
unexpected result.
Example:
a <- c(TRUE, FALSE)
b <- c(TRUE, TRUE)
result <- (a & b)
print(result) # Output: TRUE FALSE
[1] TRUE FALSE
a <- c(TRUE, FALSE)
b <- c(TRUE, TRUE)
result <- (a && b )
Error in a && b : 'length = 2' in coercion to 'logical(1)'
a <- c(TRUE, FALSE)
b <- c(TRUE, TRUE)
result <- (a[1] && b[1])
print(result) # Output: TRUE
[1] TRUE
Explanation: It checks only the first elements:
TRUE && TRUE
→ TRUE
4. |
(Element-wise Logical OR)
Performs logical OR element by element. It returns
TRUE
if either of the elements is
TRUE
.
Example:
a <- c(TRUE, FALSE, FALSE)
b <- c(FALSE, TRUE, FALSE)
result <- a | b
print(result) # Output: TRUE TRUE FALSE
[1] TRUE TRUE FALSE
Explanation:
TRUE | FALSE
→ TRUE
FALSE | TRUE
→ TRUE
FALSE | FALSE
→ FALSE
5. ||
(Logical OR – evaluates only first element)
This performs logical OR on only the first element
of the logical vectors.
Example:
a <- c(FALSE, FALSE)
b <- c(TRUE, FALSE)
result <- a || b
Error in a || b : 'length = 2' in coercion to 'logical(1)'
a <- c(FALSE, FALSE)
b <- c(TRUE, FALSE)
result <- a[1] || b[1]
print(result) # Output: TRUE
[1] TRUE
Explanation: It checks only the first elements:
FALSE || TRUE
→ TRUE
Summary Table
! |
Logical NOT |
Single value |
!TRUE |
FALSE |
|
|
|
|
& |
Element-wise AND |
Vectors |
c(TRUE, FALSE) & c(TRUE, TRUE) |
TRUE FALSE |
|
|
|
|
&& |
First-element AND |
Vectors |
c(TRUE, FALSE) && c(TRUE, TRUE) |
TRUE |
|
|
|
|
| |
Element-wise Logical OR |
Element-wise OR |
Vectors |
`c(FALSE, FALSE) |
c(TRUE, FALSE)` |
TRUE FALSE |
|
|
|| |
Logical OR |
First-element OR |
Vectors |
`c(FALSE, TRUE) |
|
c(TRUE, FALSE)` |
TRUE |
|
These logical operators are fundamental for filtering rows in
data frames, applying conditions, and
building control flows in R programming.
Certainly! Here’s a detailed explanation of Assignment
Operators in R with examples using proper sentences:
Assignment Operators in R
Assignment operators in R are used to assign values to variables. R
provides multiple ways to assign values, including leftward, rightward,
and equal sign assignments.
1. <-
(Leftward Assignment)
- Description: This is the most commonly used
assignment operator in R. It assigns a value to a variable by pointing
the arrow from the value to the variable.
- Example:
x <- 10
print(x)
[1] 10
- Explanation: The value
10
is assigned
to the variable x
. When you print x
, it
outputs 10
.
2. <<-
(Global or Upward Assignment)
- Description: This operator assigns a value to a
variable in a parent environment (used inside functions
to update global variables).
- Example:
updateVar <- function() {
y <<- 50
}
updateVar()
print(y)
[1] 50
- Explanation: The variable
y
is created
in the global environment even though it is assigned inside a function
using <<-
.
3. =
(Equal Sign Assignment)
- Description: It assigns a value just like
<-
, but it’s more commonly used when passing
arguments to functions.
- Example:
z = 20
print(z)
[1] 20
- Explanation: The value
20
is assigned
to the variable z
. Both <-
and
=
can be used for simple assignments, but
<-
is preferred in R programming style.
Summary Table
<- |
Local/Global |
General assignment |
a <- 5 |
<<- |
Parent/Global env |
Inside functions (global) |
x <<- 10 |
= |
Local |
Assign values or function args |
x = 20 |
Certainly! Here’s a detailed explanation of Functions in
R with proper structure, examples, and best practices:
FUNCTIONS IN R
What is a Function in R?
A function in R is a block of reusable code designed
to perform a specific task. R provides many built-in functions, and it
also allows users to define their own functions.
Why Use Functions?
- To avoid repetition of code
- To make code modular, clean, and readable
- To simplify debugging and testing
- To break complex problems into manageable parts
Syntax of a Function in R
function_name <- function(arg1, arg2, ...) {
# Code block
return(result)
}
Example: Simple Function in R
add_numbers <- function(a, b) {
result <- a + b
return(result)
}
add_numbers(5, 3)
[1] 8
Components of a Function
function_name |
Name of the function |
function() |
Keyword to define a function |
arguments |
Input values passed to the function |
return() |
Optional – returns output to the calling environment |
Body |
Block of code that defines what the function does |
Built-in Functions in R
R comes with many built-in functions:
sum() |
Calculates sum of values |
sum(c(1, 2, 3)) |
mean() |
Calculates average |
mean(c(4, 5, 6)) |
sqrt() |
Square root |
sqrt(25) |
length() |
Number of elements in a vector |
length(c(1,2,3)) |
User-defined Function with Default Values
greet <- function(name = "User") {
paste("Hello", name)
}
greet("Srinivas")
[1] "Hello Srinivas"
greet()
[1] "Hello User"
Function Without Return Statement
If return()
is not used, R will return the last
evaluated expression:
multiply <- function(a, b) {
a * b
}
multiply(4, 5)
[1] 20
Nested Function Example
outer <- function(x) {
inner <- function(y) {
return(y + 1)
}
return(inner(x) * 2)
}
outer(4) # returns (4+1)*2 = 10
[1] 10
Anonymous Functions (No Name)
sapply(c(1, 2, 3), function(x) x^2)
[1] 1 4 9
Variable Scope in Functions
Variables created inside a function are
local to that function:
myfunc <- function() {
x <- 10 # Local variable
print(x)
}
myfunc()
[1] 10
print(x) # Error: object 'x' not found
[1] 10
Summary Table
Built-in |
Predefined R functions |
sum() , mean() , sqrt() |
User-defined |
Functions created by users |
my_function <- function() {...} |
With defaults |
Functions with default argument vals |
greet <- function(name = "User") |
Anonymous |
Functions without name |
function(x) x+1 in sapply() |
LS0tDQp0aXRsZTogIkludHJvZHVjdGlvbiB0byBSIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyMgUiBmZWF0dXJlcw0KDQoxLiAqKldlbGwtZGV2ZWxvcGVkIGFuZCBlZmZlY3RpdmUgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UqKiDigJMgUiBpcyBhIHNpbXBsZSB5ZXQgcG93ZXJmdWwgbGFuZ3VhZ2Ugc3BlY2lmaWNhbGx5IGRlc2lnbmVkIGZvciBkYXRhIGFuYWx5c2lzIGFuZCBzdGF0aXN0aWNhbCBjb21wdXRpbmcuDQoNCjIuICoqRWZmaWNpZW50IGRhdGEgaGFuZGxpbmcgYW5kIHN0b3JhZ2UqKiDigJMgUiBwcm92aWRlcyByb2J1c3Qgc3RydWN0dXJlcyBmb3IgaGFuZGxpbmcgYW5kIHN0b3JpbmcgbGFyZ2UgZGF0YXNldHMgZWZmaWNpZW50bHkuDQoNCjMuICoqUmljaCBzZXQgb2Ygb3BlcmF0b3JzKiog4oCTIFIgaW5jbHVkZXMgYSB2YXJpZXR5IG9mIG9wZXJhdG9ycyBmb3IgcGVyZm9ybWluZyBjYWxjdWxhdGlvbnMgb24gYXJyYXlzLCBsaXN0cywgdmVjdG9ycywgYW5kIG1hdHJpY2VzLg0KDQo0LiAqKkNvbXByZWhlbnNpdmUgdG9vbHMgZm9yIGRhdGEgYW5hbHlzaXMqKiDigJMgUiBvZmZlcnMgbnVtZXJvdXMgYnVpbHQtaW4gZnVuY3Rpb25zIGFuZCBwYWNrYWdlcyB0aGF0IHN1cHBvcnQgYSB3aWRlIHJhbmdlIG9mIGRhdGEgYW5hbHlzaXMgdGFza3MuDQoNCjUuICoqQWR2YW5jZWQgZ3JhcGhpY2FsIGNhcGFiaWxpdGllcyoqIOKAkyBSIHN1cHBvcnRzIGJvdGggYmFzaWMgYW5kIGFkdmFuY2VkIGdyYXBoaWNhbCB0ZWNobmlxdWVzIGZvciBkYXRhIHZpc3VhbGl6YXRpb24sIGFpZGluZyBpbiBiZXR0ZXIgaW50ZXJwcmV0YXRpb24gb2YgcmVzdWx0cy4NCg0KNi4gKipFeHRlbnNpdmUgcGFja2FnZXMgZm9yIGFkdmFuY2VkIGFwcGxpY2F0aW9ucyoqIOKAkyBSIGhhcyBhIHZhc3QgY29sbGVjdGlvbiBvZiBwYWNrYWdlcyBmb3IgZGF0YSBtaW5pbmcsIG1hY2hpbmUgbGVhcm5pbmcsIGFuZCBiaWcgZGF0YSBhbmFseXRpY3MsIG1ha2luZyBpdCBoaWdobHkgc3VpdGFibGUgZm9yIG1vZGVybiBkYXRhIHNjaWVuY2Ugd29ya2Zsb3dzLg0KDQoNCiMjIFIgRW52aXJvbm1lbnQgV29ya3NwYWNlIERlc2NyaXB0aW9uDQoNCjxkaXYgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsiPg0KICA8aW1nIHNyYz0iUiBFbnZpcm9ubWVudC5KUEciIGFsdD0iRmlndXJlOiBSIEVudmlyb25tZW50IFdvcmtzcGFjZSIgd2lkdGg9IjcwJSI+DQo8L2Rpdj4NCg0KDQoxLiAqKlIgU2NyaXB0L0ZpbGUqKiDigJMgVGhpcyBpcyB3aGVyZSB1c2VycyB3cml0ZSBhbmQgc2F2ZSB0aGVpciBSIGNvZGUuIEl0IGFsbG93cyB5b3UgdG8gZWRpdCwgcnVuLCBhbmQgbWFuYWdlIHJldXNhYmxlIHNjcmlwdHMgZm9yIGFuYWx5c2lzIGFuZCBhdXRvbWF0aW9uLg0KDQoyLiAqKkVudmlyb25tZW50Kiog4oCTIERpc3BsYXlzIHRoZSBjdXJyZW50IHdvcmtzcGFjZSwgaW5jbHVkaW5nIGFsbCB0aGUgdmFyaWFibGVzLCBkYXRhIGZyYW1lcywgZnVuY3Rpb25zLCBhbmQgbG9hZGVkIG9iamVjdHMgdGhhdCBhcmUgYWN0aXZlIGluIHlvdXIgc2Vzc2lvbi4NCg0KMy4gKipIaXN0b3J5Kiog4oCTIEtlZXBzIGEgcmVjb3JkIG9mIGFsbCB0aGUgUiBjb21tYW5kcyBleGVjdXRlZCBkdXJpbmcgdGhlIHNlc3Npb24sIGFsbG93aW5nIHVzZXJzIHRvIHJldmlldyBhbmQgcmV1c2UgcHJldmlvdXMgY29tbWFuZHMgZWFzaWx5Lg0KDQo0LiAqKkNvbnNvbGUqKiDigJMgVGhlIGNvbW1hbmQtbGluZSBpbnRlcmZhY2Ugd2hlcmUgdXNlcnMgY2FuIGRpcmVjdGx5IGVudGVyIGFuZCBleGVjdXRlIFIgY29tbWFuZHMgYW5kIGltbWVkaWF0ZWx5IHNlZSB0aGUgb3V0cHV0IG9yIHJlc3VsdHMuDQoNCjUuICoqRmlsZXMqKiDigJMgUHJvdmlkZXMgYWNjZXNzIHRvIHRoZSBkaXJlY3Rvcnkgc3RydWN0dXJlIG9mIHlvdXIgY29tcHV0ZXIgc28gdGhhdCB5b3UgY2FuIGJyb3dzZSwgb3Blbiwgb3IgbWFuYWdlIGZpbGVzIGFuZCBmb2xkZXJzLg0KDQo2LiAqKlBsb3RzKiog4oCTIERpc3BsYXlzIHZpc3VhbCBvdXRwdXQgZ2VuZXJhdGVkIGZyb20gZGF0YSB2aXN1YWxpemF0aW9ucywgc3VjaCBhcyBncmFwaHMgYW5kIGNoYXJ0cyBjcmVhdGVkIHVzaW5nIFIncyBwbG90dGluZyBmdW5jdGlvbnMuDQoNCjcuICoqUGFja2FnZXMqKiDigJMgU2hvd3MgdGhlIGxpc3Qgb2YgUiBwYWNrYWdlcyBpbnN0YWxsZWQgYW5kIGxvYWRlZCBpbiB0aGUgc2Vzc2lvbi4gVXNlcnMgY2FuIGluc3RhbGwgbmV3IHBhY2thZ2VzIG9yIGxvYWQvdW5sb2FkIGV4aXN0aW5nIG9uZXMgZnJvbSBoZXJlLg0KDQo4LiAqKkhlbHAqKiDigJMgT2ZmZXJzIGRvY3VtZW50YXRpb24gYW5kIGhlbHAgZm9yIFIgZnVuY3Rpb25zLCBwYWNrYWdlcywgYW5kIGNvbW1hbmRzLiBVc2VycyBjYW4gc2VhcmNoIGZvciBhbmQgdmlldyBkZXRhaWxlZCBkZXNjcmlwdGlvbnMsIHVzYWdlLCBhbmQgZXhhbXBsZXMuDQoNCiMjIFRoZSBzdGVwLWJ5LXN0ZXAgaW5zdHJ1Y3Rpb25zIHRvIGRvd25sb2FkIGFuZCBpbnN0YWxsIFIgcHJvZ3JhbW1pbmcgYW5kIFJTdHVkaW86DQoNCioqU3RlcCAxOiBEb3dubG9hZCBhbmQgSW5zdGFsbCBSKioNCg0KMS4gR28gdG8gdGhlIENSQU4gUiBQcm9qZWN0IFdlYnNpdGUgaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcgLCANCg0KMi4gQ2hvb3NlIHlvdXIgT3BlcmF0aW5nIFN5c3RlbSA6IENsaWNrIG9uICJEb3dubG9hZCBSIGZvciBXaW5kb3dzIiwgIkRvd25sb2FkIFIgZm9yIG1hY09TIiwgb3IgIkRvd25sb2FkIFIgZm9yIExpbnV4IiBkZXBlbmRpbmcgb24geW91ciBzeXN0ZW0uDQoNCjMuIERvd25sb2FkIHRoZSBSIEluc3RhbGxlcjogIEZvciBXaW5kb3dzOiBDbGljayAiYmFzZSIgPiB0aGVuIGNsaWNrICJEb3dubG9hZCBSIHgueC54IGZvciBXaW5kb3dzIiAoZS5nLiwgUiA0LjMuMSkuIEZvciBtYWNPUzogQ2xpY2sgdGhlIGxpbmsgZm9yIHRoZSBsYXRlc3QgLnBrZyBpbnN0YWxsZXINCg0KNC4gUnVuIHRoZSBJbnN0YWxsZXI6IE9wZW4gdGhlIGRvd25sb2FkZWQgZmlsZSwgRm9sbG93IHRoZSBpbnN0cnVjdGlvbnMgdG8gaW5zdGFsbCBSIChkZWZhdWx0IHNldHRpbmdzIGFyZSB1c3VhbGx5IGZpbmUpDQoNCioqU3RlcCAyOiBEb3dubG9hZCBhbmQgSW5zdGFsbCBSU3R1ZGlvKioNCg0KMS4gR28gdG8gdGhlIFJTdHVkaW8gV2Vic2l0ZSBodHRwczovL3Bvc2l0LmNvL2Rvd25sb2FkL3JzdHVkaW8tZGVza3RvcC8gLERvd25sb2FkIFJTdHVkaW8gRGVza3RvcCAoRnJlZSkuIA0KDQoyLiBDbGljayBvbiAiRG93bmxvYWQgUlN0dWRpbyBEZXNrdG9wIGZvciBbWW91ciBPU10iLiBJdCB3aWxsIHJlZGlyZWN0IHlvdSB0byB0aGUgYXBwcm9wcmlhdGUgaW5zdGFsbGVyIGZvciBXaW5kb3dzLCBtYWNPUywgb3IgTGludXgNCg0KMy4gSW5zdGFsbCBSU3R1ZGlvDQoNCjQuIFJ1biB0aGUgZG93bmxvYWRlZCBpbnN0YWxsZXI6IEZvbGxvdyB0aGUgb24tc2NyZWVuIGluc3RydWN0aW9ucy4NCg0KIyMgUGFja2FnZXMgYW5kIExpYnJhcmllcw0KDQpSIHByb3ZpZGVzIGFjY2VzcyB0byBhIHZhc3QgZWNvc3lzdGVtIG9mIHBhY2thZ2VzLCB3aXRoIG1vcmUgdGhhbiA3LDc2OSBwYWNrYWdlcyBhdmFpbGFibGUgdGhyb3VnaCBDUkFOIChDb21wcmVoZW5zaXZlIFIgQXJjaGl2ZSBOZXR3b3JrKS4gVGhlc2UgcGFja2FnZXMgZXh0ZW5kIFLigJlzIGZ1bmN0aW9uYWxpdHkgYW5kIHN1cHBvcnQgYSB3aWRlIHJhbmdlIG9mIHRhc2tzIGluIGRhdGEgc2NpZW5jZSBhbmQgc3RhdGlzdGljYWwgY29tcHV0aW5nLiBTb21lIG9mIHRoZSBrZXkgY2FwYWJpbGl0aWVzIG9mZmVyZWQgYnkgUiBwYWNrYWdlcyBpbmNsdWRlOg0KDQoqKkRhdGEgdmlzdWFsaXphdGlvbjoqKiBUb29scyBmb3IgY3JlYXRpbmcgY2hhcnRzLCBncmFwaHMsIGFuZCBpbnRlcmFjdGl2ZSBwbG90cyAoZS5nLiwgZ2dwbG90MiwgcGxvdGx5KS4NCg0KKipEYXRhIHN0YXRpc3RpY3MgYW5kIGV4cGxvcmF0aW9uOioqIEZ1bmN0aW9ucyB0byBzdW1tYXJpemUsIGV4cGxvcmUsIGFuZCB1bmRlcnN0YW5kIGRhdGEgZGlzdHJpYnV0aW9ucyBhbmQgcmVsYXRpb25zaGlwcy4NCg0KKipEYXRhIHRyYW5zZm9ybWF0aW9uOioqIFV0aWxpdGllcyBmb3IgY2xlYW5pbmcsIHJlc2hhcGluZywgYW5kIG1hbmlwdWxhdGluZyBkYXRhIChlLmcuLCBkcGx5ciwgdGlkeXIpLg0KDQoqKk91dGxpZXIgZGV0ZWN0aW9uOioqIE1ldGhvZHMgZm9yIGlkZW50aWZ5aW5nIGFuZCBoYW5kbGluZyBhbm9tYWxpZXMgaW4gZGF0YS4NCg0KKipGZWF0dXJlIHNlbGVjdGlvbjoqKiBUZWNobmlxdWVzIHRvIHNlbGVjdCBpbXBvcnRhbnQgdmFyaWFibGVzIHRoYXQgY29udHJpYnV0ZSBtb3N0IHRvIHByZWRpY3Rpb24gb3IgY2xhc3NpZmljYXRpb24uDQoNCioqRGltZW5zaW9uIHJlZHVjdGlvbjoqKiBUb29scyBsaWtlIFBDQSAoUHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpcykgdG8gcmVkdWNlIHRoZSBudW1iZXIgb2YgdmFyaWFibGVzIHdoaWxlIHByZXNlcnZpbmcgZGF0YSBzdHJ1Y3R1cmUuDQoNCioqQ2xhc3NpZmljYXRpb246KiogQWxnb3JpdGhtcyBmb3Igc3VwZXJ2aXNlZCBsZWFybmluZyBhbmQgYXNzaWduaW5nIGRhdGEgdG8gY2F0ZWdvcmllcyAoZS5nLiwgZGVjaXNpb24gdHJlZXMsIFNWTSkuDQoNCioqQ2x1c3RlcmluZzoqKiBVbnN1cGVydmlzZWQgbGVhcm5pbmcgdGVjaG5pcXVlcyBmb3IgZ3JvdXBpbmcgc2ltaWxhciBkYXRhIHBvaW50cyAoZS5nLiwgay1tZWFucywgaGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcpLg0KDQoqKlJlZ3Jlc3Npb24gdmFsaWRhdGlvbjoqKiBUb29scyB0byBldmFsdWF0ZSB0aGUgcGVyZm9ybWFuY2Ugb2YgcmVncmVzc2lvbiBtb2RlbHMuDQoNCioqQ2xhc3NpZmljYXRpb24gdmFsaWRhdGlvbjoqKiBGdW5jdGlvbnMgdG8gYXNzZXNzIGFjY3VyYWN5LCBwcmVjaXNpb24sIHJlY2FsbCwgYW5kIEYxLXNjb3JlIG9mIGNsYXNzaWZpY2F0aW9uIG1vZGVscy4NCg0KKipDbHVzdGVyaW5nIHZhbGlkYXRpb246KiogTWV0cmljcyB0byB2YWxpZGF0ZSB0aGUgcXVhbGl0eSBhbmQgZWZmZWN0aXZlbmVzcyBvZiBjbHVzdGVyaW5nIHJlc3VsdHMgKGUuZy4sIHNpbGhvdWV0dGUgc2NvcmUpLg0KDQojIyBJbnN0YWxsaW5nIGFuZCBMb2FkaW5nIFBhY2thZ2VzIGluIFIgVXNpbmcgUlN0dWRpbyBHVUkgDQoNCjxkaXYgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsiPg0KICA8aW1nIHNyYz0iSW5zdGFsbGluZyBwYWNrYWdlIGluIFJfYi5KUEciIGFsdD0iRmlndXJlOiBJbnN0YWxsaW5nIGFuZCBMb2FkaW5nIFBhY2thZ2VzIGluIFIiIHdpZHRoPSI2MCUiPg0KPC9kaXY+DQoNCg0KMS4gT3BlbiBSU3R1ZGlvOiBTdGFydCBieSBvcGVuaW5nIHRoZSBSU3R1ZGlvIGFwcGxpY2F0aW9uIG9uIHlvdXIgY29tcHV0ZXIuDQoNCjIuIEluc3RhbGwgYSBQYWNrYWdlIFVzaW5nIHRoZSBHVUk6IEdvIHRvIHRoZSAiUGFja2FnZXMiIHRhYiBpbiB0aGUgYm90dG9tLXJpZ2h0IHBhbmUuDQoNCjMuIENsaWNrIG9uIHRoZSAiSW5zdGFsbCIgYnV0dG9uICh1c3VhbGx5IGF0IHRoZSB0b3AgbGVmdCBvZiB0aGUgIlBhY2thZ2VzIiB0YWIpLiBBIGRpYWxvZyBib3ggd2lsbCBhcHBlYXIuIEluIHRoZSAiUGFja2FnZXMiIGZpZWxkLCB0eXBlIHRoZSBuYW1lIG9mIHRoZSBwYWNrYWdlIHlvdSB3YW50IHRvIGluc3RhbGwgKGUuZy4sIGdncGxvdDIpLiBNYWtlIHN1cmUgdGhlIGNoZWNrYm94ICJJbnN0YWxsIGRlcGVuZGVuY2llcyIgaXMgc2VsZWN0ZWQuDQoNCjQuIENsaWNrIHRoZSAiSW5zdGFsbCIgYnV0dG9uLiBSU3R1ZGlvIHdpbGwgbm93IGRvd25sb2FkIGFuZCBpbnN0YWxsIHRoZSBwYWNrYWdlIGZyb20gQ1JBTi4NCg0KNS4gTG9hZCBhIFBhY2thZ2UgVXNpbmcgdGhlIEdVSTogQWZ0ZXIgaW5zdGFsbGF0aW9uLCBzdGF5IGluIHRoZSAiUGFja2FnZXMiIHRhYi4gRmluZCB0aGUgaW5zdGFsbGVkIHBhY2thZ2UgaW4gdGhlIGxpc3QgKGUuZy4sIGdncGxvdDIpLiBUaWNrIHRoZSBjaGVja2JveCBuZXh0IHRvIHRoZSBwYWNrYWdlIG5hbWUgdG8gbG9hZCBpdCBpbnRvIHlvdXIgUiBzZXNzaW9uLg0KDQoNCiMjIFN0ZXBzIHRvIEluc3RhbGwgYW5kIExvYWQgUGFja2FnZXMgaW4gUg0KDQoxLiAqKkluc3RhbGxpbmcgYSBQYWNrYWdlKio6IFRvIGluc3RhbGwgYSBwYWNrYWdlIGluIFIsIHlvdSB1c2UgdGhlIGluc3RhbGwucGFja2FnZXMoKSBmdW5jdGlvbi4gVGhpcyBzdGVwIGRvd25sb2FkcyB0aGUgcGFja2FnZSBmcm9tIENSQU4gYW5kIGluc3RhbGxzIGl0IG9uIHlvdXIgc3lzdGVtLg0KDQoqKkV4YW1wbGU6KiogIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KDQpUaGlzIGNvbW1hbmQgaW5zdGFsbHMgdGhlIGdncGxvdDIgcGFja2FnZSwgd2hpY2ggaXMgd2lkZWx5IHVzZWQgZm9yIGRhdGEgdmlzdWFsaXphdGlvbi4NCg0KMi4gKipMb2FkaW5nIGEgUGFja2FnZSoqIDogT25jZSBhIHBhY2thZ2UgaXMgaW5zdGFsbGVkLCB5b3UgbmVlZCB0byBsb2FkIGl0IGludG8geW91ciBjdXJyZW50IFIgc2Vzc2lvbiB1c2luZyB0aGUgbGlicmFyeSggKSBmdW5jdGlvbi4NCg0KRXhhbXBsZTogbGlicmFyeShnZ3Bsb3QyKQ0KDQpUaGlzIGNvbW1hbmQgbG9hZHMgdGhlIGdncGxvdDIgcGFja2FnZSBzbyB0aGF0IHlvdSBjYW4gdXNlIGl0cyBmdW5jdGlvbnMuDQoNCjMuICoqQ2hlY2sgaWYgYSBQYWNrYWdlIGlzIEFscmVhZHkgSW5zdGFsbGVkKiogOiANCllvdSBjYW4gY2hlY2sgaWYgYSBwYWNrYWdlIGlzIGFscmVhZHkgaW5zdGFsbGVkIHVzaW5nIHRoZSByZXF1aXJlKCkgZnVuY3Rpb24gb3IgYnkgY2hlY2tpbmcgdGhlIGluc3RhbGxlZCBwYWNrYWdlcyBsaXN0Lg0KDQpFeGFtcGxlOiByZXF1aXJlKGdncGxvdDIpDQoNCklmIHRoZSBwYWNrYWdlIGlzIG5vdCBpbnN0YWxsZWQsIHJlcXVpcmUoKSB3aWxsIHJldHVybiBGQUxTRS4NCg0KNC4gKipJbnN0YWxsIGFuZCBMb2FkIE11bHRpcGxlIFBhY2thZ2VzKiogDQpZb3UgY2FuIGluc3RhbGwgYW5kIGxvYWQgbXVsdGlwbGUgcGFja2FnZXMgdXNpbmcgYSB2ZWN0b3IgYW5kIGEgbG9vcC4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KcGFja2FnZXMgPC0gYygiZHBseXIiLCAidGlkeXIiLCAiZ2dwbG90MiIpDQoNCmluc3RhbGwucGFja2FnZXMocGFja2FnZXMpICAgIyBJbnN0YWxsIGFsbA0KDQpsYXBwbHkocGFja2FnZXMsIGxpYnJhcnksIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkgICMgTG9hZCBhbGwNCmBgYA0KDQoNCjUuICoqVmlld2luZyBJbnN0YWxsZWQgUGFja2FnZXMqKiA6IA0KWW91IGNhbiB2aWV3IGFsbCBpbnN0YWxsZWQgcGFja2FnZXMgdXNpbmc6DQoNCmBgYHtyfQ0KaW5zdGFsbGVkLnBhY2thZ2VzKCkNCmBgYA0KDQoNCjYuICoqVXBkYXRlIFBhY2thZ2VzIChPcHRpb25hbCkqKiA6IA0KVG8gdXBkYXRlIGFsbCBpbnN0YWxsZWQgcGFja2FnZXM6DQoNCmBgYHtyfQ0KdXBkYXRlLnBhY2thZ2VzKCkNCmBgYA0KDQoNCg0KQ2VydGFpbmx5ISBIZXJlJ3MgYSBkZXRhaWxlZCBleHBsYW5hdGlvbiBvZiB0aGUgKipiYXNpYyBkYXRhIHR5cGVzIGluIFIqKiwgd2l0aCBwcm9wZXIgc2VudGVuY2VzIGFuZCBleGFtcGxlcyBmb3IgZWFjaDoNCg0KLS0tDQoNCiMjICAqKkJhc2ljIERhdGEgVHlwZXMgaW4gUioqDQoNClIgaXMgYSBwb3dlcmZ1bCBwcm9ncmFtbWluZyBsYW5ndWFnZSB1c2VkIGZvciBzdGF0aXN0aWNhbCBjb21wdXRpbmcgYW5kIGRhdGEgYW5hbHlzaXMuIEl0IHN1cHBvcnRzIHNldmVyYWwgKipiYXNpYyBkYXRhIHR5cGVzKiosIHdoaWNoIGFyZSBmdW5kYW1lbnRhbCBmb3IgaGFuZGxpbmcgYW5kIG1hbmlwdWxhdGluZyBkYXRhLiBUaGVzZSBkYXRhIHR5cGVzIGluY2x1ZGU6ICoqbnVtZXJpYyoqLCAqKmludGVnZXIqKiwgKipjb21wbGV4KiosICoqY2hhcmFjdGVyIChzdHJpbmcpKiosIGFuZCAqKmxvZ2ljYWwgKGJvb2xlYW4pKiouDQoNCi0tLQ0KDQojIyMgMS4gICoqTnVtZXJpYyoqDQoNCiogVGhlICoqbnVtZXJpYyoqIGRhdGEgdHlwZSByZXByZXNlbnRzICoqcmVhbCBudW1iZXJzKiogKGkuZS4sIG51bWJlcnMgd2l0aCBkZWNpbWFsIHBvaW50cykuDQoqIEl0IGlzIHRoZSBkZWZhdWx0IHR5cGUgZm9yIG51bWJlcnMgaW4gUiB1bmxlc3Mgc3BlY2lmaWVkIG90aGVyd2lzZS4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KeCA8LSAzLjE0DQpjbGFzcyh4KSAgIyBPdXRwdXQ6ICJudW1lcmljIg0KYGBgDQoNCg0KSGVyZSwgYHhgIGlzIGEgbnVtZXJpYyB2YXJpYWJsZSBzdG9yaW5nIHRoZSB2YWx1ZSAzLjE0Lg0KDQotLS0NCg0KIyMjIDIuICAqKkludGVnZXIqKg0KDQoqIEFuICoqaW50ZWdlcioqIGlzIGEgd2hvbGUgbnVtYmVyICh3aXRob3V0IGEgZGVjaW1hbCBwb2ludCkuDQoqIEluIFIsIHlvdSBtdXN0IHVzZSBhbiAqKmBMYCBzdWZmaXgqKiB0byBleHBsaWNpdGx5IGRlZmluZSBhbiBpbnRlZ2VyLg0KDQoqKkV4YW1wbGU6KioNCg0KYGBge3J9DQp5IDwtIDEwTA0KY2xhc3MoeSkgICMgT3V0cHV0OiAiaW50ZWdlciINCmBgYA0KDQoNClRoZSBgTGAgdGVsbHMgUiB0byB0cmVhdCBgMTBgIGFzIGFuIGludGVnZXIgcmF0aGVyIHRoYW4gYSBudW1lcmljICh3aGljaCB3b3VsZCBiZSBhIGRvdWJsZSkuDQoNCi0tLQ0KDQojIyMgMy4gKipDb21wbGV4KioNCg0KKiBUaGUgKipjb21wbGV4KiogZGF0YSB0eXBlIHJlcHJlc2VudHMgKipjb21wbGV4IG51bWJlcnMqKiwgd2hpY2ggaGF2ZSBib3RoIGEgcmVhbCBhbmQgaW1hZ2luYXJ5IHBhcnQgKGUuZy4sIDEgKyAyaSkuDQoqIFVzZWZ1bCBpbiBtYXRoZW1hdGljYWwgY29tcHV0YXRpb25zIGludm9sdmluZyBjb21wbGV4IGFyaXRobWV0aWMuDQoNCioqRXhhbXBsZToqKg0KDQpgYGB7cn0NCnogPC0gMiArIDNpDQpjbGFzcyh6KSAgIyBPdXRwdXQ6ICJjb21wbGV4Ig0KYGBgDQoNCg0KSGVyZSwgYHpgIGlzIGEgY29tcGxleCBudW1iZXIgd2l0aCBhIHJlYWwgcGFydCBgMmAgYW5kIGFuIGltYWdpbmFyeSBwYXJ0IGAzaWAuDQoNCi0tLQ0KDQojIyMgNC4gICoqQ2hhcmFjdGVyIChTdHJpbmcpKioNCg0KKiBUaGUgKipjaGFyYWN0ZXIqKiBkYXRhIHR5cGUgaXMgdXNlZCB0byBzdG9yZSAqKnRleHQgb3Igc3RyaW5nIHZhbHVlcyoqLCBzdWNoIGFzIHdvcmRzLCBwaHJhc2VzLCBvciBhbnkgc2VxdWVuY2Ugb2YgY2hhcmFjdGVycy4NCiogQ2hhcmFjdGVyIGRhdGEgbXVzdCBiZSBlbmNsb3NlZCBpbiBlaXRoZXIgc2luZ2xlIGAnYCBvciBkb3VibGUgYCJgIHF1b3Rlcy4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KbmFtZSA8LSAiU3Jpbml2YXMiDQpjbGFzcyhuYW1lKSAgIyBPdXRwdXQ6ICJjaGFyYWN0ZXIiDQpgYGANCg0KDQpIZXJlLCBgIlNyaW5pdmFzImAgaXMgYSBjaGFyYWN0ZXIgc3RyaW5nLg0KDQotLS0NCg0KIyMjIDUuICoqTG9naWNhbCAoQm9vbGVhbikqKg0KDQoqIFRoZSAqKmxvZ2ljYWwqKiBkYXRhIHR5cGUgc3RvcmVzICoqVFJVRSoqIG9yICoqRkFMU0UqKiB2YWx1ZXMuDQoqIFRoaXMgdHlwZSBpcyBvZnRlbiB1c2VkIGluIGNvbmRpdGlvbnMsIGNvbXBhcmlzb25zLCBhbmQgZmlsdGVyaW5nIGRhdGEuDQoNCioqRXhhbXBsZToqKg0KDQpgYGB7cn0NCmlzX3NlbmlvciA8LSBUUlVFDQpjbGFzcyhpc19zZW5pb3IpICAjIE91dHB1dDogImxvZ2ljYWwiDQoNCmFnZSA8LSAyNQ0KYWdlID4gMzAgICMgT3V0cHV0OiBGQUxTRQ0KYGBgDQoNCg0KSGVyZSwgYGlzX3NlbmlvcmAgaXMgYSBsb2dpY2FsIHZhcmlhYmxlLiBUaGUgZXhwcmVzc2lvbiBgYWdlID4gMzBgIGFsc28gcmV0dXJucyBhIGxvZ2ljYWwgdmFsdWUuDQoNCi0tLQ0KDQojIyAgU3VtbWFyeSBUYWJsZQ0KDQp8ICoqRGF0YSBUeXBlKiogfCAqKkRlc2NyaXB0aW9uKiogICAgICAgICAgICAgICAgICAgICB8ICoqRXhhbXBsZSoqICAgICAgICB8DQp8IC0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tLSB8DQp8IE51bWVyaWMgICAgICAgfCBEZWNpbWFsIG9yIGZsb2F0aW5nLXBvaW50IG51bWJlcnMgICB8IGB4IDwtIDUuNmAgICAgICAgICB8DQp8IEludGVnZXIgICAgICAgfCBXaG9sZSBudW1iZXJzIHdpdGggYExgIHN1ZmZpeCAgICAgICB8IGB5IDwtIDEwMExgICAgICAgICB8DQp8IENvbXBsZXggICAgICAgfCBOdW1iZXJzIHdpdGggcmVhbCArIGltYWdpbmFyeSBwYXJ0cyB8IGB6IDwtIDMgKyA0aWAgICAgICB8DQp8IENoYXJhY3RlciAgICAgfCBUZXh0IG9yIHN0cmluZ3MgICAgICAgICAgICAgICAgICAgICB8IGBuYW1lIDwtICJSIFVzZXIiYCB8DQp8IExvZ2ljYWwgICAgICAgfCBCb29sZWFuIHZhbHVlcyAoYFRSVUVgIG9yIGBGQUxTRWApICB8IGBmbGFnIDwtIEZBTFNFYCAgICB8DQoNCi0tLQ0KDQoNCi0tLQ0KDQojIyAqKkFyaXRobWV0aWMgT3BlcmF0b3JzIGluIFIqKg0KDQpSIHByb3ZpZGVzIGEgc2V0IG9mIGFyaXRobWV0aWMgb3BlcmF0b3JzIHRoYXQgYXJlIHVzZWQgdG8gcGVyZm9ybSBiYXNpYyBtYXRoZW1hdGljYWwgb3BlcmF0aW9ucyBvbiBudW1lcmljIHZhbHVlcywgdmVjdG9ycywgb3IgdmFyaWFibGVzLiBUaGVzZSBvcGVyYXRvcnMgaW5jbHVkZSAqKmFkZGl0aW9uKiosICoqc3VidHJhY3Rpb24qKiwgKiptdWx0aXBsaWNhdGlvbioqLCAqKmRpdmlzaW9uKiosICoqbW9kdWx1cyoqLCBhbmQgKipleHBvbmVudGlhdGlvbioqLg0KDQotLS0NCg0KIyMjIDEuICoqQWRkaXRpb24gKGArYCkqKg0KDQpUaGUgYCtgIG9wZXJhdG9yIGlzIHVzZWQgdG8gYWRkIHR3byBvciBtb3JlIG51bWJlcnMuDQoNCioqRXhhbXBsZToqKg0KDQpgYGB7cn0NCmEgPC0gMTANCmIgPC0gNQ0KcmVzdWx0IDwtIGEgKyBiDQpwcmludChyZXN1bHQpICAjIE91dHB1dDogMTUNCmBgYA0KDQoNCkluIHRoaXMgZXhhbXBsZSwgMTAgYW5kIDUgYXJlIGFkZGVkIHRvIGdldCAxNS4NCg0KLS0tDQoNCiMjIyAyLiAqKlN1YnRyYWN0aW9uIChgLWApKioNCg0KVGhlIGAtYCBvcGVyYXRvciBpcyB1c2VkIHRvIHN1YnRyYWN0IG9uZSBudW1iZXIgZnJvbSBhbm90aGVyLg0KDQoqKkV4YW1wbGU6KioNCg0KYGBge3J9DQphIDwtIDEwDQpiIDwtIDUNCnJlc3VsdCA8LSBhIC0gYg0KcHJpbnQocmVzdWx0KSAgIyBPdXRwdXQ6IDUNCmBgYA0KDQoNCkhlcmUsIDUgaXMgc3VidHJhY3RlZCBmcm9tIDEwIHRvIGdldCA1Lg0KDQotLS0NCg0KIyMjIDMuICAqKk11bHRpcGxpY2F0aW9uIChgKmApKioNCg0KVGhlIGAqYCBvcGVyYXRvciBpcyB1c2VkIHRvIG11bHRpcGx5IG51bWJlcnMuDQoNCioqRXhhbXBsZToqKg0KDQpgYGB7cn0NCmEgPC0gMTANCmIgPC0gNQ0KcmVzdWx0IDwtIGEgKiBiDQpwcmludChyZXN1bHQpICAjIE91dHB1dDogNTANCmBgYA0KDQoNClRoZSBtdWx0aXBsaWNhdGlvbiBvZiAxMCBhbmQgNSByZXN1bHRzIGluIDUwLg0KDQotLS0NCg0KIyMjIDQuICoqRGl2aXNpb24gKGAvYCkqKg0KDQpUaGUgYC9gIG9wZXJhdG9yIGlzIHVzZWQgdG8gZGl2aWRlIG9uZSBudW1iZXIgYnkgYW5vdGhlci4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KYSA8LSAxMA0KYiA8LSA1DQpyZXN1bHQgPC0gYSAvIGINCnByaW50KHJlc3VsdCkgICMgT3V0cHV0OiAyDQpgYGANCg0KDQpIZXJlLCAxMCBkaXZpZGVkIGJ5IDUgZ2l2ZXMgdGhlIHJlc3VsdCAyLg0KDQotLS0NCg0KIyMjIDUuICAqKk1vZHVsdXMgKGAlJWApKioNCg0KVGhlIGAlJWAgb3BlcmF0b3IgZ2l2ZXMgdGhlICoqcmVtYWluZGVyKiogd2hlbiBvbmUgbnVtYmVyIGlzIGRpdmlkZWQgYnkgYW5vdGhlci4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KYSA8LSAxMA0KYiA8LSAzDQpyZXN1bHQgPC0gYSAlJSBiDQpwcmludChyZXN1bHQpICAjIE91dHB1dDogMQ0KYGBgDQoNCg0KV2hlbiAxMCBpcyBkaXZpZGVkIGJ5IDMsIHRoZSByZW1haW5kZXIgaXMgMS4NCg0KLS0tDQoNCiMjIyA2LiAgKipFeHBvbmVudGlhdGlvbiAoYF5gKSoqDQoNClRoZSBgXmAgb3BlcmF0b3IgaXMgdXNlZCB0byByYWlzZSBhIG51bWJlciB0byB0aGUgcG93ZXIgb2YgYW5vdGhlci4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KYSA8LSAyDQpiIDwtIDMNCnJlc3VsdCA8LSBhIF4gYg0KcHJpbnQocmVzdWx0KSAgIyBPdXRwdXQ6IDgNCmBgYA0KDQoNCkluIHRoaXMgY2FzZSwgMiByYWlzZWQgdG8gdGhlIHBvd2VyIG9mIDMgZXF1YWxzIDguDQoNCi0tLQ0KDQojIyBTdW1tYXJ5IFRhYmxlDQoNCnwgT3BlcmF0b3IgfCBEZXNjcmlwdGlvbiAgICAgICAgIHwgRXhhbXBsZSAgIHwgUmVzdWx0IHwNCnwgLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tIHwgLS0tLS0tIHwNCnwgYCtgICAgICAgfCBBZGRpdGlvbiAgICAgICAgICAgIHwgYDUgKyAzYCAgIHwgOCAgICAgIHwNCnwgYC1gICAgICAgfCBTdWJ0cmFjdGlvbiAgICAgICAgIHwgYDUgLSAzYCAgIHwgMiAgICAgIHwNCnwgYCpgICAgICAgfCBNdWx0aXBsaWNhdGlvbiAgICAgIHwgYDUgKiAzYCAgIHwgMTUgICAgIHwNCnwgYC9gICAgICAgfCBEaXZpc2lvbiAgICAgICAgICAgIHwgYDYgLyAzYCAgIHwgMiAgICAgIHwNCnwgYCUlYCAgICAgfCBNb2R1bHVzIChyZW1haW5kZXIpIHwgYDEwICUlIDNgIHwgMSAgICAgIHwNCnwgYF5gICAgICAgfCBFeHBvbmVudGlhdGlvbiAgICAgIHwgYDIgXiA0YCAgIHwgMTYgICAgIHwNCg0KLS0tDQoNClRoZXNlIGFyaXRobWV0aWMgb3BlcmF0b3JzIGFyZSBmcmVxdWVudGx5IHVzZWQgaW4gbWF0aGVtYXRpY2FsIGNvbXB1dGF0aW9ucywgc3RhdGlzdGljYWwgYW5hbHlzaXMsIGFuZCBkYXRhIG1hbmlwdWxhdGlvbiB0YXNrcyBpbiBSLg0KDQotLS0NCg0KIyMgICoqUmVsYXRpb25hbCBPcGVyYXRvcnMgaW4gUioqDQoNClJlbGF0aW9uYWwgb3BlcmF0b3JzIGluIFIgYXJlIHVzZWQgdG8gKipjb21wYXJlIHR3byB2YWx1ZXMgb3IgZXhwcmVzc2lvbnMqKi4gVGhlIHJlc3VsdCBvZiBhIHJlbGF0aW9uYWwgb3BlcmF0aW9uIGlzIGFsd2F5cyBhICoqbG9naWNhbCB2YWx1ZSoqOiBlaXRoZXIgYFRSVUVgIG9yIGBGQUxTRWAuIFRoZXNlIGFyZSBlc3NlbnRpYWwgZm9yIGRlY2lzaW9uLW1ha2luZyBhbmQgY29uZGl0aW9uYWwgcHJvZ3JhbW1pbmcuDQoNCi0tLQ0KDQojIyMgMS4gYDxgIChMZXNzIHRoYW4pDQoNClRoaXMgb3BlcmF0b3IgY2hlY2tzIHdoZXRoZXIgdGhlIHZhbHVlIG9uIHRoZSBsZWZ0IGlzIGxlc3MgdGhhbiB0aGUgdmFsdWUgb24gdGhlIHJpZ2h0Lg0KDQoqKkV4YW1wbGU6KioNCg0KYGBge3J9DQphIDwtIDEwDQpiIDwtIDIwDQpjIDwtIGEgPCBiDQpwcmludChjKSAgIyBPdXRwdXQ6IFRSVUUNCmBgYA0KDQoNCkV4cGxhbmF0aW9uOiBTaW5jZSAxMCBpcyBsZXNzIHRoYW4gMjAsIHRoZSByZXN1bHQgaXMgYFRSVUVgLg0KDQotLS0NCg0KIyMjIDIuIGA+YCAoR3JlYXRlciB0aGFuKQ0KDQpDaGVja3MgaWYgdGhlIHZhbHVlIG9uIHRoZSBsZWZ0IGlzIGdyZWF0ZXIgdGhhbiB0aGUgdmFsdWUgb24gdGhlIHJpZ2h0Lg0KDQoqKkV4YW1wbGU6KioNCg0KYGBge3J9DQphIDwtIDEwDQpiIDwtIDIwDQpjIDwtIGEgPiBiDQpwcmludChjKSAgIyBPdXRwdXQ6IEZBTFNFDQpgYGANCg0KDQpFeHBsYW5hdGlvbjogMTAgaXMgbm90IGdyZWF0ZXIgdGhhbiAyMCwgc28gdGhlIHJlc3VsdCBpcyBgRkFMU0VgLg0KDQotLS0NCg0KIyMjIDMuIGA8PWAgKExlc3MgdGhhbiBvciBlcXVhbCB0bykNCg0KQ2hlY2tzIGlmIHRoZSBsZWZ0LWhhbmQgc2lkZSBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gdGhlIHJpZ2h0LWhhbmQgc2lkZS4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KYSA8LSAxMA0KYiA8LSAxMA0KYyA8LSBhIDw9IGINCnByaW50KGMpICAjIE91dHB1dDogVFJVRQ0KYGBgDQoNCg0KRXhwbGFuYXRpb246IDEwIGlzIGVxdWFsIHRvIDEwLCBzbyBpdCBzYXRpc2ZpZXMgdGhlIGNvbmRpdGlvbi4NCg0KLS0tDQoNCiMjIyA0LiBgPj1gIChHcmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8pDQoNCkNoZWNrcyBpZiB0aGUgdmFsdWUgb24gdGhlIGxlZnQgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIHRoZSBvbmUgb24gdGhlIHJpZ2h0Lg0KDQoqKkV4YW1wbGU6KioNCg0KYGBge3J9DQphIDwtIDE1DQpiIDwtIDEwDQpjIDwtIGEgPj0gYg0KcHJpbnQoYykgICMgT3V0cHV0OiBUUlVFDQpgYGANCg0KDQpFeHBsYW5hdGlvbjogMTUgaXMgZ3JlYXRlciB0aGFuIDEwLCBzbyB0aGUgcmVzdWx0IGlzIGBUUlVFYC4NCg0KLS0tDQoNCiMjIyA1LiBgPT1gIChFcXVhbCB0bykNCg0KVGVzdHMgd2hldGhlciB0d28gdmFsdWVzIGFyZSBlcXVhbC4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KYSA8LSAxMA0KYiA8LSAxMA0KYyA8LSBhID09IGINCnByaW50KGMpICAjIE91dHB1dDogVFJVRQ0KYGBgDQoNCg0KRXhwbGFuYXRpb246IEJvdGggdmFsdWVzIGFyZSBlcXVhbCwgc28gaXQgcmV0dXJucyBgVFJVRWAuDQoNCi0tLQ0KDQojIyMgNi4gYCE9YCAoTm90IGVxdWFsIHRvKQ0KDQpDaGVja3MgaWYgdGhlIHR3byB2YWx1ZXMgYXJlICoqbm90IGVxdWFsKiouDQoNCioqRXhhbXBsZToqKg0KDQpgYGB7cn0NCmEgPC0gMTANCmIgPC0gMjANCmMgPC0gYSAhPSBiDQpwcmludChjKSAgIyBPdXRwdXQ6IFRSVUUNCmBgYA0KDQoNCkV4cGxhbmF0aW9uOiAxMCBhbmQgMjAgYXJlIG5vdCBlcXVhbCwgc28gdGhlIHJlc3VsdCBpcyBgVFJVRWAuDQoNCi0tLQ0KDQojIyBTdW1tYXJ5IFRhYmxlDQoNCnwgT3BlcmF0b3IgfCBEZXNjcmlwdGlvbiAgICAgICAgICAgICAgfCBFeGFtcGxlICAgIHwgUmVzdWx0IHwNCnwgLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tIHwgLS0tLS0tIHwNCnwgYDxgICAgICAgfCBMZXNzIHRoYW4gICAgICAgICAgICAgICAgfCBgMTAgPCAyMGAgIHwgVFJVRSAgIHwNCnwgYD5gICAgICAgfCBHcmVhdGVyIHRoYW4gICAgICAgICAgICAgfCBgMTAgPiAyMGAgIHwgRkFMU0UgIHwNCnwgYDw9YCAgICAgfCBMZXNzIHRoYW4gb3IgZXF1YWwgdG8gICAgfCBgMTAgPD0gMTBgIHwgVFJVRSAgIHwNCnwgYD49YCAgICAgfCBHcmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gfCBgMTUgPj0gMTBgIHwgVFJVRSAgIHwNCnwgYD09YCAgICAgfCBFcXVhbCB0byAgICAgICAgICAgICAgICAgfCBgMTAgPT0gMTBgIHwgVFJVRSAgIHwNCnwgYCE9YCAgICAgfCBOb3QgZXF1YWwgdG8gICAgICAgICAgICAgfCBgMTAgIT0gMjBgIHwgVFJVRSAgIHwNCg0KLS0tDQoNClRoZXNlIHJlbGF0aW9uYWwgb3BlcmF0b3JzIGFyZSBwYXJ0aWN1bGFybHkgdXNlZnVsIGluICoqaWYtZWxzZSBjb25kaXRpb25zKiosICoqZmlsdGVyaW5nIGRhdGEqKiwgYW5kICoqbG9vcCBjb250cm9sKiogaW4gUiBwcm9ncmFtbWluZy4NCg0KDQoNCi0tLQ0KDQojIyAgTG9naWNhbCBPcGVyYXRvcnMgaW4gUg0KDQpMb2dpY2FsIG9wZXJhdG9ycyBhcmUgdXNlZCB0byBjb21iaW5lIG9yIG1vZGlmeSBsb2dpY2FsIHZhbHVlcyAoYFRSVUVgIG9yIGBGQUxTRWApIGluIFIuIFRoZXkgYXJlIGVzcGVjaWFsbHkgdXNlZnVsIGluICoqY29uZGl0aW9uYWwgc3RhdGVtZW50cyoqLCAqKmRhdGEgZmlsdGVyaW5nKiosIGFuZCAqKnZlY3Rvcml6ZWQgb3BlcmF0aW9ucyoqLg0KDQotLS0NCg0KIyMjIDEuIGAhYCAoTG9naWNhbCBOT1QpDQoNClRoaXMgb3BlcmF0b3IgcmV2ZXJzZXMgdGhlIGxvZ2ljYWwgc3RhdGUgb2YgaXRzIG9wZXJhbmQuIElmIGEgY29uZGl0aW9uIGlzIGBUUlVFYCwgYXBwbHlpbmcgYCFgIHdpbGwgbWFrZSBpdCBgRkFMU0VgLCBhbmQgdmljZSB2ZXJzYS4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KeCA8LSBUUlVFDQpyZXN1bHQgPC0gIXgNCnByaW50KHJlc3VsdCkgICMgT3V0cHV0OiBGQUxTRQ0KYGBgDQoNCg0KKipFeHBsYW5hdGlvbjoqKiBUaGUgdmFsdWUgb2YgYHhgIGlzIGBUUlVFYC4gVGhlIGAhYCBvcGVyYXRvciBmbGlwcyBpdCB0byBgRkFMU0VgLg0KDQotLS0NCg0KIyMjIDIuIGAmYCAoRWxlbWVudC13aXNlIExvZ2ljYWwgQU5EKQ0KDQpUaGlzIG9wZXJhdG9yIHBlcmZvcm1zIGEgbG9naWNhbCBBTkQgKiplbGVtZW50IGJ5IGVsZW1lbnQqKiBvbiB0d28gbG9naWNhbCB2ZWN0b3JzLiBJdCByZXR1cm5zIGBUUlVFYCBpZiAqKmJvdGggZWxlbWVudHMqKiBhcmUgYFRSVUVgLg0KDQoqKkV4YW1wbGU6KioNCg0KYGBge3J9DQphIDwtIGMoVFJVRSwgRkFMU0UsIFRSVUUpDQpiIDwtIGMoVFJVRSwgVFJVRSwgRkFMU0UpDQpyZXN1bHQgPC0gYSAmIGINCnByaW50KHJlc3VsdCkgICMgT3V0cHV0OiBUUlVFIEZBTFNFIEZBTFNFDQpgYGANCg0KDQoqKkV4cGxhbmF0aW9uOioqIEl0IGNoZWNrcyBlYWNoIGNvcnJlc3BvbmRpbmcgcGFpcjoNCg0KKiBgVFJVRSAmIFRSVUVgIOKGkiBgVFJVRWANCiogYEZBTFNFICYgVFJVRWAg4oaSIGBGQUxTRWANCiogYFRSVUUgJiBGQUxTRWAg4oaSIGBGQUxTRWANCg0KLS0tDQoNCiMjIyAzLiBgJiZgIChMb2dpY2FsIEFORCDigJMgZXZhbHVhdGVzIG9ubHkgZmlyc3QgZWxlbWVudCkNCg0KVGhpcyBvcGVyYXRvciBhbHNvIHBlcmZvcm1zIGxvZ2ljYWwgQU5ELCBidXQgKipvbmx5IG9uIHRoZSBmaXJzdCBlbGVtZW50Kiogb2YgZWFjaCBvcGVyYW5kLiBJdCBpcyBvZnRlbiB1c2VkIGluIGNvbnRyb2wgc3RydWN0dXJlcyBsaWtlIGBpZmAgc3RhdGVtZW50cy4NCg0KDQpVc2VkIGZvciBzY2FsYXIgKHNpbmdsZSBsb2dpY2FsKSBjb21wYXJpc29ucy4NCg0KSXQgb25seSBjaGVja3MgdGhlIGZpcnN0IGVsZW1lbnQgb2YgZWFjaCBsb2dpY2FsIHZlY3Rvci4NCg0KSWYgeW91ciB2ZWN0b3IgaGFzIG1vcmUgdGhhbiBvbmUgZWxlbWVudCwgeW914oCZbGwgZ2V0IGFuIGVycm9yIG9yIHVuZXhwZWN0ZWQgcmVzdWx0Lg0KDQoNCioqRXhhbXBsZToqKg0KDQpgYGB7cn0NCmEgPC0gYyhUUlVFLCBGQUxTRSkNCmIgPC0gYyhUUlVFLCBUUlVFKQ0KcmVzdWx0IDwtIChhICYgYikNCnByaW50KHJlc3VsdCkgICMgT3V0cHV0OiBUUlVFIEZBTFNFDQoNCmBgYA0KDQpgYGB7cn0NCmEgPC0gYyhUUlVFLCBGQUxTRSkNCmIgPC0gYyhUUlVFLCBUUlVFKQ0KcmVzdWx0IDwtIChhICYmIGIgKQ0KcHJpbnQocmVzdWx0KSAgIyBPdXRwdXQ6IFRSVUUNCmBgYA0KDQoNCmBgYHtyfQ0KYSA8LSBjKFRSVUUsIEZBTFNFKQ0KYiA8LSBjKFRSVUUsIFRSVUUpDQpyZXN1bHQgPC0gKGFbMV0gJiYgYlsxXSkNCnByaW50KHJlc3VsdCkgICMgT3V0cHV0OiBUUlVFDQoNCmBgYA0KDQoNCioqRXhwbGFuYXRpb246KiogSXQgY2hlY2tzIG9ubHkgdGhlIGZpcnN0IGVsZW1lbnRzOiBgVFJVRSAmJiBUUlVFYCDihpIgYFRSVUVgDQoNCi0tLQ0KDQojIyMgNC4gYHxgIChFbGVtZW50LXdpc2UgTG9naWNhbCBPUikNCg0KUGVyZm9ybXMgbG9naWNhbCBPUiAqKmVsZW1lbnQgYnkgZWxlbWVudCoqLiBJdCByZXR1cm5zIGBUUlVFYCBpZiAqKmVpdGhlcioqIG9mIHRoZSBlbGVtZW50cyBpcyBgVFJVRWAuDQoNCioqRXhhbXBsZToqKg0KDQpgYGB7cn0NCmEgPC0gYyhUUlVFLCBGQUxTRSwgRkFMU0UpDQpiIDwtIGMoRkFMU0UsIFRSVUUsIEZBTFNFKQ0KcmVzdWx0IDwtIGEgfCBiDQpwcmludChyZXN1bHQpICAjIE91dHB1dDogVFJVRSBUUlVFIEZBTFNFDQpgYGANCg0KDQoqKkV4cGxhbmF0aW9uOioqDQoNCiogYFRSVUUgfCBGQUxTRWAg4oaSIGBUUlVFYA0KKiBgRkFMU0UgfCBUUlVFYCDihpIgYFRSVUVgDQoqIGBGQUxTRSB8IEZBTFNFYCDihpIgYEZBTFNFYA0KDQotLS0NCg0KIyMjIDUuIGB8fGAgKExvZ2ljYWwgT1Ig4oCTIGV2YWx1YXRlcyBvbmx5IGZpcnN0IGVsZW1lbnQpDQoNClRoaXMgcGVyZm9ybXMgbG9naWNhbCBPUiBvbiBvbmx5IHRoZSAqKmZpcnN0IGVsZW1lbnQqKiBvZiB0aGUgbG9naWNhbCB2ZWN0b3JzLg0KDQoqKkV4YW1wbGU6KioNCg0KYGBge3J9DQphIDwtIGMoRkFMU0UsIEZBTFNFKQ0KYiA8LSBjKFRSVUUsIEZBTFNFKQ0KcmVzdWx0IDwtIGEgfHwgYg0KcHJpbnQocmVzdWx0KSAgIyBPdXRwdXQ6IFRSVUUNCmBgYA0KDQpgYGB7cn0NCmEgPC0gYyhGQUxTRSwgRkFMU0UpDQpiIDwtIGMoVFJVRSwgRkFMU0UpDQpyZXN1bHQgPC0gYVsxXSB8fCBiWzFdDQpwcmludChyZXN1bHQpICAjIE91dHB1dDogVFJVRQ0KYGBgDQoNCg0KDQoqKkV4cGxhbmF0aW9uOioqIEl0IGNoZWNrcyBvbmx5IHRoZSBmaXJzdCBlbGVtZW50czogYEZBTFNFIHx8IFRSVUVgIOKGkiBgVFJVRWANCg0KLS0tDQoNCiMjIFN1bW1hcnkgVGFibGUNCg0KfCBPcGVyYXRvciB8IE5hbWUgICAgICAgICAgICAgIHwgV29ya3MgT24gICAgICAgIHwgRXhhbXBsZSAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgUmVzdWx0ICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICB8ICAgICAgICB8DQp8IC0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tIHwNCnwgYCFgICAgICAgfCBMb2dpY2FsIE5PVCAgICAgICB8IFNpbmdsZSB2YWx1ZSAgICB8IGAhVFJVRWAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IGBGQUxTRWAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgfCAgICAgICAgfA0KfCBgJmAgICAgICB8IEVsZW1lbnQtd2lzZSBBTkQgIHwgVmVjdG9ycyAgICAgICAgIHwgYGMoVFJVRSwgRkFMU0UpICYgYyhUUlVFLCBUUlVFKWAgIHwgYFRSVUUgRkFMU0VgICAgICAgfCAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICB8ICAgICAgICB8DQp8IGAmJmAgICAgIHwgRmlyc3QtZWxlbWVudCBBTkQgfCBWZWN0b3JzICAgICAgICAgfCBgYyhUUlVFLCBGQUxTRSkgJiYgYyhUUlVFLCBUUlVFKWAgfCBgVFJVRWAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwNCnwgYHxgICAgICAgIHwgRWxlbWVudC13aXNlIExvZ2ljYWwgT1IgICAgICAgICAgICAgICAgfCBFbGVtZW50LXdpc2UgT1IgfCBWZWN0b3JzICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBcYGMoRkFMU0UsIEZBTFNFKSB8IGMoVFJVRSwgRkFMU0UpXGAgfCBgVFJVRSBGQUxTRWAgfCAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwNCnwgYHx8YCAgICAgICB8ICAgTG9naWNhbCBPUiAgICAgICB8IEZpcnN0LWVsZW1lbnQgT1IgICAgICAgICAgICAgICAgICB8IFZlY3RvcnMgICAgICAgICAgIHwgXGBjKEZBTFNFLCBUUlVFKSB8ICAgICAgICAgICAgICB8IGMoVFJVRSwgRkFMU0UpXGAgfCBgVFJVRWAgfA0KDQotLS0NCg0KVGhlc2UgbG9naWNhbCBvcGVyYXRvcnMgYXJlIGZ1bmRhbWVudGFsIGZvciAqKmZpbHRlcmluZyByb3dzIGluIGRhdGEgZnJhbWVzKiosICoqYXBwbHlpbmcgY29uZGl0aW9ucyoqLCBhbmQgKipidWlsZGluZyBjb250cm9sIGZsb3dzKiogaW4gUiBwcm9ncmFtbWluZy4NCg0KDQpDZXJ0YWlubHkhIEhlcmUncyBhIGRldGFpbGVkIGV4cGxhbmF0aW9uIG9mICoqQXNzaWdubWVudCBPcGVyYXRvcnMgaW4gUioqIHdpdGggZXhhbXBsZXMgdXNpbmcgcHJvcGVyIHNlbnRlbmNlczoNCg0KLS0tDQoNCiMjIyAqKkFzc2lnbm1lbnQgT3BlcmF0b3JzIGluIFIqKg0KDQpBc3NpZ25tZW50IG9wZXJhdG9ycyBpbiBSIGFyZSB1c2VkIHRvIGFzc2lnbiB2YWx1ZXMgdG8gdmFyaWFibGVzLiBSIHByb3ZpZGVzIG11bHRpcGxlIHdheXMgdG8gYXNzaWduIHZhbHVlcywgaW5jbHVkaW5nIGxlZnR3YXJkLCByaWdodHdhcmQsIGFuZCBlcXVhbCBzaWduIGFzc2lnbm1lbnRzLg0KDQotLS0NCg0KIyMjIyAxLiBgPC1gIChMZWZ0d2FyZCBBc3NpZ25tZW50KQ0KDQoqICoqRGVzY3JpcHRpb24qKjogVGhpcyBpcyB0aGUgbW9zdCBjb21tb25seSB1c2VkIGFzc2lnbm1lbnQgb3BlcmF0b3IgaW4gUi4gSXQgYXNzaWducyBhIHZhbHVlIHRvIGEgdmFyaWFibGUgYnkgcG9pbnRpbmcgdGhlIGFycm93ICoqZnJvbSB0aGUgdmFsdWUgdG8gdGhlIHZhcmlhYmxlKiouDQoqICoqRXhhbXBsZSoqOg0KDQpgYGB7cn0NCnggPC0gMTANCnByaW50KHgpDQpgYGANCg0KDQoqICoqRXhwbGFuYXRpb24qKjogVGhlIHZhbHVlIGAxMGAgaXMgYXNzaWduZWQgdG8gdGhlIHZhcmlhYmxlIGB4YC4gV2hlbiB5b3UgcHJpbnQgYHhgLCBpdCBvdXRwdXRzIGAxMGAuDQoNCi0tLQ0KDQojIyMjIDIuIGA8PC1gIChHbG9iYWwgb3IgVXB3YXJkIEFzc2lnbm1lbnQpDQoNCiogKipEZXNjcmlwdGlvbioqOiBUaGlzIG9wZXJhdG9yIGFzc2lnbnMgYSB2YWx1ZSB0byBhIHZhcmlhYmxlICoqaW4gYSBwYXJlbnQgZW52aXJvbm1lbnQqKiAodXNlZCBpbnNpZGUgZnVuY3Rpb25zIHRvIHVwZGF0ZSBnbG9iYWwgdmFyaWFibGVzKS4NCiogKipFeGFtcGxlKio6DQoNCg0KYGBge3J9DQp1cGRhdGVWYXIgPC0gZnVuY3Rpb24oKSB7DQogIHkgPDwtIDUwDQp9DQp1cGRhdGVWYXIoKQ0KcHJpbnQoeSkNCmBgYA0KICANCiogKipFeHBsYW5hdGlvbioqOiBUaGUgdmFyaWFibGUgYHlgIGlzIGNyZWF0ZWQgaW4gdGhlIGdsb2JhbCBlbnZpcm9ubWVudCBldmVuIHRob3VnaCBpdCBpcyBhc3NpZ25lZCBpbnNpZGUgYSBmdW5jdGlvbiB1c2luZyBgPDwtYC4NCg0KLS0tDQoNCiMjIyMgMy4gYD1gIChFcXVhbCBTaWduIEFzc2lnbm1lbnQpDQoNCiogKipEZXNjcmlwdGlvbioqOiBJdCBhc3NpZ25zIGEgdmFsdWUganVzdCBsaWtlIGA8LWAsIGJ1dCBpdCdzIG1vcmUgY29tbW9ubHkgdXNlZCB3aGVuICoqcGFzc2luZyBhcmd1bWVudHMgdG8gZnVuY3Rpb25zKiouDQoqICoqRXhhbXBsZSoqOg0KDQpgYGB7cn0NCiAgeiA9IDIwDQogIHByaW50KHopDQpgYGANCg0KKiAqKkV4cGxhbmF0aW9uKio6IFRoZSB2YWx1ZSBgMjBgIGlzIGFzc2lnbmVkIHRvIHRoZSB2YXJpYWJsZSBgemAuIEJvdGggYDwtYCBhbmQgYD1gIGNhbiBiZSB1c2VkIGZvciBzaW1wbGUgYXNzaWdubWVudHMsIGJ1dCBgPC1gIGlzIHByZWZlcnJlZCBpbiBSIHByb2dyYW1taW5nIHN0eWxlLg0KDQotLS0NCg0KIyMjICBTdW1tYXJ5IFRhYmxlDQoNCnwgT3BlcmF0b3IgfCBVc2FnZSBTY29wZSAgICAgICB8IENvbW1vbiBVc2UgQ2FzZSAgICAgICAgICAgICAgICB8IEV4YW1wbGUgICAgfA0KfCAtLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLSB8DQp8IGA8LWAgICAgIHwgTG9jYWwvR2xvYmFsICAgICAgfCBHZW5lcmFsIGFzc2lnbm1lbnQgICAgICAgICAgICAgfCBgYSA8LSA1YCAgIHwNCnwgYDw8LWAgICAgfCBQYXJlbnQvR2xvYmFsIGVudiB8IEluc2lkZSBmdW5jdGlvbnMgKGdsb2JhbCkgICAgICB8IGB4IDw8LSAxMGAgfA0KfCBgPWAgICAgICB8IExvY2FsICAgICAgICAgICAgIHwgQXNzaWduIHZhbHVlcyBvciBmdW5jdGlvbiBhcmdzIHwgYHggPSAyMGAgICB8DQoNCi0tLQ0KDQoNCkNlcnRhaW5seSEgSGVyZSdzIGEgKipkZXRhaWxlZCBleHBsYW5hdGlvbiBvZiBGdW5jdGlvbnMgaW4gUioqIHdpdGggcHJvcGVyIHN0cnVjdHVyZSwgZXhhbXBsZXMsIGFuZCBiZXN0IHByYWN0aWNlczoNCg0KLS0tDQoNCiMjICAqKkZVTkNUSU9OUyBJTiBSKioNCg0KLS0tDQoNCiMjIyAgV2hhdCBpcyBhIEZ1bmN0aW9uIGluIFI/DQoNCkEgKipmdW5jdGlvbioqIGluIFIgaXMgYSBibG9jayBvZiByZXVzYWJsZSBjb2RlIGRlc2lnbmVkIHRvIHBlcmZvcm0gYSBzcGVjaWZpYyB0YXNrLiBSIHByb3ZpZGVzIG1hbnkgYnVpbHQtaW4gZnVuY3Rpb25zLCBhbmQgaXQgYWxzbyBhbGxvd3MgdXNlcnMgdG8gZGVmaW5lIHRoZWlyIG93biBmdW5jdGlvbnMuDQoNCi0tLQ0KDQojIyMgIFdoeSBVc2UgRnVuY3Rpb25zPw0KDQoqIFRvIGF2b2lkIHJlcGV0aXRpb24gb2YgY29kZQ0KKiBUbyBtYWtlIGNvZGUgbW9kdWxhciwgY2xlYW4sIGFuZCByZWFkYWJsZQ0KKiBUbyBzaW1wbGlmeSBkZWJ1Z2dpbmcgYW5kIHRlc3RpbmcNCiogVG8gYnJlYWsgY29tcGxleCBwcm9ibGVtcyBpbnRvIG1hbmFnZWFibGUgcGFydHMNCg0KLS0tDQoNCiMjIyAgU3ludGF4IG9mIGEgRnVuY3Rpb24gaW4gUg0KDQpgYGB7cn0NCmZ1bmN0aW9uX25hbWUgPC0gZnVuY3Rpb24oYXJnMSwgYXJnMiwgLi4uKSB7DQogICMgQ29kZSBibG9jaw0KICByZXR1cm4ocmVzdWx0KQ0KfQ0KYGBgDQoNCg0KLS0tDQoNCiMjIyAgRXhhbXBsZTogU2ltcGxlIEZ1bmN0aW9uIGluIFINCg0KYGBge3J9DQphZGRfbnVtYmVycyA8LSBmdW5jdGlvbihhLCBiKSB7DQogIHJlc3VsdCA8LSBhICsgYg0KICByZXR1cm4ocmVzdWx0KQ0KfQ0KYWRkX251bWJlcnMoNSwgMykNCmBgYA0KDQotLS0NCg0KIyMjICBDb21wb25lbnRzIG9mIGEgRnVuY3Rpb24NCg0KfCBDb21wb25lbnQgICAgICAgfCBEZXNjcmlwdGlvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB8DQp8IGBmdW5jdGlvbl9uYW1lYCB8IE5hbWUgb2YgdGhlIGZ1bmN0aW9uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCBgZnVuY3Rpb24oKWAgICAgfCBLZXl3b3JkIHRvIGRlZmluZSBhIGZ1bmN0aW9uICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgYGFyZ3VtZW50c2AgICAgIHwgSW5wdXQgdmFsdWVzIHBhc3NlZCB0byB0aGUgZnVuY3Rpb24gICAgICAgICAgICAgICAgICB8DQp8IGByZXR1cm4oKWAgICAgICB8IE9wdGlvbmFsIOKAkyByZXR1cm5zIG91dHB1dCB0byB0aGUgY2FsbGluZyBlbnZpcm9ubWVudCB8DQp8IEJvZHkgICAgICAgICAgICB8IEJsb2NrIG9mIGNvZGUgdGhhdCBkZWZpbmVzIHdoYXQgdGhlIGZ1bmN0aW9uIGRvZXMgICAgfA0KDQotLS0NCg0KIyMjICBCdWlsdC1pbiBGdW5jdGlvbnMgaW4gUg0KDQpSIGNvbWVzIHdpdGggbWFueSBidWlsdC1pbiBmdW5jdGlvbnM6DQoNCnwgRnVuY3Rpb24gICB8IERlc2NyaXB0aW9uICAgICAgICAgICAgICAgICAgICB8IEV4YW1wbGUgICAgICAgICAgICB8DQp8IC0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0gfA0KfCBgc3VtKClgICAgIHwgQ2FsY3VsYXRlcyBzdW0gb2YgdmFsdWVzICAgICAgIHwgYHN1bShjKDEsIDIsIDMpKWAgIHwNCnwgYG1lYW4oKWAgICB8IENhbGN1bGF0ZXMgYXZlcmFnZSAgICAgICAgICAgICB8IGBtZWFuKGMoNCwgNSwgNikpYCB8DQp8IGBzcXJ0KClgICAgfCBTcXVhcmUgcm9vdCAgICAgICAgICAgICAgICAgICAgfCBgc3FydCgyNSlgICAgICAgICAgfA0KfCBgbGVuZ3RoKClgIHwgTnVtYmVyIG9mIGVsZW1lbnRzIGluIGEgdmVjdG9yIHwgYGxlbmd0aChjKDEsMiwzKSlgIHwNCg0KLS0tDQoNCiMjIyAgVXNlci1kZWZpbmVkIEZ1bmN0aW9uIHdpdGggRGVmYXVsdCBWYWx1ZXMNCg0KYGBge3J9DQpncmVldCA8LSBmdW5jdGlvbihuYW1lID0gIlVzZXIiKSB7DQogIHBhc3RlKCJIZWxsbyIsIG5hbWUpDQp9DQpncmVldCgiU3Jpbml2YXMiKQ0KZ3JlZXQoKQ0KYGBgDQoNCi0tLQ0KDQojIyMgIEZ1bmN0aW9uIFdpdGhvdXQgUmV0dXJuIFN0YXRlbWVudA0KDQpJZiBgcmV0dXJuKClgIGlzIG5vdCB1c2VkLCBSIHdpbGwgcmV0dXJuIHRoZSAqKmxhc3QgZXZhbHVhdGVkIGV4cHJlc3Npb24qKjoNCg0KYGBge3J9DQptdWx0aXBseSA8LSBmdW5jdGlvbihhLCBiKSB7DQogIGEgKiBiDQp9DQptdWx0aXBseSg0LCA1KQ0KYGBgDQoNCg0KLS0tDQoNCiMjIyAgTmVzdGVkIEZ1bmN0aW9uIEV4YW1wbGUNCg0KYGBge3J9DQpvdXRlciA8LSBmdW5jdGlvbih4KSB7DQogIGlubmVyIDwtIGZ1bmN0aW9uKHkpIHsNCiAgICByZXR1cm4oeSArIDEpDQogIH0NCiAgcmV0dXJuKGlubmVyKHgpICogMikNCn0NCm91dGVyKDQpICAjIHJldHVybnMgKDQrMSkqMiA9IDEwDQpgYGANCg0KDQotLS0NCg0KIyMjICBBbm9ueW1vdXMgRnVuY3Rpb25zIChObyBOYW1lKQ0KDQpgYGB7cn0NCnNhcHBseShjKDEsIDIsIDMpLCBmdW5jdGlvbih4KSB4XjIpDQpgYGANCg0KDQotLS0NCg0KIyMjICBWYXJpYWJsZSBTY29wZSBpbiBGdW5jdGlvbnMNCg0KVmFyaWFibGVzIGNyZWF0ZWQgKippbnNpZGUqKiBhIGZ1bmN0aW9uIGFyZSAqKmxvY2FsKiogdG8gdGhhdCBmdW5jdGlvbjoNCg0KYGBge3J9DQpteWZ1bmMgPC0gZnVuY3Rpb24oKSB7DQogIHggPC0gMTAgICMgTG9jYWwgdmFyaWFibGUNCiAgcHJpbnQoeCkNCn0NCm15ZnVuYygpDQpwcmludCh4KSAgIyBFcnJvcjogb2JqZWN0ICd4JyBub3QgZm91bmQNCmBgYA0KDQoNCi0tLQ0KDQojIyMgIFN1bW1hcnkgVGFibGUNCg0KfCBUeXBlICAgICAgICAgIHwgRGVzY3JpcHRpb24gICAgICAgICAgICAgICAgICAgICAgICAgIHwgRXhhbXBsZSAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQp8IC0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHwNCnwgQnVpbHQtaW4gICAgICB8IFByZWRlZmluZWQgUiBmdW5jdGlvbnMgICAgICAgICAgICAgICB8IGBzdW0oKWAsIGBtZWFuKClgLCBgc3FydCgpYCAgICAgICAgfA0KfCBVc2VyLWRlZmluZWQgIHwgRnVuY3Rpb25zIGNyZWF0ZWQgYnkgdXNlcnMgICAgICAgICAgIHwgYG15X2Z1bmN0aW9uIDwtIGZ1bmN0aW9uKCkgey4uLn1gICB8DQp8IFdpdGggZGVmYXVsdHMgfCBGdW5jdGlvbnMgd2l0aCBkZWZhdWx0IGFyZ3VtZW50IHZhbHMgfCBgZ3JlZXQgPC0gZnVuY3Rpb24obmFtZSA9ICJVc2VyIilgIHwNCnwgQW5vbnltb3VzICAgICB8IEZ1bmN0aW9ucyB3aXRob3V0IG5hbWUgICAgICAgICAgICAgICB8IGBmdW5jdGlvbih4KSB4KzFgIGluIGBzYXBwbHkoKWAgICAgfA0KDQotLS0NCg0K