NDI Analysis - 2021 Cohort

Summary of Findings

  1. No SSS clients that were entered into the NDI search and were successful searched by NDI confirmed to have died by suicide.
  2. There was one “False Match” reported by NDI. This is an individual who has died by suicide, but was not a strong match to SSS client data. This individual was confirmed to not be a current or previous SSS client (Last name, Birth Year, Residential State did not match). This was confirmed using data and an internet search of client vs. decedent.
  3. There were 17 “True Matches” reported by the NDI. This is a NDI decedant who is a strong match to a SSS client, and is assumed to be deceased. Of the 17 potential client deaths, zero are reported as suicide or intentional self-harm. However, there were a number of client matches that died by other means of concern:
Deident Client ICD Codes Type
13276LRC Other psychoactive substance abuse Primary ICD
14859LRC Alcohol abuse Primary ICD
13720LRC Other psychoactive substance abuse; Poisoning by, adverse effect of and underdosing of cocaine Secondary and Quaternary ICD
18539LRC Mental and behavioral disorders due to use of tobacco Unspecified mental and behavioural disorder Secondary ICD
16112HRC Alcoholic cirrhosis of liver Primary ICD
17569MRC Alcohol abuse; Mental and behavioral disorders due to use of tobacco Harmful use. Primary and Secondary ICD

Use of Code

Summary of Steps:

  1. Data is reformatted from character-based NDI submission style to meaningful columns and headers
  2. Dataset is created of all clients marked by NDI as potential matches and classified as “True Match: Assumed Dead”. This includes all NDI hits in which a deceased individual in their database was a strong enough match to our client cohort be considered a deceased client.
  3. A second dataset is created of all clients marked by NDI as “FALSE Match: Assumed Alive”. This includes NDI hits where a deceased individual in their system was not a strong enough match to our client cohort to be considered a match.
  4. Within the FALSE match cohort, data is subsetted to only include those individuals who had a primary or secondary ICD code including Suicide. This allows us to double check that even though NDI marked this individual as a “FASE match”, the identified individual is in fact not an SSS client.
  5. When possible, ICD codes are automatically replaced by COD from the CDC ICD.Code Manual.
  6. A merged dataset is exported to a CSV file and all individuals remaining (TRUE matches: Potential SSS clients who have died by any means, FALSE Matches: Assumed not to be SSS clients who died by suicide). Each data entry is then confirmed by staff.

Directions:

To successfully run this script, place this file in a folder with the “CAUSE” file provided by the NDI search and the 7 CSV file of ICD Codes from the current year. Click the “RUN” button above. An excel file will be produced that includes only the entries of interested. Follow the directions in the “Interactive Data Table for Sorting” section to double check no entries were missed. Save the excel file under a new name so that it does not get overwritten in the event you run this script again. Complete the excel file.

Zip file contents Provided by NDI Analysis

File Name File Type Description
_Edits PDF User File Edit Results
PRTCAUSE PDF Cause of Death Report
SUMMARY PDF Summary Retrieval Statistics
REQFORMS PDF Death Certificate Request Forms
REPORT PDF NDI Retrieval Report
COMBINED TXT Combined File of Matching User and NDI Records
CAUSE TXT Cause of Death File, includes all personal information and match data
MATCH TXT User records involved in matches, in the same record format as submitted by the user
NOMATCH TXT User records not involved in matches with any NDI records, in the same record format as submitted by the user.
REJECTS TXT User records rejected by the NDI edit program and not included in the NDI search, in the same record format as submitted by the user

Analysis Code

Packages and Files

#Upload necessary packages
library(tidyr)
library(dplyr)
library(DT)
library(writexl)

# Import Files
#File must first be opened in excel and converted from txt file to CSV file.
cause <- read.table("FS2021-X088#00_R1.CAUSE", sep="\t", header=FALSE)

File Formatting

Reformatting from NDI submission style

#Split single imported string into columns based on character counts provided in the NDI Userguide
currated.cause=separate(cause, V1, 
into = c("Last.Name", "First.Name", "Middle.Initial", "SSN", "DOB.Month", "DOB.Day", "DOB.Year", "Father.Surname", "AoD.Unit", "AoD.Number", "Sex", "Race", "Mar.Status", "Res.State", "Birth.State", "Case.Num/Risk.Level", "Case.Created", "Blank.Field", "State.Death", "Year.Death", "St.Death.Code", "Alias", "Death.Cert.Num", "DOD.Month", "DOD.Day", "DOD.Year", "NDI:First.Name", "NDI:Middle.Initial", "NDI:Last.Name", "NDI:Father.Surname", "NDI:Surname", "NDI:SSN", "NDI:DOB.Month", "NDI:DOB.Day", "NDI:DOB.Year", "NDI:Age.Death", "NDI:Sex", "NDI:Race", "NDI:Marital.Status", "NDI:Res.State", "NDI:Birth.State", "Blank.Field.2", "Exact.Match.Indicator", "Match.Seq", "Num.Poss.Matches", "Prob.Score", "Class.Code", "Status.Code", "Blank.Field.3", "ICD.Code", "ICD.Recode", "ICD.Recode.2", "ICD.Recode.3", "Num.Entity.Axis", "Entity.Axis.Cond", "Numb.Record.Axis", "Record.Axis.Cond"), 
sep = c(20, 35, 36, 45, 47, 49, 53, 71, 72, 74, 75, 76, 77, 79, 81, 91, 97, 100, 112, 116, 119, 120, 126, 128, 130, 132, 134, 135, 136, 137, 138, 147, 148, 149, 152, 153, 154, 155, 156, 157, 158, 164, 165, 168, 171, 176, 177, 178, 179, 183, 188, 191,194,196,336, 338), remove = FALSE)

#remove the first column, which contains the string data used to create separate columns
currated.cause = subset(currated.cause, select = -c(1) )

#put an "NA" in all cells that contain nothing but white space. This must be done as the spaces are read in as characters due to file type at upload.
currated.cause[] <- lapply(currated.cause, function(x)
      type.convert(replace(x, grepl("^\\s*$", trimws(x)), NA), as.is = TRUE))

#Remove columns that have no values in any rows
currated.cause <- currated.cause[,colSums(is.na(currated.cause))<nrow(currated.cause)]

#Remove white spaces remaining as "character" reads at the end of the following columns. 
currated.cause$Last.Name=(gsub(" ","",currated.cause$Last.Name))
currated.cause$`NDI:First.Name`=(gsub(" ","",currated.cause$`NDI:First.Name`))
currated.cause$`NDI:DOB.Year`=(gsub(" ","",currated.cause$`NDI:DOB.Year`))
currated.cause$ICD.Code=(gsub(" ","",currated.cause$ICD.Code))

#Combine Month, Day and Year of birth into a single column
currated.cause$DOB <- paste(currated.cause$DOB.Month, "-", currated.cause$DOB.Day, "-", currated.cause$DOB.Year)
#Move the new single DOB variable to the DOB location in file
currated.cause=currated.cause %>% relocate(DOB, .after=DOB.Year)
#Remove original, seperate Month, Day, Year of birth columns
currated.cause <- currated.cause[ -c(3:5) ]

#Repeat process above for Date of Death and First/Last Name variables. 
currated.cause$DOD <- paste(currated.cause$DOD.Month, "-", currated.cause$DOD.Day, "-", currated.cause$DOD.Year)
currated.cause=currated.cause %>% relocate(DOD, .after=DOD.Year)
currated.cause <- currated.cause[ -c(17:19) ]

currated.cause$Last.First <- paste(currated.cause$Last.Name, ",", currated.cause$First.Name)
currated.cause=currated.cause %>% relocate(Last.First, .after=First.Name)
currated.cause <- currated.cause[ -c(1:2) ]

#Recode numerical Sex column with matching terms
currated.cause = currated.cause %>% mutate(Sex=recode(Sex, 
                         `1`="Male", `2`="Female", `9`= "Unknown",  "NA"= "Unknown"))

#Recode numerical Race column with matching terms
currated.cause = currated.cause %>% mutate(Race=recode(Race, 
                         `1`="White", `2`="Black",`3`= "Indian", `4`= "Chinese", `5`="Japanese", `6`="Hawaiian", `7`="Other-nonwhite",  `8`="Filipino", `0`="Other Asian/Pacific Islander",`9`= "Unknown",  "NA"="Unknown"))

#Recode numerical Marital Status column with matching terms
currated.cause = currated.cause %>% mutate(Mar.Status=recode(Mar.Status, 
                         `1`="Single", `2`="Married",`3`= "Widowed",  `4`= "Divorced",  `9`= "Unknown",  "NA"="Unknown"))

#Recode numerical Residential State column with matching terms
currated.cause = currated.cause %>% mutate(Res.State=recode(Res.State, 
                         `1`="Alabama", `2`="Alaska",`3`= "Arizona", `4`= "Arkansas", `5`="California", `6`="Colorado", `7`="Connecticut",  `8`="Delaware", `9`="District of Columbia", `10`= "Florida",  `11`="Georgia", `12`="Hawaii", `13`= "Idaho", `14`= "Illinois", `15`="Indiana", `16`="Iowa", `17`="Kansas", `18`="Kentucky", `19`="Louisiana", `20`= "Maine",  `21`="Maryland", `22`="Massachusetts", `23`= "Michigan", `24`= "Minnesota",  `25`="Mississippi", `26`="Missouri", `27`="Montana",`28`="Nebrasks", `29`="Nevada", `30`= "New Hampshire",  `31`="New Jersey", `32`="New Medico", `33`= "New York",  `34`= "North Carolina",  `35`="North Dakota",  `36`="Ohio", `37`="Oklahoma",  `38`="Oregon", `39`="Pennsylvania", `40`= "Rhode Island",  `41`="South Carolina", `42`="South Dakota",`43`= "Tennessee",  `44`= "Texas",  `45`="Utah",  `46`="Vermont", `47`="Virginia",  `48`="Washington", `49`="West Virginia", `50`= "Wisconsin", `51`="Wyoming",`52`="Puerto Rico", `53`= "Virgin Islands", `54`= "Guam",  `55`="Canada",  `56`="Cuba", `57`="Mexico", `59`="Remainder of World",`99`="Unknown", "NA"="Unknown"))

#Recode NDI Match symbols with matching terms
currated.cause = currated.cause %>%
  mutate(across(
    `NDI:First.Name`:`NDI:Birth.State`,
    ~ recode(
      .x,
      "X" = "Exact Match",
      "NA" = "Does Not Match",
      'NA' = "Does Not Match",
      " " = "Does Not Match",
      "?" = "Missing in NDI",
      "-" = "Missing from User",
      "N" = "Names match only NYSIIS",
      "I" = "Only First Initial Match",
      "B" = "Missing in NDI and User",
      "A" = "NDI Record is Alias",
      "IN" = "Only First Initial & Only NYSIIS"
    )
  ))

currated.cause$`NDI:First.Name`[is.na(currated.cause$`NDI:First.Name`)] <- "Does Not Match"
currated.cause$`NDI:Middle.Initial`[is.na(currated.cause$`NDI:Middle.Initial`)] <- "Does Not Match"
currated.cause$`NDI:Last.Name`[is.na(currated.cause$`NDI:Last.Name`)] <- "Does Not Match"
currated.cause$`NDI:Father.Surname`[is.na(currated.cause$`NDI:Father.Surname`)] <- "Does Not Match"
currated.cause$`NDI:Surname`[is.na(currated.cause$`NDI:Surname`)] <- "Does Not Match"
currated.cause$`NDI:SSN`[is.na(currated.cause$`NDI:SSN`)] <- "Does Not Match"
currated.cause$`NDI:DOB.Month`[is.na(currated.cause$`NDI:DOB.Month`)] <- "Does Not Match"
currated.cause$`NDI:DOB.Day`[is.na(currated.cause$`NDI:DOB.Day`)] <- "Does Not Match"
currated.cause$`NDI:DOB.Year`[is.na(currated.cause$`NDI:DOB.Year`)] <- "Does Not Match"
currated.cause$`NDI:Age.Death`[is.na(currated.cause$`NDI:Age.Death`)] <- "Does Not Match"
currated.cause$`NDI:Sex`[is.na(currated.cause$`NDI:Sex`)] <- "Does Not Match"
currated.cause$`NDI:Race`[is.na(currated.cause$`NDI:Race`)] <- "Does Not Match"
currated.cause$`NDI:Marital.Status`[is.na(currated.cause$`NDI:Marital.Status`)] <- "Does Not Match"
currated.cause$`NDI:Res.State`[is.na(currated.cause$`NDI:Res.State`)] <- "Does Not Match"
currated.cause$`NDI:Birth.State`[is.na(currated.cause$`NDI:Birth.State`)] <- "Does Not Match"

#Recode Status Code match designation with appropriate phrase
currated.cause = currated.cause %>% mutate(Status.Code=recode(Status.Code, 
                         `0`="FALSE Match: Assumed Alive",
                         `1`="TRUE Match: Assumed Dead"))

Produce dataset organized for SSS use

## Produce dataset organized for SSS use
#Reorganize columns to be in order of our submitted information followed by NDI match criteria
keep=c("Last.First", "NDI:First.Name", "NDI:Last.Name", 'DOB', "NDI:DOB.Month", "NDI:DOB.Day", "NDI:DOB.Year", 'Sex', "NDI:Sex", 'Race', "NDI:Race", 'Mar.Status',"NDI:Marital.Status",  'Res.State', "NDI:Res.State", 'Case.Num/Risk.Level', 'Case.Created', 'State.Death', 'DOD', "Death.Cert.Num", "Exact.Match.Indicator", "Status.Code", "ICD.Code", "Record.Axis.Cond")

cause.final = currated.cause[keep]

Creation of Match Files

Isolate Potential Matches

#Subset data to only include individuals with a status code of "1", which indicates a death.
death.matches=subset(cause.final, Status.Code == "TRUE Match: Assumed Dead")

Isolate Non-Matches with Death by Suicide

#Look in the status code "0" 
#status code = 0 ; ICD code for Suicide/intentional self harm resulting in death (X60-X84)
death.nomat=subset(cause.final, Status.Code == "FALSE Match: Assumed Alive")

Subset data to include only those that are True Matches, and False Matches that are death by suicide or self-harm

#Isolate records with an Record Axis Code indicating "Suicide" or "Intentional Self Harm" a a secondary ICD Code

death.nomatch2=subset(death.nomat, 
      grepl("*X6.*", Record.Axis.Cond) |
      grepl("*X7.*", Record.Axis.Cond) |
      grepl("*X8[0-4].*", Record.Axis.Cond) |
      grepl("*U03.*", Record.Axis.Cond) |
      grepl("*Y87.*", Record.Axis.Cond))
                      
check= rbind(death.matches,death.nomatch2)

### Seperate the Record axis into individual columns
### replace codes with phrases

library(splitstackshape)
check=cSplit(check, "Record.Axis.Cond", " ")

Reformating ICD Codes

Import CDC ICD codes from 2023 coding book

**Downloaded from CDC webpage*

https://ftp.cdc.gov/pub/Health_Statistics/NCHS/Publications/ICD10CM/April-1-2023-Update/

https://www.cdc.gov/nchs/icd/Comprehensive-Listing-of-ICD-10-CM-Files.htm

ICD Codes: Suicide or Intentional self-harm (X60-X84, Y)

ICD.codes=read.csv(
  "icd10cm-codes- April 1 2023.csv", header=FALSE)

ICD.codes=rename(ICD.codes, ICD.Code = V1)
ICD.codes=rename(ICD.codes, Description = V2)

ICD.codes18=read.csv("2018_ICDcodes.csv", header=FALSE)
ICD.codes18=rename(ICD.codes18, ICD.Code = V1)
ICD.codes18=rename(ICD.codes18, Description = V2)

REPLACE ALL RECORD CODES WITH TERMS

idx <- match(check$Record.Axis.Cond_1, ICD.codes$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_1[idxn] <- ICD.codes$Description[idx[idxn]]
idx <- match(check$Record.Axis.Cond_1, ICD.codes18$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_1[idxn] <- ICD.codes18$Description[idx[idxn]]

idx <- match(check$Record.Axis.Cond_2, ICD.codes$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_2[idxn] <- ICD.codes$Description[idx[idxn]]
idx <- match(check$Record.Axis.Cond_2, ICD.codes18$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_2[idxn] <- ICD.codes18$Description[idx[idxn]]

idx <- match(check$Record.Axis.Cond_3, ICD.codes$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_3[idxn] <- ICD.codes$Description[idx[idxn]]
idx <- match(check$Record.Axis.Cond_3, ICD.codes18$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_3[idxn] <- ICD.codes18$Description[idx[idxn]]

idx <- match(check$Record.Axis.Cond_4, ICD.codes$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_4[idxn] <- ICD.codes$Description[idx[idxn]]
idx <- match(check$Record.Axis.Cond_4, ICD.codes18$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_4[idxn] <- ICD.codes18$Description[idx[idxn]]

idx <- match(check$Record.Axis.Cond_5, ICD.codes$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_5[idxn] <- ICD.codes$Description[idx[idxn]]
idx <- match(check$Record.Axis.Cond_5, ICD.codes18$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_5[idxn] <- ICD.codes18$Description[idx[idxn]]

idx <- match(check$Record.Axis.Cond_6, ICD.codes$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_6[idxn] <- ICD.codes$Description[idx[idxn]]
idx <- match(check$Record.Axis.Cond_6, ICD.codes18$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_6[idxn] <- ICD.codes18$Description[idx[idxn]]

idx <- match(check$Record.Axis.Cond_7, ICD.codes$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_7[idxn] <- ICD.codes$Description[idx[idxn]]
idx <- match(check$Record.Axis.Cond_7, ICD.codes18$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_7[idxn] <- ICD.codes18$Description[idx[idxn]]

idx <- match(check$Record.Axis.Cond_8, ICD.codes$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_8[idxn] <- ICD.codes$Description[idx[idxn]]
idx <- match(check$Record.Axis.Cond_8, ICD.codes18$ICD.Code)
idxn <- which(!is.na(idx))
#idxn <- !is.na(idx) #Alternative
check$Record.Axis.Cond_8[idxn] <- ICD.codes18$Description[idx[idxn]]

Combine Potential Matches into Excel File for Verification by SSS

check$`Confirmed Client Suicide` = NA
check$`SSS Justification` = NA
write_xlsx(check,"NDI_DetailedCheck.xlsx")

Interactive Data Table

This table will consist of all “True Matches” in which the NDI search produced a probable match to an SSS client, that is those that are classified as “True Match: Assumed Dead”. This includes all NDI hits in which a deceased individual in their database was a strong enough match to our client cohort be considered a deceased client.

LS0tCnRpdGxlOiAiTkRJIEZpbmFsIEFuYWx5c2lzL1BpcGVsaW5lIEJ1aWxkIgphdXRob3I6ICJBYmJ5IEJlYXR0eSIKZGF0ZTogIjIwMjMtMDMtMTYiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IHNhbmRzdG9uZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KIyBOREkgQW5hbHlzaXMgLSAyMDIxIENvaG9ydCB7LnRhYnNldH0KIyMgU3VtbWFyeSBvZiBGaW5kaW5ncyB7LnRhYnNldH0KMS4gTm8gU1NTIGNsaWVudHMgdGhhdCAqKndlcmUgZW50ZXJlZCBpbnRvIHRoZSBOREkgc2VhcmNoIGFuZCB3ZXJlIHN1Y2Nlc3NmdWwgc2VhcmNoZWQgYnkgTkRJKiogY29uZmlybWVkIHRvIGhhdmUgZGllZCBieSBzdWljaWRlLgoyLiBUaGVyZSB3YXMgb25lICJGYWxzZSBNYXRjaCIgcmVwb3J0ZWQgYnkgTkRJLiBUaGlzIGlzIGFuIGluZGl2aWR1YWwgd2hvIGhhcyBkaWVkIGJ5IHN1aWNpZGUsIGJ1dCB3YXMgbm90IGEgc3Ryb25nIG1hdGNoIHRvIFNTUyBjbGllbnQgZGF0YS4gVGhpcyBpbmRpdmlkdWFsIHdhcyBjb25maXJtZWQgdG8gKipub3QqKiBiZSBhIGN1cnJlbnQgb3IgcHJldmlvdXMgU1NTIGNsaWVudCAoTGFzdCBuYW1lLCBCaXJ0aCBZZWFyLCBSZXNpZGVudGlhbCBTdGF0ZSBkaWQgbm90IG1hdGNoKS4gVGhpcyB3YXMgY29uZmlybWVkIHVzaW5nIGRhdGEgYW5kIGFuIGludGVybmV0IHNlYXJjaCBvZiBjbGllbnQgdnMuIGRlY2VkZW50LiAKMi4gVGhlcmUgd2VyZSAxNyAiVHJ1ZSBNYXRjaGVzIiByZXBvcnRlZCBieSB0aGUgTkRJLiBUaGlzIGlzIGEgTkRJIGRlY2VkYW50IHdobyBpcyBhIHN0cm9uZyBtYXRjaCB0byBhIFNTUyBjbGllbnQsIGFuZCBpcyBhc3N1bWVkIHRvIGJlIGRlY2Vhc2VkLiBPZiB0aGUgMTcgcG90ZW50aWFsIGNsaWVudCBkZWF0aHMsICoqemVybyoqIGFyZSByZXBvcnRlZCBhcyBzdWljaWRlIG9yIGludGVudGlvbmFsIHNlbGYtaGFybS4gSG93ZXZlciwgdGhlcmUgd2VyZSBhIG51bWJlciBvZiBjbGllbnQgbWF0Y2hlcyB0aGF0IGRpZWQgYnkgb3RoZXIgbWVhbnMgb2YgY29uY2VybjogCgpEZWlkZW50IENsaWVudCB8IElDRCBDb2RlcyB8IFR5cGUKLS0tLS0tLS0tLS0tLS0tfCAtLS0tLS0tLS0gfCAtLS0tLS0tLS0tLQoxMzI3NkxSQyB8IE90aGVyIHBzeWNob2FjdGl2ZSBzdWJzdGFuY2UgYWJ1c2V8UHJpbWFyeSBJQ0QgCjE0ODU5TFJDIHwgQWxjb2hvbCBhYnVzZSB8UHJpbWFyeSBJQ0QgCjEzNzIwTFJDIHwgT3RoZXIgcHN5Y2hvYWN0aXZlIHN1YnN0YW5jZSBhYnVzZTsgUG9pc29uaW5nIGJ5LCBhZHZlcnNlIGVmZmVjdCBvZiBhbmQgdW5kZXJkb3Npbmcgb2YgY29jYWluZSB8U2Vjb25kYXJ5IGFuZCBRdWF0ZXJuYXJ5IElDRAoxODUzOUxSQyB8IE1lbnRhbCBhbmQgYmVoYXZpb3JhbCBkaXNvcmRlcnMgZHVlIHRvIHVzZSBvZiB0b2JhY2NvIFVuc3BlY2lmaWVkIG1lbnRhbCBhbmQgYmVoYXZpb3VyYWwgZGlzb3JkZXJ8U2Vjb25kYXJ5IElDRCAKMTYxMTJIUkMgfCBBbGNvaG9saWMgY2lycmhvc2lzIG9mIGxpdmVyfFByaW1hcnkgSUNEIAoxNzU2OU1SQyB8IEFsY29ob2wgYWJ1c2U7IE1lbnRhbCBhbmQgYmVoYXZpb3JhbCBkaXNvcmRlcnMgZHVlIHRvIHVzZSBvZiB0b2JhY2NvIEhhcm1mdWwgdXNlLnxQcmltYXJ5IGFuZCBTZWNvbmRhcnkgSUNECgojIyBVc2Ugb2YgQ29kZSB7LnRhYnNldH0KCiMjIyBTdW1tYXJ5IG9mIFN0ZXBzOiAKMS4gRGF0YSBpcyByZWZvcm1hdHRlZCBmcm9tIGNoYXJhY3Rlci1iYXNlZCBOREkgc3VibWlzc2lvbiBzdHlsZSB0byBtZWFuaW5nZnVsIGNvbHVtbnMgYW5kIGhlYWRlcnMgCjIuIERhdGFzZXQgaXMgY3JlYXRlZCBvZiBhbGwgY2xpZW50cyBtYXJrZWQgYnkgTkRJIGFzIHBvdGVudGlhbCBtYXRjaGVzIGFuZCBjbGFzc2lmaWVkIGFzIOKAnFRydWUgTWF0Y2g6IEFzc3VtZWQgRGVhZOKAnS4gVGhpcyBpbmNsdWRlcyBhbGwgTkRJIGhpdHMgaW4gd2hpY2ggYSBkZWNlYXNlZCBpbmRpdmlkdWFsIGluIHRoZWlyIGRhdGFiYXNlIHdhcyBhIHN0cm9uZyBlbm91Z2ggbWF0Y2ggdG8gb3VyIGNsaWVudCBjb2hvcnQgYmUgY29uc2lkZXJlZCBhIGRlY2Vhc2VkIGNsaWVudC4gCjMuIEEgc2Vjb25kIGRhdGFzZXQgaXMgY3JlYXRlZCBvZiBhbGwgY2xpZW50cyBtYXJrZWQgYnkgTkRJIGFzIOKAnEZBTFNFIE1hdGNoOiBBc3N1bWVkIEFsaXZl4oCdLiBUaGlzIGluY2x1ZGVzIE5ESSBoaXRzIHdoZXJlIGEgZGVjZWFzZWQgaW5kaXZpZHVhbCBpbiB0aGVpciBzeXN0ZW0gd2FzIG5vdCBhIHN0cm9uZyBlbm91Z2ggbWF0Y2ggdG8gb3VyIGNsaWVudCBjb2hvcnQgdG8gYmUgY29uc2lkZXJlZCBhIG1hdGNoLiAKNC4gV2l0aGluIHRoZSBGQUxTRSBtYXRjaCBjb2hvcnQsIGRhdGEgaXMgc3Vic2V0dGVkIHRvIG9ubHkgaW5jbHVkZSB0aG9zZSBpbmRpdmlkdWFscyB3aG8gaGFkIGEgcHJpbWFyeSBvciBzZWNvbmRhcnkgSUNEIGNvZGUgaW5jbHVkaW5nIFN1aWNpZGUuIFRoaXMgYWxsb3dzIHVzIHRvIGRvdWJsZSBjaGVjayB0aGF0IGV2ZW4gdGhvdWdoIE5ESSBtYXJrZWQgdGhpcyBpbmRpdmlkdWFsIGFzIGEg4oCcRkFTRSBtYXRjaOKAnSwgdGhlIGlkZW50aWZpZWQgaW5kaXZpZHVhbCBpcyBpbiBmYWN0IG5vdCBhbiBTU1MgY2xpZW50LiAKNS4gV2hlbiBwb3NzaWJsZSwgSUNEIGNvZGVzIGFyZSBhdXRvbWF0aWNhbGx5IHJlcGxhY2VkIGJ5IENPRCBmcm9tIHRoZSBDREMgSUNELkNvZGUgTWFudWFsLiAKNi4gQSBtZXJnZWQgZGF0YXNldCBpcyBleHBvcnRlZCB0byBhIENTViBmaWxlIGFuZCBhbGwgaW5kaXZpZHVhbHMgcmVtYWluaW5nIChUUlVFIG1hdGNoZXM6IFBvdGVudGlhbCBTU1MgY2xpZW50cyB3aG8gaGF2ZSBkaWVkIGJ5IGFueSBtZWFucywgRkFMU0UgTWF0Y2hlczogQXNzdW1lZCBub3QgdG8gYmUgU1NTIGNsaWVudHMgd2hvIGRpZWQgYnkgc3VpY2lkZSkuIEVhY2ggZGF0YSBlbnRyeSBpcyB0aGVuIGNvbmZpcm1lZCBieSBzdGFmZi4gCgojIyMgRGlyZWN0aW9uczogCgpUbyBzdWNjZXNzZnVsbHkgcnVuIHRoaXMgc2NyaXB0LCBwbGFjZSB0aGlzIGZpbGUgaW4gYSBmb2xkZXIgd2l0aCB0aGUgIkNBVVNFIiBmaWxlIHByb3ZpZGVkIGJ5IHRoZSBOREkgc2VhcmNoIGFuZCB0aGUgNyBDU1YgZmlsZSBvZiBJQ0QgQ29kZXMgZnJvbSB0aGUgY3VycmVudCB5ZWFyLiBDbGljayB0aGUgIlJVTiIgYnV0dG9uIGFib3ZlLiBBbiBleGNlbCBmaWxlIHdpbGwgYmUgcHJvZHVjZWQgdGhhdCBpbmNsdWRlcyBvbmx5IHRoZSBlbnRyaWVzIG9mIGludGVyZXN0ZWQuIEZvbGxvdyB0aGUgZGlyZWN0aW9ucyBpbiB0aGUgIkludGVyYWN0aXZlIERhdGEgVGFibGUgZm9yIFNvcnRpbmciIHNlY3Rpb24gdG8gZG91YmxlIGNoZWNrIG5vIGVudHJpZXMgd2VyZSBtaXNzZWQuIFNhdmUgdGhlIGV4Y2VsIGZpbGUgdW5kZXIgYSBuZXcgbmFtZSBzbyB0aGF0IGl0IGRvZXMgbm90IGdldCBvdmVyd3JpdHRlbiBpbiB0aGUgZXZlbnQgeW91IHJ1biB0aGlzIHNjcmlwdCBhZ2Fpbi4gQ29tcGxldGUgdGhlIGV4Y2VsIGZpbGUuIAoKIyMjIFppcCBmaWxlIGNvbnRlbnRzIFByb3ZpZGVkIGJ5IE5ESSBBbmFseXNpcwoKRmlsZSBOYW1lIHwgRmlsZSBUeXBlIHwgRGVzY3JpcHRpb24KLS0tLS0tLS0tIHwgLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0KX0VkaXRzICAgIHwgUERGICAgICAgIHxVc2VyIEZpbGUgRWRpdCBSZXN1bHRzIApQUlRDQVVTRSAgfCBQREYgICAgICAgfENhdXNlIG9mIERlYXRoIFJlcG9ydApTVU1NQVJZICAgfCBQREYgICAgICAgfFN1bW1hcnkgUmV0cmlldmFsIFN0YXRpc3RpY3MKUkVRRk9STVMgIHwgUERGICAgICAgIHxEZWF0aCBDZXJ0aWZpY2F0ZSBSZXF1ZXN0IEZvcm1zIApSRVBPUlQgICAgfCBQREYgICAgICAgfE5ESSBSZXRyaWV2YWwgUmVwb3J0CkNPTUJJTkVEICB8IFRYVCAgICAgICB8Q29tYmluZWQgRmlsZSBvZiBNYXRjaGluZyBVc2VyIGFuZCBOREkgUmVjb3JkcyAKQ0FVU0UgICAgIHwgVFhUICAgICAgIHxDYXVzZSBvZiBEZWF0aCBGaWxlLCBpbmNsdWRlcyBhbGwgcGVyc29uYWwgaW5mb3JtYXRpb24gYW5kIG1hdGNoIGRhdGEKTUFUQ0ggICAgIHwgVFhUICAgICAgIHxVc2VyIHJlY29yZHMgaW52b2x2ZWQgaW4gbWF0Y2hlcywgaW4gdGhlIHNhbWUgcmVjb3JkIGZvcm1hdCBhcyBzdWJtaXR0ZWQgYnkgdGhlIHVzZXIgCk5PTUFUQ0ggICB8IFRYVCAgICAgICB8VXNlciByZWNvcmRzIG5vdCBpbnZvbHZlZCBpbiBtYXRjaGVzIHdpdGggYW55IE5ESSByZWNvcmRzLCBpbiB0aGUgc2FtZSByZWNvcmQgZm9ybWF0IGFzIHN1Ym1pdHRlZCBieSB0aGUgdXNlci4KUkVKRUNUUyAgIHwgVFhUICAgICAgIHxVc2VyIHJlY29yZHMgcmVqZWN0ZWQgYnkgdGhlIE5ESSBlZGl0IHByb2dyYW0gYW5kIG5vdCBpbmNsdWRlZCBpbiB0aGUgTkRJIHNlYXJjaCwgaW4gdGhlIHNhbWUgcmVjb3JkIGZvcm1hdCBhcyBzdWJtaXR0ZWQgYnkgdGhlIHVzZXIKCgojIyBBbmFseXNpcyBDb2RlIHsudGFic2V0fQojIyMgUGFja2FnZXMgYW5kIEZpbGVzCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojVXBsb2FkIG5lY2Vzc2FyeSBwYWNrYWdlcwpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KERUKQpsaWJyYXJ5KHdyaXRleGwpCgojIEltcG9ydCBGaWxlcwojRmlsZSBtdXN0IGZpcnN0IGJlIG9wZW5lZCBpbiBleGNlbCBhbmQgY29udmVydGVkIGZyb20gdHh0IGZpbGUgdG8gQ1NWIGZpbGUuCmNhdXNlIDwtIHJlYWQudGFibGUoIkZTMjAyMS1YMDg4IzAwX1IxLkNBVVNFIiwgc2VwPSJcdCIsIGhlYWRlcj1GQUxTRSkKYGBgCgojIyMgRmlsZSBGb3JtYXR0aW5nCiMjIyMgUmVmb3JtYXR0aW5nIGZyb20gTkRJIHN1Ym1pc3Npb24gc3R5bGUKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiNTcGxpdCBzaW5nbGUgaW1wb3J0ZWQgc3RyaW5nIGludG8gY29sdW1ucyBiYXNlZCBvbiBjaGFyYWN0ZXIgY291bnRzIHByb3ZpZGVkIGluIHRoZSBOREkgVXNlcmd1aWRlCmN1cnJhdGVkLmNhdXNlPXNlcGFyYXRlKGNhdXNlLCBWMSwgCmludG8gPSBjKCJMYXN0Lk5hbWUiLCAiRmlyc3QuTmFtZSIsICJNaWRkbGUuSW5pdGlhbCIsICJTU04iLCAiRE9CLk1vbnRoIiwgIkRPQi5EYXkiLCAiRE9CLlllYXIiLCAiRmF0aGVyLlN1cm5hbWUiLCAiQW9ELlVuaXQiLCAiQW9ELk51bWJlciIsICJTZXgiLCAiUmFjZSIsICJNYXIuU3RhdHVzIiwgIlJlcy5TdGF0ZSIsICJCaXJ0aC5TdGF0ZSIsICJDYXNlLk51bS9SaXNrLkxldmVsIiwgIkNhc2UuQ3JlYXRlZCIsICJCbGFuay5GaWVsZCIsICJTdGF0ZS5EZWF0aCIsICJZZWFyLkRlYXRoIiwgIlN0LkRlYXRoLkNvZGUiLCAiQWxpYXMiLCAiRGVhdGguQ2VydC5OdW0iLCAiRE9ELk1vbnRoIiwgIkRPRC5EYXkiLCAiRE9ELlllYXIiLCAiTkRJOkZpcnN0Lk5hbWUiLCAiTkRJOk1pZGRsZS5Jbml0aWFsIiwgIk5ESTpMYXN0Lk5hbWUiLCAiTkRJOkZhdGhlci5TdXJuYW1lIiwgIk5ESTpTdXJuYW1lIiwgIk5ESTpTU04iLCAiTkRJOkRPQi5Nb250aCIsICJOREk6RE9CLkRheSIsICJOREk6RE9CLlllYXIiLCAiTkRJOkFnZS5EZWF0aCIsICJOREk6U2V4IiwgIk5ESTpSYWNlIiwgIk5ESTpNYXJpdGFsLlN0YXR1cyIsICJOREk6UmVzLlN0YXRlIiwgIk5ESTpCaXJ0aC5TdGF0ZSIsICJCbGFuay5GaWVsZC4yIiwgIkV4YWN0Lk1hdGNoLkluZGljYXRvciIsICJNYXRjaC5TZXEiLCAiTnVtLlBvc3MuTWF0Y2hlcyIsICJQcm9iLlNjb3JlIiwgIkNsYXNzLkNvZGUiLCAiU3RhdHVzLkNvZGUiLCAiQmxhbmsuRmllbGQuMyIsICJJQ0QuQ29kZSIsICJJQ0QuUmVjb2RlIiwgIklDRC5SZWNvZGUuMiIsICJJQ0QuUmVjb2RlLjMiLCAiTnVtLkVudGl0eS5BeGlzIiwgIkVudGl0eS5BeGlzLkNvbmQiLCAiTnVtYi5SZWNvcmQuQXhpcyIsICJSZWNvcmQuQXhpcy5Db25kIiksIApzZXAgPSBjKDIwLCAzNSwgMzYsIDQ1LCA0NywgNDksIDUzLCA3MSwgNzIsIDc0LCA3NSwgNzYsIDc3LCA3OSwgODEsIDkxLCA5NywgMTAwLCAxMTIsIDExNiwgMTE5LCAxMjAsIDEyNiwgMTI4LCAxMzAsIDEzMiwgMTM0LCAxMzUsIDEzNiwgMTM3LCAxMzgsIDE0NywgMTQ4LCAxNDksIDE1MiwgMTUzLCAxNTQsIDE1NSwgMTU2LCAxNTcsIDE1OCwgMTY0LCAxNjUsIDE2OCwgMTcxLCAxNzYsIDE3NywgMTc4LCAxNzksIDE4MywgMTg4LCAxOTEsMTk0LDE5NiwzMzYsIDMzOCksIHJlbW92ZSA9IEZBTFNFKQoKI3JlbW92ZSB0aGUgZmlyc3QgY29sdW1uLCB3aGljaCBjb250YWlucyB0aGUgc3RyaW5nIGRhdGEgdXNlZCB0byBjcmVhdGUgc2VwYXJhdGUgY29sdW1ucwpjdXJyYXRlZC5jYXVzZSA9IHN1YnNldChjdXJyYXRlZC5jYXVzZSwgc2VsZWN0ID0gLWMoMSkgKQoKI3B1dCBhbiAiTkEiIGluIGFsbCBjZWxscyB0aGF0IGNvbnRhaW4gbm90aGluZyBidXQgd2hpdGUgc3BhY2UuIFRoaXMgbXVzdCBiZSBkb25lIGFzIHRoZSBzcGFjZXMgYXJlIHJlYWQgaW4gYXMgY2hhcmFjdGVycyBkdWUgdG8gZmlsZSB0eXBlIGF0IHVwbG9hZC4KY3VycmF0ZWQuY2F1c2VbXSA8LSBsYXBwbHkoY3VycmF0ZWQuY2F1c2UsIGZ1bmN0aW9uKHgpCiAgICAgIHR5cGUuY29udmVydChyZXBsYWNlKHgsIGdyZXBsKCJeXFxzKiQiLCB0cmltd3MoeCkpLCBOQSksIGFzLmlzID0gVFJVRSkpCgojUmVtb3ZlIGNvbHVtbnMgdGhhdCBoYXZlIG5vIHZhbHVlcyBpbiBhbnkgcm93cwpjdXJyYXRlZC5jYXVzZSA8LSBjdXJyYXRlZC5jYXVzZVssY29sU3Vtcyhpcy5uYShjdXJyYXRlZC5jYXVzZSkpPG5yb3coY3VycmF0ZWQuY2F1c2UpXQoKI1JlbW92ZSB3aGl0ZSBzcGFjZXMgcmVtYWluaW5nIGFzICJjaGFyYWN0ZXIiIHJlYWRzIGF0IHRoZSBlbmQgb2YgdGhlIGZvbGxvd2luZyBjb2x1bW5zLiAKY3VycmF0ZWQuY2F1c2UkTGFzdC5OYW1lPShnc3ViKCIgIiwiIixjdXJyYXRlZC5jYXVzZSRMYXN0Lk5hbWUpKQpjdXJyYXRlZC5jYXVzZSRgTkRJOkZpcnN0Lk5hbWVgPShnc3ViKCIgIiwiIixjdXJyYXRlZC5jYXVzZSRgTkRJOkZpcnN0Lk5hbWVgKSkKY3VycmF0ZWQuY2F1c2UkYE5ESTpET0IuWWVhcmA9KGdzdWIoIiAiLCIiLGN1cnJhdGVkLmNhdXNlJGBOREk6RE9CLlllYXJgKSkKY3VycmF0ZWQuY2F1c2UkSUNELkNvZGU9KGdzdWIoIiAiLCIiLGN1cnJhdGVkLmNhdXNlJElDRC5Db2RlKSkKCiNDb21iaW5lIE1vbnRoLCBEYXkgYW5kIFllYXIgb2YgYmlydGggaW50byBhIHNpbmdsZSBjb2x1bW4KY3VycmF0ZWQuY2F1c2UkRE9CIDwtIHBhc3RlKGN1cnJhdGVkLmNhdXNlJERPQi5Nb250aCwgIi0iLCBjdXJyYXRlZC5jYXVzZSRET0IuRGF5LCAiLSIsIGN1cnJhdGVkLmNhdXNlJERPQi5ZZWFyKQojTW92ZSB0aGUgbmV3IHNpbmdsZSBET0IgdmFyaWFibGUgdG8gdGhlIERPQiBsb2NhdGlvbiBpbiBmaWxlCmN1cnJhdGVkLmNhdXNlPWN1cnJhdGVkLmNhdXNlICU+JSByZWxvY2F0ZShET0IsIC5hZnRlcj1ET0IuWWVhcikKI1JlbW92ZSBvcmlnaW5hbCwgc2VwZXJhdGUgTW9udGgsIERheSwgWWVhciBvZiBiaXJ0aCBjb2x1bW5zCmN1cnJhdGVkLmNhdXNlIDwtIGN1cnJhdGVkLmNhdXNlWyAtYygzOjUpIF0KCiNSZXBlYXQgcHJvY2VzcyBhYm92ZSBmb3IgRGF0ZSBvZiBEZWF0aCBhbmQgRmlyc3QvTGFzdCBOYW1lIHZhcmlhYmxlcy4gCmN1cnJhdGVkLmNhdXNlJERPRCA8LSBwYXN0ZShjdXJyYXRlZC5jYXVzZSRET0QuTW9udGgsICItIiwgY3VycmF0ZWQuY2F1c2UkRE9ELkRheSwgIi0iLCBjdXJyYXRlZC5jYXVzZSRET0QuWWVhcikKY3VycmF0ZWQuY2F1c2U9Y3VycmF0ZWQuY2F1c2UgJT4lIHJlbG9jYXRlKERPRCwgLmFmdGVyPURPRC5ZZWFyKQpjdXJyYXRlZC5jYXVzZSA8LSBjdXJyYXRlZC5jYXVzZVsgLWMoMTc6MTkpIF0KCmN1cnJhdGVkLmNhdXNlJExhc3QuRmlyc3QgPC0gcGFzdGUoY3VycmF0ZWQuY2F1c2UkTGFzdC5OYW1lLCAiLCIsIGN1cnJhdGVkLmNhdXNlJEZpcnN0Lk5hbWUpCmN1cnJhdGVkLmNhdXNlPWN1cnJhdGVkLmNhdXNlICU+JSByZWxvY2F0ZShMYXN0LkZpcnN0LCAuYWZ0ZXI9Rmlyc3QuTmFtZSkKY3VycmF0ZWQuY2F1c2UgPC0gY3VycmF0ZWQuY2F1c2VbIC1jKDE6MikgXQoKI1JlY29kZSBudW1lcmljYWwgU2V4IGNvbHVtbiB3aXRoIG1hdGNoaW5nIHRlcm1zCmN1cnJhdGVkLmNhdXNlID0gY3VycmF0ZWQuY2F1c2UgJT4lIG11dGF0ZShTZXg9cmVjb2RlKFNleCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBgMWA9Ik1hbGUiLCBgMmA9IkZlbWFsZSIsIGA5YD0gIlVua25vd24iLCAgIk5BIj0gIlVua25vd24iKSkKCiNSZWNvZGUgbnVtZXJpY2FsIFJhY2UgY29sdW1uIHdpdGggbWF0Y2hpbmcgdGVybXMKY3VycmF0ZWQuY2F1c2UgPSBjdXJyYXRlZC5jYXVzZSAlPiUgbXV0YXRlKFJhY2U9cmVjb2RlKFJhY2UsIAogICAgICAgICAgICAgICAgICAgICAgICAgYDFgPSJXaGl0ZSIsIGAyYD0iQmxhY2siLGAzYD0gIkluZGlhbiIsIGA0YD0gIkNoaW5lc2UiLCBgNWA9IkphcGFuZXNlIiwgYDZgPSJIYXdhaWlhbiIsIGA3YD0iT3RoZXItbm9ud2hpdGUiLCAgYDhgPSJGaWxpcGlubyIsIGAwYD0iT3RoZXIgQXNpYW4vUGFjaWZpYyBJc2xhbmRlciIsYDlgPSAiVW5rbm93biIsICAiTkEiPSJVbmtub3duIikpCgojUmVjb2RlIG51bWVyaWNhbCBNYXJpdGFsIFN0YXR1cyBjb2x1bW4gd2l0aCBtYXRjaGluZyB0ZXJtcwpjdXJyYXRlZC5jYXVzZSA9IGN1cnJhdGVkLmNhdXNlICU+JSBtdXRhdGUoTWFyLlN0YXR1cz1yZWNvZGUoTWFyLlN0YXR1cywgCiAgICAgICAgICAgICAgICAgICAgICAgICBgMWA9IlNpbmdsZSIsIGAyYD0iTWFycmllZCIsYDNgPSAiV2lkb3dlZCIsICBgNGA9ICJEaXZvcmNlZCIsICBgOWA9ICJVbmtub3duIiwgICJOQSI9IlVua25vd24iKSkKCiNSZWNvZGUgbnVtZXJpY2FsIFJlc2lkZW50aWFsIFN0YXRlIGNvbHVtbiB3aXRoIG1hdGNoaW5nIHRlcm1zCmN1cnJhdGVkLmNhdXNlID0gY3VycmF0ZWQuY2F1c2UgJT4lIG11dGF0ZShSZXMuU3RhdGU9cmVjb2RlKFJlcy5TdGF0ZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBgMWA9IkFsYWJhbWEiLCBgMmA9IkFsYXNrYSIsYDNgPSAiQXJpem9uYSIsIGA0YD0gIkFya2Fuc2FzIiwgYDVgPSJDYWxpZm9ybmlhIiwgYDZgPSJDb2xvcmFkbyIsIGA3YD0iQ29ubmVjdGljdXQiLCAgYDhgPSJEZWxhd2FyZSIsIGA5YD0iRGlzdHJpY3Qgb2YgQ29sdW1iaWEiLCBgMTBgPSAiRmxvcmlkYSIsICBgMTFgPSJHZW9yZ2lhIiwgYDEyYD0iSGF3YWlpIiwgYDEzYD0gIklkYWhvIiwgYDE0YD0gIklsbGlub2lzIiwgYDE1YD0iSW5kaWFuYSIsIGAxNmA9Iklvd2EiLCBgMTdgPSJLYW5zYXMiLCBgMThgPSJLZW50dWNreSIsIGAxOWA9IkxvdWlzaWFuYSIsIGAyMGA9ICJNYWluZSIsICBgMjFgPSJNYXJ5bGFuZCIsIGAyMmA9Ik1hc3NhY2h1c2V0dHMiLCBgMjNgPSAiTWljaGlnYW4iLCBgMjRgPSAiTWlubmVzb3RhIiwgIGAyNWA9Ik1pc3Npc3NpcHBpIiwgYDI2YD0iTWlzc291cmkiLCBgMjdgPSJNb250YW5hIixgMjhgPSJOZWJyYXNrcyIsIGAyOWA9Ik5ldmFkYSIsIGAzMGA9ICJOZXcgSGFtcHNoaXJlIiwgIGAzMWA9Ik5ldyBKZXJzZXkiLCBgMzJgPSJOZXcgTWVkaWNvIiwgYDMzYD0gIk5ldyBZb3JrIiwgIGAzNGA9ICJOb3J0aCBDYXJvbGluYSIsICBgMzVgPSJOb3J0aCBEYWtvdGEiLCAgYDM2YD0iT2hpbyIsIGAzN2A9Ik9rbGFob21hIiwgIGAzOGA9Ik9yZWdvbiIsIGAzOWA9IlBlbm5zeWx2YW5pYSIsIGA0MGA9ICJSaG9kZSBJc2xhbmQiLCAgYDQxYD0iU291dGggQ2Fyb2xpbmEiLCBgNDJgPSJTb3V0aCBEYWtvdGEiLGA0M2A9ICJUZW5uZXNzZWUiLCAgYDQ0YD0gIlRleGFzIiwgIGA0NWA9IlV0YWgiLCAgYDQ2YD0iVmVybW9udCIsIGA0N2A9IlZpcmdpbmlhIiwgIGA0OGA9Ildhc2hpbmd0b24iLCBgNDlgPSJXZXN0IFZpcmdpbmlhIiwgYDUwYD0gIldpc2NvbnNpbiIsIGA1MWA9Ild5b21pbmciLGA1MmA9IlB1ZXJ0byBSaWNvIiwgYDUzYD0gIlZpcmdpbiBJc2xhbmRzIiwgYDU0YD0gIkd1YW0iLCAgYDU1YD0iQ2FuYWRhIiwgIGA1NmA9IkN1YmEiLCBgNTdgPSJNZXhpY28iLCBgNTlgPSJSZW1haW5kZXIgb2YgV29ybGQiLGA5OWA9IlVua25vd24iLCAiTkEiPSJVbmtub3duIikpCgojUmVjb2RlIE5ESSBNYXRjaCBzeW1ib2xzIHdpdGggbWF0Y2hpbmcgdGVybXMKY3VycmF0ZWQuY2F1c2UgPSBjdXJyYXRlZC5jYXVzZSAlPiUKICBtdXRhdGUoYWNyb3NzKAogICAgYE5ESTpGaXJzdC5OYW1lYDpgTkRJOkJpcnRoLlN0YXRlYCwKICAgIH4gcmVjb2RlKAogICAgICAueCwKICAgICAgIlgiID0gIkV4YWN0IE1hdGNoIiwKICAgICAgIk5BIiA9ICJEb2VzIE5vdCBNYXRjaCIsCiAgICAgICdOQScgPSAiRG9lcyBOb3QgTWF0Y2giLAogICAgICAiICIgPSAiRG9lcyBOb3QgTWF0Y2giLAogICAgICAiPyIgPSAiTWlzc2luZyBpbiBOREkiLAogICAgICAiLSIgPSAiTWlzc2luZyBmcm9tIFVzZXIiLAogICAgICAiTiIgPSAiTmFtZXMgbWF0Y2ggb25seSBOWVNJSVMiLAogICAgICAiSSIgPSAiT25seSBGaXJzdCBJbml0aWFsIE1hdGNoIiwKICAgICAgIkIiID0gIk1pc3NpbmcgaW4gTkRJIGFuZCBVc2VyIiwKICAgICAgIkEiID0gIk5ESSBSZWNvcmQgaXMgQWxpYXMiLAogICAgICAiSU4iID0gIk9ubHkgRmlyc3QgSW5pdGlhbCAmIE9ubHkgTllTSUlTIgogICAgKQogICkpCgpjdXJyYXRlZC5jYXVzZSRgTkRJOkZpcnN0Lk5hbWVgW2lzLm5hKGN1cnJhdGVkLmNhdXNlJGBOREk6Rmlyc3QuTmFtZWApXSA8LSAiRG9lcyBOb3QgTWF0Y2giCmN1cnJhdGVkLmNhdXNlJGBOREk6TWlkZGxlLkluaXRpYWxgW2lzLm5hKGN1cnJhdGVkLmNhdXNlJGBOREk6TWlkZGxlLkluaXRpYWxgKV0gPC0gIkRvZXMgTm90IE1hdGNoIgpjdXJyYXRlZC5jYXVzZSRgTkRJOkxhc3QuTmFtZWBbaXMubmEoY3VycmF0ZWQuY2F1c2UkYE5ESTpMYXN0Lk5hbWVgKV0gPC0gIkRvZXMgTm90IE1hdGNoIgpjdXJyYXRlZC5jYXVzZSRgTkRJOkZhdGhlci5TdXJuYW1lYFtpcy5uYShjdXJyYXRlZC5jYXVzZSRgTkRJOkZhdGhlci5TdXJuYW1lYCldIDwtICJEb2VzIE5vdCBNYXRjaCIKY3VycmF0ZWQuY2F1c2UkYE5ESTpTdXJuYW1lYFtpcy5uYShjdXJyYXRlZC5jYXVzZSRgTkRJOlN1cm5hbWVgKV0gPC0gIkRvZXMgTm90IE1hdGNoIgpjdXJyYXRlZC5jYXVzZSRgTkRJOlNTTmBbaXMubmEoY3VycmF0ZWQuY2F1c2UkYE5ESTpTU05gKV0gPC0gIkRvZXMgTm90IE1hdGNoIgpjdXJyYXRlZC5jYXVzZSRgTkRJOkRPQi5Nb250aGBbaXMubmEoY3VycmF0ZWQuY2F1c2UkYE5ESTpET0IuTW9udGhgKV0gPC0gIkRvZXMgTm90IE1hdGNoIgpjdXJyYXRlZC5jYXVzZSRgTkRJOkRPQi5EYXlgW2lzLm5hKGN1cnJhdGVkLmNhdXNlJGBOREk6RE9CLkRheWApXSA8LSAiRG9lcyBOb3QgTWF0Y2giCmN1cnJhdGVkLmNhdXNlJGBOREk6RE9CLlllYXJgW2lzLm5hKGN1cnJhdGVkLmNhdXNlJGBOREk6RE9CLlllYXJgKV0gPC0gIkRvZXMgTm90IE1hdGNoIgpjdXJyYXRlZC5jYXVzZSRgTkRJOkFnZS5EZWF0aGBbaXMubmEoY3VycmF0ZWQuY2F1c2UkYE5ESTpBZ2UuRGVhdGhgKV0gPC0gIkRvZXMgTm90IE1hdGNoIgpjdXJyYXRlZC5jYXVzZSRgTkRJOlNleGBbaXMubmEoY3VycmF0ZWQuY2F1c2UkYE5ESTpTZXhgKV0gPC0gIkRvZXMgTm90IE1hdGNoIgpjdXJyYXRlZC5jYXVzZSRgTkRJOlJhY2VgW2lzLm5hKGN1cnJhdGVkLmNhdXNlJGBOREk6UmFjZWApXSA8LSAiRG9lcyBOb3QgTWF0Y2giCmN1cnJhdGVkLmNhdXNlJGBOREk6TWFyaXRhbC5TdGF0dXNgW2lzLm5hKGN1cnJhdGVkLmNhdXNlJGBOREk6TWFyaXRhbC5TdGF0dXNgKV0gPC0gIkRvZXMgTm90IE1hdGNoIgpjdXJyYXRlZC5jYXVzZSRgTkRJOlJlcy5TdGF0ZWBbaXMubmEoY3VycmF0ZWQuY2F1c2UkYE5ESTpSZXMuU3RhdGVgKV0gPC0gIkRvZXMgTm90IE1hdGNoIgpjdXJyYXRlZC5jYXVzZSRgTkRJOkJpcnRoLlN0YXRlYFtpcy5uYShjdXJyYXRlZC5jYXVzZSRgTkRJOkJpcnRoLlN0YXRlYCldIDwtICJEb2VzIE5vdCBNYXRjaCIKCiNSZWNvZGUgU3RhdHVzIENvZGUgbWF0Y2ggZGVzaWduYXRpb24gd2l0aCBhcHByb3ByaWF0ZSBwaHJhc2UKY3VycmF0ZWQuY2F1c2UgPSBjdXJyYXRlZC5jYXVzZSAlPiUgbXV0YXRlKFN0YXR1cy5Db2RlPXJlY29kZShTdGF0dXMuQ29kZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBgMGA9IkZBTFNFIE1hdGNoOiBBc3N1bWVkIEFsaXZlIiwKICAgICAgICAgICAgICAgICAgICAgICAgIGAxYD0iVFJVRSBNYXRjaDogQXNzdW1lZCBEZWFkIikpCmBgYAoKIyMjIyBQcm9kdWNlIGRhdGFzZXQgb3JnYW5pemVkIGZvciBTU1MgdXNlCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQoKIyMgUHJvZHVjZSBkYXRhc2V0IG9yZ2FuaXplZCBmb3IgU1NTIHVzZQojUmVvcmdhbml6ZSBjb2x1bW5zIHRvIGJlIGluIG9yZGVyIG9mIG91ciBzdWJtaXR0ZWQgaW5mb3JtYXRpb24gZm9sbG93ZWQgYnkgTkRJIG1hdGNoIGNyaXRlcmlhCmtlZXA9YygiTGFzdC5GaXJzdCIsICJOREk6Rmlyc3QuTmFtZSIsICJOREk6TGFzdC5OYW1lIiwgJ0RPQicsICJOREk6RE9CLk1vbnRoIiwgIk5ESTpET0IuRGF5IiwgIk5ESTpET0IuWWVhciIsICdTZXgnLCAiTkRJOlNleCIsICdSYWNlJywgIk5ESTpSYWNlIiwgJ01hci5TdGF0dXMnLCJOREk6TWFyaXRhbC5TdGF0dXMiLCAgJ1Jlcy5TdGF0ZScsICJOREk6UmVzLlN0YXRlIiwgJ0Nhc2UuTnVtL1Jpc2suTGV2ZWwnLCAnQ2FzZS5DcmVhdGVkJywgJ1N0YXRlLkRlYXRoJywgJ0RPRCcsICJEZWF0aC5DZXJ0Lk51bSIsICJFeGFjdC5NYXRjaC5JbmRpY2F0b3IiLCAiU3RhdHVzLkNvZGUiLCAiSUNELkNvZGUiLCAiUmVjb3JkLkF4aXMuQ29uZCIpCgpjYXVzZS5maW5hbCA9IGN1cnJhdGVkLmNhdXNlW2tlZXBdCmBgYAoKIyMjIENyZWF0aW9uIG9mIE1hdGNoIEZpbGVzCiMjIyMgSXNvbGF0ZSBQb3RlbnRpYWwgTWF0Y2hlcyAKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiNTdWJzZXQgZGF0YSB0byBvbmx5IGluY2x1ZGUgaW5kaXZpZHVhbHMgd2l0aCBhIHN0YXR1cyBjb2RlIG9mICIxIiwgd2hpY2ggaW5kaWNhdGVzIGEgZGVhdGguCmRlYXRoLm1hdGNoZXM9c3Vic2V0KGNhdXNlLmZpbmFsLCBTdGF0dXMuQ29kZSA9PSAiVFJVRSBNYXRjaDogQXNzdW1lZCBEZWFkIikKYGBgCgojIyMjIElzb2xhdGUgTm9uLU1hdGNoZXMgd2l0aCBEZWF0aCBieSBTdWljaWRlCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KI0xvb2sgaW4gdGhlIHN0YXR1cyBjb2RlICIwIiAKI3N0YXR1cyBjb2RlID0gMCA7IElDRCBjb2RlIGZvciBTdWljaWRlL2ludGVudGlvbmFsIHNlbGYgaGFybSByZXN1bHRpbmcgaW4gZGVhdGggKFg2MC1YODQpCmRlYXRoLm5vbWF0PXN1YnNldChjYXVzZS5maW5hbCwgU3RhdHVzLkNvZGUgPT0gIkZBTFNFIE1hdGNoOiBBc3N1bWVkIEFsaXZlIikKYGBgCgojIyMjIFN1YnNldCBkYXRhIHRvIGluY2x1ZGUgb25seSB0aG9zZSB0aGF0IGFyZSBUcnVlIE1hdGNoZXMsIGFuZCBGYWxzZSBNYXRjaGVzIHRoYXQgYXJlIGRlYXRoIGJ5IHN1aWNpZGUgb3Igc2VsZi1oYXJtCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojSXNvbGF0ZSByZWNvcmRzIHdpdGggYW4gUmVjb3JkIEF4aXMgQ29kZSBpbmRpY2F0aW5nICJTdWljaWRlIiBvciAiSW50ZW50aW9uYWwgU2VsZiBIYXJtIiBhIGEgc2Vjb25kYXJ5IElDRCBDb2RlCgpkZWF0aC5ub21hdGNoMj1zdWJzZXQoZGVhdGgubm9tYXQsIAogICAgICBncmVwbCgiKlg2LioiLCBSZWNvcmQuQXhpcy5Db25kKSB8CiAgICAgIGdyZXBsKCIqWDcuKiIsIFJlY29yZC5BeGlzLkNvbmQpIHwKICAgICAgZ3JlcGwoIipYOFswLTRdLioiLCBSZWNvcmQuQXhpcy5Db25kKSB8CiAgICAgIGdyZXBsKCIqVTAzLioiLCBSZWNvcmQuQXhpcy5Db25kKSB8CiAgICAgIGdyZXBsKCIqWTg3LioiLCBSZWNvcmQuQXhpcy5Db25kKSkKICAgICAgICAgICAgICAgICAgICAgIApjaGVjaz0gcmJpbmQoZGVhdGgubWF0Y2hlcyxkZWF0aC5ub21hdGNoMikKCiMjIyBTZXBlcmF0ZSB0aGUgUmVjb3JkIGF4aXMgaW50byBpbmRpdmlkdWFsIGNvbHVtbnMKIyMjIHJlcGxhY2UgY29kZXMgd2l0aCBwaHJhc2VzCgpsaWJyYXJ5KHNwbGl0c3RhY2tzaGFwZSkKY2hlY2s9Y1NwbGl0KGNoZWNrLCAiUmVjb3JkLkF4aXMuQ29uZCIsICIgIikKYGBgCgojIyMgUmVmb3JtYXRpbmcgSUNEIENvZGVzCiMjIyMgSW1wb3J0IENEQyBJQ0QgY29kZXMgZnJvbSAyMDIzIGNvZGluZyBib29rCgoqKkRvd25sb2FkZWQgZnJvbSBDREMgd2VicGFnZSoKCmh0dHBzOi8vZnRwLmNkYy5nb3YvcHViL0hlYWx0aF9TdGF0aXN0aWNzL05DSFMvUHVibGljYXRpb25zL0lDRDEwQ00vQXByaWwtMS0yMDIzLVVwZGF0ZS8KCmh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9pY2QvQ29tcHJlaGVuc2l2ZS1MaXN0aW5nLW9mLUlDRC0xMC1DTS1GaWxlcy5odG0KCklDRCBDb2RlczogU3VpY2lkZSBvciBJbnRlbnRpb25hbCBzZWxmLWhhcm0gKFg2MC1YODQsIFkpCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KSUNELmNvZGVzPXJlYWQuY3N2KAogICJpY2QxMGNtLWNvZGVzLSBBcHJpbCAxIDIwMjMuY3N2IiwgaGVhZGVyPUZBTFNFKQoKSUNELmNvZGVzPXJlbmFtZShJQ0QuY29kZXMsIElDRC5Db2RlID0gVjEpCklDRC5jb2Rlcz1yZW5hbWUoSUNELmNvZGVzLCBEZXNjcmlwdGlvbiA9IFYyKQoKSUNELmNvZGVzMTg9cmVhZC5jc3YoIjIwMThfSUNEY29kZXMuY3N2IiwgaGVhZGVyPUZBTFNFKQpJQ0QuY29kZXMxOD1yZW5hbWUoSUNELmNvZGVzMTgsIElDRC5Db2RlID0gVjEpCklDRC5jb2RlczE4PXJlbmFtZShJQ0QuY29kZXMxOCwgRGVzY3JpcHRpb24gPSBWMikKYGBgCgojIyMjIFJFUExBQ0UgQUxMIFJFQ09SRCBDT0RFUyBXSVRIIFRFUk1TCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KCmlkeCA8LSBtYXRjaChjaGVjayRSZWNvcmQuQXhpcy5Db25kXzEsIElDRC5jb2RlcyRJQ0QuQ29kZSkKaWR4biA8LSB3aGljaCghaXMubmEoaWR4KSkKI2lkeG4gPC0gIWlzLm5hKGlkeCkgI0FsdGVybmF0aXZlCmNoZWNrJFJlY29yZC5BeGlzLkNvbmRfMVtpZHhuXSA8LSBJQ0QuY29kZXMkRGVzY3JpcHRpb25baWR4W2lkeG5dXQppZHggPC0gbWF0Y2goY2hlY2skUmVjb3JkLkF4aXMuQ29uZF8xLCBJQ0QuY29kZXMxOCRJQ0QuQ29kZSkKaWR4biA8LSB3aGljaCghaXMubmEoaWR4KSkKI2lkeG4gPC0gIWlzLm5hKGlkeCkgI0FsdGVybmF0aXZlCmNoZWNrJFJlY29yZC5BeGlzLkNvbmRfMVtpZHhuXSA8LSBJQ0QuY29kZXMxOCREZXNjcmlwdGlvbltpZHhbaWR4bl1dCgppZHggPC0gbWF0Y2goY2hlY2skUmVjb3JkLkF4aXMuQ29uZF8yLCBJQ0QuY29kZXMkSUNELkNvZGUpCmlkeG4gPC0gd2hpY2goIWlzLm5hKGlkeCkpCiNpZHhuIDwtICFpcy5uYShpZHgpICNBbHRlcm5hdGl2ZQpjaGVjayRSZWNvcmQuQXhpcy5Db25kXzJbaWR4bl0gPC0gSUNELmNvZGVzJERlc2NyaXB0aW9uW2lkeFtpZHhuXV0KaWR4IDwtIG1hdGNoKGNoZWNrJFJlY29yZC5BeGlzLkNvbmRfMiwgSUNELmNvZGVzMTgkSUNELkNvZGUpCmlkeG4gPC0gd2hpY2goIWlzLm5hKGlkeCkpCiNpZHhuIDwtICFpcy5uYShpZHgpICNBbHRlcm5hdGl2ZQpjaGVjayRSZWNvcmQuQXhpcy5Db25kXzJbaWR4bl0gPC0gSUNELmNvZGVzMTgkRGVzY3JpcHRpb25baWR4W2lkeG5dXQoKaWR4IDwtIG1hdGNoKGNoZWNrJFJlY29yZC5BeGlzLkNvbmRfMywgSUNELmNvZGVzJElDRC5Db2RlKQppZHhuIDwtIHdoaWNoKCFpcy5uYShpZHgpKQojaWR4biA8LSAhaXMubmEoaWR4KSAjQWx0ZXJuYXRpdmUKY2hlY2skUmVjb3JkLkF4aXMuQ29uZF8zW2lkeG5dIDwtIElDRC5jb2RlcyREZXNjcmlwdGlvbltpZHhbaWR4bl1dCmlkeCA8LSBtYXRjaChjaGVjayRSZWNvcmQuQXhpcy5Db25kXzMsIElDRC5jb2RlczE4JElDRC5Db2RlKQppZHhuIDwtIHdoaWNoKCFpcy5uYShpZHgpKQojaWR4biA8LSAhaXMubmEoaWR4KSAjQWx0ZXJuYXRpdmUKY2hlY2skUmVjb3JkLkF4aXMuQ29uZF8zW2lkeG5dIDwtIElDRC5jb2RlczE4JERlc2NyaXB0aW9uW2lkeFtpZHhuXV0KCmlkeCA8LSBtYXRjaChjaGVjayRSZWNvcmQuQXhpcy5Db25kXzQsIElDRC5jb2RlcyRJQ0QuQ29kZSkKaWR4biA8LSB3aGljaCghaXMubmEoaWR4KSkKI2lkeG4gPC0gIWlzLm5hKGlkeCkgI0FsdGVybmF0aXZlCmNoZWNrJFJlY29yZC5BeGlzLkNvbmRfNFtpZHhuXSA8LSBJQ0QuY29kZXMkRGVzY3JpcHRpb25baWR4W2lkeG5dXQppZHggPC0gbWF0Y2goY2hlY2skUmVjb3JkLkF4aXMuQ29uZF80LCBJQ0QuY29kZXMxOCRJQ0QuQ29kZSkKaWR4biA8LSB3aGljaCghaXMubmEoaWR4KSkKI2lkeG4gPC0gIWlzLm5hKGlkeCkgI0FsdGVybmF0aXZlCmNoZWNrJFJlY29yZC5BeGlzLkNvbmRfNFtpZHhuXSA8LSBJQ0QuY29kZXMxOCREZXNjcmlwdGlvbltpZHhbaWR4bl1dCgppZHggPC0gbWF0Y2goY2hlY2skUmVjb3JkLkF4aXMuQ29uZF81LCBJQ0QuY29kZXMkSUNELkNvZGUpCmlkeG4gPC0gd2hpY2goIWlzLm5hKGlkeCkpCiNpZHhuIDwtICFpcy5uYShpZHgpICNBbHRlcm5hdGl2ZQpjaGVjayRSZWNvcmQuQXhpcy5Db25kXzVbaWR4bl0gPC0gSUNELmNvZGVzJERlc2NyaXB0aW9uW2lkeFtpZHhuXV0KaWR4IDwtIG1hdGNoKGNoZWNrJFJlY29yZC5BeGlzLkNvbmRfNSwgSUNELmNvZGVzMTgkSUNELkNvZGUpCmlkeG4gPC0gd2hpY2goIWlzLm5hKGlkeCkpCiNpZHhuIDwtICFpcy5uYShpZHgpICNBbHRlcm5hdGl2ZQpjaGVjayRSZWNvcmQuQXhpcy5Db25kXzVbaWR4bl0gPC0gSUNELmNvZGVzMTgkRGVzY3JpcHRpb25baWR4W2lkeG5dXQoKaWR4IDwtIG1hdGNoKGNoZWNrJFJlY29yZC5BeGlzLkNvbmRfNiwgSUNELmNvZGVzJElDRC5Db2RlKQppZHhuIDwtIHdoaWNoKCFpcy5uYShpZHgpKQojaWR4biA8LSAhaXMubmEoaWR4KSAjQWx0ZXJuYXRpdmUKY2hlY2skUmVjb3JkLkF4aXMuQ29uZF82W2lkeG5dIDwtIElDRC5jb2RlcyREZXNjcmlwdGlvbltpZHhbaWR4bl1dCmlkeCA8LSBtYXRjaChjaGVjayRSZWNvcmQuQXhpcy5Db25kXzYsIElDRC5jb2RlczE4JElDRC5Db2RlKQppZHhuIDwtIHdoaWNoKCFpcy5uYShpZHgpKQojaWR4biA8LSAhaXMubmEoaWR4KSAjQWx0ZXJuYXRpdmUKY2hlY2skUmVjb3JkLkF4aXMuQ29uZF82W2lkeG5dIDwtIElDRC5jb2RlczE4JERlc2NyaXB0aW9uW2lkeFtpZHhuXV0KCmlkeCA8LSBtYXRjaChjaGVjayRSZWNvcmQuQXhpcy5Db25kXzcsIElDRC5jb2RlcyRJQ0QuQ29kZSkKaWR4biA8LSB3aGljaCghaXMubmEoaWR4KSkKI2lkeG4gPC0gIWlzLm5hKGlkeCkgI0FsdGVybmF0aXZlCmNoZWNrJFJlY29yZC5BeGlzLkNvbmRfN1tpZHhuXSA8LSBJQ0QuY29kZXMkRGVzY3JpcHRpb25baWR4W2lkeG5dXQppZHggPC0gbWF0Y2goY2hlY2skUmVjb3JkLkF4aXMuQ29uZF83LCBJQ0QuY29kZXMxOCRJQ0QuQ29kZSkKaWR4biA8LSB3aGljaCghaXMubmEoaWR4KSkKI2lkeG4gPC0gIWlzLm5hKGlkeCkgI0FsdGVybmF0aXZlCmNoZWNrJFJlY29yZC5BeGlzLkNvbmRfN1tpZHhuXSA8LSBJQ0QuY29kZXMxOCREZXNjcmlwdGlvbltpZHhbaWR4bl1dCgppZHggPC0gbWF0Y2goY2hlY2skUmVjb3JkLkF4aXMuQ29uZF84LCBJQ0QuY29kZXMkSUNELkNvZGUpCmlkeG4gPC0gd2hpY2goIWlzLm5hKGlkeCkpCiNpZHhuIDwtICFpcy5uYShpZHgpICNBbHRlcm5hdGl2ZQpjaGVjayRSZWNvcmQuQXhpcy5Db25kXzhbaWR4bl0gPC0gSUNELmNvZGVzJERlc2NyaXB0aW9uW2lkeFtpZHhuXV0KaWR4IDwtIG1hdGNoKGNoZWNrJFJlY29yZC5BeGlzLkNvbmRfOCwgSUNELmNvZGVzMTgkSUNELkNvZGUpCmlkeG4gPC0gd2hpY2goIWlzLm5hKGlkeCkpCiNpZHhuIDwtICFpcy5uYShpZHgpICNBbHRlcm5hdGl2ZQpjaGVjayRSZWNvcmQuQXhpcy5Db25kXzhbaWR4bl0gPC0gSUNELmNvZGVzMTgkRGVzY3JpcHRpb25baWR4W2lkeG5dXQoKYGBgCgojIyMjIENvbWJpbmUgUG90ZW50aWFsIE1hdGNoZXMgaW50byBFeGNlbCBGaWxlIGZvciBWZXJpZmljYXRpb24gYnkgU1NTCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KY2hlY2skYENvbmZpcm1lZCBDbGllbnQgU3VpY2lkZWAgPSBOQQpjaGVjayRgU1NTIEp1c3RpZmljYXRpb25gID0gTkEKd3JpdGVfeGxzeChjaGVjaywiTkRJX0RldGFpbGVkQ2hlY2sueGxzeCIpCmBgYAoKIyMgSW50ZXJhY3RpdmUgRGF0YSBUYWJsZSB7LnRhYnNldH0KCj5UaGlzIHRhYmxlIHdpbGwgY29uc2lzdCBvZiBhbGwgIlRydWUgTWF0Y2hlcyIgaW4gd2hpY2ggdGhlIE5ESSBzZWFyY2ggcHJvZHVjZWQgYSBwcm9iYWJsZSBtYXRjaCB0byBhbiBTU1MgY2xpZW50LCB0aGF0IGlzIHRob3NlIHRoYXQgYXJlIGNsYXNzaWZpZWQgYXMg4oCcVHJ1ZSBNYXRjaDogQXNzdW1lZCBEZWFk4oCdLiBUaGlzIGluY2x1ZGVzIGFsbCBOREkgaGl0cyBpbiB3aGljaCBhIGRlY2Vhc2VkIGluZGl2aWR1YWwgaW4gdGhlaXIgZGF0YWJhc2Ugd2FzIGEgc3Ryb25nIGVub3VnaCBtYXRjaCB0byBvdXIgY2xpZW50IGNvaG9ydCBiZSBjb25zaWRlcmVkIGEgZGVjZWFzZWQgY2xpZW50LiAKCgpgYGB7ciwgZWNobz1GQUxTRSwgIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkoZGF0YS50YWJsZSkKCmRhdGF0Ymw9Y2hlY2sKI2luY2x1ZGUgb25seSB0aG9zZSBpbmRpdmlkdWFsIHdlcmUgd2VyZSAidHJ1ZSBtYXRjaGVzIiB0byBTU1MgY2xpZW50cwpkYXRhdGJsPXN1YnNldChkYXRhdGJsLCBTdGF0dXMuQ29kZSA9PSAnVFJVRSBNYXRjaDogQXNzdW1lZCBEZWFkJykKZGF0YXRibCA8LSBjaGVja1ssYygxNiw4LDEwLCAxMiwgMTQsIDE3OjE5LCAyNDozMSApXQoKZGF0YXRhYmxlKGRhdGEgPSBkYXRhdGJsLCB3aWR0aD1OVUxMLCAgZmlsdGVyID0gInRvcCIsIGNhcHRpb249ICJUYWJsZSAzOiAiLCByb3duYW1lcz1GLCBjb2xuYW1lcyA9IGMoJ0Nhc2UgTnVtYmVyJywgJ1NleCcsICdSYWNlJywgJ01hcml0YWwgU3RhdHVzJywgJ1Jlc2lkZW50aWFsIFN0YXRlJywgJ0Nhc2UgQ3JlYXRpb24nLCAnU3RhdGUgb2YgRGVhdGgnLCAnRGF0ZSBvZiBEZWF0aCcsICdQcmltYXJ5IElDRCcsICdTZWNvbmRhcnkgSUNEJywgJ1RlcnRpYXJ5IElDRCcsICdRdWF0ZXJuYXJ5IElDRCcsICdRdWluYXJ5IElDRCcsICdTZW5hcnkgSUNEJywgJ1NlcHRlbmFyeSBJQ0QnLCAnT2N0b25hcnkgSUNEJyksCiAgICAgICAgICBvcHRpb25zID0gbGlzdCgKICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gIDIwLAogIGluaXRDb21wbGV0ZSA9IEpTKAogICAgImZ1bmN0aW9uKHNldHRpbmdzLCBqc29uKSB7IiwKICAgICIkKHRoaXMuYXBpKCkudGFibGUoKS5oZWFkZXIoKSkuY3NzKHsnYmFja2dyb3VuZC1jb2xvcic6ICdncmV5JywgJ2NvbG9yJzogJyNmZmYnfSk7IiwKICAgICJ9IikpKQoKYGBg