Required packages

Provide the packages required to reproduce the report. Make sure you fulfilled the minimum requirement #10.

# This is the R chunk for the required packages
library(tidyr)

library(dplyr)

library(editrules)

library(deducorrect)

library(outliers)

## Executive Summary
#This report provides the preprocessing of 2 datasets, which contains methods to merge datasets, convert variable type, label factor variable, reshape data into a tidy format, mutate new variable, scan outliers for numeric variables, transform data, scan errors (missing values, special values, obvious errors, and inconsistency) and use the technique to deal with errors (missing values, special values, obvious errors, and inconsistency) by only using packages of tidyr, dplyr, editrules, deducorrect, and outliers. This report aims to provide a sample of how to preprocess datasets, the source of datasets is all come from the government of VIC https://www.vic.gov.au/, they are all open and have a Creative Commons Licence. 
# This is the R chunk for the Data Section

## Data

#Import dataset from website, this dataset is from the government of victoria and it's source website is: https://discover.data.vic.gov.au/dataset/all-schools-fte-enrolments-feb-2015. This dataset contains information collected from the February 2014 school census of Victorian schools until February 2015. This dataset contains 54 variables but we are going to subset to 9 variables otherwise it will be too large and when we merge variables together or merge two datasets together, R will reports Error: vector memory exhausted (limit reached?). After we subset the data set, there will be 9 variables left: 

#"Education_Sector":It refers to educational sector.
#"Entity_Type":It refers to type of school district.       
#"School_No":It refers to the code that represent the school.
#"School_Name":It refers to the name of school.         
#"School_Type":It refers to the type of school.         
#"School_Status":It refers to the status of school.
#"Prep.Males.Total..":It refers to the total number of preparatory male student.
#"Prep.Females.Total..":It refers to the total number of preparatory female student.
#"Prep.Total..":It refers to the total number of preparatory student. 

#Import dataset from website.
url <- "http://www.education.vic.gov.au/Documents/about/research/datavic/dv171-Feb2015FTEenrolments.csv"
All_Schools_FTE_enrolments_Feb_2015 <- read.csv(url, stringsAsFactors = FALSE)

#We need to subset data because this dataset is too big, if we don't subset dataset, then when we merge variables together or merge two datasets together, R will reports Error: vector memory exhausted (limit reached?).
All_Schools_FTE_enrolments_Feb_2015 <- subset(All_Schools_FTE_enrolments_Feb_2015, select = Education_Sector:Prep.Total..)

head(All_Schools_FTE_enrolments_Feb_2015)



#Import dataset from another website, this dataset is from the government of victoria and it's source website is: https://discover.data.vic.gov.au/dataset/all-schools-fte-enrolments-feb-2016. This dataset contains information collected from the February 2015 school census of Victorian schools until February 2016. This dataset also contains 54 variables but we are going to subset to 9 variables due to the problem of large dataset. And these 9 variables are the same as the previous dataset, it means that they have the same variable and also those variables have the same meaning.

#Import dataset from website.
url <- "http://www.education.vic.gov.au/Documents/about/research/datavic/dv214-allschoolsfetenrolfeb2016.csv"
All_Schools_FTE_enrolments_Feb_2016 <- read.csv(url, stringsAsFactors = FALSE)

#We use anti_join() function to obtain the different data from student enrolments in 2015 (New data), because we woudl like merge additional data from student enrolments in 2016 with student enrolments in 2016 in next step.
New_All_Schools_FTE_enrolments_Feb_2016 <- anti_join(All_Schools_FTE_enrolments_Feb_2016, All_Schools_FTE_enrolments_Feb_2015, by = "School_Name")

#The same situation in this one, we have to minimize data otherwise, R will generate error when merge 2 dataset because they are too large.
New_All_Schools_FTE_enrolments_Feb_2016 <- subset(New_All_Schools_FTE_enrolments_Feb_2016, select = Education_Sector:Prep.Total..)

head(New_All_Schools_FTE_enrolments_Feb_2016)

#We use bind_rows() function to merge two datasets because they have the same variables.
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students <- bind_rows(All_Schools_FTE_enrolments_Feb_2015, New_All_Schools_FTE_enrolments_Feb_2016)

head(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students)

Tidy & Manipulate Data I

# This is the R chunk for the Tidy & Manipulate Data I 

#We put this part (Tidy & Manipulate Data I) prior to the (Understand) part is because there will be some variables created after we tidy this dataset and it is better to convert variable type, rename variable, rearrange variables after we set down the dataset. 



#The problem of this dataset is that the column names are not names of variables, but values of a variable. In this case, the column names "Prep.Males.Total..", and "Prep.Females.Total.." represent values of the gender variable, and each row represents two observations, not one. 
head(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students)

#Therefore, we use gather() function to merge two variables into a factor variable and also create a new variable which is called "Number_of_students".
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2 <- All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students %>%
gather(`Prep.Males.Total..`, `Prep.Females.Total..`, key = "Gender", value = "Number_of_students")

head(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2)
NA
NA

Understand

# This is the R chunk for the Understand Section

#Rearrange and rename and rearrange variables
#We first check the order of variables. 
str(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2)
'data.frame':   4502 obs. of  9 variables:
 $ Education_Sector  : chr  "Catholic" "Catholic" "Catholic" "Catholic" ...
 $ Entity_Type       : int  2 2 2 2 2 2 2 2 2 2 ...
 $ School_No         : int  20 25 26 28 29 30 33 35 60 77 ...
 $ School_Name       : chr  "Parade College" "Simonds Catholic College" "Christian Brothers' College St Kilda" "St Patrick's College Ballarat" ...
 $ School_Type       : chr  "Secondary" "Secondary" "Secondary" "Secondary" ...
 $ School_Status     : chr  "O" "O" "O" "O" ...
 $ Prep.Total..      : num  0 0 0 0 34 44 0 0 38 39 ...
 $ Gender            : chr  "Prep.Males.Total.." "Prep.Males.Total.." "Prep.Males.Total.." "Prep.Males.Total.." ...
 $ Number_of_students: num  0 0 0 0 15 19 0 0 22 15 ...
#We use select() function to rearrange the order of variables.
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2 <- All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2 %>% select(School_Name, School_No, School_Type, School_Status, Education_Sector, Entity_Type, Gender, Number_of_students, Prep.Total..)

#Given that we gather two variables together to build up a factor variable "Gender". We should rename the levels of "Gender".
#Then, use levels() function to check the level name of this variable.
levels(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Gender)
NULL
#We use label() function to re-label the name of levels in a factor variable.
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Gender <- factor(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Gender,levels = c("Prep.Females.Total..","Prep.Males.Total.."),
                                                                                     labels = c("Female","Male"))

#We also notice that the variable name of "Prep.Total.." doesn't look good (because there are some ".." in the name) and "Number_of_students" should actually be "Number_of_pre.student".
#We use rename() function to rename variables.                              
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2 <- All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2 %>% 
  rename(
    Total_number_of_pre.student_for_school = Prep.Total..
    , Number_of_pre.student = Number_of_students
  )

#Check the variables and order again, this also prove that this dataset contains multiple data types (numerics, characters, factors).
str(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2)
'data.frame':   4502 obs. of  9 variables:
 $ School_Name                           : chr  "Parade College" "Simonds Catholic College" "Christian Brothers' College St Kilda" "St Patrick's College Ballarat" ...
 $ School_No                             : int  20 25 26 28 29 30 33 35 60 77 ...
 $ School_Type                           : chr  "Secondary" "Secondary" "Secondary" "Secondary" ...
 $ School_Status                         : chr  "O" "O" "O" "O" ...
 $ Education_Sector                      : chr  "Catholic" "Catholic" "Catholic" "Catholic" ...
 $ Entity_Type                           : int  2 2 2 2 2 2 2 2 2 2 ...
 $ Gender                                : Factor w/ 2 levels "Female","Male": 2 2 2 2 2 2 2 2 2 2 ...
 $ Number_of_pre.student                 : num  0 0 0 0 15 19 0 0 22 15 ...
 $ Total_number_of_pre.student_for_school: num  0 0 0 0 34 44 0 0 38 39 ...
#Convert variable type
#Notice that "Education_Sector" has some values are the same, so try to covert it into factor variable.
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Education_Sector <- as.factor(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Education_Sector)

is.factor(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Education_Sector)
[1] TRUE
#Check the levels of this variable, and the result is that there are only 3 levels. This confirms my guess and this variable should actually be a factor variable.
levels(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Education_Sector)
[1] "Catholic"    "Government"  "Independent"
#Entity_Type is obviously a factor variable but R indicate that as int. So, we need to convert it into factor variable.
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Entity_Type <- as.factor(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Entity_Type)

is.factor(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Entity_Type)
[1] TRUE
#To ensure that this variable is a factor variable, we check the levels for this variable and the result is that there are only 2 levels. This confirms my guess and this variable should actually be a factor variable.
levels(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Entity_Type)
[1] "1" "2"
#School_Type is obviously a factor variable but R indicate that as chr. So, we need to convert it into factor variable.
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$School_Type <- as.factor(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$School_Type)

is.factor(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$School_Type)
[1] TRUE
#To ensure that this variable is a factor variable, we check the levels for this variable and the result is that there are only 5 levels. This confirms my guess and this variable should actually be a factor variable.
levels(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$School_Type)
[1] "Language"  "Pri/Sec"   "Primary"   "Secondary" "Special"  
#Notice that "School_Status" has some values are the same, so try to covert it into factor variable.
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$School_Status <- as.factor(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$School_Status)

is.factor(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$School_Status)
[1] TRUE
#Check the levels of this variable, and the result is that there are only 2 levels. This confirms my guess and this variable should actually be a factor variable.
levels(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$School_Status)
[1] "O" "U"
#This variable has to be integer because it can't be half student.
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Number_of_pre.student <- as.integer(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Number_of_pre.student)
is.integer(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Number_of_pre.student)
[1] TRUE
#This variable has to be integer because it can't be half student.
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Total_number_of_pre.student_for_school <- as.integer(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Total_number_of_pre.student_for_school)
is.integer(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2$Total_number_of_pre.student_for_school)
[1] TRUE
#Check the varibale type again to make sure everything is good. 
str(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2)
'data.frame':   4502 obs. of  9 variables:
 $ School_Name                           : chr  "Parade College" "Simonds Catholic College" "Christian Brothers' College St Kilda" "St Patrick's College Ballarat" ...
 $ School_No                             : int  20 25 26 28 29 30 33 35 60 77 ...
 $ School_Type                           : Factor w/ 5 levels "Language","Pri/Sec",..: 4 4 4 4 3 3 4 4 3 3 ...
 $ School_Status                         : Factor w/ 2 levels "O","U": 1 1 1 1 1 1 1 1 1 1 ...
 $ Education_Sector                      : Factor w/ 3 levels "Catholic","Government",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Entity_Type                           : Factor w/ 2 levels "1","2": 2 2 2 2 2 2 2 2 2 2 ...
 $ Gender                                : Factor w/ 2 levels "Female","Male": 2 2 2 2 2 2 2 2 2 2 ...
 $ Number_of_pre.student                 : int  0 0 0 0 15 19 0 0 22 15 ...
 $ Total_number_of_pre.student_for_school: int  0 0 0 0 34 44 0 0 38 39 ...

Tidy & Manipulate Data II

# This is the R chunk for the Tidy & Manipulate Data II 

#Mutate new variable
#Use mutate() function to create a new variable. This new variable is the sex proportion in terms of male and female for each school. And it's formula is: Sex_proportion_for_the_pre.student_in_school = Number_of_pre.student / Total_number_of_pre.student_for_school.
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2 <- mutate(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2,
Sex_proportion_for_the_pre.student_in_school = Number_of_pre.student / Total_number_of_pre.student_for_school
)

#Check if we create "Sex_proportion_for_the_pre.student_in_school" successfully.
str(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2)
'data.frame':   4502 obs. of  10 variables:
 $ School_Name                                 : chr  "Parade College" "Simonds Catholic College" "Christian Brothers' College St Kilda" "St Patrick's College Ballarat" ...
 $ School_No                                   : int  20 25 26 28 29 30 33 35 60 77 ...
 $ School_Type                                 : Factor w/ 5 levels "Language","Pri/Sec",..: 4 4 4 4 3 3 4 4 3 3 ...
 $ School_Status                               : Factor w/ 2 levels "O","U": 1 1 1 1 1 1 1 1 1 1 ...
 $ Education_Sector                            : Factor w/ 3 levels "Catholic","Government",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Entity_Type                                 : Factor w/ 2 levels "1","2": 2 2 2 2 2 2 2 2 2 2 ...
 $ Gender                                      : Factor w/ 2 levels "Female","Male": 2 2 2 2 2 2 2 2 2 2 ...
 $ Number_of_pre.student                       : int  0 0 0 0 15 19 0 0 22 15 ...
 $ Total_number_of_pre.student_for_school      : int  0 0 0 0 34 44 0 0 38 39 ...
 $ Sex_proportion_for_the_pre.student_in_school: num  NaN NaN NaN NaN 0.441 ...

Scan I

# This is the R chunk for the Scan I

#Sometimes dataset can have obious errors. For example, sex proportion cannot be negative or beyond 1. For checking these inconsistency, we would like to apply rules to check whether this dataset violates the rule by using editfile() function. And also, we could also apply rules to correct errors by using correctionRules() function. When the number of rules increase, it is better to manage the rules separate from the data. The function of editrules() can check which rules are obeyed or not and allows one to find the minimal set of variables to adapt so that all rules can be obeyed. In addition,correctionRules() function force variables to follow it's constraints so that, it is very helpful when correcting data. In this part, we are going to using editrules() and correctionRules() to deal with inconsistency.

#The first thing is to check the consistency of "Total_number_of_pre.student_for_school" = "Number_of_pre.student" for male + "Number_of_pre.student" for female.
#It is more convenient to check the consistency of "Total_number_of_pre.student_for_school" = "Number_of_pre.student" for male + "Number_of_pre.student" for female by spreading the "Gender" out.
#We find out that there is a variable prevent us to spread "Gender" out in "All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2", which is called "Sex_proportion_for_the_pre.student_in_school". 
#That is because "Sex_proportion_for_the_pre.student_in_school" = "Number_of_pre.student"/"Total_number_of_pre.student_for_school". And when we spread "Gender" out, it will produce many NaN values.
#And this is why we should exclude "Sex_proportion_for_the_pre.student_in_school" first and then spread "Gender" out.
Data_for_checking_inconsistency1 = subset(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2, select = -Sex_proportion_for_the_pre.student_in_school )

#And then we use spread() function to spread it out.
Data_for_checking_inconsistency2 <- spread(Data_for_checking_inconsistency1, key = Gender, value = Number_of_pre.student)

#Import rules into R
Rules1 <- editfile("/Users/macbook/Documents/RMIT-Master of Analytics/Data wrangling/editrules2.txt", type = "all")

Rules1

Edit set:
num1 : Female + Male == Total_number_of_pre.student_for_school 
#Use summary() function to avoid the problem of large data size.
Violated1 <- violatedEdits(Rules1, Data_for_checking_inconsistency2)

summary(Violated1)
Edit violations, 2251 observations, 0 completely missing (0%):

Edit violations per record:
#The result shows that this data does have some errors.



#To correct those errors, we import rules for correction.
Rules2 <- correctionRules("/Users/macbook/Documents/RMIT-Master of Analytics/Data wrangling/editrules3.txt")

Rules2
Object of class 'correctionRules'
##  1-------
  if (Male + Female != Total_number_of_pre.student_for_school) {
      Total_number_of_pre.student_for_school <- Male + Female
  } 
#Apply rules into the data that contains errors.
cor <- correctWithRules(Rules2, Data_for_checking_inconsistency2)

#And then, check it again whether we successfully correct errors.
#Use summary() function to avoid the problem of large data size.
Violated2 <- violatedEdits(Rules1, cor$corrected)

summary(Violated2)
No violations detected, 0 checks evaluated to NA
NULL
#And then, after correcting the data, we put "Sex_proportion_for_the_pre.student_in_school" back into the dataset.
#The first thing is to reshape the dataset of "Data_for_checking_inconsistency2".
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3 <- Data_for_checking_inconsistency2 %>%
  gather(`Male`, `Female`, key = "Gender", value = "Number_of_pre.student")

#And then, put "Sex_proportion_for_the_pre.student_in_school" back into the dataset.
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3 <- mutate(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3,
                                                                              Sex_proportion_for_the_pre.student_in_school = Number_of_pre.student / Total_number_of_pre.student_for_school
)

#And then, rearrange the sequence of variables.
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3 <- All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_2 %>% select(School_Name, School_No, School_Type, School_Status, Education_Sector, Entity_Type, Gender, Number_of_pre.student, Total_number_of_pre.student_for_school, Sex_proportion_for_the_pre.student_in_school)



#The second thing is to check inifite value, special value, and missing value. For convenience, we first build up a function to better deal with missing values, infinite values, and NaN values. We acutally would like to use sapply() function to look for errors but this function could not deal with NaN values. Thus, we should write up a function to deal with NaN values.
is.specialorNA <- function(x){
  if (is.numeric(x)) (is.infinite(x) | is.nan(x) | is.na(x))
}

#There are 932 na value for column "Sex_proportion_for_the_pre.student_in_school"
sapply(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3, function(x) sum( is.na(x) ))
                                 School_Name 
                                           0 
                                   School_No 
                                           0 
                                 School_Type 
                                           0 
                               School_Status 
                                           0 
                            Education_Sector 
                                           0 
                                 Entity_Type 
                                           0 
                                      Gender 
                                           0 
                       Number_of_pre.student 
                                           0 
      Total_number_of_pre.student_for_school 
                                           0 
Sex_proportion_for_the_pre.student_in_school 
                                         932 
#There are 0 infinite value for this dataset
sapply(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3, function(x) sum( is.infinite(x) ))
                                 School_Name 
                                           0 
                                   School_No 
                                           0 
                                 School_Type 
                                           0 
                               School_Status 
                                           0 
                            Education_Sector 
                                           0 
                                 Entity_Type 
                                           0 
                                      Gender 
                                           0 
                       Number_of_pre.student 
                                           0 
      Total_number_of_pre.student_for_school 
                                           0 
Sex_proportion_for_the_pre.student_in_school 
                                           0 
#There are 932 NaN value for column "Sex_proportion_for_the_pre.student_in_school"
sapply(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3, function(x) sum( is.nan(x) ))
                                 School_Name 
                                           0 
                                   School_No 
                                           0 
                                 School_Type 
                                           0 
                               School_Status 
                                           0 
                            Education_Sector 
                                           0 
                                 Entity_Type 
                                           0 
                                      Gender 
                                           0 
                       Number_of_pre.student 
                                           0 
      Total_number_of_pre.student_for_school 
                                           0 
Sex_proportion_for_the_pre.student_in_school 
                                         932 
#NaN means "not a number". When R generate NaN, it means that the value just makes a little sense. In this case, we find out a lot of NaNs in the variable of “Sex_proportion_for_the_pre.student_in_school”, which is calculated by the formula of:
#Sex_proportion_for_the_pre.student_in_school = Number_of_pre.student / Total_number_of_pre.student_for_school. 
#Number_of_pre.student can be 0 and Total_number_of_pre.student_for_school can be 0 either. The is the reason of NaN because when 0 divided by 0, it is meaningless and that’s why R generate NaN as the result. To fix this special value, we can just covert NaN to 0 directly. 
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3$Sex_proportion_for_the_pre.student_in_school[All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3$Sex_proportion_for_the_pre.student_in_school == "NaN" ] <- 0

#And then, check it again whether we eliminate all NaN values and Na values.
sapply(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3, function(x) sum( is.na(x) ))
                                 School_Name 
                                           0 
                                   School_No 
                                           0 
                                 School_Type 
                                           0 
                               School_Status 
                                           0 
                            Education_Sector 
                                           0 
                                 Entity_Type 
                                           0 
                                      Gender 
                                           0 
                       Number_of_pre.student 
                                           0 
      Total_number_of_pre.student_for_school 
                                           0 
Sex_proportion_for_the_pre.student_in_school 
                                           0 
sapply(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3, function(x) sum( is.nan(x) ))
                                 School_Name 
                                           0 
                                   School_No 
                                           0 
                                 School_Type 
                                           0 
                               School_Status 
                                           0 
                            Education_Sector 
                                           0 
                                 Entity_Type 
                                           0 
                                      Gender 
                                           0 
                       Number_of_pre.student 
                                           0 
      Total_number_of_pre.student_for_school 
                                           0 
Sex_proportion_for_the_pre.student_in_school 
                                           0 
#We successfully remove all NaN values and Na values.



#The third thing is to check incoensistency, and we do the same thing as what we done previously.
#Firts, we import rules into R.
Rules3 <- editfile("/Users/macbook/Documents/RMIT-Master of Analytics/Data wrangling/editrules.txt", type = "all")

Rules3

Data model:
dat1 : Education_Sector %in% c('Catholic', 'Government', 'Independent')
dat2 : Entity_Type %in% c('1', '2')
dat3 : Gender %in% c('Female', 'Male')
dat4 : School_Status %in% c('O', 'U')
dat5 : School_Type %in% c('Language', 'Pri/Sec', 'Primary', 'Secondary', 'Special') 

Edit set:
num1 : Number_of_pre.student <= Total_number_of_pre.student_for_school
num2 : Sex_proportion_for_the_pre.student_in_school <= 1
num3 : 0 <= Sex_proportion_for_the_pre.student_in_school 
#Use summary() function to avoid the problem of large data size.

Violated3 <- violatedEdits(Rules3, All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3)

summary(Violated3)
No violations detected, 0 checks evaluated to NA
NULL
#Fortunately, we don't have any inconsistencies. 

Transform

# This is the R chunk for the Transform Section


#7 Data transformation
#The reaosn to put "data transformation" prior to the "Scan II" is that we have data who has right-skewed distribution. And we decide to use z-scores method in order to locate where are the outliers. 
#Therefore, we have to transform data from right-skewed distribution to approximately normal distribution first. 
hist(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3$Sex_proportion_for_the_pre.student_in_school)


#Based on the variable "Sex_proportion_for_the_pre.student_in_school", it contains 0 values and it is right-skewed.
#We first try to use square root transformation to deal with this data because this data has 0 values and it is reight-skewed.
sqrt_salary <- sqrt(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3$Sex_proportion_for_the_pre.student_in_school)
hist(sqrt_salary)


#As result, it is still right skewed and still need to be improved.

#We note that this data contrains 0 values or 1 values, and it is because there are some all-male school or all-female school.
#When investigating sex porporion, it is meaningless to investigate what percentage of male student in a all-female school or what percentage of female student in all-male school.
#Therefore, we should remove 0 value and 1 value. 
subset_no_0_1 <- All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3 %>% filter(Sex_proportion_for_the_pre.student_in_school != "0" & Sex_proportion_for_the_pre.student_in_school !="1")

#Now, let's produce a histogram again. 
hist(subset_no_0_1$Sex_proportion_for_the_pre.student_in_school)


#As result, it is approximately normal distributed now.

Scan II

# This is the R chunk for the Scan II

#We first check out which variable is numeric. 
str(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3)
'data.frame':   4502 obs. of  10 variables:
 $ School_Name                                 : chr  "Parade College" "Simonds Catholic College" "Christian Brothers' College St Kilda" "St Patrick's College Ballarat" ...
 $ School_No                                   : int  20 25 26 28 29 30 33 35 60 77 ...
 $ School_Type                                 : Factor w/ 5 levels "Language","Pri/Sec",..: 4 4 4 4 3 3 4 4 3 3 ...
 $ School_Status                               : Factor w/ 2 levels "O","U": 1 1 1 1 1 1 1 1 1 1 ...
 $ Education_Sector                            : Factor w/ 3 levels "Catholic","Government",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Entity_Type                                 : Factor w/ 2 levels "1","2": 2 2 2 2 2 2 2 2 2 2 ...
 $ Gender                                      : Factor w/ 2 levels "Female","Male": 2 2 2 2 2 2 2 2 2 2 ...
 $ Number_of_pre.student                       : int  0 0 0 0 15 19 0 0 22 15 ...
 $ Total_number_of_pre.student_for_school      : int  0 0 0 0 34 44 0 0 38 39 ...
 $ Sex_proportion_for_the_pre.student_in_school: num  0 0 0 0 0.441 ...
#We could see that there are 4 numeric variables: 
#School_No, Number_of_pre.student, Total_number_of_pre.student_for_school, and Sex_proportion_for_the_pre.student_in_school
#However, School_No is not necessary to be scanned because it is just a code to represent a school and not a numeric number technically. 



#First, we are going to investigate outliers of "Sex_proportion_for_the_pre.student_in_school".
hist(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3$Sex_proportion_for_the_pre.student_in_school)


#And also, they are non-symmetric/ non-normal data distributions, it is right-skewed distribution.
#As we known, there are all-male school and all-female school, so we expect that there are some outliers is 0 or 1 in terms of sex proportion.
#So, we should use z-scores method to look for outliers. The reason is that we could know which values are outliers, and knowing how many outliers are there, and if there are just a samll acount of outliers we may choose to delete them.
#Given that we already normalize the right-skewed distribution of "Sex_proportion_for_the_pre.student_in_school"
#Now, we could directly apply z-scores method to look for outliers.

#We now calculate z scores:
z.scores <- subset_no_0_1$Sex_proportion_for_the_pre.student_in_school %>%  scores(type = "z")
z.scores %>% summary()
     Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
-3.571547 -0.558508 -0.000538  0.000000  0.557432  3.570471 
#we can see that the maximum is 12.04. And we can find the locations of the z-scores whose absolute value is greater than 3 by using which().
which( abs(z.scores) >3 )
 [1]   24  120  154  641  701  708  774 1171 1287 1361 1374 1451 1489
[14] 1491 1708 1804 1838 2325 2385 2392 2458 2855 2971 3045 3058 3135
[27] 3173 3175 3349
#By using length() function, we can see that there are 29 outliers.
length (which( abs(z.scores) >3 ))
[1] 29
#It is still possible that those outliers are not the result of data entry errors, measurement errors, experimental errors, intentional errors, data processing errors or due to the sampling (i.e., sampling error) because very low sex proportion or very high sex proportion does happened in some school.
#But it is also possible that those outliers are actually errors.
#In this case, we should use capping technique to deal with outliers because we are not sure about whether there are errors. 
#Thus, we should use the safe way to deal with this data: Replacing the outliers with the nearest neighbours that are not outliers.

#First, we need to create our own function: cap. This means that we need to first find the value that are less than (quantiles 0.25)-1.5*IQR and then repalce it as (quantiles 0.05). Second, find the value that are bigger than (quantiles 0.75)+1.5*IQR and then repalce it as (quantiles 0.95).
cap <- function(x){
  quantiles <- quantile( x, c(.05, 0.25, 0.75, .95 ) )
  x[ x < quantiles[2] - 1.5*IQR(x) ] <- quantiles[1]
  x[ x > quantiles[3] + 1.5*IQR(x) ] <- quantiles[4]
  x
}

#And then, cap the outliers.
Sex_proportion_capped <- subset_no_0_1$Sex_proportion_for_the_pre.student_in_school %>% cap()

#Let's check outliers again.
z.scores <- Sex_proportion_capped %>%  scores(type = "z")
z.scores %>% summary()
      Min.    1st Qu.     Median       Mean    3rd Qu.       Max. 
-2.5208407 -0.6305411 -0.0004412  0.0000000  0.6296587  2.5199584 
#we can see that the maximum is 2.5199584. And we can find whcih value whose absolute Z-value is greater than 3 by using which().
which( abs(z.scores) >3 )
integer(0)
#By using length() function, we can see that there are 0 outliers.
length (which( abs(z.scores) >3 ))
[1] 0
#Second, we are going to ivestigate outliers of "Number_of_pre.student" in terms of "gender". 
#Given that they are one factor variable and one numeric variable. And also, they are non-symmetric/ non-normal data distributions.
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3_male <-All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3 %>% filter(Gender == "Male")

hist(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3_male$Number_of_pre.student)


All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3_female <-All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3 %>% filter(Gender == "Female")

hist(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3_female$Number_of_pre.student)


#Thus, in this case, using the technique of "Bivariate box plot" is highly encouraged.

boxplot(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3$Number_of_pre.student ~ All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3$Gender, main="Number of pre.student by gender", ylab = "Number of pre.student", xlab = "Gender")


#Using the bivariate box plot approach, we can easily detect outliers in "Number_of_pre.student" for a given "Gender".
#However, these outliers are valuable becasue this variable (Number_of_pre.student) is used for collect information of the number of stduent for different gender in different school. 
#And, it is okay that some school have a lot of student (note that outliers are all beyond the upper fence for both male and female) because schools can be like all-male school or all-female school. 
#Moreover, school type is divided by "Language", "Pri/Sec", "Primary", "Secondary", and "Special", it is expected that there should be many pre-student for language school or special school, and less pre-student for Pri/Sec, Primary, and Secondary school.
#And, we could see that the Q1 is just around 0 and Q3 is around 30 for both male and female. Obviously, there are a lot of primary and secondary school who has 0 pre-student or only very samll number of pre-student in this datset.
#Therefore, it is possible that some "Language" and "Special" school have a lot of students and are defined as outliers in this plot. So, these outliers are explainable. 
#However, it is still possible that some outliers are errors such as measurement error or sampleing error.
#Thus, we should use the safe way to deal with this data: Replacing the outliers with the nearest neighbours that are not outliers.
#Given that we already have our own function: cap and we could just directly apply cap function into dataset.



#We first deal with the outliers for male.
Student_male_capped <- All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3_male$Number_of_pre.student %>% cap()

#Let's check outliers again.
z.scores2 <- Student_male_capped %>%  scores(type = "z")
z.scores2 %>% summary()
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
-1.0015 -0.9418 -0.2859  0.0000  0.6086  2.9342 
#we can see that the maximum is 2.9342. And we can find whcih value whose absolute Z-value is greater than 3 by using which().
which( abs(z.scores2) >3 )
integer(0)
#By using length() function, we can see that there are 0 outliers.
length (which( abs(z.scores2) >3 ))
[1] 0
#And then, we deal with the outliers for female.
Student_female_capped <- All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3_female$Number_of_pre.student %>% cap()

#Let's check outliers again.
z.scores3 <- Student_female_capped %>%  scores(type = "z")
z.scores3 %>% summary()
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
-1.0039 -0.9410 -0.3118  0.0000  0.6320  2.9602 
#we can see that the maximum is 2.9602. And we can find whcih value whose absolute Z-value is greater than 3 by using which().
which( abs(z.scores3) >3 )
integer(0)
#By using length() function, we can see that there are 0 outliers.
length (which( abs(z.scores3) >3 ))
[1] 0
#Third, we are going to investigate outliers of "Total_number_of_pre.student_for_school".
hist(All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3$Total_number_of_pre.student_for_school)


#And also, they are non-symmetric/ non-normal data distributions.
#Thus, in this case, using the technique of "Univariate box plot" is highly encouraged.
All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3$Total_number_of_pre.student_for_school %>%  boxplot(main="Box Plot of total number of pre.student for school", ylab="Total number of pre.student", col = "grey")


#This case is very similar to the previous case, outliers are all beyond the upper fence. As we can see in the plot, outliers are all in around 140 students to 250 student. It seems okay because some big school can have 250 pre-student. 
#And, we could see that the Q1 is just around 0 and Q3 is around 50. Obviously, this plot has the same situation with the previous one, there are a lot of primary and secondary school who has 0 pre-student only very samll number of pre-student in this datset.
#Therefore, it is possible that some "Language" and "Special" school have a lot of students and are defined as outliers in this plot. So, these outliers are explainable. 
#Outliers are valuable and explainable.
#However, it is still possible that some outliers are errors such as measurement error or sampleing error.
#Thus, we should use the safe way to deal with this data: Replacing the outliers with the nearest neighbours that are not outliers.
#Given that we already have our own function: cap and we could just directly apply cap function into dataset.



Total_tudent_capped <- All_Schools_FTE_enrolments_Feb_2015_Combine_2016_for_pre.students_3$Total_number_of_pre.student_for_school %>% cap()

#Let's check outliers again.
z.scores4 <- Total_tudent_capped %>%  scores(type = "z")
z.scores4 %>% summary()
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
-1.0269 -0.9327 -0.2739  0.0000  0.6046  2.8948 
#we can see that the maximum is 2.8948. And we can find whcih value whose absolute Z-value is greater than 3 by using which().
which( abs(z.scores4) >3 )
integer(0)
#By using length() function, we can see that there are 0 outliers.
length (which( abs(z.scores4) >3 ))
[1] 0
LS0tCnRpdGxlOiAiTUFUSDIzNDkgRGF0YSBXcmFuZ2xpbmciCmF1dGhvcjogIldlbnh1YW4gQ2hlbiAgIFMzNjEzNjM2IgpzdWJ0aXRsZTogQXNzaWdubWVudCAyCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQojIyBSZXF1aXJlZCBwYWNrYWdlcyAKCgpQcm92aWRlIHRoZSBwYWNrYWdlcyByZXF1aXJlZCB0byByZXByb2R1Y2UgdGhlIHJlcG9ydC4gTWFrZSBzdXJlIHlvdSBmdWxmaWxsZWQgdGhlIG1pbmltdW0gcmVxdWlyZW1lbnQgIzEwLgoKYGBge3J9CiMgVGhpcyBpcyB0aGUgUiBjaHVuayBmb3IgdGhlIHJlcXVpcmVkIHBhY2thZ2VzCmxpYnJhcnkodGlkeXIpCgpsaWJyYXJ5KGRwbHlyKQoKbGlicmFyeShlZGl0cnVsZXMpCgpsaWJyYXJ5KGRlZHVjb3JyZWN0KQoKbGlicmFyeShvdXRsaWVycykKYGBgCgpgYGB7cn0KCiMjIEV4ZWN1dGl2ZSBTdW1tYXJ5CiNUaGlzIHJlcG9ydCBwcm92aWRlcyB0aGUgcHJlcHJvY2Vzc2luZyBvZiAyIGRhdGFzZXRzLCB3aGljaCBjb250YWlucyBtZXRob2RzIHRvIG1lcmdlIGRhdGFzZXRzLCBjb252ZXJ0IHZhcmlhYmxlIHR5cGUsIGxhYmVsIGZhY3RvciB2YXJpYWJsZSwgcmVzaGFwZSBkYXRhIGludG8gYSB0aWR5IGZvcm1hdCwgbXV0YXRlIG5ldyB2YXJpYWJsZSwgc2NhbiBvdXRsaWVycyBmb3IgbnVtZXJpYyB2YXJpYWJsZXMsIHRyYW5zZm9ybSBkYXRhLCBzY2FuIGVycm9ycyAobWlzc2luZyB2YWx1ZXMsIHNwZWNpYWwgdmFsdWVzLCBvYnZpb3VzIGVycm9ycywgYW5kIGluY29uc2lzdGVuY3kpIGFuZCB1c2UgdGhlIHRlY2huaXF1ZSB0byBkZWFsIHdpdGggZXJyb3JzIChtaXNzaW5nIHZhbHVlcywgc3BlY2lhbCB2YWx1ZXMsIG9idmlvdXMgZXJyb3JzLCBhbmQgaW5jb25zaXN0ZW5jeSkgYnkgb25seSB1c2luZyBwYWNrYWdlcyBvZiB0aWR5ciwgZHBseXIsIGVkaXRydWxlcywgZGVkdWNvcnJlY3QsIGFuZCBvdXRsaWVycy4gVGhpcyByZXBvcnQgYWltcyB0byBwcm92aWRlIGEgc2FtcGxlIG9mIGhvdyB0byBwcmVwcm9jZXNzIGRhdGFzZXRzLCB0aGUgc291cmNlIG9mIGRhdGFzZXRzIGlzIGFsbCBjb21lIGZyb20gdGhlIGdvdmVybm1lbnQgb2YgVklDIGh0dHBzOi8vd3d3LnZpYy5nb3YuYXUvLCB0aGV5IGFyZSBhbGwgb3BlbiBhbmQgaGF2ZSBhIENyZWF0aXZlIENvbW1vbnMgTGljZW5jZS4gCmBgYAoKYGBge3J9CiMgVGhpcyBpcyB0aGUgUiBjaHVuayBmb3IgdGhlIERhdGEgU2VjdGlvbgoKIyMgRGF0YQoKI0ltcG9ydCBkYXRhc2V0IGZyb20gd2Vic2l0ZSwgdGhpcyBkYXRhc2V0IGlzIGZyb20gdGhlIGdvdmVybm1lbnQgb2YgdmljdG9yaWEgYW5kIGl0J3Mgc291cmNlIHdlYnNpdGUgaXM6IGh0dHBzOi8vZGlzY292ZXIuZGF0YS52aWMuZ292LmF1L2RhdGFzZXQvYWxsLXNjaG9vbHMtZnRlLWVucm9sbWVudHMtZmViLTIwMTUuIFRoaXMgZGF0YXNldCBjb250YWlucyBpbmZvcm1hdGlvbiBjb2xsZWN0ZWQgZnJvbSB0aGUgRmVicnVhcnkgMjAxNCBzY2hvb2wgY2Vuc3VzIG9mIFZpY3RvcmlhbiBzY2hvb2xzIHVudGlsIEZlYnJ1YXJ5IDIwMTUuIFRoaXMgZGF0YXNldCBjb250YWlucyA1NCB2YXJpYWJsZXMgYnV0IHdlIGFyZSBnb2luZyB0byBzdWJzZXQgdG8gOSB2YXJpYWJsZXMgb3RoZXJ3aXNlIGl0IHdpbGwgYmUgdG9vIGxhcmdlIGFuZCB3aGVuIHdlIG1lcmdlIHZhcmlhYmxlcyB0b2dldGhlciBvciBtZXJnZSB0d28gZGF0YXNldHMgdG9nZXRoZXIsIFIgd2lsbCByZXBvcnRzIEVycm9yOiB2ZWN0b3IgbWVtb3J5IGV4aGF1c3RlZCAobGltaXQgcmVhY2hlZD8pLiBBZnRlciB3ZSBzdWJzZXQgdGhlIGRhdGEgc2V0LCB0aGVyZSB3aWxsIGJlIDkgdmFyaWFibGVzIGxlZnQ6IAoKIyJFZHVjYXRpb25fU2VjdG9yIjpJdCByZWZlcnMgdG8gZWR1Y2F0aW9uYWwgc2VjdG9yLgojIkVudGl0eV9UeXBlIjpJdCByZWZlcnMgdG8gdHlwZSBvZiBzY2hvb2wgZGlzdHJpY3QuICAgICAgIAojIlNjaG9vbF9ObyI6SXQgcmVmZXJzIHRvIHRoZSBjb2RlIHRoYXQgcmVwcmVzZW50IHRoZSBzY2hvb2wuCiMiU2Nob29sX05hbWUiOkl0IHJlZmVycyB0byB0aGUgbmFtZSBvZiBzY2hvb2wuICAgICAgICAgCiMiU2Nob29sX1R5cGUiOkl0IHJlZmVycyB0byB0aGUgdHlwZSBvZiBzY2hvb2wuICAgICAgICAgCiMiU2Nob29sX1N0YXR1cyI6SXQgcmVmZXJzIHRvIHRoZSBzdGF0dXMgb2Ygc2Nob29sLgojIlByZXAuTWFsZXMuVG90YWwuLiI6SXQgcmVmZXJzIHRvIHRoZSB0b3RhbCBudW1iZXIgb2YgcHJlcGFyYXRvcnkgbWFsZSBzdHVkZW50LgojIlByZXAuRmVtYWxlcy5Ub3RhbC4uIjpJdCByZWZlcnMgdG8gdGhlIHRvdGFsIG51bWJlciBvZiBwcmVwYXJhdG9yeSBmZW1hbGUgc3R1ZGVudC4KIyJQcmVwLlRvdGFsLi4iOkl0IHJlZmVycyB0byB0aGUgdG90YWwgbnVtYmVyIG9mIHByZXBhcmF0b3J5IHN0dWRlbnQuIAoKI0ltcG9ydCBkYXRhc2V0IGZyb20gd2Vic2l0ZS4KdXJsIDwtICJodHRwOi8vd3d3LmVkdWNhdGlvbi52aWMuZ292LmF1L0RvY3VtZW50cy9hYm91dC9yZXNlYXJjaC9kYXRhdmljL2R2MTcxLUZlYjIwMTVGVEVlbnJvbG1lbnRzLmNzdiIKQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTUgPC0gcmVhZC5jc3YodXJsLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgojV2UgbmVlZCB0byBzdWJzZXQgZGF0YSBiZWNhdXNlIHRoaXMgZGF0YXNldCBpcyB0b28gYmlnLCBpZiB3ZSBkb24ndCBzdWJzZXQgZGF0YXNldCwgdGhlbiB3aGVuIHdlIG1lcmdlIHZhcmlhYmxlcyB0b2dldGhlciBvciBtZXJnZSB0d28gZGF0YXNldHMgdG9nZXRoZXIsIFIgd2lsbCByZXBvcnRzIEVycm9yOiB2ZWN0b3IgbWVtb3J5IGV4aGF1c3RlZCAobGltaXQgcmVhY2hlZD8pLgpBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNSA8LSBzdWJzZXQoQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTUsIHNlbGVjdCA9IEVkdWNhdGlvbl9TZWN0b3I6UHJlcC5Ub3RhbC4uKQoKaGVhZChBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNSkKCgoKI0ltcG9ydCBkYXRhc2V0IGZyb20gYW5vdGhlciB3ZWJzaXRlLCB0aGlzIGRhdGFzZXQgaXMgZnJvbSB0aGUgZ292ZXJubWVudCBvZiB2aWN0b3JpYSBhbmQgaXQncyBzb3VyY2Ugd2Vic2l0ZSBpczogaHR0cHM6Ly9kaXNjb3Zlci5kYXRhLnZpYy5nb3YuYXUvZGF0YXNldC9hbGwtc2Nob29scy1mdGUtZW5yb2xtZW50cy1mZWItMjAxNi4gVGhpcyBkYXRhc2V0IGNvbnRhaW5zIGluZm9ybWF0aW9uIGNvbGxlY3RlZCBmcm9tIHRoZSBGZWJydWFyeSAyMDE1IHNjaG9vbCBjZW5zdXMgb2YgVmljdG9yaWFuIHNjaG9vbHMgdW50aWwgRmVicnVhcnkgMjAxNi4gVGhpcyBkYXRhc2V0IGFsc28gY29udGFpbnMgNTQgdmFyaWFibGVzIGJ1dCB3ZSBhcmUgZ29pbmcgdG8gc3Vic2V0IHRvIDkgdmFyaWFibGVzIGR1ZSB0byB0aGUgcHJvYmxlbSBvZiBsYXJnZSBkYXRhc2V0LiBBbmQgdGhlc2UgOSB2YXJpYWJsZXMgYXJlIHRoZSBzYW1lIGFzIHRoZSBwcmV2aW91cyBkYXRhc2V0LCBpdCBtZWFucyB0aGF0IHRoZXkgaGF2ZSB0aGUgc2FtZSB2YXJpYWJsZSBhbmQgYWxzbyB0aG9zZSB2YXJpYWJsZXMgaGF2ZSB0aGUgc2FtZSBtZWFuaW5nLgoKI0ltcG9ydCBkYXRhc2V0IGZyb20gd2Vic2l0ZS4KdXJsIDwtICJodHRwOi8vd3d3LmVkdWNhdGlvbi52aWMuZ292LmF1L0RvY3VtZW50cy9hYm91dC9yZXNlYXJjaC9kYXRhdmljL2R2MjE0LWFsbHNjaG9vbHNmZXRlbnJvbGZlYjIwMTYuY3N2IgpBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNiA8LSByZWFkLmNzdih1cmwsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCiNXZSB1c2UgYW50aV9qb2luKCkgZnVuY3Rpb24gdG8gb2J0YWluIHRoZSBkaWZmZXJlbnQgZGF0YSBmcm9tIHN0dWRlbnQgZW5yb2xtZW50cyBpbiAyMDE1IChOZXcgZGF0YSksIGJlY2F1c2Ugd2Ugd291ZGwgbGlrZSBtZXJnZSBhZGRpdGlvbmFsIGRhdGEgZnJvbSBzdHVkZW50IGVucm9sbWVudHMgaW4gMjAxNiB3aXRoIHN0dWRlbnQgZW5yb2xtZW50cyBpbiAyMDE2IGluIG5leHQgc3RlcC4KTmV3X0FsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE2IDwtIGFudGlfam9pbihBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNiwgQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTUsIGJ5ID0gIlNjaG9vbF9OYW1lIikKCiNUaGUgc2FtZSBzaXR1YXRpb24gaW4gdGhpcyBvbmUsIHdlIGhhdmUgdG8gbWluaW1pemUgZGF0YSBvdGhlcndpc2UsIFIgd2lsbCBnZW5lcmF0ZSBlcnJvciB3aGVuIG1lcmdlIDIgZGF0YXNldCBiZWNhdXNlIHRoZXkgYXJlIHRvbyBsYXJnZS4KTmV3X0FsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE2IDwtIHN1YnNldChOZXdfQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTYsIHNlbGVjdCA9IEVkdWNhdGlvbl9TZWN0b3I6UHJlcC5Ub3RhbC4uKQoKaGVhZChOZXdfQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTYpCgojV2UgdXNlIGJpbmRfcm93cygpIGZ1bmN0aW9uIHRvIG1lcmdlIHR3byBkYXRhc2V0cyBiZWNhdXNlIHRoZXkgaGF2ZSB0aGUgc2FtZSB2YXJpYWJsZXMuCkFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzIDwtIGJpbmRfcm93cyhBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNSwgTmV3X0FsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE2KQoKaGVhZChBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50cykKYGBgCgojIwlUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIEkgCgpgYGB7cn0KIyBUaGlzIGlzIHRoZSBSIGNodW5rIGZvciB0aGUgVGlkeSAmIE1hbmlwdWxhdGUgRGF0YSBJIAoKI1dlIHB1dCB0aGlzIHBhcnQgKFRpZHkgJiBNYW5pcHVsYXRlIERhdGEgSSkgcHJpb3IgdG8gdGhlIChVbmRlcnN0YW5kKSBwYXJ0IGlzIGJlY2F1c2UgdGhlcmUgd2lsbCBiZSBzb21lIHZhcmlhYmxlcyBjcmVhdGVkIGFmdGVyIHdlIHRpZHkgdGhpcyBkYXRhc2V0IGFuZCBpdCBpcyBiZXR0ZXIgdG8gY29udmVydCB2YXJpYWJsZSB0eXBlLCByZW5hbWUgdmFyaWFibGUsIHJlYXJyYW5nZSB2YXJpYWJsZXMgYWZ0ZXIgd2Ugc2V0IGRvd24gdGhlIGRhdGFzZXQuIAoKCgojVGhlIHByb2JsZW0gb2YgdGhpcyBkYXRhc2V0IGlzIHRoYXQgdGhlIGNvbHVtbiBuYW1lcyBhcmUgbm90IG5hbWVzIG9mIHZhcmlhYmxlcywgYnV0IHZhbHVlcyBvZiBhIHZhcmlhYmxlLiBJbiB0aGlzIGNhc2UsIHRoZSBjb2x1bW4gbmFtZXMgIlByZXAuTWFsZXMuVG90YWwuLiIsIGFuZCAiUHJlcC5GZW1hbGVzLlRvdGFsLi4iIHJlcHJlc2VudCB2YWx1ZXMgb2YgdGhlIGdlbmRlciB2YXJpYWJsZSwgYW5kIGVhY2ggcm93IHJlcHJlc2VudHMgdHdvIG9ic2VydmF0aW9ucywgbm90IG9uZS4gCmhlYWQoQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHMpCgojVGhlcmVmb3JlLCB3ZSB1c2UgZ2F0aGVyKCkgZnVuY3Rpb24gdG8gbWVyZ2UgdHdvIHZhcmlhYmxlcyBpbnRvIGEgZmFjdG9yIHZhcmlhYmxlIGFuZCBhbHNvIGNyZWF0ZSBhIG5ldyB2YXJpYWJsZSB3aGljaCBpcyBjYWxsZWQgIk51bWJlcl9vZl9zdHVkZW50cyIuCkFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIgPC0gQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHMgJT4lCmdhdGhlcihgUHJlcC5NYWxlcy5Ub3RhbC4uYCwgYFByZXAuRmVtYWxlcy5Ub3RhbC4uYCwga2V5ID0gIkdlbmRlciIsIHZhbHVlID0gIk51bWJlcl9vZl9zdHVkZW50cyIpCgpoZWFkKEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIpCgoKYGBgCgojIyBVbmRlcnN0YW5kIAoKYGBge3J9CiMgVGhpcyBpcyB0aGUgUiBjaHVuayBmb3IgdGhlIFVuZGVyc3RhbmQgU2VjdGlvbgoKI1JlYXJyYW5nZSBhbmQgcmVuYW1lIGFuZCByZWFycmFuZ2UgdmFyaWFibGVzCiNXZSBmaXJzdCBjaGVjayB0aGUgb3JkZXIgb2YgdmFyaWFibGVzLiAKc3RyKEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIpCgojV2UgdXNlIHNlbGVjdCgpIGZ1bmN0aW9uIHRvIHJlYXJyYW5nZSB0aGUgb3JkZXIgb2YgdmFyaWFibGVzLgpBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yIDwtIEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIgJT4lIHNlbGVjdChTY2hvb2xfTmFtZSwgU2Nob29sX05vLCBTY2hvb2xfVHlwZSwgU2Nob29sX1N0YXR1cywgRWR1Y2F0aW9uX1NlY3RvciwgRW50aXR5X1R5cGUsIEdlbmRlciwgTnVtYmVyX29mX3N0dWRlbnRzLCBQcmVwLlRvdGFsLi4pCgojR2l2ZW4gdGhhdCB3ZSBnYXRoZXIgdHdvIHZhcmlhYmxlcyB0b2dldGhlciB0byBidWlsZCB1cCBhIGZhY3RvciB2YXJpYWJsZSAiR2VuZGVyIi4gV2Ugc2hvdWxkIHJlbmFtZSB0aGUgbGV2ZWxzIG9mICJHZW5kZXIiLgojVGhlbiwgdXNlIGxldmVscygpIGZ1bmN0aW9uIHRvIGNoZWNrIHRoZSBsZXZlbCBuYW1lIG9mIHRoaXMgdmFyaWFibGUuCmxldmVscyhBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yJEdlbmRlcikKCiNXZSB1c2UgbGFiZWwoKSBmdW5jdGlvbiB0byByZS1sYWJlbCB0aGUgbmFtZSBvZiBsZXZlbHMgaW4gYSBmYWN0b3IgdmFyaWFibGUuCkFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIkR2VuZGVyIDwtIGZhY3RvcihBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yJEdlbmRlcixsZXZlbHMgPSBjKCJQcmVwLkZlbWFsZXMuVG90YWwuLiIsIlByZXAuTWFsZXMuVG90YWwuLiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiRmVtYWxlIiwiTWFsZSIpKQoKI1dlIGFsc28gbm90aWNlIHRoYXQgdGhlIHZhcmlhYmxlIG5hbWUgb2YgIlByZXAuVG90YWwuLiIgZG9lc24ndCBsb29rIGdvb2QgKGJlY2F1c2UgdGhlcmUgYXJlIHNvbWUgIi4uIiBpbiB0aGUgbmFtZSkgYW5kICJOdW1iZXJfb2Zfc3R1ZGVudHMiIHNob3VsZCBhY3R1YWxseSBiZSAiTnVtYmVyX29mX3ByZS5zdHVkZW50Ii4KI1dlIHVzZSByZW5hbWUoKSBmdW5jdGlvbiB0byByZW5hbWUgdmFyaWFibGVzLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIApBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yIDwtIEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIgJT4lIAogIHJlbmFtZSgKICAgIFRvdGFsX251bWJlcl9vZl9wcmUuc3R1ZGVudF9mb3Jfc2Nob29sID0gUHJlcC5Ub3RhbC4uCiAgICAsIE51bWJlcl9vZl9wcmUuc3R1ZGVudCA9IE51bWJlcl9vZl9zdHVkZW50cwogICkKCiNDaGVjayB0aGUgdmFyaWFibGVzIGFuZCBvcmRlciBhZ2FpbiwgdGhpcyBhbHNvIHByb3ZlIHRoYXQgdGhpcyBkYXRhc2V0IGNvbnRhaW5zIG11bHRpcGxlIGRhdGEgdHlwZXMgKG51bWVyaWNzLCBjaGFyYWN0ZXJzLCBmYWN0b3JzKS4Kc3RyKEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIpCgoKCiNDb252ZXJ0IHZhcmlhYmxlIHR5cGUKI05vdGljZSB0aGF0ICJFZHVjYXRpb25fU2VjdG9yIiBoYXMgc29tZSB2YWx1ZXMgYXJlIHRoZSBzYW1lLCBzbyB0cnkgdG8gY292ZXJ0IGl0IGludG8gZmFjdG9yIHZhcmlhYmxlLgpBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yJEVkdWNhdGlvbl9TZWN0b3IgPC0gYXMuZmFjdG9yKEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIkRWR1Y2F0aW9uX1NlY3RvcikKCmlzLmZhY3RvcihBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yJEVkdWNhdGlvbl9TZWN0b3IpCgojQ2hlY2sgdGhlIGxldmVscyBvZiB0aGlzIHZhcmlhYmxlLCBhbmQgdGhlIHJlc3VsdCBpcyB0aGF0IHRoZXJlIGFyZSBvbmx5IDMgbGV2ZWxzLiBUaGlzIGNvbmZpcm1zIG15IGd1ZXNzIGFuZCB0aGlzIHZhcmlhYmxlIHNob3VsZCBhY3R1YWxseSBiZSBhIGZhY3RvciB2YXJpYWJsZS4KbGV2ZWxzKEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIkRWR1Y2F0aW9uX1NlY3RvcikKCgojRW50aXR5X1R5cGUgaXMgb2J2aW91c2x5IGEgZmFjdG9yIHZhcmlhYmxlIGJ1dCBSIGluZGljYXRlIHRoYXQgYXMgaW50LiBTbywgd2UgbmVlZCB0byBjb252ZXJ0IGl0IGludG8gZmFjdG9yIHZhcmlhYmxlLgpBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yJEVudGl0eV9UeXBlIDwtIGFzLmZhY3RvcihBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yJEVudGl0eV9UeXBlKQoKaXMuZmFjdG9yKEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIkRW50aXR5X1R5cGUpCgojVG8gZW5zdXJlIHRoYXQgdGhpcyB2YXJpYWJsZSBpcyBhIGZhY3RvciB2YXJpYWJsZSwgd2UgY2hlY2sgdGhlIGxldmVscyBmb3IgdGhpcyB2YXJpYWJsZSBhbmQgdGhlIHJlc3VsdCBpcyB0aGF0IHRoZXJlIGFyZSBvbmx5IDIgbGV2ZWxzLiBUaGlzIGNvbmZpcm1zIG15IGd1ZXNzIGFuZCB0aGlzIHZhcmlhYmxlIHNob3VsZCBhY3R1YWxseSBiZSBhIGZhY3RvciB2YXJpYWJsZS4KbGV2ZWxzKEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIkRW50aXR5X1R5cGUpCgoKCiNTY2hvb2xfVHlwZSBpcyBvYnZpb3VzbHkgYSBmYWN0b3IgdmFyaWFibGUgYnV0IFIgaW5kaWNhdGUgdGhhdCBhcyBjaHIuIFNvLCB3ZSBuZWVkIHRvIGNvbnZlcnQgaXQgaW50byBmYWN0b3IgdmFyaWFibGUuCkFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIkU2Nob29sX1R5cGUgPC0gYXMuZmFjdG9yKEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIkU2Nob29sX1R5cGUpCgppcy5mYWN0b3IoQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfMiRTY2hvb2xfVHlwZSkKCiNUbyBlbnN1cmUgdGhhdCB0aGlzIHZhcmlhYmxlIGlzIGEgZmFjdG9yIHZhcmlhYmxlLCB3ZSBjaGVjayB0aGUgbGV2ZWxzIGZvciB0aGlzIHZhcmlhYmxlIGFuZCB0aGUgcmVzdWx0IGlzIHRoYXQgdGhlcmUgYXJlIG9ubHkgNSBsZXZlbHMuIFRoaXMgY29uZmlybXMgbXkgZ3Vlc3MgYW5kIHRoaXMgdmFyaWFibGUgc2hvdWxkIGFjdHVhbGx5IGJlIGEgZmFjdG9yIHZhcmlhYmxlLgpsZXZlbHMoQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfMiRTY2hvb2xfVHlwZSkKCgoKI05vdGljZSB0aGF0ICJTY2hvb2xfU3RhdHVzIiBoYXMgc29tZSB2YWx1ZXMgYXJlIHRoZSBzYW1lLCBzbyB0cnkgdG8gY292ZXJ0IGl0IGludG8gZmFjdG9yIHZhcmlhYmxlLgpBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yJFNjaG9vbF9TdGF0dXMgPC0gYXMuZmFjdG9yKEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIkU2Nob29sX1N0YXR1cykKCmlzLmZhY3RvcihBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yJFNjaG9vbF9TdGF0dXMpCgojQ2hlY2sgdGhlIGxldmVscyBvZiB0aGlzIHZhcmlhYmxlLCBhbmQgdGhlIHJlc3VsdCBpcyB0aGF0IHRoZXJlIGFyZSBvbmx5IDIgbGV2ZWxzLiBUaGlzIGNvbmZpcm1zIG15IGd1ZXNzIGFuZCB0aGlzIHZhcmlhYmxlIHNob3VsZCBhY3R1YWxseSBiZSBhIGZhY3RvciB2YXJpYWJsZS4KbGV2ZWxzKEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIkU2Nob29sX1N0YXR1cykKCgoKI1RoaXMgdmFyaWFibGUgaGFzIHRvIGJlIGludGVnZXIgYmVjYXVzZSBpdCBjYW4ndCBiZSBoYWxmIHN0dWRlbnQuCkFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIkTnVtYmVyX29mX3ByZS5zdHVkZW50IDwtIGFzLmludGVnZXIoQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfMiROdW1iZXJfb2ZfcHJlLnN0dWRlbnQpCmlzLmludGVnZXIoQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfMiROdW1iZXJfb2ZfcHJlLnN0dWRlbnQpCgoKCiNUaGlzIHZhcmlhYmxlIGhhcyB0byBiZSBpbnRlZ2VyIGJlY2F1c2UgaXQgY2FuJ3QgYmUgaGFsZiBzdHVkZW50LgpBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yJFRvdGFsX251bWJlcl9vZl9wcmUuc3R1ZGVudF9mb3Jfc2Nob29sIDwtIGFzLmludGVnZXIoQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfMiRUb3RhbF9udW1iZXJfb2ZfcHJlLnN0dWRlbnRfZm9yX3NjaG9vbCkKaXMuaW50ZWdlcihBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yJFRvdGFsX251bWJlcl9vZl9wcmUuc3R1ZGVudF9mb3Jfc2Nob29sKQoKI0NoZWNrIHRoZSB2YXJpYmFsZSB0eXBlIGFnYWluIHRvIG1ha2Ugc3VyZSBldmVyeXRoaW5nIGlzIGdvb2QuIApzdHIoQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfMikKCmBgYAoKIyMJVGlkeSAmIE1hbmlwdWxhdGUgRGF0YSBJSSAKCmBgYHtyfQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBUaWR5ICYgTWFuaXB1bGF0ZSBEYXRhIElJIAoKI011dGF0ZSBuZXcgdmFyaWFibGUKI1VzZSBtdXRhdGUoKSBmdW5jdGlvbiB0byBjcmVhdGUgYSBuZXcgdmFyaWFibGUuIFRoaXMgbmV3IHZhcmlhYmxlIGlzIHRoZSBzZXggcHJvcG9ydGlvbiBpbiB0ZXJtcyBvZiBtYWxlIGFuZCBmZW1hbGUgZm9yIGVhY2ggc2Nob29sLiBBbmQgaXQncyBmb3JtdWxhIGlzOiBTZXhfcHJvcG9ydGlvbl9mb3JfdGhlX3ByZS5zdHVkZW50X2luX3NjaG9vbCA9IE51bWJlcl9vZl9wcmUuc3R1ZGVudCAvIFRvdGFsX251bWJlcl9vZl9wcmUuc3R1ZGVudF9mb3Jfc2Nob29sLgpBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yIDwtIG11dGF0ZShBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yLApTZXhfcHJvcG9ydGlvbl9mb3JfdGhlX3ByZS5zdHVkZW50X2luX3NjaG9vbCA9IE51bWJlcl9vZl9wcmUuc3R1ZGVudCAvIFRvdGFsX251bWJlcl9vZl9wcmUuc3R1ZGVudF9mb3Jfc2Nob29sCikKCiNDaGVjayBpZiB3ZSBjcmVhdGUgIlNleF9wcm9wb3J0aW9uX2Zvcl90aGVfcHJlLnN0dWRlbnRfaW5fc2Nob29sIiBzdWNjZXNzZnVsbHkuCnN0cihBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yKQpgYGAKCiMjCVNjYW4gSSAKCmBgYHtyfQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBTY2FuIEkKCiNTb21ldGltZXMgZGF0YXNldCBjYW4gaGF2ZSBvYmlvdXMgZXJyb3JzLiBGb3IgZXhhbXBsZSwgc2V4IHByb3BvcnRpb24gY2Fubm90IGJlIG5lZ2F0aXZlIG9yIGJleW9uZCAxLiBGb3IgY2hlY2tpbmcgdGhlc2UgaW5jb25zaXN0ZW5jeSwgd2Ugd291bGQgbGlrZSB0byBhcHBseSBydWxlcyB0byBjaGVjayB3aGV0aGVyIHRoaXMgZGF0YXNldCB2aW9sYXRlcyB0aGUgcnVsZSBieSB1c2luZyBlZGl0ZmlsZSgpIGZ1bmN0aW9uLiBBbmQgYWxzbywgd2UgY291bGQgYWxzbyBhcHBseSBydWxlcyB0byBjb3JyZWN0IGVycm9ycyBieSB1c2luZyBjb3JyZWN0aW9uUnVsZXMoKSBmdW5jdGlvbi4gV2hlbiB0aGUgbnVtYmVyIG9mIHJ1bGVzIGluY3JlYXNlLCBpdCBpcyBiZXR0ZXIgdG8gbWFuYWdlIHRoZSBydWxlcyBzZXBhcmF0ZSBmcm9tIHRoZSBkYXRhLiBUaGUgZnVuY3Rpb24gb2YgZWRpdHJ1bGVzKCkgY2FuIGNoZWNrIHdoaWNoIHJ1bGVzIGFyZSBvYmV5ZWQgb3Igbm90IGFuZCBhbGxvd3Mgb25lIHRvIGZpbmQgdGhlIG1pbmltYWwgc2V0IG9mIHZhcmlhYmxlcyB0byBhZGFwdCBzbyB0aGF0IGFsbCBydWxlcyBjYW4gYmUgb2JleWVkLiBJbiBhZGRpdGlvbixjb3JyZWN0aW9uUnVsZXMoKSBmdW5jdGlvbiBmb3JjZSB2YXJpYWJsZXMgdG8gZm9sbG93IGl0J3MgY29uc3RyYWludHMgc28gdGhhdCwgaXQgaXMgdmVyeSBoZWxwZnVsIHdoZW4gY29ycmVjdGluZyBkYXRhLiBJbiB0aGlzIHBhcnQsIHdlIGFyZSBnb2luZyB0byB1c2luZyBlZGl0cnVsZXMoKSBhbmQgY29ycmVjdGlvblJ1bGVzKCkgdG8gZGVhbCB3aXRoIGluY29uc2lzdGVuY3kuCgojVGhlIGZpcnN0IHRoaW5nIGlzIHRvIGNoZWNrIHRoZSBjb25zaXN0ZW5jeSBvZiAiVG90YWxfbnVtYmVyX29mX3ByZS5zdHVkZW50X2Zvcl9zY2hvb2wiID0gIk51bWJlcl9vZl9wcmUuc3R1ZGVudCIgZm9yIG1hbGUgKyAiTnVtYmVyX29mX3ByZS5zdHVkZW50IiBmb3IgZmVtYWxlLgojSXQgaXMgbW9yZSBjb252ZW5pZW50IHRvIGNoZWNrIHRoZSBjb25zaXN0ZW5jeSBvZiAiVG90YWxfbnVtYmVyX29mX3ByZS5zdHVkZW50X2Zvcl9zY2hvb2wiID0gIk51bWJlcl9vZl9wcmUuc3R1ZGVudCIgZm9yIG1hbGUgKyAiTnVtYmVyX29mX3ByZS5zdHVkZW50IiBmb3IgZmVtYWxlIGJ5IHNwcmVhZGluZyB0aGUgIkdlbmRlciIgb3V0LgojV2UgZmluZCBvdXQgdGhhdCB0aGVyZSBpcyBhIHZhcmlhYmxlIHByZXZlbnQgdXMgdG8gc3ByZWFkICJHZW5kZXIiIG91dCBpbiAiQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfMiIsIHdoaWNoIGlzIGNhbGxlZCAiU2V4X3Byb3BvcnRpb25fZm9yX3RoZV9wcmUuc3R1ZGVudF9pbl9zY2hvb2wiLiAKI1RoYXQgaXMgYmVjYXVzZSAiU2V4X3Byb3BvcnRpb25fZm9yX3RoZV9wcmUuc3R1ZGVudF9pbl9zY2hvb2wiID0gIk51bWJlcl9vZl9wcmUuc3R1ZGVudCIvIlRvdGFsX251bWJlcl9vZl9wcmUuc3R1ZGVudF9mb3Jfc2Nob29sIi4gQW5kIHdoZW4gd2Ugc3ByZWFkICJHZW5kZXIiIG91dCwgaXQgd2lsbCBwcm9kdWNlIG1hbnkgTmFOIHZhbHVlcy4KI0FuZCB0aGlzIGlzIHdoeSB3ZSBzaG91bGQgZXhjbHVkZSAiU2V4X3Byb3BvcnRpb25fZm9yX3RoZV9wcmUuc3R1ZGVudF9pbl9zY2hvb2wiIGZpcnN0IGFuZCB0aGVuIHNwcmVhZCAiR2VuZGVyIiBvdXQuCkRhdGFfZm9yX2NoZWNraW5nX2luY29uc2lzdGVuY3kxID0gc3Vic2V0KEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzIsIHNlbGVjdCA9IC1TZXhfcHJvcG9ydGlvbl9mb3JfdGhlX3ByZS5zdHVkZW50X2luX3NjaG9vbCApCgojQW5kIHRoZW4gd2UgdXNlIHNwcmVhZCgpIGZ1bmN0aW9uIHRvIHNwcmVhZCBpdCBvdXQuCkRhdGFfZm9yX2NoZWNraW5nX2luY29uc2lzdGVuY3kyIDwtIHNwcmVhZChEYXRhX2Zvcl9jaGVja2luZ19pbmNvbnNpc3RlbmN5MSwga2V5ID0gR2VuZGVyLCB2YWx1ZSA9IE51bWJlcl9vZl9wcmUuc3R1ZGVudCkKCiNJbXBvcnQgcnVsZXMgaW50byBSClJ1bGVzMSA8LSBlZGl0ZmlsZSgiL1VzZXJzL21hY2Jvb2svRG9jdW1lbnRzL1JNSVQtTWFzdGVyIG9mIEFuYWx5dGljcy9EYXRhIHdyYW5nbGluZy9lZGl0cnVsZXMyLnR4dCIsIHR5cGUgPSAiYWxsIikKClJ1bGVzMQoKI1VzZSBzdW1tYXJ5KCkgZnVuY3Rpb24gdG8gYXZvaWQgdGhlIHByb2JsZW0gb2YgbGFyZ2UgZGF0YSBzaXplLgpWaW9sYXRlZDEgPC0gdmlvbGF0ZWRFZGl0cyhSdWxlczEsIERhdGFfZm9yX2NoZWNraW5nX2luY29uc2lzdGVuY3kyKQoKc3VtbWFyeShWaW9sYXRlZDEpCgojVGhlIHJlc3VsdCBzaG93cyB0aGF0IHRoaXMgZGF0YSBkb2VzIGhhdmUgc29tZSBlcnJvcnMuCgoKCiNUbyBjb3JyZWN0IHRob3NlIGVycm9ycywgd2UgaW1wb3J0IHJ1bGVzIGZvciBjb3JyZWN0aW9uLgpSdWxlczIgPC0gY29ycmVjdGlvblJ1bGVzKCIvVXNlcnMvbWFjYm9vay9Eb2N1bWVudHMvUk1JVC1NYXN0ZXIgb2YgQW5hbHl0aWNzL0RhdGEgd3JhbmdsaW5nL2VkaXRydWxlczMudHh0IikKClJ1bGVzMgoKI0FwcGx5IHJ1bGVzIGludG8gdGhlIGRhdGEgdGhhdCBjb250YWlucyBlcnJvcnMuCmNvciA8LSBjb3JyZWN0V2l0aFJ1bGVzKFJ1bGVzMiwgRGF0YV9mb3JfY2hlY2tpbmdfaW5jb25zaXN0ZW5jeTIpCgojQW5kIHRoZW4sIGNoZWNrIGl0IGFnYWluIHdoZXRoZXIgd2Ugc3VjY2Vzc2Z1bGx5IGNvcnJlY3QgZXJyb3JzLgojVXNlIHN1bW1hcnkoKSBmdW5jdGlvbiB0byBhdm9pZCB0aGUgcHJvYmxlbSBvZiBsYXJnZSBkYXRhIHNpemUuClZpb2xhdGVkMiA8LSB2aW9sYXRlZEVkaXRzKFJ1bGVzMSwgY29yJGNvcnJlY3RlZCkKCnN1bW1hcnkoVmlvbGF0ZWQyKQoKCgojQW5kIHRoZW4sIGFmdGVyIGNvcnJlY3RpbmcgdGhlIGRhdGEsIHdlIHB1dCAiU2V4X3Byb3BvcnRpb25fZm9yX3RoZV9wcmUuc3R1ZGVudF9pbl9zY2hvb2wiIGJhY2sgaW50byB0aGUgZGF0YXNldC4KI1RoZSBmaXJzdCB0aGluZyBpcyB0byByZXNoYXBlIHRoZSBkYXRhc2V0IG9mICJEYXRhX2Zvcl9jaGVja2luZ19pbmNvbnNpc3RlbmN5MiIuCkFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzMgPC0gRGF0YV9mb3JfY2hlY2tpbmdfaW5jb25zaXN0ZW5jeTIgJT4lCiAgZ2F0aGVyKGBNYWxlYCwgYEZlbWFsZWAsIGtleSA9ICJHZW5kZXIiLCB2YWx1ZSA9ICJOdW1iZXJfb2ZfcHJlLnN0dWRlbnQiKQoKI0FuZCB0aGVuLCBwdXQgIlNleF9wcm9wb3J0aW9uX2Zvcl90aGVfcHJlLnN0dWRlbnRfaW5fc2Nob29sIiBiYWNrIGludG8gdGhlIGRhdGFzZXQuCkFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzMgPC0gbXV0YXRlKEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNleF9wcm9wb3J0aW9uX2Zvcl90aGVfcHJlLnN0dWRlbnRfaW5fc2Nob29sID0gTnVtYmVyX29mX3ByZS5zdHVkZW50IC8gVG90YWxfbnVtYmVyX29mX3ByZS5zdHVkZW50X2Zvcl9zY2hvb2wKKQoKI0FuZCB0aGVuLCByZWFycmFuZ2UgdGhlIHNlcXVlbmNlIG9mIHZhcmlhYmxlcy4KQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfMyA8LSBBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18yICU+JSBzZWxlY3QoU2Nob29sX05hbWUsIFNjaG9vbF9ObywgU2Nob29sX1R5cGUsIFNjaG9vbF9TdGF0dXMsIEVkdWNhdGlvbl9TZWN0b3IsIEVudGl0eV9UeXBlLCBHZW5kZXIsIE51bWJlcl9vZl9wcmUuc3R1ZGVudCwgVG90YWxfbnVtYmVyX29mX3ByZS5zdHVkZW50X2Zvcl9zY2hvb2wsIFNleF9wcm9wb3J0aW9uX2Zvcl90aGVfcHJlLnN0dWRlbnRfaW5fc2Nob29sKQoKCgojVGhlIHNlY29uZCB0aGluZyBpcyB0byBjaGVjayBpbmlmaXRlIHZhbHVlLCBzcGVjaWFsIHZhbHVlLCBhbmQgbWlzc2luZyB2YWx1ZS4gRm9yIGNvbnZlbmllbmNlLCB3ZSBmaXJzdCBidWlsZCB1cCBhIGZ1bmN0aW9uIHRvIGJldHRlciBkZWFsIHdpdGggbWlzc2luZyB2YWx1ZXMsIGluZmluaXRlIHZhbHVlcywgYW5kIE5hTiB2YWx1ZXMuIFdlIGFjdXRhbGx5IHdvdWxkIGxpa2UgdG8gdXNlIHNhcHBseSgpIGZ1bmN0aW9uIHRvIGxvb2sgZm9yIGVycm9ycyBidXQgdGhpcyBmdW5jdGlvbiBjb3VsZCBub3QgZGVhbCB3aXRoIE5hTiB2YWx1ZXMuIFRodXMsIHdlIHNob3VsZCB3cml0ZSB1cCBhIGZ1bmN0aW9uIHRvIGRlYWwgd2l0aCBOYU4gdmFsdWVzLgppcy5zcGVjaWFsb3JOQSA8LSBmdW5jdGlvbih4KXsKICBpZiAoaXMubnVtZXJpYyh4KSkgKGlzLmluZmluaXRlKHgpIHwgaXMubmFuKHgpIHwgaXMubmEoeCkpCn0KCiNUaGVyZSBhcmUgOTMyIG5hIHZhbHVlIGZvciBjb2x1bW4gIlNleF9wcm9wb3J0aW9uX2Zvcl90aGVfcHJlLnN0dWRlbnRfaW5fc2Nob29sIgpzYXBwbHkoQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfMywgZnVuY3Rpb24oeCkgc3VtKCBpcy5uYSh4KSApKQoKI1RoZXJlIGFyZSAwIGluZmluaXRlIHZhbHVlIGZvciB0aGlzIGRhdGFzZXQKc2FwcGx5KEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzMsIGZ1bmN0aW9uKHgpIHN1bSggaXMuaW5maW5pdGUoeCkgKSkKCiNUaGVyZSBhcmUgOTMyIE5hTiB2YWx1ZSBmb3IgY29sdW1uICJTZXhfcHJvcG9ydGlvbl9mb3JfdGhlX3ByZS5zdHVkZW50X2luX3NjaG9vbCIKc2FwcGx5KEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzMsIGZ1bmN0aW9uKHgpIHN1bSggaXMubmFuKHgpICkpCgojTmFOIG1lYW5zICJub3QgYSBudW1iZXIiLiBXaGVuIFIgZ2VuZXJhdGUgTmFOLCBpdCBtZWFucyB0aGF0IHRoZSB2YWx1ZSBqdXN0IG1ha2VzIGEgbGl0dGxlIHNlbnNlLiBJbiB0aGlzIGNhc2UsIHdlIGZpbmQgb3V0IGEgbG90IG9mIE5hTnMgaW4gdGhlIHZhcmlhYmxlIG9mIOKAnFNleF9wcm9wb3J0aW9uX2Zvcl90aGVfcHJlLnN0dWRlbnRfaW5fc2Nob29s4oCdLCB3aGljaCBpcyBjYWxjdWxhdGVkIGJ5IHRoZSBmb3JtdWxhIG9mOgojU2V4X3Byb3BvcnRpb25fZm9yX3RoZV9wcmUuc3R1ZGVudF9pbl9zY2hvb2wgPSBOdW1iZXJfb2ZfcHJlLnN0dWRlbnQgLyBUb3RhbF9udW1iZXJfb2ZfcHJlLnN0dWRlbnRfZm9yX3NjaG9vbC4gCiNOdW1iZXJfb2ZfcHJlLnN0dWRlbnQgY2FuIGJlIDAgYW5kIFRvdGFsX251bWJlcl9vZl9wcmUuc3R1ZGVudF9mb3Jfc2Nob29sIGNhbiBiZSAwIGVpdGhlci4gVGhlIGlzIHRoZSByZWFzb24gb2YgTmFOIGJlY2F1c2Ugd2hlbiAwIGRpdmlkZWQgYnkgMCwgaXQgaXMgbWVhbmluZ2xlc3MgYW5kIHRoYXTigJlzIHdoeSBSIGdlbmVyYXRlIE5hTiBhcyB0aGUgcmVzdWx0LiBUbyBmaXggdGhpcyBzcGVjaWFsIHZhbHVlLCB3ZSBjYW4ganVzdCBjb3ZlcnQgTmFOIHRvIDAgZGlyZWN0bHkuIApBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18zJFNleF9wcm9wb3J0aW9uX2Zvcl90aGVfcHJlLnN0dWRlbnRfaW5fc2Nob29sW0FsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzMkU2V4X3Byb3BvcnRpb25fZm9yX3RoZV9wcmUuc3R1ZGVudF9pbl9zY2hvb2wgPT0gIk5hTiIgXSA8LSAwCgojQW5kIHRoZW4sIGNoZWNrIGl0IGFnYWluIHdoZXRoZXIgd2UgZWxpbWluYXRlIGFsbCBOYU4gdmFsdWVzIGFuZCBOYSB2YWx1ZXMuCnNhcHBseShBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18zLCBmdW5jdGlvbih4KSBzdW0oIGlzLm5hKHgpICkpCgpzYXBwbHkoQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfMywgZnVuY3Rpb24oeCkgc3VtKCBpcy5uYW4oeCkgKSkKCiNXZSBzdWNjZXNzZnVsbHkgcmVtb3ZlIGFsbCBOYU4gdmFsdWVzIGFuZCBOYSB2YWx1ZXMuCgoKCiNUaGUgdGhpcmQgdGhpbmcgaXMgdG8gY2hlY2sgaW5jb2Vuc2lzdGVuY3ksIGFuZCB3ZSBkbyB0aGUgc2FtZSB0aGluZyBhcyB3aGF0IHdlIGRvbmUgcHJldmlvdXNseS4KI0ZpcnRzLCB3ZSBpbXBvcnQgcnVsZXMgaW50byBSLgpSdWxlczMgPC0gZWRpdGZpbGUoIi9Vc2Vycy9tYWNib29rL0RvY3VtZW50cy9STUlULU1hc3RlciBvZiBBbmFseXRpY3MvRGF0YSB3cmFuZ2xpbmcvZWRpdHJ1bGVzLnR4dCIsIHR5cGUgPSAiYWxsIikKClJ1bGVzMwoKI1VzZSBzdW1tYXJ5KCkgZnVuY3Rpb24gdG8gYXZvaWQgdGhlIHByb2JsZW0gb2YgbGFyZ2UgZGF0YSBzaXplLgoKVmlvbGF0ZWQzIDwtIHZpb2xhdGVkRWRpdHMoUnVsZXMzLCBBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18zKQoKc3VtbWFyeShWaW9sYXRlZDMpCgojRm9ydHVuYXRlbHksIHdlIGRvbid0IGhhdmUgYW55IGluY29uc2lzdGVuY2llcy4gCmBgYAoKIyMJVHJhbnNmb3JtIAoKYGBge3J9CiMgVGhpcyBpcyB0aGUgUiBjaHVuayBmb3IgdGhlIFRyYW5zZm9ybSBTZWN0aW9uCgoKIzcgRGF0YSB0cmFuc2Zvcm1hdGlvbgojVGhlIHJlYW9zbiB0byBwdXQgImRhdGEgdHJhbnNmb3JtYXRpb24iIHByaW9yIHRvIHRoZSAiU2NhbiBJSSIgaXMgdGhhdCB3ZSBoYXZlIGRhdGEgd2hvIGhhcyByaWdodC1za2V3ZWQgZGlzdHJpYnV0aW9uLiBBbmQgd2UgZGVjaWRlIHRvIHVzZSB6LXNjb3JlcyBtZXRob2QgaW4gb3JkZXIgdG8gbG9jYXRlIHdoZXJlIGFyZSB0aGUgb3V0bGllcnMuIAojVGhlcmVmb3JlLCB3ZSBoYXZlIHRvIHRyYW5zZm9ybSBkYXRhIGZyb20gcmlnaHQtc2tld2VkIGRpc3RyaWJ1dGlvbiB0byBhcHByb3hpbWF0ZWx5IG5vcm1hbCBkaXN0cmlidXRpb24gZmlyc3QuIApoaXN0KEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzMkU2V4X3Byb3BvcnRpb25fZm9yX3RoZV9wcmUuc3R1ZGVudF9pbl9zY2hvb2wpCgojQmFzZWQgb24gdGhlIHZhcmlhYmxlICJTZXhfcHJvcG9ydGlvbl9mb3JfdGhlX3ByZS5zdHVkZW50X2luX3NjaG9vbCIsIGl0IGNvbnRhaW5zIDAgdmFsdWVzIGFuZCBpdCBpcyByaWdodC1za2V3ZWQuCiNXZSBmaXJzdCB0cnkgdG8gdXNlIHNxdWFyZSByb290IHRyYW5zZm9ybWF0aW9uIHRvIGRlYWwgd2l0aCB0aGlzIGRhdGEgYmVjYXVzZSB0aGlzIGRhdGEgaGFzIDAgdmFsdWVzIGFuZCBpdCBpcyByZWlnaHQtc2tld2VkLgpzcXJ0X3NhbGFyeSA8LSBzcXJ0KEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzMkU2V4X3Byb3BvcnRpb25fZm9yX3RoZV9wcmUuc3R1ZGVudF9pbl9zY2hvb2wpCmhpc3Qoc3FydF9zYWxhcnkpCgojQXMgcmVzdWx0LCBpdCBpcyBzdGlsbCByaWdodCBza2V3ZWQgYW5kIHN0aWxsIG5lZWQgdG8gYmUgaW1wcm92ZWQuCgojV2Ugbm90ZSB0aGF0IHRoaXMgZGF0YSBjb250cmFpbnMgMCB2YWx1ZXMgb3IgMSB2YWx1ZXMsIGFuZCBpdCBpcyBiZWNhdXNlIHRoZXJlIGFyZSBzb21lIGFsbC1tYWxlIHNjaG9vbCBvciBhbGwtZmVtYWxlIHNjaG9vbC4KI1doZW4gaW52ZXN0aWdhdGluZyBzZXggcG9ycG9yaW9uLCBpdCBpcyBtZWFuaW5nbGVzcyB0byBpbnZlc3RpZ2F0ZSB3aGF0IHBlcmNlbnRhZ2Ugb2YgbWFsZSBzdHVkZW50IGluIGEgYWxsLWZlbWFsZSBzY2hvb2wgb3Igd2hhdCBwZXJjZW50YWdlIG9mIGZlbWFsZSBzdHVkZW50IGluIGFsbC1tYWxlIHNjaG9vbC4KI1RoZXJlZm9yZSwgd2Ugc2hvdWxkIHJlbW92ZSAwIHZhbHVlIGFuZCAxIHZhbHVlLiAKc3Vic2V0X25vXzBfMSA8LSBBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18zICU+JSBmaWx0ZXIoU2V4X3Byb3BvcnRpb25fZm9yX3RoZV9wcmUuc3R1ZGVudF9pbl9zY2hvb2wgIT0gIjAiICYgU2V4X3Byb3BvcnRpb25fZm9yX3RoZV9wcmUuc3R1ZGVudF9pbl9zY2hvb2wgIT0iMSIpCgojTm93LCBsZXQncyBwcm9kdWNlIGEgaGlzdG9ncmFtIGFnYWluLiAKaGlzdChzdWJzZXRfbm9fMF8xJFNleF9wcm9wb3J0aW9uX2Zvcl90aGVfcHJlLnN0dWRlbnRfaW5fc2Nob29sKQoKI0FzIHJlc3VsdCwgaXQgaXMgYXBwcm94aW1hdGVseSBub3JtYWwgZGlzdHJpYnV0ZWQgbm93LgpgYGAKCiMjCVNjYW4gSUkKCmBgYHtyfQojIFRoaXMgaXMgdGhlIFIgY2h1bmsgZm9yIHRoZSBTY2FuIElJCgojV2UgZmlyc3QgY2hlY2sgb3V0IHdoaWNoIHZhcmlhYmxlIGlzIG51bWVyaWMuIApzdHIoQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfMykKCiNXZSBjb3VsZCBzZWUgdGhhdCB0aGVyZSBhcmUgNCBudW1lcmljIHZhcmlhYmxlczogCiNTY2hvb2xfTm8sIE51bWJlcl9vZl9wcmUuc3R1ZGVudCwgVG90YWxfbnVtYmVyX29mX3ByZS5zdHVkZW50X2Zvcl9zY2hvb2wsIGFuZCBTZXhfcHJvcG9ydGlvbl9mb3JfdGhlX3ByZS5zdHVkZW50X2luX3NjaG9vbAojSG93ZXZlciwgU2Nob29sX05vIGlzIG5vdCBuZWNlc3NhcnkgdG8gYmUgc2Nhbm5lZCBiZWNhdXNlIGl0IGlzIGp1c3QgYSBjb2RlIHRvIHJlcHJlc2VudCBhIHNjaG9vbCBhbmQgbm90IGEgbnVtZXJpYyBudW1iZXIgdGVjaG5pY2FsbHkuIAoKCgojRmlyc3QsIHdlIGFyZSBnb2luZyB0byBpbnZlc3RpZ2F0ZSBvdXRsaWVycyBvZiAiU2V4X3Byb3BvcnRpb25fZm9yX3RoZV9wcmUuc3R1ZGVudF9pbl9zY2hvb2wiLgpoaXN0KEFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzMkU2V4X3Byb3BvcnRpb25fZm9yX3RoZV9wcmUuc3R1ZGVudF9pbl9zY2hvb2wpCgojQW5kIGFsc28sIHRoZXkgYXJlIG5vbi1zeW1tZXRyaWMvIG5vbi1ub3JtYWwgZGF0YSBkaXN0cmlidXRpb25zLCBpdCBpcyByaWdodC1za2V3ZWQgZGlzdHJpYnV0aW9uLgojQXMgd2Uga25vd24sIHRoZXJlIGFyZSBhbGwtbWFsZSBzY2hvb2wgYW5kIGFsbC1mZW1hbGUgc2Nob29sLCBzbyB3ZSBleHBlY3QgdGhhdCB0aGVyZSBhcmUgc29tZSBvdXRsaWVycyBpcyAwIG9yIDEgaW4gdGVybXMgb2Ygc2V4IHByb3BvcnRpb24uCiNTbywgd2Ugc2hvdWxkIHVzZSB6LXNjb3JlcyBtZXRob2QgdG8gbG9vayBmb3Igb3V0bGllcnMuIFRoZSByZWFzb24gaXMgdGhhdCB3ZSBjb3VsZCBrbm93IHdoaWNoIHZhbHVlcyBhcmUgb3V0bGllcnMsIGFuZCBrbm93aW5nIGhvdyBtYW55IG91dGxpZXJzIGFyZSB0aGVyZSwgYW5kIGlmIHRoZXJlIGFyZSBqdXN0IGEgc2FtbGwgYWNvdW50IG9mIG91dGxpZXJzIHdlIG1heSBjaG9vc2UgdG8gZGVsZXRlIHRoZW0uCiNHaXZlbiB0aGF0IHdlIGFscmVhZHkgbm9ybWFsaXplIHRoZSByaWdodC1za2V3ZWQgZGlzdHJpYnV0aW9uIG9mICJTZXhfcHJvcG9ydGlvbl9mb3JfdGhlX3ByZS5zdHVkZW50X2luX3NjaG9vbCIKI05vdywgd2UgY291bGQgZGlyZWN0bHkgYXBwbHkgei1zY29yZXMgbWV0aG9kIHRvIGxvb2sgZm9yIG91dGxpZXJzLgoKI1dlIG5vdyBjYWxjdWxhdGUgeiBzY29yZXM6Cnouc2NvcmVzIDwtIHN1YnNldF9ub18wXzEkU2V4X3Byb3BvcnRpb25fZm9yX3RoZV9wcmUuc3R1ZGVudF9pbl9zY2hvb2wgJT4lICBzY29yZXModHlwZSA9ICJ6IikKei5zY29yZXMgJT4lIHN1bW1hcnkoKQoKI3dlIGNhbiBzZWUgdGhhdCB0aGUgbWF4aW11bSBpcyAxMi4wNC4gQW5kIHdlIGNhbiBmaW5kIHRoZSBsb2NhdGlvbnMgb2YgdGhlIHotc2NvcmVzIHdob3NlIGFic29sdXRlIHZhbHVlIGlzIGdyZWF0ZXIgdGhhbiAzIGJ5IHVzaW5nIHdoaWNoKCkuCndoaWNoKCBhYnMoei5zY29yZXMpID4zICkKCiNCeSB1c2luZyBsZW5ndGgoKSBmdW5jdGlvbiwgd2UgY2FuIHNlZSB0aGF0IHRoZXJlIGFyZSAyOSBvdXRsaWVycy4KbGVuZ3RoICh3aGljaCggYWJzKHouc2NvcmVzKSA+MyApKQoKI0l0IGlzIHN0aWxsIHBvc3NpYmxlIHRoYXQgdGhvc2Ugb3V0bGllcnMgYXJlIG5vdCB0aGUgcmVzdWx0IG9mIGRhdGEgZW50cnkgZXJyb3JzLCBtZWFzdXJlbWVudCBlcnJvcnMsIGV4cGVyaW1lbnRhbCBlcnJvcnMsIGludGVudGlvbmFsIGVycm9ycywgZGF0YSBwcm9jZXNzaW5nIGVycm9ycyBvciBkdWUgdG8gdGhlIHNhbXBsaW5nIChpLmUuLCBzYW1wbGluZyBlcnJvcikgYmVjYXVzZSB2ZXJ5IGxvdyBzZXggcHJvcG9ydGlvbiBvciB2ZXJ5IGhpZ2ggc2V4IHByb3BvcnRpb24gZG9lcyBoYXBwZW5lZCBpbiBzb21lIHNjaG9vbC4KI0J1dCBpdCBpcyBhbHNvIHBvc3NpYmxlIHRoYXQgdGhvc2Ugb3V0bGllcnMgYXJlIGFjdHVhbGx5IGVycm9ycy4KI0luIHRoaXMgY2FzZSwgd2Ugc2hvdWxkIHVzZSBjYXBwaW5nIHRlY2huaXF1ZSB0byBkZWFsIHdpdGggb3V0bGllcnMgYmVjYXVzZSB3ZSBhcmUgbm90IHN1cmUgYWJvdXQgd2hldGhlciB0aGVyZSBhcmUgZXJyb3JzLiAKI1RodXMsIHdlIHNob3VsZCB1c2UgdGhlIHNhZmUgd2F5IHRvIGRlYWwgd2l0aCB0aGlzIGRhdGE6IFJlcGxhY2luZyB0aGUgb3V0bGllcnMgd2l0aCB0aGUgbmVhcmVzdCBuZWlnaGJvdXJzIHRoYXQgYXJlIG5vdCBvdXRsaWVycy4KCiNGaXJzdCwgd2UgbmVlZCB0byBjcmVhdGUgb3VyIG93biBmdW5jdGlvbjogY2FwLiBUaGlzIG1lYW5zIHRoYXQgd2UgbmVlZCB0byBmaXJzdCBmaW5kIHRoZSB2YWx1ZSB0aGF0IGFyZSBsZXNzIHRoYW4gKHF1YW50aWxlcyAwLjI1KS0xLjUqSVFSIGFuZCB0aGVuIHJlcGFsY2UgaXQgYXMgKHF1YW50aWxlcyAwLjA1KS4gU2Vjb25kLCBmaW5kIHRoZSB2YWx1ZSB0aGF0IGFyZSBiaWdnZXIgdGhhbiAocXVhbnRpbGVzIDAuNzUpKzEuNSpJUVIgYW5kIHRoZW4gcmVwYWxjZSBpdCBhcyAocXVhbnRpbGVzIDAuOTUpLgpjYXAgPC0gZnVuY3Rpb24oeCl7CiAgcXVhbnRpbGVzIDwtIHF1YW50aWxlKCB4LCBjKC4wNSwgMC4yNSwgMC43NSwgLjk1ICkgKQogIHhbIHggPCBxdWFudGlsZXNbMl0gLSAxLjUqSVFSKHgpIF0gPC0gcXVhbnRpbGVzWzFdCiAgeFsgeCA+IHF1YW50aWxlc1szXSArIDEuNSpJUVIoeCkgXSA8LSBxdWFudGlsZXNbNF0KICB4Cn0KCiNBbmQgdGhlbiwgY2FwIHRoZSBvdXRsaWVycy4KU2V4X3Byb3BvcnRpb25fY2FwcGVkIDwtIHN1YnNldF9ub18wXzEkU2V4X3Byb3BvcnRpb25fZm9yX3RoZV9wcmUuc3R1ZGVudF9pbl9zY2hvb2wgJT4lIGNhcCgpCgojTGV0J3MgY2hlY2sgb3V0bGllcnMgYWdhaW4uCnouc2NvcmVzIDwtIFNleF9wcm9wb3J0aW9uX2NhcHBlZCAlPiUgIHNjb3Jlcyh0eXBlID0gInoiKQp6LnNjb3JlcyAlPiUgc3VtbWFyeSgpCgojd2UgY2FuIHNlZSB0aGF0IHRoZSBtYXhpbXVtIGlzIDIuNTE5OTU4NC4gQW5kIHdlIGNhbiBmaW5kIHdoY2loIHZhbHVlIHdob3NlIGFic29sdXRlIFotdmFsdWUgaXMgZ3JlYXRlciB0aGFuIDMgYnkgdXNpbmcgd2hpY2goKS4Kd2hpY2goIGFicyh6LnNjb3JlcykgPjMgKQoKI0J5IHVzaW5nIGxlbmd0aCgpIGZ1bmN0aW9uLCB3ZSBjYW4gc2VlIHRoYXQgdGhlcmUgYXJlIDAgb3V0bGllcnMuCmxlbmd0aCAod2hpY2goIGFicyh6LnNjb3JlcykgPjMgKSkKCgoKI1NlY29uZCwgd2UgYXJlIGdvaW5nIHRvIGl2ZXN0aWdhdGUgb3V0bGllcnMgb2YgIk51bWJlcl9vZl9wcmUuc3R1ZGVudCIgaW4gdGVybXMgb2YgImdlbmRlciIuIAojR2l2ZW4gdGhhdCB0aGV5IGFyZSBvbmUgZmFjdG9yIHZhcmlhYmxlIGFuZCBvbmUgbnVtZXJpYyB2YXJpYWJsZS4gQW5kIGFsc28sIHRoZXkgYXJlIG5vbi1zeW1tZXRyaWMvIG5vbi1ub3JtYWwgZGF0YSBkaXN0cmlidXRpb25zLgpBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18zX21hbGUgPC1BbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18zICU+JSBmaWx0ZXIoR2VuZGVyID09ICJNYWxlIikKCmhpc3QoQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfM19tYWxlJE51bWJlcl9vZl9wcmUuc3R1ZGVudCkKCkFsbF9TY2hvb2xzX0ZURV9lbnJvbG1lbnRzX0ZlYl8yMDE1X0NvbWJpbmVfMjAxNl9mb3JfcHJlLnN0dWRlbnRzXzNfZmVtYWxlIDwtQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfMyAlPiUgZmlsdGVyKEdlbmRlciA9PSAiRmVtYWxlIikKCmhpc3QoQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfM19mZW1hbGUkTnVtYmVyX29mX3ByZS5zdHVkZW50KQoKI1RodXMsIGluIHRoaXMgY2FzZSwgdXNpbmcgdGhlIHRlY2huaXF1ZSBvZiAiQml2YXJpYXRlIGJveCBwbG90IiBpcyBoaWdobHkgZW5jb3VyYWdlZC4KCmJveHBsb3QoQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfMyROdW1iZXJfb2ZfcHJlLnN0dWRlbnQgfiBBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18zJEdlbmRlciwgbWFpbj0iTnVtYmVyIG9mIHByZS5zdHVkZW50IGJ5IGdlbmRlciIsIHlsYWIgPSAiTnVtYmVyIG9mIHByZS5zdHVkZW50IiwgeGxhYiA9ICJHZW5kZXIiKQoKI1VzaW5nIHRoZSBiaXZhcmlhdGUgYm94IHBsb3QgYXBwcm9hY2gsIHdlIGNhbiBlYXNpbHkgZGV0ZWN0IG91dGxpZXJzIGluICJOdW1iZXJfb2ZfcHJlLnN0dWRlbnQiIGZvciBhIGdpdmVuICJHZW5kZXIiLgojSG93ZXZlciwgdGhlc2Ugb3V0bGllcnMgYXJlIHZhbHVhYmxlIGJlY2FzdWUgdGhpcyB2YXJpYWJsZSAoTnVtYmVyX29mX3ByZS5zdHVkZW50KSBpcyB1c2VkIGZvciBjb2xsZWN0IGluZm9ybWF0aW9uIG9mIHRoZSBudW1iZXIgb2Ygc3RkdWVudCBmb3IgZGlmZmVyZW50IGdlbmRlciBpbiBkaWZmZXJlbnQgc2Nob29sLiAKI0FuZCwgaXQgaXMgb2theSB0aGF0IHNvbWUgc2Nob29sIGhhdmUgYSBsb3Qgb2Ygc3R1ZGVudCAobm90ZSB0aGF0IG91dGxpZXJzIGFyZSBhbGwgYmV5b25kIHRoZSB1cHBlciBmZW5jZSBmb3IgYm90aCBtYWxlIGFuZCBmZW1hbGUpIGJlY2F1c2Ugc2Nob29scyBjYW4gYmUgbGlrZSBhbGwtbWFsZSBzY2hvb2wgb3IgYWxsLWZlbWFsZSBzY2hvb2wuIAojTW9yZW92ZXIsIHNjaG9vbCB0eXBlIGlzIGRpdmlkZWQgYnkgIkxhbmd1YWdlIiwgIlByaS9TZWMiLCAiUHJpbWFyeSIsICJTZWNvbmRhcnkiLCBhbmQgIlNwZWNpYWwiLCBpdCBpcyBleHBlY3RlZCB0aGF0IHRoZXJlIHNob3VsZCBiZSBtYW55IHByZS1zdHVkZW50IGZvciBsYW5ndWFnZSBzY2hvb2wgb3Igc3BlY2lhbCBzY2hvb2wsIGFuZCBsZXNzIHByZS1zdHVkZW50IGZvciBQcmkvU2VjLCBQcmltYXJ5LCBhbmQgU2Vjb25kYXJ5IHNjaG9vbC4KI0FuZCwgd2UgY291bGQgc2VlIHRoYXQgdGhlIFExIGlzIGp1c3QgYXJvdW5kIDAgYW5kIFEzIGlzIGFyb3VuZCAzMCBmb3IgYm90aCBtYWxlIGFuZCBmZW1hbGUuIE9idmlvdXNseSwgdGhlcmUgYXJlIGEgbG90IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSBzY2hvb2wgd2hvIGhhcyAwIHByZS1zdHVkZW50IG9yIG9ubHkgdmVyeSBzYW1sbCBudW1iZXIgb2YgcHJlLXN0dWRlbnQgaW4gdGhpcyBkYXRzZXQuCiNUaGVyZWZvcmUsIGl0IGlzIHBvc3NpYmxlIHRoYXQgc29tZSAiTGFuZ3VhZ2UiIGFuZCAiU3BlY2lhbCIgc2Nob29sIGhhdmUgYSBsb3Qgb2Ygc3R1ZGVudHMgYW5kIGFyZSBkZWZpbmVkIGFzIG91dGxpZXJzIGluIHRoaXMgcGxvdC4gU28sIHRoZXNlIG91dGxpZXJzIGFyZSBleHBsYWluYWJsZS4gCiNIb3dldmVyLCBpdCBpcyBzdGlsbCBwb3NzaWJsZSB0aGF0IHNvbWUgb3V0bGllcnMgYXJlIGVycm9ycyBzdWNoIGFzIG1lYXN1cmVtZW50IGVycm9yIG9yIHNhbXBsZWluZyBlcnJvci4KI1RodXMsIHdlIHNob3VsZCB1c2UgdGhlIHNhZmUgd2F5IHRvIGRlYWwgd2l0aCB0aGlzIGRhdGE6IFJlcGxhY2luZyB0aGUgb3V0bGllcnMgd2l0aCB0aGUgbmVhcmVzdCBuZWlnaGJvdXJzIHRoYXQgYXJlIG5vdCBvdXRsaWVycy4KI0dpdmVuIHRoYXQgd2UgYWxyZWFkeSBoYXZlIG91ciBvd24gZnVuY3Rpb246IGNhcCBhbmQgd2UgY291bGQganVzdCBkaXJlY3RseSBhcHBseSBjYXAgZnVuY3Rpb24gaW50byBkYXRhc2V0LgoKCgojV2UgZmlyc3QgZGVhbCB3aXRoIHRoZSBvdXRsaWVycyBmb3IgbWFsZS4KU3R1ZGVudF9tYWxlX2NhcHBlZCA8LSBBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18zX21hbGUkTnVtYmVyX29mX3ByZS5zdHVkZW50ICU+JSBjYXAoKQoKI0xldCdzIGNoZWNrIG91dGxpZXJzIGFnYWluLgp6LnNjb3JlczIgPC0gU3R1ZGVudF9tYWxlX2NhcHBlZCAlPiUgIHNjb3Jlcyh0eXBlID0gInoiKQp6LnNjb3JlczIgJT4lIHN1bW1hcnkoKQoKI3dlIGNhbiBzZWUgdGhhdCB0aGUgbWF4aW11bSBpcyAyLjkzNDIuIEFuZCB3ZSBjYW4gZmluZCB3aGNpaCB2YWx1ZSB3aG9zZSBhYnNvbHV0ZSBaLXZhbHVlIGlzIGdyZWF0ZXIgdGhhbiAzIGJ5IHVzaW5nIHdoaWNoKCkuCndoaWNoKCBhYnMoei5zY29yZXMyKSA+MyApCgojQnkgdXNpbmcgbGVuZ3RoKCkgZnVuY3Rpb24sIHdlIGNhbiBzZWUgdGhhdCB0aGVyZSBhcmUgMCBvdXRsaWVycy4KbGVuZ3RoICh3aGljaCggYWJzKHouc2NvcmVzMikgPjMgKSkKCgoKI0FuZCB0aGVuLCB3ZSBkZWFsIHdpdGggdGhlIG91dGxpZXJzIGZvciBmZW1hbGUuClN0dWRlbnRfZmVtYWxlX2NhcHBlZCA8LSBBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18zX2ZlbWFsZSROdW1iZXJfb2ZfcHJlLnN0dWRlbnQgJT4lIGNhcCgpCgojTGV0J3MgY2hlY2sgb3V0bGllcnMgYWdhaW4uCnouc2NvcmVzMyA8LSBTdHVkZW50X2ZlbWFsZV9jYXBwZWQgJT4lICBzY29yZXModHlwZSA9ICJ6IikKei5zY29yZXMzICU+JSBzdW1tYXJ5KCkKCiN3ZSBjYW4gc2VlIHRoYXQgdGhlIG1heGltdW0gaXMgMi45NjAyLiBBbmQgd2UgY2FuIGZpbmQgd2hjaWggdmFsdWUgd2hvc2UgYWJzb2x1dGUgWi12YWx1ZSBpcyBncmVhdGVyIHRoYW4gMyBieSB1c2luZyB3aGljaCgpLgp3aGljaCggYWJzKHouc2NvcmVzMykgPjMgKQoKI0J5IHVzaW5nIGxlbmd0aCgpIGZ1bmN0aW9uLCB3ZSBjYW4gc2VlIHRoYXQgdGhlcmUgYXJlIDAgb3V0bGllcnMuCmxlbmd0aCAod2hpY2goIGFicyh6LnNjb3JlczMpID4zICkpCgoKCiNUaGlyZCwgd2UgYXJlIGdvaW5nIHRvIGludmVzdGlnYXRlIG91dGxpZXJzIG9mICJUb3RhbF9udW1iZXJfb2ZfcHJlLnN0dWRlbnRfZm9yX3NjaG9vbCIuCmhpc3QoQWxsX1NjaG9vbHNfRlRFX2Vucm9sbWVudHNfRmViXzIwMTVfQ29tYmluZV8yMDE2X2Zvcl9wcmUuc3R1ZGVudHNfMyRUb3RhbF9udW1iZXJfb2ZfcHJlLnN0dWRlbnRfZm9yX3NjaG9vbCkKCiNBbmQgYWxzbywgdGhleSBhcmUgbm9uLXN5bW1ldHJpYy8gbm9uLW5vcm1hbCBkYXRhIGRpc3RyaWJ1dGlvbnMuCiNUaHVzLCBpbiB0aGlzIGNhc2UsIHVzaW5nIHRoZSB0ZWNobmlxdWUgb2YgIlVuaXZhcmlhdGUgYm94IHBsb3QiIGlzIGhpZ2hseSBlbmNvdXJhZ2VkLgpBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18zJFRvdGFsX251bWJlcl9vZl9wcmUuc3R1ZGVudF9mb3Jfc2Nob29sICU+JSAgYm94cGxvdChtYWluPSJCb3ggUGxvdCBvZiB0b3RhbCBudW1iZXIgb2YgcHJlLnN0dWRlbnQgZm9yIHNjaG9vbCIsIHlsYWI9IlRvdGFsIG51bWJlciBvZiBwcmUuc3R1ZGVudCIsIGNvbCA9ICJncmV5IikKCiNUaGlzIGNhc2UgaXMgdmVyeSBzaW1pbGFyIHRvIHRoZSBwcmV2aW91cyBjYXNlLCBvdXRsaWVycyBhcmUgYWxsIGJleW9uZCB0aGUgdXBwZXIgZmVuY2UuIEFzIHdlIGNhbiBzZWUgaW4gdGhlIHBsb3QsIG91dGxpZXJzIGFyZSBhbGwgaW4gYXJvdW5kIDE0MCBzdHVkZW50cyB0byAyNTAgc3R1ZGVudC4gSXQgc2VlbXMgb2theSBiZWNhdXNlIHNvbWUgYmlnIHNjaG9vbCBjYW4gaGF2ZSAyNTAgcHJlLXN0dWRlbnQuIAojQW5kLCB3ZSBjb3VsZCBzZWUgdGhhdCB0aGUgUTEgaXMganVzdCBhcm91bmQgMCBhbmQgUTMgaXMgYXJvdW5kIDUwLiBPYnZpb3VzbHksIHRoaXMgcGxvdCBoYXMgdGhlIHNhbWUgc2l0dWF0aW9uIHdpdGggdGhlIHByZXZpb3VzIG9uZSwgdGhlcmUgYXJlIGEgbG90IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSBzY2hvb2wgd2hvIGhhcyAwIHByZS1zdHVkZW50IG9ubHkgdmVyeSBzYW1sbCBudW1iZXIgb2YgcHJlLXN0dWRlbnQgaW4gdGhpcyBkYXRzZXQuCiNUaGVyZWZvcmUsIGl0IGlzIHBvc3NpYmxlIHRoYXQgc29tZSAiTGFuZ3VhZ2UiIGFuZCAiU3BlY2lhbCIgc2Nob29sIGhhdmUgYSBsb3Qgb2Ygc3R1ZGVudHMgYW5kIGFyZSBkZWZpbmVkIGFzIG91dGxpZXJzIGluIHRoaXMgcGxvdC4gU28sIHRoZXNlIG91dGxpZXJzIGFyZSBleHBsYWluYWJsZS4gCiNPdXRsaWVycyBhcmUgdmFsdWFibGUgYW5kIGV4cGxhaW5hYmxlLgojSG93ZXZlciwgaXQgaXMgc3RpbGwgcG9zc2libGUgdGhhdCBzb21lIG91dGxpZXJzIGFyZSBlcnJvcnMgc3VjaCBhcyBtZWFzdXJlbWVudCBlcnJvciBvciBzYW1wbGVpbmcgZXJyb3IuCiNUaHVzLCB3ZSBzaG91bGQgdXNlIHRoZSBzYWZlIHdheSB0byBkZWFsIHdpdGggdGhpcyBkYXRhOiBSZXBsYWNpbmcgdGhlIG91dGxpZXJzIHdpdGggdGhlIG5lYXJlc3QgbmVpZ2hib3VycyB0aGF0IGFyZSBub3Qgb3V0bGllcnMuCiNHaXZlbiB0aGF0IHdlIGFscmVhZHkgaGF2ZSBvdXIgb3duIGZ1bmN0aW9uOiBjYXAgYW5kIHdlIGNvdWxkIGp1c3QgZGlyZWN0bHkgYXBwbHkgY2FwIGZ1bmN0aW9uIGludG8gZGF0YXNldC4KCgoKVG90YWxfdHVkZW50X2NhcHBlZCA8LSBBbGxfU2Nob29sc19GVEVfZW5yb2xtZW50c19GZWJfMjAxNV9Db21iaW5lXzIwMTZfZm9yX3ByZS5zdHVkZW50c18zJFRvdGFsX251bWJlcl9vZl9wcmUuc3R1ZGVudF9mb3Jfc2Nob29sICU+JSBjYXAoKQoKI0xldCdzIGNoZWNrIG91dGxpZXJzIGFnYWluLgp6LnNjb3JlczQgPC0gVG90YWxfdHVkZW50X2NhcHBlZCAlPiUgIHNjb3Jlcyh0eXBlID0gInoiKQp6LnNjb3JlczQgJT4lIHN1bW1hcnkoKQoKI3dlIGNhbiBzZWUgdGhhdCB0aGUgbWF4aW11bSBpcyAyLjg5NDguIEFuZCB3ZSBjYW4gZmluZCB3aGNpaCB2YWx1ZSB3aG9zZSBhYnNvbHV0ZSBaLXZhbHVlIGlzIGdyZWF0ZXIgdGhhbiAzIGJ5IHVzaW5nIHdoaWNoKCkuCndoaWNoKCBhYnMoei5zY29yZXM0KSA+MyApCgojQnkgdXNpbmcgbGVuZ3RoKCkgZnVuY3Rpb24sIHdlIGNhbiBzZWUgdGhhdCB0aGVyZSBhcmUgMCBvdXRsaWVycy4KbGVuZ3RoICh3aGljaCggYWJzKHouc2NvcmVzNCkgPjMgKSkKCmBgYAo=