The goal of this tutorial is to introduce you to one of the most commonly used programming languages in computational biology: R. Throughout this tutorial, you can think of learning R as learning how to use a specialized smartphone, and learning the specific R packages as the various apps designed to help you do different tasks computational biologists do.

Step 1: Create an account with RStudio Cloud

R & R Studio are free! For this tutorial, I recommend you use R Studio Cloud. To create a free account just access this website https://login.rstudio.cloud and create a new account using your preferred email address.

Step 1b: Download and install R + R studio alternative

R is free and will always be! If after this workshop, you would like to go one step further, you can download R by accessing this website: http://www.r-project.org/ The download link will take you to a list of CRAN mirrors – pick a mirror: e.g. South Africa (for a list of the mirrors https://cran.r-project.org/mirrors.html).

Download R studio - free option; http://www.rstudio.com/ide/download/.

R studio is composed by 4 panels: 1=Top Left, 2=Top Right, 3=Bottom Left, and 4=Bottom right. Note taking happens in Panel 1. Panel 2 has “your environment”, every time you open R, you read data or create any kind of object in R it will be listed in your Environment tab. Any code you run in Panel 3 will appear also in Panel 2, under History and anything that you visualize and more will be in Panel 4. We will delve more into the details soon.

You will then need to set your working directory in your local computer if you chose the option to download R.

A working directory is the folder in your computer where all available data are & results will be saved.To find out the current working directory, type getwd() and hit ENTER.To set a new working directory, you will specify the computer path to a folder, for example setwd(“~/Dropbox/USB”). You can also use the non-programming option by following the drop-down menu on R Studio: click on the tab called Session -> Set Working Directory -> Choose Directory and just select the folder of your choice in your computer.

Step 2: Learn the Help Command

Practice makes perfect A way to learn is by deciphering error messages! So, if you get an error message, which is the output showing on red font, don’t panic! Computational biologists are constantly figuring out what error messages mean and why do we get them. An effective way to do this is to google your error message. Often someone has already found a solution and there is a ton of help online! Now since we are learning how to code, we can ask R for help using a specific function in a package by calling in R’s built-in help function, or by directly typing a question mark before the function you are trying to use.

#You want to learn what the function "help()" does in R
?help()
help() 

Question 1: How would you access built-in help about the R package dplyr, this is a commonly used package in data wrangling, management or rearranging (https://dplyr.tidyverse.org/).
A/

Step 3: Do basic calculations

R is like a smartphone, and its built-in package called base can do everything calculators do & much more! Let’s explore using R as a calculator.

Let’s use R to do some simple calculations:

#Sum
3 + 3

#Exponential
2^-7

#log function
?log() #add a question mark before a function to learn about what it does.
log(2)

Question 2: What type of logarithm (e.g. natural log, common log-base 10, or binary logarithm) does the log function computes?
A/

But then why using R and not a calculator? In R, anyone can create so called functions to create plots, maps, figures, organize data bases, conduct statistical analyses, make presentations, build websites, analyze whole genome sequences, among others.

Step 4: Familiarize yourself with packages and versions

Functions are compiled into packages (remember to think of these as the apps in a smartphone) published into the Comprehensive R Archive Network (CRAN), R’s central software repository hosted by the R foundation. In March 2022, there were 18,948 R packages made available through CRAN. (https://cran.r-project.org/web/packages/)

When using R or R studio, you can find all the built-in packages under Packages in Panel 4. To search for a specific package you can select “Install”, this opens a new window in which you may select the CRAN repository (recommended option) and search the name of the package by typing the name of it under Packages (separate multiple with space or comma). Make sure that under “Install to Library” -> you use the default location to install R packages and double check that the box for “install dependencies” is ticked. We can also install packages by coding in the console (Panel 3).

For instance search the package called ggplot2 used to create elegant graphs/plots using your data. The amount of freely available tutorials varies a lot among packages, some plotting packages like ggplot have lots of tutorials online whereas more specific packages will have sparse info. Yet, almost all packages have a user guide available online or by simply clicking on the name of the package in Panel 4, under the Packages tab, or the help() function we examined earlier.

#Example installing packages in R
install.packages("ggplot2") #used to create nice plots
install.packages("dplyr") #used to do data management
install.packages("tidyr") #used to tidy messy data
install.packages("tibble") #used together with dplyr to make simple frames
install.packages("explore") #used to do exploratory analyses
install.packages("patchwork") #creates multiplots / composer of plots
install.packages("tidyverse")
library("tidyverse")
library("ggplot2") #Running the library() command "activates" the packages
library("dplyr")
library("tidyr")
library("tibble")
library("explore")
library("patchwork")

It will become tricky to manage packages if these require different R versions (just like some apps in your smartphones that stopped being supported in old smartphones). It is important to keep the packages you often need organized and only load those that you will use, to avoid any problems. Also, since the community is actively developing free packages, there ways to install these are getting easier and easier.

Step 5: Familiarize yourself with objects in R

R programming language recognizes a handful of fundamental units used to perform different actions, we call those objects. The main types of objects in r are:

Functions: In R, a function is an object that we will code. Think of this as a task you want the computer to do for you. We will use functions by specifying instructions using arguments (inside of the parentheses) that may be necessary for the function to accomplish the actions. The basic syntax of a function can look as simple as this: help() or log(x,base=y).

Vectors: Vectors are variables, or series of values of the same class, they can be continuous (“numeric”), categorical (“factor”)", etc.

Data Frames and Tibbles: A data frame is a matrix composed by variables, but formatting variables as a data frame allows handling versatility in your R studio environment. Many functions require formatting your data as data frame. We often need to try out different ways to re-organize our data, so to do this we will take advantage of a new, simpler and versatile version of the data frame object called the tibble to be used along with the package dplyr.

List: A list can comprise all sorts of object types. Few functions require data as lists.

Other: Other less frequently used objects include: scalars (a single value), matrices (similar to data frame, but allow objects with varying lengths).

Let’s explore these in R:

#Object
x <- 3 + 5
x

#Vector
y <- c(1, 2, 3, 4, 5) 
y

seq(1,10, by = 1)#Creates a sequence following specific rules 

vector1<-seq(1, 10,  by = 1)
vector2<-seq(1, 20, by = 2)
vector3<-seq(1, 30,  by = 3)
vector4<-c("A", "B", "C", "D", "E", "F","G", "H", "I", "J")

#Data frame
df1<-data.frame(vector1,vector2,vector3, vector4)

#Tibble
tibble1<-tibble::tibble(df1)

#List
list1<- list(df1, vector1, vector2, vector3, vector4, x, y) 

#Note that giving a name (e.g, "df1") will have downstream implications.
#It is important to give your objects unique, intuitive, short & simple names.

Question 3: What is an advantage and a disadvantage of using a list?
A/

Step 6: Familiarize yourself with functions in R

Here try to find a few more of the many built-in functions in r, for example:

#Calculate mean
?mean
mean(vector1)
#Sum values in a vector using
?sum
sum(vector2)

#If we want to build a data frame we *need* to have a set of vectors all of the same length 
#Figure out length of a vector:
length(vector3)
#Retrieve unique values in vector
unique(vector4)
#Sort values in a vector 
df1$vector5<-sort(vector4, decreasing = TRUE)
#Sample 6 values at random from a numeric vector
sample(vector3, 3)
#Sample 4 letters at random from a character vector
sample(vector4, 4)

Question 4: How would you modify the sample() function to sample only three values at random, allowing a given number or character to appear more than once?
A/

You can also use R to plot functions just as most scientific calculators do. But before coding plots, we will learn a few more R commands to extract information from data frames or similar objects.

Step 7: Practice using data frames

Very often we want to summarize, visualize, simulate or analyze existing data, for that, one can start by using the data frame format in R. Here we are going to explore functions using very basic data frames, to learn more about how the data look like.

Note that in R studio, going to Panel 2 and simply clicking on a given data frame, will retrieve all its contents in a new tab in Panel 1.

Question 5: How would you modify one of this functions (e.g. mean()) to deal with missing values?
A/

Step 8: Practice exporting data frame

If you want to save/export the data frame you created in R, you just need to call a function named write.csv. To export your data frame, just name the file. I recommend you save your traditional data files (aka. excel-like tables) to use in R as a .csv (comma-separated values) file format.

#Exporting data
write.csv(df1, "df_2022jul2.csv") 

Question 6: Where is the file saved? Use the getwd() function to find out. How can you export text or a list that was created using R?
A/

Step 9: Practice importing data in R

Very often we have data that we want to import into R, there are several formats that are compatible with R. Data tables can be generated in R or other software, for example: excel, statistical software or google sheets (free). When data is not generated in R, data, can still easily be imported but there are distinct ways to import files depending the format of the data to be imported. Common formats include data as: text or .txt, comma separated values or .csv and/or as excel .xlsx (only the latter requires installing a package called .openxlsx. I recommend that you always save or import the data as .csv.

We previouly saved our data as a .csv, to import these data, we can just use the read.csv() function -as long as the file is contained in our current folder used as working directory.

#Import data as csv
imported_df1<-read.csv("df_2022jul2.csv", header=T)

Step 10: Create plots

We can use base R to create quick plots and identify patterns. We then can export these as a .pdf file format. Plotting is one of the biggest strengths of R. The possibilities are unlimited and there is a universe of tutorials out there to show you how to customize plots. Over the years I have moved on from base R into using the package ggplot2 which we will explore next.

#First: Plotting with base R
#Plot 1 continuous variable
hist(sample(seq(1:100),200, replace=TRUE), breaks=25, main="") #Note Question 7

#Plot 2 continuous variables
plot(df1$Cont1~df1$Cont2)

#Plot 1 continuous variable and 1 Binary/Categorical
boxplot(df1$Cont1~df1$Binary1)

#To export a pdf file with multiple figures:
pdf("plotsA_2022jul2.pdf")
hist(sample(seq(1:100),200, replace=TRUE), breaks=25, main="")
plot(df1$Cont1~df1$Cont2)
boxplot(df1$Cont1~df1$Binary1)
dev.off()

Question 7: What happens when we remove main="". How would you go about to rename your y axis label?
A/

Next we will use data on the survival status of individual passengers on board of the Titanic ship. Visit my google drive to download the titanic data set .csv format: https://drive.google.com/file/d/1jhGvXkYSrtsgmEnZ2GBR6AzBy1BUGbNg/view?usp=sharing

After successfully downloading trains.csv file you would be able to use the Upload option in Panel 4. Simply choose the file to upload, and hit Ok. Once you do this, it will be available in your environment.

Question 8: Did you get an error trying to upload this data file? How did you go about to fix this error?
A/

#Import the data set
titanic <- read.csv('trains.csv',stringsAsFactors = F, header = T)

#Explore the data set using the functions we learned before
head(titanic) #to see first 10 rows and column names
summary(titanic) #to get a summary of each column
#***Note that R describes missing data as "NA"

#Plot to summarize passenger age with base R
hist(na.omit(titanic$age),col=rainbow(length(1:8)),main="",xlab="age", ylab="count")

Step 11: Practice using ggplot2

Base R plots can be modified to look as pretty/detailed as you would like them to look. However, packages like ggplot2 make all the heavy-lifting for you. Next we will learn how to make a few simple, yet publication-level, nice looking plots using ggplot2 and the data management package dplyr. This tutorial does not cover data wrangling using dplyr, but there are many out there that do!

We just created a simple histogram using base R to use as comparison with the same plot created using ggplot2 and associated packages.

#Now let's use dplyr and ggplot2
#Part 1
#Note how the base R grammar we learned earlier differs a lot from "ggplot2" and "dplyr" (a series of packages as part of the "Tidyverse") we will use now to visualize the same data:
titanic %>% head(10) #Overview of the first 10 rows
only_1class <- filter(titanic, pclass == "1") #Extract rows that match a given criteria (like subset() in base R)
countstitanic<- titanic %>% count(sex,pclass,age, sort = TRUE)
widetitanic <- countstitanic %>% spread(sex,n) #Sometimes we want to have a "wide" format
longtitanic <- widetitanic %>% gather(sex, n, female:male, factor_key=TRUE)#this can reverse back to "long"
titanic %>% describe_tbl() #Describes data
summary_titanic<- titanic %>% group_by(sex, pclass) %>%dplyr::summarize(Mean = mean(age, na.rm=TRUE))#Generate summary

#Plot to summarize passenger age with ggplot
p1<-titanic %>% drop_na() %>% ggplot(aes(x=age))+
  geom_histogram(fill=rainbow(length(1:8)),bins=8,show.legend = FALSE)+
  labs(x = "age")
p1
#Packages like "dplyr" and "ggplot2" do a lot of the hard initial coding/data wrangling for you, giving you more time to focus on more advanced functions to use with your data.

The histogram created using this simple ggplot Rcode is more attractive, but we can do a lot more to customize this plot. For instance you can try adding different themes (e.g., classic, bw, minimal). Simply type theme followed by tab on the console to learn about the different themes and how to add them to an existing ggplot.

Step 12: Create publication-ready plots using ggplot2 and dplyr

#Part 2
#We can combine multiple categorical and continuous variables
p2<-ggplot(data=na.omit(titanic),
           aes(x=factor(sex),y=age,fill=factor(survived)))+
  geom_boxplot()+
  labs(title="Survival of passengers by sex, age and class",
       subtitle="Not everyone had equal chances of surviving", 
       caption="Plot by J.Golcher") +
  xlab("Passenger class")+
  ylab("age")+
  facet_wrap(~factor(pclass))+
  scale_fill_manual(values=c("mediumvioletred","cornflowerblue"),
                    name="",breaks=c("0", "1"),labels=c("died", "survived"))+
  theme(plot.title = element_text(face = "bold"))

p2

Using ggplot, we can quickly make clear figures that help data interpretation. Multiple data visualization R tutorials and cheat sheets exist in the internet. If you are interested in how to go from beginner to pro, again practice makes perfect. There are also new packages that make it easier to explore patterns from data, one of them is the package explore. This part of the tutorial is adapted from a 2022 tutorial written by Roland Crasser that can be accessed here: https://cran.r-project.org/web/packages/explore/vignettes/explore_titanic.html

#Part 3
#Let's explore functions and plots in explore
#
#First let's make age a categorical variable:
titanic$age_cat <- cut(titanic$age,breaks=c(0,19,60,90),
                       labels=c("children","adult","senior"))

#This is perhaps unnecessary but just to be sure
titanic2 <- tibble(titanic) #data frame into tibble

#We would like to reorganize our data as counts per categories
titan_sum<-titanic2 %>% group_by(pclass, survived,age_cat,sex) %>% dplyr::count()

titan_sum %>% describe_tbl(n=n) #describes data and NA

#Creating plots using explore
p3<-titan_sum %>% explore(age_cat, n = n) #passenger class distrib.
p4<-titan_sum %>% explore(age_cat, target = survived, n = n)
p5<-titan_sum %>% explore_all(n = n) #To see counts for all vars.
p6<-titan_sum %>% explore_all(target = survived, n = n, split = TRUE)

p3
p4
p5
p6

Step 13: Export ggplot2 charts

In this example we went beyond simply plotting using base R to practice data re-organization with advanced visualization. Lastly we will learn how to arrange and export ggplot figures using the package patchwork.

#Part 4
#A package to save ggplots
library(patchwork)
p<-(p1)/(p2)
#Save plots
ggsave("plotsB_2023jan17.pdf", p)

Question 9: How would you modify this code to save the plots next to one another using patchwork (instead of one on top ot the other).
A/

Now we have explored how to make a few plots using base R and some of the newest plotting options available associated to the package ggplot2. Still, remember that this is the very tiny tip of the iceberg. It will be up to you to take it from here and make significant progress in your R journey coding and making plots. There are almost too many resources online to learn how to visualize data using R, but as a start visit: https://www.r-graph-gallery.com/ to get inspired with a gallery of different types of charts.

Step 14: Run a simple statistical test

As a biologist, one of the first statistical tests we learn is how to calculate a Chi-squared value. For instance, such tests are used in the context of transmission genetics, together with the Chi-squared value distribution table to test for significance rejecting a null hypothesis of observations deviating or not from expected. As you already guessed it, R can do this for you and much more. We will start by learning how to do this test using the console, and review how to interpret results of the chisq.test() function in base R using the Titanic toy data set.

Question 10: What would be 1)the null and 2)the alternative hypotheses for a Chi-squared test looking at passenger survival by class? After running the code below: 3)Was the p-value significant? 4) What does this mean?
A/

#Chi-squared test using R
res1<-chisq.test(titanic$pclass, titanic$survived)
res1
res1$observed
res1$expected

Step 15: Cite R and Rpackages

It is key to give credit to the generous people who develop packages for free, often with public funds from universities and other research institutions. Providing authors with the credit they deserve also encourages funding agencies to support their work, which ultimately benefits the entire community of R users.

citation() #To cite R
R.Version() #Figure out R version
RStudio.Version() #To cite R studio
#To cite all the packages  used in this tutorial:
citation("ggplot2")
citation("dplyr")
citation("tibble")
citation("explore")
citation("patchwork")

This mini-workshop was modified from the 2018 Workshop notes Intro to R for fisheries researchers in Tanzania co-taught by Dr. Jessica Rick and Dr. Jimena Golcher-Benavides. I would like to thank the generous R & R learning community for all the high-quality learning resources freely available online.

For more learning resources on how to use R & R Studio, check out these guidelines written by Thomas Mock: https://www.rstudio.com/resources/webinars/a-gentle-introduction-to-tidy-statistics-in-r/.

LS0tCnRpdGxlOiAnSW50cm8gdG8gUiBpbiAxNSBTdGVwcycKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQo8IS0tIyBNb2RpZmllZCBmcm9tIFdvcmtzaG9wIEludHJvIHRvIFIgMjAxOCBjby10YXVnaHQgYnkgRHIuIEplc3NpY2EgUmljayBhbmQgRHIuIEppbWVuYSBHb2xjaGVyLUJlbmF2aWRlcywgTGFzdCBVcGRhdGU6IDIwMjMgSmFuIDE3LS0+CgpUaGUgZ29hbCBvZiB0aGlzIHR1dG9yaWFsIGlzIHRvIGludHJvZHVjZSB5b3UgdG8gb25lIG9mIHRoZSBtb3N0IGNvbW1vbmx5IHVzZWQgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzIGluIGNvbXB1dGF0aW9uYWwgYmlvbG9neTogKipSKiouIFRocm91Z2hvdXQgdGhpcyB0dXRvcmlhbCwgeW91IGNhbiB0aGluayBvZiBsZWFybmluZyAqKlIqKiBhcyBsZWFybmluZyBob3cgdG8gdXNlIGEgc3BlY2lhbGl6ZWQgc21hcnRwaG9uZSwgYW5kIGxlYXJuaW5nIHRoZSBzcGVjaWZpYyAqKlIgcGFja2FnZXMqKiBhcyB0aGUgdmFyaW91cyBhcHBzIGRlc2lnbmVkIHRvIGhlbHAgeW91IGRvIGRpZmZlcmVudCB0YXNrcyBjb21wdXRhdGlvbmFsIGJpb2xvZ2lzdHMgZG8uCgojIyMgU3RlcCAxOiBDcmVhdGUgYW4gYWNjb3VudCB3aXRoIFJTdHVkaW8gQ2xvdWQKKipSICYgUiBTdHVkaW8gYXJlIGZyZWUhKioKRm9yIHRoaXMgdHV0b3JpYWwsIEkgcmVjb21tZW5kIHlvdSB1c2UgUiBTdHVkaW8gQ2xvdWQuIFRvIGNyZWF0ZSBhIGZyZWUgYWNjb3VudCBqdXN0IGFjY2VzcyB0aGlzIHdlYnNpdGUgKmh0dHBzOi8vbG9naW4ucnN0dWRpby5jbG91ZCogYW5kIGNyZWF0ZSBhIG5ldyBhY2NvdW50IHVzaW5nIHlvdXIgcHJlZmVycmVkIGVtYWlsIGFkZHJlc3MuCgojIyMjIFN0ZXAgMWI6IERvd25sb2FkIGFuZCBpbnN0YWxsIFIgKyBSIHN0dWRpbyBhbHRlcm5hdGl2ZSAKKipSIGlzIGZyZWUgYW5kIHdpbGwgYWx3YXlzIGJlISoqCklmIGFmdGVyIHRoaXMgd29ya3Nob3AsIHlvdSB3b3VsZCBsaWtlIHRvIGdvIG9uZSBzdGVwIGZ1cnRoZXIsIHlvdSBjYW4gZG93bmxvYWQgUiAgYnkgYWNjZXNzaW5nIHRoaXMgd2Vic2l0ZTogICpodHRwOi8vd3d3LnItcHJvamVjdC5vcmcvKgpUaGUgIGRvd25sb2FkICBsaW5rICB3aWxsICB0YWtlICB5b3UgIHRvICBhICBsaXN0ICBvZiAgQ1JBTiAgbWlycm9ycyAg4oCTICBwaWNrICBhIG1pcnJvcjogZS5nLiBTb3V0aCBBZnJpY2EgKGZvciBhIGxpc3Qgb2YgdGhlIG1pcnJvcnMgKmh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL21pcnJvcnMuaHRtbCopLgoKRG93bmxvYWQgIFIgIHN0dWRpbyAtIGZyZWUgb3B0aW9uOyAgKmh0dHA6Ly93d3cucnN0dWRpby5jb20vaWRlL2Rvd25sb2FkLyouCgpSIHN0dWRpbyBpcyBjb21wb3NlZCBieSAqKjQgcGFuZWxzKio6ICoqMT0qKlRvcCBMZWZ0LCAqKjI9KipUb3AgUmlnaHQsICoqMz0qKkJvdHRvbSBMZWZ0LCBhbmQgKio0PSoqQm90dG9tIHJpZ2h0LiBOb3RlIHRha2luZyBoYXBwZW5zIGluICoqUGFuZWwgMSoqLiAqKlBhbmVsIDIqKiBoYXMgInlvdXIgZW52aXJvbm1lbnQiLCBldmVyeSB0aW1lIHlvdSBvcGVuIFIsIHlvdSByZWFkIGRhdGEgb3IgY3JlYXRlIGFueSBraW5kIG9mIG9iamVjdCBpbiBSIGl0IHdpbGwgYmUgbGlzdGVkIGluIHlvdXIgKioqRW52aXJvbm1lbnQqKiogdGFiLiBBbnkgY29kZSB5b3UgcnVuIGluICoqUGFuZWwgMyoqIHdpbGwgYXBwZWFyIGFsc28gaW4gUGFuZWwgMiwgdW5kZXIgKioqSGlzdG9yeSoqKiBhbmQgYW55dGhpbmcgdGhhdCB5b3UgdmlzdWFsaXplIGFuZCBtb3JlIHdpbGwgYmUgaW4gKipQYW5lbCA0KiouIFdlIHdpbGwgZGVsdmUgbW9yZSBpbnRvIHRoZSBkZXRhaWxzIHNvb24uCgoqWW91IHdpbGwgdGhlbiBuZWVkIHRvIHNldCB5b3VyIHdvcmtpbmcgZGlyZWN0b3J5IGluIHlvdXIgbG9jYWwgY29tcHV0ZXIgaWYgeW91IGNob3NlIHRoZSBvcHRpb24gdG8gZG93bmxvYWQgUi4qCgpBIHdvcmtpbmcgZGlyZWN0b3J5IGlzIHRoZSBmb2xkZXIgaW4geW91ciBjb21wdXRlciB3aGVyZSBhbGwgYXZhaWxhYmxlIGRhdGEgYXJlICYgcmVzdWx0cyB3aWxsIGJlIHNhdmVkLlRvIGZpbmQgb3V0IHRoZSBjdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5LCB0eXBlIGdldHdkKCkgYW5kIGhpdCBFTlRFUi5UbyBzZXQgYSBuZXcgd29ya2luZyBkaXJlY3RvcnksIHlvdSB3aWxsIHNwZWNpZnkgdGhlIGNvbXB1dGVyIHBhdGggdG8gYSBmb2xkZXIsIGZvciBleGFtcGxlICpzZXR3ZCgifi9Ecm9wYm94L1VTQiIpKi4gWW91IGNhbiBhbHNvIHVzZSB0aGUgbm9uLXByb2dyYW1taW5nIG9wdGlvbiBieSBmb2xsb3dpbmcgdGhlIGRyb3AtZG93biBtZW51IG9uIFIgU3R1ZGlvOiBjbGljayBvbiB0aGUgdGFiIGNhbGxlZCAqU2Vzc2lvbiogLT4gKlNldCBXb3JraW5nIERpcmVjdG9yeSogLT4gKkNob29zZSBEaXJlY3RvcnkqIGFuZCBqdXN0IHNlbGVjdCB0aGUgZm9sZGVyIG9mIHlvdXIgY2hvaWNlIGluIHlvdXIgY29tcHV0ZXIuCgojIyMgU3RlcCAyOiBMZWFybiB0aGUgSGVscCBDb21tYW5kCgoqKipQcmFjdGljZSBtYWtlcyBwZXJmZWN0KioqICBBIHdheSB0byBsZWFybiBpcyBieSBkZWNpcGhlcmluZyBlcnJvciBtZXNzYWdlcyEgClNvLCBpZiB5b3UgZ2V0IGFuIGVycm9yIG1lc3NhZ2UsIHdoaWNoIGlzIHRoZSBvdXRwdXQgc2hvd2luZyBvbiByZWQgZm9udCwgZG9uJ3QgcGFuaWMhIENvbXB1dGF0aW9uYWwgYmlvbG9naXN0cyBhcmUgY29uc3RhbnRseSBmaWd1cmluZyBvdXQgd2hhdCBlcnJvciBtZXNzYWdlcyBtZWFuIGFuZCB3aHkgZG8gd2UgZ2V0IHRoZW0uIEFuIGVmZmVjdGl2ZSB3YXkgdG8gZG8gdGhpcyBpcyB0byAqKmdvb2dsZSoqIHlvdXIgZXJyb3IgbWVzc2FnZS4gT2Z0ZW4gc29tZW9uZSBoYXMgYWxyZWFkeSBmb3VuZCBhIHNvbHV0aW9uIGFuZCB0aGVyZSBpcyBhIHRvbiBvZiBoZWxwIG9ubGluZSEgTm93IHNpbmNlIHdlIGFyZSBsZWFybmluZyBob3cgdG8gY29kZSwgd2UgY2FuIGFzayBSIGZvciBoZWxwIHVzaW5nIGEgc3BlY2lmaWMgZnVuY3Rpb24gaW4gYSBwYWNrYWdlIGJ5IGNhbGxpbmcgaW4gUidzIGJ1aWx0LWluIGhlbHAgZnVuY3Rpb24sIG9yIGJ5IGRpcmVjdGx5IHR5cGluZyBhIHF1ZXN0aW9uIG1hcmsgYmVmb3JlIHRoZSBmdW5jdGlvbiB5b3UgYXJlIHRyeWluZyB0byB1c2UuCgpgYGB7ciwgZXZhbD1GQUxTRX0KI1lvdSB3YW50IHRvIGxlYXJuIHdoYXQgdGhlIGZ1bmN0aW9uICJoZWxwKCkiIGRvZXMgaW4gUgo/aGVscCgpCmhlbHAoKSAKYGBgCgoqKipRdWVzdGlvbiAxOioqKiBIb3cgd291bGQgeW91IGFjY2VzcyBidWlsdC1pbiBoZWxwIGFib3V0IHRoZSBSIHBhY2thZ2UgKmRwbHlyKiwgdGhpcyBpcyBhIGNvbW1vbmx5IHVzZWQgcGFja2FnZSBpbiBkYXRhIHdyYW5nbGluZywgbWFuYWdlbWVudCBvciByZWFycmFuZ2luZyAoKmh0dHBzOi8vZHBseXIudGlkeXZlcnNlLm9yZy8qKS4gIAoqKipBLyoqKgoKIyMjIFN0ZXAgMzogRG8gYmFzaWMgY2FsY3VsYXRpb25zClIgaXMgbGlrZSBhIHNtYXJ0cGhvbmUsIGFuZCBpdHMgYnVpbHQtaW4gcGFja2FnZSBjYWxsZWQgKipiYXNlKiogY2FuIGRvIGV2ZXJ5dGhpbmcgY2FsY3VsYXRvcnMgZG8gJiBtdWNoIG1vcmUhIExldCdzIGV4cGxvcmUgdXNpbmcgUiBhcyBhIGNhbGN1bGF0b3IuCgpMZXQncyB1c2UgUiB0byBkbyBzb21lIHNpbXBsZSBjYWxjdWxhdGlvbnM6CmBgYHtyLCBldmFsPUZBTFNFfQojU3VtCjMgKyAzCgojRXhwb25lbnRpYWwKMl4tNwoKI2xvZyBmdW5jdGlvbgo/bG9nKCkgI2FkZCBhIHF1ZXN0aW9uIG1hcmsgYmVmb3JlIGEgZnVuY3Rpb24gdG8gbGVhcm4gYWJvdXQgd2hhdCBpdCBkb2VzLgpsb2coMikKYGBgCioqKlF1ZXN0aW9uIDI6KioqIFdoYXQgdHlwZSBvZiBsb2dhcml0aG0gKGUuZy4gbmF0dXJhbCBsb2csIGNvbW1vbiBsb2ctYmFzZSAxMCwgb3IgYmluYXJ5IGxvZ2FyaXRobSkgZG9lcyB0aGUgbG9nIGZ1bmN0aW9uIGNvbXB1dGVzPyAgCioqKkEvKioqIAoKKioqQnV0IHRoZW4gd2h5IHVzaW5nIFIgYW5kIG5vdCBhIGNhbGN1bGF0b3I/KioqCkluIFIsIGFueW9uZSBjYW4gY3JlYXRlIHNvIGNhbGxlZCAqKmZ1bmN0aW9ucyoqIHRvIGNyZWF0ZSBwbG90cywgbWFwcywgZmlndXJlcywgb3JnYW5pemUgZGF0YSBiYXNlcywgY29uZHVjdCBzdGF0aXN0aWNhbCBhbmFseXNlcywgbWFrZSBwcmVzZW50YXRpb25zLCBidWlsZCB3ZWJzaXRlcywgYW5hbHl6ZSB3aG9sZSBnZW5vbWUgc2VxdWVuY2VzLCBhbW9uZyBvdGhlcnMuCgojIyMgU3RlcCA0OiBGYW1pbGlhcml6ZSB5b3Vyc2VsZiB3aXRoIHBhY2thZ2VzIGFuZCB2ZXJzaW9ucyAKRnVuY3Rpb25zIGFyZSBjb21waWxlZCBpbnRvICoqcGFja2FnZXMqKiAgKHJlbWVtYmVyIHRvIHRoaW5rIG9mIHRoZXNlIGFzIHRoZSBhcHBzIGluIGEgc21hcnRwaG9uZSkgcHVibGlzaGVkIGludG8gdGhlIENvbXByZWhlbnNpdmUgUiBBcmNoaXZlIE5ldHdvcmsgKENSQU4pLCBSJ3MgY2VudHJhbCBzb2Z0d2FyZSByZXBvc2l0b3J5IGhvc3RlZCBieSB0aGUgUiBmb3VuZGF0aW9uLiBJbiBNYXJjaCAyMDIyLCB0aGVyZSB3ZXJlIDE4LDk0OCBSIHBhY2thZ2VzIG1hZGUgYXZhaWxhYmxlIHRocm91Z2ggQ1JBTi4gKCpodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvKikKCldoZW4gdXNpbmcgUiBvciBSIHN0dWRpbywgeW91IGNhbiBmaW5kIGFsbCB0aGUgYnVpbHQtaW4gcGFja2FnZXMgdW5kZXIgKipQYWNrYWdlcyoqIGluIFBhbmVsIDQuIFRvIHNlYXJjaCBmb3IgYSBzcGVjaWZpYyBwYWNrYWdlIHlvdSBjYW4gc2VsZWN0ICJJbnN0YWxsIiwgdGhpcyBvcGVucyBhIG5ldyB3aW5kb3cgaW4gd2hpY2ggeW91IG1heSBzZWxlY3QgdGhlIENSQU4gcmVwb3NpdG9yeSAocmVjb21tZW5kZWQgb3B0aW9uKSBhbmQgc2VhcmNoIHRoZSBuYW1lIG9mIHRoZSBwYWNrYWdlIGJ5IHR5cGluZyB0aGUgbmFtZSBvZiBpdCB1bmRlciAqKlBhY2thZ2VzIChzZXBhcmF0ZSBtdWx0aXBsZSB3aXRoIHNwYWNlIG9yIGNvbW1hKSoqLiBNYWtlIHN1cmUgdGhhdCB1bmRlciAiSW5zdGFsbCB0byBMaWJyYXJ5IiAtPiB5b3UgdXNlIHRoZSBkZWZhdWx0IGxvY2F0aW9uIHRvIGluc3RhbGwgUiBwYWNrYWdlcyBhbmQgZG91YmxlIGNoZWNrIHRoYXQgdGhlIGJveCBmb3IgImluc3RhbGwgZGVwZW5kZW5jaWVzIiBpcyB0aWNrZWQuIFdlIGNhbiBhbHNvIGluc3RhbGwgcGFja2FnZXMgYnkgY29kaW5nIGluIHRoZSBjb25zb2xlICgqKlBhbmVsIDMqKikuCgpGb3IgaW5zdGFuY2Ugc2VhcmNoIHRoZSBwYWNrYWdlIGNhbGxlZCAqKmdncGxvdDIqKiB1c2VkIHRvIGNyZWF0ZSBlbGVnYW50IGdyYXBocy9wbG90cyB1c2luZyB5b3VyIGRhdGEuIFRoZSBhbW91bnQgb2YgZnJlZWx5IGF2YWlsYWJsZSB0dXRvcmlhbHMgdmFyaWVzIGEgbG90IGFtb25nIHBhY2thZ2VzLCBzb21lIHBsb3R0aW5nIHBhY2thZ2VzIGxpa2UgZ2dwbG90IGhhdmUgbG90cyBvZiB0dXRvcmlhbHMgb25saW5lIHdoZXJlYXMgbW9yZSBzcGVjaWZpYyBwYWNrYWdlcyB3aWxsIGhhdmUgc3BhcnNlIGluZm8uIFlldCwgYWxtb3N0IGFsbCBwYWNrYWdlcyBoYXZlIGEgdXNlciBndWlkZSBhdmFpbGFibGUgb25saW5lIG9yIGJ5IHNpbXBseSBjbGlja2luZyBvbiB0aGUgbmFtZSBvZiB0aGUgcGFja2FnZSBpbiBQYW5lbCA0LCB1bmRlciB0aGUgKipQYWNrYWdlcyoqIHRhYiwgb3IgdGhlICoqaGVscCgpKiogZnVuY3Rpb24gd2UgZXhhbWluZWQgZWFybGllci4KCmBgYHtyLCBldmFsPUZBTFNFfQojRXhhbXBsZSBpbnN0YWxsaW5nIHBhY2thZ2VzIGluIFIKaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpICN1c2VkIHRvIGNyZWF0ZSBuaWNlIHBsb3RzCmluc3RhbGwucGFja2FnZXMoImRwbHlyIikgI3VzZWQgdG8gZG8gZGF0YSBtYW5hZ2VtZW50Cmluc3RhbGwucGFja2FnZXMoInRpZHlyIikgI3VzZWQgdG8gdGlkeSBtZXNzeSBkYXRhCmluc3RhbGwucGFja2FnZXMoInRpYmJsZSIpICN1c2VkIHRvZ2V0aGVyIHdpdGggZHBseXIgdG8gbWFrZSBzaW1wbGUgZnJhbWVzCmluc3RhbGwucGFja2FnZXMoImV4cGxvcmUiKSAjdXNlZCB0byBkbyBleHBsb3JhdG9yeSBhbmFseXNlcwppbnN0YWxsLnBhY2thZ2VzKCJwYXRjaHdvcmsiKSAjY3JlYXRlcyBtdWx0aXBsb3RzIC8gY29tcG9zZXIgb2YgcGxvdHMKaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikKbGlicmFyeSgidGlkeXZlcnNlIikKbGlicmFyeSgiZ2dwbG90MiIpICNSdW5uaW5nIHRoZSBsaWJyYXJ5KCkgY29tbWFuZCAiYWN0aXZhdGVzIiB0aGUgcGFja2FnZXMKbGlicmFyeSgiZHBseXIiKQpsaWJyYXJ5KCJ0aWR5ciIpCmxpYnJhcnkoInRpYmJsZSIpCmxpYnJhcnkoImV4cGxvcmUiKQpsaWJyYXJ5KCJwYXRjaHdvcmsiKQpgYGAKCkl0IHdpbGwgYmVjb21lIHRyaWNreSB0byBtYW5hZ2UgcGFja2FnZXMgaWYgdGhlc2UgcmVxdWlyZSBkaWZmZXJlbnQgUiB2ZXJzaW9ucyAoanVzdCBsaWtlIHNvbWUgYXBwcyBpbiB5b3VyIHNtYXJ0cGhvbmVzIHRoYXQgc3RvcHBlZCBiZWluZyBzdXBwb3J0ZWQgaW4gb2xkIHNtYXJ0cGhvbmVzKS4gSXQgaXMgaW1wb3J0YW50IHRvIGtlZXAgdGhlIHBhY2thZ2VzIHlvdSBvZnRlbiBuZWVkIG9yZ2FuaXplZCBhbmQgb25seSBsb2FkIHRob3NlIHRoYXQgeW91IHdpbGwgdXNlLCB0byBhdm9pZCBhbnkgcHJvYmxlbXMuIEFsc28sIHNpbmNlIHRoZSBjb21tdW5pdHkgaXMgYWN0aXZlbHkgZGV2ZWxvcGluZyAqKmZyZWUqKiBwYWNrYWdlcywgdGhlcmUgd2F5cyB0byBpbnN0YWxsIHRoZXNlIGFyZSBnZXR0aW5nIGVhc2llciBhbmQgZWFzaWVyLgoKIyMjIFN0ZXAgNTogRmFtaWxpYXJpemUgeW91cnNlbGYgd2l0aCBvYmplY3RzIGluIFIKUiBwcm9ncmFtbWluZyBsYW5ndWFnZSByZWNvZ25pemVzIGEgaGFuZGZ1bCBvZiBmdW5kYW1lbnRhbCAqdW5pdHMqIHVzZWQgdG8gcGVyZm9ybSBkaWZmZXJlbnQgYWN0aW9ucywgd2UgY2FsbCB0aG9zZSAqb2JqZWN0cyouIFRoZSBtYWluIHR5cGVzIG9mIG9iamVjdHMgaW4gciBhcmU6CgoqKkZ1bmN0aW9uczoqKiBJbiBSLCBhIGZ1bmN0aW9uIGlzIGFuIG9iamVjdCB0aGF0IHdlIHdpbGwgKmNvZGUqLiBUaGluayBvZiB0aGlzIGFzIGEgdGFzayB5b3Ugd2FudCB0aGUgY29tcHV0ZXIgdG8gZG8gZm9yIHlvdS4gV2Ugd2lsbCB1c2UgZnVuY3Rpb25zIGJ5IHNwZWNpZnlpbmcgaW5zdHJ1Y3Rpb25zIHVzaW5nICphcmd1bWVudHMqIChpbnNpZGUgb2YgdGhlIHBhcmVudGhlc2VzKSB0aGF0IG1heSBiZSBuZWNlc3NhcnkgZm9yIHRoZSBmdW5jdGlvbiB0byBhY2NvbXBsaXNoIHRoZSBhY3Rpb25zLiBUaGUgYmFzaWMgc3ludGF4IG9mIGEgZnVuY3Rpb24gY2FuIGxvb2sgYXMgc2ltcGxlIGFzIHRoaXM6ICpoZWxwKCkqIG9yICpsb2coeCxiYXNlPXkpKi4KCioqVmVjdG9yczoqKiBWZWN0b3JzIGFyZSB2YXJpYWJsZXMsIG9yIHNlcmllcyBvZiB2YWx1ZXMgb2YgdGhlIHNhbWUgY2xhc3MsIHRoZXkgY2FuIGJlIGNvbnRpbnVvdXMgKCJudW1lcmljIiksIGNhdGVnb3JpY2FsICgiZmFjdG9yIikiLCBldGMuCgoqKkRhdGEgRnJhbWVzIGFuZCBUaWJibGVzOioqIEEgZGF0YSBmcmFtZSBpcyBhIG1hdHJpeCBjb21wb3NlZCBieSB2YXJpYWJsZXMsIGJ1dCBmb3JtYXR0aW5nIHZhcmlhYmxlcyBhcyBhIGRhdGEgZnJhbWUgYWxsb3dzIGhhbmRsaW5nIHZlcnNhdGlsaXR5IGluIHlvdXIgUiBzdHVkaW8gZW52aXJvbm1lbnQuIE1hbnkgZnVuY3Rpb25zIHJlcXVpcmUgZm9ybWF0dGluZyB5b3VyIGRhdGEgYXMgZGF0YSBmcmFtZS4gV2Ugb2Z0ZW4gbmVlZCB0byB0cnkgb3V0IGRpZmZlcmVudCB3YXlzIHRvIHJlLW9yZ2FuaXplIG91ciBkYXRhLCBzbyB0byBkbyB0aGlzIHdlIHdpbGwgdGFrZSBhZHZhbnRhZ2Ugb2YgYSBuZXcsIHNpbXBsZXIgYW5kIHZlcnNhdGlsZSB2ZXJzaW9uIG9mIHRoZSAqZGF0YSBmcmFtZSogb2JqZWN0IGNhbGxlZCB0aGUgKnRpYmJsZSogdG8gYmUgdXNlZCBhbG9uZyB3aXRoIHRoZSBwYWNrYWdlICpkcGx5ciouIAoKKipMaXN0OioqIEEgbGlzdCBjYW4gY29tcHJpc2UgYWxsIHNvcnRzIG9mIG9iamVjdCB0eXBlcy4gRmV3IGZ1bmN0aW9ucyByZXF1aXJlIGRhdGEgYXMgbGlzdHMuCgoqKk90aGVyOioqIE90aGVyIGxlc3MgZnJlcXVlbnRseSB1c2VkIG9iamVjdHMgaW5jbHVkZTogc2NhbGFycyAoYSBzaW5nbGUgdmFsdWUpLCBtYXRyaWNlcyAoc2ltaWxhciB0byBkYXRhIGZyYW1lLCBidXQgYWxsb3cgb2JqZWN0cyB3aXRoIHZhcnlpbmcgbGVuZ3RocykuCgpMZXQncyBleHBsb3JlIHRoZXNlIGluIFI6CmBgYHtyLGV2YWw9RkFMU0V9CiNPYmplY3QKeCA8LSAzICsgNQp4CgojVmVjdG9yCnkgPC0gYygxLCAyLCAzLCA0LCA1KSAKeQoKc2VxKDEsMTAsIGJ5ID0gMSkjQ3JlYXRlcyBhIHNlcXVlbmNlIGZvbGxvd2luZyBzcGVjaWZpYyBydWxlcyAKCnZlY3RvcjE8LXNlcSgxLCAxMCwgIGJ5ID0gMSkKdmVjdG9yMjwtc2VxKDEsIDIwLCBieSA9IDIpCnZlY3RvcjM8LXNlcSgxLCAzMCwgIGJ5ID0gMykKdmVjdG9yNDwtYygiQSIsICJCIiwgIkMiLCAiRCIsICJFIiwgIkYiLCJHIiwgIkgiLCAiSSIsICJKIikKCiNEYXRhIGZyYW1lCmRmMTwtZGF0YS5mcmFtZSh2ZWN0b3IxLHZlY3RvcjIsdmVjdG9yMywgdmVjdG9yNCkKCiNUaWJibGUKdGliYmxlMTwtdGliYmxlOjp0aWJibGUoZGYxKQoKI0xpc3QKbGlzdDE8LSBsaXN0KGRmMSwgdmVjdG9yMSwgdmVjdG9yMiwgdmVjdG9yMywgdmVjdG9yNCwgeCwgeSkgCgojTm90ZSB0aGF0IGdpdmluZyBhIG5hbWUgKGUuZywgImRmMSIpIHdpbGwgaGF2ZSBkb3duc3RyZWFtIGltcGxpY2F0aW9ucy4KI0l0IGlzIGltcG9ydGFudCB0byBnaXZlIHlvdXIgb2JqZWN0cyB1bmlxdWUsIGludHVpdGl2ZSwgc2hvcnQgJiBzaW1wbGUgbmFtZXMuCgpgYGAKKioqUXVlc3Rpb24gMzoqKiogV2hhdCBpcyBhbiBhZHZhbnRhZ2UgYW5kIGEgZGlzYWR2YW50YWdlIG9mIHVzaW5nIGEgbGlzdD8gIAoqKipBLyoqKgoKIyMjIFN0ZXAgNjogRmFtaWxpYXJpemUgeW91cnNlbGYgd2l0aCBmdW5jdGlvbnMgaW4gUgpIZXJlIHRyeSB0byBmaW5kIGEgZmV3IG1vcmUgb2YgdGhlIG1hbnkgYnVpbHQtaW4gZnVuY3Rpb25zIGluIHIsIGZvciBleGFtcGxlOgpgYGB7cixldmFsPUZBTFNFfQojQ2FsY3VsYXRlIG1lYW4KP21lYW4KbWVhbih2ZWN0b3IxKQojU3VtIHZhbHVlcyBpbiBhIHZlY3RvciB1c2luZwo/c3VtCnN1bSh2ZWN0b3IyKQoKI0lmIHdlIHdhbnQgdG8gYnVpbGQgYSBkYXRhIGZyYW1lIHdlICpuZWVkKiB0byBoYXZlIGEgc2V0IG9mIHZlY3RvcnMgYWxsIG9mIHRoZSBzYW1lIGxlbmd0aCAKI0ZpZ3VyZSBvdXQgbGVuZ3RoIG9mIGEgdmVjdG9yOgpsZW5ndGgodmVjdG9yMykKI1JldHJpZXZlIHVuaXF1ZSB2YWx1ZXMgaW4gdmVjdG9yCnVuaXF1ZSh2ZWN0b3I0KQojU29ydCB2YWx1ZXMgaW4gYSB2ZWN0b3IgCmRmMSR2ZWN0b3I1PC1zb3J0KHZlY3RvcjQsIGRlY3JlYXNpbmcgPSBUUlVFKQojU2FtcGxlIDYgdmFsdWVzIGF0IHJhbmRvbSBmcm9tIGEgbnVtZXJpYyB2ZWN0b3IKc2FtcGxlKHZlY3RvcjMsIDMpCiNTYW1wbGUgNCBsZXR0ZXJzIGF0IHJhbmRvbSBmcm9tIGEgY2hhcmFjdGVyIHZlY3RvcgpzYW1wbGUodmVjdG9yNCwgNCkKYGBgCioqKlF1ZXN0aW9uIDQ6KioqIEhvdyB3b3VsZCB5b3UgbW9kaWZ5IHRoZSAqc2FtcGxlKCkqIGZ1bmN0aW9uIHRvIHNhbXBsZSBvbmx5IHRocmVlIHZhbHVlcyBhdCByYW5kb20sIGFsbG93aW5nIGEgZ2l2ZW4gbnVtYmVyIG9yIGNoYXJhY3RlciB0byBhcHBlYXIgbW9yZSB0aGFuIG9uY2U/ICAKKioqQS8qKioKCllvdSBjYW4gYWxzbyB1c2UgUiB0byBwbG90IGZ1bmN0aW9ucyBqdXN0IGFzIG1vc3Qgc2NpZW50aWZpYyBjYWxjdWxhdG9ycyBkby4gQnV0IGJlZm9yZSBjb2RpbmcgcGxvdHMsIHdlIHdpbGwgbGVhcm4gYSBmZXcgbW9yZSBSIGNvbW1hbmRzIHRvIGV4dHJhY3QgaW5mb3JtYXRpb24gZnJvbSBkYXRhIGZyYW1lcyBvciBzaW1pbGFyIG9iamVjdHMuCgojIyMgU3RlcCA3OiBQcmFjdGljZSB1c2luZyBkYXRhIGZyYW1lcwpWZXJ5IG9mdGVuIHdlIHdhbnQgdG8gc3VtbWFyaXplLCB2aXN1YWxpemUsIHNpbXVsYXRlIG9yIGFuYWx5emUgZXhpc3RpbmcgZGF0YSwgZm9yIHRoYXQsIG9uZSBjYW4gc3RhcnQgYnkgdXNpbmcgdGhlIGRhdGEgZnJhbWUgZm9ybWF0IGluIFIuIEhlcmUgd2UgYXJlIGdvaW5nIHRvIGV4cGxvcmUgZnVuY3Rpb25zIHVzaW5nIHZlcnkgYmFzaWMgZGF0YSBmcmFtZXMsIHRvIGxlYXJuIG1vcmUgYWJvdXQgaG93IHRoZSBkYXRhIGxvb2sgbGlrZS4KCk5vdGUgdGhhdCBpbiBSIHN0dWRpbywgZ29pbmcgdG8gKipQYW5lbCAyKiogYW5kIHNpbXBseSBjbGlja2luZyBvbiBhIGdpdmVuIGRhdGEgZnJhbWUsIHdpbGwgcmV0cmlldmUgYWxsIGl0cyBjb250ZW50cyBpbiBhIG5ldyB0YWIgaW4gKipQYW5lbCAxKiouCgpgYGB7cixldmFsPUZBTFNFLGVjaG89RkFMU0UscmVzdWx0cz0naGlkZSd9CiNWaWV3IGRhdGEgYnkgc2ltcGx5IGNhbGxpbmcgdGhlIGRhdGEgZnJhbWUgaW4gdGhlIGNvbnNvbGUKZGYxICNOb3RlOiBpZiB0aGlzIGlzIHRvbyBsYXJnZSwgaXQgd2lsbCBvbmx5IGRpc3BsYXkgYSBzdWJzZXQKVmlldyhkZjEpICNUaGlzIHdpbGwgb3BlbiBhIHdpbmRvdyB3aXRoIGEgZGF0YSBmcmFtZQpoZWFkKGRmMSkgI1RvIHNlZSBvbmx5IHRoZSBmaXJzdCByb3dzCnRhaWwoZGYxKSAjVG8gc2VlIG9ubHkgdGhlIGxhc3Qgcm93cwoKI0xlYXJuIHRoZSBkaW1lbnNpb25zIG9mIGFuIGV4aXN0aW5nIGRhdGEgZnJhbWUKZGltKGRmMSkgI2RpbWVuc2lvbnMgY2FuIGFsc28gYmUgZm91bmQgaW4gUGFuZWwgMgoKI0FyZSB0aGVyZSBtaXNzaW5nIHZhbHVlcyBpbiBteSBkYXRhPwppcy5uYShkZjEpICMgQW5zd2VyOiBGYWxzZQoKI0FkZCBhIG5ldyBjb2x1bW4gdG8gZXhpc3RpbmcgZGF0YSBmcmFtZQpkZjEkQmluYXJ5MTwtYygxLDAsMSwwLDEsMCwxLDAsMSwwKQoKI0FkZCBhIG5ldyBjb2x1bW4gd2l0aCBtaXNzaW5nIHZhbHVlcyB0byBleGlzdGluZyBkYXRhIGZyYW1lCiNNaXNzaW5nIHZhbHVlcyBzaG91bGQgYmUgc2ltcGx5IGVudGVyZWQgYXM6IE5BCmRmMSRDb250PC1jKDAuMSwwLjIsMC4zLE5BLDAuNSwwLjYsMC43LDAuOCwwLjksMSkKaXMubmEoZGYxJENvbnQpICNNaXNzaW5nIHZhbHVlPwojISEhISFOb3RlOiBhbHdheXMgZW50ZXIgYSBtaXNzaW5nIHZhbHVlIGFzOiBOQQoKI0ZpZ3VyZSBvdXQgd2hhdCBSIHRoaW5rcyB0aGUgdmFyaWFibGVzIGFyZToKc3RyKGRmMSkKI05vdGUgdGhhdCB3ZSBuYW1lZCBzb21lIHZhcmlhYmxlcyAKI2ltcGx5aW5nIHRoYXQgdGhleSBhcmUgY29udGludW91cyAoZm9yIGV4YW1wbGUgQ29udDEpCgojVmVyeSBvZnRlbiB3ZSBuZWVkIHRvIHNwZWNpZnkgdGhlIGtpbmQgb2YgdmFyaWFibGVzIHRvIFIKCiNUbyBjaGFuZ2UgY29sdW1uIG5hbWVzIHRvIGV4aXN0aW5nIGRhdGEgZnJhbWUKY29sbmFtZXMoZGYxKTwtYygiQ29udDEiLCAgIkNvbnQyIiwgICJDb250MyIsICAiQ2F0MSIsIkNhdDIiLCAiQmluYXJ5MSIsIkNvbnQ0IikgCgojVG8gc3BlY2lmeSBhIGdpdmVuIHZhcmlhYmxlIGFzIGNvbnRpbnVvdXMKZGYxJENvbnQxPC1hcy5pbnRlZ2VyKGRmMSRDb250MSkgI2FsdGVybmF0aXZlIGFzLmludGVnZXIoKQpzdHIoZGYxKSAjTm90ZSB0aGF0IHRoaXMgY2hhbmdlZCB0aGUgc3RydWN0dXJlIG9mIG91ciBkYXRhIGZyYW1lCmRmMSRDb250MjwtYXMuaW50ZWdlcihkZjEkQ29udDIpIApkZjEkQ29udDM8LWFzLmludGVnZXIoZGYxJENvbnQzKSAKI1RvIHNwZWNpZnkgYSBnaXZlbiB2YXJpYWJsZSBhcyBjYXRlZ29yaWNhbApkZjEkQ2F0MTwtYXMuZmFjdG9yKGRmMSRDYXQxKSAKZGYxJENhdDI8LWFzLmZhY3RvcihkZjEkQ2F0MikgCmRmMSRCaW5hcnkxPC1hcy5mYWN0b3IoZGYxJEJpbmFyeTEpIApkZjEkQ29udDQ8LWFzLm51bWVyaWMoZGYxJENvbnQ0KSAKc3RyKGRmMSkKCiNTdW1tYXJpemUgYWxsIHZhcmlhYmxlcyBpbiB0aGUgZGF0YSBmcmFtZQpzdW1tYXJ5KGRmMSkKCmBgYAoKKioqUXVlc3Rpb24gNToqKiogSG93IHdvdWxkIHlvdSBtb2RpZnkgb25lIG9mIHRoaXMgZnVuY3Rpb25zIChlLmcuICptZWFuKCkqKSB0byBkZWFsIHdpdGggbWlzc2luZyB2YWx1ZXM/ICAKKioqQS8qKioKCiMjIyBTdGVwIDg6IFByYWN0aWNlIGV4cG9ydGluZyBkYXRhIGZyYW1lCklmIHlvdSB3YW50IHRvIHNhdmUvZXhwb3J0IHRoZSBkYXRhIGZyYW1lIHlvdSBjcmVhdGVkIGluIFIsIHlvdSBqdXN0IG5lZWQgdG8gY2FsbCBhIGZ1bmN0aW9uIG5hbWVkICp3cml0ZS5jc3YqLiBUbyBleHBvcnQgeW91ciBkYXRhIGZyYW1lLCBqdXN0IG5hbWUgdGhlIGZpbGUuIEkgcmVjb21tZW5kIHlvdSBzYXZlIHlvdXIgdHJhZGl0aW9uYWwgZGF0YSBmaWxlcyAoYWthLiAqZXhjZWwtbGlrZSogdGFibGVzKSB0byB1c2UgaW4gUiBhcyBhICoqKi5jc3YqKiogKCoqYyoqb21tYS0qKnMqKmVwYXJhdGVkICoqdioqYWx1ZXMpIGZpbGUgZm9ybWF0LgoKYGBge3IsZXZhbD1GQUxTRX0KI0V4cG9ydGluZyBkYXRhCndyaXRlLmNzdihkZjEsICJkZl8yMDIyanVsMi5jc3YiKSAKCmBgYAoqKipRdWVzdGlvbiA2OioqKiBXaGVyZSBpcyB0aGUgZmlsZSBzYXZlZD8gVXNlIHRoZSBnZXR3ZCgpIGZ1bmN0aW9uIHRvIGZpbmQgb3V0LiBIb3cgY2FuIHlvdSBleHBvcnQgdGV4dCBvciBhIGxpc3QgdGhhdCB3YXMgY3JlYXRlZCB1c2luZyBSPyAgCioqKkEvKioqCgojIyMgU3RlcCA5OiBQcmFjdGljZSBpbXBvcnRpbmcgZGF0YSBpbiBSClZlcnkgb2Z0ZW4gd2UgaGF2ZSBkYXRhIHRoYXQgd2Ugd2FudCB0byBpbXBvcnQgaW50byBSLCB0aGVyZSBhcmUgc2V2ZXJhbCBmb3JtYXRzIHRoYXQgYXJlIGNvbXBhdGlibGUgd2l0aCBSLiAgRGF0YSB0YWJsZXMgY2FuIGJlIGdlbmVyYXRlZCBpbiBSIG9yIG90aGVyIHNvZnR3YXJlLCBmb3IgZXhhbXBsZTogIGV4Y2VsLCBzdGF0aXN0aWNhbCBzb2Z0d2FyZSBvciBnb29nbGUgc2hlZXRzIChmcmVlKS4gV2hlbiBkYXRhIGlzIG5vdCBnZW5lcmF0ZWQgaW4gUiwgZGF0YSwgY2FuIHN0aWxsIGVhc2lseSBiZSBpbXBvcnRlZCBidXQgdGhlcmUgYXJlIGRpc3RpbmN0IHdheXMgdG8gaW1wb3J0IGZpbGVzIGRlcGVuZGluZyB0aGUgZm9ybWF0IG9mIHRoZSBkYXRhIHRvIGJlIGltcG9ydGVkLiBDb21tb24gZm9ybWF0cyBpbmNsdWRlIGRhdGEgYXM6IHRleHQgb3IgKi50eHQqLCBjb21tYSBzZXBhcmF0ZWQgdmFsdWVzIG9yICoqKi5jc3YqKiogYW5kL29yIGFzIGV4Y2VsICoueGxzeCogKG9ubHkgdGhlIGxhdHRlciByZXF1aXJlcyBpbnN0YWxsaW5nIGEgcGFja2FnZSBjYWxsZWQgKi5vcGVueGxzeCouIEkgcmVjb21tZW5kIHRoYXQgeW91IGFsd2F5cyBzYXZlIG9yIGltcG9ydCB0aGUgZGF0YSBhcyAqKiouY3N2KioqLgoKV2UgcHJldmlvdWx5IHNhdmVkIG91ciBkYXRhIGFzIGEgKi5jc3YqLCB0byBpbXBvcnQgdGhlc2UgZGF0YSwgd2UgY2FuIGp1c3QgdXNlIHRoZSAqKnJlYWQuY3N2KCkqKiBmdW5jdGlvbiAqKiotYXMgbG9uZyBhcyB0aGUgZmlsZSBpcyBjb250YWluZWQgaW4gb3VyIGN1cnJlbnQgZm9sZGVyIHVzZWQgYXMgd29ya2luZyBkaXJlY3RvcnkuKioqCgpgYGB7cixldmFsPUZBTFNFfQojSW1wb3J0IGRhdGEgYXMgY3N2CmltcG9ydGVkX2RmMTwtcmVhZC5jc3YoImRmXzIwMjJqdWwyLmNzdiIsIGhlYWRlcj1UKQpgYGAKCiMjIyBTdGVwIDEwOiBDcmVhdGUgcGxvdHMKV2UgY2FuIHVzZSBiYXNlIFIgdG8gY3JlYXRlIHF1aWNrIHBsb3RzIGFuZCBpZGVudGlmeSBwYXR0ZXJucy4gV2UgdGhlbiBjYW4gZXhwb3J0IHRoZXNlIGFzIGEgKioqLnBkZioqKiBmaWxlIGZvcm1hdC4gUGxvdHRpbmcgaXMgb25lIG9mIHRoZSBiaWdnZXN0IHN0cmVuZ3RocyBvZiBSLiBUaGUgcG9zc2liaWxpdGllcyBhcmUgdW5saW1pdGVkIGFuZCB0aGVyZSBpcyBhIHVuaXZlcnNlIG9mIHR1dG9yaWFscyBvdXQgdGhlcmUgdG8gc2hvdyB5b3UgaG93IHRvIGN1c3RvbWl6ZSBwbG90cy4gT3ZlciB0aGUgeWVhcnMgSSBoYXZlIG1vdmVkIG9uIGZyb20gYmFzZSBSIGludG8gdXNpbmcgdGhlIHBhY2thZ2UgKmdncGxvdDIqIHdoaWNoIHdlIHdpbGwgZXhwbG9yZSBuZXh0LiAKCmBgYHtyLGV2YWw9RkFMU0V9CgojRmlyc3Q6IFBsb3R0aW5nIHdpdGggYmFzZSBSCiNQbG90IDEgY29udGludW91cyB2YXJpYWJsZQpoaXN0KHNhbXBsZShzZXEoMToxMDApLDIwMCwgcmVwbGFjZT1UUlVFKSwgYnJlYWtzPTI1LCBtYWluPSIiKSAjTm90ZSBRdWVzdGlvbiA3CgojUGxvdCAyIGNvbnRpbnVvdXMgdmFyaWFibGVzCnBsb3QoZGYxJENvbnQxfmRmMSRDb250MikKCiNQbG90IDEgY29udGludW91cyB2YXJpYWJsZSBhbmQgMSBCaW5hcnkvQ2F0ZWdvcmljYWwKYm94cGxvdChkZjEkQ29udDF+ZGYxJEJpbmFyeTEpCgojVG8gZXhwb3J0IGEgcGRmIGZpbGUgd2l0aCBtdWx0aXBsZSBmaWd1cmVzOgpwZGYoInBsb3RzQV8yMDIyanVsMi5wZGYiKQpoaXN0KHNhbXBsZShzZXEoMToxMDApLDIwMCwgcmVwbGFjZT1UUlVFKSwgYnJlYWtzPTI1LCBtYWluPSIiKQpwbG90KGRmMSRDb250MX5kZjEkQ29udDIpCmJveHBsb3QoZGYxJENvbnQxfmRmMSRCaW5hcnkxKQpkZXYub2ZmKCkKCmBgYAoqKipRdWVzdGlvbiA3OioqKiBXaGF0IGhhcHBlbnMgd2hlbiB3ZSByZW1vdmUgKm1haW49IiIqLiBIb3cgd291bGQgeW91IGdvIGFib3V0IHRvIHJlbmFtZSB5b3VyIHkgYXhpcyBsYWJlbD8gIAoqKipBLyoqKgoKTmV4dCB3ZSB3aWxsIHVzZSBkYXRhIG9uIHRoZSBzdXJ2aXZhbCBzdGF0dXMgb2YgaW5kaXZpZHVhbCBwYXNzZW5nZXJzIG9uIGJvYXJkIG9mIHRoZSAqKipUaXRhbmljKioqIHNoaXAuIFZpc2l0IG15IGdvb2dsZSBkcml2ZSB0byBkb3dubG9hZCB0aGUgdGl0YW5pYyBkYXRhIHNldCAqKi5jc3YqKiBmb3JtYXQ6ICpodHRwczovL2RyaXZlLmdvb2dsZS5jb20vZmlsZS9kLzFqaEd2WGtZU3J0c2dtRW5aMkdCUjZBekJ5MUJVR2JOZy92aWV3P3VzcD1zaGFyaW5nKgoKQWZ0ZXIgc3VjY2Vzc2Z1bGx5IGRvd25sb2FkaW5nICp0cmFpbnMuY3N2KiBmaWxlIHlvdSB3b3VsZCBiZSBhYmxlIHRvIHVzZSB0aGUgKioqVXBsb2FkKioqIG9wdGlvbiBpbiAqKlBhbmVsIDQqKi4gU2ltcGx5IGNob29zZSB0aGUgZmlsZSB0byB1cGxvYWQsIGFuZCBoaXQgKioqT2sqKiouIE9uY2UgeW91IGRvIHRoaXMsIGl0IHdpbGwgYmUgYXZhaWxhYmxlIGluIHlvdXIgZW52aXJvbm1lbnQuCgoKKioqUXVlc3Rpb24gODoqKiogRGlkIHlvdSBnZXQgYW4gZXJyb3IgdHJ5aW5nIHRvIHVwbG9hZCB0aGlzIGRhdGEgZmlsZT8gSG93IGRpZCB5b3UgZ28gYWJvdXQgdG8gZml4IHRoaXMgZXJyb3I/ICAKKioqQS8qKioKYGBge3IsIGV2YWw9RkFMU0V9CiNJbXBvcnQgdGhlIGRhdGEgc2V0CnRpdGFuaWMgPC0gcmVhZC5jc3YoJ3RyYWlucy5jc3YnLHN0cmluZ3NBc0ZhY3RvcnMgPSBGLCBoZWFkZXIgPSBUKQoKI0V4cGxvcmUgdGhlIGRhdGEgc2V0IHVzaW5nIHRoZSBmdW5jdGlvbnMgd2UgbGVhcm5lZCBiZWZvcmUKaGVhZCh0aXRhbmljKSAjdG8gc2VlIGZpcnN0IDEwIHJvd3MgYW5kIGNvbHVtbiBuYW1lcwpzdW1tYXJ5KHRpdGFuaWMpICN0byBnZXQgYSBzdW1tYXJ5IG9mIGVhY2ggY29sdW1uCiMqKipOb3RlIHRoYXQgUiBkZXNjcmliZXMgbWlzc2luZyBkYXRhIGFzICJOQSIKCiNQbG90IHRvIHN1bW1hcml6ZSBwYXNzZW5nZXIgYWdlIHdpdGggYmFzZSBSCmhpc3QobmEub21pdCh0aXRhbmljJGFnZSksY29sPXJhaW5ib3cobGVuZ3RoKDE6OCkpLG1haW49IiIseGxhYj0iYWdlIiwgeWxhYj0iY291bnQiKQoKYGBgCgojIyMgU3RlcCAxMTogIFByYWN0aWNlIHVzaW5nIGdncGxvdDIKQmFzZSBSIHBsb3RzIGNhbiBiZSBtb2RpZmllZCB0byBsb29rIGFzIHByZXR0eS9kZXRhaWxlZCBhcyB5b3Ugd291bGQgbGlrZSB0aGVtIHRvIGxvb2suIEhvd2V2ZXIsIHBhY2thZ2VzIGxpa2UgKipnZ3Bsb3QyKiogbWFrZSBhbGwgdGhlIGhlYXZ5LWxpZnRpbmcgZm9yIHlvdS4gTmV4dCB3ZSB3aWxsIGxlYXJuIGhvdyB0byBtYWtlIGEgZmV3IHNpbXBsZSwgeWV0IHB1YmxpY2F0aW9uLWxldmVsLCAqbmljZSBsb29raW5nIHBsb3RzKiB1c2luZyAqKmdncGxvdDIqKiBhbmQgdGhlIGRhdGEgbWFuYWdlbWVudCBwYWNrYWdlICoqZHBseXIqKi4gVGhpcyB0dXRvcmlhbCBkb2VzIG5vdCBjb3ZlciBkYXRhIHdyYW5nbGluZyB1c2luZyBkcGx5ciwgYnV0IHRoZXJlIGFyZSBtYW55IG91dCB0aGVyZSB0aGF0IGRvIQoKV2UganVzdCBjcmVhdGVkIGEgc2ltcGxlIGhpc3RvZ3JhbSB1c2luZyBiYXNlIFIgdG8gdXNlIGFzIGNvbXBhcmlzb24gd2l0aCB0aGUgc2FtZSBwbG90IGNyZWF0ZWQgdXNpbmcgKmdncGxvdDIqIGFuZCBhc3NvY2lhdGVkIHBhY2thZ2VzLgpgYGB7ciwgZXZhbD1GQUxTRX0KI05vdyBsZXQncyB1c2UgZHBseXIgYW5kIGdncGxvdDIKI1BhcnQgMQojTm90ZSBob3cgdGhlIGJhc2UgUiBncmFtbWFyIHdlIGxlYXJuZWQgZWFybGllciBkaWZmZXJzIGEgbG90IGZyb20gImdncGxvdDIiIGFuZCAiZHBseXIiIChhIHNlcmllcyBvZiBwYWNrYWdlcyBhcyBwYXJ0IG9mIHRoZSAiVGlkeXZlcnNlIikgd2Ugd2lsbCB1c2Ugbm93IHRvIHZpc3VhbGl6ZSB0aGUgc2FtZSBkYXRhOgp0aXRhbmljICU+JSBoZWFkKDEwKSAjT3ZlcnZpZXcgb2YgdGhlIGZpcnN0IDEwIHJvd3MKb25seV8xY2xhc3MgPC0gZmlsdGVyKHRpdGFuaWMsIHBjbGFzcyA9PSAiMSIpICNFeHRyYWN0IHJvd3MgdGhhdCBtYXRjaCBhIGdpdmVuIGNyaXRlcmlhIChsaWtlIHN1YnNldCgpIGluIGJhc2UgUikKY291bnRzdGl0YW5pYzwtIHRpdGFuaWMgJT4lIGNvdW50KHNleCxwY2xhc3MsYWdlLCBzb3J0ID0gVFJVRSkKd2lkZXRpdGFuaWMgPC0gY291bnRzdGl0YW5pYyAlPiUgc3ByZWFkKHNleCxuKSAjU29tZXRpbWVzIHdlIHdhbnQgdG8gaGF2ZSBhICJ3aWRlIiBmb3JtYXQKbG9uZ3RpdGFuaWMgPC0gd2lkZXRpdGFuaWMgJT4lIGdhdGhlcihzZXgsIG4sIGZlbWFsZTptYWxlLCBmYWN0b3Jfa2V5PVRSVUUpI3RoaXMgY2FuIHJldmVyc2UgYmFjayB0byAibG9uZyIKdGl0YW5pYyAlPiUgZGVzY3JpYmVfdGJsKCkgI0Rlc2NyaWJlcyBkYXRhCnN1bW1hcnlfdGl0YW5pYzwtIHRpdGFuaWMgJT4lIGdyb3VwX2J5KHNleCwgcGNsYXNzKSAlPiVkcGx5cjo6c3VtbWFyaXplKE1lYW4gPSBtZWFuKGFnZSwgbmEucm09VFJVRSkpI0dlbmVyYXRlIHN1bW1hcnkKCiNQbG90IHRvIHN1bW1hcml6ZSBwYXNzZW5nZXIgYWdlIHdpdGggZ2dwbG90CnAxPC10aXRhbmljICU+JSBkcm9wX25hKCkgJT4lIGdncGxvdChhZXMoeD1hZ2UpKSsKICBnZW9tX2hpc3RvZ3JhbShmaWxsPXJhaW5ib3cobGVuZ3RoKDE6OCkpLGJpbnM9OCxzaG93LmxlZ2VuZCA9IEZBTFNFKSsKICBsYWJzKHggPSAiYWdlIikKcDEKI1BhY2thZ2VzIGxpa2UgImRwbHlyIiBhbmQgImdncGxvdDIiIGRvIGEgbG90IG9mIHRoZSBoYXJkIGluaXRpYWwgY29kaW5nL2RhdGEgd3JhbmdsaW5nIGZvciB5b3UsIGdpdmluZyB5b3UgbW9yZSB0aW1lIHRvIGZvY3VzIG9uIG1vcmUgYWR2YW5jZWQgZnVuY3Rpb25zIHRvIHVzZSB3aXRoIHlvdXIgZGF0YS4KCmBgYApUaGUgaGlzdG9ncmFtIGNyZWF0ZWQgdXNpbmcgdGhpcyBzaW1wbGUgZ2dwbG90IFJjb2RlIGlzIG1vcmUgYXR0cmFjdGl2ZSwgYnV0IHdlIGNhbiBkbyBhIGxvdCBtb3JlIHRvIGN1c3RvbWl6ZSB0aGlzIHBsb3QuIEZvciBpbnN0YW5jZSB5b3UgY2FuIHRyeSBhZGRpbmcgZGlmZmVyZW50IHRoZW1lcyAoZS5nLiwgY2xhc3NpYywgYncsIG1pbmltYWwpLiBTaW1wbHkgdHlwZSAqKip0aGVtZSoqKiBmb2xsb3dlZCBieSB0YWIgb24gdGhlIGNvbnNvbGUgdG8gbGVhcm4gYWJvdXQgdGhlIGRpZmZlcmVudCB0aGVtZXMgYW5kIGhvdyB0byBhZGQgdGhlbSB0byBhbiBleGlzdGluZyBnZ3Bsb3QuCgojIyMgU3RlcCAxMjogIENyZWF0ZSBwdWJsaWNhdGlvbi1yZWFkeSBwbG90cyB1c2luZyBnZ3Bsb3QyIGFuZCBkcGx5cgpgYGB7ciwgZXZhbD1GQUxTRX0KI1BhcnQgMgojV2UgY2FuIGNvbWJpbmUgbXVsdGlwbGUgY2F0ZWdvcmljYWwgYW5kIGNvbnRpbnVvdXMgdmFyaWFibGVzCnAyPC1nZ3Bsb3QoZGF0YT1uYS5vbWl0KHRpdGFuaWMpLAogICAgICAgICAgIGFlcyh4PWZhY3RvcihzZXgpLHk9YWdlLGZpbGw9ZmFjdG9yKHN1cnZpdmVkKSkpKwogIGdlb21fYm94cGxvdCgpKwogIGxhYnModGl0bGU9IlN1cnZpdmFsIG9mIHBhc3NlbmdlcnMgYnkgc2V4LCBhZ2UgYW5kIGNsYXNzIiwKICAgICAgIHN1YnRpdGxlPSJOb3QgZXZlcnlvbmUgaGFkIGVxdWFsIGNoYW5jZXMgb2Ygc3Vydml2aW5nIiwgCiAgICAgICBjYXB0aW9uPSJQbG90IGJ5IEouR29sY2hlciIpICsKICB4bGFiKCJQYXNzZW5nZXIgY2xhc3MiKSsKICB5bGFiKCJhZ2UiKSsKICBmYWNldF93cmFwKH5mYWN0b3IocGNsYXNzKSkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIm1lZGl1bXZpb2xldHJlZCIsImNvcm5mbG93ZXJibHVlIiksCiAgICAgICAgICAgICAgICAgICAgbmFtZT0iIixicmVha3M9YygiMCIsICIxIiksbGFiZWxzPWMoImRpZWQiLCAic3Vydml2ZWQiKSkrCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSkKCnAyCgpgYGAKVXNpbmcgZ2dwbG90LCB3ZSBjYW4gcXVpY2tseSBtYWtlIGNsZWFyIGZpZ3VyZXMgdGhhdCBoZWxwIGRhdGEgaW50ZXJwcmV0YXRpb24uIE11bHRpcGxlIGRhdGEgdmlzdWFsaXphdGlvbiBSIHR1dG9yaWFscyBhbmQgY2hlYXQgc2hlZXRzIGV4aXN0IGluIHRoZSBpbnRlcm5ldC4gSWYgeW91IGFyZSBpbnRlcmVzdGVkIGluIGhvdyB0byBnbyBmcm9tIGJlZ2lubmVyIHRvIHBybywgYWdhaW4gKioqcHJhY3RpY2UgbWFrZXMgcGVyZmVjdCoqKi4gVGhlcmUgYXJlIGFsc28gbmV3IHBhY2thZ2VzIHRoYXQgbWFrZSBpdCBlYXNpZXIgdG8gZXhwbG9yZSBwYXR0ZXJucyBmcm9tIGRhdGEsIG9uZSBvZiB0aGVtIGlzIHRoZSBwYWNrYWdlICoqKmV4cGxvcmUqKiouIFRoaXMgcGFydCBvZiB0aGUgdHV0b3JpYWwgaXMgYWRhcHRlZCBmcm9tIGEgMjAyMiB0dXRvcmlhbCB3cml0dGVuIGJ5IFJvbGFuZCBDcmFzc2VyIHRoYXQgY2FuIGJlIGFjY2Vzc2VkIGhlcmU6ICpodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZXhwbG9yZS92aWduZXR0ZXMvZXhwbG9yZV90aXRhbmljLmh0bWwqCgpgYGB7ciwgZXZhbD1GQUxTRX0KI1BhcnQgMwojTGV0J3MgZXhwbG9yZSBmdW5jdGlvbnMgYW5kIHBsb3RzIGluIGV4cGxvcmUKIwojRmlyc3QgbGV0J3MgbWFrZSBhZ2UgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZToKdGl0YW5pYyRhZ2VfY2F0IDwtIGN1dCh0aXRhbmljJGFnZSxicmVha3M9YygwLDE5LDYwLDkwKSwKICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiY2hpbGRyZW4iLCJhZHVsdCIsInNlbmlvciIpKQoKI1RoaXMgaXMgcGVyaGFwcyB1bm5lY2Vzc2FyeSBidXQganVzdCB0byBiZSBzdXJlCnRpdGFuaWMyIDwtIHRpYmJsZSh0aXRhbmljKSAjZGF0YSBmcmFtZSBpbnRvIHRpYmJsZQoKI1dlIHdvdWxkIGxpa2UgdG8gcmVvcmdhbml6ZSBvdXIgZGF0YSBhcyBjb3VudHMgcGVyIGNhdGVnb3JpZXMKdGl0YW5fc3VtPC10aXRhbmljMiAlPiUgZ3JvdXBfYnkocGNsYXNzLCBzdXJ2aXZlZCxhZ2VfY2F0LHNleCkgJT4lIGRwbHlyOjpjb3VudCgpCgp0aXRhbl9zdW0gJT4lIGRlc2NyaWJlX3RibChuPW4pICNkZXNjcmliZXMgZGF0YSBhbmQgTkEKCiNDcmVhdGluZyBwbG90cyB1c2luZyBleHBsb3JlCnAzPC10aXRhbl9zdW0gJT4lIGV4cGxvcmUoYWdlX2NhdCwgbiA9IG4pICNwYXNzZW5nZXIgY2xhc3MgZGlzdHJpYi4KcDQ8LXRpdGFuX3N1bSAlPiUgZXhwbG9yZShhZ2VfY2F0LCB0YXJnZXQgPSBzdXJ2aXZlZCwgbiA9IG4pCnA1PC10aXRhbl9zdW0gJT4lIGV4cGxvcmVfYWxsKG4gPSBuKSAjVG8gc2VlIGNvdW50cyBmb3IgYWxsIHZhcnMuCnA2PC10aXRhbl9zdW0gJT4lIGV4cGxvcmVfYWxsKHRhcmdldCA9IHN1cnZpdmVkLCBuID0gbiwgc3BsaXQgPSBUUlVFKQoKcDMKcDQKcDUKcDYKYGBgCiMjIyBTdGVwIDEzOiAgRXhwb3J0IGdncGxvdDIgY2hhcnRzCkluIHRoaXMgZXhhbXBsZSB3ZSB3ZW50IGJleW9uZCBzaW1wbHkgcGxvdHRpbmcgdXNpbmcgYmFzZSBSIHRvIHByYWN0aWNlIGRhdGEgcmUtb3JnYW5pemF0aW9uIHdpdGggYWR2YW5jZWQgdmlzdWFsaXphdGlvbi4gTGFzdGx5IHdlIHdpbGwgbGVhcm4gaG93IHRvIGFycmFuZ2UgYW5kIGV4cG9ydCBnZ3Bsb3QgZmlndXJlcyB1c2luZyB0aGUgcGFja2FnZSAqcGF0Y2h3b3JrKi4KCmBgYHtyLCBldmFsPUZBTFNFfQojUGFydCA0CiNBIHBhY2thZ2UgdG8gc2F2ZSBnZ3Bsb3RzCmxpYnJhcnkocGF0Y2h3b3JrKQpwPC0ocDEpLyhwMikKI1NhdmUgcGxvdHMKZ2dzYXZlKCJwbG90c0JfMjAyM2phbjE3LnBkZiIsIHApCmBgYAoKKioqUXVlc3Rpb24gOToqKiogSG93IHdvdWxkIHlvdSBtb2RpZnkgdGhpcyBjb2RlIHRvIHNhdmUgdGhlIHBsb3RzIG5leHQgdG8gb25lIGFub3RoZXIgdXNpbmcgKnBhdGNod29yayogKGluc3RlYWQgb2Ygb25lIG9uIHRvcCBvdCB0aGUgb3RoZXIpLiAgCioqKkEvKioqCgpOb3cgd2UgaGF2ZSBleHBsb3JlZCBob3cgdG8gbWFrZSBhIGZldyBwbG90cyB1c2luZyBiYXNlIFIgYW5kIHNvbWUgb2YgdGhlIG5ld2VzdCBwbG90dGluZyBvcHRpb25zIGF2YWlsYWJsZSBhc3NvY2lhdGVkIHRvIHRoZSBwYWNrYWdlICpnZ3Bsb3QyKi4gU3RpbGwsIHJlbWVtYmVyIHRoYXQgdGhpcyBpcyB0aGUgdmVyeSB0aW55IHRpcCBvZiB0aGUgaWNlYmVyZy4gSXQgd2lsbCBiZSB1cCB0byB5b3UgdG8gdGFrZSBpdCBmcm9tIGhlcmUgYW5kIG1ha2Ugc2lnbmlmaWNhbnQgcHJvZ3Jlc3MgaW4geW91ciBSIGpvdXJuZXkgY29kaW5nIGFuZCBtYWtpbmcgcGxvdHMuIFRoZXJlIGFyZSBhbG1vc3QgdG9vIG1hbnkgcmVzb3VyY2VzIG9ubGluZSB0byBsZWFybiBob3cgdG8gdmlzdWFsaXplIGRhdGEgdXNpbmcgUiwgYnV0IGFzIGEgc3RhcnQgdmlzaXQ6ICpodHRwczovL3d3dy5yLWdyYXBoLWdhbGxlcnkuY29tLyogdG8gZ2V0IGluc3BpcmVkIHdpdGggYSBnYWxsZXJ5IG9mIGRpZmZlcmVudCB0eXBlcyBvZiBjaGFydHMuCgojIyMgU3RlcCAxNDogIFJ1biBhIHNpbXBsZSBzdGF0aXN0aWNhbCB0ZXN0CkFzIGEgYmlvbG9naXN0LCBvbmUgb2YgdGhlIGZpcnN0IHN0YXRpc3RpY2FsIHRlc3RzIHdlIGxlYXJuIGlzIGhvdyB0byBjYWxjdWxhdGUgYSBDaGktc3F1YXJlZCB2YWx1ZS4gRm9yIGluc3RhbmNlLCBzdWNoIHRlc3RzIGFyZSB1c2VkIGluIHRoZSBjb250ZXh0IG9mIHRyYW5zbWlzc2lvbiBnZW5ldGljcywgdG9nZXRoZXIgd2l0aCB0aGUgQ2hpLXNxdWFyZWQgdmFsdWUgZGlzdHJpYnV0aW9uIHRhYmxlIHRvIHRlc3QgZm9yIHNpZ25pZmljYW5jZSByZWplY3RpbmcgYSBudWxsIGh5cG90aGVzaXMgb2Ygb2JzZXJ2YXRpb25zIGRldmlhdGluZyBvciBub3QgZnJvbSBleHBlY3RlZC4gQXMgeW91IGFscmVhZHkgZ3Vlc3NlZCBpdCwgUiBjYW4gZG8gdGhpcyBmb3IgeW91IGFuZCBtdWNoIG1vcmUuIFdlIHdpbGwgc3RhcnQgYnkgbGVhcm5pbmcgaG93IHRvIGRvIHRoaXMgdGVzdCB1c2luZyB0aGUgY29uc29sZSwgYW5kIHJldmlldyBob3cgdG8gaW50ZXJwcmV0IHJlc3VsdHMgb2YgdGhlICpjaGlzcS50ZXN0KCkqIGZ1bmN0aW9uIGluIGJhc2UgUiB1c2luZyB0aGUgVGl0YW5pYyB0b3kgZGF0YSBzZXQuCgoqKipRdWVzdGlvbiAxMDoqKiogV2hhdCB3b3VsZCBiZSAqKjEpKip0aGUgbnVsbCBhbmQgKioyKSoqdGhlIGFsdGVybmF0aXZlIGh5cG90aGVzZXMgZm9yIGEgQ2hpLXNxdWFyZWQgdGVzdCBsb29raW5nIGF0IHBhc3NlbmdlciBzdXJ2aXZhbCBieSBjbGFzcz8gQWZ0ZXIgcnVubmluZyB0aGUgY29kZSBiZWxvdzogKiozKSoqV2FzIHRoZSBwLXZhbHVlIHNpZ25pZmljYW50PyAqKjQpKiogV2hhdCBkb2VzIHRoaXMgbWVhbj8gIAoqKipBLyoqKgpgYGB7ciwgZXZhbD1GQUxTRX0KI0NoaS1zcXVhcmVkIHRlc3QgdXNpbmcgUgpyZXMxPC1jaGlzcS50ZXN0KHRpdGFuaWMkcGNsYXNzLCB0aXRhbmljJHN1cnZpdmVkKQpyZXMxCnJlczEkb2JzZXJ2ZWQKcmVzMSRleHBlY3RlZAoKYGBgCgojIyMgU3RlcCAxNTogQ2l0ZSBSIGFuZCBScGFja2FnZXMKSXQgaXMga2V5IHRvIGdpdmUgY3JlZGl0IHRvIHRoZSBnZW5lcm91cyBwZW9wbGUgd2hvIGRldmVsb3AgcGFja2FnZXMgZm9yIGZyZWUsIG9mdGVuIHdpdGggcHVibGljIGZ1bmRzIGZyb20gdW5pdmVyc2l0aWVzIGFuZCBvdGhlciByZXNlYXJjaCBpbnN0aXR1dGlvbnMuIFByb3ZpZGluZyBhdXRob3JzIHdpdGggdGhlIGNyZWRpdCB0aGV5IGRlc2VydmUgYWxzbyBlbmNvdXJhZ2VzIGZ1bmRpbmcgYWdlbmNpZXMgdG8gc3VwcG9ydCB0aGVpciB3b3JrLCB3aGljaCB1bHRpbWF0ZWx5IGJlbmVmaXRzIHRoZSBlbnRpcmUgY29tbXVuaXR5IG9mIFIgdXNlcnMuCgpgYGB7cixldmFsPUZBTFNFfQpjaXRhdGlvbigpICNUbyBjaXRlIFIKUi5WZXJzaW9uKCkgI0ZpZ3VyZSBvdXQgUiB2ZXJzaW9uClJTdHVkaW8uVmVyc2lvbigpICNUbyBjaXRlIFIgc3R1ZGlvCiNUbyBjaXRlIGFsbCB0aGUgcGFja2FnZXMgIHVzZWQgaW4gdGhpcyB0dXRvcmlhbDoKY2l0YXRpb24oImdncGxvdDIiKQpjaXRhdGlvbigiZHBseXIiKQpjaXRhdGlvbigidGliYmxlIikKY2l0YXRpb24oImV4cGxvcmUiKQpjaXRhdGlvbigicGF0Y2h3b3JrIikKCmBgYAoKCipUaGlzIG1pbmktd29ya3Nob3Agd2FzIG1vZGlmaWVkIGZyb20gdGhlIDIwMTggV29ya3Nob3Agbm90ZXMgSW50cm8gdG8gUiBmb3IgZmlzaGVyaWVzIHJlc2VhcmNoZXJzIGluIFRhbnphbmlhIGNvLXRhdWdodCBieSBEci4gSmVzc2ljYSBSaWNrIGFuZCBEci4gSmltZW5hIEdvbGNoZXItQmVuYXZpZGVzLiBJIHdvdWxkIGxpa2UgdG8gdGhhbmsgdGhlIGdlbmVyb3VzIFIgJiBSIGxlYXJuaW5nIGNvbW11bml0eSBmb3IgYWxsIHRoZSBoaWdoLXF1YWxpdHkgbGVhcm5pbmcgcmVzb3VyY2VzIGZyZWVseSBhdmFpbGFibGUgb25saW5lLioKCkZvciBtb3JlIGxlYXJuaW5nIHJlc291cmNlcyBvbiBob3cgdG8gdXNlIFIgJiBSIFN0dWRpbywgY2hlY2sgb3V0IHRoZXNlIGd1aWRlbGluZXMgd3JpdHRlbiBieSBUaG9tYXMgTW9jazogKmh0dHBzOi8vd3d3LnJzdHVkaW8uY29tL3Jlc291cmNlcy93ZWJpbmFycy9hLWdlbnRsZS1pbnRyb2R1Y3Rpb24tdG8tdGlkeS1zdGF0aXN0aWNzLWluLXIvKi4KCg==