Introduction

R Stat is a widely used programming tool for statistical analysis. This guide is aimed at providing foundations on the R programming language. This guide will be useful for beginners as well as for those who have already started using R in their analysis, but haven’t got hold of the programming language underneath. Once you get the grip of this language, you will be empowered to use the built-in libraries and libraries contributed by R user communities to choose and use statistical functions on your data. For comprehensive list of packages available in R, you may visit this link: R Packages

Installation

For installation and use of R and R Studio, please follow these links: R; R Studio

Data Types

There are different kinds of data. They can be quantitative or qualitative. Quantitative data are numeric and can be continuous or discrete. When discrete numeric data can be ranked, they are called ordinal. Qualitative data are also known as nominal. R supports the following data types. Note that the integer values are suffixed with the letter L. The character values are enclosed within single or double quotes.

datatypes <- data.frame(
   'Data Type'=c('integer','double','numeric','complex','logical','character'),
   Description=c('whole numbers','numbers with decimals','numbers with decimals',
                 'numbers with imaginary parts','binary status',
                 'an empty string or a character or a string of charactars'),
   Examples=c('Inf, 0L, 23L, 9976L, Inf', '-Inf, 0.1, 12.987, 0.000012, Inf',
              '-Inf, 0.1, 12.987, 0.000012, Inf', '12i, 4+2i','TRUE, FALSE, 1, 0',
              "'', 'a', 'xyz', 'small', 'a lot of ice floats on sea'"),
   check.names=FALSE, row.names=NULL
)
knitr::kable(datatypes, caption='Data Types')

Character data type are ideal for storing date values. The different date formats can be expressed in string literals effectively, such as: '10 Oct 2017', 'Wed 10-01-87 5:30:45 PM'

However, to ease date value manipulations and calculations, these string literals are converted into date objects. For more details, see Date Functions.

Special values

R uses predefined keywords to represent certain special values.

specialVals <- data.frame(
   Keywords=c('Inf','-Inf','NA','NULL','TRUE','FALSE', 'pi'),
   Description=c('infinite: largest number unknown','negative inf: smallest number unknown',
                 'a logical value representing missing values',
                 'dont allocate memory','logical value; equals to 1; abbreviated as: T',
                 'logical value; equals to 0; abbrev. as: F', 'a constant in radians; equals to 3.14'),
   Uses=c('number of atoms in universe', 'a negative value divided by zero',
         'missing values', 'enforce no memory allocation',
         'truth in binary status such as yes or no','absence of an observable state',
         'arcs and angles'), check.names=FALSE, row.names=NULL
)
knitr::kable(specialVals, caption='Special values and constants')

Variables

In order to access a value (of different Data Types) or a set of values, R allows user defined symbolic names. Depending on the type of data, variables are called numeric variable or logial variable and so on. Variables can be named using alphanumeric characters. The rules are (a) no spaces are allowed, (b) no special characters are allowed except a dot (.) or an underscore (_), and (c) numbers are not allowed at the start.

Operations, Operands and Operators

Operations are tasks performed by the scripts. These can be assignments, mathematical expressions, comparisons, function calls and so on. Some operations use special ‘operators’ to perform specific tasks on ‘operands’. The operators in R are represented by special symbols. Operands are ‘data values’ on which the operator will perform a task. R allows variable names in place of these operands (data values), as they point to some value. Similarly, a function or another operation that returns a value can be used in place of operands. An operation where operands and operators are used in a line of R code are sometimes called expressions. In assignment expressions, the target variable to which a value to be stored appears on the side of arrow mark (this side <-) and value appears at the tail end (<- this side). An expression without assignment operator is volatile i.e. the result of the expressions are not stored anywhere. Relational expressions returns TRUE or FALSE. The operands of logical operators are logial TRUE or FALSE.

Assume that a and b are two logical variables, then the logical operation “a & b” will return TRUE only when both a and b are TRUE. Similarly, “a | b” will return FALSE only when both a and b are FALSE.

Except for exponent and rightward assignment, all other operators are evaluated from left to right. If you want to override default precedence, enclose expressions within parenthesis (sometimes referred as precedence operator). For instance compare the results of the following pair of math expressions:

Also note that enclosing an expression or a group of expressions within paranthesis increases readability of the code.

Be aware that there are special operators, other than those mentioned above, are present in R. For instance, %in% is a vector operator (see Vector operations) and %*% is a true matrix multiplication operator (see Matrix operations). In addition to that, the two square brackets (open and close types - []) together forms array access operator (see Accessing and editing vector elements and Accessing and editing matrix elements ).

# Mathematical expressions

#Assume initPop, maxRange and minIterations are numeric variables used in the
#below examples

initPop <- initPop + 34 #addition
range <- maxRange - 1.2 #subtraction
tripleIter <- minIterations * 3 #multiplication
expOf2 <- 2.718 ** 2 #square. Function: exp(2)
sqrtOf5 <- 5L ^ (1/2) #exponent. Function: sqrt(5L)
infVal <- -100 / 0 #division
leftOver <- 1000 %% 3 #modulus
weightPerBatch <- 349.8 %/% 49.2 #gets floor value of the result


# Comparative expressions (relational, logical)

# Assume airTemp and stopValveRange are numeric variables; and isFlying and isRaining are 
#logical variables used in the below examples.

isCold <- (airTemp <= 18) #less than or equal to. Similar: >, >=, <
stopValve <- (stopValveRange == 50) #equality
notInFlight <- !(isFlying) #logical not operation. Other use: a != b

isColdAndFlying <- isCold && isFlying #logical AND
isColdOrisRaining <- isCold || isRaining #logical OR

Functions

A function is a block of code (having one or more lines of code) to carry out a specific operation on the input values if given. When input values are not specified, functions simply perform a task using instructions. The input variables are called parameters. A function can have zero to many paramters. A function may return a result derived out of the task performed inside the function. Frequently used tasks are wrapped in functions, hence it helps in eliminating redundancy in the script or program. All the variables defined inside a function are called local variables. Their values are not visible outside the function in the calling program. However, their values can be returned back to the program. R has a lot of built-in functions that are bundled along with the base package and allows the user to define custom functions. Sometimes, functions are also called routines.

Creating Functions

The R syntax for defining a custom function is given below with examples.

functionNameHere <- function(parameter1='initial value', parameter2='init val', ...) {
   # <function tasks goes here>
   return(returnValue) #return is optional
}

#Example 1: This function takes two parameters (number1 and number2). Both are numeric 
#variables and initialised to zero. Inside the function, a local variable (returnValue) is created and assigned the value of addition of the two numbers. Finally, the added value is returned back to the caller of the function.
addTwoNumbers <- function(number1=0, number2=0){
   returnValue <- number1 + number2
   return(returnValue)
}

#function calls without input values. This is possible when the parameters are
#initialised in the function definition. 
addTwoNumbers() #returns 0 (= 0 + 0)

#function calls with just one value.
addTwoNumbers(2) #eturns 2 (= 2 + 0) (number1 gets the value 2; number2 is the default 0)

#function calls with two values
addTwoNumbers(2, 4) #number1=2; number2=4; returns 6 (= 2 + 4)

#function calls with named parameters; note that the order in which parameters are passed
#can be changed
addTwoNumbers(number2=7, number1=4) #returns 11 (= 4 + 7)


#Example2: This function just prints a preset error message to the user when called.
#It neither accepts any paramters nor returns any value.
raiseErrorMessage <- function() {
   print('Error occurred during the process. Pleaes contact the admin for troubleshooting!')
}

#<your main code goes here, during which an error occurred...>
raiseErrorMessage() #prints the error message
#<you further proceed with the code...>

Testing global assignment operator using functions

The variables created as function parameters or other variables that are created inside the funtion block are local variables. Local variables are neither visible nor has scope outside the function. Global assignment operators are used define global scope to variables used in the function body. Let us understand this using the following demo.

x <- 100 #a global variable x

#now, let us try modify the value of x from a function
F1 <- function() {   x <- 200 }
#let us call the function to actually modify and check the value of x
F1(); print(x)

#the above attempt will fail to change the value in x, because of the rules
#of scope of variable as explained above;

#There are three ways we can achieve this:
#1st way:
F2 <- function() { val <- 200; return(val) }
x <- F2()
#The function F2 returns a value that gets assigned to the outside x

#2nd way:
F3 <- function(val=0) { val <- val+100; return(val) }
x <- F3(x)
#The function F3 accepts the x from outside and modifies it; the modified
#value is then returned to the caller where it is transferred to the x
#defined outside

#3rd way:
F4 <- function() { x <<- 200 }
x <- F4()
#The function F4 uses global assignment operator where the LHS operand of <<-
#operator is assumed to be global

#Note that if x is not defined outside before it is used in the function 
#call that uses global assignment operator on it, then a global 
#variable x will be created from function call.

Built-in functions

R comes with several builtin functions in its base package. The functions can be directly called from the script with the required paramters. The help on any function can be seen by typing ?<function name>. Here, most frequently used functions are listed with examples and are grouped by their purpose. Some functions have parameters that are not explained here. Here, we focus only on the essential paramter list.

Data type checking

The function typeof(x) gives the name of data type of the variable x. There are a set of functions whose names follow this pattern check if the variable x belong to the specified data type: is.<datatype>(x). These functions return TRUE or FALSE.

#let us create some scalars and vectors for demo
x <- -Inf; y <- TRUE; z <- NA

typeof(x) #returns 'numeric'
typeof(y) #returns 'logical'

is.numeric(x) #returns TRUE
is.logical(y) #returns TRUE
is.integer(x) #returns FALSE
is.double(x) #returns TRUE
is.character(x) #returns FALSE

is.na(z) #checks if the value is NA
is.null(z) #checks if the value is NULL
is.infinite(x) #returns TRUE
is.finite(z) #returns FALSE

Data type conversions

Type conversion function transforms a variable from one data type to another. There are a few restrictions as well. These functions follow naming pattern: as.<datatype>().

as.numeric('87') #converts string numbers to numeric
as.numeric('X98') #throws error due to the presence of the letter X
as.numeric(FALSE) #returns 0; returns 1 for TRUE
as.integer(67.6123) # returns 67; converts double to integer

as.character(1999) #converts number to string literal '1999'
as.character(FALSE) #returns character value

as.logical(0) #=FALSE
as.logical(5065) #any number greater than 0 are TRUE

z <- 1
as.logical(z) #returns TRUE; 1=TRUE; 0=FALSE

Math functions

Some of the frequently used math functions are listed below.

abs(-18723.23) #removes sign
round(pi, digits=2) #pi value rounded off to 2 decimals
signif(expOf2, digits=3) #extracts 3 significant numbers from pi
floor(pi) #next lowest integer 
ceiling(pi) #next largest integer

log(45) #natural log
log10(45) #log base 10; Similar: log2()
log(45, base=pi) #log base of any number

exp(2) #e power 2
sqrt(56) #square root; cube root?
factorial(3) #3! = 1 * 2 * 3

sin(20) #Similar trignometric functions: cos(), tan(), asin(), acos(), atan()

Date Functions

We have seen that the text form is the convenient way of storing date values in different formats. However, date values can be stored as equivalent numeric values (a relative value with reference to an arbitrary date). Let us see the functions related to date values and their uses.

#let us initialise some date values as character type
programStartsOn <- '11 10 2017' #format: DD MM YYYY
eventEndsAt <- '18 03 21 5:30:00 PM'#format: YY MM DD HH:MM:SS AM/PM

#we can convert the above strings into Date objects, as in:
#pass the date string varible or its literal with format spec.
pso <- as.Date(programStartsOn, '%d %m %Y', tz='Asia/Calcutta') 
eea <- as.Date(eventEndsAt, '%y %m %d %H:%M:%S %p', tz='Asia/Calcutta')

#if you get warnings on timezone, you need to look at zone.tab file in 
#the installation folders of R; the tz specifications are OS specific;
Sys.setenv(TZ='Asia/Calcutta') #the approp TZ for the session will clear it

#once Date objects are created, their formats can be converted to the
#requirements, as in:
format(pso, '%Y %b %d %I:%M %p %z')

#where the format specifications are:
#  %d  - numeric day of month
#  %m  - numeric month of the year
#  %y  - two digit year format
#  %Y  - four digit year format
#  %I  - hour value in 12 hr format
#  %H  - hour value in 24 hr format
#  %M  - minutes of the hour
#  %S  - seconds of the minute
#  %p  - AM/PM for 12 hr format
#  %a  - weekday abbr;     %A  - Full weekday
#  %b  - month abbr;       %B  - Full month
#  %j  - decimal day of the year
#  %U  - decimal week of the year(starting Sunday)
#  %W  - decimal week of the year(starting Monday)
#  %z  - offset from GMT;  %Z  - time zone

#you should have noticed an issue with the previous function call to 
#format(); the time value was ignored with as.Date() conversion;

#the better version of as.Date() to handle these issues is as.POSIXct()
pso1 <- as.POSIXct(programStartsOn, '%d %m %Y', tz=Sys.getenv('TZ'))
eea1 <- as.POSIXct(eventEndsAt, '%y %m %d %I:%M:%S %p', tz=Sys.getenv('TZ'))

#now format() can be executed without any issues, as in:
format(pso1, '%Y %b %d %I:%M %p %z')
format(eea1, '%Y %b %d %I:%M %p %z')

The other date functions and their uses are liste below:

Sys.date() #system date
Sys.time() #system time
Sys.timezone() #system timezone

#to get difference between two dates
difftime(pso1, eea1, units='auto')
difftime(format(Sys.time(),'%H:%M'), format(eea1,'%H:%M'), units='auto')

#specific units of differences can be specified. The options are:
#weeks, days, hours, mins, secs

#difference in months is not available. See 'Functions(Miscellaneous)'.

Iterable container objects

Container objects are used to store multiple values. Vectors, matrices, lists, and dataframes are unique in their structure and purpose. However, they can be related to each other by some of their properties. R allows sensible conversions of one container to another with some restrictions. One of the common feature of container objects is that they are iterable. Iterable refers to a method of accessing elements of a container through sequential looping (see Looping statements).

Vectors

Vectors are single dimensional arrays. They allow values of single data type. When you add a logical value to a numeric vector, the logical values are automatically converted into numeric values (TRUE=1, FALSE=0). On the other hand, when you mix a character value to numeric vector, all elements are converted into character. You can use functions like typeof(), is.numeric() and as.logical() like functions on vectors as well (see Data type checking, Data type conversions). Each element of a vector can be given a name. Named vectors are useful when you have a few elements. However, the data type rules are the same for named vectors as well.

Built-in vectors

#some built-in vectors
LETTERS #upper case english alphabets
letters #lower case alphabets
month.name #12 full month names
month.abb #12 abbreviations of month names

Creating vectors

1:25 #creates a vector of integers starting from 1 to 25
c(1:25) #same as above

c() #does not create a empty vector; it resutls in NULL
vector() #cretes a empty logical vector

#to create an integer vector of length 15 initialized with 0s
vector(mode='integer', length=15L) 

seq(from=1, to=25) #same as above; default interval=1

c(45, 23, 12, 76, 24, 90, 88) #a vector of double data type
c(45L, 23L, 12L, 76L, 24L, 90L, 88L) #a vector of integer data type

c('UAG', 'UGA', 'UAA') #a character vector
c(amber='UAG', umber='UGA', ochre='UAA') #a named character vector

# Mixing data values does automatic type conversion
c(45, 23, 12, 76, 24, TRUE, 88) #numeric vector; TRUE gets the value of 1
c(45, 'XY', 12, 76, 24, 90, 88) #character vector
#note that all numbers have become character literals

a <- c() #giving results against intuition; does not create empty vector; results in NULL
a <- vector() #create empty vector = vector(mode='logical', length=0L)
vector(mode='double', length=10L) #creates double vector of length 10; default values=0

seq(0, 1, by=0.01) #creates numeric vector starting from 0 to 1 with an interval of 0.01

#creates numeric vector with a range of 0 to 1 divided into specified length;
#interval is calculated by length of vector specified
seq(0, 1, length.out=12) 

rep(TRUE, times=10) #creates logical vector of 10 TRUEs
rep(c(TRUE, FALSE), times=10) #creates logical vector of 10 consecutive TRUE, FALSEs
rep(c(1,2,3), each=3) #each element in c(1,2,3) are repeated 3 times
rep(c(1,2,3), each=3, length.out=5) #same as above, but limits the length to 5

Vector type checking

The functions listed under Data type checking also work on vectors. The functions is.na(), is.null(), is.finite(), and is.infinite() checks each element and returns a logical vector representing if the ‘is’ condition matched or not.

x <- c(T, NULL, F, F, T, F, NA); y <- seq(1, 10, length.out=20)
z <- letters; k <- c('red', NULL, 'blue'); u <- c(2, 4, NULL, 5, 9)
#note that the NULL value in logical vector x is replaced with FALSE automatically;
#and the NULL in character vector k and numeric vector u are ignored completely.

typeof(x) #returns 'logical'
typeof(y) #returns 'double'

is.logical(x); is.logical(y) #returns TRUE and FALSE respectively
is.integer(y); is.numeric(y); is.numeric(z) #returns FALSE, TRUE, FALSE respectively

# to check if any of the elements is NA, the following function is used
is.na(x) #returns a logical vector of FALSE, FALSE, FALSE, FALSE, FALSE, TRUE

#whereas, is.null() just checks if the vector x is NULL or not; it does not check
#each elements
is.null(x) #returns FALSE

Vector type conversions

x <- c(12.34, 14.21, 17.06, 14.67) #this is a double vector
as.integer(x) #removes decimal points from x
as.character(x) #converts the double values to string literals

y <- c('12', '00', '15', '17', '00') #this is a character vector
as.numeric(y) #converts the char vector into numeric vector

#converts the char vector into num vector, and then into logical vector
#all zeros are FALSE, values greater than 0 are TRUE
as.logical(as.numeric(y))

z <- c(T, F, F, T, T, F) #this is a logical vector TRUE and FALSE are abbreviated
as.integer(z) #converts logical vector into integer vector; T=1, F=0
as.character(z) #results in 'TRUE', 'FALSE', 'FALSE', 'TRUE', 'TRUE', 'FALSE'

Accessing and editing vector elements

# Accessing vector element by location index

x <- c(12.34, 14.21, 17.06, 14.67) #this is a double vector
x[1] #extracts the first element from x
x[4] <- 20.00 #modifies the 4th element to 20.00; the vector x is modified
x[-3] #extracts all elements other than the 3rd element
x[-c(1,3)] #extracts all elements other than 1st and 3rd element

#WARNIMG:this will overwrite the vector x and replace it with numeric scalar
x <- 20.00
x[] <- 20.00 #this replaces all values with 20.00
x[1:3] <- 10.00 #this will replace the first 3 elements with 10.00
x[c(2,5)] <- 5.00 #this will replace 2nd and 5th element with 5.00


# Accessing vector element by names of elements

stopCodons <- c(amber='UAG', umber='UGA', ochre='UAA') #this is a named vector
stopCodons['umber'] #this extracts the value of element named 'umber'
stopCodons[c('amber','ochre')] #extracts values of elements named 'amber' or 'ochre'


# Logical extraction of vector elements

#this is a sample char vector
randomLetters <- c("z", "r", "o", "n", "g", "j", "s", "v", "i", "f") 

#There are 10 alphabets in this vector; the following will extract all elements in 
#odd positions;
#Note that in the following expression, the logical vector passed to vector access 
#operator [] has the logical value TRUE at odd positions
randomLetters[c(T, F, T, F, T, F, T, F, T, F)]

#With the same vector, the vowels can be extracted by passing the logical vector
#with TRUE in the positions where vowels are present. In the above example the 3rd and 9th 
#positions have the vowels 'o' and 'i' respectively.
randomLetters[c(F, F, T, F, F, F, F, F, T, F)]

#The above methods are feasible when the size of vectors is manageable, and when 
#the positions of required elements are known; the %in% operator makes this
#easy and scalable;
#To make the above example more robust, the following can be used:
randomLetters[randomLetters %in% c('a', 'e', 'i', 'o', 'u')]

# In the above example, the expression inside [], returns a logical vector by matching each  
# element to the reference vector c('a', 'e', 'i', 'o', 'u'); all matching positions gets
# the value TRUE and the remaining gets FALSE

#The above example can reverse the condition (i.e. all elements that are NOT vowels) using
#negation operator, as given below:
randomLetters[!randomLetters %in% c('a', 'e', 'i', 'o', 'u')]


# Logical extraction of numeric vector elements

randomNumbers <- c(8,6,6,rep(3,3),rep(4,3)) #this is sample numeric vector of 9 elements

# The following expression will extract all even numbers
randomNumbers[c(T, T, T, F, F, F, T, T, T)]

#-which can also be achieved (robust and scalable) using the following conditional expression
randomNumbers[randomNumbers %% 2 == 0]

Vector operations

numObservations <- c(2, 3, 2, 4, 2)
numWeights <- c(1.0, 0.5, 0.5, 2.0, 0.1)
numCharge <- c(100, 200, 300)

# scalar operations are performed on every element (applicable to all math operators)
numObservations * 12 #all elements are multiplied by 12

# operations on two vectors of same length (applicable for all opeartions)
rep(2, 5) * numWeights #each complementary pairs are multiplied

#operations on two vectors of differing length (excuted with warning message);
#The lenght of vector with minimum number of elements is automatically adjusted 
#so as to match the length of maximum number of elements; the elements in the minimum
#length vector are repeated (recycled) one or more times to fill the gap
numCharge + numObservations #the numcharge vector is extended to the length 
#of 5 automatically

#the not opeartor on a logical vector reverses all logical values
movementDetected_d1 <- c(T, T, T, F, F, F, T, T, T)
movementNotDetected <- !(movementDetected_d1)

#the logical AND (&) and OR (|) operators checks every elements pair wise on
#two logical vectors
movementDetected_d2 <- c(T, T, F, T, T, F, T, F, T)
movementDetected_d1 & movementDetected_d2

#note that we don't use scalar logical operators && and || on vectors, which when used on 
#vectors checks only the first pair only

Generic vector functions (applicable to all types of vectors)

#let's create a char vector of some alphabets
randomLetters <- c("z", "r", "o", "n", "g", "j", "s", "v", "i", "f") 

names(stopCodons) #works only if the vector elements are named
sort(randomLetters) #sorts alphabets in ascending order

#sample() is a statistical function that samples a given vector (the population)
#for a given sample size; the parameter 'replace' when set to TRUE allows the sample
#to select same elements repeatedly; in statistical terms this kind of sampling is called
#sampling without exclusion or sampling with replacement; when this parameter is set to FALSE,
#sampling does not allow an element from the population to be selected more than once;
#when the sample size is larger than the population, then it becomes mandatory to set replace=T
randomNumbers <- sample(1:10, size=50, replace=T) #samples 50 random numbers in 1:100

sort(randomNumbers, decreasing=T) #sorts the randomNumbers sample in descending order
rev(randomNumbers) #flips or reverses the vector elements
length(letters) #counts elements

randomNumbers2 <- c(8,6,6,rep(3,3),rep(4,10),rep(5,4)) #creates a numeric vector

unique(randomNumbers2) #removes duplicates
freqRandNums <- table(randomNumbers2) #frequency of unique values
#the following expression gets the position of the value having maximum frequency 
#from frequency table ('freqRandNums')
which.max(freqRandNums)

freqRandNums[which.max(freqRandNums)] #fetches the frequency of unimodal value

#let's extend the randomNumbers2 with a repeat of the digit 5 of length 6; this makes 
#the vector bimodal; this is to give a demo on how to get 
randomNumbers2 <- c(randomNumbers2, rep(5,6))
fr2 <- table(randomNumbers2) #this creates frequency table for the modified vector
#the following expression gets all modals of same length from the new frequency table 'fr2'
as.numeric(names(fr2[fr2 == fr2[which.max(fr2)]]))

Numeric vector functions

sum(randomNumbers) #totaling

sum(movementDetected) #logical vector summing; T=1; F=0
#the logical vector summing will be useful to check how many elements in a vector
#matches a particular condition; it is like taking the count of all TRUEs

#to count the number of randomLetters that are vowels
sum(randomLetters %in% c('a','e','i','o','u'))
#to count the number  of elements that are even
sum(randomNumbers %% 2 == 0)

#the following are some frequently used numeric vector functions;
#the parameter na.rm when set to TRUE, ignores missing values present in a vector;
#when this parameter is FALSE (default) and when the numeric vector contains
#missing values (represented by NA), these functions will return NA as the result

mean(randomNumbers, na.rm=T) #averaging
max(randomNumbers, na.rm=T) 
min(randomNumbers, na.rm=T)
range(randomNumbers, na.rm=T) #gives min to max range
median(randomNumbers, na.rm=T) #center average=location
var(randomNumbers, na.rm=T) #variance
sd(randomNumbers, na.rm=T) #standard deviation

#Mode (= the most frequently observed value) function is not avilable in the
#base R; see 'Functions(Miscellaneous)' for a function definition of mode;

#if you want to classify numeric vector values into groups using 
#levels or breaks or bins, use cut() function, as in:

#(1) specify number of groups by 'breaks' parameter
#cuts 1:10 in two equal groups and labels them as A and B
cut(1:10, breaks=2, labels=c('A','B'))
#does the same trick even if numbers are shuffled
cut(c(10, 3, 6, 2, 4, 7, 1, 9, 5), breaks=2, labels=c('A','B'))

#(2) or specify exact break points using a vector
cut(1:10, breaks=c(0,5,10), labels=c('A','B'))
#Note: to include the minimum value in the grouping set the lowest
#break point as minimum-1

#Also note that by specifying labels with a vector of labels, then
#the a factorized vector is returned (See 'Factors' and revisit this...);
#Instead you set labels=FALSE to get numeric ordering of groups as
#a simple vector, as in:
cut(c(1:10), breaks=2, labels=FALSE)

Character vector functions

#the following is a string variable (in R this is a character vector of length 1);
#in english this is a sentence
myText <- 'You can\'t get out of life alive! Be bold!'
#note that in the string we have used the escape character backslash (\) to 
#let R know that the single quote inside the string is a part of it

#to split the above text by space delimiter:
strsplit(myText, split=' ') #creates a character vector of words seperated by single space

#to split the same by exclamatory mark:
strsplit(myText, split='!') #creates a char vector of length 2


#let us create a sample (size=999) of letters denoting nucleotide bases that 
#forms the structure of genes
randomNucleotides <- sample(c('a','u', 'g', 'c'), 999, replace=T)

# paste0 concatenates vector elements using seperator specified by collapse
randomGeneSeq <- paste0(randomNucleotides, collapse='') #note: collapse specifies empty string

#the above expression binds all 999 random base letters (=char vector of length 999) 
#into one string (=char vector of length 1)

length(randomNucleotides) #gives the length of char vector
nchar(randomGeneSeq) #gives the length of the string

randomGeneSeq <- toupper(randomGeneSeq) #converts to upper case

firstCodon <- substr(randomGeneSeq, 1, 3) #extracts part of the string from 1 to 3

# split the gene sequence string by a given length; codons are triplet bases
codons <- substring(randomGeneSeq, first=seq(1, nchar(randomGeneSeq)-2, by=3), 
                 last=seq(3, nchar(randomGeneSeq), by=3))

#the function substring() allows its parameters 'first' and 'last' to
#take a vector of starting positions and ending positions respectively

table(codons) #Frequency of each unique codon in the vector 'codons'


# earlier we had seen strsplit() can be used to split a string using delimiters
# such as a space or or a special character; in fact, the delimiter can be 
# any character or a string or a word; it can also be regular expressions;
# some examples are given below

# split vector by a given value
codons1 <- strsplit(randomGeneSeq, split='UAG') #splits the string using a word ('UAG')

#note that strsplit returns the value as a list; hence, codons1 is a list object

#if split needs to happen if any of a given set of words, then the regular expression
# to be passed to the split parameter is:
splicedSeq <- strsplit(randomGeneSeq, split='(UAG|UGA|UAA)')

#let us create a string literal of special characters;

specialChars <- '~!@#$%^&*()_+-={}[]|\\:;"\'<,>.?/' #there are 31 special chars in this string
#note that for some special characters when written in a string literal, they
#need to be given with escape character backslash (\); 
#such special characters are the backslash itself, and a single quote;
#a single quote needs an escpae character when it appears inside a string enclosed by two
#single quotes; if a string literal is enclosed within double quotes then the single
#quote does not require the escape character, instead a double quote will;
#try to remove the escape character and see what happens

#suppose if your string contains any of these special chars and you want to 
#split your string by one of the special characters, then you can very well
#use them as delimiters EXCEPT for $ (dollar), ^ (caret), * (asterisk), () (open or close
#parentheses), + (plus), {} (open or close curly brackets), [] (open or close square
#brackets), | (pipe), . (dot), ? (question)

#if you still want to split a string with these exceptional special chars, then
#use the following regular expression:
unlist(strsplit(specialChars, split='\\$')) #just replace $ with any of the exceptional chars 

#in addition to that,if you want to split by backslash, then use:
unlist(strsplit(specialChars, split='\\\\'))
#and for a single quote (also double quote if the string enclosed in double quotes)
unlist(strsplit(specialChars, split='\''))


# search and extract char vector using grep() function and regular expressions

#let us create some char vectors for demo
chemFormulae <- c('NaHCO_3','NaClO','H_2O_2','NaBO_3','Na_2B_4O_7.10 H_2O','S','KHC_4H_4O_6',
                  'MgSO_4.7 H_2O','CF_2Cl_2','PbS','C_2H_5OH','C','CaSO_4.2 H_20','Na_2S_2O_3',
                  'N_2O','CaO','CaCO_3','NaOH','CaCO_3','CH_3COC_2H_5','Mg(OH)_2','HCl',
                  'H_2SO_4','CaSO_4.2 H_2O','K_2CO_3','FeS_2','SiO_2','Hg','(CH_3)_2CHOH',
                  'NH_4Cl','NaCl','KCl','KNO_3','Ca(OH)_2','C_12H_22O_11','Na_3PO_4',
                  'Na_2CO_3.10 H_2O','CH_3OH')
chemNames <- c('sodium bicarbonate','sodium hypochlorite','hydrogen peroxide',
               'sodium perborate','sodium tetraborate decahydrate','sulfur',
               'potassium hydrogen tartrate','magnesium sulfate heptahydrate',
               'dichlorodifluoromethane','lead (II) sulfide','ethanol','carbon',
               'calcium sulfate dihydrate','sodium thiosulfate','dinitrogen oxide',
               'calcium oxide','calcium carbonate','sodium hydroxide','calcium carbonate',
               'ethyl methyl ketone','magnesium hydroxide','hydrochloric acid',
               'sulfuric acid','calcium sulfate hydrate','potassium carbonate',
               'iron disulfide','silicon dioxide','mercury','isopropyl alcohol',
               'ammonium chloride','sodium chloride','potassium chloride',
               'potassium nitrate','calcium hydroxide','sucrose','sodium phosphate',
               'sodium carbonate decahydrate','methyl alcohol')

# the general syntax of grep() function is:
# grep(pattern='the regular expression is used here', 
#      x=<the char vector that needs to be searched>, 
#      ignore.case=F, value=F)

#the 3rd parameter 'ignore.case' is set to TRUE or FALSE for toggling case sensitivity;
#the 4th parameter 'value' is set to TRUE if you want the grep() to return the elements
#in the vector that matches the regular expressions; by default (FALSE) it returns the 
#index position of the matching elements

grep('OH', chemFormulae) #returns index locations of compounds having OH group
#in the above expression, grep searches for the presence of OH as is;
#when the search string OH is given within square brackets - '[OH]', then
#it will result in compounds that have oxygen and/or hydrogen in its formulae;

#note that the above expression returns the index locations as a vector; which can 
#be used to fetch the related elements from chemFormulae or chemNames, as given below:
chemFormulae[grep('OH', chemFormulae)]
#this is equivalent of grep('OH', chemFormulae, value=T)
#but the index locations are useful, if used to get the corresponding chemical names that
#are stored in a different vector (chemNames), as in:
chemNames[grep('OH', chemFormulae)]


#to search for Na or K in the compounds, let us try:
grep('[NaK]', chemFormulae, value=T) #there is a problem in this!

#the above expression will fetch the compounds with the letters N, a, K, which
#is not the intended search; we wanted to consider Na as a seperate search option 
#along with K; in order to achieve the expected results, we would use the following:
grep('Na|K', chemFormulae, value=T)

#suppose, we want to search for compounds that have Na or K and also 
#followed by 'OH' somewhere; let us try using the regular expression as given below:
grep('Na|K.*OH', chemFormulae, value=T) #there is a problem here!

#before solving the problem, let us understand the use of .*;
# the dot character represents any character and * indicates that the preceding 
#character may appear any number of times; here the preceding character is any 
#character (which is a dot!)

#the above results, in fact finds all compounds with Na or K, but it does not
#correctly identified the OH groups after Na or K; instead it searched for the 
#letters O or H after Na or K; this problem can be solved using the following 
#expression:
grep('(Na|K).*(OH)', chemFormulae, value=T)
#in the above expression, we have introduced () to enclose the search words, which
#will fetch hydroxide compounds of Na and K


#let us now try to extract all hydrated compounds (=the compounds that have
#H_2O group)
grep('.*(H_2O)', chemFormulae, value=T) #why does it fetch H_2O_2?
#the above expression fetches hydrated compounds including hydrogen peroxide (H_2O_2)
#which is having two O atoms at the end (O_2) and not expected to be part of the search;

#we can solve the above problem, by using $ symbol to denote the end of search, as in:
grep('.*(H_2O)$', chemFormulae, value=T)


#earlier we have created a vector of triplet codons in the variable 'codons';
#if you want to search for those codons that start with the base A and end with base U
#having any letter in between, then follow the regular expression as given below:
grep('^(A).(U)$', codons, value=T)

#let us say we have a character vector of binary literals, such as:
binaryCode <- c('1100001100','000000','1111111111', '10001100', '0011110000')

#if you want to search for the codes that should start with 11, then the expressin is:
grep('^11.*', binaryCode, value=T) #.* allows any digits to succeed 11

#suppose, if you want to make the second digit of the starting value 11 to be optional,
#then use suffix ? to the digit that you want it make it optional, as in:
grep('^11?.*', binaryCode, value=T) #? makes the preceding character optional

#the following fetches the binary codes having four 1s anywhere within the string
grep('1{4}', binaryCode, value=T) #use of {n} repeats

#whereas, if you want to extract the binary codes having four 11s anywhere within, then
#enclose 11 within parenthesis to group:
grep('(11){4}', binaryCode, value=T) #use of {n} repeats

#you may add a range of values within curly braces as well; for instance the 
#following expression will fetch codes where 1s are repeated 2 to 4 times
grep('1{2,4}', binaryCode, value=T) #use of {n,m} range repeats


#let us create another vector of alpha numeric passwords for demo:
alphanumCodes <- c('XX000AXZER2','X3000AXZERV','YY021AXYOQ5',
                   'X5000AXZERQ','ZZ103AXUIR1', 'X9XX45PORT')

#matching word should start with X followed by a digit; .* for any chars after that
grep('^X[0-9].*', alphanumCodes, value=T) 
#matching word should start with a capital letter followed by a digit
grep('^[A-Z][0-9].*', alphanumCodes, value=T)

#building a complex pattern: should start with atleast 2 capital letters followed 
#by 3 digits and five letters and finally should end with a digit
grep('^[A-Z]{2}[0-9]{3}[A-Z]{5}[0-9]$', alphanumCodes, value=T) #how to build a pattern?

#should not start with ZZ (denoted by ^[^Z]{2}), but at 3rd position there should be
#3 digits and five capital letters, but should end with a digit
grep('^[^Z]{2}[0-9]{3}[A-Z]{5}[0-9]$', alphanumCodes, value=T) #use of '^' within []?


#gsub is similar to grep, except for replacement string
gsub(pattern='(UAG|UGA|UAA)', replacement='|*|', randomGeneSeq)
#the above expression replaces the words UAG or UGA or UAA with |*| when
#found in the string 'randomGeneSeq'

Matrices

Matrices are extension of vectors. While vectors are single dimensional arrays, matrices are multidimensional. Like vectors matrices are also strongly typed. Data type mixing follows the rules explained for vectors. (see Vectors). Matrices can be viewed as a collection of column vectors or row vectors. They have rows and columns like a table. Number of rows and columns define the 2D structure. Here, we focus on 2D matrices. Like named vectors, each column or row can be given a name.

Creating matrices

matrix() #creates a 1R X 1C matrix with a value of NA
matrix(nrow=5) #creates a 5R X 1C matrix with default values of NAs
matrix(nrow=5, ncol=5) #creates 5R X 5C matrix (with NAs)
matrix(0, 3, 5) #creates the 3R X 5C matrix with 0 as default values

#any vector can be converted into 2D matrix of different plausible dimensions;
#for instance:
numVector <- 1:36 #a numeric vector of 36 elements starting from 1 to 36

#the above vector can be converted into matrices of 18 different dimensions;
#a few examples are given below:
matrix(numVector, nrow=1) #creates 1R X 36C matrix; values filled from numVector
matrix(numVector, ncol=6) #creates 6R X 6C square matrix; values filled columnwise
matrix(numVector, ncol=6, byrow=T) #6R X 6C matrix; but values filled rowwise
matrix(numVector, nrow=4, ncol=9, byrow=T) #4R x 9C matrix; values filled rowwise


#let us create a 4X5 matrix of random numbers
matRandomNum <- matrix(sample(0:10, 20, replace=T), nrow=4, byrow=T)
#let us also create 6x6 matrix of random letters (lower case)
matRandomChar <- matrix(sample(letters, 36, replace=T), ncol=6)

Matrix type checking and conversions

Like vectors matrix is also strongly typed. Hence, type checking follows the rules of vectors. see Vector type checking for more details.

typeof(matRandomChar) #returns 
is.logical(matRandomNum)

#however, with type conversion there is a problem!. The good news is the conversion occurs
#correctly; but it also removes #the dimension from the source matrix and converts the 
#result into a vector 
as.logical(matRandomNum) #returns a logical vector (0 = F; >0 = T)
#WARNING: Also, the logical vector resulting by reading the matrix columnwise

#To solve these problems, you would need to convert the resulting vector into
#matrix, as in:
matrix(as.logical(matRandomNum), nrow=4) #do not use byrow=T in this expression!

Accessing and editing matrix elements

Vector elements are accessed using [i] operator with either the index location (i) or the name of the element (as string literal within quotes) if it is a named vector. Similarly, matrix also uses the same operator. However, you would need to specify row and column index - [r,c], to handle 2D matrix. Alternatively, you may use column names and/or row names.

dim(matRandomChar) #returns the dimension vector (rows, cols)
nrow(matRandomNum) #returns number of rows
ncol(matRandomChar) #returns number of cols

colnames(matRandomChar) #reads column names vector; by default this is NULL
row.names(matRandomNum) #reads row names vector; by default this is NULL
colnames(matRandomNum) <- sprintf('Series%d', 1:5) #sets column names
row.names(matRandomNum) <- sprintf('Obs%d', 1:4) #sets row names

#accessing by index locations
matRandomChar[3, 5] #value of element at 3rd row and 5th column
matRandomChar[3, ] #values of elements at 3rd row completely (row vector)
matRandomChar[, 5] #values of elements at 5th column completely (column vector)

matRandomChar[1:3, ] #first 3 rows only
matRandomChar[, c(2,4)] #2nd and 4th columns only

#to extract a block of matrix within matrix starting at 2nd row/3rd column and
#ending at 3rd row/5th column
matRandomChar[2:5, 3:4]

#a few examples to access by column and row names
matRandomNum['Obs2', ] #row identified by row name 'Obs2'
matRandomNum[c('Obs3','Obs5'),  ] #multiple rows identified by the given rownames
#the elements in row (Obs2), but only from the columns - Series2 and Series4
matRandomNum['Obs2', c('Series2', 'Series4')]

#When you know the ways to access a single element or a row or a column or a block of
#elements, you may also change them by assignment operator just like how you modified
#elements of a vector!

Matrix operations

You can do math and logical operations on matrix with scalar, vector, and matrix operands. The scalar operations are simple. The operations using the other two have certain rules and limitations. These are explained with examples below:

#scalar operations (applicable to all math and logical operations)
matRandomNum + 2 #adds two to all elements
(matRandomNum / 2) * 1.5 #divides the elements by 2, then multiplies by 1.5

#the following expression, first gets reminder of division (modulus) by 2 on all 
#elements, then compares if each element equals to 0; returns a logical matrix
#based on the match
(matRandomNum %% 2) == 0

matRandomChar != 'a' #checks if each character equals 'a' or not; retunrs logical matrix

# using vector operands with matrices
# the following expression checks if any of the element equals any of the letters given
# in the reference vector (here it is vowels vector); there is a problem here!
# this operation removes the matrix dimension and creates a vector whose length equals to
# the total number of elements in the matrix;
# also note that the matching follows columnwise operation (use byrow=F when you recreate
# the complementary matrix using matrix() function)
matRandomChar %in% c('a','e','i','o','u')

#if numeric operations are specified with a vector of more than one elements, then the 
#vector elements are recycled; first it will start with 1st column 1st row, then it moves down
#the column, then it moves to the next column; it goes on until it fills all positions;
matRandomNum + c(4:1) #this operation creates a virtual matrix of the same dimension and uses
#the vector elements to fill matrix with values following the rule explained above; the virtual
#matrix will look like this:
vmat <- matrix(c(4:1), nrow=nrow(matRandomNum), ncol=ncol(matRandomNum))
#now, the math operation will use vmat in place of the vector as given below;
matRandomNum + vmat #each complementary element will be added;
#you wont be seeing the above steps when execute matRandomNum + c(4:1); 
#but it explains the underlying process of such operations;
#the above method is applied to any math operation on a matrix with vector operands of any size

#note that, in the above example, the ultimate operation is applied on two matrices; 
#and the matrix addition creates matrix of the same size (otherwise known as conformable 
#matrices or arrays);
#matrix additions, subtractions, multiplications, divisions and other math operations on element
#by element basis; the elements at the complementary positions are added, subtracted, and so on.

#these kind of math operations will fail on non-conformable matrices; for example:
vmat * matrix(rep(1:2, 3), nrow=3) #will fail due to non-conformity, while...
vmat * vmat #will succeed

#the above matrix multiplication is a simple one to one process and uses the regular
#multiplication operator - asterisk (*);
#while talking about matrix operations, we need to know the true 'matrix multiplication' that
#follows a special arithmetic rules; and in order to specify this tru matrix multiplication
#R uses a special multiplication operator - %*%; the rules and examples are given below:

#Rules of true matrix multiplication:
#(1) The primary rule (conformity rule) is that the number of columns of the first matrix 
#should be equal to the number of rows of the second matrix.

#for instance, the following is a self-multiplication, which will fail according to the 
#above rule; same rule is applicable for any two matrices of different dimensions.
vmat %*% vmat

#however, the above operation will succeed if vmat is a square matrix

#in order to achieve self-multiplication on non-square matrices, you may need to transpose 
#the matrix, as in:
vmat %*% t(vmax)

Matrix functions

colSums(matRandomNum, na.rm=T) #Sum on each column
#colSums creates a row vector
#na.rm=T makes sure that the missing values are ignored

rowSums(matRandomNum, na.rm=T) #Sum on each row
#rowSums creates a column vector

colMeans(matRandomNum, na.rm=T) #Average of each col
round(colMeans(matRandomNum, na.rm=T),2) #nesting the above function with round()

rowMeans(matRandomNum, na.rm=T) #Average of each row

cbind(matRandomNum,rowSums(matRandomNum)) #adds a column to a matrix
rbind(matRandomNum, colSums(matRandomNum)) #adds a row to a matrix

t(matRandomNum) #tranpose of matrix
solve(matRandomNum[,1:4]) #inverse of a matrix (complex mathematical operation)

Lists

Lists are like containers of different kinds of objects. Each object can be named. The objects do not loose their type or class just being a part of a list. In R workspace, all variables and objects that are once created become part of a unnamed global list. This list can be accessed using the function ls().

Creating lists

aListOfObjects <- ls() #fetches all available objects in the workspace
#aListOfObjects is a list

#the following creates a list of combination of numeric, character and logical vectors.
lstGCS <- list(CO2=c(400,600), temp=c(20,30), photoperiod=c('auto','default'), 
               humid=c(40.5, 60.0), 
               isWaterFlowRegulated=c(T,F))

#you may create objects externally and then create a list out of it
#first, let us create a few objects
CO2=c(400,600)
isWaterFlowRegulated=c(T,F))
photoperiod=c('auto','default')
humid=c(40.5, 60.0)

#the following is a list of all objects created above, including a character string
lstSettings  <- list('default settings', CO2, isWaterFlowRegulated, photoperiod, humid)

#note that the above list of objects are not named yet; however, it is only optional;
#the names can be set like this:
names(lstSettings) <- c('title', 'param1', 'param2', 'param3', 'param4')

#a new list can be merged with an existing list, as in:
miscSettings <- list(intensity=c(32000, 120000))
c(miscSettings, lstGCS) #merges the two lists (any number of list can be merged like this)

#if a vector is added to a list, each vector element will be added as an independant
#object to the list; for instance, the following operation will create a list of length 4.
c(miscSettings, c(1,2,3)) #the length of list will be 4

#the right way to do that is by using list() function itself
list(miscSettings, c(1,2,3)) #the vector is merged as a list (length=2)

Accessing list elements

lstSettings[[2]]  #second object in the list
lstSettings$param4 #fetch object using a name

lstGCS$photoperiod #extracts photoperiod of its original type i.e. a vector
#whereas, the following will return photoperiod as a list object
lstGCS['photoperiod'] #gets a vector as a list object

#if you want to extract the first element in the vector photoperiod that is part of a list,
#the you might use the following syntax intuitively:
lstGCS['photoperiod'][1]
#however, the result is same as the previous command (and does not extract the first 
#element in photoperiod)

#unlists a list to solve the expected result from the above problem i.e. to get the 1st
#element
unlist(lstGCS['photoperiod'])[1]
#or, you may use:
lstGCS$photoperiod[1]

#the list objects can be accessed using numeric index
lstGCS[3] #returns photoperiod as a list
lstGCS[[3]] #returns a vector (unlists a list)
lstGCS[[3]][2] #returns the 2nd element of 3rd object if it is a vector

Factors

Factors are unique values, otherwise known as levels or factors, of vectors. The levels are sorted alphabetically or numerically (depending on the type of vector) in ascending order. And this ordered levels are numbered starting from 1 to the length of levels. The order and numbering can be changed while creating a factor of a vector.

Creating factors

isAmorphous <- c('Yes', 'No', 'No', 'Yes', 'No') #just a char vector
is.factor(isAmorphous) #checks if a factor is associated with a vector

isAmorphous <- factor(isAmorphous) #factorizes a vector
# or use
isAmorphous <- as.factor(isAmorphous) # but levels can't be reordered with this

levels(isAmorphous) #returns levels; two levels: 'No' and 'Yes' where 'No'=1, 'Yes' = 2
labels(isAmorphous) #vector of default names given to each element. chr vec: '1','2',...'5'
str(isAmorphous) #structure of vector with factor

factor(isAmorphous, levels=c('Yes','No')) #changes the order of levels
factor(isAmorphous, levels=c('Yes', 'N')) #incorrect levels coerces values to NA

isPresent <- c(1, 0, 0, 1, 1, 0, 0, 0, 0, 1) #just a numeric vector
#Warning! Better not to use factoring when the number of levels is unmanageable
isPresent <- factor(isPresent) #factorizes the numeric vector
#in the above case, 0 will be factored as 1, and 1 will be factored as 2!

labels(isPresent) #chr vec of num seq: '1','2',....'10'
levels(isPresent) # 0 and 1
str(isPresent) #structure of the vector with its levels

#we know that isAmorphous is a character vector, hence any math operation does 
#NOT make any sense; but there are occasions - like specifying weights for
#categories, you might need to convert them into numeric equivalent;
#factoring helps you with the conversion, while retaining the character values;

isAmorphous*2 #will give NA results, but 
#the following will use the numeric equivalent as per factor definition, and the
#math operation will succeed
as.integer(isAmorphous)*2

#you would expect,
isPresent * 2 # to succeed because isPresent is a numeric vector, but
#the above will result in NAs due to factoring;

as.integer(isPresent) * 2
#the above operation will be the multiplication 2 with the factor values 
#rather than the actual numeric values of the vector

#The above case might have given you an idea about why factoring of numeric
#vectors with many unique values (levels) might create confusion!

#Note: 
#(1) you have to refactor the factored vector everytime when you modify the vector
#(2) the subset of a factored vector retains the levels
#(3) if X is a factored vector, as.vector(X) removes factors, but this process
#    always converts X into a character vector irrespective of its original type;
#    similarly, you may use as.xxxx() functions appropriately; see 'Data type checking
#    and conversions' for as.xxxx() functions.
#(4) the same rules are applicable for logical vectors as well

Data frames

Data frames are also container of different types of vectors of same length. They are equivalent of 2D matrix in terms of dimension, but unlike matrices, they can accomodate different data types. That means each row may be a collection of different data types, while each column is a collection of values of the same data type only. They are also equivalent of data table just like a MS Excel sheet containing table data.

Creating dataframes

# Create dataframe using vectors

#let us create vectors of same length
colID <- c(1:10)
colSamp <- sample(200:300, 10, replace=F)
colRandFrac <- runif(10)
colLogical <- c(T, F, T, F, T, F, T, F, T, F)
colQual <- c('ace','mod', 'simp', 'ace', 'cool', 'ruf', 'simp', 'ace','mod', 'top')

#the following will create a dataframe of the above vectors as columns
dfTmp <- data.frame(colID, colSamp, colRandFrac, colLogical, colQual,
                    stringsAsFactors=F) #cretes df
names(dfTmp); colnames(dfTmp) #variable names as col names
row.names(dfTmp) #default row names

#Warning! if length of one of the columns differ, its length will automatically 
#be adjusted to the max length of all vectors; however, if more than one column
#has differing lengths, then R will throw an error;


# Creating dataframes using matrices

#let us create a matrix of 6R X 5C of numeric type
growthByDay <- matrix(
  c(5.0,4.0,5.0,5.2,6.0,
    5.5,4.0,6.0,5.2,5.5,
    6.0,5.0,9.0,5.2,6.0,
    6.2,5.5,8.0,5.2,5.5,
    6.3,5.6,7.0,5.2,6.0,
    6.3,5.7,4.0,5.2,5.5),
    ncol=5, nrow=6, byrow=T)
row.names(growthByDay) <- 1:6 #set row names
colnames(growthByDay) <- sprintf('exp%d', 1:5) #give column names

class(growthByDay); dim(growthByDay) #checks the class name and dimension of matrix
dfGrowthByDay <- as.data.frame(growthByDay) #converts matrix into dataframe

names(dfGrowthByDay); colnames(dfGrowthByDay) #col names same as that of matrix
row.names(dfGrowthByDay) #row names same as that of matrix


# Create dataframe using lists provided:
#(1) there are only vectors in the list (scalars are actually single values vectors)
#(2) the vectors in the list should have same length or their lengths are adjusted
as.data.frame(lstGCS)

#In the following list, there are vectors that are of lesser length, but the conversion
#automatically adjusts their length to the maximum length of other vectors
lstGCS1 <- list(CO2=400, temp=20, photoperiod=c('auto','default'), humid=c(40.5, 60.0), 
               isWaterFlowRegulated=T) #df of 2 rows; if humid is of length 3 then fails
as.data.frame(lstGCS1) #succeeds;lengths are adjusted using recycling

lstGCS2 <- list(CO2=NA, temp=20, photoperiod=c('auto','default'), humid=c(40.5, 60.0), 
                isWaterFlowRegulated=T)
as.data.frame(lstGCS2) #succeeds with NA; but for NULL this will fail with error

#Note: if a dataframes is present in the list, the list to dataframe conversion will
#succeed only if the lengths of vectors present in the list and the row length of 
#dataframe objects are the same.

Accessing dataframe elements

dfTmp[1:5,] #first 5 rows as f
dfTmp[5:10, c('colID', 'colQual')] #last six rows and only two cols as df

dfTmp[ ,"colLogical"] #just one col as vector
dfTmp$colSamp #just one col as vector

Functions of dataframes

dim(dfTmp); nrow(dfTmp); ncol(dfTmp) #gets dimensions

colSums(dfTmp[,1:3]) #on numeric columns only

dfTmp <- edit(dfTmp) #opens the dataframe with an editor

head(dfTmp); tail(dfTmp) #gets first and last few rows of dataframe
#head and tail also works for matrices and vectors

#Note: Treat each column as a vector: which means that all vector functions can be applied

#while, cbind and rbind functions can merge two data frames together 
#horizontally or vertically; 
#however, it has limitations or constraints;
#for example, to cbind two dataframes, they should have equal number of
#rows; 
#similarly: to rbind they should have equal number columns; in addition to
#this rbind requires the data type of columns being merged should match;

#if two dataframes are associated by a common column (known as key column),
#then they can be merged by their key; the key can be a combination of more
#than one columns;

#let us first construct two dataframes that share a key column:
dfX <- data.frame(ID=c(1:3), col=c('red','blue','green'))
dfY <- data.frame(ID=c(1:3), what=c('apple','berries','leaves'))

#to merge the above two dataframes by the column 'ID':
merge(x=dfX, y=dfY, by='ID')

#if key column names are different as in:
dfX <- data.frame(ID=c(1:3), col=c('red','blue','green'))
dfY <- data.frame(key=c(1:3), what=c('apple','berries','leaves'))
#then,
merge(x=dfX, y=dfY, by.x='ID', by.y='key')

#if one of the table has missing observations, as in:
dfX <- data.frame(ID=c(1:3), col=c('red','blue','green'))
#the observation with ID value 2 is missing
dfY <- data.frame(ID=c(1,3), what=c('apple','leaves'))
#then, only the matching entries will be merged, as in:
merge(x=dfX, y=dfY, by='ID')

#however, you may specify, for which of the dataframes you want
#to have all entries; (where the missing values of the other, 
#if any, will be replaced with NA values), as in:
merge(x=dfX, y=dfY, by='ID', all.x=T, all.y=F)


#you can sort the dataframe by a one or more column names, as in:
dfX[order(dfX$ID, decreasing=T), ] #sorts by ID in desc. order

#you can apply an aggregate function on dataframes, as in:
dfA <- data.frame(vals1=1:21, vals2=runif(21), grp=cut(1:21, breaks=3, labels=F))
aggregate(dfA[,c('vals1','vals2')], by=list(dfA$grp), FUN=mean)

#Note1: you include more than one column in the list of 'by' parameter
#to specify a combinatorial grouping column;
#Note2: you may also specify user defined function or any of the aggregate
#functions instead of 'FUN=mean'.

Creating empty objects by object name functions

a <- c() #NULL

vec <- vector() #logical empty
veca <- vector(mode='integer', length=10) #10 zeros; mode=>class

lst <- list() #list of 0 objects
fs <- factor() #factor with 0 levels

df <- data.frame() #empty df: 0r x 0c
typeof(df) #list; class(df) #data.frame

Flow Control

In programming, it might be required to conditionally control the operations, to call functions, and to use expressions. The conditions will make the linear flow of the program to branch out one or more times. Hence, the single starting point of the program might take different paths before it reaches one of the end points. The conditions are like the nodes of branches in the flow of the program. In R programming, if(), ifelse(), if()..else if()..else are the conditional structures available.

#The basic control structures

#Let us create the variables a and b
a <- 10; b <- NA

#To verify if the control statements affect the opertion on these
#variables, let us print their values
cat(sprintf('a=%0.2f, b=%0.2f\n', a, b))

if(TRUE) a <- 20 #it is as if you are changing a <- 20 directly
#what will happen with the following check?
if(FALSE) b <- 60

cat(sprintf('a=%0.2f, b=%0.2f\n', a, b))

#let us introduce, dichotomous control
if(a <= 10) a <- a * 2 else a <- a / 2 #one line if..else
#note that the operations inside if..else control are assignments

cat(sprintf('a=%0.2f, b=%0.2f\n', a, b))

#we can also make if..else to return values conditionally
b <- a <- if(a <= 10) a * 2 else a / 2 #if..else returns

cat(sprintf('a=%0.2f, b=%0.2f\n', a, b))

#the more convenient readable variant of if..else form is...
d <- ifelse(a <= 10, a*2, a/2)

Within if or else conditions, we might need to use more than one line of codes. R supports that with if(){}.. else{} code block structure

message <- ''
#the following is a simple one-line code block
if(a == b) {message <- 'a equals b'} else {message <- 'a and b are different'}
print(message)
#or,
if(a == b) {print('a equals b')} else {print('a and b are different')}

#for a more readable if..else block, use the following syntax and indentations
c <- 0
if(message == 'a equals b'){
  c <- sqrt(a)
  print(sprintf('The value of c is: %0.2f', c))
} else {
  print('The value of c is not changed')
}
#note that within {} multiple lines of codes can be included

For complex flow control, you may enclose one if..else block within another. This is called nesting of controls. Multiple “nested if’s” are allowed in R.

randomLetters <- sample(letters, 20, replace=T)
vowels <- c('a', 'e', 'i', 'o', 'u')
selectedNumbers <- c(16, 49, 25, 81, 27)

if (sum(randomLetters %in% vowels) > 0) {
   print('At least one alphabet is a vowel')
   if(any(selectedNumbers %% 6 == 0)) {
      print('At least one number is divisible by 6')
   } else {
      print('None of the numbers is divisible by 6')
   }
} else {
   print('No vowels present in the alphabets selected ')
}

The if..else block is not simply dichotomous. It can have multiple levels of checks in between.

#what will be the output with the following control structure?
habitat <- 'exosphere'
if (habitat == 'water'){
  print('Is it fresh or salt?')
} else if (habitat == 'land') {
  print('Is it elevated or plain?')
} else if (habitat == 'air') {
  print('Does it float or fly?')
} else {
  print('Is it alien?')
}

Looping structures

Sometimes, you might need to repeat a particular opertion for a finite or infinite number of times. Such repeatitions are called loops. R has two looping structuers namely “for” loop and “while” loop. The former is a finite loop by its definition. Whereas, only the while loop can be written as infinite loop. However while loop can be modified to become finite. When the loop is finite, you may want to have control for an early conditional exit. Similarly, you may want to have a conditional exit in infinite loops. The “break” command supports such exit in R. They can be made conditional by wrapping them in if..else controls.

#a simple for loop
for(i in 1:10) print('hello world!') #prints hello world 10 times

#you can make use of the iterator variable (i) in the for expression
for(i in 1:10) print(i*2)

#the sequence in for loop can be any vector, as in:
for(thisname in c('Aconite','Aster','Aubrieta')) print(thisname)

#the vector can be passed as a variable
diseases <- c('Malaria','Typhoid','HIV')
for(disease in diseases){
   cat('The causal agent is a ')
   if(disease=='Malaria'){
      cat(sprintf('Protozoan\n'))
   } else if(disease=='Typhoid'){
      cat(sprintf('Gram negative bacterium\n'))
   } else {
      cat(sprintf('Virus\n'))
   }
}
#also, note that we enclosed a block of code to be executed in the for loop
#within {}

The for loop can be used on iterable container objects (matrices, lists and dataframes) whereever it makes sense, as in:

#let us loop through the rows of the matrix 'growthByDay'
for (r in 1:nrow(growthByDay)){
   print(mean(growthByDay[r,])) #prints mean value of each row vector
}
#Similarly, you can loop through column vectors

The for loop can be nested, as in:

#let us loop through each cell of the matrix, using nested loop
for (c in 1:ncol(growthByDay)){
  print(names(dfTmp)[c])
  for (r in 1:nrow(growthByDay)){
    if (r < nrow(growthByDay)){
      cat(sprintf('%0.2f\t', growthByDay[r,c]))
    } else {
      cat(sprintf('%0.2f\n', growthByDay[r,c]))
    }
  }
}

“for loop” works on list object as well, as in:

i <- 0
for (item in lstGCS) {
  i <- i + 1
  #cat(sprintf('List%d:\t', i))
  #or to start with the name of the list item
  cat(sprintf('%s:\t', names(lstGCS)[i]))
  if (length(item) > 1){
    for (itemval in item) cat(sprintf('%s\t', itemval))
    cat('\n')
  } else {
    print(item)
  }
}

The early exit from “for loop” can be achieved using conditional break, as in:

cnt <- 0
for (i in 1:1000){
   Sys.sleep(0.01)
   cat(sprintf('\r%d', i)) #to pause for 0.01s
   samp <- sample(1:20, 100, replace=T) #sample of 100 values btwn 1 and 20
   #if mean of this random sample equals 10 print message and exit
   if (round(mean(samp),2) == 10) {
      cat(sprintf('\nIt took %d trials to arrive at mean of 10.\n', i))
      cnt <- i
      break
   }
   cnt <- cnt + 1
}

To achieve infinite loop ‘while loop’ can be used. Note1: press Ctrl+C or Ctrl-Z to exit forcefully from infinite loop Note2: if you are in R Studio, click on Stop sign (red filled hexagon) to the top right corner of the title bar of Console pane

i <- 0
while(TRUE) {
  Sys.sleep(0.01); cat(sprintf('\r%d', i))
   i <- i + 1
   #if(i == 200) break
}
#Note: Uncomment the "#if(i == 200) break" in the above to exit conditionally

#The while loop can also be made a finite if condition is given to while(),
#as in:
j <- 100
while(j <= 100){
   print(j)
   #the following early exit can also be used
   #if(j*5==25) break
}

There are some special functions in R, such as apply, sapply, and lapply, to apply any function on each element of a list or vector iteratively.

#the following sapply() applies exp() function on each element of the
#sequence 1,2,3,..,10, and returns a vector of exponents.
sapply(1:10, FUN=function(x) exp(x))

#if 'sapply' is replaced with 'lapply', the return values are the same, but
#the values are returned as a list, as in:
lapply(1:10, FUN=function(x) exp(x))
#you need to wrap the above command with unlist() to convert the returned 
#list into a vector

#however, lapply may be useful to loop through column vectors of a dataframe,
#as in:
lapply(dfTmp, FUN=function(x) table(x))
#though, the frequency function (table) works for most kinds of data types, 
#it may not make sense to use it on continuous numeric data and discrete
#numeric vector containing numerous unique values

#Unlike lapply, the 'apply()' has a provision to choose the margin of the 
#matrix or a dataframe on which the function can be applied;
#the margins are either row vectors or column vectors;
apply(growthByDay, 1, FUN=mean) #margin 1 denotes row vectors of the matrix
#the above is equivalent of the following:
rowMeans(growthByDay)

#similarly,
apply(growthByDay, 2, FUN=mean) #will give..
colMeans(growthByDay)


#Note that, in all the above apply functions, the vector or list passed 
#can be of any type; only constraint is that an appropriate function 
#needs to be applied based on the data type;

#Also note that, the function applied can be any built-in function in R or
#any user-defined function

Data inputs

R has several ways to accept input from the user or external files and output the data to console or files. Some of them are exemplified below.

#to access the value of the key pressed by the user:
keyIn <- readline()

#the following is a user-defined function that accepts keyboard input
# and prints the numeric equivalent of the key pressed;
#it keeps asking for user input until Esc key is pressed
getValOfChar <- function(){
  keyIn <- readline(prompt='Enter any key(Press Esc to stop):')
  
  if (is.na(keyIn)) {
    return(NULL)
  } else {
    keyVal <- as.integer(charToRaw(keyIn))
    cat(sprintf('%s: %d\n', keyIn, keyVal))
    getValOfChar()
  }
}
#make a call to the function:
getValOfChar()

Instead of waiting for individual key press event, the scan() function allows the user to input a definite number of values; the data type can be specified

#prompt the user
print('Enter five observations of tree girth (Ctrl-Z or Esc to end)')

#accept the value inputs from the user (comma delimited)
treeGirths <- as.double(scan(what='double', nmax=5, sep=','))

#do whatever with the values read
cat(sprintf('Average±SD tree girth (m): %0.2f ± %0.2f', 
              mean(treeGirths), sd(treeGirths)))

The scan() function can also be modified to read input from a flat file. For instance, the following is the content of treeGirth.txt file:

12.4,13.2,14.8,12.7,14.1,14.2,15.0

The values are of double type and seperated by comma delimiter. Let us say we want to scan the first five values from the file. Using scan, this can be achieved, as in:

#open the connection to the file in read-only mode
fconTreeGirth <- file('treeGirth.txt', 'r')

#scan first five double typed values and retrieve
treeGirths <- as.double(scan(file=fconTreeGirth, what='double', nmax=5, sep=','))

#do whatever you want to do with the values extracted
cat(sprintf('Average±SD tree girth (m): %0.2f ± %0.2f', 
            mean(treeGirths), sd(treeGirths)))

#it is mandatory to close the connection to the file
close(fconTreeGirth)

You may also want to read flat files line by line. The “readLines” function (note the capital letter L in the function name) can be used for this purpose. The content of the file ‘Selfish Gene-Richard Dawkins.txt’ is: ” The gene-centred view of evolution that Dawkins championed and crystallized is now central both to evolutionary theorizing and to lay commentaries on natural history such as wildlife documentaries.

A bird or a bee risks its life and health to bring its offspring into the world not to help itself, and certainly not to help its species — the prevailing, lazy thinking of the 1960s, even among luminaries of evolution such as Julian Huxley and Konrad Lorenz — but (unconsciously) so that its genes go on.

Genes that cause birds and bees to breed survive at the expense of other genes.

No other explanation makes sense, although some insist that there are other ways to tell the story. ”

#first open the connection to the file
fconSelfishGene <- file('Selfish Gene-Richard Dawkins.txt', 'r')

thisLine <- "" #to begin while loop, this initializtion is required
linenumber <- 1 #initialize the line number
while(length(thisLine)>0){
   #read one line at a time
   thisLine <- readLines(fconSelfishGene, n=1)
   
   #print number of characters in each line
   cat(sprintf('Number of chars in line %d: %d\n', 
               linenumber, nchar(thisLine)))
   
   linenumber <- linenumber+1 #increment the line number
}
close(fconSelfishGene) #dont forget to close the connection

#Note that the length of any empty line is 1. While nchar() returns the 
#length of the line in terms of number of characters.

#Also note that, once the end of file is reached, you can not point back
#to the start of the file with the same connection; for which, you would
#need to close the connection and open it again afresh;

#you can also read the whole content of the file in one shot, as in:
fconSelfishGene <- file('Selfish Gene-Richard Dawkins.txt', 'r')
excerpts <- readLines(fconSelfishGene) #all lines are read
print(excerpts[c(1,3)]) #prints only the 1st and 3rd lines
close(fconSelfishGene)

Many data files are available in the form of text files in which the data are arranged in the form of a matrix or a table; the matrix/table structure the row values are delimited by a comma or a space or a tab or some other special character; and each line of row are delimited by a new line or carriage return (not visible); and the tables may not have headers (columns);

In order to read these kinds of files into R, read.table() or read.csv() function is used. The following is the content of the space delimited data file - delimited.txt:

ID exp1 exp2 exp3 exp4 exp5 qual 1 5 4 5 5.2 6 AA 2 5.5 4 6 5.2 5.5 C 3 6 5 9 5.2 6 C 4 6.2 5.5 8 5.2 5.5 A 5 6.3 5.6 7 5.2 6 A 6 6.3 5.7 4 5.2 5.5 B

The read.csv() extracts the content of the file into a R data.frame object, as in:

#sep is one space character, header is present, single quote was used 
#for string values in the rows;
myTable <- read.csv(file='Main Sessions/delimited.csv', sep=' ', 
  header=T, stringsAsFactors=F, quote="\'")
print(myTable)

#By default, double quote is assumed for string values; or if one of the 
#value in a column contains non-numeric values, the column will be
#considered as a character type column;

#if stringsAsFactors is set to TRUE, then read.csv() will factorize the character type 
#columns (which is the default)

#Note that there is no need to open a connection and close it.

Data output

As we have data input functions, R also supports the data output functions, especially to write content into files for storing results.

The sink() function allows the console ouputs to get redirected to a file, as in:

#open the connection to a file
sink('analyticalresults.txt', append=F, split=F)

#for a new file 'append' is set to FALSE, if it is an existing file then
#you might need to add the new content to it; for which, you would set
#'append' to TRUE;

#when 'split' is set to FALSE, then you wont see any console output; all 
#the outputs are sent only to the file;

#as sink() has opened a connection to the file earlier, the outputs 
#(matrices) of the loop are sent to file;
for(i in 1:10){
  print(growthByDay * i)
}

sink() #this is required to write the file to file system and to close it

The complementary function of read.csv() is write.csv() which writes a dataframe object into a text file with specified delimiters.

newfile <- 'myTable.csv'
write.csv(dfTmp, file=newfile, row.names=F)

#the default delimiter of values in a row is comma;
#when row.names is set to FALSE, the row IDs of the matrix or data.frame
#will be ignored while writing the content into the file

Functions (miscellaneous)

Functions of files and directories

getwd() #gets the current working directory of the R session
setwd(getwd()) #sets the working dir

newdir <- 'myFolder/subFolder'
dir.exists(newdir) #checks if the specified folder exists
#if absolute path is not given, it checks in the working dir

dir.create(newdir, recursive=T)  #creates the dir specified
#recursive=T when parent and sub-folders need to be created

file.exists('treeGirth.txt') #checks if the file is present in the current
#working directory

#the following lists all the folders in the path given
list.dirs(path=getwd(), full.names=T, recursive=F)
#if recursive=T, then all subfolders will also be listed

#Similarly, the following lists all files with a given pattern
myfiles <- list.files(path=sprintf('%s/Main Sessions',getwd()), pattern='*.R$', full.names=F)

#The function rmdir(<dir>) will delete a folder; similarly, unlink(<file>)
#will delete the specified file;

Some user defined functions

#mode function to obtain the most frequently observed value in a vector
#is not available in base R; let us write a function for it:
myMode <- function(numVec=NULL){
   ft <- table(numVec) #a table of values vs frequencies
   maxFreq <- max(ft) #gets the largest frequency
   #to extract all entries in the table that share the max freq
   allEntriesWithMaxFreq <- ft[ft==maxFreq]
   #because 'ft' is a named vector, where the names are the unique
   #values for which the freq count were obtained; hence, the names that
   #share the maximum freq are the mode values
   modes <- names(allEntriesWithMaxFreq)
   #because the names are of character type, we need to convert them to
   #numeric format
   modes <- as.numeric(modes)
   #finally, if the result is multi-model (modes>1), then we need to 
   #take average of all modal values
   return( mean(modes))
}

#the above function can be zipped into two lines of code by wrapping
#functions over functions, as in:
myMode <- function(numVec=NULL){
   ft <- table(numVec)
   return (mean(as.numeric(names(ft[ft==max(ft)]))))
}

#to use it:
myMode(randomNumbers)


#let us define a function to get the difference between two dates in months
diffMonths <- function(df1=NA, df2=NA){
   if(!all(c(class(pso)[1],class(pso1)[1]) %in% c('Date','POSIXct'))){
      print('The date values should be either Date object or POSIXct object!')
      return(NULL)
   } else {
      diffm <- as.numeric(difftime(d2, d1, units='days')) %/% 30L
      return(diffm)
   }
}
#to use it:
date1 <- as.Date('01 Jan 2010', '%d %b %Y')
date2 <- as.POSIXct('01 Jan 2010', '%d %b %Y')
diffMonths(date1, date2)
LS0tCnRpdGxlOiAiUiBQcm9ncmFtbWluZyBMYW5ndWFnZSAtIEVzc2VudGlhbHMiCmF1dGhvcjogIkFuYmFyYXNhbiBNYW5pY2thbSBSYWp1LCBQaC5ELiIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKdXJsY29sb3I6IGJsdWUKLS0tCgojIyBJbnRyb2R1Y3Rpb24KUiBTdGF0IGlzIGEgd2lkZWx5IHVzZWQgcHJvZ3JhbW1pbmcgdG9vbCBmb3Igc3RhdGlzdGljYWwgYW5hbHlzaXMuIFRoaXMgZ3VpZGUKaXMgYWltZWQgYXQgcHJvdmlkaW5nIGZvdW5kYXRpb25zIG9uIHRoZSBSIHByb2dyYW1taW5nIGxhbmd1YWdlLiBUaGlzIGd1aWRlIHdpbGwKYmUgdXNlZnVsIGZvciBiZWdpbm5lcnMgYXMgd2VsbCBhcyBmb3IgdGhvc2Ugd2hvIGhhdmUgYWxyZWFkeSBzdGFydGVkIHVzaW5nIFIgCmluIHRoZWlyIGFuYWx5c2lzLCBidXQgaGF2ZW4ndCBnb3QgaG9sZCBvZiB0aGUgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UgdW5kZXJuZWF0aC4KT25jZSB5b3UgZ2V0IHRoZSBncmlwIG9mIHRoaXMgbGFuZ3VhZ2UsIHlvdSB3aWxsIGJlIGVtcG93ZXJlZCB0byB1c2UgdGhlIApidWlsdC1pbiBsaWJyYXJpZXMgYW5kIGxpYnJhcmllcyBjb250cmlidXRlZCBieSBSIHVzZXIgY29tbXVuaXRpZXMgdG8gY2hvb3NlIAphbmQgdXNlIHN0YXRpc3RpY2FsIGZ1bmN0aW9ucyBvbiB5b3VyIGRhdGEuIEZvciBjb21wcmVoZW5zaXZlIGxpc3Qgb2YgcGFja2FnZXMgCmF2YWlsYWJsZSBpbiBSLCB5b3UgbWF5IHZpc2l0IHRoaXMgbGluazogCltSIFBhY2thZ2VzXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvYXZhaWxhYmxlX3BhY2thZ2VzX2J5X25hbWUuaHRtbCkKCiMjIEluc3RhbGxhdGlvbgpGb3IgaW5zdGFsbGF0aW9uIGFuZCB1c2Ugb2YgUiBhbmQgUiBTdHVkaW8sIHBsZWFzZSBmb2xsb3cgdGhlc2UgbGlua3M6CltSXShodHRwczovL3d3dy5yLXByb2plY3Qub3JnLyk7IFtSIFN0dWRpb10od3d3LnJzdHVkaW8uY29tKQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gRkFMU0UpCmBgYAoKIyMgRGF0YSBUeXBlcwpUaGVyZSBhcmUgZGlmZmVyZW50IGtpbmRzIG9mIGRhdGEuIFRoZXkgY2FuIGJlIHF1YW50aXRhdGl2ZSBvciBxdWFsaXRhdGl2ZS4gUXVhbnRpdGF0aXZlIGRhdGEgYXJlIG51bWVyaWMgYW5kIGNhbiBiZSBjb250aW51b3VzIG9yIGRpc2NyZXRlLiBXaGVuIGRpc2NyZXRlIG51bWVyaWMgZGF0YSBjYW4gYmUgcmFua2VkLCB0aGV5IGFyZSBjYWxsZWQgb3JkaW5hbC4gUXVhbGl0YXRpdmUgZGF0YSBhcmUgYWxzbyBrbm93biBhcyBub21pbmFsLiBSIHN1cHBvcnRzIHRoZSBmb2xsb3dpbmcgZGF0YSB0eXBlcy4gTm90ZSB0aGF0IHRoZSBpbnRlZ2VyIHZhbHVlcyBhcmUgc3VmZml4ZWQgd2l0aCB0aGUgbGV0dGVyIEwuIFRoZSBjaGFyYWN0ZXIgdmFsdWVzIGFyZSBlbmNsb3NlZCB3aXRoaW4gc2luZ2xlIG9yIGRvdWJsZSBxdW90ZXMuCgpgYGB7ciBjb21tZW50PScnfQpkYXRhdHlwZXMgPC0gZGF0YS5mcmFtZSgKICAgJ0RhdGEgVHlwZSc9YygnaW50ZWdlcicsJ2RvdWJsZScsJ251bWVyaWMnLCdjb21wbGV4JywnbG9naWNhbCcsJ2NoYXJhY3RlcicpLAogICBEZXNjcmlwdGlvbj1jKCd3aG9sZSBudW1iZXJzJywnbnVtYmVycyB3aXRoIGRlY2ltYWxzJywnbnVtYmVycyB3aXRoIGRlY2ltYWxzJywKICAgICAgICAgICAgICAgICAnbnVtYmVycyB3aXRoIGltYWdpbmFyeSBwYXJ0cycsJ2JpbmFyeSBzdGF0dXMnLAogICAgICAgICAgICAgICAgICdhbiBlbXB0eSBzdHJpbmcgb3IgYSBjaGFyYWN0ZXIgb3IgYSBzdHJpbmcgb2YgY2hhcmFjdGFycycpLAogICBFeGFtcGxlcz1jKCdJbmYsIDBMLCAyM0wsIDk5NzZMLCBJbmYnLCAnLUluZiwgMC4xLCAxMi45ODcsIDAuMDAwMDEyLCBJbmYnLAogICAgICAgICAgICAgICctSW5mLCAwLjEsIDEyLjk4NywgMC4wMDAwMTIsIEluZicsICcxMmksIDQrMmknLCdUUlVFLCBGQUxTRSwgMSwgMCcsCiAgICAgICAgICAgICAgIicnLCAnYScsICd4eXonLCAnc21hbGwnLCAnYSBsb3Qgb2YgaWNlIGZsb2F0cyBvbiBzZWEnIiksCiAgIGNoZWNrLm5hbWVzPUZBTFNFLCByb3cubmFtZXM9TlVMTAopCmtuaXRyOjprYWJsZShkYXRhdHlwZXMsIGNhcHRpb249J0RhdGEgVHlwZXMnKQpgYGAKCkNoYXJhY3RlciBkYXRhIHR5cGUgYXJlIGlkZWFsIGZvciBzdG9yaW5nIGRhdGUgdmFsdWVzLiBUaGUgZGlmZmVyZW50IGRhdGUgZm9ybWF0cyBjYW4gYmUgZXhwcmVzc2VkIGluIHN0cmluZyBsaXRlcmFscyBlZmZlY3RpdmVseSwgc3VjaCBhczoKICAgXCcxMCBPY3QgMjAxN1wnLCBcJ1dlZCAxMC0wMS04NyA1OjMwOjQ1IFBNXCcKICAgCkhvd2V2ZXIsIHRvIGVhc2UgZGF0ZSB2YWx1ZSBtYW5pcHVsYXRpb25zIGFuZCBjYWxjdWxhdGlvbnMsIHRoZXNlIHN0cmluZyBsaXRlcmFscyBhcmUgY29udmVydGVkIGludG8gZGF0ZSBvYmplY3RzLiBGb3IgbW9yZSBkZXRhaWxzLCBzZWUgKipEYXRlIEZ1bmN0aW9ucyoqLgoKCgoKCiMjIFNwZWNpYWwgdmFsdWVzClIgdXNlcyBwcmVkZWZpbmVkIGtleXdvcmRzIHRvIHJlcHJlc2VudCBjZXJ0YWluIHNwZWNpYWwgdmFsdWVzLgoKYGBge3IgY29tbWVudD0nJ30Kc3BlY2lhbFZhbHMgPC0gZGF0YS5mcmFtZSgKICAgS2V5d29yZHM9YygnSW5mJywnLUluZicsJ05BJywnTlVMTCcsJ1RSVUUnLCdGQUxTRScsICdwaScpLAogICBEZXNjcmlwdGlvbj1jKCdpbmZpbml0ZTogbGFyZ2VzdCBudW1iZXIgdW5rbm93bicsJ25lZ2F0aXZlIGluZjogc21hbGxlc3QgbnVtYmVyIHVua25vd24nLAogICAgICAgICAgICAgICAgICdhIGxvZ2ljYWwgdmFsdWUgcmVwcmVzZW50aW5nIG1pc3NpbmcgdmFsdWVzJywKICAgICAgICAgICAgICAgICAnZG9udCBhbGxvY2F0ZSBtZW1vcnknLCdsb2dpY2FsIHZhbHVlOyBlcXVhbHMgdG8gMTsgYWJicmV2aWF0ZWQgYXM6IFQnLAogICAgICAgICAgICAgICAgICdsb2dpY2FsIHZhbHVlOyBlcXVhbHMgdG8gMDsgYWJicmV2LiBhczogRicsICdhIGNvbnN0YW50IGluIHJhZGlhbnM7IGVxdWFscyB0byAzLjE0JyksCiAgIFVzZXM9YygnbnVtYmVyIG9mIGF0b21zIGluIHVuaXZlcnNlJywgJ2EgbmVnYXRpdmUgdmFsdWUgZGl2aWRlZCBieSB6ZXJvJywKICAgICAgICAgJ21pc3NpbmcgdmFsdWVzJywgJ2VuZm9yY2Ugbm8gbWVtb3J5IGFsbG9jYXRpb24nLAogICAgICAgICAndHJ1dGggaW4gYmluYXJ5IHN0YXR1cyBzdWNoIGFzIHllcyBvciBubycsJ2Fic2VuY2Ugb2YgYW4gb2JzZXJ2YWJsZSBzdGF0ZScsCiAgICAgICAgICdhcmNzIGFuZCBhbmdsZXMnKSwgY2hlY2submFtZXM9RkFMU0UsIHJvdy5uYW1lcz1OVUxMCikKa25pdHI6OmthYmxlKHNwZWNpYWxWYWxzLCBjYXB0aW9uPSdTcGVjaWFsIHZhbHVlcyBhbmQgY29uc3RhbnRzJykKYGBgCgoKCgojIyBWYXJpYWJsZXMKSW4gb3JkZXIgdG8gYWNjZXNzIGEgdmFsdWUgKG9mIGRpZmZlcmVudCBEYXRhIFR5cGVzKSBvciBhIHNldCBvZiB2YWx1ZXMsIFIgYWxsb3dzIHVzZXIgZGVmaW5lZCBzeW1ib2xpYyBuYW1lcy4gRGVwZW5kaW5nIG9uIHRoZSB0eXBlIG9mIGRhdGEsIHZhcmlhYmxlcyBhcmUgY2FsbGVkIG51bWVyaWMgdmFyaWFibGUgb3IgbG9naWFsIHZhcmlhYmxlIGFuZCBzbyBvbi4gVmFyaWFibGVzIGNhbiBiZSBuYW1lZCB1c2luZyBhbHBoYW51bWVyaWMgY2hhcmFjdGVycy4gVGhlIHJ1bGVzIGFyZSAoYSkgbm8gc3BhY2VzIGFyZSBhbGxvd2VkLCAoYikgbm8gc3BlY2lhbCBjaGFyYWN0ZXJzIGFyZSBhbGxvd2VkIGV4Y2VwdCBhIGRvdCAoLikgb3IgYW4gdW5kZXJzY29yZSAoXyksIGFuZCAoYykgbnVtYmVycyBhcmUgbm90IGFsbG93ZWQgYXQgdGhlIHN0YXJ0LgoKICAgLSBFeGFtcGxlczogY2VsbEdyb3d0aCwgYW5udWFsSW5jb21lLCB3YXZlTGVuZ3RoLCBwb3B1bGF0aW9uLCBjb2xvciwgbmFtZQoKCgoKIyMgT3BlcmF0aW9ucywgT3BlcmFuZHMgYW5kIE9wZXJhdG9ycwpPcGVyYXRpb25zIGFyZSB0YXNrcyBwZXJmb3JtZWQgYnkgdGhlIHNjcmlwdHMuIFRoZXNlIGNhbiBiZSBhc3NpZ25tZW50cywgbWF0aGVtYXRpY2FsIGV4cHJlc3Npb25zLCBjb21wYXJpc29ucywgZnVuY3Rpb24gY2FsbHMgYW5kIHNvIG9uLiBTb21lIG9wZXJhdGlvbnMgdXNlIHNwZWNpYWwgJ29wZXJhdG9ycycgdG8gcGVyZm9ybSBzcGVjaWZpYyB0YXNrcyBvbiAnb3BlcmFuZHMnLiBUaGUgb3BlcmF0b3JzIGluIFIgYXJlIHJlcHJlc2VudGVkIGJ5IHNwZWNpYWwgc3ltYm9scy4gT3BlcmFuZHMgYXJlICdkYXRhIHZhbHVlcycgb24gd2hpY2ggdGhlIG9wZXJhdG9yIHdpbGwgcGVyZm9ybSBhIHRhc2suIFIgYWxsb3dzIHZhcmlhYmxlIG5hbWVzIGluIHBsYWNlIG9mIHRoZXNlIG9wZXJhbmRzIChkYXRhIHZhbHVlcyksIGFzIHRoZXkgcG9pbnQgdG8gc29tZSB2YWx1ZS4gU2ltaWxhcmx5LCBhIGZ1bmN0aW9uIG9yIGFub3RoZXIgb3BlcmF0aW9uIHRoYXQgcmV0dXJucyBhIHZhbHVlIGNhbiBiZSB1c2VkIGluIHBsYWNlIG9mIG9wZXJhbmRzLiBBbiBvcGVyYXRpb24gd2hlcmUgb3BlcmFuZHMgYW5kIG9wZXJhdG9ycyBhcmUgdXNlZCBpbiBhIGxpbmUgb2YgUiBjb2RlIGFyZSBzb21ldGltZXMgY2FsbGVkIGV4cHJlc3Npb25zLiBJbiBhc3NpZ25tZW50IGV4cHJlc3Npb25zLCB0aGUgdGFyZ2V0IHZhcmlhYmxlIHRvIHdoaWNoIGEgdmFsdWUgdG8gYmUgc3RvcmVkIGFwcGVhcnMgb24gdGhlIHNpZGUgb2YgYXJyb3cgbWFyayAodGhpcyBzaWRlIDwtKSBhbmQgdmFsdWUgYXBwZWFycyBhdCB0aGUgdGFpbCBlbmQgKDwtIHRoaXMgc2lkZSkuIEFuIGV4cHJlc3Npb24gd2l0aG91dCBhc3NpZ25tZW50IG9wZXJhdG9yIGlzIHZvbGF0aWxlIGkuZS4gdGhlIHJlc3VsdCBvZiB0aGUgZXhwcmVzc2lvbnMgYXJlIG5vdCBzdG9yZWQgYW55d2hlcmUuIFJlbGF0aW9uYWwgZXhwcmVzc2lvbnMgcmV0dXJucyBUUlVFIG9yIEZBTFNFLiBUaGUgb3BlcmFuZHMgb2YgbG9naWNhbCBvcGVyYXRvcnMgYXJlIGxvZ2lhbCBUUlVFIG9yIEZBTFNFLgoKYGBge3IgY29tbWVudD0nJywgZWNobz1GQUxTRSwgZXZhbD1UUlVFLCByZXN1bHRzPSdhc2lzJ30KbWF0aE9wZXIgPC0gZGF0YS5mcmFtZSgKICAgT3BlcmF0b3I9YygnPC0sIC0+JywgJy0+PiwgPDwtJywgJysgLC0gLCogLC8nLCAnJS8lLCAlJSwgXiBvciAqKicpLAogICBEZXNjcmlwdGlvbj1jKCdhc3NpZ25tZW50JywgJ2dsb2JhbCBhc3NpZ25tZW50JywKICAgICAgICAgICAgICAgICAnYWRkLCBzdWJ0cmFjdCwgbXVsdGlwbHksIGRpdmlkZScsIAogICAgICAgICAgICAgICAgICdpbnRlZ2VyIGRpdmlzaW9uLCBtb2R1bHVzLCBleHBvbmVudCcpLAogICBFeGFtcGxlcz1jKCdhIDwtIDAuMTInLCAneCA8PC0gMTInLCAgJ2EgKiAxMiAtPiBiJywgJ3JlbSA8LSBwb3AgJSUgMjAnKSwKICAgY2hlY2submFtZXM9RkFMU0UsIHJvdy5uYW1lcz1OVUxMCikKa25pdHI6OmthYmxlKG1hdGhPcGVyLCBmb3JtYXQ9J3BhbmRvYycsIGNhcHRpb249J01hdGhlbWF0aWNhbCBvcGVyYXRvcnMnKQpyZWxPcGVyIDwtIGRhdGEuZnJhbWUoCiAgIE9wZXJhdG9yPWMoJzwsIDw9LCA+LCA+PScsICc9PSwgIT0nKSwKICAgRGVzY3JpcHRpb249YygnbGVzcyB0aGFuLCBsZXNzIHRoYW4gb3IgZXF1YWwgdG8sIGdyZWF0ZXIgdGhhbiwgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvJywgJ2VxdWFsIHRvLCBub3QgZXF1YWwgdG8nKSwKICAgRXhhbXBsZXM9YygnYSA8PSAxMCcsICdiICE9IGEnKSwKICAgY2hlY2submFtZXM9RkFMU0UsIHJvdy5uYW1lcz1OVUxMCikKa25pdHI6OmthYmxlKHJlbE9wZXIsIGZvcm1hdD0ncGFuZG9jJywgY2FwdGlvbj0nUmVsYXRpb25hbCBvcGVyYXRvcnMnKQoKbG9naWNhbE9wZXIgPC0gZGF0YS5mcmFtZSgKICAgT3BlcmF0b3I9YygnJiwgJiYnLCAnfCwgfHwnKSwKICAgRGVzY3JpcHRpb249YygnbG9naWNhbCBBTkQ7ICYgY29tcGFyZXMgbG9naWNhbCB2ZWN0b3InLCAnbG9naWNhbCBPUjsgfCBjb21wYXJlcyBsb2dpY2FsIHZlY3RvcicpLAogICBFeGFtcGxlcz1jKCdhICYmIGIgd2hlcmUgYSBhbmQgYiBhcmUgbG9naWNhbCBzY2FsYXJzJywgJ1ggfCBZIHdoZXJlIFggYW5kIFkgYXJlIGxvZ2ljYWwgdmVjdG9ycycpLAogICBjaGVjay5uYW1lcz1GQUxTRSwgcm93Lm5hbWVzPU5VTEwKKQprbml0cjo6a2FibGUobG9naWNhbE9wZXIsIGZvcm1hdD0ncGFuZG9jJywgY2FwdGlvbj0nTG9naWNhbCBvcGVyYXRvcnMnKQpgYGAKCkFzc3VtZSB0aGF0IGEgYW5kIGIgYXJlIHR3byBsb2dpY2FsIHZhcmlhYmxlcywgdGhlbiB0aGUgbG9naWNhbCBvcGVyYXRpb24gImEgJiBiIiB3aWxsIHJldHVybiBUUlVFIG9ubHkgd2hlbiBib3RoIGEgYW5kIGIgYXJlIFRSVUUuIFNpbWlsYXJseSwgImEgfCBiIiB3aWxsIHJldHVybiBGQUxTRSBvbmx5IHdoZW4gYm90aCBhIGFuZCBiIGFyZSBGQUxTRS4KCkV4Y2VwdCBmb3IgZXhwb25lbnQgYW5kIHJpZ2h0d2FyZCBhc3NpZ25tZW50LCBhbGwgb3RoZXIgb3BlcmF0b3JzIGFyZSBldmFsdWF0ZWQgZnJvbSBsZWZ0IHRvIHJpZ2h0LiBJZiB5b3Ugd2FudCB0byBvdmVycmlkZSBkZWZhdWx0IHByZWNlZGVuY2UsIGVuY2xvc2UgZXhwcmVzc2lvbnMgd2l0aGluIHBhcmVudGhlc2lzIChzb21ldGltZXMgcmVmZXJyZWQgYXMgcHJlY2VkZW5jZSBvcGVyYXRvcikuIEZvciBpbnN0YW5jZSBjb21wYXJlIHRoZSByZXN1bHRzIG9mIHRoZSBmb2xsb3dpbmcgcGFpciBvZiBtYXRoIGV4cHJlc3Npb25zOgoKICAgKiAyIF4gMyBeIDQgaXMgZXF1aXZhbGVudCBvZiAyIF4gODEsIHdoZXJlYXMgKDIgXiAzKSBeIDQgaXMgZXF1aXZhbGVudCBvZiA2IF4gNAogICAqIDIgKiAzICsgNCBpcyBlcXVpdmFsZW50IG9mIDYgKyA0LCB3aGVyZWFzIDIgKiAoMyArIDQpIGlzIGVxdWl2YWxlbnQgb2YgMiAqIDcKICAgCkFsc28gbm90ZSB0aGF0IGVuY2xvc2luZyBhbiBleHByZXNzaW9uIG9yIGEgZ3JvdXAgb2YgZXhwcmVzc2lvbnMgd2l0aGluIHBhcmFudGhlc2lzIGluY3JlYXNlcyByZWFkYWJpbGl0eSBvZiB0aGUgY29kZS4KCkJlIGF3YXJlIHRoYXQgdGhlcmUgYXJlIHNwZWNpYWwgb3BlcmF0b3JzLCBvdGhlciB0aGFuIHRob3NlIG1lbnRpb25lZCBhYm92ZSwgYXJlIHByZXNlbnQgaW4gUi4gRm9yIGluc3RhbmNlLCAlaW4lIGlzIGEgdmVjdG9yIG9wZXJhdG9yIChzZWUgKipWZWN0b3Igb3BlcmF0aW9ucyoqKSBhbmQgJVwqJSBpcyBhIHRydWUgbWF0cml4IG11bHRpcGxpY2F0aW9uIG9wZXJhdG9yIChzZWUgKipNYXRyaXggb3BlcmF0aW9ucyoqKS4gSW4gYWRkaXRpb24gdG8gdGhhdCwgdGhlIHR3byBzcXVhcmUgYnJhY2tldHMgKG9wZW4gYW5kIGNsb3NlIHR5cGVzIC0gW10pIHRvZ2V0aGVyIGZvcm1zIGFycmF5IGFjY2VzcyBvcGVyYXRvciAoc2VlICoqQWNjZXNzaW5nIGFuZCBlZGl0aW5nIHZlY3RvciBlbGVtZW50cyoqIGFuZCAqKkFjY2Vzc2luZyBhbmQgZWRpdGluZyBtYXRyaXggZWxlbWVudHMqKiApLgoKYGBge3IgZXZhbD1GQUxTRSwgZWNobz1UUlVFfQojIE1hdGhlbWF0aWNhbCBleHByZXNzaW9ucwoKI0Fzc3VtZSBpbml0UG9wLCBtYXhSYW5nZSBhbmQgbWluSXRlcmF0aW9ucyBhcmUgbnVtZXJpYyB2YXJpYWJsZXMgdXNlZCBpbiB0aGUKI2JlbG93IGV4YW1wbGVzCgppbml0UG9wIDwtIGluaXRQb3AgKyAzNCAjYWRkaXRpb24KcmFuZ2UgPC0gbWF4UmFuZ2UgLSAxLjIgI3N1YnRyYWN0aW9uCnRyaXBsZUl0ZXIgPC0gbWluSXRlcmF0aW9ucyAqIDMgI211bHRpcGxpY2F0aW9uCmV4cE9mMiA8LSAyLjcxOCAqKiAyICNzcXVhcmUuIEZ1bmN0aW9uOiBleHAoMikKc3FydE9mNSA8LSA1TCBeICgxLzIpICNleHBvbmVudC4gRnVuY3Rpb246IHNxcnQoNUwpCmluZlZhbCA8LSAtMTAwIC8gMCAjZGl2aXNpb24KbGVmdE92ZXIgPC0gMTAwMCAlJSAzICNtb2R1bHVzCndlaWdodFBlckJhdGNoIDwtIDM0OS44ICUvJSA0OS4yICNnZXRzIGZsb29yIHZhbHVlIG9mIHRoZSByZXN1bHQKCgojIENvbXBhcmF0aXZlIGV4cHJlc3Npb25zIChyZWxhdGlvbmFsLCBsb2dpY2FsKQoKIyBBc3N1bWUgYWlyVGVtcCBhbmQgc3RvcFZhbHZlUmFuZ2UgYXJlIG51bWVyaWMgdmFyaWFibGVzOyBhbmQgaXNGbHlpbmcgYW5kIGlzUmFpbmluZyBhcmUgCiNsb2dpY2FsIHZhcmlhYmxlcyB1c2VkIGluIHRoZSBiZWxvdyBleGFtcGxlcy4KCmlzQ29sZCA8LSAoYWlyVGVtcCA8PSAxOCkgI2xlc3MgdGhhbiBvciBlcXVhbCB0by4gU2ltaWxhcjogPiwgPj0sIDwKc3RvcFZhbHZlIDwtIChzdG9wVmFsdmVSYW5nZSA9PSA1MCkgI2VxdWFsaXR5Cm5vdEluRmxpZ2h0IDwtICEoaXNGbHlpbmcpICNsb2dpY2FsIG5vdCBvcGVyYXRpb24uIE90aGVyIHVzZTogYSAhPSBiCgppc0NvbGRBbmRGbHlpbmcgPC0gaXNDb2xkICYmIGlzRmx5aW5nICNsb2dpY2FsIEFORAppc0NvbGRPcmlzUmFpbmluZyA8LSBpc0NvbGQgfHwgaXNSYWluaW5nICNsb2dpY2FsIE9SCmBgYAoKCiMjIEZ1bmN0aW9ucwpBIGZ1bmN0aW9uIGlzIGEgYmxvY2sgb2YgY29kZSAoaGF2aW5nIG9uZSBvciBtb3JlIGxpbmVzIG9mIGNvZGUpIHRvIGNhcnJ5IG91dCBhIHNwZWNpZmljIG9wZXJhdGlvbiBvbiB0aGUgaW5wdXQgdmFsdWVzIGlmIGdpdmVuLiBXaGVuIGlucHV0IHZhbHVlcyBhcmUgbm90IHNwZWNpZmllZCwgZnVuY3Rpb25zIHNpbXBseSBwZXJmb3JtIGEgdGFzayB1c2luZyBpbnN0cnVjdGlvbnMuIFRoZSBpbnB1dCB2YXJpYWJsZXMgYXJlIGNhbGxlZCBwYXJhbWV0ZXJzLiBBIGZ1bmN0aW9uIGNhbiBoYXZlIHplcm8gdG8gbWFueSBwYXJhbXRlcnMuIEEgZnVuY3Rpb24gbWF5IHJldHVybiBhIHJlc3VsdCBkZXJpdmVkIG91dCBvZiB0aGUgdGFzayBwZXJmb3JtZWQgaW5zaWRlIHRoZSBmdW5jdGlvbi4gRnJlcXVlbnRseSB1c2VkIHRhc2tzIGFyZSB3cmFwcGVkIGluIGZ1bmN0aW9ucywgaGVuY2UgaXQgaGVscHMgaW4gZWxpbWluYXRpbmcgcmVkdW5kYW5jeSBpbiB0aGUgc2NyaXB0IG9yIHByb2dyYW0uIEFsbCB0aGUgdmFyaWFibGVzIGRlZmluZWQgaW5zaWRlIGEgZnVuY3Rpb24gYXJlIGNhbGxlZCBsb2NhbCB2YXJpYWJsZXMuIFRoZWlyIHZhbHVlcyBhcmUgbm90IHZpc2libGUgb3V0c2lkZSB0aGUgZnVuY3Rpb24gaW4gdGhlIGNhbGxpbmcgcHJvZ3JhbS4gSG93ZXZlciwgdGhlaXIgdmFsdWVzIGNhbiBiZSByZXR1cm5lZCBiYWNrIHRvIHRoZSBwcm9ncmFtLiBSIGhhcyBhIGxvdCBvZiBidWlsdC1pbiBmdW5jdGlvbnMgdGhhdCBhcmUgYnVuZGxlZCBhbG9uZyB3aXRoIHRoZSBiYXNlIHBhY2thZ2UgYW5kIGFsbG93cyB0aGUgdXNlciB0byBkZWZpbmUgY3VzdG9tIGZ1bmN0aW9ucy4gU29tZXRpbWVzLCBmdW5jdGlvbnMgYXJlIGFsc28gY2FsbGVkIHJvdXRpbmVzLgoKIyMjIENyZWF0aW5nIEZ1bmN0aW9ucwpUaGUgUiBzeW50YXggZm9yIGRlZmluaW5nIGEgY3VzdG9tIGZ1bmN0aW9uIGlzIGdpdmVuIGJlbG93IHdpdGggZXhhbXBsZXMuCgpgYGB7ciBldmFsPUYsIGVjaG89VH0KZnVuY3Rpb25OYW1lSGVyZSA8LSBmdW5jdGlvbihwYXJhbWV0ZXIxPSdpbml0aWFsIHZhbHVlJywgcGFyYW1ldGVyMj0naW5pdCB2YWwnLCAuLi4pIHsKICAgIyA8ZnVuY3Rpb24gdGFza3MgZ29lcyBoZXJlPgogICByZXR1cm4ocmV0dXJuVmFsdWUpICNyZXR1cm4gaXMgb3B0aW9uYWwKfQoKI0V4YW1wbGUgMTogVGhpcyBmdW5jdGlvbiB0YWtlcyB0d28gcGFyYW1ldGVycyAobnVtYmVyMSBhbmQgbnVtYmVyMikuIEJvdGggYXJlIG51bWVyaWMgCiN2YXJpYWJsZXMgYW5kIGluaXRpYWxpc2VkIHRvIHplcm8uIEluc2lkZSB0aGUgZnVuY3Rpb24sIGEgbG9jYWwgdmFyaWFibGUgKHJldHVyblZhbHVlKSBpcyBjcmVhdGVkIGFuZCBhc3NpZ25lZCB0aGUgdmFsdWUgb2YgYWRkaXRpb24gb2YgdGhlIHR3byBudW1iZXJzLiBGaW5hbGx5LCB0aGUgYWRkZWQgdmFsdWUgaXMgcmV0dXJuZWQgYmFjayB0byB0aGUgY2FsbGVyIG9mIHRoZSBmdW5jdGlvbi4KYWRkVHdvTnVtYmVycyA8LSBmdW5jdGlvbihudW1iZXIxPTAsIG51bWJlcjI9MCl7CiAgIHJldHVyblZhbHVlIDwtIG51bWJlcjEgKyBudW1iZXIyCiAgIHJldHVybihyZXR1cm5WYWx1ZSkKfQoKI2Z1bmN0aW9uIGNhbGxzIHdpdGhvdXQgaW5wdXQgdmFsdWVzLiBUaGlzIGlzIHBvc3NpYmxlIHdoZW4gdGhlIHBhcmFtZXRlcnMgYXJlCiNpbml0aWFsaXNlZCBpbiB0aGUgZnVuY3Rpb24gZGVmaW5pdGlvbi4gCmFkZFR3b051bWJlcnMoKSAjcmV0dXJucyAwICg9IDAgKyAwKQoKI2Z1bmN0aW9uIGNhbGxzIHdpdGgganVzdCBvbmUgdmFsdWUuCmFkZFR3b051bWJlcnMoMikgI2V0dXJucyAyICg9IDIgKyAwKSAobnVtYmVyMSBnZXRzIHRoZSB2YWx1ZSAyOyBudW1iZXIyIGlzIHRoZSBkZWZhdWx0IDApCgojZnVuY3Rpb24gY2FsbHMgd2l0aCB0d28gdmFsdWVzCmFkZFR3b051bWJlcnMoMiwgNCkgI251bWJlcjE9MjsgbnVtYmVyMj00OyByZXR1cm5zIDYgKD0gMiArIDQpCgojZnVuY3Rpb24gY2FsbHMgd2l0aCBuYW1lZCBwYXJhbWV0ZXJzOyBub3RlIHRoYXQgdGhlIG9yZGVyIGluIHdoaWNoIHBhcmFtZXRlcnMgYXJlIHBhc3NlZAojY2FuIGJlIGNoYW5nZWQKYWRkVHdvTnVtYmVycyhudW1iZXIyPTcsIG51bWJlcjE9NCkgI3JldHVybnMgMTEgKD0gNCArIDcpCgoKI0V4YW1wbGUyOiBUaGlzIGZ1bmN0aW9uIGp1c3QgcHJpbnRzIGEgcHJlc2V0IGVycm9yIG1lc3NhZ2UgdG8gdGhlIHVzZXIgd2hlbiBjYWxsZWQuCiNJdCBuZWl0aGVyIGFjY2VwdHMgYW55IHBhcmFtdGVycyBub3IgcmV0dXJucyBhbnkgdmFsdWUuCnJhaXNlRXJyb3JNZXNzYWdlIDwtIGZ1bmN0aW9uKCkgewogICBwcmludCgnRXJyb3Igb2NjdXJyZWQgZHVyaW5nIHRoZSBwcm9jZXNzLiBQbGVhZXMgY29udGFjdCB0aGUgYWRtaW4gZm9yIHRyb3VibGVzaG9vdGluZyEnKQp9CgojPHlvdXIgbWFpbiBjb2RlIGdvZXMgaGVyZSwgZHVyaW5nIHdoaWNoIGFuIGVycm9yIG9jY3VycmVkLi4uPgpyYWlzZUVycm9yTWVzc2FnZSgpICNwcmludHMgdGhlIGVycm9yIG1lc3NhZ2UKIzx5b3UgZnVydGhlciBwcm9jZWVkIHdpdGggdGhlIGNvZGUuLi4+CmBgYAoKIyMjIFRlc3RpbmcgZ2xvYmFsIGFzc2lnbm1lbnQgb3BlcmF0b3IgdXNpbmcgZnVuY3Rpb25zClRoZSB2YXJpYWJsZXMgY3JlYXRlZCBhcyBmdW5jdGlvbiBwYXJhbWV0ZXJzIG9yIG90aGVyIHZhcmlhYmxlcyB0aGF0IGFyZSBjcmVhdGVkIGluc2lkZSB0aGUgZnVudGlvbiBibG9jayBhcmUgbG9jYWwgdmFyaWFibGVzLiBMb2NhbCB2YXJpYWJsZXMgYXJlIG5laXRoZXIgdmlzaWJsZSBub3IgaGFzIHNjb3BlIG91dHNpZGUgdGhlIGZ1bmN0aW9uLiBHbG9iYWwgYXNzaWdubWVudCBvcGVyYXRvcnMgYXJlIHVzZWQgZGVmaW5lIGdsb2JhbCBzY29wZSB0byB2YXJpYWJsZXMgdXNlZCBpbiB0aGUgZnVuY3Rpb24gYm9keS4gTGV0IHVzIHVuZGVyc3RhbmQgdGhpcyB1c2luZyB0aGUgZm9sbG93aW5nIGRlbW8uCmBgYHtyIGV2YWw9RiwgZWNobz1UfQp4IDwtIDEwMCAjYSBnbG9iYWwgdmFyaWFibGUgeAoKI25vdywgbGV0IHVzIHRyeSBtb2RpZnkgdGhlIHZhbHVlIG9mIHggZnJvbSBhIGZ1bmN0aW9uCkYxIDwtIGZ1bmN0aW9uKCkgeyAgIHggPC0gMjAwIH0KI2xldCB1cyBjYWxsIHRoZSBmdW5jdGlvbiB0byBhY3R1YWxseSBtb2RpZnkgYW5kIGNoZWNrIHRoZSB2YWx1ZSBvZiB4CkYxKCk7IHByaW50KHgpCgojdGhlIGFib3ZlIGF0dGVtcHQgd2lsbCBmYWlsIHRvIGNoYW5nZSB0aGUgdmFsdWUgaW4geCwgYmVjYXVzZSBvZiB0aGUgcnVsZXMKI29mIHNjb3BlIG9mIHZhcmlhYmxlIGFzIGV4cGxhaW5lZCBhYm92ZTsKCiNUaGVyZSBhcmUgdGhyZWUgd2F5cyB3ZSBjYW4gYWNoaWV2ZSB0aGlzOgojMXN0IHdheToKRjIgPC0gZnVuY3Rpb24oKSB7IHZhbCA8LSAyMDA7IHJldHVybih2YWwpIH0KeCA8LSBGMigpCiNUaGUgZnVuY3Rpb24gRjIgcmV0dXJucyBhIHZhbHVlIHRoYXQgZ2V0cyBhc3NpZ25lZCB0byB0aGUgb3V0c2lkZSB4CgojMm5kIHdheToKRjMgPC0gZnVuY3Rpb24odmFsPTApIHsgdmFsIDwtIHZhbCsxMDA7IHJldHVybih2YWwpIH0KeCA8LSBGMyh4KQojVGhlIGZ1bmN0aW9uIEYzIGFjY2VwdHMgdGhlIHggZnJvbSBvdXRzaWRlIGFuZCBtb2RpZmllcyBpdDsgdGhlIG1vZGlmaWVkCiN2YWx1ZSBpcyB0aGVuIHJldHVybmVkIHRvIHRoZSBjYWxsZXIgd2hlcmUgaXQgaXMgdHJhbnNmZXJyZWQgdG8gdGhlIHgKI2RlZmluZWQgb3V0c2lkZQoKIzNyZCB3YXk6CkY0IDwtIGZ1bmN0aW9uKCkgeyB4IDw8LSAyMDAgfQp4IDwtIEY0KCkKI1RoZSBmdW5jdGlvbiBGNCB1c2VzIGdsb2JhbCBhc3NpZ25tZW50IG9wZXJhdG9yIHdoZXJlIHRoZSBMSFMgb3BlcmFuZCBvZiA8PC0KI29wZXJhdG9yIGlzIGFzc3VtZWQgdG8gYmUgZ2xvYmFsCgojTm90ZSB0aGF0IGlmIHggaXMgbm90IGRlZmluZWQgb3V0c2lkZSBiZWZvcmUgaXQgaXMgdXNlZCBpbiB0aGUgZnVuY3Rpb24gCiNjYWxsIHRoYXQgdXNlcyBnbG9iYWwgYXNzaWdubWVudCBvcGVyYXRvciBvbiBpdCwgdGhlbiBhIGdsb2JhbCAKI3ZhcmlhYmxlIHggd2lsbCBiZSBjcmVhdGVkIGZyb20gZnVuY3Rpb24gY2FsbC4KYGBgCgoKCiMjIyBCdWlsdC1pbiBmdW5jdGlvbnMKUiBjb21lcyB3aXRoIHNldmVyYWwgYnVpbHRpbiBmdW5jdGlvbnMgaW4gaXRzIGJhc2UgcGFja2FnZS4gVGhlIGZ1bmN0aW9ucyBjYW4gYmUgZGlyZWN0bHkgY2FsbGVkIGZyb20gdGhlIHNjcmlwdCB3aXRoIHRoZSByZXF1aXJlZCBwYXJhbXRlcnMuIFRoZSBoZWxwIG9uIGFueSBmdW5jdGlvbiBjYW4gYmUgc2VlbiBieSB0eXBpbmcgP1w8ZnVuY3Rpb24gbmFtZVw+LiBIZXJlLCBtb3N0IGZyZXF1ZW50bHkgdXNlZCBmdW5jdGlvbnMgYXJlIGxpc3RlZCB3aXRoIGV4YW1wbGVzIGFuZCBhcmUgZ3JvdXBlZCBieSB0aGVpciBwdXJwb3NlLiBTb21lIGZ1bmN0aW9ucyBoYXZlIHBhcmFtZXRlcnMgdGhhdCBhcmUgbm90IGV4cGxhaW5lZCBoZXJlLiBIZXJlLCB3ZSBmb2N1cyBvbmx5IG9uIHRoZSBlc3NlbnRpYWwgcGFyYW10ZXIgbGlzdC4KCiMjIyBEYXRhIHR5cGUgY2hlY2tpbmcKVGhlIGZ1bmN0aW9uIHR5cGVvZih4KSBnaXZlcyB0aGUgbmFtZSBvZiBkYXRhIHR5cGUgb2YgdGhlIHZhcmlhYmxlIHguIFRoZXJlIGFyZSBhIHNldCBvZiBmdW5jdGlvbnMgd2hvc2UgbmFtZXMgZm9sbG93IHRoaXMgcGF0dGVybiBjaGVjayBpZiB0aGUgdmFyaWFibGUgeCBiZWxvbmcgdG8gdGhlIHNwZWNpZmllZCBkYXRhIHR5cGU6IGlzLlw8ZGF0YXR5cGVcPih4KS4gVGhlc2UgZnVuY3Rpb25zIHJldHVybiBUUlVFIG9yIEZBTFNFLgoKYGBge3IgZXZhbD1GLCBlY2hvPVR9CiNsZXQgdXMgY3JlYXRlIHNvbWUgc2NhbGFycyBhbmQgdmVjdG9ycyBmb3IgZGVtbwp4IDwtIC1JbmY7IHkgPC0gVFJVRTsgeiA8LSBOQQoKdHlwZW9mKHgpICNyZXR1cm5zICdudW1lcmljJwp0eXBlb2YoeSkgI3JldHVybnMgJ2xvZ2ljYWwnCgppcy5udW1lcmljKHgpICNyZXR1cm5zIFRSVUUKaXMubG9naWNhbCh5KSAjcmV0dXJucyBUUlVFCmlzLmludGVnZXIoeCkgI3JldHVybnMgRkFMU0UKaXMuZG91YmxlKHgpICNyZXR1cm5zIFRSVUUKaXMuY2hhcmFjdGVyKHgpICNyZXR1cm5zIEZBTFNFCgppcy5uYSh6KSAjY2hlY2tzIGlmIHRoZSB2YWx1ZSBpcyBOQQppcy5udWxsKHopICNjaGVja3MgaWYgdGhlIHZhbHVlIGlzIE5VTEwKaXMuaW5maW5pdGUoeCkgI3JldHVybnMgVFJVRQppcy5maW5pdGUoeikgI3JldHVybnMgRkFMU0UKYGBgCgoKIyMjIERhdGEgdHlwZSBjb252ZXJzaW9ucwpUeXBlIGNvbnZlcnNpb24gZnVuY3Rpb24gdHJhbnNmb3JtcyBhIHZhcmlhYmxlIGZyb20gb25lIGRhdGEgdHlwZSB0byBhbm90aGVyLiBUaGVyZSBhcmUgYSBmZXcgcmVzdHJpY3Rpb25zIGFzIHdlbGwuIFRoZXNlIGZ1bmN0aW9ucyBmb2xsb3cgbmFtaW5nIHBhdHRlcm46IGFzLlw8ZGF0YXR5cGVcPigpLgoKYGBge3IgZXZhbD1GQUxTRSwgZWNobz1UfQphcy5udW1lcmljKCc4NycpICNjb252ZXJ0cyBzdHJpbmcgbnVtYmVycyB0byBudW1lcmljCmFzLm51bWVyaWMoJ1g5OCcpICN0aHJvd3MgZXJyb3IgZHVlIHRvIHRoZSBwcmVzZW5jZSBvZiB0aGUgbGV0dGVyIFgKYXMubnVtZXJpYyhGQUxTRSkgI3JldHVybnMgMDsgcmV0dXJucyAxIGZvciBUUlVFCmFzLmludGVnZXIoNjcuNjEyMykgIyByZXR1cm5zIDY3OyBjb252ZXJ0cyBkb3VibGUgdG8gaW50ZWdlcgoKYXMuY2hhcmFjdGVyKDE5OTkpICNjb252ZXJ0cyBudW1iZXIgdG8gc3RyaW5nIGxpdGVyYWwgJzE5OTknCmFzLmNoYXJhY3RlcihGQUxTRSkgI3JldHVybnMgY2hhcmFjdGVyIHZhbHVlCgphcy5sb2dpY2FsKDApICM9RkFMU0UKYXMubG9naWNhbCg1MDY1KSAjYW55IG51bWJlciBncmVhdGVyIHRoYW4gMCBhcmUgVFJVRQoKeiA8LSAxCmFzLmxvZ2ljYWwoeikgI3JldHVybnMgVFJVRTsgMT1UUlVFOyAwPUZBTFNFCmBgYAoKCiMjIyBNYXRoIGZ1bmN0aW9ucwpTb21lIG9mIHRoZSBmcmVxdWVudGx5IHVzZWQgbWF0aCBmdW5jdGlvbnMgYXJlIGxpc3RlZCBiZWxvdy4KCmBgYHtyIGV2YWw9RkFMU0UsIGVjaG89VFJVRX0KYWJzKC0xODcyMy4yMykgI3JlbW92ZXMgc2lnbgpyb3VuZChwaSwgZGlnaXRzPTIpICNwaSB2YWx1ZSByb3VuZGVkIG9mZiB0byAyIGRlY2ltYWxzCnNpZ25pZihleHBPZjIsIGRpZ2l0cz0zKSAjZXh0cmFjdHMgMyBzaWduaWZpY2FudCBudW1iZXJzIGZyb20gcGkKZmxvb3IocGkpICNuZXh0IGxvd2VzdCBpbnRlZ2VyIApjZWlsaW5nKHBpKSAjbmV4dCBsYXJnZXN0IGludGVnZXIKCmxvZyg0NSkgI25hdHVyYWwgbG9nCmxvZzEwKDQ1KSAjbG9nIGJhc2UgMTA7IFNpbWlsYXI6IGxvZzIoKQpsb2coNDUsIGJhc2U9cGkpICNsb2cgYmFzZSBvZiBhbnkgbnVtYmVyCgpleHAoMikgI2UgcG93ZXIgMgpzcXJ0KDU2KSAjc3F1YXJlIHJvb3Q7IGN1YmUgcm9vdD8KZmFjdG9yaWFsKDMpICMzISA9IDEgKiAyICogMwoKc2luKDIwKSAjU2ltaWxhciB0cmlnbm9tZXRyaWMgZnVuY3Rpb25zOiBjb3MoKSwgdGFuKCksIGFzaW4oKSwgYWNvcygpLCBhdGFuKCkKYGBgCgojIyMgRGF0ZSBGdW5jdGlvbnMKV2UgaGF2ZSBzZWVuIHRoYXQgdGhlIHRleHQgZm9ybSBpcyB0aGUgY29udmVuaWVudCB3YXkgb2Ygc3RvcmluZyBkYXRlIHZhbHVlcyBpbiBkaWZmZXJlbnQgZm9ybWF0cy4gSG93ZXZlciwgZGF0ZSB2YWx1ZXMgY2FuIGJlIHN0b3JlZCBhcyBlcXVpdmFsZW50IG51bWVyaWMgdmFsdWVzIChhIHJlbGF0aXZlIHZhbHVlIHdpdGggcmVmZXJlbmNlIHRvIGFuIGFyYml0cmFyeSBkYXRlKS4gTGV0IHVzIHNlZSB0aGUgZnVuY3Rpb25zIHJlbGF0ZWQgdG8gZGF0ZSB2YWx1ZXMgYW5kIHRoZWlyIHVzZXMuCmBgYHtyIGV2YWw9RiwgZWNobz1UfQojbGV0IHVzIGluaXRpYWxpc2Ugc29tZSBkYXRlIHZhbHVlcyBhcyBjaGFyYWN0ZXIgdHlwZQpwcm9ncmFtU3RhcnRzT24gPC0gJzExIDEwIDIwMTcnICNmb3JtYXQ6IEREIE1NIFlZWVkKZXZlbnRFbmRzQXQgPC0gJzE4IDAzIDIxIDU6MzA6MDAgUE0nI2Zvcm1hdDogWVkgTU0gREQgSEg6TU06U1MgQU0vUE0KCiN3ZSBjYW4gY29udmVydCB0aGUgYWJvdmUgc3RyaW5ncyBpbnRvIERhdGUgb2JqZWN0cywgYXMgaW46CiNwYXNzIHRoZSBkYXRlIHN0cmluZyB2YXJpYmxlIG9yIGl0cyBsaXRlcmFsIHdpdGggZm9ybWF0IHNwZWMuCnBzbyA8LSBhcy5EYXRlKHByb2dyYW1TdGFydHNPbiwgJyVkICVtICVZJywgdHo9J0FzaWEvQ2FsY3V0dGEnKSAKZWVhIDwtIGFzLkRhdGUoZXZlbnRFbmRzQXQsICcleSAlbSAlZCAlSDolTTolUyAlcCcsIHR6PSdBc2lhL0NhbGN1dHRhJykKCiNpZiB5b3UgZ2V0IHdhcm5pbmdzIG9uIHRpbWV6b25lLCB5b3UgbmVlZCB0byBsb29rIGF0IHpvbmUudGFiIGZpbGUgaW4gCiN0aGUgaW5zdGFsbGF0aW9uIGZvbGRlcnMgb2YgUjsgdGhlIHR6IHNwZWNpZmljYXRpb25zIGFyZSBPUyBzcGVjaWZpYzsKU3lzLnNldGVudihUWj0nQXNpYS9DYWxjdXR0YScpICN0aGUgYXBwcm9wIFRaIGZvciB0aGUgc2Vzc2lvbiB3aWxsIGNsZWFyIGl0Cgojb25jZSBEYXRlIG9iamVjdHMgYXJlIGNyZWF0ZWQsIHRoZWlyIGZvcm1hdHMgY2FuIGJlIGNvbnZlcnRlZCB0byB0aGUKI3JlcXVpcmVtZW50cywgYXMgaW46CmZvcm1hdChwc28sICclWSAlYiAlZCAlSTolTSAlcCAleicpCgojd2hlcmUgdGhlIGZvcm1hdCBzcGVjaWZpY2F0aW9ucyBhcmU6CiMgICVkICAtIG51bWVyaWMgZGF5IG9mIG1vbnRoCiMgICVtICAtIG51bWVyaWMgbW9udGggb2YgdGhlIHllYXIKIyAgJXkgIC0gdHdvIGRpZ2l0IHllYXIgZm9ybWF0CiMgICVZICAtIGZvdXIgZGlnaXQgeWVhciBmb3JtYXQKIyAgJUkgIC0gaG91ciB2YWx1ZSBpbiAxMiBociBmb3JtYXQKIyAgJUggIC0gaG91ciB2YWx1ZSBpbiAyNCBociBmb3JtYXQKIyAgJU0gIC0gbWludXRlcyBvZiB0aGUgaG91cgojICAlUyAgLSBzZWNvbmRzIG9mIHRoZSBtaW51dGUKIyAgJXAgIC0gQU0vUE0gZm9yIDEyIGhyIGZvcm1hdAojICAlYSAgLSB3ZWVrZGF5IGFiYnI7ICAgICAlQSAgLSBGdWxsIHdlZWtkYXkKIyAgJWIgIC0gbW9udGggYWJicjsgICAgICAgJUIgIC0gRnVsbCBtb250aAojICAlaiAgLSBkZWNpbWFsIGRheSBvZiB0aGUgeWVhcgojICAlVSAgLSBkZWNpbWFsIHdlZWsgb2YgdGhlIHllYXIoc3RhcnRpbmcgU3VuZGF5KQojICAlVyAgLSBkZWNpbWFsIHdlZWsgb2YgdGhlIHllYXIoc3RhcnRpbmcgTW9uZGF5KQojICAleiAgLSBvZmZzZXQgZnJvbSBHTVQ7ICAlWiAgLSB0aW1lIHpvbmUKCiN5b3Ugc2hvdWxkIGhhdmUgbm90aWNlZCBhbiBpc3N1ZSB3aXRoIHRoZSBwcmV2aW91cyBmdW5jdGlvbiBjYWxsIHRvIAojZm9ybWF0KCk7IHRoZSB0aW1lIHZhbHVlIHdhcyBpZ25vcmVkIHdpdGggYXMuRGF0ZSgpIGNvbnZlcnNpb247CgojdGhlIGJldHRlciB2ZXJzaW9uIG9mIGFzLkRhdGUoKSB0byBoYW5kbGUgdGhlc2UgaXNzdWVzIGlzIGFzLlBPU0lYY3QoKQpwc28xIDwtIGFzLlBPU0lYY3QocHJvZ3JhbVN0YXJ0c09uLCAnJWQgJW0gJVknLCB0ej1TeXMuZ2V0ZW52KCdUWicpKQplZWExIDwtIGFzLlBPU0lYY3QoZXZlbnRFbmRzQXQsICcleSAlbSAlZCAlSTolTTolUyAlcCcsIHR6PVN5cy5nZXRlbnYoJ1RaJykpCgojbm93IGZvcm1hdCgpIGNhbiBiZSBleGVjdXRlZCB3aXRob3V0IGFueSBpc3N1ZXMsIGFzIGluOgpmb3JtYXQocHNvMSwgJyVZICViICVkICVJOiVNICVwICV6JykKZm9ybWF0KGVlYTEsICclWSAlYiAlZCAlSTolTSAlcCAleicpCgpgYGAKClRoZSBvdGhlciBkYXRlIGZ1bmN0aW9ucyBhbmQgdGhlaXIgdXNlcyBhcmUgbGlzdGUgYmVsb3c6CmBgYHtyIGV2YWw9RiwgZWNobz1UfQpTeXMuZGF0ZSgpICNzeXN0ZW0gZGF0ZQpTeXMudGltZSgpICNzeXN0ZW0gdGltZQpTeXMudGltZXpvbmUoKSAjc3lzdGVtIHRpbWV6b25lCgojdG8gZ2V0IGRpZmZlcmVuY2UgYmV0d2VlbiB0d28gZGF0ZXMKZGlmZnRpbWUocHNvMSwgZWVhMSwgdW5pdHM9J2F1dG8nKQpkaWZmdGltZShmb3JtYXQoU3lzLnRpbWUoKSwnJUg6JU0nKSwgZm9ybWF0KGVlYTEsJyVIOiVNJyksIHVuaXRzPSdhdXRvJykKCiNzcGVjaWZpYyB1bml0cyBvZiBkaWZmZXJlbmNlcyBjYW4gYmUgc3BlY2lmaWVkLiBUaGUgb3B0aW9ucyBhcmU6CiN3ZWVrcywgZGF5cywgaG91cnMsIG1pbnMsIHNlY3MKCiNkaWZmZXJlbmNlIGluIG1vbnRocyBpcyBub3QgYXZhaWxhYmxlLiBTZWUgJ0Z1bmN0aW9ucyhNaXNjZWxsYW5lb3VzKScuCmBgYAoKCiMjIEl0ZXJhYmxlIGNvbnRhaW5lciBvYmplY3RzCkNvbnRhaW5lciBvYmplY3RzIGFyZSB1c2VkIHRvIHN0b3JlIG11bHRpcGxlIHZhbHVlcy4gVmVjdG9ycywgbWF0cmljZXMsIGxpc3RzLCBhbmQgZGF0YWZyYW1lcyBhcmUgdW5pcXVlIGluIHRoZWlyIHN0cnVjdHVyZSBhbmQgcHVycG9zZS4gSG93ZXZlciwgdGhleSBjYW4gYmUgcmVsYXRlZCB0byBlYWNoIG90aGVyIGJ5IHNvbWUgb2YgdGhlaXIgcHJvcGVydGllcy4gUiBhbGxvd3Mgc2Vuc2libGUgY29udmVyc2lvbnMgb2Ygb25lIGNvbnRhaW5lciB0byBhbm90aGVyIHdpdGggc29tZSByZXN0cmljdGlvbnMuIE9uZSBvZiB0aGUgY29tbW9uIGZlYXR1cmUgb2YgY29udGFpbmVyIG9iamVjdHMgaXMgdGhhdCB0aGV5IGFyZSBpdGVyYWJsZS4gSXRlcmFibGUgcmVmZXJzIHRvIGEgbWV0aG9kIG9mIGFjY2Vzc2luZyBlbGVtZW50cyBvZiBhIGNvbnRhaW5lciB0aHJvdWdoIHNlcXVlbnRpYWwgbG9vcGluZyAoc2VlIExvb3Bpbmcgc3RhdGVtZW50cykuCgojIyMgVmVjdG9ycwpWZWN0b3JzIGFyZSBzaW5nbGUgZGltZW5zaW9uYWwgYXJyYXlzLiBUaGV5IGFsbG93IHZhbHVlcyBvZiBzaW5nbGUgZGF0YSB0eXBlLiBXaGVuIHlvdSBhZGQgYSBsb2dpY2FsIHZhbHVlIHRvIGEgbnVtZXJpYyB2ZWN0b3IsIHRoZSBsb2dpY2FsIHZhbHVlcyBhcmUgYXV0b21hdGljYWxseSBjb252ZXJ0ZWQgaW50byBudW1lcmljIHZhbHVlcyAoVFJVRT0xLCBGQUxTRT0wKS4gT24gdGhlIG90aGVyIGhhbmQsIHdoZW4geW91IG1peCBhIGNoYXJhY3RlciB2YWx1ZSB0byBudW1lcmljIHZlY3RvciwgYWxsIGVsZW1lbnRzIGFyZSBjb252ZXJ0ZWQgaW50byBjaGFyYWN0ZXIuIFlvdSBjYW4gdXNlIGZ1bmN0aW9ucyBsaWtlIHR5cGVvZigpLCBpcy5udW1lcmljKCkgYW5kIGFzLmxvZ2ljYWwoKSBsaWtlIGZ1bmN0aW9ucyBvbiB2ZWN0b3JzIGFzIHdlbGwgKHNlZSAqKkRhdGEgdHlwZSBjaGVja2luZywgRGF0YSB0eXBlIGNvbnZlcnNpb25zKiopLiBFYWNoIGVsZW1lbnQgb2YgYSB2ZWN0b3IgY2FuIGJlIGdpdmVuIGEgbmFtZS4gTmFtZWQgdmVjdG9ycyBhcmUgdXNlZnVsIHdoZW4geW91IGhhdmUgYSBmZXcgZWxlbWVudHMuIEhvd2V2ZXIsIHRoZSBkYXRhIHR5cGUgcnVsZXMgYXJlIHRoZSBzYW1lIGZvciBuYW1lZCB2ZWN0b3JzIGFzIHdlbGwuCgojIyMjIEJ1aWx0LWluIHZlY3RvcnMKYGBge3IgZXZhbD1GLCBlY2hvPVR9CiNzb21lIGJ1aWx0LWluIHZlY3RvcnMKTEVUVEVSUyAjdXBwZXIgY2FzZSBlbmdsaXNoIGFscGhhYmV0cwpsZXR0ZXJzICNsb3dlciBjYXNlIGFscGhhYmV0cwptb250aC5uYW1lICMxMiBmdWxsIG1vbnRoIG5hbWVzCm1vbnRoLmFiYiAjMTIgYWJicmV2aWF0aW9ucyBvZiBtb250aCBuYW1lcwpgYGAKCiMjIyMgQ3JlYXRpbmcgdmVjdG9ycwpgYGB7ciBldmFsPUYsIGVjaG89VH0KMToyNSAjY3JlYXRlcyBhIHZlY3RvciBvZiBpbnRlZ2VycyBzdGFydGluZyBmcm9tIDEgdG8gMjUKYygxOjI1KSAjc2FtZSBhcyBhYm92ZQoKYygpICNkb2VzIG5vdCBjcmVhdGUgYSBlbXB0eSB2ZWN0b3I7IGl0IHJlc3V0bHMgaW4gTlVMTAp2ZWN0b3IoKSAjY3JldGVzIGEgZW1wdHkgbG9naWNhbCB2ZWN0b3IKCiN0byBjcmVhdGUgYW4gaW50ZWdlciB2ZWN0b3Igb2YgbGVuZ3RoIDE1IGluaXRpYWxpemVkIHdpdGggMHMKdmVjdG9yKG1vZGU9J2ludGVnZXInLCBsZW5ndGg9MTVMKSAKCnNlcShmcm9tPTEsIHRvPTI1KSAjc2FtZSBhcyBhYm92ZTsgZGVmYXVsdCBpbnRlcnZhbD0xCgpjKDQ1LCAyMywgMTIsIDc2LCAyNCwgOTAsIDg4KSAjYSB2ZWN0b3Igb2YgZG91YmxlIGRhdGEgdHlwZQpjKDQ1TCwgMjNMLCAxMkwsIDc2TCwgMjRMLCA5MEwsIDg4TCkgI2EgdmVjdG9yIG9mIGludGVnZXIgZGF0YSB0eXBlCgpjKCdVQUcnLCAnVUdBJywgJ1VBQScpICNhIGNoYXJhY3RlciB2ZWN0b3IKYyhhbWJlcj0nVUFHJywgdW1iZXI9J1VHQScsIG9jaHJlPSdVQUEnKSAjYSBuYW1lZCBjaGFyYWN0ZXIgdmVjdG9yCgojIE1peGluZyBkYXRhIHZhbHVlcyBkb2VzIGF1dG9tYXRpYyB0eXBlIGNvbnZlcnNpb24KYyg0NSwgMjMsIDEyLCA3NiwgMjQsIFRSVUUsIDg4KSAjbnVtZXJpYyB2ZWN0b3I7IFRSVUUgZ2V0cyB0aGUgdmFsdWUgb2YgMQpjKDQ1LCAnWFknLCAxMiwgNzYsIDI0LCA5MCwgODgpICNjaGFyYWN0ZXIgdmVjdG9yCiNub3RlIHRoYXQgYWxsIG51bWJlcnMgaGF2ZSBiZWNvbWUgY2hhcmFjdGVyIGxpdGVyYWxzCgphIDwtIGMoKSAjZ2l2aW5nIHJlc3VsdHMgYWdhaW5zdCBpbnR1aXRpb247IGRvZXMgbm90IGNyZWF0ZSBlbXB0eSB2ZWN0b3I7IHJlc3VsdHMgaW4gTlVMTAphIDwtIHZlY3RvcigpICNjcmVhdGUgZW1wdHkgdmVjdG9yID0gdmVjdG9yKG1vZGU9J2xvZ2ljYWwnLCBsZW5ndGg9MEwpCnZlY3Rvcihtb2RlPSdkb3VibGUnLCBsZW5ndGg9MTBMKSAjY3JlYXRlcyBkb3VibGUgdmVjdG9yIG9mIGxlbmd0aCAxMDsgZGVmYXVsdCB2YWx1ZXM9MAoKc2VxKDAsIDEsIGJ5PTAuMDEpICNjcmVhdGVzIG51bWVyaWMgdmVjdG9yIHN0YXJ0aW5nIGZyb20gMCB0byAxIHdpdGggYW4gaW50ZXJ2YWwgb2YgMC4wMQoKI2NyZWF0ZXMgbnVtZXJpYyB2ZWN0b3Igd2l0aCBhIHJhbmdlIG9mIDAgdG8gMSBkaXZpZGVkIGludG8gc3BlY2lmaWVkIGxlbmd0aDsKI2ludGVydmFsIGlzIGNhbGN1bGF0ZWQgYnkgbGVuZ3RoIG9mIHZlY3RvciBzcGVjaWZpZWQKc2VxKDAsIDEsIGxlbmd0aC5vdXQ9MTIpIAoKcmVwKFRSVUUsIHRpbWVzPTEwKSAjY3JlYXRlcyBsb2dpY2FsIHZlY3RvciBvZiAxMCBUUlVFcwpyZXAoYyhUUlVFLCBGQUxTRSksIHRpbWVzPTEwKSAjY3JlYXRlcyBsb2dpY2FsIHZlY3RvciBvZiAxMCBjb25zZWN1dGl2ZSBUUlVFLCBGQUxTRXMKcmVwKGMoMSwyLDMpLCBlYWNoPTMpICNlYWNoIGVsZW1lbnQgaW4gYygxLDIsMykgYXJlIHJlcGVhdGVkIDMgdGltZXMKcmVwKGMoMSwyLDMpLCBlYWNoPTMsIGxlbmd0aC5vdXQ9NSkgI3NhbWUgYXMgYWJvdmUsIGJ1dCBsaW1pdHMgdGhlIGxlbmd0aCB0byA1CmBgYAoKCiMjIyMgVmVjdG9yIHR5cGUgY2hlY2tpbmcKVGhlIGZ1bmN0aW9ucyBsaXN0ZWQgdW5kZXIgKipEYXRhIHR5cGUgY2hlY2tpbmcqKiBhbHNvIHdvcmsgb24gdmVjdG9ycy4gVGhlIGZ1bmN0aW9ucyBpcy5uYSgpLCBpcy5udWxsKCksIGlzLmZpbml0ZSgpLCBhbmQgaXMuaW5maW5pdGUoKSBjaGVja3MgZWFjaCBlbGVtZW50IGFuZCByZXR1cm5zIGEgbG9naWNhbCB2ZWN0b3IgcmVwcmVzZW50aW5nIGlmIHRoZSAnaXMnIGNvbmRpdGlvbiBtYXRjaGVkIG9yIG5vdC4KYGBge3IgZXZhbD1GLCBlY2hvPVR9CnggPC0gYyhULCBOVUxMLCBGLCBGLCBULCBGLCBOQSk7IHkgPC0gc2VxKDEsIDEwLCBsZW5ndGgub3V0PTIwKQp6IDwtIGxldHRlcnM7IGsgPC0gYygncmVkJywgTlVMTCwgJ2JsdWUnKTsgdSA8LSBjKDIsIDQsIE5VTEwsIDUsIDkpCiNub3RlIHRoYXQgdGhlIE5VTEwgdmFsdWUgaW4gbG9naWNhbCB2ZWN0b3IgeCBpcyByZXBsYWNlZCB3aXRoIEZBTFNFIGF1dG9tYXRpY2FsbHk7CiNhbmQgdGhlIE5VTEwgaW4gY2hhcmFjdGVyIHZlY3RvciBrIGFuZCBudW1lcmljIHZlY3RvciB1IGFyZSBpZ25vcmVkIGNvbXBsZXRlbHkuCgp0eXBlb2YoeCkgI3JldHVybnMgJ2xvZ2ljYWwnCnR5cGVvZih5KSAjcmV0dXJucyAnZG91YmxlJwoKaXMubG9naWNhbCh4KTsgaXMubG9naWNhbCh5KSAjcmV0dXJucyBUUlVFIGFuZCBGQUxTRSByZXNwZWN0aXZlbHkKaXMuaW50ZWdlcih5KTsgaXMubnVtZXJpYyh5KTsgaXMubnVtZXJpYyh6KSAjcmV0dXJucyBGQUxTRSwgVFJVRSwgRkFMU0UgcmVzcGVjdGl2ZWx5CgojIHRvIGNoZWNrIGlmIGFueSBvZiB0aGUgZWxlbWVudHMgaXMgTkEsIHRoZSBmb2xsb3dpbmcgZnVuY3Rpb24gaXMgdXNlZAppcy5uYSh4KSAjcmV0dXJucyBhIGxvZ2ljYWwgdmVjdG9yIG9mIEZBTFNFLCBGQUxTRSwgRkFMU0UsIEZBTFNFLCBGQUxTRSwgVFJVRQoKI3doZXJlYXMsIGlzLm51bGwoKSBqdXN0IGNoZWNrcyBpZiB0aGUgdmVjdG9yIHggaXMgTlVMTCBvciBub3Q7IGl0IGRvZXMgbm90IGNoZWNrCiNlYWNoIGVsZW1lbnRzCmlzLm51bGwoeCkgI3JldHVybnMgRkFMU0UKYGBgCgoKIyMjIyBWZWN0b3IgdHlwZSBjb252ZXJzaW9ucwpgYGB7ciBldmFsPUYsIGVjaG89VH0KeCA8LSBjKDEyLjM0LCAxNC4yMSwgMTcuMDYsIDE0LjY3KSAjdGhpcyBpcyBhIGRvdWJsZSB2ZWN0b3IKYXMuaW50ZWdlcih4KSAjcmVtb3ZlcyBkZWNpbWFsIHBvaW50cyBmcm9tIHgKYXMuY2hhcmFjdGVyKHgpICNjb252ZXJ0cyB0aGUgZG91YmxlIHZhbHVlcyB0byBzdHJpbmcgbGl0ZXJhbHMKCnkgPC0gYygnMTInLCAnMDAnLCAnMTUnLCAnMTcnLCAnMDAnKSAjdGhpcyBpcyBhIGNoYXJhY3RlciB2ZWN0b3IKYXMubnVtZXJpYyh5KSAjY29udmVydHMgdGhlIGNoYXIgdmVjdG9yIGludG8gbnVtZXJpYyB2ZWN0b3IKCiNjb252ZXJ0cyB0aGUgY2hhciB2ZWN0b3IgaW50byBudW0gdmVjdG9yLCBhbmQgdGhlbiBpbnRvIGxvZ2ljYWwgdmVjdG9yCiNhbGwgemVyb3MgYXJlIEZBTFNFLCB2YWx1ZXMgZ3JlYXRlciB0aGFuIDAgYXJlIFRSVUUKYXMubG9naWNhbChhcy5udW1lcmljKHkpKQoKeiA8LSBjKFQsIEYsIEYsIFQsIFQsIEYpICN0aGlzIGlzIGEgbG9naWNhbCB2ZWN0b3IgVFJVRSBhbmQgRkFMU0UgYXJlIGFiYnJldmlhdGVkCmFzLmludGVnZXIoeikgI2NvbnZlcnRzIGxvZ2ljYWwgdmVjdG9yIGludG8gaW50ZWdlciB2ZWN0b3I7IFQ9MSwgRj0wCmFzLmNoYXJhY3Rlcih6KSAjcmVzdWx0cyBpbiAnVFJVRScsICdGQUxTRScsICdGQUxTRScsICdUUlVFJywgJ1RSVUUnLCAnRkFMU0UnCmBgYAoKCiMjIyMgQWNjZXNzaW5nIGFuZCBlZGl0aW5nIHZlY3RvciBlbGVtZW50cwpgYGB7ciBldmFsPUYsIGVjaG89VH0KIyBBY2Nlc3NpbmcgdmVjdG9yIGVsZW1lbnQgYnkgbG9jYXRpb24gaW5kZXgKCnggPC0gYygxMi4zNCwgMTQuMjEsIDE3LjA2LCAxNC42NykgI3RoaXMgaXMgYSBkb3VibGUgdmVjdG9yCnhbMV0gI2V4dHJhY3RzIHRoZSBmaXJzdCBlbGVtZW50IGZyb20geAp4WzRdIDwtIDIwLjAwICNtb2RpZmllcyB0aGUgNHRoIGVsZW1lbnQgdG8gMjAuMDA7IHRoZSB2ZWN0b3IgeCBpcyBtb2RpZmllZAp4Wy0zXSAjZXh0cmFjdHMgYWxsIGVsZW1lbnRzIG90aGVyIHRoYW4gdGhlIDNyZCBlbGVtZW50CnhbLWMoMSwzKV0gI2V4dHJhY3RzIGFsbCBlbGVtZW50cyBvdGhlciB0aGFuIDFzdCBhbmQgM3JkIGVsZW1lbnQKCiNXQVJOSU1HOnRoaXMgd2lsbCBvdmVyd3JpdGUgdGhlIHZlY3RvciB4IGFuZCByZXBsYWNlIGl0IHdpdGggbnVtZXJpYyBzY2FsYXIKeCA8LSAyMC4wMAp4W10gPC0gMjAuMDAgI3RoaXMgcmVwbGFjZXMgYWxsIHZhbHVlcyB3aXRoIDIwLjAwCnhbMTozXSA8LSAxMC4wMCAjdGhpcyB3aWxsIHJlcGxhY2UgdGhlIGZpcnN0IDMgZWxlbWVudHMgd2l0aCAxMC4wMAp4W2MoMiw1KV0gPC0gNS4wMCAjdGhpcyB3aWxsIHJlcGxhY2UgMm5kIGFuZCA1dGggZWxlbWVudCB3aXRoIDUuMDAKCgojIEFjY2Vzc2luZyB2ZWN0b3IgZWxlbWVudCBieSBuYW1lcyBvZiBlbGVtZW50cwoKc3RvcENvZG9ucyA8LSBjKGFtYmVyPSdVQUcnLCB1bWJlcj0nVUdBJywgb2NocmU9J1VBQScpICN0aGlzIGlzIGEgbmFtZWQgdmVjdG9yCnN0b3BDb2RvbnNbJ3VtYmVyJ10gI3RoaXMgZXh0cmFjdHMgdGhlIHZhbHVlIG9mIGVsZW1lbnQgbmFtZWQgJ3VtYmVyJwpzdG9wQ29kb25zW2MoJ2FtYmVyJywnb2NocmUnKV0gI2V4dHJhY3RzIHZhbHVlcyBvZiBlbGVtZW50cyBuYW1lZCAnYW1iZXInIG9yICdvY2hyZScKCgojIExvZ2ljYWwgZXh0cmFjdGlvbiBvZiB2ZWN0b3IgZWxlbWVudHMKCiN0aGlzIGlzIGEgc2FtcGxlIGNoYXIgdmVjdG9yCnJhbmRvbUxldHRlcnMgPC0gYygieiIsICJyIiwgIm8iLCAibiIsICJnIiwgImoiLCAicyIsICJ2IiwgImkiLCAiZiIpIAoKI1RoZXJlIGFyZSAxMCBhbHBoYWJldHMgaW4gdGhpcyB2ZWN0b3I7IHRoZSBmb2xsb3dpbmcgd2lsbCBleHRyYWN0IGFsbCBlbGVtZW50cyBpbiAKI29kZCBwb3NpdGlvbnM7CiNOb3RlIHRoYXQgaW4gdGhlIGZvbGxvd2luZyBleHByZXNzaW9uLCB0aGUgbG9naWNhbCB2ZWN0b3IgcGFzc2VkIHRvIHZlY3RvciBhY2Nlc3MgCiNvcGVyYXRvciBbXSBoYXMgdGhlIGxvZ2ljYWwgdmFsdWUgVFJVRSBhdCBvZGQgcG9zaXRpb25zCnJhbmRvbUxldHRlcnNbYyhULCBGLCBULCBGLCBULCBGLCBULCBGLCBULCBGKV0KCiNXaXRoIHRoZSBzYW1lIHZlY3RvciwgdGhlIHZvd2VscyBjYW4gYmUgZXh0cmFjdGVkIGJ5IHBhc3NpbmcgdGhlIGxvZ2ljYWwgdmVjdG9yCiN3aXRoIFRSVUUgaW4gdGhlIHBvc2l0aW9ucyB3aGVyZSB2b3dlbHMgYXJlIHByZXNlbnQuIEluIHRoZSBhYm92ZSBleGFtcGxlIHRoZSAzcmQgYW5kIDl0aCAKI3Bvc2l0aW9ucyBoYXZlIHRoZSB2b3dlbHMgJ28nIGFuZCAnaScgcmVzcGVjdGl2ZWx5LgpyYW5kb21MZXR0ZXJzW2MoRiwgRiwgVCwgRiwgRiwgRiwgRiwgRiwgVCwgRildCgojVGhlIGFib3ZlIG1ldGhvZHMgYXJlIGZlYXNpYmxlIHdoZW4gdGhlIHNpemUgb2YgdmVjdG9ycyBpcyBtYW5hZ2VhYmxlLCBhbmQgd2hlbiAKI3RoZSBwb3NpdGlvbnMgb2YgcmVxdWlyZWQgZWxlbWVudHMgYXJlIGtub3duOyB0aGUgJWluJSBvcGVyYXRvciBtYWtlcyB0aGlzCiNlYXN5IGFuZCBzY2FsYWJsZTsKI1RvIG1ha2UgdGhlIGFib3ZlIGV4YW1wbGUgbW9yZSByb2J1c3QsIHRoZSBmb2xsb3dpbmcgY2FuIGJlIHVzZWQ6CnJhbmRvbUxldHRlcnNbcmFuZG9tTGV0dGVycyAlaW4lIGMoJ2EnLCAnZScsICdpJywgJ28nLCAndScpXQoKIyBJbiB0aGUgYWJvdmUgZXhhbXBsZSwgdGhlIGV4cHJlc3Npb24gaW5zaWRlIFtdLCByZXR1cm5zIGEgbG9naWNhbCB2ZWN0b3IgYnkgbWF0Y2hpbmcgZWFjaCAgCiMgZWxlbWVudCB0byB0aGUgcmVmZXJlbmNlIHZlY3RvciBjKCdhJywgJ2UnLCAnaScsICdvJywgJ3UnKTsgYWxsIG1hdGNoaW5nIHBvc2l0aW9ucyBnZXRzCiMgdGhlIHZhbHVlIFRSVUUgYW5kIHRoZSByZW1haW5pbmcgZ2V0cyBGQUxTRQoKI1RoZSBhYm92ZSBleGFtcGxlIGNhbiByZXZlcnNlIHRoZSBjb25kaXRpb24gKGkuZS4gYWxsIGVsZW1lbnRzIHRoYXQgYXJlIE5PVCB2b3dlbHMpIHVzaW5nCiNuZWdhdGlvbiBvcGVyYXRvciwgYXMgZ2l2ZW4gYmVsb3c6CnJhbmRvbUxldHRlcnNbIXJhbmRvbUxldHRlcnMgJWluJSBjKCdhJywgJ2UnLCAnaScsICdvJywgJ3UnKV0KCgojIExvZ2ljYWwgZXh0cmFjdGlvbiBvZiBudW1lcmljIHZlY3RvciBlbGVtZW50cwoKcmFuZG9tTnVtYmVycyA8LSBjKDgsNiw2LHJlcCgzLDMpLHJlcCg0LDMpKSAjdGhpcyBpcyBzYW1wbGUgbnVtZXJpYyB2ZWN0b3Igb2YgOSBlbGVtZW50cwoKIyBUaGUgZm9sbG93aW5nIGV4cHJlc3Npb24gd2lsbCBleHRyYWN0IGFsbCBldmVuIG51bWJlcnMKcmFuZG9tTnVtYmVyc1tjKFQsIFQsIFQsIEYsIEYsIEYsIFQsIFQsIFQpXQoKIy13aGljaCBjYW4gYWxzbyBiZSBhY2hpZXZlZCAocm9idXN0IGFuZCBzY2FsYWJsZSkgdXNpbmcgdGhlIGZvbGxvd2luZyBjb25kaXRpb25hbCBleHByZXNzaW9uCnJhbmRvbU51bWJlcnNbcmFuZG9tTnVtYmVycyAlJSAyID09IDBdCgpgYGAKCiMjIyMgVmVjdG9yIG9wZXJhdGlvbnMKYGBge3IgZXZhbD1GLCBlY2hvPVR9Cm51bU9ic2VydmF0aW9ucyA8LSBjKDIsIDMsIDIsIDQsIDIpCm51bVdlaWdodHMgPC0gYygxLjAsIDAuNSwgMC41LCAyLjAsIDAuMSkKbnVtQ2hhcmdlIDwtIGMoMTAwLCAyMDAsIDMwMCkKCiMgc2NhbGFyIG9wZXJhdGlvbnMgYXJlIHBlcmZvcm1lZCBvbiBldmVyeSBlbGVtZW50IChhcHBsaWNhYmxlIHRvIGFsbCBtYXRoIG9wZXJhdG9ycykKbnVtT2JzZXJ2YXRpb25zICogMTIgI2FsbCBlbGVtZW50cyBhcmUgbXVsdGlwbGllZCBieSAxMgoKIyBvcGVyYXRpb25zIG9uIHR3byB2ZWN0b3JzIG9mIHNhbWUgbGVuZ3RoIChhcHBsaWNhYmxlIGZvciBhbGwgb3BlYXJ0aW9ucykKcmVwKDIsIDUpICogbnVtV2VpZ2h0cyAjZWFjaCBjb21wbGVtZW50YXJ5IHBhaXJzIGFyZSBtdWx0aXBsaWVkCgojb3BlcmF0aW9ucyBvbiB0d28gdmVjdG9ycyBvZiBkaWZmZXJpbmcgbGVuZ3RoIChleGN1dGVkIHdpdGggd2FybmluZyBtZXNzYWdlKTsKI1RoZSBsZW5naHQgb2YgdmVjdG9yIHdpdGggbWluaW11bSBudW1iZXIgb2YgZWxlbWVudHMgaXMgYXV0b21hdGljYWxseSBhZGp1c3RlZCAKI3NvIGFzIHRvIG1hdGNoIHRoZSBsZW5ndGggb2YgbWF4aW11bSBudW1iZXIgb2YgZWxlbWVudHM7IHRoZSBlbGVtZW50cyBpbiB0aGUgbWluaW11bQojbGVuZ3RoIHZlY3RvciBhcmUgcmVwZWF0ZWQgKHJlY3ljbGVkKSBvbmUgb3IgbW9yZSB0aW1lcyB0byBmaWxsIHRoZSBnYXAKbnVtQ2hhcmdlICsgbnVtT2JzZXJ2YXRpb25zICN0aGUgbnVtY2hhcmdlIHZlY3RvciBpcyBleHRlbmRlZCB0byB0aGUgbGVuZ3RoIAojb2YgNSBhdXRvbWF0aWNhbGx5CgojdGhlIG5vdCBvcGVhcnRvciBvbiBhIGxvZ2ljYWwgdmVjdG9yIHJldmVyc2VzIGFsbCBsb2dpY2FsIHZhbHVlcwptb3ZlbWVudERldGVjdGVkX2QxIDwtIGMoVCwgVCwgVCwgRiwgRiwgRiwgVCwgVCwgVCkKbW92ZW1lbnROb3REZXRlY3RlZCA8LSAhKG1vdmVtZW50RGV0ZWN0ZWRfZDEpCgojdGhlIGxvZ2ljYWwgQU5EICgmKSBhbmQgT1IgKHwpIG9wZXJhdG9ycyBjaGVja3MgZXZlcnkgZWxlbWVudHMgcGFpciB3aXNlIG9uCiN0d28gbG9naWNhbCB2ZWN0b3JzCm1vdmVtZW50RGV0ZWN0ZWRfZDIgPC0gYyhULCBULCBGLCBULCBULCBGLCBULCBGLCBUKQptb3ZlbWVudERldGVjdGVkX2QxICYgbW92ZW1lbnREZXRlY3RlZF9kMgoKI25vdGUgdGhhdCB3ZSBkb24ndCB1c2Ugc2NhbGFyIGxvZ2ljYWwgb3BlcmF0b3JzICYmIGFuZCB8fCBvbiB2ZWN0b3JzLCB3aGljaCB3aGVuIHVzZWQgb24gCiN2ZWN0b3JzIGNoZWNrcyBvbmx5IHRoZSBmaXJzdCBwYWlyIG9ubHkKCmBgYAoKCiMjIyMgR2VuZXJpYyB2ZWN0b3IgZnVuY3Rpb25zIChhcHBsaWNhYmxlIHRvIGFsbCB0eXBlcyBvZiB2ZWN0b3JzKQpgYGB7ciBldmFsPUYsIGVjaG89VH0KI2xldCdzIGNyZWF0ZSBhIGNoYXIgdmVjdG9yIG9mIHNvbWUgYWxwaGFiZXRzCnJhbmRvbUxldHRlcnMgPC0gYygieiIsICJyIiwgIm8iLCAibiIsICJnIiwgImoiLCAicyIsICJ2IiwgImkiLCAiZiIpIAoKbmFtZXMoc3RvcENvZG9ucykgI3dvcmtzIG9ubHkgaWYgdGhlIHZlY3RvciBlbGVtZW50cyBhcmUgbmFtZWQKc29ydChyYW5kb21MZXR0ZXJzKSAjc29ydHMgYWxwaGFiZXRzIGluIGFzY2VuZGluZyBvcmRlcgoKI3NhbXBsZSgpIGlzIGEgc3RhdGlzdGljYWwgZnVuY3Rpb24gdGhhdCBzYW1wbGVzIGEgZ2l2ZW4gdmVjdG9yICh0aGUgcG9wdWxhdGlvbikKI2ZvciBhIGdpdmVuIHNhbXBsZSBzaXplOyB0aGUgcGFyYW1ldGVyICdyZXBsYWNlJyB3aGVuIHNldCB0byBUUlVFIGFsbG93cyB0aGUgc2FtcGxlCiN0byBzZWxlY3Qgc2FtZSBlbGVtZW50cyByZXBlYXRlZGx5OyBpbiBzdGF0aXN0aWNhbCB0ZXJtcyB0aGlzIGtpbmQgb2Ygc2FtcGxpbmcgaXMgY2FsbGVkCiNzYW1wbGluZyB3aXRob3V0IGV4Y2x1c2lvbiBvciBzYW1wbGluZyB3aXRoIHJlcGxhY2VtZW50OyB3aGVuIHRoaXMgcGFyYW1ldGVyIGlzIHNldCB0byBGQUxTRSwKI3NhbXBsaW5nIGRvZXMgbm90IGFsbG93IGFuIGVsZW1lbnQgZnJvbSB0aGUgcG9wdWxhdGlvbiB0byBiZSBzZWxlY3RlZCBtb3JlIHRoYW4gb25jZTsKI3doZW4gdGhlIHNhbXBsZSBzaXplIGlzIGxhcmdlciB0aGFuIHRoZSBwb3B1bGF0aW9uLCB0aGVuIGl0IGJlY29tZXMgbWFuZGF0b3J5IHRvIHNldCByZXBsYWNlPVQKcmFuZG9tTnVtYmVycyA8LSBzYW1wbGUoMToxMCwgc2l6ZT01MCwgcmVwbGFjZT1UKSAjc2FtcGxlcyA1MCByYW5kb20gbnVtYmVycyBpbiAxOjEwMAoKc29ydChyYW5kb21OdW1iZXJzLCBkZWNyZWFzaW5nPVQpICNzb3J0cyB0aGUgcmFuZG9tTnVtYmVycyBzYW1wbGUgaW4gZGVzY2VuZGluZyBvcmRlcgpyZXYocmFuZG9tTnVtYmVycykgI2ZsaXBzIG9yIHJldmVyc2VzIHRoZSB2ZWN0b3IgZWxlbWVudHMKbGVuZ3RoKGxldHRlcnMpICNjb3VudHMgZWxlbWVudHMKCnJhbmRvbU51bWJlcnMyIDwtIGMoOCw2LDYscmVwKDMsMykscmVwKDQsMTApLHJlcCg1LDQpKSAjY3JlYXRlcyBhIG51bWVyaWMgdmVjdG9yCgp1bmlxdWUocmFuZG9tTnVtYmVyczIpICNyZW1vdmVzIGR1cGxpY2F0ZXMKZnJlcVJhbmROdW1zIDwtIHRhYmxlKHJhbmRvbU51bWJlcnMyKSAjZnJlcXVlbmN5IG9mIHVuaXF1ZSB2YWx1ZXMKI3RoZSBmb2xsb3dpbmcgZXhwcmVzc2lvbiBnZXRzIHRoZSBwb3NpdGlvbiBvZiB0aGUgdmFsdWUgaGF2aW5nIG1heGltdW0gZnJlcXVlbmN5IAojZnJvbSBmcmVxdWVuY3kgdGFibGUgKCdmcmVxUmFuZE51bXMnKQp3aGljaC5tYXgoZnJlcVJhbmROdW1zKQoKZnJlcVJhbmROdW1zW3doaWNoLm1heChmcmVxUmFuZE51bXMpXSAjZmV0Y2hlcyB0aGUgZnJlcXVlbmN5IG9mIHVuaW1vZGFsIHZhbHVlCgojbGV0J3MgZXh0ZW5kIHRoZSByYW5kb21OdW1iZXJzMiB3aXRoIGEgcmVwZWF0IG9mIHRoZSBkaWdpdCA1IG9mIGxlbmd0aCA2OyB0aGlzIG1ha2VzIAojdGhlIHZlY3RvciBiaW1vZGFsOyB0aGlzIGlzIHRvIGdpdmUgYSBkZW1vIG9uIGhvdyB0byBnZXQgCnJhbmRvbU51bWJlcnMyIDwtIGMocmFuZG9tTnVtYmVyczIsIHJlcCg1LDYpKQpmcjIgPC0gdGFibGUocmFuZG9tTnVtYmVyczIpICN0aGlzIGNyZWF0ZXMgZnJlcXVlbmN5IHRhYmxlIGZvciB0aGUgbW9kaWZpZWQgdmVjdG9yCiN0aGUgZm9sbG93aW5nIGV4cHJlc3Npb24gZ2V0cyBhbGwgbW9kYWxzIG9mIHNhbWUgbGVuZ3RoIGZyb20gdGhlIG5ldyBmcmVxdWVuY3kgdGFibGUgJ2ZyMicKYXMubnVtZXJpYyhuYW1lcyhmcjJbZnIyID09IGZyMlt3aGljaC5tYXgoZnIyKV1dKSkKCmBgYAoKCiMjIyMgTnVtZXJpYyB2ZWN0b3IgZnVuY3Rpb25zCgpgYGB7ciBldmFsPUYsIGVjaG89VH0Kc3VtKHJhbmRvbU51bWJlcnMpICN0b3RhbGluZwoKc3VtKG1vdmVtZW50RGV0ZWN0ZWQpICNsb2dpY2FsIHZlY3RvciBzdW1taW5nOyBUPTE7IEY9MAojdGhlIGxvZ2ljYWwgdmVjdG9yIHN1bW1pbmcgd2lsbCBiZSB1c2VmdWwgdG8gY2hlY2sgaG93IG1hbnkgZWxlbWVudHMgaW4gYSB2ZWN0b3IKI21hdGNoZXMgYSBwYXJ0aWN1bGFyIGNvbmRpdGlvbjsgaXQgaXMgbGlrZSB0YWtpbmcgdGhlIGNvdW50IG9mIGFsbCBUUlVFcwoKI3RvIGNvdW50IHRoZSBudW1iZXIgb2YgcmFuZG9tTGV0dGVycyB0aGF0IGFyZSB2b3dlbHMKc3VtKHJhbmRvbUxldHRlcnMgJWluJSBjKCdhJywnZScsJ2knLCdvJywndScpKQojdG8gY291bnQgdGhlIG51bWJlciAgb2YgZWxlbWVudHMgdGhhdCBhcmUgZXZlbgpzdW0ocmFuZG9tTnVtYmVycyAlJSAyID09IDApCgojdGhlIGZvbGxvd2luZyBhcmUgc29tZSBmcmVxdWVudGx5IHVzZWQgbnVtZXJpYyB2ZWN0b3IgZnVuY3Rpb25zOwojdGhlIHBhcmFtZXRlciBuYS5ybSB3aGVuIHNldCB0byBUUlVFLCBpZ25vcmVzIG1pc3NpbmcgdmFsdWVzIHByZXNlbnQgaW4gYSB2ZWN0b3I7CiN3aGVuIHRoaXMgcGFyYW1ldGVyIGlzIEZBTFNFIChkZWZhdWx0KSBhbmQgd2hlbiB0aGUgbnVtZXJpYyB2ZWN0b3IgY29udGFpbnMKI21pc3NpbmcgdmFsdWVzIChyZXByZXNlbnRlZCBieSBOQSksIHRoZXNlIGZ1bmN0aW9ucyB3aWxsIHJldHVybiBOQSBhcyB0aGUgcmVzdWx0CgptZWFuKHJhbmRvbU51bWJlcnMsIG5hLnJtPVQpICNhdmVyYWdpbmcKbWF4KHJhbmRvbU51bWJlcnMsIG5hLnJtPVQpIAptaW4ocmFuZG9tTnVtYmVycywgbmEucm09VCkKcmFuZ2UocmFuZG9tTnVtYmVycywgbmEucm09VCkgI2dpdmVzIG1pbiB0byBtYXggcmFuZ2UKbWVkaWFuKHJhbmRvbU51bWJlcnMsIG5hLnJtPVQpICNjZW50ZXIgYXZlcmFnZT1sb2NhdGlvbgp2YXIocmFuZG9tTnVtYmVycywgbmEucm09VCkgI3ZhcmlhbmNlCnNkKHJhbmRvbU51bWJlcnMsIG5hLnJtPVQpICNzdGFuZGFyZCBkZXZpYXRpb24KCiNNb2RlICg9IHRoZSBtb3N0IGZyZXF1ZW50bHkgb2JzZXJ2ZWQgdmFsdWUpIGZ1bmN0aW9uIGlzIG5vdCBhdmlsYWJsZSBpbiB0aGUKI2Jhc2UgUjsgc2VlICdGdW5jdGlvbnMoTWlzY2VsbGFuZW91cyknIGZvciBhIGZ1bmN0aW9uIGRlZmluaXRpb24gb2YgbW9kZTsKCiNpZiB5b3Ugd2FudCB0byBjbGFzc2lmeSBudW1lcmljIHZlY3RvciB2YWx1ZXMgaW50byBncm91cHMgdXNpbmcgCiNsZXZlbHMgb3IgYnJlYWtzIG9yIGJpbnMsIHVzZSBjdXQoKSBmdW5jdGlvbiwgYXMgaW46CgojKDEpIHNwZWNpZnkgbnVtYmVyIG9mIGdyb3VwcyBieSAnYnJlYWtzJyBwYXJhbWV0ZXIKI2N1dHMgMToxMCBpbiB0d28gZXF1YWwgZ3JvdXBzIGFuZCBsYWJlbHMgdGhlbSBhcyBBIGFuZCBCCmN1dCgxOjEwLCBicmVha3M9MiwgbGFiZWxzPWMoJ0EnLCdCJykpCiNkb2VzIHRoZSBzYW1lIHRyaWNrIGV2ZW4gaWYgbnVtYmVycyBhcmUgc2h1ZmZsZWQKY3V0KGMoMTAsIDMsIDYsIDIsIDQsIDcsIDEsIDksIDUpLCBicmVha3M9MiwgbGFiZWxzPWMoJ0EnLCdCJykpCgojKDIpIG9yIHNwZWNpZnkgZXhhY3QgYnJlYWsgcG9pbnRzIHVzaW5nIGEgdmVjdG9yCmN1dCgxOjEwLCBicmVha3M9YygwLDUsMTApLCBsYWJlbHM9YygnQScsJ0InKSkKI05vdGU6IHRvIGluY2x1ZGUgdGhlIG1pbmltdW0gdmFsdWUgaW4gdGhlIGdyb3VwaW5nIHNldCB0aGUgbG93ZXN0CiNicmVhayBwb2ludCBhcyBtaW5pbXVtLTEKCiNBbHNvIG5vdGUgdGhhdCBieSBzcGVjaWZ5aW5nIGxhYmVscyB3aXRoIGEgdmVjdG9yIG9mIGxhYmVscywgdGhlbgojdGhlIGEgZmFjdG9yaXplZCB2ZWN0b3IgaXMgcmV0dXJuZWQgKFNlZSAnRmFjdG9ycycgYW5kIHJldmlzaXQgdGhpcy4uLik7CiNJbnN0ZWFkIHlvdSBzZXQgbGFiZWxzPUZBTFNFIHRvIGdldCBudW1lcmljIG9yZGVyaW5nIG9mIGdyb3VwcyBhcwojYSBzaW1wbGUgdmVjdG9yLCBhcyBpbjoKY3V0KGMoMToxMCksIGJyZWFrcz0yLCBsYWJlbHM9RkFMU0UpCgpgYGAKCiMjIyMgQ2hhcmFjdGVyIHZlY3RvciBmdW5jdGlvbnMKCmBgYHtyIGV2YWw9RiwgZWNobz1UfQojdGhlIGZvbGxvd2luZyBpcyBhIHN0cmluZyB2YXJpYWJsZSAoaW4gUiB0aGlzIGlzIGEgY2hhcmFjdGVyIHZlY3RvciBvZiBsZW5ndGggMSk7CiNpbiBlbmdsaXNoIHRoaXMgaXMgYSBzZW50ZW5jZQpteVRleHQgPC0gJ1lvdSBjYW5cJ3QgZ2V0IG91dCBvZiBsaWZlIGFsaXZlISBCZSBib2xkIScKI25vdGUgdGhhdCBpbiB0aGUgc3RyaW5nIHdlIGhhdmUgdXNlZCB0aGUgZXNjYXBlIGNoYXJhY3RlciBiYWNrc2xhc2ggKFwpIHRvIAojbGV0IFIga25vdyB0aGF0IHRoZSBzaW5nbGUgcXVvdGUgaW5zaWRlIHRoZSBzdHJpbmcgaXMgYSBwYXJ0IG9mIGl0CgojdG8gc3BsaXQgdGhlIGFib3ZlIHRleHQgYnkgc3BhY2UgZGVsaW1pdGVyOgpzdHJzcGxpdChteVRleHQsIHNwbGl0PScgJykgI2NyZWF0ZXMgYSBjaGFyYWN0ZXIgdmVjdG9yIG9mIHdvcmRzIHNlcGVyYXRlZCBieSBzaW5nbGUgc3BhY2UKCiN0byBzcGxpdCB0aGUgc2FtZSBieSBleGNsYW1hdG9yeSBtYXJrOgpzdHJzcGxpdChteVRleHQsIHNwbGl0PSchJykgI2NyZWF0ZXMgYSBjaGFyIHZlY3RvciBvZiBsZW5ndGggMgoKCiNsZXQgdXMgY3JlYXRlIGEgc2FtcGxlIChzaXplPTk5OSkgb2YgbGV0dGVycyBkZW5vdGluZyBudWNsZW90aWRlIGJhc2VzIHRoYXQgCiNmb3JtcyB0aGUgc3RydWN0dXJlIG9mIGdlbmVzCnJhbmRvbU51Y2xlb3RpZGVzIDwtIHNhbXBsZShjKCdhJywndScsICdnJywgJ2MnKSwgOTk5LCByZXBsYWNlPVQpCgojIHBhc3RlMCBjb25jYXRlbmF0ZXMgdmVjdG9yIGVsZW1lbnRzIHVzaW5nIHNlcGVyYXRvciBzcGVjaWZpZWQgYnkgY29sbGFwc2UKcmFuZG9tR2VuZVNlcSA8LSBwYXN0ZTAocmFuZG9tTnVjbGVvdGlkZXMsIGNvbGxhcHNlPScnKSAjbm90ZTogY29sbGFwc2Ugc3BlY2lmaWVzIGVtcHR5IHN0cmluZwoKI3RoZSBhYm92ZSBleHByZXNzaW9uIGJpbmRzIGFsbCA5OTkgcmFuZG9tIGJhc2UgbGV0dGVycyAoPWNoYXIgdmVjdG9yIG9mIGxlbmd0aCA5OTkpIAojaW50byBvbmUgc3RyaW5nICg9Y2hhciB2ZWN0b3Igb2YgbGVuZ3RoIDEpCgpsZW5ndGgocmFuZG9tTnVjbGVvdGlkZXMpICNnaXZlcyB0aGUgbGVuZ3RoIG9mIGNoYXIgdmVjdG9yCm5jaGFyKHJhbmRvbUdlbmVTZXEpICNnaXZlcyB0aGUgbGVuZ3RoIG9mIHRoZSBzdHJpbmcKCnJhbmRvbUdlbmVTZXEgPC0gdG91cHBlcihyYW5kb21HZW5lU2VxKSAjY29udmVydHMgdG8gdXBwZXIgY2FzZQoKZmlyc3RDb2RvbiA8LSBzdWJzdHIocmFuZG9tR2VuZVNlcSwgMSwgMykgI2V4dHJhY3RzIHBhcnQgb2YgdGhlIHN0cmluZyBmcm9tIDEgdG8gMwoKIyBzcGxpdCB0aGUgZ2VuZSBzZXF1ZW5jZSBzdHJpbmcgYnkgYSBnaXZlbiBsZW5ndGg7IGNvZG9ucyBhcmUgdHJpcGxldCBiYXNlcwpjb2RvbnMgPC0gc3Vic3RyaW5nKHJhbmRvbUdlbmVTZXEsIGZpcnN0PXNlcSgxLCBuY2hhcihyYW5kb21HZW5lU2VxKS0yLCBieT0zKSwgCiAgICAgICAgICAgICAgICAgbGFzdD1zZXEoMywgbmNoYXIocmFuZG9tR2VuZVNlcSksIGJ5PTMpKQoKI3RoZSBmdW5jdGlvbiBzdWJzdHJpbmcoKSBhbGxvd3MgaXRzIHBhcmFtZXRlcnMgJ2ZpcnN0JyBhbmQgJ2xhc3QnIHRvCiN0YWtlIGEgdmVjdG9yIG9mIHN0YXJ0aW5nIHBvc2l0aW9ucyBhbmQgZW5kaW5nIHBvc2l0aW9ucyByZXNwZWN0aXZlbHkKCnRhYmxlKGNvZG9ucykgI0ZyZXF1ZW5jeSBvZiBlYWNoIHVuaXF1ZSBjb2RvbiBpbiB0aGUgdmVjdG9yICdjb2RvbnMnCgoKIyBlYXJsaWVyIHdlIGhhZCBzZWVuIHN0cnNwbGl0KCkgY2FuIGJlIHVzZWQgdG8gc3BsaXQgYSBzdHJpbmcgdXNpbmcgZGVsaW1pdGVycwojIHN1Y2ggYXMgYSBzcGFjZSBvciBvciBhIHNwZWNpYWwgY2hhcmFjdGVyOyBpbiBmYWN0LCB0aGUgZGVsaW1pdGVyIGNhbiBiZSAKIyBhbnkgY2hhcmFjdGVyIG9yIGEgc3RyaW5nIG9yIGEgd29yZDsgaXQgY2FuIGFsc28gYmUgcmVndWxhciBleHByZXNzaW9uczsKIyBzb21lIGV4YW1wbGVzIGFyZSBnaXZlbiBiZWxvdwoKIyBzcGxpdCB2ZWN0b3IgYnkgYSBnaXZlbiB2YWx1ZQpjb2RvbnMxIDwtIHN0cnNwbGl0KHJhbmRvbUdlbmVTZXEsIHNwbGl0PSdVQUcnKSAjc3BsaXRzIHRoZSBzdHJpbmcgdXNpbmcgYSB3b3JkICgnVUFHJykKCiNub3RlIHRoYXQgc3Ryc3BsaXQgcmV0dXJucyB0aGUgdmFsdWUgYXMgYSBsaXN0OyBoZW5jZSwgY29kb25zMSBpcyBhIGxpc3Qgb2JqZWN0CgojaWYgc3BsaXQgbmVlZHMgdG8gaGFwcGVuIGlmIGFueSBvZiBhIGdpdmVuIHNldCBvZiB3b3JkcywgdGhlbiB0aGUgcmVndWxhciBleHByZXNzaW9uCiMgdG8gYmUgcGFzc2VkIHRvIHRoZSBzcGxpdCBwYXJhbWV0ZXIgaXM6CnNwbGljZWRTZXEgPC0gc3Ryc3BsaXQocmFuZG9tR2VuZVNlcSwgc3BsaXQ9JyhVQUd8VUdBfFVBQSknKQoKI2xldCB1cyBjcmVhdGUgYSBzdHJpbmcgbGl0ZXJhbCBvZiBzcGVjaWFsIGNoYXJhY3RlcnM7CgpzcGVjaWFsQ2hhcnMgPC0gJ34hQCMkJV4mKigpXystPXt9W118XFw6OyJcJzwsPi4/LycgI3RoZXJlIGFyZSAzMSBzcGVjaWFsIGNoYXJzIGluIHRoaXMgc3RyaW5nCiNub3RlIHRoYXQgZm9yIHNvbWUgc3BlY2lhbCBjaGFyYWN0ZXJzIHdoZW4gd3JpdHRlbiBpbiBhIHN0cmluZyBsaXRlcmFsLCB0aGV5CiNuZWVkIHRvIGJlIGdpdmVuIHdpdGggZXNjYXBlIGNoYXJhY3RlciBiYWNrc2xhc2ggKFwpOyAKI3N1Y2ggc3BlY2lhbCBjaGFyYWN0ZXJzIGFyZSB0aGUgYmFja3NsYXNoIGl0c2VsZiwgYW5kIGEgc2luZ2xlIHF1b3RlOwojYSBzaW5nbGUgcXVvdGUgbmVlZHMgYW4gZXNjcGFlIGNoYXJhY3RlciB3aGVuIGl0IGFwcGVhcnMgaW5zaWRlIGEgc3RyaW5nIGVuY2xvc2VkIGJ5IHR3bwojc2luZ2xlIHF1b3RlczsgaWYgYSBzdHJpbmcgbGl0ZXJhbCBpcyBlbmNsb3NlZCB3aXRoaW4gZG91YmxlIHF1b3RlcyB0aGVuIHRoZSBzaW5nbGUKI3F1b3RlIGRvZXMgbm90IHJlcXVpcmUgdGhlIGVzY2FwZSBjaGFyYWN0ZXIsIGluc3RlYWQgYSBkb3VibGUgcXVvdGUgd2lsbDsKI3RyeSB0byByZW1vdmUgdGhlIGVzY2FwZSBjaGFyYWN0ZXIgYW5kIHNlZSB3aGF0IGhhcHBlbnMKCiNzdXBwb3NlIGlmIHlvdXIgc3RyaW5nIGNvbnRhaW5zIGFueSBvZiB0aGVzZSBzcGVjaWFsIGNoYXJzIGFuZCB5b3Ugd2FudCB0byAKI3NwbGl0IHlvdXIgc3RyaW5nIGJ5IG9uZSBvZiB0aGUgc3BlY2lhbCBjaGFyYWN0ZXJzLCB0aGVuIHlvdSBjYW4gdmVyeSB3ZWxsCiN1c2UgdGhlbSBhcyBkZWxpbWl0ZXJzIEVYQ0VQVCBmb3IgJCAoZG9sbGFyKSwgXiAoY2FyZXQpLCAqIChhc3RlcmlzayksICgpIChvcGVuIG9yIGNsb3NlCiNwYXJlbnRoZXNlcyksICsgKHBsdXMpLCB7fSAob3BlbiBvciBjbG9zZSBjdXJseSBicmFja2V0cyksIFtdIChvcGVuIG9yIGNsb3NlIHNxdWFyZQojYnJhY2tldHMpLCB8IChwaXBlKSwgLiAoZG90KSwgPyAocXVlc3Rpb24pCgojaWYgeW91IHN0aWxsIHdhbnQgdG8gc3BsaXQgYSBzdHJpbmcgd2l0aCB0aGVzZSBleGNlcHRpb25hbCBzcGVjaWFsIGNoYXJzLCB0aGVuCiN1c2UgdGhlIGZvbGxvd2luZyByZWd1bGFyIGV4cHJlc3Npb246CnVubGlzdChzdHJzcGxpdChzcGVjaWFsQ2hhcnMsIHNwbGl0PSdcXCQnKSkgI2p1c3QgcmVwbGFjZSAkIHdpdGggYW55IG9mIHRoZSBleGNlcHRpb25hbCBjaGFycyAKCiNpbiBhZGRpdGlvbiB0byB0aGF0LGlmIHlvdSB3YW50IHRvIHNwbGl0IGJ5IGJhY2tzbGFzaCwgdGhlbiB1c2U6CnVubGlzdChzdHJzcGxpdChzcGVjaWFsQ2hhcnMsIHNwbGl0PSdcXFxcJykpCiNhbmQgZm9yIGEgc2luZ2xlIHF1b3RlIChhbHNvIGRvdWJsZSBxdW90ZSBpZiB0aGUgc3RyaW5nIGVuY2xvc2VkIGluIGRvdWJsZSBxdW90ZXMpCnVubGlzdChzdHJzcGxpdChzcGVjaWFsQ2hhcnMsIHNwbGl0PSdcJycpKQoKCiMgc2VhcmNoIGFuZCBleHRyYWN0IGNoYXIgdmVjdG9yIHVzaW5nIGdyZXAoKSBmdW5jdGlvbiBhbmQgcmVndWxhciBleHByZXNzaW9ucwoKI2xldCB1cyBjcmVhdGUgc29tZSBjaGFyIHZlY3RvcnMgZm9yIGRlbW8KY2hlbUZvcm11bGFlIDwtIGMoJ05hSENPXzMnLCdOYUNsTycsJ0hfMk9fMicsJ05hQk9fMycsJ05hXzJCXzRPXzcuMTAgSF8yTycsJ1MnLCdLSENfNEhfNE9fNicsCiAgICAgICAgICAgICAgICAgICdNZ1NPXzQuNyBIXzJPJywnQ0ZfMkNsXzInLCdQYlMnLCdDXzJIXzVPSCcsJ0MnLCdDYVNPXzQuMiBIXzIwJywnTmFfMlNfMk9fMycsCiAgICAgICAgICAgICAgICAgICdOXzJPJywnQ2FPJywnQ2FDT18zJywnTmFPSCcsJ0NhQ09fMycsJ0NIXzNDT0NfMkhfNScsJ01nKE9IKV8yJywnSENsJywKICAgICAgICAgICAgICAgICAgJ0hfMlNPXzQnLCdDYVNPXzQuMiBIXzJPJywnS18yQ09fMycsJ0ZlU18yJywnU2lPXzInLCdIZycsJyhDSF8zKV8yQ0hPSCcsCiAgICAgICAgICAgICAgICAgICdOSF80Q2wnLCdOYUNsJywnS0NsJywnS05PXzMnLCdDYShPSClfMicsJ0NfMTJIXzIyT18xMScsJ05hXzNQT180JywKICAgICAgICAgICAgICAgICAgJ05hXzJDT18zLjEwIEhfMk8nLCdDSF8zT0gnKQpjaGVtTmFtZXMgPC0gYygnc29kaXVtIGJpY2FyYm9uYXRlJywnc29kaXVtIGh5cG9jaGxvcml0ZScsJ2h5ZHJvZ2VuIHBlcm94aWRlJywKICAgICAgICAgICAgICAgJ3NvZGl1bSBwZXJib3JhdGUnLCdzb2RpdW0gdGV0cmFib3JhdGUgZGVjYWh5ZHJhdGUnLCdzdWxmdXInLAogICAgICAgICAgICAgICAncG90YXNzaXVtIGh5ZHJvZ2VuIHRhcnRyYXRlJywnbWFnbmVzaXVtIHN1bGZhdGUgaGVwdGFoeWRyYXRlJywKICAgICAgICAgICAgICAgJ2RpY2hsb3JvZGlmbHVvcm9tZXRoYW5lJywnbGVhZCAoSUkpIHN1bGZpZGUnLCdldGhhbm9sJywnY2FyYm9uJywKICAgICAgICAgICAgICAgJ2NhbGNpdW0gc3VsZmF0ZSBkaWh5ZHJhdGUnLCdzb2RpdW0gdGhpb3N1bGZhdGUnLCdkaW5pdHJvZ2VuIG94aWRlJywKICAgICAgICAgICAgICAgJ2NhbGNpdW0gb3hpZGUnLCdjYWxjaXVtIGNhcmJvbmF0ZScsJ3NvZGl1bSBoeWRyb3hpZGUnLCdjYWxjaXVtIGNhcmJvbmF0ZScsCiAgICAgICAgICAgICAgICdldGh5bCBtZXRoeWwga2V0b25lJywnbWFnbmVzaXVtIGh5ZHJveGlkZScsJ2h5ZHJvY2hsb3JpYyBhY2lkJywKICAgICAgICAgICAgICAgJ3N1bGZ1cmljIGFjaWQnLCdjYWxjaXVtIHN1bGZhdGUgaHlkcmF0ZScsJ3BvdGFzc2l1bSBjYXJib25hdGUnLAogICAgICAgICAgICAgICAnaXJvbiBkaXN1bGZpZGUnLCdzaWxpY29uIGRpb3hpZGUnLCdtZXJjdXJ5JywnaXNvcHJvcHlsIGFsY29ob2wnLAogICAgICAgICAgICAgICAnYW1tb25pdW0gY2hsb3JpZGUnLCdzb2RpdW0gY2hsb3JpZGUnLCdwb3Rhc3NpdW0gY2hsb3JpZGUnLAogICAgICAgICAgICAgICAncG90YXNzaXVtIG5pdHJhdGUnLCdjYWxjaXVtIGh5ZHJveGlkZScsJ3N1Y3Jvc2UnLCdzb2RpdW0gcGhvc3BoYXRlJywKICAgICAgICAgICAgICAgJ3NvZGl1bSBjYXJib25hdGUgZGVjYWh5ZHJhdGUnLCdtZXRoeWwgYWxjb2hvbCcpCgojIHRoZSBnZW5lcmFsIHN5bnRheCBvZiBncmVwKCkgZnVuY3Rpb24gaXM6CiMgZ3JlcChwYXR0ZXJuPSd0aGUgcmVndWxhciBleHByZXNzaW9uIGlzIHVzZWQgaGVyZScsIAojICAgICAgeD08dGhlIGNoYXIgdmVjdG9yIHRoYXQgbmVlZHMgdG8gYmUgc2VhcmNoZWQ+LCAKIyAgICAgIGlnbm9yZS5jYXNlPUYsIHZhbHVlPUYpCgojdGhlIDNyZCBwYXJhbWV0ZXIgJ2lnbm9yZS5jYXNlJyBpcyBzZXQgdG8gVFJVRSBvciBGQUxTRSBmb3IgdG9nZ2xpbmcgY2FzZSBzZW5zaXRpdml0eTsKI3RoZSA0dGggcGFyYW1ldGVyICd2YWx1ZScgaXMgc2V0IHRvIFRSVUUgaWYgeW91IHdhbnQgdGhlIGdyZXAoKSB0byByZXR1cm4gdGhlIGVsZW1lbnRzCiNpbiB0aGUgdmVjdG9yIHRoYXQgbWF0Y2hlcyB0aGUgcmVndWxhciBleHByZXNzaW9uczsgYnkgZGVmYXVsdCAoRkFMU0UpIGl0IHJldHVybnMgdGhlIAojaW5kZXggcG9zaXRpb24gb2YgdGhlIG1hdGNoaW5nIGVsZW1lbnRzCgpncmVwKCdPSCcsIGNoZW1Gb3JtdWxhZSkgI3JldHVybnMgaW5kZXggbG9jYXRpb25zIG9mIGNvbXBvdW5kcyBoYXZpbmcgT0ggZ3JvdXAKI2luIHRoZSBhYm92ZSBleHByZXNzaW9uLCBncmVwIHNlYXJjaGVzIGZvciB0aGUgcHJlc2VuY2Ugb2YgT0ggYXMgaXM7CiN3aGVuIHRoZSBzZWFyY2ggc3RyaW5nIE9IIGlzIGdpdmVuIHdpdGhpbiBzcXVhcmUgYnJhY2tldHMgLSAnW09IXScsIHRoZW4KI2l0IHdpbGwgcmVzdWx0IGluIGNvbXBvdW5kcyB0aGF0IGhhdmUgb3h5Z2VuIGFuZC9vciBoeWRyb2dlbiBpbiBpdHMgZm9ybXVsYWU7Cgojbm90ZSB0aGF0IHRoZSBhYm92ZSBleHByZXNzaW9uIHJldHVybnMgdGhlIGluZGV4IGxvY2F0aW9ucyBhcyBhIHZlY3Rvcjsgd2hpY2ggY2FuIAojYmUgdXNlZCB0byBmZXRjaCB0aGUgcmVsYXRlZCBlbGVtZW50cyBmcm9tIGNoZW1Gb3JtdWxhZSBvciBjaGVtTmFtZXMsIGFzIGdpdmVuIGJlbG93OgpjaGVtRm9ybXVsYWVbZ3JlcCgnT0gnLCBjaGVtRm9ybXVsYWUpXQojdGhpcyBpcyBlcXVpdmFsZW50IG9mIGdyZXAoJ09IJywgY2hlbUZvcm11bGFlLCB2YWx1ZT1UKQojYnV0IHRoZSBpbmRleCBsb2NhdGlvbnMgYXJlIHVzZWZ1bCwgaWYgdXNlZCB0byBnZXQgdGhlIGNvcnJlc3BvbmRpbmcgY2hlbWljYWwgbmFtZXMgdGhhdAojYXJlIHN0b3JlZCBpbiBhIGRpZmZlcmVudCB2ZWN0b3IgKGNoZW1OYW1lcyksIGFzIGluOgpjaGVtTmFtZXNbZ3JlcCgnT0gnLCBjaGVtRm9ybXVsYWUpXQoKCiN0byBzZWFyY2ggZm9yIE5hIG9yIEsgaW4gdGhlIGNvbXBvdW5kcywgbGV0IHVzIHRyeToKZ3JlcCgnW05hS10nLCBjaGVtRm9ybXVsYWUsIHZhbHVlPVQpICN0aGVyZSBpcyBhIHByb2JsZW0gaW4gdGhpcyEKCiN0aGUgYWJvdmUgZXhwcmVzc2lvbiB3aWxsIGZldGNoIHRoZSBjb21wb3VuZHMgd2l0aCB0aGUgbGV0dGVycyBOLCBhLCBLLCB3aGljaAojaXMgbm90IHRoZSBpbnRlbmRlZCBzZWFyY2g7IHdlIHdhbnRlZCB0byBjb25zaWRlciBOYSBhcyBhIHNlcGVyYXRlIHNlYXJjaCBvcHRpb24gCiNhbG9uZyB3aXRoIEs7IGluIG9yZGVyIHRvIGFjaGlldmUgdGhlIGV4cGVjdGVkIHJlc3VsdHMsIHdlIHdvdWxkIHVzZSB0aGUgZm9sbG93aW5nOgpncmVwKCdOYXxLJywgY2hlbUZvcm11bGFlLCB2YWx1ZT1UKQoKI3N1cHBvc2UsIHdlIHdhbnQgdG8gc2VhcmNoIGZvciBjb21wb3VuZHMgdGhhdCBoYXZlIE5hIG9yIEsgYW5kIGFsc28gCiNmb2xsb3dlZCBieSAnT0gnIHNvbWV3aGVyZTsgbGV0IHVzIHRyeSB1c2luZyB0aGUgcmVndWxhciBleHByZXNzaW9uIGFzIGdpdmVuIGJlbG93OgpncmVwKCdOYXxLLipPSCcsIGNoZW1Gb3JtdWxhZSwgdmFsdWU9VCkgI3RoZXJlIGlzIGEgcHJvYmxlbSBoZXJlIQoKI2JlZm9yZSBzb2x2aW5nIHRoZSBwcm9ibGVtLCBsZXQgdXMgdW5kZXJzdGFuZCB0aGUgdXNlIG9mIC4qOwojIHRoZSBkb3QgY2hhcmFjdGVyIHJlcHJlc2VudHMgYW55IGNoYXJhY3RlciBhbmQgKiBpbmRpY2F0ZXMgdGhhdCB0aGUgcHJlY2VkaW5nIAojY2hhcmFjdGVyIG1heSBhcHBlYXIgYW55IG51bWJlciBvZiB0aW1lczsgaGVyZSB0aGUgcHJlY2VkaW5nIGNoYXJhY3RlciBpcyBhbnkgCiNjaGFyYWN0ZXIgKHdoaWNoIGlzIGEgZG90ISkKCiN0aGUgYWJvdmUgcmVzdWx0cywgaW4gZmFjdCBmaW5kcyBhbGwgY29tcG91bmRzIHdpdGggTmEgb3IgSywgYnV0IGl0IGRvZXMgbm90CiNjb3JyZWN0bHkgaWRlbnRpZmllZCB0aGUgT0ggZ3JvdXBzIGFmdGVyIE5hIG9yIEs7IGluc3RlYWQgaXQgc2VhcmNoZWQgZm9yIHRoZSAKI2xldHRlcnMgTyBvciBIIGFmdGVyIE5hIG9yIEs7IHRoaXMgcHJvYmxlbSBjYW4gYmUgc29sdmVkIHVzaW5nIHRoZSBmb2xsb3dpbmcgCiNleHByZXNzaW9uOgpncmVwKCcoTmF8SykuKihPSCknLCBjaGVtRm9ybXVsYWUsIHZhbHVlPVQpCiNpbiB0aGUgYWJvdmUgZXhwcmVzc2lvbiwgd2UgaGF2ZSBpbnRyb2R1Y2VkICgpIHRvIGVuY2xvc2UgdGhlIHNlYXJjaCB3b3Jkcywgd2hpY2gKI3dpbGwgZmV0Y2ggaHlkcm94aWRlIGNvbXBvdW5kcyBvZiBOYSBhbmQgSwoKCiNsZXQgdXMgbm93IHRyeSB0byBleHRyYWN0IGFsbCBoeWRyYXRlZCBjb21wb3VuZHMgKD10aGUgY29tcG91bmRzIHRoYXQgaGF2ZQojSF8yTyBncm91cCkKZ3JlcCgnLiooSF8yTyknLCBjaGVtRm9ybXVsYWUsIHZhbHVlPVQpICN3aHkgZG9lcyBpdCBmZXRjaCBIXzJPXzI/CiN0aGUgYWJvdmUgZXhwcmVzc2lvbiBmZXRjaGVzIGh5ZHJhdGVkIGNvbXBvdW5kcyBpbmNsdWRpbmcgaHlkcm9nZW4gcGVyb3hpZGUgKEhfMk9fMikKI3doaWNoIGlzIGhhdmluZyB0d28gTyBhdG9tcyBhdCB0aGUgZW5kIChPXzIpIGFuZCBub3QgZXhwZWN0ZWQgdG8gYmUgcGFydCBvZiB0aGUgc2VhcmNoOwoKI3dlIGNhbiBzb2x2ZSB0aGUgYWJvdmUgcHJvYmxlbSwgYnkgdXNpbmcgJCBzeW1ib2wgdG8gZGVub3RlIHRoZSBlbmQgb2Ygc2VhcmNoLCBhcyBpbjoKZ3JlcCgnLiooSF8yTykkJywgY2hlbUZvcm11bGFlLCB2YWx1ZT1UKQoKCiNlYXJsaWVyIHdlIGhhdmUgY3JlYXRlZCBhIHZlY3RvciBvZiB0cmlwbGV0IGNvZG9ucyBpbiB0aGUgdmFyaWFibGUgJ2NvZG9ucyc7CiNpZiB5b3Ugd2FudCB0byBzZWFyY2ggZm9yIHRob3NlIGNvZG9ucyB0aGF0IHN0YXJ0IHdpdGggdGhlIGJhc2UgQSBhbmQgZW5kIHdpdGggYmFzZSBVCiNoYXZpbmcgYW55IGxldHRlciBpbiBiZXR3ZWVuLCB0aGVuIGZvbGxvdyB0aGUgcmVndWxhciBleHByZXNzaW9uIGFzIGdpdmVuIGJlbG93OgpncmVwKCdeKEEpLihVKSQnLCBjb2RvbnMsIHZhbHVlPVQpCgojbGV0IHVzIHNheSB3ZSBoYXZlIGEgY2hhcmFjdGVyIHZlY3RvciBvZiBiaW5hcnkgbGl0ZXJhbHMsIHN1Y2ggYXM6CmJpbmFyeUNvZGUgPC0gYygnMTEwMDAwMTEwMCcsJzAwMDAwMCcsJzExMTExMTExMTEnLCAnMTAwMDExMDAnLCAnMDAxMTExMDAwMCcpCgojaWYgeW91IHdhbnQgdG8gc2VhcmNoIGZvciB0aGUgY29kZXMgdGhhdCBzaG91bGQgc3RhcnQgd2l0aCAxMSwgdGhlbiB0aGUgZXhwcmVzc2luIGlzOgpncmVwKCdeMTEuKicsIGJpbmFyeUNvZGUsIHZhbHVlPVQpICMuKiBhbGxvd3MgYW55IGRpZ2l0cyB0byBzdWNjZWVkIDExCgojc3VwcG9zZSwgaWYgeW91IHdhbnQgdG8gbWFrZSB0aGUgc2Vjb25kIGRpZ2l0IG9mIHRoZSBzdGFydGluZyB2YWx1ZSAxMSB0byBiZSBvcHRpb25hbCwKI3RoZW4gdXNlIHN1ZmZpeCA/IHRvIHRoZSBkaWdpdCB0aGF0IHlvdSB3YW50IGl0IG1ha2UgaXQgb3B0aW9uYWwsIGFzIGluOgpncmVwKCdeMTE/LionLCBiaW5hcnlDb2RlLCB2YWx1ZT1UKSAjPyBtYWtlcyB0aGUgcHJlY2VkaW5nIGNoYXJhY3RlciBvcHRpb25hbAoKI3RoZSBmb2xsb3dpbmcgZmV0Y2hlcyB0aGUgYmluYXJ5IGNvZGVzIGhhdmluZyBmb3VyIDFzIGFueXdoZXJlIHdpdGhpbiB0aGUgc3RyaW5nCmdyZXAoJzF7NH0nLCBiaW5hcnlDb2RlLCB2YWx1ZT1UKSAjdXNlIG9mIHtufSByZXBlYXRzCgojd2hlcmVhcywgaWYgeW91IHdhbnQgdG8gZXh0cmFjdCB0aGUgYmluYXJ5IGNvZGVzIGhhdmluZyBmb3VyIDExcyBhbnl3aGVyZSB3aXRoaW4sIHRoZW4KI2VuY2xvc2UgMTEgd2l0aGluIHBhcmVudGhlc2lzIHRvIGdyb3VwOgpncmVwKCcoMTEpezR9JywgYmluYXJ5Q29kZSwgdmFsdWU9VCkgI3VzZSBvZiB7bn0gcmVwZWF0cwoKI3lvdSBtYXkgYWRkIGEgcmFuZ2Ugb2YgdmFsdWVzIHdpdGhpbiBjdXJseSBicmFjZXMgYXMgd2VsbDsgZm9yIGluc3RhbmNlIHRoZSAKI2ZvbGxvd2luZyBleHByZXNzaW9uIHdpbGwgZmV0Y2ggY29kZXMgd2hlcmUgMXMgYXJlIHJlcGVhdGVkIDIgdG8gNCB0aW1lcwpncmVwKCcxezIsNH0nLCBiaW5hcnlDb2RlLCB2YWx1ZT1UKSAjdXNlIG9mIHtuLG19IHJhbmdlIHJlcGVhdHMKCgojbGV0IHVzIGNyZWF0ZSBhbm90aGVyIHZlY3RvciBvZiBhbHBoYSBudW1lcmljIHBhc3N3b3JkcyBmb3IgZGVtbzoKYWxwaGFudW1Db2RlcyA8LSBjKCdYWDAwMEFYWkVSMicsJ1gzMDAwQVhaRVJWJywnWVkwMjFBWFlPUTUnLAogICAgICAgICAgICAgICAgICAgJ1g1MDAwQVhaRVJRJywnWloxMDNBWFVJUjEnLCAnWDlYWDQ1UE9SVCcpCgojbWF0Y2hpbmcgd29yZCBzaG91bGQgc3RhcnQgd2l0aCBYIGZvbGxvd2VkIGJ5IGEgZGlnaXQ7IC4qIGZvciBhbnkgY2hhcnMgYWZ0ZXIgdGhhdApncmVwKCdeWFswLTldLionLCBhbHBoYW51bUNvZGVzLCB2YWx1ZT1UKSAKI21hdGNoaW5nIHdvcmQgc2hvdWxkIHN0YXJ0IHdpdGggYSBjYXBpdGFsIGxldHRlciBmb2xsb3dlZCBieSBhIGRpZ2l0CmdyZXAoJ15bQS1aXVswLTldLionLCBhbHBoYW51bUNvZGVzLCB2YWx1ZT1UKQoKI2J1aWxkaW5nIGEgY29tcGxleCBwYXR0ZXJuOiBzaG91bGQgc3RhcnQgd2l0aCBhdGxlYXN0IDIgY2FwaXRhbCBsZXR0ZXJzIGZvbGxvd2VkIAojYnkgMyBkaWdpdHMgYW5kIGZpdmUgbGV0dGVycyBhbmQgZmluYWxseSBzaG91bGQgZW5kIHdpdGggYSBkaWdpdApncmVwKCdeW0EtWl17Mn1bMC05XXszfVtBLVpdezV9WzAtOV0kJywgYWxwaGFudW1Db2RlcywgdmFsdWU9VCkgI2hvdyB0byBidWlsZCBhIHBhdHRlcm4/Cgojc2hvdWxkIG5vdCBzdGFydCB3aXRoIFpaIChkZW5vdGVkIGJ5IF5bXlpdezJ9KSwgYnV0IGF0IDNyZCBwb3NpdGlvbiB0aGVyZSBzaG91bGQgYmUKIzMgZGlnaXRzIGFuZCBmaXZlIGNhcGl0YWwgbGV0dGVycywgYnV0IHNob3VsZCBlbmQgd2l0aCBhIGRpZ2l0CmdyZXAoJ15bXlpdezJ9WzAtOV17M31bQS1aXXs1fVswLTldJCcsIGFscGhhbnVtQ29kZXMsIHZhbHVlPVQpICN1c2Ugb2YgJ14nIHdpdGhpbiBbXT8KCgojZ3N1YiBpcyBzaW1pbGFyIHRvIGdyZXAsIGV4Y2VwdCBmb3IgcmVwbGFjZW1lbnQgc3RyaW5nCmdzdWIocGF0dGVybj0nKFVBR3xVR0F8VUFBKScsIHJlcGxhY2VtZW50PSd8KnwnLCByYW5kb21HZW5lU2VxKQojdGhlIGFib3ZlIGV4cHJlc3Npb24gcmVwbGFjZXMgdGhlIHdvcmRzIFVBRyBvciBVR0Egb3IgVUFBIHdpdGggfCp8IHdoZW4KI2ZvdW5kIGluIHRoZSBzdHJpbmcgJ3JhbmRvbUdlbmVTZXEnCgpgYGAKCgojIyMgTWF0cmljZXMKTWF0cmljZXMgYXJlIGV4dGVuc2lvbiBvZiB2ZWN0b3JzLiBXaGlsZSB2ZWN0b3JzIGFyZSBzaW5nbGUgZGltZW5zaW9uYWwgYXJyYXlzLCBtYXRyaWNlcyBhcmUgbXVsdGlkaW1lbnNpb25hbC4gTGlrZSB2ZWN0b3JzIG1hdHJpY2VzIGFyZSBhbHNvIHN0cm9uZ2x5IHR5cGVkLiBEYXRhIHR5cGUgbWl4aW5nIGZvbGxvd3MgdGhlIHJ1bGVzIGV4cGxhaW5lZCBmb3IgdmVjdG9ycy4gKCoqc2VlIFZlY3RvcnMqKikuIE1hdHJpY2VzIGNhbiBiZSB2aWV3ZWQgYXMgYSBjb2xsZWN0aW9uIG9mIGNvbHVtbiB2ZWN0b3JzIG9yIHJvdyB2ZWN0b3JzLiBUaGV5IGhhdmUgcm93cyBhbmQgY29sdW1ucyBsaWtlIGEgdGFibGUuIE51bWJlciBvZiByb3dzIGFuZCBjb2x1bW5zIGRlZmluZSB0aGUgMkQgc3RydWN0dXJlLiBIZXJlLCB3ZSBmb2N1cyBvbiAyRCBtYXRyaWNlcy4gTGlrZSBuYW1lZCB2ZWN0b3JzLCBlYWNoIGNvbHVtbiBvciByb3cgY2FuIGJlIGdpdmVuIGEgbmFtZS4KCgojIyMjIENyZWF0aW5nIG1hdHJpY2VzCmBgYHtyIGV2YWw9RiwgZWNobz1UfQptYXRyaXgoKSAjY3JlYXRlcyBhIDFSIFggMUMgbWF0cml4IHdpdGggYSB2YWx1ZSBvZiBOQQptYXRyaXgobnJvdz01KSAjY3JlYXRlcyBhIDVSIFggMUMgbWF0cml4IHdpdGggZGVmYXVsdCB2YWx1ZXMgb2YgTkFzCm1hdHJpeChucm93PTUsIG5jb2w9NSkgI2NyZWF0ZXMgNVIgWCA1QyBtYXRyaXggKHdpdGggTkFzKQptYXRyaXgoMCwgMywgNSkgI2NyZWF0ZXMgdGhlIDNSIFggNUMgbWF0cml4IHdpdGggMCBhcyBkZWZhdWx0IHZhbHVlcwoKI2FueSB2ZWN0b3IgY2FuIGJlIGNvbnZlcnRlZCBpbnRvIDJEIG1hdHJpeCBvZiBkaWZmZXJlbnQgcGxhdXNpYmxlIGRpbWVuc2lvbnM7CiNmb3IgaW5zdGFuY2U6Cm51bVZlY3RvciA8LSAxOjM2ICNhIG51bWVyaWMgdmVjdG9yIG9mIDM2IGVsZW1lbnRzIHN0YXJ0aW5nIGZyb20gMSB0byAzNgoKI3RoZSBhYm92ZSB2ZWN0b3IgY2FuIGJlIGNvbnZlcnRlZCBpbnRvIG1hdHJpY2VzIG9mIDE4IGRpZmZlcmVudCBkaW1lbnNpb25zOwojYSBmZXcgZXhhbXBsZXMgYXJlIGdpdmVuIGJlbG93OgptYXRyaXgobnVtVmVjdG9yLCBucm93PTEpICNjcmVhdGVzIDFSIFggMzZDIG1hdHJpeDsgdmFsdWVzIGZpbGxlZCBmcm9tIG51bVZlY3RvcgptYXRyaXgobnVtVmVjdG9yLCBuY29sPTYpICNjcmVhdGVzIDZSIFggNkMgc3F1YXJlIG1hdHJpeDsgdmFsdWVzIGZpbGxlZCBjb2x1bW53aXNlCm1hdHJpeChudW1WZWN0b3IsIG5jb2w9NiwgYnlyb3c9VCkgIzZSIFggNkMgbWF0cml4OyBidXQgdmFsdWVzIGZpbGxlZCByb3d3aXNlCm1hdHJpeChudW1WZWN0b3IsIG5yb3c9NCwgbmNvbD05LCBieXJvdz1UKSAjNFIgeCA5QyBtYXRyaXg7IHZhbHVlcyBmaWxsZWQgcm93d2lzZQoKCiNsZXQgdXMgY3JlYXRlIGEgNFg1IG1hdHJpeCBvZiByYW5kb20gbnVtYmVycwptYXRSYW5kb21OdW0gPC0gbWF0cml4KHNhbXBsZSgwOjEwLCAyMCwgcmVwbGFjZT1UKSwgbnJvdz00LCBieXJvdz1UKQojbGV0IHVzIGFsc28gY3JlYXRlIDZ4NiBtYXRyaXggb2YgcmFuZG9tIGxldHRlcnMgKGxvd2VyIGNhc2UpCm1hdFJhbmRvbUNoYXIgPC0gbWF0cml4KHNhbXBsZShsZXR0ZXJzLCAzNiwgcmVwbGFjZT1UKSwgbmNvbD02KQoKYGBgCgoKIyMjIyBNYXRyaXggdHlwZSBjaGVja2luZyBhbmQgY29udmVyc2lvbnMKTGlrZSB2ZWN0b3JzIG1hdHJpeCBpcyBhbHNvIHN0cm9uZ2x5IHR5cGVkLiBIZW5jZSwgdHlwZSBjaGVja2luZyBmb2xsb3dzIHRoZSBydWxlcyBvZiB2ZWN0b3JzLiBzZWUgKipWZWN0b3IgdHlwZSBjaGVja2luZyoqIGZvciBtb3JlIGRldGFpbHMuIApgYGB7ciBldmFsPUYsIGVjaG89VH0KdHlwZW9mKG1hdFJhbmRvbUNoYXIpICNyZXR1cm5zIAppcy5sb2dpY2FsKG1hdFJhbmRvbU51bSkKCiNob3dldmVyLCB3aXRoIHR5cGUgY29udmVyc2lvbiB0aGVyZSBpcyBhIHByb2JsZW0hLiBUaGUgZ29vZCBuZXdzIGlzIHRoZSBjb252ZXJzaW9uIG9jY3VycwojY29ycmVjdGx5OyBidXQgaXQgYWxzbyByZW1vdmVzICN0aGUgZGltZW5zaW9uIGZyb20gdGhlIHNvdXJjZSBtYXRyaXggYW5kIGNvbnZlcnRzIHRoZSAKI3Jlc3VsdCBpbnRvIGEgdmVjdG9yIAphcy5sb2dpY2FsKG1hdFJhbmRvbU51bSkgI3JldHVybnMgYSBsb2dpY2FsIHZlY3RvciAoMCA9IEY7ID4wID0gVCkKI1dBUk5JTkc6IEFsc28sIHRoZSBsb2dpY2FsIHZlY3RvciByZXN1bHRpbmcgYnkgcmVhZGluZyB0aGUgbWF0cml4IGNvbHVtbndpc2UKCiNUbyBzb2x2ZSB0aGVzZSBwcm9ibGVtcywgeW91IHdvdWxkIG5lZWQgdG8gY29udmVydCB0aGUgcmVzdWx0aW5nIHZlY3RvciBpbnRvCiNtYXRyaXgsIGFzIGluOgptYXRyaXgoYXMubG9naWNhbChtYXRSYW5kb21OdW0pLCBucm93PTQpICNkbyBub3QgdXNlIGJ5cm93PVQgaW4gdGhpcyBleHByZXNzaW9uIQpgYGAKCiMjIyMgQWNjZXNzaW5nIGFuZCBlZGl0aW5nIG1hdHJpeCBlbGVtZW50cwpWZWN0b3IgZWxlbWVudHMgYXJlIGFjY2Vzc2VkIHVzaW5nIFtpXSBvcGVyYXRvciB3aXRoIGVpdGhlciB0aGUgaW5kZXggbG9jYXRpb24gKGkpIG9yIHRoZSBuYW1lIG9mIHRoZSBlbGVtZW50IChhcyBzdHJpbmcgbGl0ZXJhbCB3aXRoaW4gcXVvdGVzKSBpZiBpdCBpcyBhIG5hbWVkIHZlY3Rvci4gU2ltaWxhcmx5LCBtYXRyaXggYWxzbyB1c2VzIHRoZSBzYW1lIG9wZXJhdG9yLiBIb3dldmVyLCB5b3Ugd291bGQgbmVlZCB0byBzcGVjaWZ5IHJvdyBhbmQgY29sdW1uIGluZGV4IC0gW3IsY10sIHRvIGhhbmRsZSAyRCBtYXRyaXguIEFsdGVybmF0aXZlbHksIHlvdSBtYXkgdXNlIGNvbHVtbiBuYW1lcyBhbmQvb3Igcm93IG5hbWVzLgpgYGB7ciBldmFsPUYsIGVjaG89VH0KZGltKG1hdFJhbmRvbUNoYXIpICNyZXR1cm5zIHRoZSBkaW1lbnNpb24gdmVjdG9yIChyb3dzLCBjb2xzKQpucm93KG1hdFJhbmRvbU51bSkgI3JldHVybnMgbnVtYmVyIG9mIHJvd3MKbmNvbChtYXRSYW5kb21DaGFyKSAjcmV0dXJucyBudW1iZXIgb2YgY29scwoKY29sbmFtZXMobWF0UmFuZG9tQ2hhcikgI3JlYWRzIGNvbHVtbiBuYW1lcyB2ZWN0b3I7IGJ5IGRlZmF1bHQgdGhpcyBpcyBOVUxMCnJvdy5uYW1lcyhtYXRSYW5kb21OdW0pICNyZWFkcyByb3cgbmFtZXMgdmVjdG9yOyBieSBkZWZhdWx0IHRoaXMgaXMgTlVMTApjb2xuYW1lcyhtYXRSYW5kb21OdW0pIDwtIHNwcmludGYoJ1NlcmllcyVkJywgMTo1KSAjc2V0cyBjb2x1bW4gbmFtZXMKcm93Lm5hbWVzKG1hdFJhbmRvbU51bSkgPC0gc3ByaW50ZignT2JzJWQnLCAxOjQpICNzZXRzIHJvdyBuYW1lcwoKI2FjY2Vzc2luZyBieSBpbmRleCBsb2NhdGlvbnMKbWF0UmFuZG9tQ2hhclszLCA1XSAjdmFsdWUgb2YgZWxlbWVudCBhdCAzcmQgcm93IGFuZCA1dGggY29sdW1uCm1hdFJhbmRvbUNoYXJbMywgXSAjdmFsdWVzIG9mIGVsZW1lbnRzIGF0IDNyZCByb3cgY29tcGxldGVseSAocm93IHZlY3RvcikKbWF0UmFuZG9tQ2hhclssIDVdICN2YWx1ZXMgb2YgZWxlbWVudHMgYXQgNXRoIGNvbHVtbiBjb21wbGV0ZWx5IChjb2x1bW4gdmVjdG9yKQoKbWF0UmFuZG9tQ2hhclsxOjMsIF0gI2ZpcnN0IDMgcm93cyBvbmx5Cm1hdFJhbmRvbUNoYXJbLCBjKDIsNCldICMybmQgYW5kIDR0aCBjb2x1bW5zIG9ubHkKCiN0byBleHRyYWN0IGEgYmxvY2sgb2YgbWF0cml4IHdpdGhpbiBtYXRyaXggc3RhcnRpbmcgYXQgMm5kIHJvdy8zcmQgY29sdW1uIGFuZAojZW5kaW5nIGF0IDNyZCByb3cvNXRoIGNvbHVtbgptYXRSYW5kb21DaGFyWzI6NSwgMzo0XQoKI2EgZmV3IGV4YW1wbGVzIHRvIGFjY2VzcyBieSBjb2x1bW4gYW5kIHJvdyBuYW1lcwptYXRSYW5kb21OdW1bJ09iczInLCBdICNyb3cgaWRlbnRpZmllZCBieSByb3cgbmFtZSAnT2JzMicKbWF0UmFuZG9tTnVtW2MoJ09iczMnLCdPYnM1JyksICBdICNtdWx0aXBsZSByb3dzIGlkZW50aWZpZWQgYnkgdGhlIGdpdmVuIHJvd25hbWVzCiN0aGUgZWxlbWVudHMgaW4gcm93IChPYnMyKSwgYnV0IG9ubHkgZnJvbSB0aGUgY29sdW1ucyAtIFNlcmllczIgYW5kIFNlcmllczQKbWF0UmFuZG9tTnVtWydPYnMyJywgYygnU2VyaWVzMicsICdTZXJpZXM0JyldCgojV2hlbiB5b3Uga25vdyB0aGUgd2F5cyB0byBhY2Nlc3MgYSBzaW5nbGUgZWxlbWVudCBvciBhIHJvdyBvciBhIGNvbHVtbiBvciBhIGJsb2NrIG9mCiNlbGVtZW50cywgeW91IG1heSBhbHNvIGNoYW5nZSB0aGVtIGJ5IGFzc2lnbm1lbnQgb3BlcmF0b3IganVzdCBsaWtlIGhvdyB5b3UgbW9kaWZpZWQKI2VsZW1lbnRzIG9mIGEgdmVjdG9yIQpgYGAKCgojIyMjIE1hdHJpeCBvcGVyYXRpb25zCllvdSBjYW4gZG8gbWF0aCBhbmQgbG9naWNhbCBvcGVyYXRpb25zIG9uIG1hdHJpeCB3aXRoIHNjYWxhciwgdmVjdG9yLCBhbmQgbWF0cml4IG9wZXJhbmRzLiBUaGUgc2NhbGFyIG9wZXJhdGlvbnMgYXJlIHNpbXBsZS4gVGhlIG9wZXJhdGlvbnMgdXNpbmcgdGhlIG90aGVyIHR3byBoYXZlIGNlcnRhaW4gcnVsZXMgYW5kIGxpbWl0YXRpb25zLiBUaGVzZSBhcmUgZXhwbGFpbmVkIHdpdGggZXhhbXBsZXMgYmVsb3c6CmBgYHtyIGV2YWw9RiwgZWNobz1UfQojc2NhbGFyIG9wZXJhdGlvbnMgKGFwcGxpY2FibGUgdG8gYWxsIG1hdGggYW5kIGxvZ2ljYWwgb3BlcmF0aW9ucykKbWF0UmFuZG9tTnVtICsgMiAjYWRkcyB0d28gdG8gYWxsIGVsZW1lbnRzCihtYXRSYW5kb21OdW0gLyAyKSAqIDEuNSAjZGl2aWRlcyB0aGUgZWxlbWVudHMgYnkgMiwgdGhlbiBtdWx0aXBsaWVzIGJ5IDEuNQoKI3RoZSBmb2xsb3dpbmcgZXhwcmVzc2lvbiwgZmlyc3QgZ2V0cyByZW1pbmRlciBvZiBkaXZpc2lvbiAobW9kdWx1cykgYnkgMiBvbiBhbGwgCiNlbGVtZW50cywgdGhlbiBjb21wYXJlcyBpZiBlYWNoIGVsZW1lbnQgZXF1YWxzIHRvIDA7IHJldHVybnMgYSBsb2dpY2FsIG1hdHJpeAojYmFzZWQgb24gdGhlIG1hdGNoCihtYXRSYW5kb21OdW0gJSUgMikgPT0gMAoKbWF0UmFuZG9tQ2hhciAhPSAnYScgI2NoZWNrcyBpZiBlYWNoIGNoYXJhY3RlciBlcXVhbHMgJ2EnIG9yIG5vdDsgcmV0dW5ycyBsb2dpY2FsIG1hdHJpeAoKIyB1c2luZyB2ZWN0b3Igb3BlcmFuZHMgd2l0aCBtYXRyaWNlcwojIHRoZSBmb2xsb3dpbmcgZXhwcmVzc2lvbiBjaGVja3MgaWYgYW55IG9mIHRoZSBlbGVtZW50IGVxdWFscyBhbnkgb2YgdGhlIGxldHRlcnMgZ2l2ZW4KIyBpbiB0aGUgcmVmZXJlbmNlIHZlY3RvciAoaGVyZSBpdCBpcyB2b3dlbHMgdmVjdG9yKTsgdGhlcmUgaXMgYSBwcm9ibGVtIGhlcmUhCiMgdGhpcyBvcGVyYXRpb24gcmVtb3ZlcyB0aGUgbWF0cml4IGRpbWVuc2lvbiBhbmQgY3JlYXRlcyBhIHZlY3RvciB3aG9zZSBsZW5ndGggZXF1YWxzIHRvCiMgdGhlIHRvdGFsIG51bWJlciBvZiBlbGVtZW50cyBpbiB0aGUgbWF0cml4OwojIGFsc28gbm90ZSB0aGF0IHRoZSBtYXRjaGluZyBmb2xsb3dzIGNvbHVtbndpc2Ugb3BlcmF0aW9uICh1c2UgYnlyb3c9RiB3aGVuIHlvdSByZWNyZWF0ZQojIHRoZSBjb21wbGVtZW50YXJ5IG1hdHJpeCB1c2luZyBtYXRyaXgoKSBmdW5jdGlvbikKbWF0UmFuZG9tQ2hhciAlaW4lIGMoJ2EnLCdlJywnaScsJ28nLCd1JykKCiNpZiBudW1lcmljIG9wZXJhdGlvbnMgYXJlIHNwZWNpZmllZCB3aXRoIGEgdmVjdG9yIG9mIG1vcmUgdGhhbiBvbmUgZWxlbWVudHMsIHRoZW4gdGhlIAojdmVjdG9yIGVsZW1lbnRzIGFyZSByZWN5Y2xlZDsgZmlyc3QgaXQgd2lsbCBzdGFydCB3aXRoIDFzdCBjb2x1bW4gMXN0IHJvdywgdGhlbiBpdCBtb3ZlcyBkb3duCiN0aGUgY29sdW1uLCB0aGVuIGl0IG1vdmVzIHRvIHRoZSBuZXh0IGNvbHVtbjsgaXQgZ29lcyBvbiB1bnRpbCBpdCBmaWxscyBhbGwgcG9zaXRpb25zOwptYXRSYW5kb21OdW0gKyBjKDQ6MSkgI3RoaXMgb3BlcmF0aW9uIGNyZWF0ZXMgYSB2aXJ0dWFsIG1hdHJpeCBvZiB0aGUgc2FtZSBkaW1lbnNpb24gYW5kIHVzZXMKI3RoZSB2ZWN0b3IgZWxlbWVudHMgdG8gZmlsbCBtYXRyaXggd2l0aCB2YWx1ZXMgZm9sbG93aW5nIHRoZSBydWxlIGV4cGxhaW5lZCBhYm92ZTsgdGhlIHZpcnR1YWwKI21hdHJpeCB3aWxsIGxvb2sgbGlrZSB0aGlzOgp2bWF0IDwtIG1hdHJpeChjKDQ6MSksIG5yb3c9bnJvdyhtYXRSYW5kb21OdW0pLCBuY29sPW5jb2wobWF0UmFuZG9tTnVtKSkKI25vdywgdGhlIG1hdGggb3BlcmF0aW9uIHdpbGwgdXNlIHZtYXQgaW4gcGxhY2Ugb2YgdGhlIHZlY3RvciBhcyBnaXZlbiBiZWxvdzsKbWF0UmFuZG9tTnVtICsgdm1hdCAjZWFjaCBjb21wbGVtZW50YXJ5IGVsZW1lbnQgd2lsbCBiZSBhZGRlZDsKI3lvdSB3b250IGJlIHNlZWluZyB0aGUgYWJvdmUgc3RlcHMgd2hlbiBleGVjdXRlIG1hdFJhbmRvbU51bSArIGMoNDoxKTsgCiNidXQgaXQgZXhwbGFpbnMgdGhlIHVuZGVybHlpbmcgcHJvY2VzcyBvZiBzdWNoIG9wZXJhdGlvbnM7CiN0aGUgYWJvdmUgbWV0aG9kIGlzIGFwcGxpZWQgdG8gYW55IG1hdGggb3BlcmF0aW9uIG9uIGEgbWF0cml4IHdpdGggdmVjdG9yIG9wZXJhbmRzIG9mIGFueSBzaXplCgojbm90ZSB0aGF0LCBpbiB0aGUgYWJvdmUgZXhhbXBsZSwgdGhlIHVsdGltYXRlIG9wZXJhdGlvbiBpcyBhcHBsaWVkIG9uIHR3byBtYXRyaWNlczsgCiNhbmQgdGhlIG1hdHJpeCBhZGRpdGlvbiBjcmVhdGVzIG1hdHJpeCBvZiB0aGUgc2FtZSBzaXplIChvdGhlcndpc2Uga25vd24gYXMgY29uZm9ybWFibGUgCiNtYXRyaWNlcyBvciBhcnJheXMpOwojbWF0cml4IGFkZGl0aW9ucywgc3VidHJhY3Rpb25zLCBtdWx0aXBsaWNhdGlvbnMsIGRpdmlzaW9ucyBhbmQgb3RoZXIgbWF0aCBvcGVyYXRpb25zIG9uIGVsZW1lbnQKI2J5IGVsZW1lbnQgYmFzaXM7IHRoZSBlbGVtZW50cyBhdCB0aGUgY29tcGxlbWVudGFyeSBwb3NpdGlvbnMgYXJlIGFkZGVkLCBzdWJ0cmFjdGVkLCBhbmQgc28gb24uCgojdGhlc2Uga2luZCBvZiBtYXRoIG9wZXJhdGlvbnMgd2lsbCBmYWlsIG9uIG5vbi1jb25mb3JtYWJsZSBtYXRyaWNlczsgZm9yIGV4YW1wbGU6CnZtYXQgKiBtYXRyaXgocmVwKDE6MiwgMyksIG5yb3c9MykgI3dpbGwgZmFpbCBkdWUgdG8gbm9uLWNvbmZvcm1pdHksIHdoaWxlLi4uCnZtYXQgKiB2bWF0ICN3aWxsIHN1Y2NlZWQKCiN0aGUgYWJvdmUgbWF0cml4IG11bHRpcGxpY2F0aW9uIGlzIGEgc2ltcGxlIG9uZSB0byBvbmUgcHJvY2VzcyBhbmQgdXNlcyB0aGUgcmVndWxhcgojbXVsdGlwbGljYXRpb24gb3BlcmF0b3IgLSBhc3RlcmlzayAoKik7CiN3aGlsZSB0YWxraW5nIGFib3V0IG1hdHJpeCBvcGVyYXRpb25zLCB3ZSBuZWVkIHRvIGtub3cgdGhlIHRydWUgJ21hdHJpeCBtdWx0aXBsaWNhdGlvbicgdGhhdAojZm9sbG93cyBhIHNwZWNpYWwgYXJpdGhtZXRpYyBydWxlczsgYW5kIGluIG9yZGVyIHRvIHNwZWNpZnkgdGhpcyB0cnUgbWF0cml4IG11bHRpcGxpY2F0aW9uCiNSIHVzZXMgYSBzcGVjaWFsIG11bHRpcGxpY2F0aW9uIG9wZXJhdG9yIC0gJSolOyB0aGUgcnVsZXMgYW5kIGV4YW1wbGVzIGFyZSBnaXZlbiBiZWxvdzoKCiNSdWxlcyBvZiB0cnVlIG1hdHJpeCBtdWx0aXBsaWNhdGlvbjoKIygxKSBUaGUgcHJpbWFyeSBydWxlIChjb25mb3JtaXR5IHJ1bGUpIGlzIHRoYXQgdGhlIG51bWJlciBvZiBjb2x1bW5zIG9mIHRoZSBmaXJzdCBtYXRyaXggCiNzaG91bGQgYmUgZXF1YWwgdG8gdGhlIG51bWJlciBvZiByb3dzIG9mIHRoZSBzZWNvbmQgbWF0cml4LgoKI2ZvciBpbnN0YW5jZSwgdGhlIGZvbGxvd2luZyBpcyBhIHNlbGYtbXVsdGlwbGljYXRpb24sIHdoaWNoIHdpbGwgZmFpbCBhY2NvcmRpbmcgdG8gdGhlIAojYWJvdmUgcnVsZTsgc2FtZSBydWxlIGlzIGFwcGxpY2FibGUgZm9yIGFueSB0d28gbWF0cmljZXMgb2YgZGlmZmVyZW50IGRpbWVuc2lvbnMuCnZtYXQgJSolIHZtYXQKCiNob3dldmVyLCB0aGUgYWJvdmUgb3BlcmF0aW9uIHdpbGwgc3VjY2VlZCBpZiB2bWF0IGlzIGEgc3F1YXJlIG1hdHJpeAoKI2luIG9yZGVyIHRvIGFjaGlldmUgc2VsZi1tdWx0aXBsaWNhdGlvbiBvbiBub24tc3F1YXJlIG1hdHJpY2VzLCB5b3UgbWF5IG5lZWQgdG8gdHJhbnNwb3NlIAojdGhlIG1hdHJpeCwgYXMgaW46CnZtYXQgJSolIHQodm1heCkKCmBgYAoKIyMjIyBNYXRyaXggZnVuY3Rpb25zCgpgYGB7ciBldmFsPUYsIGVjaG89VH0KY29sU3VtcyhtYXRSYW5kb21OdW0sIG5hLnJtPVQpICNTdW0gb24gZWFjaCBjb2x1bW4KI2NvbFN1bXMgY3JlYXRlcyBhIHJvdyB2ZWN0b3IKI25hLnJtPVQgbWFrZXMgc3VyZSB0aGF0IHRoZSBtaXNzaW5nIHZhbHVlcyBhcmUgaWdub3JlZAoKcm93U3VtcyhtYXRSYW5kb21OdW0sIG5hLnJtPVQpICNTdW0gb24gZWFjaCByb3cKI3Jvd1N1bXMgY3JlYXRlcyBhIGNvbHVtbiB2ZWN0b3IKCmNvbE1lYW5zKG1hdFJhbmRvbU51bSwgbmEucm09VCkgI0F2ZXJhZ2Ugb2YgZWFjaCBjb2wKcm91bmQoY29sTWVhbnMobWF0UmFuZG9tTnVtLCBuYS5ybT1UKSwyKSAjbmVzdGluZyB0aGUgYWJvdmUgZnVuY3Rpb24gd2l0aCByb3VuZCgpCgpyb3dNZWFucyhtYXRSYW5kb21OdW0sIG5hLnJtPVQpICNBdmVyYWdlIG9mIGVhY2ggcm93CgpjYmluZChtYXRSYW5kb21OdW0scm93U3VtcyhtYXRSYW5kb21OdW0pKSAjYWRkcyBhIGNvbHVtbiB0byBhIG1hdHJpeApyYmluZChtYXRSYW5kb21OdW0sIGNvbFN1bXMobWF0UmFuZG9tTnVtKSkgI2FkZHMgYSByb3cgdG8gYSBtYXRyaXgKCnQobWF0UmFuZG9tTnVtKSAjdHJhbnBvc2Ugb2YgbWF0cml4CnNvbHZlKG1hdFJhbmRvbU51bVssMTo0XSkgI2ludmVyc2Ugb2YgYSBtYXRyaXggKGNvbXBsZXggbWF0aGVtYXRpY2FsIG9wZXJhdGlvbikKYGBgCgoKIyMjIExpc3RzCkxpc3RzIGFyZSBsaWtlIGNvbnRhaW5lcnMgb2YgZGlmZmVyZW50IGtpbmRzIG9mIG9iamVjdHMuIEVhY2ggb2JqZWN0IGNhbiBiZSBuYW1lZC4gVGhlIG9iamVjdHMgZG8gbm90IGxvb3NlIHRoZWlyIHR5cGUgb3IgY2xhc3MganVzdCBiZWluZyBhIHBhcnQgb2YgYSBsaXN0LiBJbiBSIHdvcmtzcGFjZSwgYWxsIHZhcmlhYmxlcyBhbmQgb2JqZWN0cyB0aGF0IGFyZSBvbmNlIGNyZWF0ZWQgYmVjb21lIHBhcnQgb2YgYSB1bm5hbWVkIGdsb2JhbCBsaXN0LiBUaGlzIGxpc3QgY2FuIGJlIGFjY2Vzc2VkIHVzaW5nIHRoZSBmdW5jdGlvbiBscygpLgoKIyMjIyBDcmVhdGluZyBsaXN0cwpgYGB7ciBldmFsPUYsIGVjaG89VH0KYUxpc3RPZk9iamVjdHMgPC0gbHMoKSAjZmV0Y2hlcyBhbGwgYXZhaWxhYmxlIG9iamVjdHMgaW4gdGhlIHdvcmtzcGFjZQojYUxpc3RPZk9iamVjdHMgaXMgYSBsaXN0CgojdGhlIGZvbGxvd2luZyBjcmVhdGVzIGEgbGlzdCBvZiBjb21iaW5hdGlvbiBvZiBudW1lcmljLCBjaGFyYWN0ZXIgYW5kIGxvZ2ljYWwgdmVjdG9ycy4KbHN0R0NTIDwtIGxpc3QoQ08yPWMoNDAwLDYwMCksIHRlbXA9YygyMCwzMCksIHBob3RvcGVyaW9kPWMoJ2F1dG8nLCdkZWZhdWx0JyksIAogICAgICAgICAgICAgICBodW1pZD1jKDQwLjUsIDYwLjApLCAKICAgICAgICAgICAgICAgaXNXYXRlckZsb3dSZWd1bGF0ZWQ9YyhULEYpKQoKI3lvdSBtYXkgY3JlYXRlIG9iamVjdHMgZXh0ZXJuYWxseSBhbmQgdGhlbiBjcmVhdGUgYSBsaXN0IG91dCBvZiBpdAojZmlyc3QsIGxldCB1cyBjcmVhdGUgYSBmZXcgb2JqZWN0cwpDTzI9Yyg0MDAsNjAwKQppc1dhdGVyRmxvd1JlZ3VsYXRlZD1jKFQsRikpCnBob3RvcGVyaW9kPWMoJ2F1dG8nLCdkZWZhdWx0JykKaHVtaWQ9Yyg0MC41LCA2MC4wKQoKI3RoZSBmb2xsb3dpbmcgaXMgYSBsaXN0IG9mIGFsbCBvYmplY3RzIGNyZWF0ZWQgYWJvdmUsIGluY2x1ZGluZyBhIGNoYXJhY3RlciBzdHJpbmcKbHN0U2V0dGluZ3MgIDwtIGxpc3QoJ2RlZmF1bHQgc2V0dGluZ3MnLCBDTzIsIGlzV2F0ZXJGbG93UmVndWxhdGVkLCBwaG90b3BlcmlvZCwgaHVtaWQpCgojbm90ZSB0aGF0IHRoZSBhYm92ZSBsaXN0IG9mIG9iamVjdHMgYXJlIG5vdCBuYW1lZCB5ZXQ7IGhvd2V2ZXIsIGl0IGlzIG9ubHkgb3B0aW9uYWw7CiN0aGUgbmFtZXMgY2FuIGJlIHNldCBsaWtlIHRoaXM6Cm5hbWVzKGxzdFNldHRpbmdzKSA8LSBjKCd0aXRsZScsICdwYXJhbTEnLCAncGFyYW0yJywgJ3BhcmFtMycsICdwYXJhbTQnKQoKI2EgbmV3IGxpc3QgY2FuIGJlIG1lcmdlZCB3aXRoIGFuIGV4aXN0aW5nIGxpc3QsIGFzIGluOgptaXNjU2V0dGluZ3MgPC0gbGlzdChpbnRlbnNpdHk9YygzMjAwMCwgMTIwMDAwKSkKYyhtaXNjU2V0dGluZ3MsIGxzdEdDUykgI21lcmdlcyB0aGUgdHdvIGxpc3RzIChhbnkgbnVtYmVyIG9mIGxpc3QgY2FuIGJlIG1lcmdlZCBsaWtlIHRoaXMpCgojaWYgYSB2ZWN0b3IgaXMgYWRkZWQgdG8gYSBsaXN0LCBlYWNoIHZlY3RvciBlbGVtZW50IHdpbGwgYmUgYWRkZWQgYXMgYW4gaW5kZXBlbmRhbnQKI29iamVjdCB0byB0aGUgbGlzdDsgZm9yIGluc3RhbmNlLCB0aGUgZm9sbG93aW5nIG9wZXJhdGlvbiB3aWxsIGNyZWF0ZSBhIGxpc3Qgb2YgbGVuZ3RoIDQuCmMobWlzY1NldHRpbmdzLCBjKDEsMiwzKSkgI3RoZSBsZW5ndGggb2YgbGlzdCB3aWxsIGJlIDQKCiN0aGUgcmlnaHQgd2F5IHRvIGRvIHRoYXQgaXMgYnkgdXNpbmcgbGlzdCgpIGZ1bmN0aW9uIGl0c2VsZgpsaXN0KG1pc2NTZXR0aW5ncywgYygxLDIsMykpICN0aGUgdmVjdG9yIGlzIG1lcmdlZCBhcyBhIGxpc3QgKGxlbmd0aD0yKQpgYGAKCgojIyMjIEFjY2Vzc2luZyBsaXN0IGVsZW1lbnRzCmBgYHtyIGV2YWw9RiwgZWNobz1UfQpsc3RTZXR0aW5nc1tbMl1dICAjc2Vjb25kIG9iamVjdCBpbiB0aGUgbGlzdApsc3RTZXR0aW5ncyRwYXJhbTQgI2ZldGNoIG9iamVjdCB1c2luZyBhIG5hbWUKCmxzdEdDUyRwaG90b3BlcmlvZCAjZXh0cmFjdHMgcGhvdG9wZXJpb2Qgb2YgaXRzIG9yaWdpbmFsIHR5cGUgaS5lLiBhIHZlY3Rvcgojd2hlcmVhcywgdGhlIGZvbGxvd2luZyB3aWxsIHJldHVybiBwaG90b3BlcmlvZCBhcyBhIGxpc3Qgb2JqZWN0CmxzdEdDU1sncGhvdG9wZXJpb2QnXSAjZ2V0cyBhIHZlY3RvciBhcyBhIGxpc3Qgb2JqZWN0CgojaWYgeW91IHdhbnQgdG8gZXh0cmFjdCB0aGUgZmlyc3QgZWxlbWVudCBpbiB0aGUgdmVjdG9yIHBob3RvcGVyaW9kIHRoYXQgaXMgcGFydCBvZiBhIGxpc3QsCiN0aGUgeW91IG1pZ2h0IHVzZSB0aGUgZm9sbG93aW5nIHN5bnRheCBpbnR1aXRpdmVseToKbHN0R0NTWydwaG90b3BlcmlvZCddWzFdCiNob3dldmVyLCB0aGUgcmVzdWx0IGlzIHNhbWUgYXMgdGhlIHByZXZpb3VzIGNvbW1hbmQgKGFuZCBkb2VzIG5vdCBleHRyYWN0IHRoZSBmaXJzdCAKI2VsZW1lbnQgaW4gcGhvdG9wZXJpb2QpCgojdW5saXN0cyBhIGxpc3QgdG8gc29sdmUgdGhlIGV4cGVjdGVkIHJlc3VsdCBmcm9tIHRoZSBhYm92ZSBwcm9ibGVtIGkuZS4gdG8gZ2V0IHRoZSAxc3QKI2VsZW1lbnQKdW5saXN0KGxzdEdDU1sncGhvdG9wZXJpb2QnXSlbMV0KI29yLCB5b3UgbWF5IHVzZToKbHN0R0NTJHBob3RvcGVyaW9kWzFdCgojdGhlIGxpc3Qgb2JqZWN0cyBjYW4gYmUgYWNjZXNzZWQgdXNpbmcgbnVtZXJpYyBpbmRleApsc3RHQ1NbM10gI3JldHVybnMgcGhvdG9wZXJpb2QgYXMgYSBsaXN0CmxzdEdDU1tbM11dICNyZXR1cm5zIGEgdmVjdG9yICh1bmxpc3RzIGEgbGlzdCkKbHN0R0NTW1szXV1bMl0gI3JldHVybnMgdGhlIDJuZCBlbGVtZW50IG9mIDNyZCBvYmplY3QgaWYgaXQgaXMgYSB2ZWN0b3IKYGBgCgoKIyMjIEZhY3RvcnMKRmFjdG9ycyBhcmUgdW5pcXVlIHZhbHVlcywgb3RoZXJ3aXNlIGtub3duIGFzIGxldmVscyBvciBmYWN0b3JzLCBvZiB2ZWN0b3JzLiBUaGUgbGV2ZWxzIGFyZSBzb3J0ZWQgYWxwaGFiZXRpY2FsbHkgb3IgbnVtZXJpY2FsbHkgKGRlcGVuZGluZyBvbiB0aGUgdHlwZSBvZiB2ZWN0b3IpIGluIGFzY2VuZGluZyBvcmRlci4gQW5kIHRoaXMgb3JkZXJlZCBsZXZlbHMgYXJlIG51bWJlcmVkIHN0YXJ0aW5nIGZyb20gMSB0byB0aGUgbGVuZ3RoIG9mIGxldmVscy4gVGhlIG9yZGVyIGFuZCBudW1iZXJpbmcgY2FuIGJlIGNoYW5nZWQgd2hpbGUgY3JlYXRpbmcgYSBmYWN0b3Igb2YgYSB2ZWN0b3IuCgojIyMjIENyZWF0aW5nIGZhY3RvcnMKYGBge3IgZXZhbD1GLCBlY2hvPVR9CmlzQW1vcnBob3VzIDwtIGMoJ1llcycsICdObycsICdObycsICdZZXMnLCAnTm8nKSAjanVzdCBhIGNoYXIgdmVjdG9yCmlzLmZhY3Rvcihpc0Ftb3JwaG91cykgI2NoZWNrcyBpZiBhIGZhY3RvciBpcyBhc3NvY2lhdGVkIHdpdGggYSB2ZWN0b3IKCmlzQW1vcnBob3VzIDwtIGZhY3Rvcihpc0Ftb3JwaG91cykgI2ZhY3Rvcml6ZXMgYSB2ZWN0b3IKIyBvciB1c2UKaXNBbW9ycGhvdXMgPC0gYXMuZmFjdG9yKGlzQW1vcnBob3VzKSAjIGJ1dCBsZXZlbHMgY2FuJ3QgYmUgcmVvcmRlcmVkIHdpdGggdGhpcwoKbGV2ZWxzKGlzQW1vcnBob3VzKSAjcmV0dXJucyBsZXZlbHM7IHR3byBsZXZlbHM6ICdObycgYW5kICdZZXMnIHdoZXJlICdObyc9MSwgJ1llcycgPSAyCmxhYmVscyhpc0Ftb3JwaG91cykgI3ZlY3RvciBvZiBkZWZhdWx0IG5hbWVzIGdpdmVuIHRvIGVhY2ggZWxlbWVudC4gY2hyIHZlYzogJzEnLCcyJywuLi4nNScKc3RyKGlzQW1vcnBob3VzKSAjc3RydWN0dXJlIG9mIHZlY3RvciB3aXRoIGZhY3RvcgoKZmFjdG9yKGlzQW1vcnBob3VzLCBsZXZlbHM9YygnWWVzJywnTm8nKSkgI2NoYW5nZXMgdGhlIG9yZGVyIG9mIGxldmVscwpmYWN0b3IoaXNBbW9ycGhvdXMsIGxldmVscz1jKCdZZXMnLCAnTicpKSAjaW5jb3JyZWN0IGxldmVscyBjb2VyY2VzIHZhbHVlcyB0byBOQQoKaXNQcmVzZW50IDwtIGMoMSwgMCwgMCwgMSwgMSwgMCwgMCwgMCwgMCwgMSkgI2p1c3QgYSBudW1lcmljIHZlY3RvcgojV2FybmluZyEgQmV0dGVyIG5vdCB0byB1c2UgZmFjdG9yaW5nIHdoZW4gdGhlIG51bWJlciBvZiBsZXZlbHMgaXMgdW5tYW5hZ2VhYmxlCmlzUHJlc2VudCA8LSBmYWN0b3IoaXNQcmVzZW50KSAjZmFjdG9yaXplcyB0aGUgbnVtZXJpYyB2ZWN0b3IKI2luIHRoZSBhYm92ZSBjYXNlLCAwIHdpbGwgYmUgZmFjdG9yZWQgYXMgMSwgYW5kIDEgd2lsbCBiZSBmYWN0b3JlZCBhcyAyIQoKbGFiZWxzKGlzUHJlc2VudCkgI2NociB2ZWMgb2YgbnVtIHNlcTogJzEnLCcyJywuLi4uJzEwJwpsZXZlbHMoaXNQcmVzZW50KSAjIDAgYW5kIDEKc3RyKGlzUHJlc2VudCkgI3N0cnVjdHVyZSBvZiB0aGUgdmVjdG9yIHdpdGggaXRzIGxldmVscwoKI3dlIGtub3cgdGhhdCBpc0Ftb3JwaG91cyBpcyBhIGNoYXJhY3RlciB2ZWN0b3IsIGhlbmNlIGFueSBtYXRoIG9wZXJhdGlvbiBkb2VzIAojTk9UIG1ha2UgYW55IHNlbnNlOyBidXQgdGhlcmUgYXJlIG9jY2FzaW9ucyAtIGxpa2Ugc3BlY2lmeWluZyB3ZWlnaHRzIGZvcgojY2F0ZWdvcmllcywgeW91IG1pZ2h0IG5lZWQgdG8gY29udmVydCB0aGVtIGludG8gbnVtZXJpYyBlcXVpdmFsZW50OwojZmFjdG9yaW5nIGhlbHBzIHlvdSB3aXRoIHRoZSBjb252ZXJzaW9uLCB3aGlsZSByZXRhaW5pbmcgdGhlIGNoYXJhY3RlciB2YWx1ZXM7Cgppc0Ftb3JwaG91cyoyICN3aWxsIGdpdmUgTkEgcmVzdWx0cywgYnV0IAojdGhlIGZvbGxvd2luZyB3aWxsIHVzZSB0aGUgbnVtZXJpYyBlcXVpdmFsZW50IGFzIHBlciBmYWN0b3IgZGVmaW5pdGlvbiwgYW5kIHRoZQojbWF0aCBvcGVyYXRpb24gd2lsbCBzdWNjZWVkCmFzLmludGVnZXIoaXNBbW9ycGhvdXMpKjIKCiN5b3Ugd291bGQgZXhwZWN0LAppc1ByZXNlbnQgKiAyICMgdG8gc3VjY2VlZCBiZWNhdXNlIGlzUHJlc2VudCBpcyBhIG51bWVyaWMgdmVjdG9yLCBidXQKI3RoZSBhYm92ZSB3aWxsIHJlc3VsdCBpbiBOQXMgZHVlIHRvIGZhY3RvcmluZzsKCmFzLmludGVnZXIoaXNQcmVzZW50KSAqIDIKI3RoZSBhYm92ZSBvcGVyYXRpb24gd2lsbCBiZSB0aGUgbXVsdGlwbGljYXRpb24gMiB3aXRoIHRoZSBmYWN0b3IgdmFsdWVzIAojcmF0aGVyIHRoYW4gdGhlIGFjdHVhbCBudW1lcmljIHZhbHVlcyBvZiB0aGUgdmVjdG9yCgojVGhlIGFib3ZlIGNhc2UgbWlnaHQgaGF2ZSBnaXZlbiB5b3UgYW4gaWRlYSBhYm91dCB3aHkgZmFjdG9yaW5nIG9mIG51bWVyaWMKI3ZlY3RvcnMgd2l0aCBtYW55IHVuaXF1ZSB2YWx1ZXMgKGxldmVscykgbWlnaHQgY3JlYXRlIGNvbmZ1c2lvbiEKCiNOb3RlOiAKIygxKSB5b3UgaGF2ZSB0byByZWZhY3RvciB0aGUgZmFjdG9yZWQgdmVjdG9yIGV2ZXJ5dGltZSB3aGVuIHlvdSBtb2RpZnkgdGhlIHZlY3RvcgojKDIpIHRoZSBzdWJzZXQgb2YgYSBmYWN0b3JlZCB2ZWN0b3IgcmV0YWlucyB0aGUgbGV2ZWxzCiMoMykgaWYgWCBpcyBhIGZhY3RvcmVkIHZlY3RvciwgYXMudmVjdG9yKFgpIHJlbW92ZXMgZmFjdG9ycywgYnV0IHRoaXMgcHJvY2VzcwojICAgIGFsd2F5cyBjb252ZXJ0cyBYIGludG8gYSBjaGFyYWN0ZXIgdmVjdG9yIGlycmVzcGVjdGl2ZSBvZiBpdHMgb3JpZ2luYWwgdHlwZTsKIyAgICBzaW1pbGFybHksIHlvdSBtYXkgdXNlIGFzLnh4eHgoKSBmdW5jdGlvbnMgYXBwcm9wcmlhdGVseTsgc2VlICdEYXRhIHR5cGUgY2hlY2tpbmcKIyAgICBhbmQgY29udmVyc2lvbnMnIGZvciBhcy54eHh4KCkgZnVuY3Rpb25zLgojKDQpIHRoZSBzYW1lIHJ1bGVzIGFyZSBhcHBsaWNhYmxlIGZvciBsb2dpY2FsIHZlY3RvcnMgYXMgd2VsbAoKYGBgCgoKIyMjIERhdGEgZnJhbWVzCkRhdGEgZnJhbWVzIGFyZSBhbHNvIGNvbnRhaW5lciBvZiBkaWZmZXJlbnQgdHlwZXMgb2YgdmVjdG9ycyBvZiBzYW1lIGxlbmd0aC4gVGhleSBhcmUgZXF1aXZhbGVudCBvZiAyRCBtYXRyaXggaW4gdGVybXMgb2YgZGltZW5zaW9uLCBidXQgdW5saWtlIG1hdHJpY2VzLCB0aGV5IGNhbiBhY2NvbW9kYXRlIGRpZmZlcmVudCBkYXRhIHR5cGVzLiBUaGF0IG1lYW5zIGVhY2ggcm93IG1heSBiZSBhIGNvbGxlY3Rpb24gb2YgZGlmZmVyZW50IGRhdGEgdHlwZXMsIHdoaWxlIGVhY2ggY29sdW1uIGlzIGEgY29sbGVjdGlvbiBvZiB2YWx1ZXMgb2YgdGhlIHNhbWUgZGF0YSB0eXBlIG9ubHkuIFRoZXkgYXJlIGFsc28gZXF1aXZhbGVudCBvZiBkYXRhIHRhYmxlIGp1c3QgbGlrZSBhIE1TIEV4Y2VsIHNoZWV0IGNvbnRhaW5pbmcgdGFibGUgZGF0YS4KCiMjIyMgQ3JlYXRpbmcgZGF0YWZyYW1lcwpgYGB7ciBldmFsPUYsIGVjaG89VH0KIyBDcmVhdGUgZGF0YWZyYW1lIHVzaW5nIHZlY3RvcnMKCiNsZXQgdXMgY3JlYXRlIHZlY3RvcnMgb2Ygc2FtZSBsZW5ndGgKY29sSUQgPC0gYygxOjEwKQpjb2xTYW1wIDwtIHNhbXBsZSgyMDA6MzAwLCAxMCwgcmVwbGFjZT1GKQpjb2xSYW5kRnJhYyA8LSBydW5pZigxMCkKY29sTG9naWNhbCA8LSBjKFQsIEYsIFQsIEYsIFQsIEYsIFQsIEYsIFQsIEYpCmNvbFF1YWwgPC0gYygnYWNlJywnbW9kJywgJ3NpbXAnLCAnYWNlJywgJ2Nvb2wnLCAncnVmJywgJ3NpbXAnLCAnYWNlJywnbW9kJywgJ3RvcCcpCgojdGhlIGZvbGxvd2luZyB3aWxsIGNyZWF0ZSBhIGRhdGFmcmFtZSBvZiB0aGUgYWJvdmUgdmVjdG9ycyBhcyBjb2x1bW5zCmRmVG1wIDwtIGRhdGEuZnJhbWUoY29sSUQsIGNvbFNhbXAsIGNvbFJhbmRGcmFjLCBjb2xMb2dpY2FsLCBjb2xRdWFsLAogICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RikgI2NyZXRlcyBkZgpuYW1lcyhkZlRtcCk7IGNvbG5hbWVzKGRmVG1wKSAjdmFyaWFibGUgbmFtZXMgYXMgY29sIG5hbWVzCnJvdy5uYW1lcyhkZlRtcCkgI2RlZmF1bHQgcm93IG5hbWVzCgojV2FybmluZyEgaWYgbGVuZ3RoIG9mIG9uZSBvZiB0aGUgY29sdW1ucyBkaWZmZXIsIGl0cyBsZW5ndGggd2lsbCBhdXRvbWF0aWNhbGx5IAojYmUgYWRqdXN0ZWQgdG8gdGhlIG1heCBsZW5ndGggb2YgYWxsIHZlY3RvcnM7IGhvd2V2ZXIsIGlmIG1vcmUgdGhhbiBvbmUgY29sdW1uCiNoYXMgZGlmZmVyaW5nIGxlbmd0aHMsIHRoZW4gUiB3aWxsIHRocm93IGFuIGVycm9yOwoKCiMgQ3JlYXRpbmcgZGF0YWZyYW1lcyB1c2luZyBtYXRyaWNlcwoKI2xldCB1cyBjcmVhdGUgYSBtYXRyaXggb2YgNlIgWCA1QyBvZiBudW1lcmljIHR5cGUKZ3Jvd3RoQnlEYXkgPC0gbWF0cml4KAogIGMoNS4wLDQuMCw1LjAsNS4yLDYuMCwKICAgIDUuNSw0LjAsNi4wLDUuMiw1LjUsCiAgICA2LjAsNS4wLDkuMCw1LjIsNi4wLAogICAgNi4yLDUuNSw4LjAsNS4yLDUuNSwKICAgIDYuMyw1LjYsNy4wLDUuMiw2LjAsCiAgICA2LjMsNS43LDQuMCw1LjIsNS41KSwKICAgIG5jb2w9NSwgbnJvdz02LCBieXJvdz1UKQpyb3cubmFtZXMoZ3Jvd3RoQnlEYXkpIDwtIDE6NiAjc2V0IHJvdyBuYW1lcwpjb2xuYW1lcyhncm93dGhCeURheSkgPC0gc3ByaW50ZignZXhwJWQnLCAxOjUpICNnaXZlIGNvbHVtbiBuYW1lcwoKY2xhc3MoZ3Jvd3RoQnlEYXkpOyBkaW0oZ3Jvd3RoQnlEYXkpICNjaGVja3MgdGhlIGNsYXNzIG5hbWUgYW5kIGRpbWVuc2lvbiBvZiBtYXRyaXgKZGZHcm93dGhCeURheSA8LSBhcy5kYXRhLmZyYW1lKGdyb3d0aEJ5RGF5KSAjY29udmVydHMgbWF0cml4IGludG8gZGF0YWZyYW1lCgpuYW1lcyhkZkdyb3d0aEJ5RGF5KTsgY29sbmFtZXMoZGZHcm93dGhCeURheSkgI2NvbCBuYW1lcyBzYW1lIGFzIHRoYXQgb2YgbWF0cml4CnJvdy5uYW1lcyhkZkdyb3d0aEJ5RGF5KSAjcm93IG5hbWVzIHNhbWUgYXMgdGhhdCBvZiBtYXRyaXgKCgojIENyZWF0ZSBkYXRhZnJhbWUgdXNpbmcgbGlzdHMgcHJvdmlkZWQ6CiMoMSkgdGhlcmUgYXJlIG9ubHkgdmVjdG9ycyBpbiB0aGUgbGlzdCAoc2NhbGFycyBhcmUgYWN0dWFsbHkgc2luZ2xlIHZhbHVlcyB2ZWN0b3JzKQojKDIpIHRoZSB2ZWN0b3JzIGluIHRoZSBsaXN0IHNob3VsZCBoYXZlIHNhbWUgbGVuZ3RoIG9yIHRoZWlyIGxlbmd0aHMgYXJlIGFkanVzdGVkCmFzLmRhdGEuZnJhbWUobHN0R0NTKQoKI0luIHRoZSBmb2xsb3dpbmcgbGlzdCwgdGhlcmUgYXJlIHZlY3RvcnMgdGhhdCBhcmUgb2YgbGVzc2VyIGxlbmd0aCwgYnV0IHRoZSBjb252ZXJzaW9uCiNhdXRvbWF0aWNhbGx5IGFkanVzdHMgdGhlaXIgbGVuZ3RoIHRvIHRoZSBtYXhpbXVtIGxlbmd0aCBvZiBvdGhlciB2ZWN0b3JzCmxzdEdDUzEgPC0gbGlzdChDTzI9NDAwLCB0ZW1wPTIwLCBwaG90b3BlcmlvZD1jKCdhdXRvJywnZGVmYXVsdCcpLCBodW1pZD1jKDQwLjUsIDYwLjApLCAKICAgICAgICAgICAgICAgaXNXYXRlckZsb3dSZWd1bGF0ZWQ9VCkgI2RmIG9mIDIgcm93czsgaWYgaHVtaWQgaXMgb2YgbGVuZ3RoIDMgdGhlbiBmYWlscwphcy5kYXRhLmZyYW1lKGxzdEdDUzEpICNzdWNjZWVkcztsZW5ndGhzIGFyZSBhZGp1c3RlZCB1c2luZyByZWN5Y2xpbmcKCmxzdEdDUzIgPC0gbGlzdChDTzI9TkEsIHRlbXA9MjAsIHBob3RvcGVyaW9kPWMoJ2F1dG8nLCdkZWZhdWx0JyksIGh1bWlkPWMoNDAuNSwgNjAuMCksIAogICAgICAgICAgICAgICAgaXNXYXRlckZsb3dSZWd1bGF0ZWQ9VCkKYXMuZGF0YS5mcmFtZShsc3RHQ1MyKSAjc3VjY2VlZHMgd2l0aCBOQTsgYnV0IGZvciBOVUxMIHRoaXMgd2lsbCBmYWlsIHdpdGggZXJyb3IKCiNOb3RlOiBpZiBhIGRhdGFmcmFtZXMgaXMgcHJlc2VudCBpbiB0aGUgbGlzdCwgdGhlIGxpc3QgdG8gZGF0YWZyYW1lIGNvbnZlcnNpb24gd2lsbAojc3VjY2VlZCBvbmx5IGlmIHRoZSBsZW5ndGhzIG9mIHZlY3RvcnMgcHJlc2VudCBpbiB0aGUgbGlzdCBhbmQgdGhlIHJvdyBsZW5ndGggb2YgCiNkYXRhZnJhbWUgb2JqZWN0cyBhcmUgdGhlIHNhbWUuCgpgYGAKCgojIyMjIEFjY2Vzc2luZyBkYXRhZnJhbWUgZWxlbWVudHMKYGBge3IgZXZhbD1GLCBlY2hvPVR9CmRmVG1wWzE6NSxdICNmaXJzdCA1IHJvd3MgYXMgZgpkZlRtcFs1OjEwLCBjKCdjb2xJRCcsICdjb2xRdWFsJyldICNsYXN0IHNpeCByb3dzIGFuZCBvbmx5IHR3byBjb2xzIGFzIGRmCgpkZlRtcFsgLCJjb2xMb2dpY2FsIl0gI2p1c3Qgb25lIGNvbCBhcyB2ZWN0b3IKZGZUbXAkY29sU2FtcCAjanVzdCBvbmUgY29sIGFzIHZlY3RvcgoKYGBgCgojIyMjIEZ1bmN0aW9ucyBvZiBkYXRhZnJhbWVzCmBgYHtyIGV2YWw9RiwgZWNobz1UfQpkaW0oZGZUbXApOyBucm93KGRmVG1wKTsgbmNvbChkZlRtcCkgI2dldHMgZGltZW5zaW9ucwoKY29sU3VtcyhkZlRtcFssMTozXSkgI29uIG51bWVyaWMgY29sdW1ucyBvbmx5CgpkZlRtcCA8LSBlZGl0KGRmVG1wKSAjb3BlbnMgdGhlIGRhdGFmcmFtZSB3aXRoIGFuIGVkaXRvcgoKaGVhZChkZlRtcCk7IHRhaWwoZGZUbXApICNnZXRzIGZpcnN0IGFuZCBsYXN0IGZldyByb3dzIG9mIGRhdGFmcmFtZQojaGVhZCBhbmQgdGFpbCBhbHNvIHdvcmtzIGZvciBtYXRyaWNlcyBhbmQgdmVjdG9ycwoKI05vdGU6IFRyZWF0IGVhY2ggY29sdW1uIGFzIGEgdmVjdG9yOiB3aGljaCBtZWFucyB0aGF0IGFsbCB2ZWN0b3IgZnVuY3Rpb25zIGNhbiBiZSBhcHBsaWVkCgojd2hpbGUsIGNiaW5kIGFuZCByYmluZCBmdW5jdGlvbnMgY2FuIG1lcmdlIHR3byBkYXRhIGZyYW1lcyB0b2dldGhlciAKI2hvcml6b250YWxseSBvciB2ZXJ0aWNhbGx5OyAKI2hvd2V2ZXIsIGl0IGhhcyBsaW1pdGF0aW9ucyBvciBjb25zdHJhaW50czsKI2ZvciBleGFtcGxlLCB0byBjYmluZCB0d28gZGF0YWZyYW1lcywgdGhleSBzaG91bGQgaGF2ZSBlcXVhbCBudW1iZXIgb2YKI3Jvd3M7IAojc2ltaWxhcmx5OiB0byByYmluZCB0aGV5IHNob3VsZCBoYXZlIGVxdWFsIG51bWJlciBjb2x1bW5zOyBpbiBhZGRpdGlvbiB0bwojdGhpcyByYmluZCByZXF1aXJlcyB0aGUgZGF0YSB0eXBlIG9mIGNvbHVtbnMgYmVpbmcgbWVyZ2VkIHNob3VsZCBtYXRjaDsKCiNpZiB0d28gZGF0YWZyYW1lcyBhcmUgYXNzb2NpYXRlZCBieSBhIGNvbW1vbiBjb2x1bW4gKGtub3duIGFzIGtleSBjb2x1bW4pLAojdGhlbiB0aGV5IGNhbiBiZSBtZXJnZWQgYnkgdGhlaXIga2V5OyB0aGUga2V5IGNhbiBiZSBhIGNvbWJpbmF0aW9uIG9mIG1vcmUKI3RoYW4gb25lIGNvbHVtbnM7CgojbGV0IHVzIGZpcnN0IGNvbnN0cnVjdCB0d28gZGF0YWZyYW1lcyB0aGF0IHNoYXJlIGEga2V5IGNvbHVtbjoKZGZYIDwtIGRhdGEuZnJhbWUoSUQ9YygxOjMpLCBjb2w9YygncmVkJywnYmx1ZScsJ2dyZWVuJykpCmRmWSA8LSBkYXRhLmZyYW1lKElEPWMoMTozKSwgd2hhdD1jKCdhcHBsZScsJ2JlcnJpZXMnLCdsZWF2ZXMnKSkKCiN0byBtZXJnZSB0aGUgYWJvdmUgdHdvIGRhdGFmcmFtZXMgYnkgdGhlIGNvbHVtbiAnSUQnOgptZXJnZSh4PWRmWCwgeT1kZlksIGJ5PSdJRCcpCgojaWYga2V5IGNvbHVtbiBuYW1lcyBhcmUgZGlmZmVyZW50IGFzIGluOgpkZlggPC0gZGF0YS5mcmFtZShJRD1jKDE6MyksIGNvbD1jKCdyZWQnLCdibHVlJywnZ3JlZW4nKSkKZGZZIDwtIGRhdGEuZnJhbWUoa2V5PWMoMTozKSwgd2hhdD1jKCdhcHBsZScsJ2JlcnJpZXMnLCdsZWF2ZXMnKSkKI3RoZW4sCm1lcmdlKHg9ZGZYLCB5PWRmWSwgYnkueD0nSUQnLCBieS55PSdrZXknKQoKI2lmIG9uZSBvZiB0aGUgdGFibGUgaGFzIG1pc3Npbmcgb2JzZXJ2YXRpb25zLCBhcyBpbjoKZGZYIDwtIGRhdGEuZnJhbWUoSUQ9YygxOjMpLCBjb2w9YygncmVkJywnYmx1ZScsJ2dyZWVuJykpCiN0aGUgb2JzZXJ2YXRpb24gd2l0aCBJRCB2YWx1ZSAyIGlzIG1pc3NpbmcKZGZZIDwtIGRhdGEuZnJhbWUoSUQ9YygxLDMpLCB3aGF0PWMoJ2FwcGxlJywnbGVhdmVzJykpCiN0aGVuLCBvbmx5IHRoZSBtYXRjaGluZyBlbnRyaWVzIHdpbGwgYmUgbWVyZ2VkLCBhcyBpbjoKbWVyZ2UoeD1kZlgsIHk9ZGZZLCBieT0nSUQnKQoKI2hvd2V2ZXIsIHlvdSBtYXkgc3BlY2lmeSwgZm9yIHdoaWNoIG9mIHRoZSBkYXRhZnJhbWVzIHlvdSB3YW50CiN0byBoYXZlIGFsbCBlbnRyaWVzOyAod2hlcmUgdGhlIG1pc3NpbmcgdmFsdWVzIG9mIHRoZSBvdGhlciwgCiNpZiBhbnksIHdpbGwgYmUgcmVwbGFjZWQgd2l0aCBOQSB2YWx1ZXMpLCBhcyBpbjoKbWVyZ2UoeD1kZlgsIHk9ZGZZLCBieT0nSUQnLCBhbGwueD1ULCBhbGwueT1GKQoKCiN5b3UgY2FuIHNvcnQgdGhlIGRhdGFmcmFtZSBieSBhIG9uZSBvciBtb3JlIGNvbHVtbiBuYW1lcywgYXMgaW46CmRmWFtvcmRlcihkZlgkSUQsIGRlY3JlYXNpbmc9VCksIF0gI3NvcnRzIGJ5IElEIGluIGRlc2MuIG9yZGVyCgojeW91IGNhbiBhcHBseSBhbiBhZ2dyZWdhdGUgZnVuY3Rpb24gb24gZGF0YWZyYW1lcywgYXMgaW46CmRmQSA8LSBkYXRhLmZyYW1lKHZhbHMxPTE6MjEsIHZhbHMyPXJ1bmlmKDIxKSwgZ3JwPWN1dCgxOjIxLCBicmVha3M9MywgbGFiZWxzPUYpKQphZ2dyZWdhdGUoZGZBWyxjKCd2YWxzMScsJ3ZhbHMyJyldLCBieT1saXN0KGRmQSRncnApLCBGVU49bWVhbikKCiNOb3RlMTogeW91IGluY2x1ZGUgbW9yZSB0aGFuIG9uZSBjb2x1bW4gaW4gdGhlIGxpc3Qgb2YgJ2J5JyBwYXJhbWV0ZXIKI3RvIHNwZWNpZnkgYSBjb21iaW5hdG9yaWFsIGdyb3VwaW5nIGNvbHVtbjsKI05vdGUyOiB5b3UgbWF5IGFsc28gc3BlY2lmeSB1c2VyIGRlZmluZWQgZnVuY3Rpb24gb3IgYW55IG9mIHRoZSBhZ2dyZWdhdGUKI2Z1bmN0aW9ucyBpbnN0ZWFkIG9mICdGVU49bWVhbicuCgpgYGAKCgojIyMgQ3JlYXRpbmcgZW1wdHkgb2JqZWN0cyBieSBvYmplY3QgbmFtZSBmdW5jdGlvbnMKYGBge3IgZXZhbD1GLCBlY2hvPVR9CmEgPC0gYygpICNOVUxMCgp2ZWMgPC0gdmVjdG9yKCkgI2xvZ2ljYWwgZW1wdHkKdmVjYSA8LSB2ZWN0b3IobW9kZT0naW50ZWdlcicsIGxlbmd0aD0xMCkgIzEwIHplcm9zOyBtb2RlPT5jbGFzcwoKbHN0IDwtIGxpc3QoKSAjbGlzdCBvZiAwIG9iamVjdHMKZnMgPC0gZmFjdG9yKCkgI2ZhY3RvciB3aXRoIDAgbGV2ZWxzCgpkZiA8LSBkYXRhLmZyYW1lKCkgI2VtcHR5IGRmOiAwciB4IDBjCnR5cGVvZihkZikgI2xpc3Q7IGNsYXNzKGRmKSAjZGF0YS5mcmFtZQpgYGAKCiMjIEZsb3cgQ29udHJvbApJbiBwcm9ncmFtbWluZywgaXQgbWlnaHQgYmUgcmVxdWlyZWQgdG8gY29uZGl0aW9uYWxseSBjb250cm9sIHRoZSBvcGVyYXRpb25zLCB0byBjYWxsIGZ1bmN0aW9ucywgYW5kIHRvIHVzZSBleHByZXNzaW9ucy4gVGhlIGNvbmRpdGlvbnMgd2lsbCBtYWtlIHRoZSBsaW5lYXIgZmxvdyBvZiB0aGUgcHJvZ3JhbSB0byBicmFuY2ggb3V0IG9uZSBvciBtb3JlIHRpbWVzLiBIZW5jZSwgdGhlIHNpbmdsZSBzdGFydGluZyBwb2ludCBvZiB0aGUgcHJvZ3JhbSBtaWdodCB0YWtlIGRpZmZlcmVudCBwYXRocyBiZWZvcmUgaXQgcmVhY2hlcyBvbmUgb2YgdGhlIGVuZCBwb2ludHMuIFRoZSBjb25kaXRpb25zIGFyZSBsaWtlIHRoZSBub2RlcyBvZiBicmFuY2hlcyBpbiB0aGUgZmxvdyBvZiB0aGUgcHJvZ3JhbS4gSW4gUiBwcm9ncmFtbWluZywgaWYoKSwgaWZlbHNlKCksIGlmKCkuLmVsc2UgaWYoKS4uZWxzZSBhcmUgdGhlIGNvbmRpdGlvbmFsIHN0cnVjdHVyZXMgYXZhaWxhYmxlLiAKCmBgYHtyIGV2YWw9RiwgZWNobz1UfQojVGhlIGJhc2ljIGNvbnRyb2wgc3RydWN0dXJlcwoKI0xldCB1cyBjcmVhdGUgdGhlIHZhcmlhYmxlcyBhIGFuZCBiCmEgPC0gMTA7IGIgPC0gTkEKCiNUbyB2ZXJpZnkgaWYgdGhlIGNvbnRyb2wgc3RhdGVtZW50cyBhZmZlY3QgdGhlIG9wZXJ0aW9uIG9uIHRoZXNlCiN2YXJpYWJsZXMsIGxldCB1cyBwcmludCB0aGVpciB2YWx1ZXMKY2F0KHNwcmludGYoJ2E9JTAuMmYsIGI9JTAuMmZcbicsIGEsIGIpKQoKaWYoVFJVRSkgYSA8LSAyMCAjaXQgaXMgYXMgaWYgeW91IGFyZSBjaGFuZ2luZyBhIDwtIDIwIGRpcmVjdGx5CiN3aGF0IHdpbGwgaGFwcGVuIHdpdGggdGhlIGZvbGxvd2luZyBjaGVjaz8KaWYoRkFMU0UpIGIgPC0gNjAKCmNhdChzcHJpbnRmKCdhPSUwLjJmLCBiPSUwLjJmXG4nLCBhLCBiKSkKCiNsZXQgdXMgaW50cm9kdWNlLCBkaWNob3RvbW91cyBjb250cm9sCmlmKGEgPD0gMTApIGEgPC0gYSAqIDIgZWxzZSBhIDwtIGEgLyAyICNvbmUgbGluZSBpZi4uZWxzZQojbm90ZSB0aGF0IHRoZSBvcGVyYXRpb25zIGluc2lkZSBpZi4uZWxzZSBjb250cm9sIGFyZSBhc3NpZ25tZW50cwoKY2F0KHNwcmludGYoJ2E9JTAuMmYsIGI9JTAuMmZcbicsIGEsIGIpKQoKI3dlIGNhbiBhbHNvIG1ha2UgaWYuLmVsc2UgdG8gcmV0dXJuIHZhbHVlcyBjb25kaXRpb25hbGx5CmIgPC0gYSA8LSBpZihhIDw9IDEwKSBhICogMiBlbHNlIGEgLyAyICNpZi4uZWxzZSByZXR1cm5zCgpjYXQoc3ByaW50ZignYT0lMC4yZiwgYj0lMC4yZlxuJywgYSwgYikpCgojdGhlIG1vcmUgY29udmVuaWVudCByZWFkYWJsZSB2YXJpYW50IG9mIGlmLi5lbHNlIGZvcm0gaXMuLi4KZCA8LSBpZmVsc2UoYSA8PSAxMCwgYSoyLCBhLzIpCmBgYAoKV2l0aGluIGlmIG9yIGVsc2UgY29uZGl0aW9ucywgd2UgbWlnaHQgbmVlZCB0byB1c2UgbW9yZSB0aGFuIG9uZSBsaW5lIG9mIGNvZGVzLiBSIHN1cHBvcnRzIHRoYXQgd2l0aCBpZigpe30uLiBlbHNle30gY29kZSBibG9jayBzdHJ1Y3R1cmUKYGBge3IgZXZhbD1GLCBlY2hvPVR9Cm1lc3NhZ2UgPC0gJycKI3RoZSBmb2xsb3dpbmcgaXMgYSBzaW1wbGUgb25lLWxpbmUgY29kZSBibG9jawppZihhID09IGIpIHttZXNzYWdlIDwtICdhIGVxdWFscyBiJ30gZWxzZSB7bWVzc2FnZSA8LSAnYSBhbmQgYiBhcmUgZGlmZmVyZW50J30KcHJpbnQobWVzc2FnZSkKI29yLAppZihhID09IGIpIHtwcmludCgnYSBlcXVhbHMgYicpfSBlbHNlIHtwcmludCgnYSBhbmQgYiBhcmUgZGlmZmVyZW50Jyl9CgojZm9yIGEgbW9yZSByZWFkYWJsZSBpZi4uZWxzZSBibG9jaywgdXNlIHRoZSBmb2xsb3dpbmcgc3ludGF4IGFuZCBpbmRlbnRhdGlvbnMKYyA8LSAwCmlmKG1lc3NhZ2UgPT0gJ2EgZXF1YWxzIGInKXsKICBjIDwtIHNxcnQoYSkKICBwcmludChzcHJpbnRmKCdUaGUgdmFsdWUgb2YgYyBpczogJTAuMmYnLCBjKSkKfSBlbHNlIHsKICBwcmludCgnVGhlIHZhbHVlIG9mIGMgaXMgbm90IGNoYW5nZWQnKQp9CiNub3RlIHRoYXQgd2l0aGluIHt9IG11bHRpcGxlIGxpbmVzIG9mIGNvZGVzIGNhbiBiZSBpbmNsdWRlZApgYGAKCkZvciBjb21wbGV4IGZsb3cgY29udHJvbCwgeW91IG1heSBlbmNsb3NlIG9uZSBpZi4uZWxzZSBibG9jayB3aXRoaW4gYW5vdGhlci4gVGhpcyBpcyBjYWxsZWQgbmVzdGluZyBvZiBjb250cm9scy4gTXVsdGlwbGUgIm5lc3RlZCBpZidzIiBhcmUgYWxsb3dlZCBpbiBSLgpgYGB7cn0KcmFuZG9tTGV0dGVycyA8LSBzYW1wbGUobGV0dGVycywgMjAsIHJlcGxhY2U9VCkKdm93ZWxzIDwtIGMoJ2EnLCAnZScsICdpJywgJ28nLCAndScpCnNlbGVjdGVkTnVtYmVycyA8LSBjKDE2LCA0OSwgMjUsIDgxLCAyNykKCmlmIChzdW0ocmFuZG9tTGV0dGVycyAlaW4lIHZvd2VscykgPiAwKSB7CiAgIHByaW50KCdBdCBsZWFzdCBvbmUgYWxwaGFiZXQgaXMgYSB2b3dlbCcpCiAgIGlmKGFueShzZWxlY3RlZE51bWJlcnMgJSUgNiA9PSAwKSkgewogICAgICBwcmludCgnQXQgbGVhc3Qgb25lIG51bWJlciBpcyBkaXZpc2libGUgYnkgNicpCiAgIH0gZWxzZSB7CiAgICAgIHByaW50KCdOb25lIG9mIHRoZSBudW1iZXJzIGlzIGRpdmlzaWJsZSBieSA2JykKICAgfQp9IGVsc2UgewogICBwcmludCgnTm8gdm93ZWxzIHByZXNlbnQgaW4gdGhlIGFscGhhYmV0cyBzZWxlY3RlZCAnKQp9CmBgYAoKVGhlIGlmLi5lbHNlIGJsb2NrIGlzIG5vdCBzaW1wbHkgZGljaG90b21vdXMuIEl0IGNhbiBoYXZlIG11bHRpcGxlIGxldmVscyBvZiBjaGVja3MgaW4gYmV0d2Vlbi4KYGBge3IgZXZhbD1GLCBlY2hvPVR9CiN3aGF0IHdpbGwgYmUgdGhlIG91dHB1dCB3aXRoIHRoZSBmb2xsb3dpbmcgY29udHJvbCBzdHJ1Y3R1cmU/CmhhYml0YXQgPC0gJ2V4b3NwaGVyZScKaWYgKGhhYml0YXQgPT0gJ3dhdGVyJyl7CiAgcHJpbnQoJ0lzIGl0IGZyZXNoIG9yIHNhbHQ/JykKfSBlbHNlIGlmIChoYWJpdGF0ID09ICdsYW5kJykgewogIHByaW50KCdJcyBpdCBlbGV2YXRlZCBvciBwbGFpbj8nKQp9IGVsc2UgaWYgKGhhYml0YXQgPT0gJ2FpcicpIHsKICBwcmludCgnRG9lcyBpdCBmbG9hdCBvciBmbHk/JykKfSBlbHNlIHsKICBwcmludCgnSXMgaXQgYWxpZW4/JykKfQpgYGAKCiMjIyBMb29waW5nIHN0cnVjdHVyZXMKU29tZXRpbWVzLCB5b3UgbWlnaHQgbmVlZCB0byByZXBlYXQgYSBwYXJ0aWN1bGFyIG9wZXJ0aW9uIGZvciBhIGZpbml0ZSBvciBpbmZpbml0ZSBudW1iZXIgb2YgdGltZXMuIFN1Y2ggcmVwZWF0aXRpb25zIGFyZSBjYWxsZWQgbG9vcHMuIFIgaGFzIHR3byBsb29waW5nIHN0cnVjdHVlcnMgbmFtZWx5ICJmb3IiIGxvb3AgYW5kICAid2hpbGUiIGxvb3AuIFRoZSBmb3JtZXIgaXMgYSBmaW5pdGUgbG9vcCBieSBpdHMgZGVmaW5pdGlvbi4gV2hlcmVhcywgb25seSB0aGUgd2hpbGUgbG9vcCBjYW4gYmUgd3JpdHRlbiBhcyBpbmZpbml0ZSBsb29wLiBIb3dldmVyIHdoaWxlIGxvb3AgY2FuIGJlIG1vZGlmaWVkIHRvIGJlY29tZSBmaW5pdGUuIFdoZW4gdGhlIGxvb3AgaXMgZmluaXRlLCB5b3UgbWF5IHdhbnQgdG8gaGF2ZSBjb250cm9sIGZvciBhbiBlYXJseSBjb25kaXRpb25hbCBleGl0LiBTaW1pbGFybHksIHlvdSBtYXkgd2FudCB0byBoYXZlIGEgY29uZGl0aW9uYWwgZXhpdCBpbiBpbmZpbml0ZSBsb29wcy4gVGhlICJicmVhayIgY29tbWFuZCBzdXBwb3J0cyBzdWNoIGV4aXQgaW4gUi4gVGhleSBjYW4gYmUgbWFkZSBjb25kaXRpb25hbCBieSB3cmFwcGluZyB0aGVtIGluIGlmLi5lbHNlIGNvbnRyb2xzLgoKYGBge3IgZXZhbD1GLCBlY2hvPVR9CiNhIHNpbXBsZSBmb3IgbG9vcApmb3IoaSBpbiAxOjEwKSBwcmludCgnaGVsbG8gd29ybGQhJykgI3ByaW50cyBoZWxsbyB3b3JsZCAxMCB0aW1lcwoKI3lvdSBjYW4gbWFrZSB1c2Ugb2YgdGhlIGl0ZXJhdG9yIHZhcmlhYmxlIChpKSBpbiB0aGUgZm9yIGV4cHJlc3Npb24KZm9yKGkgaW4gMToxMCkgcHJpbnQoaSoyKQoKI3RoZSBzZXF1ZW5jZSBpbiBmb3IgbG9vcCBjYW4gYmUgYW55IHZlY3RvciwgYXMgaW46CmZvcih0aGlzbmFtZSBpbiBjKCdBY29uaXRlJywnQXN0ZXInLCdBdWJyaWV0YScpKSBwcmludCh0aGlzbmFtZSkKCiN0aGUgdmVjdG9yIGNhbiBiZSBwYXNzZWQgYXMgYSB2YXJpYWJsZQpkaXNlYXNlcyA8LSBjKCdNYWxhcmlhJywnVHlwaG9pZCcsJ0hJVicpCmZvcihkaXNlYXNlIGluIGRpc2Vhc2VzKXsKICAgY2F0KCdUaGUgY2F1c2FsIGFnZW50IGlzIGEgJykKICAgaWYoZGlzZWFzZT09J01hbGFyaWEnKXsKICAgICAgY2F0KHNwcmludGYoJ1Byb3Rvem9hblxuJykpCiAgIH0gZWxzZSBpZihkaXNlYXNlPT0nVHlwaG9pZCcpewogICAgICBjYXQoc3ByaW50ZignR3JhbSBuZWdhdGl2ZSBiYWN0ZXJpdW1cbicpKQogICB9IGVsc2UgewogICAgICBjYXQoc3ByaW50ZignVmlydXNcbicpKQogICB9Cn0KI2Fsc28sIG5vdGUgdGhhdCB3ZSBlbmNsb3NlZCBhIGJsb2NrIG9mIGNvZGUgdG8gYmUgZXhlY3V0ZWQgaW4gdGhlIGZvciBsb29wCiN3aXRoaW4ge30KYGBgCgpUaGUgZm9yIGxvb3AgY2FuIGJlIHVzZWQgb24gaXRlcmFibGUgY29udGFpbmVyIG9iamVjdHMgKG1hdHJpY2VzLCBsaXN0cyBhbmQgZGF0YWZyYW1lcykgd2hlcmVldmVyIGl0IG1ha2VzIHNlbnNlLCBhcyBpbjoKYGBge3IgZXZhbD1GLCBlY2hvPVR9CiNsZXQgdXMgbG9vcCB0aHJvdWdoIHRoZSByb3dzIG9mIHRoZSBtYXRyaXggJ2dyb3d0aEJ5RGF5Jwpmb3IgKHIgaW4gMTpucm93KGdyb3d0aEJ5RGF5KSl7CiAgIHByaW50KG1lYW4oZ3Jvd3RoQnlEYXlbcixdKSkgI3ByaW50cyBtZWFuIHZhbHVlIG9mIGVhY2ggcm93IHZlY3Rvcgp9CiNTaW1pbGFybHksIHlvdSBjYW4gbG9vcCB0aHJvdWdoIGNvbHVtbiB2ZWN0b3JzCmBgYAoKVGhlIGZvciBsb29wIGNhbiBiZSBuZXN0ZWQsIGFzIGluOgpgYGB7ciBldmFsPUYsIGVjaG89VH0KI2xldCB1cyBsb29wIHRocm91Z2ggZWFjaCBjZWxsIG9mIHRoZSBtYXRyaXgsIHVzaW5nIG5lc3RlZCBsb29wCmZvciAoYyBpbiAxOm5jb2woZ3Jvd3RoQnlEYXkpKXsKICBwcmludChuYW1lcyhkZlRtcClbY10pCiAgZm9yIChyIGluIDE6bnJvdyhncm93dGhCeURheSkpewogICAgaWYgKHIgPCBucm93KGdyb3d0aEJ5RGF5KSl7CiAgICAgIGNhdChzcHJpbnRmKCclMC4yZlx0JywgZ3Jvd3RoQnlEYXlbcixjXSkpCiAgICB9IGVsc2UgewogICAgICBjYXQoc3ByaW50ZignJTAuMmZcbicsIGdyb3d0aEJ5RGF5W3IsY10pKQogICAgfQogIH0KfQpgYGAKCiJmb3IgbG9vcCIgd29ya3Mgb24gbGlzdCBvYmplY3QgYXMgd2VsbCwgYXMgaW46CmBgYHtyIGV2YWw9RiwgZWNobz1UfQppIDwtIDAKZm9yIChpdGVtIGluIGxzdEdDUykgewogIGkgPC0gaSArIDEKICAjY2F0KHNwcmludGYoJ0xpc3QlZDpcdCcsIGkpKQogICNvciB0byBzdGFydCB3aXRoIHRoZSBuYW1lIG9mIHRoZSBsaXN0IGl0ZW0KICBjYXQoc3ByaW50ZignJXM6XHQnLCBuYW1lcyhsc3RHQ1MpW2ldKSkKICBpZiAobGVuZ3RoKGl0ZW0pID4gMSl7CiAgICBmb3IgKGl0ZW12YWwgaW4gaXRlbSkgY2F0KHNwcmludGYoJyVzXHQnLCBpdGVtdmFsKSkKICAgIGNhdCgnXG4nKQogIH0gZWxzZSB7CiAgICBwcmludChpdGVtKQogIH0KfQpgYGAKClRoZSBlYXJseSBleGl0IGZyb20gImZvciBsb29wIiBjYW4gYmUgYWNoaWV2ZWQgdXNpbmcgY29uZGl0aW9uYWwgYnJlYWssIGFzIGluOgpgYGB7ciBldmFsPUYsIGVjaG89VH0KY250IDwtIDAKZm9yIChpIGluIDE6MTAwMCl7CiAgIFN5cy5zbGVlcCgwLjAxKQogICBjYXQoc3ByaW50ZignXHIlZCcsIGkpKSAjdG8gcGF1c2UgZm9yIDAuMDFzCiAgIHNhbXAgPC0gc2FtcGxlKDE6MjAsIDEwMCwgcmVwbGFjZT1UKSAjc2FtcGxlIG9mIDEwMCB2YWx1ZXMgYnR3biAxIGFuZCAyMAogICAjaWYgbWVhbiBvZiB0aGlzIHJhbmRvbSBzYW1wbGUgZXF1YWxzIDEwIHByaW50IG1lc3NhZ2UgYW5kIGV4aXQKICAgaWYgKHJvdW5kKG1lYW4oc2FtcCksMikgPT0gMTApIHsKICAgICAgY2F0KHNwcmludGYoJ1xuSXQgdG9vayAlZCB0cmlhbHMgdG8gYXJyaXZlIGF0IG1lYW4gb2YgMTAuXG4nLCBpKSkKICAgICAgY250IDwtIGkKICAgICAgYnJlYWsKICAgfQogICBjbnQgPC0gY250ICsgMQp9CmBgYAoKVG8gYWNoaWV2ZSBpbmZpbml0ZSBsb29wICd3aGlsZSBsb29wJyBjYW4gYmUgdXNlZC4KKioqTm90ZTE6IHByZXNzIEN0cmwrQyBvciBDdHJsLVogdG8gZXhpdCBmb3JjZWZ1bGx5IGZyb20gaW5maW5pdGUgbG9vcCoqKgoqKipOb3RlMjogaWYgeW91IGFyZSBpbiBSIFN0dWRpbywgY2xpY2sgb24gU3RvcCBzaWduIChyZWQgZmlsbGVkIGhleGFnb24pIHRvIHRoZSB0b3AgcmlnaHQgY29ybmVyIG9mIHRoZSB0aXRsZSBiYXIgb2YgQ29uc29sZSBwYW5lKioqCmBgYHtyIGV2YWw9RiwgZWNobz1UfQppIDwtIDAKd2hpbGUoVFJVRSkgewogIFN5cy5zbGVlcCgwLjAxKTsgY2F0KHNwcmludGYoJ1xyJWQnLCBpKSkKICAgaSA8LSBpICsgMQogICAjaWYoaSA9PSAyMDApIGJyZWFrCn0KI05vdGU6IFVuY29tbWVudCB0aGUgIiNpZihpID09IDIwMCkgYnJlYWsiIGluIHRoZSBhYm92ZSB0byBleGl0IGNvbmRpdGlvbmFsbHkKCiNUaGUgd2hpbGUgbG9vcCBjYW4gYWxzbyBiZSBtYWRlIGEgZmluaXRlIGlmIGNvbmRpdGlvbiBpcyBnaXZlbiB0byB3aGlsZSgpLAojYXMgaW46CmogPC0gMTAwCndoaWxlKGogPD0gMTAwKXsKICAgcHJpbnQoaikKICAgI3RoZSBmb2xsb3dpbmcgZWFybHkgZXhpdCBjYW4gYWxzbyBiZSB1c2VkCiAgICNpZihqKjU9PTI1KSBicmVhawp9CmBgYAoKVGhlcmUgYXJlIHNvbWUgc3BlY2lhbCBmdW5jdGlvbnMgaW4gUiwgc3VjaCBhcyBhcHBseSwgc2FwcGx5LCBhbmQgbGFwcGx5LCB0byBhcHBseSBhbnkgZnVuY3Rpb24gb24gZWFjaCBlbGVtZW50IG9mIGEgbGlzdCBvciB2ZWN0b3IgaXRlcmF0aXZlbHkuCmBgYHtyIGV2YWw9RiwgZWNobz1UfQojdGhlIGZvbGxvd2luZyBzYXBwbHkoKSBhcHBsaWVzIGV4cCgpIGZ1bmN0aW9uIG9uIGVhY2ggZWxlbWVudCBvZiB0aGUKI3NlcXVlbmNlIDEsMiwzLC4uLDEwLCBhbmQgcmV0dXJucyBhIHZlY3RvciBvZiBleHBvbmVudHMuCnNhcHBseSgxOjEwLCBGVU49ZnVuY3Rpb24oeCkgZXhwKHgpKQoKI2lmICdzYXBwbHknIGlzIHJlcGxhY2VkIHdpdGggJ2xhcHBseScsIHRoZSByZXR1cm4gdmFsdWVzIGFyZSB0aGUgc2FtZSwgYnV0CiN0aGUgdmFsdWVzIGFyZSByZXR1cm5lZCBhcyBhIGxpc3QsIGFzIGluOgpsYXBwbHkoMToxMCwgRlVOPWZ1bmN0aW9uKHgpIGV4cCh4KSkKI3lvdSBuZWVkIHRvIHdyYXAgdGhlIGFib3ZlIGNvbW1hbmQgd2l0aCB1bmxpc3QoKSB0byBjb252ZXJ0IHRoZSByZXR1cm5lZCAKI2xpc3QgaW50byBhIHZlY3RvcgoKI2hvd2V2ZXIsIGxhcHBseSBtYXkgYmUgdXNlZnVsIHRvIGxvb3AgdGhyb3VnaCBjb2x1bW4gdmVjdG9ycyBvZiBhIGRhdGFmcmFtZSwKI2FzIGluOgpsYXBwbHkoZGZUbXAsIEZVTj1mdW5jdGlvbih4KSB0YWJsZSh4KSkKI3Rob3VnaCwgdGhlIGZyZXF1ZW5jeSBmdW5jdGlvbiAodGFibGUpIHdvcmtzIGZvciBtb3N0IGtpbmRzIG9mIGRhdGEgdHlwZXMsIAojaXQgbWF5IG5vdCBtYWtlIHNlbnNlIHRvIHVzZSBpdCBvbiBjb250aW51b3VzIG51bWVyaWMgZGF0YSBhbmQgZGlzY3JldGUKI251bWVyaWMgdmVjdG9yIGNvbnRhaW5pbmcgbnVtZXJvdXMgdW5pcXVlIHZhbHVlcwoKI1VubGlrZSBsYXBwbHksIHRoZSAnYXBwbHkoKScgaGFzIGEgcHJvdmlzaW9uIHRvIGNob29zZSB0aGUgbWFyZ2luIG9mIHRoZSAKI21hdHJpeCBvciBhIGRhdGFmcmFtZSBvbiB3aGljaCB0aGUgZnVuY3Rpb24gY2FuIGJlIGFwcGxpZWQ7CiN0aGUgbWFyZ2lucyBhcmUgZWl0aGVyIHJvdyB2ZWN0b3JzIG9yIGNvbHVtbiB2ZWN0b3JzOwphcHBseShncm93dGhCeURheSwgMSwgRlVOPW1lYW4pICNtYXJnaW4gMSBkZW5vdGVzIHJvdyB2ZWN0b3JzIG9mIHRoZSBtYXRyaXgKI3RoZSBhYm92ZSBpcyBlcXVpdmFsZW50IG9mIHRoZSBmb2xsb3dpbmc6CnJvd01lYW5zKGdyb3d0aEJ5RGF5KQoKI3NpbWlsYXJseSwKYXBwbHkoZ3Jvd3RoQnlEYXksIDIsIEZVTj1tZWFuKSAjd2lsbCBnaXZlLi4KY29sTWVhbnMoZ3Jvd3RoQnlEYXkpCgoKI05vdGUgdGhhdCwgaW4gYWxsIHRoZSBhYm92ZSBhcHBseSBmdW5jdGlvbnMsIHRoZSB2ZWN0b3Igb3IgbGlzdCBwYXNzZWQgCiNjYW4gYmUgb2YgYW55IHR5cGU7IG9ubHkgY29uc3RyYWludCBpcyB0aGF0IGFuIGFwcHJvcHJpYXRlIGZ1bmN0aW9uIAojbmVlZHMgdG8gYmUgYXBwbGllZCBiYXNlZCBvbiB0aGUgZGF0YSB0eXBlOwoKI0Fsc28gbm90ZSB0aGF0LCB0aGUgZnVuY3Rpb24gYXBwbGllZCBjYW4gYmUgYW55IGJ1aWx0LWluIGZ1bmN0aW9uIGluIFIgb3IKI2FueSB1c2VyLWRlZmluZWQgZnVuY3Rpb24KYGBgCgoKIyMgRGF0YSBpbnB1dHMKUiBoYXMgc2V2ZXJhbCB3YXlzIHRvIGFjY2VwdCBpbnB1dCBmcm9tIHRoZSB1c2VyIG9yIGV4dGVybmFsIGZpbGVzIGFuZCBvdXRwdXQgdGhlIGRhdGEgdG8gY29uc29sZSBvciBmaWxlcy4gU29tZSBvZiB0aGVtIGFyZSBleGVtcGxpZmllZCBiZWxvdy4KYGBge3IgZWNobz1ULCBldmFsPUZ9CiN0byBhY2Nlc3MgdGhlIHZhbHVlIG9mIHRoZSBrZXkgcHJlc3NlZCBieSB0aGUgdXNlcjoKa2V5SW4gPC0gcmVhZGxpbmUoKQoKI3RoZSBmb2xsb3dpbmcgaXMgYSB1c2VyLWRlZmluZWQgZnVuY3Rpb24gdGhhdCBhY2NlcHRzIGtleWJvYXJkIGlucHV0CiMgYW5kIHByaW50cyB0aGUgbnVtZXJpYyBlcXVpdmFsZW50IG9mIHRoZSBrZXkgcHJlc3NlZDsKI2l0IGtlZXBzIGFza2luZyBmb3IgdXNlciBpbnB1dCB1bnRpbCBFc2Mga2V5IGlzIHByZXNzZWQKZ2V0VmFsT2ZDaGFyIDwtIGZ1bmN0aW9uKCl7CiAga2V5SW4gPC0gcmVhZGxpbmUocHJvbXB0PSdFbnRlciBhbnkga2V5KFByZXNzIEVzYyB0byBzdG9wKTonKQogIAogIGlmIChpcy5uYShrZXlJbikpIHsKICAgIHJldHVybihOVUxMKQogIH0gZWxzZSB7CiAgICBrZXlWYWwgPC0gYXMuaW50ZWdlcihjaGFyVG9SYXcoa2V5SW4pKQogICAgY2F0KHNwcmludGYoJyVzOiAlZFxuJywga2V5SW4sIGtleVZhbCkpCiAgICBnZXRWYWxPZkNoYXIoKQogIH0KfQojbWFrZSBhIGNhbGwgdG8gdGhlIGZ1bmN0aW9uOgpnZXRWYWxPZkNoYXIoKQpgYGAKCkluc3RlYWQgb2Ygd2FpdGluZyBmb3IgaW5kaXZpZHVhbCBrZXkgcHJlc3MgZXZlbnQsIHRoZSBzY2FuKCkgZnVuY3Rpb24gYWxsb3dzIHRoZSB1c2VyIHRvIGlucHV0IGEgZGVmaW5pdGUgbnVtYmVyIG9mIHZhbHVlczsgdGhlIGRhdGEgdHlwZSBjYW4gYmUgc3BlY2lmaWVkCmBgYHtyIGV2YWw9RiwgZWNobz1UfQojcHJvbXB0IHRoZSB1c2VyCnByaW50KCdFbnRlciBmaXZlIG9ic2VydmF0aW9ucyBvZiB0cmVlIGdpcnRoIChDdHJsLVogb3IgRXNjIHRvIGVuZCknKQoKI2FjY2VwdCB0aGUgdmFsdWUgaW5wdXRzIGZyb20gdGhlIHVzZXIgKGNvbW1hIGRlbGltaXRlZCkKdHJlZUdpcnRocyA8LSBhcy5kb3VibGUoc2Nhbih3aGF0PSdkb3VibGUnLCBubWF4PTUsIHNlcD0nLCcpKQoKI2RvIHdoYXRldmVyIHdpdGggdGhlIHZhbHVlcyByZWFkCmNhdChzcHJpbnRmKCdBdmVyYWdlwrFTRCB0cmVlIGdpcnRoIChtKTogJTAuMmYgwrEgJTAuMmYnLCAKICAgICAgICAgICAgICBtZWFuKHRyZWVHaXJ0aHMpLCBzZCh0cmVlR2lydGhzKSkpCmBgYAoKVGhlIHNjYW4oKSBmdW5jdGlvbiBjYW4gYWxzbyBiZSBtb2RpZmllZCB0byByZWFkIGlucHV0IGZyb20gYSBmbGF0IGZpbGUuIEZvciBpbnN0YW5jZSwgdGhlIGZvbGxvd2luZyBpcyB0aGUgY29udGVudCBvZiB0cmVlR2lydGgudHh0IGZpbGU6CgoxMi40LDEzLjIsMTQuOCwxMi43LDE0LjEsMTQuMiwxNS4wCgpUaGUgdmFsdWVzIGFyZSBvZiBkb3VibGUgdHlwZSBhbmQgc2VwZXJhdGVkIGJ5IGNvbW1hIGRlbGltaXRlci4gTGV0IHVzIHNheSB3ZSB3YW50IHRvIHNjYW4gdGhlIGZpcnN0IGZpdmUgdmFsdWVzIGZyb20gdGhlIGZpbGUuIFVzaW5nIHNjYW4sIHRoaXMgY2FuIGJlIGFjaGlldmVkLCBhcyBpbjoKYGBge3IgZXZhbD1GLCBlY2hvPVR9CiNvcGVuIHRoZSBjb25uZWN0aW9uIHRvIHRoZSBmaWxlIGluIHJlYWQtb25seSBtb2RlCmZjb25UcmVlR2lydGggPC0gZmlsZSgndHJlZUdpcnRoLnR4dCcsICdyJykKCiNzY2FuIGZpcnN0IGZpdmUgZG91YmxlIHR5cGVkIHZhbHVlcyBhbmQgcmV0cmlldmUKdHJlZUdpcnRocyA8LSBhcy5kb3VibGUoc2NhbihmaWxlPWZjb25UcmVlR2lydGgsIHdoYXQ9J2RvdWJsZScsIG5tYXg9NSwgc2VwPScsJykpCgojZG8gd2hhdGV2ZXIgeW91IHdhbnQgdG8gZG8gd2l0aCB0aGUgdmFsdWVzIGV4dHJhY3RlZApjYXQoc3ByaW50ZignQXZlcmFnZcKxU0QgdHJlZSBnaXJ0aCAobSk6ICUwLjJmIMKxICUwLjJmJywgCiAgICAgICAgICAgIG1lYW4odHJlZUdpcnRocyksIHNkKHRyZWVHaXJ0aHMpKSkKCiNpdCBpcyBtYW5kYXRvcnkgdG8gY2xvc2UgdGhlIGNvbm5lY3Rpb24gdG8gdGhlIGZpbGUKY2xvc2UoZmNvblRyZWVHaXJ0aCkKYGBgCgpZb3UgbWF5IGFsc28gd2FudCB0byByZWFkIGZsYXQgZmlsZXMgbGluZSBieSBsaW5lLiBUaGUgInJlYWRMaW5lcyIgZnVuY3Rpb24gKG5vdGUgdGhlIGNhcGl0YWwgbGV0dGVyIEwgaW4gdGhlIGZ1bmN0aW9uIG5hbWUpIGNhbiBiZSB1c2VkIGZvciB0aGlzIHB1cnBvc2UuIFRoZSBjb250ZW50IG9mIHRoZSBmaWxlICdTZWxmaXNoIEdlbmUtUmljaGFyZCBEYXdraW5zLnR4dCcgaXM6CiIKVGhlIGdlbmUtY2VudHJlZCB2aWV3IG9mIGV2b2x1dGlvbiB0aGF0IERhd2tpbnMgY2hhbXBpb25lZCBhbmQgY3J5c3RhbGxpemVkIGlzIG5vdyBjZW50cmFsIGJvdGggdG8gZXZvbHV0aW9uYXJ5IHRoZW9yaXppbmcgYW5kIHRvIGxheSBjb21tZW50YXJpZXMgb24gbmF0dXJhbCBoaXN0b3J5IHN1Y2ggYXMgd2lsZGxpZmUgZG9jdW1lbnRhcmllcy4gCgpBIGJpcmQgb3IgYSBiZWUgcmlza3MgaXRzIGxpZmUgYW5kIGhlYWx0aCB0byBicmluZyBpdHMgb2Zmc3ByaW5nIGludG8gdGhlIHdvcmxkIG5vdCB0byBoZWxwIGl0c2VsZiwgYW5kIGNlcnRhaW5seSBub3QgdG8gaGVscCBpdHMgc3BlY2llcyDigJQgdGhlIHByZXZhaWxpbmcsIGxhenkgdGhpbmtpbmcgb2YgdGhlIDE5NjBzLCBldmVuIGFtb25nIGx1bWluYXJpZXMgb2YgZXZvbHV0aW9uIHN1Y2ggYXMgSnVsaWFuIEh1eGxleSBhbmQgS29ucmFkIExvcmVueiDigJQgYnV0ICh1bmNvbnNjaW91c2x5KSBzbyB0aGF0IGl0cyBnZW5lcyBnbyBvbi4gCgpHZW5lcyB0aGF0IGNhdXNlIGJpcmRzIGFuZCBiZWVzIHRvIGJyZWVkIHN1cnZpdmUgYXQgdGhlIGV4cGVuc2Ugb2Ygb3RoZXIgZ2VuZXMuIAoKTm8gb3RoZXIgZXhwbGFuYXRpb24gbWFrZXMgc2Vuc2UsIGFsdGhvdWdoIHNvbWUgaW5zaXN0IHRoYXQgdGhlcmUgYXJlIG90aGVyIHdheXMgdG8gdGVsbCB0aGUgc3RvcnkuCiIKCmBgYHtyIGV2YWw9RiwgZWNobz1UfQojZmlyc3Qgb3BlbiB0aGUgY29ubmVjdGlvbiB0byB0aGUgZmlsZQpmY29uU2VsZmlzaEdlbmUgPC0gZmlsZSgnU2VsZmlzaCBHZW5lLVJpY2hhcmQgRGF3a2lucy50eHQnLCAncicpCgp0aGlzTGluZSA8LSAiIiAjdG8gYmVnaW4gd2hpbGUgbG9vcCwgdGhpcyBpbml0aWFsaXp0aW9uIGlzIHJlcXVpcmVkCmxpbmVudW1iZXIgPC0gMSAjaW5pdGlhbGl6ZSB0aGUgbGluZSBudW1iZXIKd2hpbGUobGVuZ3RoKHRoaXNMaW5lKT4wKXsKICAgI3JlYWQgb25lIGxpbmUgYXQgYSB0aW1lCiAgIHRoaXNMaW5lIDwtIHJlYWRMaW5lcyhmY29uU2VsZmlzaEdlbmUsIG49MSkKICAgCiAgICNwcmludCBudW1iZXIgb2YgY2hhcmFjdGVycyBpbiBlYWNoIGxpbmUKICAgY2F0KHNwcmludGYoJ051bWJlciBvZiBjaGFycyBpbiBsaW5lICVkOiAlZFxuJywgCiAgICAgICAgICAgICAgIGxpbmVudW1iZXIsIG5jaGFyKHRoaXNMaW5lKSkpCiAgIAogICBsaW5lbnVtYmVyIDwtIGxpbmVudW1iZXIrMSAjaW5jcmVtZW50IHRoZSBsaW5lIG51bWJlcgp9CmNsb3NlKGZjb25TZWxmaXNoR2VuZSkgI2RvbnQgZm9yZ2V0IHRvIGNsb3NlIHRoZSBjb25uZWN0aW9uCgojTm90ZSB0aGF0IHRoZSBsZW5ndGggb2YgYW55IGVtcHR5IGxpbmUgaXMgMS4gV2hpbGUgbmNoYXIoKSByZXR1cm5zIHRoZSAKI2xlbmd0aCBvZiB0aGUgbGluZSBpbiB0ZXJtcyBvZiBudW1iZXIgb2YgY2hhcmFjdGVycy4KCiNBbHNvIG5vdGUgdGhhdCwgb25jZSB0aGUgZW5kIG9mIGZpbGUgaXMgcmVhY2hlZCwgeW91IGNhbiBub3QgcG9pbnQgYmFjawojdG8gdGhlIHN0YXJ0IG9mIHRoZSBmaWxlIHdpdGggdGhlIHNhbWUgY29ubmVjdGlvbjsgZm9yIHdoaWNoLCB5b3Ugd291bGQKI25lZWQgdG8gY2xvc2UgdGhlIGNvbm5lY3Rpb24gYW5kIG9wZW4gaXQgYWdhaW4gYWZyZXNoOwoKI3lvdSBjYW4gYWxzbyByZWFkIHRoZSB3aG9sZSBjb250ZW50IG9mIHRoZSBmaWxlIGluIG9uZSBzaG90LCBhcyBpbjoKZmNvblNlbGZpc2hHZW5lIDwtIGZpbGUoJ1NlbGZpc2ggR2VuZS1SaWNoYXJkIERhd2tpbnMudHh0JywgJ3InKQpleGNlcnB0cyA8LSByZWFkTGluZXMoZmNvblNlbGZpc2hHZW5lKSAjYWxsIGxpbmVzIGFyZSByZWFkCnByaW50KGV4Y2VycHRzW2MoMSwzKV0pICNwcmludHMgb25seSB0aGUgMXN0IGFuZCAzcmQgbGluZXMKY2xvc2UoZmNvblNlbGZpc2hHZW5lKQpgYGAKCk1hbnkgZGF0YSBmaWxlcyBhcmUgYXZhaWxhYmxlIGluIHRoZSBmb3JtIG9mIHRleHQgZmlsZXMgaW4gd2hpY2ggdGhlIGRhdGEgYXJlIGFycmFuZ2VkIGluIHRoZSBmb3JtIG9mIGEgbWF0cml4IG9yIGEgdGFibGU7IHRoZSBtYXRyaXgvdGFibGUgc3RydWN0dXJlIHRoZSByb3cgdmFsdWVzIGFyZSBkZWxpbWl0ZWQgYnkgYSBjb21tYSBvciBhIHNwYWNlIG9yIGEgdGFiIG9yIHNvbWUgb3RoZXIgc3BlY2lhbCBjaGFyYWN0ZXI7IGFuZCBlYWNoIGxpbmUgb2Ygcm93IGFyZSBkZWxpbWl0ZWQgYnkgYSBuZXcgbGluZSBvciBjYXJyaWFnZSByZXR1cm4gKG5vdCB2aXNpYmxlKTsgYW5kIHRoZSB0YWJsZXMgbWF5IG5vdCBoYXZlIGhlYWRlcnMgKGNvbHVtbnMpOwoKSW4gb3JkZXIgdG8gcmVhZCB0aGVzZSBraW5kcyBvZiBmaWxlcyBpbnRvIFIsIHJlYWQudGFibGUoKSBvciByZWFkLmNzdigpIGZ1bmN0aW9uIGlzIHVzZWQuIFRoZSBmb2xsb3dpbmcgaXMgdGhlIGNvbnRlbnQgb2YgdGhlIHNwYWNlIGRlbGltaXRlZCBkYXRhIGZpbGUgLSBkZWxpbWl0ZWQudHh0OgoKSUQgZXhwMSBleHAyIGV4cDMgZXhwNCBleHA1IHF1YWwKMSA1IDQgNSA1LjIgNiBBQQoyIDUuNSA0IDYgNS4yIDUuNSBDCjMgNiA1IDkgNS4yIDYgQwo0IDYuMiA1LjUgOCA1LjIgNS41IEEKNSA2LjMgNS42IDcgNS4yIDYgQQo2IDYuMyA1LjcgNCA1LjIgNS41IEIKClRoZSByZWFkLmNzdigpIGV4dHJhY3RzIHRoZSBjb250ZW50IG9mIHRoZSBmaWxlIGludG8gYSBSIGRhdGEuZnJhbWUgb2JqZWN0LCBhcyBpbjoKYGBge3IgZXZhbD1GLCBlY2hvPVR9CiNzZXAgaXMgb25lIHNwYWNlIGNoYXJhY3RlciwgaGVhZGVyIGlzIHByZXNlbnQsIHNpbmdsZSBxdW90ZSB3YXMgdXNlZCAKI2ZvciBzdHJpbmcgdmFsdWVzIGluIHRoZSByb3dzOwpteVRhYmxlIDwtIHJlYWQuY3N2KGZpbGU9J01haW4gU2Vzc2lvbnMvZGVsaW1pdGVkLmNzdicsIHNlcD0nICcsIAogIGhlYWRlcj1ULCBzdHJpbmdzQXNGYWN0b3JzPUYsIHF1b3RlPSJcJyIpCnByaW50KG15VGFibGUpCgojQnkgZGVmYXVsdCwgZG91YmxlIHF1b3RlIGlzIGFzc3VtZWQgZm9yIHN0cmluZyB2YWx1ZXM7IG9yIGlmIG9uZSBvZiB0aGUgCiN2YWx1ZSBpbiBhIGNvbHVtbiBjb250YWlucyBub24tbnVtZXJpYyB2YWx1ZXMsIHRoZSBjb2x1bW4gd2lsbCBiZQojY29uc2lkZXJlZCBhcyBhIGNoYXJhY3RlciB0eXBlIGNvbHVtbjsKCiNpZiBzdHJpbmdzQXNGYWN0b3JzIGlzIHNldCB0byBUUlVFLCB0aGVuIHJlYWQuY3N2KCkgd2lsbCBmYWN0b3JpemUgdGhlIGNoYXJhY3RlciB0eXBlIAojY29sdW1ucyAod2hpY2ggaXMgdGhlIGRlZmF1bHQpCgojTm90ZSB0aGF0IHRoZXJlIGlzIG5vIG5lZWQgdG8gb3BlbiBhIGNvbm5lY3Rpb24gYW5kIGNsb3NlIGl0LgpgYGAKCgojIyBEYXRhIG91dHB1dApBcyB3ZSBoYXZlIGRhdGEgaW5wdXQgZnVuY3Rpb25zLCBSIGFsc28gc3VwcG9ydHMgdGhlIGRhdGEgb3V0cHV0IGZ1bmN0aW9ucywgZXNwZWNpYWxseSB0byB3cml0ZSBjb250ZW50IGludG8gZmlsZXMgZm9yIHN0b3JpbmcgcmVzdWx0cy4KClRoZSBzaW5rKCkgZnVuY3Rpb24gYWxsb3dzIHRoZSBjb25zb2xlIG91cHV0cyB0byBnZXQgcmVkaXJlY3RlZCB0byBhIGZpbGUsIGFzIGluOgpgYGB7ciBlY2hvPVQsIGV2YWw9Rn0KI29wZW4gdGhlIGNvbm5lY3Rpb24gdG8gYSBmaWxlCnNpbmsoJ2FuYWx5dGljYWxyZXN1bHRzLnR4dCcsIGFwcGVuZD1GLCBzcGxpdD1GKQoKI2ZvciBhIG5ldyBmaWxlICdhcHBlbmQnIGlzIHNldCB0byBGQUxTRSwgaWYgaXQgaXMgYW4gZXhpc3RpbmcgZmlsZSB0aGVuCiN5b3UgbWlnaHQgbmVlZCB0byBhZGQgdGhlIG5ldyBjb250ZW50IHRvIGl0OyBmb3Igd2hpY2gsIHlvdSB3b3VsZCBzZXQKIydhcHBlbmQnIHRvIFRSVUU7Cgojd2hlbiAnc3BsaXQnIGlzIHNldCB0byBGQUxTRSwgdGhlbiB5b3Ugd29udCBzZWUgYW55IGNvbnNvbGUgb3V0cHV0OyBhbGwgCiN0aGUgb3V0cHV0cyBhcmUgc2VudCBvbmx5IHRvIHRoZSBmaWxlOwoKI2FzIHNpbmsoKSBoYXMgb3BlbmVkIGEgY29ubmVjdGlvbiB0byB0aGUgZmlsZSBlYXJsaWVyLCB0aGUgb3V0cHV0cyAKIyhtYXRyaWNlcykgb2YgdGhlIGxvb3AgYXJlIHNlbnQgdG8gZmlsZTsKZm9yKGkgaW4gMToxMCl7CiAgcHJpbnQoZ3Jvd3RoQnlEYXkgKiBpKQp9CgpzaW5rKCkgI3RoaXMgaXMgcmVxdWlyZWQgdG8gd3JpdGUgdGhlIGZpbGUgdG8gZmlsZSBzeXN0ZW0gYW5kIHRvIGNsb3NlIGl0CmBgYAoKVGhlIGNvbXBsZW1lbnRhcnkgZnVuY3Rpb24gb2YgcmVhZC5jc3YoKSBpcyB3cml0ZS5jc3YoKSB3aGljaCB3cml0ZXMgYSBkYXRhZnJhbWUgb2JqZWN0IGludG8gYSB0ZXh0IGZpbGUgd2l0aCBzcGVjaWZpZWQgZGVsaW1pdGVycy4KYGBge3IgZXZhbD1GLCBlY2hvPVR9Cm5ld2ZpbGUgPC0gJ215VGFibGUuY3N2Jwp3cml0ZS5jc3YoZGZUbXAsIGZpbGU9bmV3ZmlsZSwgcm93Lm5hbWVzPUYpCgojdGhlIGRlZmF1bHQgZGVsaW1pdGVyIG9mIHZhbHVlcyBpbiBhIHJvdyBpcyBjb21tYTsKI3doZW4gcm93Lm5hbWVzIGlzIHNldCB0byBGQUxTRSwgdGhlIHJvdyBJRHMgb2YgdGhlIG1hdHJpeCBvciBkYXRhLmZyYW1lCiN3aWxsIGJlIGlnbm9yZWQgd2hpbGUgd3JpdGluZyB0aGUgY29udGVudCBpbnRvIHRoZSBmaWxlCmBgYAoKIyMgRnVuY3Rpb25zIChtaXNjZWxsYW5lb3VzKQoKIyMjIEZ1bmN0aW9ucyBvZiBmaWxlcyBhbmQgZGlyZWN0b3JpZXMKYGBge3IgZXZhbD1GLCBlY2hvPVR9CmdldHdkKCkgI2dldHMgdGhlIGN1cnJlbnQgd29ya2luZyBkaXJlY3Rvcnkgb2YgdGhlIFIgc2Vzc2lvbgpzZXR3ZChnZXR3ZCgpKSAjc2V0cyB0aGUgd29ya2luZyBkaXIKCm5ld2RpciA8LSAnbXlGb2xkZXIvc3ViRm9sZGVyJwpkaXIuZXhpc3RzKG5ld2RpcikgI2NoZWNrcyBpZiB0aGUgc3BlY2lmaWVkIGZvbGRlciBleGlzdHMKI2lmIGFic29sdXRlIHBhdGggaXMgbm90IGdpdmVuLCBpdCBjaGVja3MgaW4gdGhlIHdvcmtpbmcgZGlyCgpkaXIuY3JlYXRlKG5ld2RpciwgcmVjdXJzaXZlPVQpICAjY3JlYXRlcyB0aGUgZGlyIHNwZWNpZmllZAojcmVjdXJzaXZlPVQgd2hlbiBwYXJlbnQgYW5kIHN1Yi1mb2xkZXJzIG5lZWQgdG8gYmUgY3JlYXRlZAoKZmlsZS5leGlzdHMoJ3RyZWVHaXJ0aC50eHQnKSAjY2hlY2tzIGlmIHRoZSBmaWxlIGlzIHByZXNlbnQgaW4gdGhlIGN1cnJlbnQKI3dvcmtpbmcgZGlyZWN0b3J5CgojdGhlIGZvbGxvd2luZyBsaXN0cyBhbGwgdGhlIGZvbGRlcnMgaW4gdGhlIHBhdGggZ2l2ZW4KbGlzdC5kaXJzKHBhdGg9Z2V0d2QoKSwgZnVsbC5uYW1lcz1ULCByZWN1cnNpdmU9RikKI2lmIHJlY3Vyc2l2ZT1ULCB0aGVuIGFsbCBzdWJmb2xkZXJzIHdpbGwgYWxzbyBiZSBsaXN0ZWQKCiNTaW1pbGFybHksIHRoZSBmb2xsb3dpbmcgbGlzdHMgYWxsIGZpbGVzIHdpdGggYSBnaXZlbiBwYXR0ZXJuCm15ZmlsZXMgPC0gbGlzdC5maWxlcyhwYXRoPXNwcmludGYoJyVzL01haW4gU2Vzc2lvbnMnLGdldHdkKCkpLCBwYXR0ZXJuPScqLlIkJywgZnVsbC5uYW1lcz1GKQoKI1RoZSBmdW5jdGlvbiBybWRpcig8ZGlyPikgd2lsbCBkZWxldGUgYSBmb2xkZXI7IHNpbWlsYXJseSwgdW5saW5rKDxmaWxlPikKI3dpbGwgZGVsZXRlIHRoZSBzcGVjaWZpZWQgZmlsZTsKYGBgCgojIyMgU29tZSB1c2VyIGRlZmluZWQgZnVuY3Rpb25zCmBgYHtyIGV2YWw9RiwgZWNobz1UfQojbW9kZSBmdW5jdGlvbiB0byBvYnRhaW4gdGhlIG1vc3QgZnJlcXVlbnRseSBvYnNlcnZlZCB2YWx1ZSBpbiBhIHZlY3RvcgojaXMgbm90IGF2YWlsYWJsZSBpbiBiYXNlIFI7IGxldCB1cyB3cml0ZSBhIGZ1bmN0aW9uIGZvciBpdDoKbXlNb2RlIDwtIGZ1bmN0aW9uKG51bVZlYz1OVUxMKXsKICAgZnQgPC0gdGFibGUobnVtVmVjKSAjYSB0YWJsZSBvZiB2YWx1ZXMgdnMgZnJlcXVlbmNpZXMKICAgbWF4RnJlcSA8LSBtYXgoZnQpICNnZXRzIHRoZSBsYXJnZXN0IGZyZXF1ZW5jeQogICAjdG8gZXh0cmFjdCBhbGwgZW50cmllcyBpbiB0aGUgdGFibGUgdGhhdCBzaGFyZSB0aGUgbWF4IGZyZXEKICAgYWxsRW50cmllc1dpdGhNYXhGcmVxIDwtIGZ0W2Z0PT1tYXhGcmVxXQogICAjYmVjYXVzZSAnZnQnIGlzIGEgbmFtZWQgdmVjdG9yLCB3aGVyZSB0aGUgbmFtZXMgYXJlIHRoZSB1bmlxdWUKICAgI3ZhbHVlcyBmb3Igd2hpY2ggdGhlIGZyZXEgY291bnQgd2VyZSBvYnRhaW5lZDsgaGVuY2UsIHRoZSBuYW1lcyB0aGF0CiAgICNzaGFyZSB0aGUgbWF4aW11bSBmcmVxIGFyZSB0aGUgbW9kZSB2YWx1ZXMKICAgbW9kZXMgPC0gbmFtZXMoYWxsRW50cmllc1dpdGhNYXhGcmVxKQogICAjYmVjYXVzZSB0aGUgbmFtZXMgYXJlIG9mIGNoYXJhY3RlciB0eXBlLCB3ZSBuZWVkIHRvIGNvbnZlcnQgdGhlbSB0bwogICAjbnVtZXJpYyBmb3JtYXQKICAgbW9kZXMgPC0gYXMubnVtZXJpYyhtb2RlcykKICAgI2ZpbmFsbHksIGlmIHRoZSByZXN1bHQgaXMgbXVsdGktbW9kZWwgKG1vZGVzPjEpLCB0aGVuIHdlIG5lZWQgdG8gCiAgICN0YWtlIGF2ZXJhZ2Ugb2YgYWxsIG1vZGFsIHZhbHVlcwogICByZXR1cm4oIG1lYW4obW9kZXMpKQp9CgojdGhlIGFib3ZlIGZ1bmN0aW9uIGNhbiBiZSB6aXBwZWQgaW50byB0d28gbGluZXMgb2YgY29kZSBieSB3cmFwcGluZwojZnVuY3Rpb25zIG92ZXIgZnVuY3Rpb25zLCBhcyBpbjoKbXlNb2RlIDwtIGZ1bmN0aW9uKG51bVZlYz1OVUxMKXsKICAgZnQgPC0gdGFibGUobnVtVmVjKQogICByZXR1cm4gKG1lYW4oYXMubnVtZXJpYyhuYW1lcyhmdFtmdD09bWF4KGZ0KV0pKSkpCn0KCiN0byB1c2UgaXQ6Cm15TW9kZShyYW5kb21OdW1iZXJzKQoKCiNsZXQgdXMgZGVmaW5lIGEgZnVuY3Rpb24gdG8gZ2V0IHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdHdvIGRhdGVzIGluIG1vbnRocwpkaWZmTW9udGhzIDwtIGZ1bmN0aW9uKGRmMT1OQSwgZGYyPU5BKXsKICAgaWYoIWFsbChjKGNsYXNzKHBzbylbMV0sY2xhc3MocHNvMSlbMV0pICVpbiUgYygnRGF0ZScsJ1BPU0lYY3QnKSkpewogICAgICBwcmludCgnVGhlIGRhdGUgdmFsdWVzIHNob3VsZCBiZSBlaXRoZXIgRGF0ZSBvYmplY3Qgb3IgUE9TSVhjdCBvYmplY3QhJykKICAgICAgcmV0dXJuKE5VTEwpCiAgIH0gZWxzZSB7CiAgICAgIGRpZmZtIDwtIGFzLm51bWVyaWMoZGlmZnRpbWUoZDIsIGQxLCB1bml0cz0nZGF5cycpKSAlLyUgMzBMCiAgICAgIHJldHVybihkaWZmbSkKICAgfQp9CiN0byB1c2UgaXQ6CmRhdGUxIDwtIGFzLkRhdGUoJzAxIEphbiAyMDEwJywgJyVkICViICVZJykKZGF0ZTIgPC0gYXMuUE9TSVhjdCgnMDEgSmFuIDIwMTAnLCAnJWQgJWIgJVknKQpkaWZmTW9udGhzKGRhdGUxLCBkYXRlMikKYGBgCgo=