Introduction

This document outlines the analyses from Study 1 in insert article title here (insert authors, 2020). The purpose of this study was to investigate Ward et al.’s (2017) second experiment by completing a direct replication. Therefore, the present study investigated how the mere prescence of one’s smartphone effects cogntiion. This was pre-registered through OSF and can be found at the following link: https://osf.io/5fq4r.

The main goal of the current study was to see if Ward et al.’s findings replicated (experiment two). Therefore, as in Ward et al., participants were randomly assigned to one of six possible conditions. These conditions were based on two independent variables: smartphone location and smartphone power. For smartphone location, a participant’s smartphone was in one of three locations: (1) on the participant’s desk (“on desk”), (2) in their pocket/bag (“pocket/bag”), or (3) outside the testing room (“outside”). For smartphone power, a participant’s smartphone was either (1) powered ON or (2) powered OFF, in their respective location. For all conditions, participants were instructed to keep their smartphones on silent (i.e., no virbations if any notifications are received during the study). Also, as per Ward et al., participants in the “on desk” location conditions were instructed to keep their devices facing up.

Each participant completed two main tasks (counter-balanced):

1. An Automated Operation Span (OSpan) Task (Unsworth et al., 2005), which required participants to retain letter strings (i.e. ranging from three to seven letters in length) in memory while solving some simple math problems (e.g. “(7/7) + 6 = ?”). This task was a behavioural measure of the attentional control component of working memory.

  • Scoring:
    • Performance, measured with the OSpan absolute score, was shown by how many trials a participant correctly recalled all the letters in a given block (75 blocks in total). For example, a participant who recalled three letters (in a block with three letters), five letters (in a block with five letters), and two letters (in a block with six letters) would have an OSpan absolute score of eight for those blocks (i.e. 3 + 5 + 0 = 8). Therefore, OSpan absolute score showed performance where higher scores represented better performance.

2. The Cue-Dependent Go/No-Go Task (Bezdjia et al., 2009), which required participants to respond to “go” targets (i.e. green rectangle) while withholding any response to “no-go” targets (i.e. blue rectangle). This task included a cue component, where vertical targets (i.e., rectangles) were more likely to be “go” targets (i.e. 80% “go” and 20% “no-go”) and horizontal targets were more likely to be “no-go” targets (i.e. 80% “no-go” and 20% “go”). Participants were not explicitly made aware of the cue component. This task was a behavioural measure of sustained attention.

  • Scoring:
    • Performance was measured with mean omission errors and RT. It should be noted that mean errors can be divided into total error, commission error, and omission error. Commission errors occurred when a participant responded to a target stimulus. Omission errors occurred when a participant failed to respond to a non-target stimulus. Total errors were the sum of commission and omission errors. The present study focused on mean omission errors. Therefore, for each participant, higher mean omission errors represented lower performance. Additionally, higher mean RT also showed lower performance (i.e. indicative of greater interference).

Finally, after completing both tasks, all participants completed three survey measures:

1. The Demographic Questionnaire, which was created for the present study and consisted of four items: age (i.e. in years), gender (i.e. male, female, other, or prefer not to say), program (e.g. psychology, engineering), and year of study (e.g. first, fourth). The purpose of these items was to give a brief description of the sample.

2. The Smartphone Usage Questionnaire (SUQ), which was created for the present study and consisted of modified items from Ward et al.’s survey measures (i.e. found in the “BRAIN DRAIN” WEB APPENDIX”). Some items were forced-choice and some were on a 7-point likert scale ranging from 1 (“Never”) to 7 (“Always”). There were 10 items in total and there were five types of items, which measured: (1) smartphone use frequency (three items; e.g. “On average, how many text messages do you send per day?”); (2) smartphone use without external stimulation (two items; e.g. “If I am waiting to meet a friend, I pass the time by using my smartphone.”), or during other activities (two items; e.g. “I use my smartphone while driving.”); (3) smartphone subjective value (one item; e.g. “How much money would it take for you to give up your phone for a full day?”); (4) smartphone notification type (one item; e.g. “Do you receive notifications (a sound or vibration) on your phone? Please indicate all that apply.”); and (5) phantom vibrations (one item; e.g. “Have you ever thought you heard your phone ring or thought you felt it vibrate, only to find out you were wrong?”). The purpose of the SUQ was to measure participants’ typical smartphone use.

3. Smartphone Attachment and Dependency Inventory (SAD), which was from Ward et al.’s (2017) study. The SAD used 13-items (i.e. 7-point likert scale) that asked participants to rate (i.e., from 1 = Strongly Disagree to 7 = Strongly Agree) how much they agreed with statements regarding their emotional attachment and dependency on their smartphones. The purpose of the SAD was to measure each participant’s reliance on their smartphone.

  • Scoring:
    • Smartphone reliance was calculated with a sum total for all items with a range of 13 to 91. Higher scores indicated a higher level of reliance with three levels: low reliance (13-39), moderate reliance (40-65), and high reliance (66+).

A total of 453 undergraduate students participated in this study. Of the total sample size, 44 participants were excluded due to either testing error (11; e.g. incomplete task data), or experimenter or external confounds (33; e.g. interruption during testing, distracting noise during testing). Therefore, 409 participants were included in the analyses for the location (on desk = 134; pocket/bag = 141; outside = 134) and power (ON = 213; OFF = 196) condition.

Data Analysis Plan

The present study completed a pre-registered data anallysis (pre-registered direct replication on Open Science Framework; OSF). Below is a summary of the data analysis plan (view full version https://osf.io/d5eja & https://osf.io/ptc7k/).

Hypotheses

  1. The location effect hypothesis predicted that those who were closest in proximity to their smartphone (i.e. those with their smartphones on their desk) would show lower performance on the OSpan task.

  2. The power effect hypothesis predicted that smartphone power (i.e. either ON or OFF) would not affect performance on both cognitive tasks.

  3. The moderation effect hypothesis predicted that smartphone attachment and dependency (i.e. SAD score) would moderate the location effect: those who reported higher smartphone attachment and dependency would perform worse on the OSpan task.

Note: All hypotheses were based on the findings from Ward et al. (2017)

Inclusion / Exclusion Criteria

There were two exclusion critera in the present study:

1. OSpan Task

  • Only data from participants who scored 85% accuracy on the math component or above was used.
    • Criteria helped control for any participants who did not follow instructions and neglected the math component of the task. Note: This was the same criteria as in Ward et al. (2017)

2. Cue-Dependent Go/No-Go Task

  • Only data from those who scored higher than chance performance was used (e.g. reponded to at least 50% of “Go” trials and withheld response to at least 50% of “No-Go” trials).
    • Criteria helped control for any participants who did not complete the task as instructed (e.g. guessing). Note: There was no inclusion/exclusion criteria for thsi task in Ward et al. (2017)

Analysis

Testing the Location and Power Hypotheses:

1. OSpan Task

  • The OSpan absolute score was used to measure OSpan performance.
  • A 3(smartphone location: desk, pocket/bag, outside) x 2(smartphone power: ON, OFF) between-subjects ANOVA was conducted (DV = OSpan absolute score).
    • Post-hocs completed if there was a significant ANOVA (\(\alpha = 0.05\)) to determine which location(s) and/or power status were significantly different.

2. Cue-Dependent Go/No-Go Task

  • An error (i.e. omission errors) and accuracy (i.e. RT) analysis was completed using the average omission errors and RT for each participant.

    (a) Error Analysis
    • A 3(Smartphone location: desk, pocket/bag, outside) x 2(Smartphone power: ON, OFF) x 2(Cue type: Go, No-Go) mixed ANOVA was completed (DV = average omission error(s)).
      • The between-subjects factors:smartphone location and power
      • The within-subjects factor: pre-target cue type
      • Post-hocs completed if there was a significant ANOVA (\(\alpha = 0.05\)) to determine which location(s), power status, and/or cue type(s) were significantly different.
    (b) Accuracy Analysis
    • A 3(smartphone location: desk, pocket/bag, outside) x 2(smartphone power: ON, OFF) between-subjects ANOVA was conducted (DV = average RT).
      • The between-subjects factors:smartphone location and power
      • The within-subjects factor: pre-target cue type
      • Post-hocs completed if there was a significant ANOVA (\(\alpha = 0.05\)) to determine which location(s) and/or power status were significantly different.

Testing the Moderation Hypothesis:

3. SAD

(a) Factor Analysis

  • A principal components factor analysis with a Varimax rotation was completed for participant’s SAD score.
    • This was done to confirm the two main factors found by Ward et al. (2017): smartphone dependence and emotional attachment.

(b) Generalized Linear Model

  • A univariate generalized linear model was used to examine if smartphone reliance (i.e. SAD score) was a moderator of the relationship between the experimental manipulation and task performance.

Note: These analysis were completed regardless of the results for the location and power hypotheses.

Analysis Prep

Load Required Libraries

The following packages were used to complete the analyses, visualizations, etc. in this document.

# Code has been commented out to reduce computation time, uncomment any to run the code

# library(devtools)
# install_github("vqv/ggbiplot")
library(ggbiplot)
library(welchADF)
library(schoRsch)
library(plyr)
library(dplyr)
library(lattice)
library(car)
library(knitr)
library(ggplot2)
library(ggpubr)
library(kableExtra)
library(magrittr)
library(ez)
library(Hmisc)
library(rstatix)
library(purrr)
library(Formula)
library(gridExtra)
library(psych)
library(survival)
library(tidyverse)
library(DescTools)
library(GPArotation)
library(apaTables)

Additional Functions

Rounding p-values

This rounding function was adapted from Emily Nielsen’s Rpubs. The function (“p_round(x)”) was created to assess and print p-values. If \(p \ge .005\), the function will display “$p = $” and the value rounded to two decimal places. If $ .0005 p <.005\(, the function will display “\)p = $” and the value rounded to three decimal places. If \(p < .0005\), the function will display “\(p < .001\)”.


p_round <- function(x){
  if(x > .005)
    {x1 = (paste("= ", gsub("0\\.","\\.", round(x, digits = 2)), sep = ''))
  }  
  else if(x == .005){x1 = (paste("=", gsub("0\\.","\\.", 0.01)))
  }
  else if(x > .0005 & x < .005)
    {x1 = (paste("= ", gsub("0\\.","\\.", round(x, digits = 3)), sep = ''))
  }  
  else if(x == .0005){x1 = (paste("=", gsub("0\\.","\\.", 0.001)))
  }
  else{x1 = (paste("<", gsub("0\\.","\\.", 0.001)))
  } 
  (x1)
}

Raw Data

There are five raw data files that were imported for the present study (see the Import Raw Data section).

Task Data

  1. OSpan Raw Data
    • spreadsheet, collected manually from each participant
  2. Go/No-Go Raw Data
    • psychopy excel files
    • Note: raw data was extracted from folder into one file (see the Import Raw Data section)

Survey Measures

  1. Demographic & SUQ Raw Data
    • csv files exported from Qualtrics
  2. SAD Raw Data
    • csv files exported from Qualtrics
  3. Testing Tracking Sheet
    • csv files, collected during testing

Import Raw Data

1. OSpan Raw Data

The OSpan Raw Data was collected using the Inquisit 5 software (LINK), which used the same automated OSpan task as in Ward et al. (2017). The raw data from the OSpan was imported as a dataframe, “ospan_raw”, and included the following: (click to see description)

  • Participant number [ospan_participant]
  • OSpan ID [ospan_ID]
    • A 9-digit ID given by the Iquisit 5 software
  • OSpan Absolute Score [ospan_absolute_score]
    • Performance measured by how many trials a participant correctly recalled all the letters in a given block (75 blocks in total). For example, a participant who recalled three letters (in a block with three letters), five letters (in a block with five letters), and two letters (in a block with six letters) would have an OSpan absolute score of eight for those blocks (i.e. 3 + 5 + 0 = 8).
  • Total Letters Recalled [ospan_total_corr]
    • Performance measured by how many letters were recalled in total, regardless of whether all letters were correct within a given block.
  • Total Math Errors [ospan_math_err_tot]
    • the sum of all math errors (i.e. speed and accuracy)
  • Speed Errors [ospan_math_err_speed]
    • the sum of the speed related math errors
      • where a participant exceeded their time limit to respond to the math component of the task
  • Accuracy Errors [ospan_math_err_accuracy]
    • the sum of the accuracy related math errors
      • where a participant answered incorrectly on the math component of the task
  • Math Percentage [ospan_math_percent_corr]
    • the percent of all math trials that were answered correctly
      • Participants were asked to keep their math percentage at 85% or above to ensure participants did not ignore the math component of the task to improve on the letter recall component
  • Math Percentage Criteria [ospan_math_criteria_85]
    • whether a participant met the math criteria (i.e. 85% or above; yes or no)
      coding information (click to expand)
      • 1 = yes
      • 0 = no * including any participant that did not complete the OSpan task

This code imported the OSpan raw data. (click to expand)

ospan_raw = utils::read.csv("raw_ospan.csv", header = TRUE)

# reorganize rows so that the data is ordered by the participant number (e.g. 1, 2, 3, 4...)
ospan_raw = dplyr::arrange(ospan_raw, ospan_participant)

2. Go/No-Go Raw Data

The Go/No-Go Raw Data was collected using Psychopy (version: XXXX). Each participant’s data was stored in a separate folder (default from psychopy) as an excel file. The following code re-organized the raw data into a single wide format of the data as a dataframe, “gng_data_extracted”, and two data frames that separate the raw data by cue type (i.e.“vertical” or “horizontal”), “gng_data_extracted_v” and “gng_data_extracted_h”. (click to see descriptions)

For the gng_data_extracted data frame:

  • Participant number [gng_participant]
  • Age [age]
  • First Language [lang]
    • self-reported whether their fist language was English (i.e. yes or no)

      coding information (click to expand)

      code 1 2
      response Yes No
  • Total trials completed [gng_trial_tot]
  • GnG Score [gng_score]
    • the sum of the correct answers
  • Total Responses [gng_resp_tot]
    • the sum of the responses for all trials
  • Total No Responses [gng_no_resp_tot]
    • the sum of the trials without a response
  • Total Errors [gng_err_tot]
    • the sum of all errors for all trials
  • Commission Errors [gng_err_com]
    • the sum of all comission errors, defined as:
      • where a reponse was made during a “no-go” trial (i.e. committing an erorr)
  • Omission Errors [gng_err_omi]
    • the sum of all omission errors, defined as:
      • where a reponse was NOT made during a “go” trial (i.e. failing to respond)
  • Average Reaction Time (RT) [gng_rt_av]

For the gng_data_extracted_v data frame:

  • Participant number [gng_participant]
  • Age [age_long]
  • First Language [lang_long]
    • self-reported whether their fist language was English (i.e. yes or no)

      coding information (click to expand)

      code 1 2
      response Yes No
  • Total trials completed [trial_tot_v]
  • GnG Score [score_v]
    • the sum of the correct answers
  • Total Responses [resp_tot_v]
    • the sum of the responses for all trials
  • Total No Responses [no_resp_tot_v]
    • the sum of the trials without a response
  • Total Errors [err_tot_v]
    • the sum of all errors for all trials
  • Commission Errors [err_com_v]
    • the sum of all comission errors, defined as:
      • where a reponse was made during a “no-go” trial (i.e. committing an erorr)
  • Omission Errors [err_omi_v]
    • the sum of all omission errors, defined as:
      • where a reponse was NOT made during a “go” trial (i.e. failing to respond)
  • Average Reaction Time (RT) [rt_av_v]
  • Response Exclusion Criteria [exclude_v]
    • This depicts whether a participant should be excluded from analysis based on the response exclusion criteria
      • To be included, participants should score higher than chance performance (i.e. responded to at least 50% of “Go” trials and withheld response to at least 50% of “No-Go” trials)

        coding information (click to expand)

        code 1 2
        response Yes (participant excluded) No (participant included)

For the gng_data_extracted_h data frame:

  • Participant number [gng_participant]
  • Age [age_long]
  • First Language [lang_long]
    • self-reported whether their fist language was English (i.e. yes or no)

      coding information (click to expand)

      code 1 2
      response Yes No
  • Total trials completed [trial_tot_h]
  • GnG Score [score_h]
    • the sum of the correct answers
  • Total Responses [resp_tot_h]
    • the sum of the responses for all trials
  • Total No Responses [no_resp_tot_h]
    • the sum of the trials without a response
  • Total Errors [err_tot_h]
    • the sum of all errors for all trials
  • Commission Errors [err_com_h]
    • the sum of all comission errors, defined as:
      • where a reponse was made during a “no-go” trial (i.e. committing an erorr)
  • Omission Errors [err_omi_h]
    • the sum of all omission errors, defined as:
      • where a reponse was NOT made during a “go” trial (i.e. failing to respond)
  • Average Reaction Time (RT) [rt_av_h]
  • Response Exclusion Criteria [exclude_h]
    • This depicts whether a participant should be excluded from analysis based on the response exclusion criteria
      • To be included, participants should score higher than chance performance (i.e. responded to at least 50% of “Go” trials and withheld response to at least 50% of “No-Go” trials)

        coding information (click to expand)

        code 1 2
        response Yes (participant excluded) No (participant included)

This code imported the Go/No-Go raw data without separating the data by cue type. (click to expand)


#---WIDE DATA FRAME---"gng_data_extracted"  

#--This code completes the following tasks:
# (1) Create a function that extracts any required information from all psychopy folders at once
# (2) Create a list of all the directory paths to each individual file 
# (3) Apply the function to the files 
# (4) Create a data frame of the result of the function on the files

#--The FINAL OUTPUT = a wide format of the raw GnG data including:
# participant, age, lang, trial_tot, score, resp_tot, no_resp_tot, err_tot, err_com, err_omi, rt_av

#--NOTES:

# Step (3) will give warnings if there is any missing data that the function was not specified how to handle
# example: Any participant that did not respond to an item or during all trials will have an "NA" response in the data
# example: Any participant who reported their age or first language in an irregular manner (e.g. "ninteen" rather than "19")
# Either example will result in a warning, since the function would have to force that output to be "NA" as well

# Individual participant files do not stay in chronological order 
# (they are re-ordered so that all ps that start with the digit "1" go first, then the "2"...)

#--(1) Create a function that extracts any required information from all psychopy folders at once

# create a function that extracts all the required information from each excel file
# details for what is extracted in this function is found within it, 
# to use it to extract any other &/ additional information, edit within the function itself
extract_gng = function(data) {
  temp_data = readxl::read_excel(data)
  
  # Participant number (participant)
  participant = as.numeric(temp_data[which(temp_data == "participant"),2])
  
  # Age (age)
  age = as.integer(temp_data[which(temp_data == "Age"),2])
  
  # Gender (gender)
  # will be populated from survey measures
  
  # First Language (lang)
  # this finds if the language reported was English: if yes = 1; no = 0
  lang = ifelse(stringr::str_detect(as.character(temp_data[which(temp_data == "First Language"),2]), stringr::fixed("english", ignore_case=TRUE)), 1, 0)
  
  # Location Condition (location; either: (1) desk, (2) pocket/bag, or (3) outside)
  # will be populated from survey measures
  
  # Power Condition (power; either: (1) ON,or (2) OFF)
  # will be populated from survey measures
  
  # Total trials completed (trial_tot)
  # count the "order" column, which shows the order in which the trials were showed (random for each participant)
  # note: must ignore the NA values
  trial_tot = sum((is.na(temp_data$cue) == "FALSE" & is.na(temp_data$order) == "FALSE"), na.rm = TRUE) #alternative: sum(complete.cases(temp_data$order))
  
  # GnG Score (score)
  # sum of the correct answers from the "key_resp_slash.corr_raw" column
  # note: must ignore the NA values
  score = sum(temp_data$key_resp_slash.corr_raw, na.rm = TRUE)
  
  # Total Responses (resp_tot)
  # sum of the responses from the "key_resp_slash.keys_raw" column
  # note: must ignore the NA values
  resp_tot = sum((is.na(temp_data$cue) == "FALSE" & is.na(temp_data$key_resp_slash.keys_raw) == "FALSE"), na.rm = TRUE) #alternative: sum(complete.cases(temp_data$key_resp_slash.keys_raw))
  
  # Total No Responses (no_resp_tot)
  # subtract total responses made from completed trials 
  # note: must ignore the NA values
  no_resp_tot = (trial_tot - resp_tot)
  
  # Total Errors (err_tot)
  # sum of the incorrect answers from the "key_resp_slash.corr_raw"
  err_tot = sum((temp_data$key_resp_slash.corr_raw == "0") == "TRUE", na.rm = TRUE) # alternative: sum(!temp_data$key_resp_slash.corr_raw, na.rm = TRUE)
  
  # Commission Errors (err_com)
  # sum any cases where a reponse was made & the answer was incorrect (i.e. committing an erorr)
  err_com = sum((temp_data$key_resp_slash.corr_raw == "0" & !is.na(temp_data$key_resp_slash.keys_raw)) == "TRUE", na.rm = TRUE)
  
  # Omission Errors (err_omi)
  # sum any cases where a reponse was NOT made & the answer was incorrect (i.e. failing to respond)
  err_omi = sum((temp_data$key_resp_slash.corr_raw == "0" & is.na(temp_data$key_resp_slash.keys_raw)) == "TRUE", na.rm = TRUE)
  
  # Average Reaction Time (RT) (rt_av)
  # calculate the average / mean RT for all responses
  # Note: the "no-go" trials required no response for a correct trial (for 1,000ms)
  rt_av = mean(temp_data$key_resp_slash.rt_raw, na.rm = TRUE)
  
  temp_dataframe = as.data.frame(c(participant, age, lang, trial_tot, 
                                   score, resp_tot, no_resp_tot, 
                                   err_tot, err_com, err_omi, rt_av))
}

#--(2) Create a list of all the directory paths to each individual file 

# Find the location of each excel (.xlsx) files
# the folders containing the files should be in 1 folder (e.g. "" in this case)
# this returns a list of each file's location
# Note: the pattern is set to ignore any hidden / temporary files by adding the start of each file name (e.g. "^NoGo")
files_psychopy = dir("/Users/anaruizpardo/RStudio/Smartphone_study/Study 1- Smartphone Replication/Dissertation (04:20:20)/Raw Data Organizing/gng_raw_folders", 
                     recursive = TRUE, full.names=TRUE, pattern="^NoGo(.*)xlsx$")

#--(3) Apply the function to the files 

# Apply the function to all excel files
result = sapply(files_psychopy, extract_gng)

#--(4) Create a data frame of the result of the function on the files

# take the lists of the extracted data and turn it into a data frame
gng_data_extracted = data.frame(Reduce(rbind, result)) # alternative method: x = data.frame(t(sapply(result,c)))
# rename the columns
colnames(gng_data_extracted) = c("gng_participant", "age", "lang", "gng_trial_tot", "gng_score", 
                                 "gng_resp_tot", "gng_no_resp_tot", "gng_err_tot", "gng_err_com", 
                                 "gng_err_omi", "gng_rt_av") 
# remove row names to avoid confusion
rownames(gng_data_extracted) = NULL

# reorganize rows so that the data is ordered by the participant number (e.g. 1, 2, 3, 4...)
gng_data_extracted = dplyr::arrange(gng_data_extracted, gng_participant)

This code imported the Go/No-Go raw data and separated the data by cue type (i.e. “vertical” or “horizontal”). (click to expand)


#--- for the LONG DATA FRAME - CUE TYPE (vertical vs. horizontal) --- "gng_data_extracted_v" & "gng_data_extracted_h" 
  
#-- This code differs from the above code in that it organizes the gng data based the CUE type (i.e. either a "vertical" (v) or "horizontal" (h)).
  # This means that the data is in a long format to test the within-subjects factor of cue type.

#--This code completes the following tasks:
# (1) Create a function that extracts any required information from all psychopy folders at once
# (2) Create a list of all the directory paths to each individual file 
# (3) Apply the function to the files 
# (4) Create a data frame of the result of the function on the files
# (5) Re-structure the data into 1 data frame in a long format for a repeated measures analysis

#--The FINAL OUTPUT = a wide format of the raw GnG data including:
# participant, age, lang, trial_tot, score, resp_tot, no_resp_tot, err_tot, err_com, err_omi, rt_av

#--NOTES:

# Step (3) will give warnings if there is any missing data that the function was not specified how to handle
# example: Any participant that did not respond to an item or during all trials will have an "NA" response in the data
# example: Any participant who reported their age or first language in an irregular manner (e.g. "ninteen" rather than "19")
# Either example will result in a warning, since the function would have to force that output to be "NA" as well

# Individual participant files do not stay in chronological order 
# (they are re-ordered so that all ps that start with the digit "1" go first, then the "2"...)

#--(1) Create a function that extracts any required information from all psychopy folders at once...
# for the "vertical" (v) (extract_gng_v) and "horizontal" (h) (extract_gng_h) trials

# create a function that extracts all the required information from each excel file
# details for what is extracted in this function is found within it, 
# to use it to extract any other &/ additional information, edit within the function itself
# NOTE: this function extracts 2 versions of each value: one for the "vertical" (v) trials, and one for the "horizontal" (h) trials

extract_gng_v = function(data) {
  temp_data = readxl::read_excel(data)
  
  # Participant number (participant_long)
  participant_long = as.numeric(temp_data[which(temp_data == "participant"),2])
  # only one is extracted since this will not change b/w CUE type
  
  # Age (age_long)
  age_long = as.integer(temp_data[which(temp_data == "Age"),2])
  # only one is extracted since this will not change b/w CUE type
  
  # Gender (gender)
  # will be populated from survey measures
  # only one is extracted since this will not change b/w CUE type
  
  # First Language (lang_long)
  # this finds if the language reported was English: if yes = 1; no = 0
  lang_long = ifelse(stringr::str_detect(as.character(temp_data[which(temp_data == "First Language"),2]), stringr::fixed("english", ignore_case=TRUE)), 1, 0)
  # only one is extracted since this will not change b/w CUE type
  
  # Location Condition (location; either: (1) desk, (2) pocket/bag, or (3) outside)
  # will be populated from survey measures
  # only one is extracted since this will not change b/w CUE type
  
  # Power Condition (power; either: (1) ON,or (2) OFF)
  # will be populated from survey measures
  # only one is extracted since this will not change b/w CUE type
  
  # Total trials completed for the "vertical" (v) (trial_tot_v)
  # count the "order" column, which shows the order in which the trials were showed (random for each participant)
  # note: must ignore the NA values
  trial_tot_v = sum((temp_data$cue == "v_b.png" & is.na(temp_data$order) == "FALSE"), na.rm = TRUE)
  
  # GnG Score for the "vertical" (v) (score_v)  
  # sum of the correct answers from the "key_resp_slash.corr_raw" column
  # note: must ignore the NA values
  score_v = sum(temp_data$cue == "v_b.png" & temp_data$key_resp_slash.corr_raw, na.rm = TRUE)  
  
  # Total Responses for the "vertical" (v) (resp_tot_v)
  # sum of the responses from the "key_resp_slash.keys_raw" column
  # note: must ignore the NA values
  resp_tot_v = sum((temp_data$cue == "v_b.png" & temp_data$key_resp_slash.keys_raw == "'slash'"), na.rm = TRUE)  
  
  # Total No Responses for the "vertical" (v) (no_resp_tot_v)  
  # subtract total responses made from completed trials 
  # note: must ignore the NA values
  no_resp_tot_v = (trial_tot_v - resp_tot_v)  
  
  # Total Errors for the "vertical" (v) (err_tot_v) 
  # sum of the incorrect answers from the "key_resp_slash.corr_raw"
  err_tot_v = sum((temp_data$cue == "v_b.png" & temp_data$key_resp_slash.corr_raw == "0"), na.rm = TRUE)  
  
  # Commission Errors for the "vertical" (v) (err_com_v) 
  # sum any cases where a reponse was made & the answer was incorrect (i.e. committing an error)
  err_com_v = sum(temp_data$cue == "v_b.png" & temp_data$key_resp_slash.corr_raw == "0" & !is.na(temp_data$key_resp_slash.keys_raw), na.rm = TRUE)  
  
  # Omission Errors for the "vertical" (v) (err_omi_v)  
  # sum any cases where a reponse was NOT made & the answer was incorrect (i.e. failing to respond)
  err_omi_v = sum(temp_data$cue == "v_b.png" & temp_data$key_resp_slash.corr_raw == "0" & is.na(temp_data$key_resp_slash.keys_raw), na.rm = TRUE)  

  # Average Reaction Time (RT) for the "vertical" (v) (rt_av_v)  
  # calculate the average / mean RT for all responses
  # Note: the "no-go" trials required no response for a correct trial (for 1,000ms)
  rt_av_v = mean(temp_data$key_resp_slash.rt_raw[which(temp_data$cue == "v_b.png")], na.rm = TRUE)  
  
  # Exclusion Criteria for the "vertical" (v) (exclude_v)
  # calculate whether participants scored higher than chance performance 
  # (i.e. responded to at least 50% of “Go” trials and withheld response to at least 50% of “No-Go” trials)
  # code: exclude = 1; include (do not exclude) = 2
  # NOTE: this calculation is meant to exclude the participant as a whole, therefore, 
  # it does not calculate it for the cue type specifically
    # first, get the total trials and response totals for the "go" and "no-go" trials
      # "go"
      trial_tot_go = sum((temp_data$corrAns == "slash" & is.na(temp_data$order) == "FALSE"), na.rm = TRUE)
      resp_tot_go = sum((temp_data$corrAns == "slash" & temp_data$key_resp_slash.keys_raw == "'slash'"), na.rm = TRUE)
      # "no-go"
      trial_tot_nogo = sum((temp_data$corrAns == "none" & is.na(temp_data$order) == "FALSE"), na.rm = TRUE)
      resp_tot_nogo = sum((temp_data$corrAns == "none" & temp_data$key_resp_slash.keys_raw == "'slash'"), na.rm = TRUE)
    # next, find the minimum response needed based on the 50% criteria
    min_resp = trial_tot_go * .50
    # find if the participant meets exclusion criteria for the "go" and "no-go" trials
    meets_min_go = resp_tot_go > (min_resp)
    meets_min_nogo = resp_tot_nogo < (min_resp)
    # find if the participant meets exclusion criteria (exclude = 1; include = 2)
    exclude_v = ifelse((meets_min_go == "TRUE" & meets_min_nogo == "TRUE") == "FALSE", 1, 2)
  
  temp_dataframe_v = as.data.frame(c(participant_long, age_long, lang_long, trial_tot_v, score_v, resp_tot_v, 
                                        no_resp_tot_v, err_tot_v, err_com_v, err_omi_v, rt_av_v, exclude_v))
}  

extract_gng_h = function(data) {
  temp_data = readxl::read_excel(data)
  
  # Participant number (participant_long)
  participant_long = as.numeric(temp_data[which(temp_data == "participant"),2])
  # only one is extracted since this will not change b/w CUE type
  
  # Age (age_long)
  age_long = as.integer(temp_data[which(temp_data == "Age"),2])
  # only one is extracted since this will not change b/w CUE type
  
  # Gender (gender)
  # will be populated from survey measures
  # only one is extracted since this will not change b/w CUE type
  
  # First Language (lang_long)
  # this finds if the language reported was English: if yes = 1; no = 0
  lang_long = ifelse(stringr::str_detect(as.character(temp_data[which(temp_data == "First Language"),2]), stringr::fixed("english", ignore_case=TRUE)), 1, 0)
  # only one is extracted since this will not change b/w CUE type
  
  # Location Condition (location; either: (1) desk, (2) pocket/bag, or (3) outside)
  # will be populated from survey measures
  # only one is extracted since this will not change b/w CUE type
  
  # Power Condition (power; either: (1) ON,or (2) OFF)
  # will be populated from survey measures
  # only one is extracted since this will not change b/w CUE type
  
  # Total trials completed for the "horizontal" (h) (trial_tot_h)
  # count the "order" column, which shows the order in which the trials were showed (random for each participant)
  # note: must ignore the NA values
  trial_tot_h = sum((temp_data$cue == "h_b.png" & is.na(temp_data$order) == "FALSE"), na.rm = TRUE)
  
  # GnG Score for the "horizontal" (h) (score_h)  
  # sum of the correct answers from the "key_resp_slash.corr_raw" column
  # note: must ignore the NA values
  score_h = sum(temp_data$cue == "h_b.png" & temp_data$key_resp_slash.corr_raw, na.rm = TRUE)  
  
  # Total Responses for the "horizontal" (h) (resp_tot_h)
  # sum of the responses from the "key_resp_slash.keys_raw" column
  # note: must ignore the NA values
  resp_tot_h = sum((temp_data$cue == "h_b.png" & temp_data$key_resp_slash.keys_raw == "'slash'"), na.rm = TRUE)  
  
  # Total No Responses for the "horizontal" (h) (no_resp_tot_h)  
  # subtract total responses made from completed trials 
  # note: must ignore the NA values
  no_resp_tot_h = (trial_tot_h - resp_tot_h)  
  
  # Total Errors for the "horizontal" (h) (err_tot_h) 
  # sum of the incorrect answers from the "key_resp_slash.corr_raw"
  err_tot_h = sum((temp_data$cue == "h_b.png" & temp_data$key_resp_slash.corr_raw == "0"), na.rm = TRUE)  
  
  # Commission Errors for the "horizontal" (h) (err_com_h) 
  # sum any cases where a reponse was made & the answer was incorrect (i.e. committing an error)
  err_com_h = sum(temp_data$cue == "h_b.png" & temp_data$key_resp_slash.corr_raw == "0" & !is.na(temp_data$key_resp_slash.keys_raw), na.rm = TRUE)  
  
  # Omission Errors for the "horizontal" (h) (err_omi_h)  
  # sum any cases where a reponse was NOT made & the answer was incorrect (i.e. failing to respond)
  err_omi_h = sum(temp_data$cue == "h_b.png" & temp_data$key_resp_slash.corr_raw == "0" & is.na(temp_data$key_resp_slash.keys_raw), na.rm = TRUE)  
  
  # Average Reaction Time (RT) for the "horizontal" (h) (rt_av_h)  
  # calculate the average / mean RT for all responses
  # Note: the "no-go" trials required no response for a correct trial (for 1,000ms)
  rt_av_h = mean(temp_data$key_resp_slash.rt_raw[which(temp_data$cue == "h_b.png")], na.rm = TRUE)  
  
  # Exclusion Criteria for the "horizontal" (h) (exclude_h)
  # calculate whether participants scored higher than chance performance 
  # (i.e. responded to at least 50% of “Go” trials and withheld response to at least 50% of “No-Go” trials)
  # code: exclude = 1; include (do not exclude) = 2
  # NOTE: this calculation is meant to exclude the participant as a whole, therefore, 
  # it does not calculate it for the cue type specifically
  # first, get the total trials and response totals for the "go" and "no-go" trials
  # "go"
  trial_tot_go = sum((temp_data$corrAns == "slash" & is.na(temp_data$order) == "FALSE"), na.rm = TRUE)
  resp_tot_go = sum((temp_data$corrAns == "slash" & temp_data$key_resp_slash.keys_raw == "'slash'"), na.rm = TRUE)
  # "no-go"
  trial_tot_nogo = sum((temp_data$corrAns == "none" & is.na(temp_data$order) == "FALSE"), na.rm = TRUE)
  resp_tot_nogo = sum((temp_data$corrAns == "none" & temp_data$key_resp_slash.keys_raw == "'slash'"), na.rm = TRUE)
  # next, find the minimum response needed based on the 50% criteria
  min_resp = trial_tot_go * .50
  # find if the participant meets exclusion criteria for the "go" and "no-go" trials
  meets_min_go = resp_tot_go > (min_resp)
  meets_min_nogo = resp_tot_nogo < (min_resp)
  # find if the participant meets exclusion criteria (exclude = 1; include = 2)
  exclude_h = ifelse((meets_min_go == "TRUE" & meets_min_nogo == "TRUE") == "FALSE", 1, 2)
  
  temp_dataframe_h = as.data.frame(c(participant_long, age_long, lang_long, trial_tot_h, score_h, resp_tot_h, 
                                     no_resp_tot_h, err_tot_h, err_com_h, err_omi_h, rt_av_h, exclude_h))
}  

#--(2) Create a list of all the directory paths to each individual file 

# Find the location of each excel (.xlsx) files
# the folders containing the files should be in 1 folder (e.g. "" in this case)
# this returns a list of each file's location
# Note: the pattern is set to ignore any hidden / temporary files by adding the start of each file name (e.g. "^NoGo")
# THIS IS THE SAME AS IN THE ABOVE CODE, SO IT IS COMMENTED OUT TO AVOID EXTRA COMPUTING POWER

# files_psychopy = dir("/Users/anaruizpardo/RStudio/Smartphone_study/Study 1- Smartphone Replication/Dissertation (04:20:20)/Raw Data Organizing/gng_raw_folders", 
#                     recursive = TRUE, full.names=TRUE, pattern="^NoGo(.*)xlsx$")

#--(3) Apply the function to the files 

# Apply the function to all excel files for the "vertical" (v) and "horizontal" (h) trials  
result_v = sapply(files_psychopy, extract_gng_v)
result_h = sapply(files_psychopy, extract_gng_h)

#--(4) Create a data frame of the result of the function on the files...
# for the "vertical" (gng_data_extracted_v) and "horizontal" (gng_data_extracted_h) trials  

# take the lists of the extracted data and turn it into a data frame for the "vertical" (h) trials
gng_data_extracted_v = data.frame(Reduce(rbind, result_v)) 
# rename the columns
colnames(gng_data_extracted_v) = c("participant_long", "age_long", "lang_long", "trial_tot_v", "score_v", 
                                         "resp_tot_v", "no_resp_tot_v", "err_tot_v", "err_com_v", 
                                         "err_omi_v", "rt_av_v", "exclude_v")

# take the lists of the extracted data and turn it into a data frame for the "horizontal" (h) trials
gng_data_extracted_h = data.frame(Reduce(rbind, result_h)) 
# rename the columns
colnames(gng_data_extracted_h) = c("participant_long", "age_long", "lang_long", "trial_tot_h", "score_h", 
                                           "resp_tot_h", "no_resp_tot_h", "err_tot_h", "err_com_h", 
                                           "err_omi_h", "rt_av_h", "exclude_h")
# remove row names to avoid confusion
rownames(gng_data_extracted_v) = NULL
rownames(gng_data_extracted_h) = NULL

# reorganize rows so that the data is ordered by the participant number (e.g. 1, 2, 3, 4...)
gng_data_extracted_v = dplyr::arrange(gng_data_extracted_v, participant_long)
gng_data_extracted_h = dplyr::arrange(gng_data_extracted_h, participant_long)

3. & 4. Demographic, SUQ, and SAD Raw Data

The Demographic & SUQ Raw Data and SAD Raw Data was collected using Qualtrics the Inquisit 5 software (LINK), which was the same as Ward et al. (2017). The raw data from the OSpan was imported as a dataframe, “ospan_raw”, and included the following: (click to see description)

General, Manipulation, and Demographic Information

General Information: (click to expand)

  • Start Date [date_start]
    • The date and time when a participant began their survey on Qualtrics (Y/M/D H:M)
  • End Date [date_end]
    • The date and time when a participant finished their survey on Qualtrics (Y/M/D H:M)
  • Duration (in seconds) [duration(s)]
    • The duration of the survey for the participant in seconds
  • Recorded Date [date_rec]
    • The date and time when a participant’s data was recorded on Qualtrics (Y/M/D H:M)
  • Participant number [sur_participant]

Manipulation Condition: (click to expand)

  • Smartphone Location [sur_location]
    • The smartphone location assigned to the participant (i.e. desk, pocket/bag, or outside)

      coding information (click to expand)

      code 1 2 3
      response Desk Pocket/Bag Outside
  • Smartphone Power [sur_power]
    • The smartphone power assigned to the participant (i.e. ON or OFF)

      coding information (click to expand)

      code 1 2
      response On Off
  • Smartphone Condition [sur_condition]
    • The smartphone condition (i.e. combination of location & power) assigned to the participant

      coding information (click to expand)

      code 1 2 3 4 5 6
      response ON & Desk ON & Pocket/Bag ON & Outside OFF & Desk OFF & Pocket/Bag OFF & Outside

Demographics: (click to expand)

  • Gender [gender]
    • Participant’s self-reported gender (i.e., male, female, other, or prefer not to say)

      coding information (click to expand)

      code 1 2 3 4
      response Male Female Other Prefer not to say
  • Year [year]
    • Participant’s self-reported year of study in their respective program (e.g. 1, 2, 3, 4)
  • Program [program]
    • Participant’s self-reported program of study (e.g., biology, BMOS, psychology)

      coding information (click to expand)

      1 = actuarial 11 = economics 21 = management 31 = psychology
      2 = anthropology science 22 = mathematics 32 = SASAH
      3 = arts 13 = english 23 = medical science 33 = science
      4 = arts & humanities 14 = film 24 = MIT 34 = social science
      5 = biology 15 = FIMS 25 = MOS 35 = sociology
      6 = BMOS 16 = geography 26 = music 36 = software
      7 = chemistry 17 = health science 27 = nutrition & dietetics 37 = visual arts
      8 = computer science 18 = integrated science 28 = philosophy
      9 = consumer behaviour 19 = kinesiology 29 = physics
      10 = criminology 20 = linguistics 30 = political science
The Smartphone Use Questionnaire (SUQ)

The purpose of the SUQ was to measure participants’ typical smartphone use. The SUQ was created for the present study and consisted of modified items from Ward and colleagues’ (2017) survey measures. (i.e. found in the “BRAIN DRAIN” WEB APPENDIX”). Some items were forced-choice and some were on a 7-point likert scale ranging from 1 (“Never”) to 7 (“Always”). There were 10 items in total and there were five types of items, which measured:

1. Smartphone Use Frequency: (SUQ_use_1 - SUQ_use_3)

Each of the following items used the following coding:

CODE 1 2 3 4
response 0-5 6-10 11-15 > 15
  • Text Messages (per day) [SUQ_use_1]
    • Answer to the following question: “On average, how many text messages do you send per day?
  • Social Media Messages (per day) [SUQ_use_2]
    • Answer to the following question: “On average, how many social media based messages do you send per day from your smartphone? (iMessage, Facebook Messenger, WhatsApp, WeChat, direct messages within social media platforms, etc.)
  • Social Media Posts (per day) [SUQ_use_3]
    • Answer to the following question: “On average, how many social media posts (e.g. written post, picture, article, etc.) do you send per day from your smartphone? (Facebook, Twitter, Instagram, etc.)

2. Smartphone Use With External Stimulation or During Other Activities: (SUQ_use_4 - SUQ_use_7)

Each of the following items used the following coding:

code 1 2 3 4 5 6 7
response Never About half
the time
Always
no text specified
  • Text Messages (per day) [SUQ_use_4]
    • Answer to the following question: “I look at my smartphone before I roll out of bed in the morning.
  • Social Media Messages (per day) [SUQ_use_5]
    • Answer to the following question: “If I am waiting to meet a friend, I pass the time by using my smartphone.
  • Social Media Posts (per day) [SUQ_use_6]
    • Answer to the following question: “I use my smartphone while driving.
  • Social Media Posts (per day) [SUQ_use_7]
    • Answer to the following question: “If my smartphone rings or vibrates in the middle of personal business, I look at it.

3. Smartphone Subjective Value: (SUQ_exp_1)

  • Subjective Value [SUQ_use_1]
    • Answer to the following question: “How much money would it take for you to give up your phone for a full day?

      coding information (click to expand)

      code 1 2 3 4
      response $0-$20 $21-$40 $41-$60 > $60

4. Smartphone Notification Type: (SUQ_exp_2 & SUQ_exp_3)

  • Notification Type [SUQ_use_2]
    • Answer to the following question: “Do you receive notifications (a sound or vibration) on your phone? Please indicate all that apply.

      coding information (click to expand)

      code 1 2 3 4 5 6 7
      response Email Facebook Twitter Instagram LinkedIn Snapchat Other (specify)
  • Specify Notification Type [SUQ_exp_3]
    • Answer to the following question: “Please Specify: Where you receive notifications (a sound or vibration) on your phone?

5. Phantom Vibrations: (SUQ_exp_4)

  • Phantom Vibrations [SUQ_use_4]
    • Answer to the following question: “Have you ever thought you heard your phone ring or thought you felt it vibrate, only to find out you were wrong?

      coding information (click to expand)

      code 1 2
      response Yes No
The Smartphone Attachment and Dependency Inventory (SAD; Ward et al., 2017)

The SAD asked participants to respond to 13 items (SAD_1-SAD_13) using a 7-point likert scale. (click to expand)

code 1 2 3 4 5 6 7
response Strongly
Disagree
Disagree Somewhat
Disagree
Neutral Somewhat
Agree
Agree Strongly
Agree
  • SAD_1: I would have trouble getting through a normal day without my smartphone.
  • SAD_2: It would be painful for me to give up my smartphone for a day.
  • SAD_3: I feel like I could not live without my smartphone.
  • SAD_4: If I forgot to bring my smartphone with me, I would feel anxious.
  • SAD_5: It drives me crazy when my smartphone runs out of battery.
  • SAD_6: I am upset and annoyed when I find I do not have reception on my smartphone.
  • SAD_7: I feel impatient when the Internet connection speed on my smartphone is slow.
  • SAD_8: I feel lonely when my smartphone does not ring or vibrate for several hours.
  • SAD_9: Using my smartphone relieves me of my stress.
  • SAD_20: I feel excited when I have a new message or notification.
  • SAD_11: Using my smartphone makes me feel happy.
  • SAD_12: I find it tough to focus whenever my smartphone is nearby.
  • SAD_13: I become less attentive to my surroundings when I’m using my smartphone.

This code imported the Demographic, SUQ, and SAD raw data. (click to expand)

survey_raw = utils::read.csv("raw_survey.csv", header = TRUE)

# reorganize rows so that the data is ordered by the participant number (e.g. 1, 2, 3, 4...)
survey_raw = dplyr::arrange(survey_raw, sur_participant)

5. Testing Tracking Sheet Raw Data

The Testing Tracking Sheet Raw Data was collected during testing by the experimenter to store relevant information on participant’s (1) General Information (e.g. testing start date), (2) Manipulation Condition (e.g. assigned location and power manipulation), and (3) Data Cleaning (e.g. exclusion critera from testing error or other non-task-specific criteria). The raw data from the tracking sheet was imported as a dataframe, “track_raw”, and included the following: (click to see description)

1. General Information:

  • Testing Date [track_date]
    • The date a participant completed the study (Y/M/D)
  • Testing Time [date_end]
    • The time a participant was scheduled to complete the study (24hr-time). Note: Many participants were tested at the same time, but in separate cubicle-type desks to avoid any group-testing dynamic
  • Participant number [track_participant]

2. Manupulation Condition:

  • Smartphone Location [track_location]
    • The smartphone location assigned to the participant (i.e. desk, pocket/bag, or outside)

      coding information (click to expand)

      code 1 2 3
      response Desk Pocket/Bag Outside
  • Smartphone Power [track_power]
    • The smartphone power assigned to the participant (i.e. ON or OFF)

      coding information (click to expand)

      code 1 2
      response On Off
  • Smartphone Condition [track_condition]
    • The smartphone condition (i.e. combination of location & power) assigned to the participant

      coding information (click to expand)

      code 1 2 3 4 5 6
      response ON & Desk ON & Pocket/Bag ON & Outside OFF & Desk OFF & Pocket/Bag OFF & Outside
  • Counter Balanced Order [balance]
    • This depicts which of the main tasks (i.e. either the OSpan task or the Cue-Dependent Go/No-Go Task) was completed first

      coding information (click to expand)

      code 1 2
      response OSpan Task completed first Cue-Dependent Go/No-Go Task completed first

3. Data Cleaning:

  • Exclude from Analysis [exclude]
    • This depicts whether a participant should be excluded from analysis due to testing error or other non-task-specific criteria (i.e. for reasons other than the task exclusion criteria in the data analysis plan).

      coding information (click to expand)

      code 1 2
      response Yes (participant excluded) No (participant included)
  • Reason for Exclusion from Analysis [reason]
    • This depicts the reason (summarized into 5 categories) a participant should be excluded from analysis due to testing error or other non-task-specific criteria (i.e. for reasons other than the task exclusion criteria in the data analysis plan). Note: this includes a category for “no exclusion issues”, where a participant was not excluded

      coding information (click to expand)

      code 1 2 3 4 5
      response no exclusion issues external distractor (noise) gng incomplete gng missing ospan missing
  • Possible Outlier [pos_out]
    • This depicts whether a participant is a possible outlier for exploratory analyses. Note: this was not applied to any analysis unless explicitly stated

      coding information (click to expand)

      code 1 2
      response Yes (does qualify as a possible outlier) No (does not qualify as a possible outlier)
  • Experimenter [experimenter]
    • This depicts which experimenter (3 total) collected the data for a participant. Note: this was collected for exploratory analyses and was not used unless explicitly stated

      coding information (click to expand)

      code 1 2 3
      response ARP SW LM

This code imported the study tracking sheet raw data. (click to expand)

track_raw = utils::read.csv("raw_tracking.csv", header = TRUE)

# reorganize rows so that the data is ordered by the participant number (e.g. 1, 2, 3, 4...)
track_raw = dplyr::arrange(track_raw, track_participant)

Construct Working Dataframes

In order to complete the present study’s analyses, eight data frames were created.

1. All Data

All the data from the present study in one data frame: “all_data” (click to see more)

  • This data included the following:
    • participant, track_date, track_time, location, power, condition, balance, exclude, reason, pos_out, experimenter, ospan_ID, ospan_absolute_score, ospan_total_corr, ospan_math_err_tot, ospan_math_err_speed, ospan_math_err_accuracy, ospan_math_percent_corr, ospan_math_criteria_85, age, lang, gng_trial_tot, gng_score, gng_resp_tot, gng_no_resp_tot, gng_err_tot, gng_err_com, gng_err_omi, gng_rt_av, date_start, date_end, duration.s., date_rec, gender, program, year, SUQ_use_1, SUQ_use_2, SUQ_use_3, SUQ_use_4, SUQ_use_5, SUQ_use_6, SUQ_use_7, SUQ_exp_1, SUQ_exp_2, SUQ_exp_3, SUQ_exp_4, SAD_1, SAD_2, SAD_3, SAD_4, SAD_5, SAD_6, SAD_7, SAD_8, SAD_9, SAD_10, SAD_11, SAD_12, SAD_13

This code organized the raw data into one data frame. (click to expand)


# Find the final participant list for the analyses  
  # get a list of participants that (1) completed the gng task and (2) are not excluded (i.e., inclusion list) based on the "exclude" column in the tracking sheet  
  # (1) First get the gng participant list  
  gng_par_list = gng_data_extracted$gng_participant  
  # (2) Next, get the inclusion list  
  include_par_list = data.frame(track_raw$track_participant[which(track_raw$exclude %in% 2)])  
    colnames(include_par_list) = c("par_list")
  # Get a list of all the participants who completed the study (from the testing tracking sheet)
  all_participants = as.data.frame(track_raw$track_participant)
    colnames(all_participants) = c("all_participants")
  
# find the participants to remove from the data
  # Filter each data list from the list of all participants  
  gng_remove = data.frame("all_participants" = filter(all_participants, !(all_participants %in% gng_par_list)))
  track_remove = data.frame("all_participants" = filter(all_participants, !(all_participants %in% include_par_list$par_list)))
  reason_remove = c(rep("gng", length(gng_remove$all_participants)), rep("track", length(track_remove$all_participants)))
  
  # Make a list of all the removed participants -- "all_remove"
  all_remove_notclean = data.frame(rbind(gng_remove, track_remove), reason_remove)
    # remove any duplicates from the list
    all_remove_nodup = all_remove_notclean[!duplicated(all_remove_notclean$all_participants), ]
    # reorganize rows so that the data is ordered by the participant number (e.g. 1, 2, 3, 4...)  
    all_remove = dplyr::arrange(all_remove_nodup, all_participants)  
    
# Filter raw data using the final participant list for: ospan_raw, gng_raw, survey_raw, and track_raw
  # This will now the the working data for the study (i.e. the "final" data)  
    # OSpan Data  
    ospan_final = dplyr::filter(ospan_raw, !ospan_participant %in% all_remove$all_participants)
    # Gng Data  
    gng_final = dplyr::filter(gng_data_extracted, !gng_participant %in% all_remove$all_participants)
    # Survey Data  
    survey_final = dplyr::filter(survey_raw, !sur_participant %in% all_remove$all_participants)
    # Tracking Data  
    track_final = dplyr::filter(track_raw, !track_participant %in% all_remove$all_participants)

# Combine all the final data into 1 data frame with the following:
  # Start by creating a data frame with the final participant list in the 1st column: "participant"
  all_par = as.data.frame(track_final$track_participant)
    colnames(all_par) = c("participant")

  # to use the merge function, change the respective "participant" column name in each data frame to "participant"
    # OSpan Data
    colnames(ospan_final)[which(names(ospan_final) == "ospan_participant")] = c("participant")
    # Gng Data
    colnames(gng_final)[which(names(gng_final) == "gng_participant")] = c("participant")
    # Survey Data
    colnames(survey_final)[which(names(survey_final) == "sur_participant")] = c("participant")
    # Tracking Data
    colnames(track_final)[which(names(track_final) == "track_participant")] = c("participant")

# Merge all 4 data frames into 1 data frame -- "all_data"
  all_data = Reduce(function(x, y) merge(x, y, by="participant"), list(track_final, ospan_final, gng_final, dplyr::select(survey_final, -c(sur_location, sur_power, sur_condition))))
    # rename the tracking sheet columns for the location, power, and condition 
    colnames(all_data)[which(names(all_data) == c("track_location", "track_power", "track_condition"))] = c("location", "power", "condition")

2. All Data - Go/No-Go separated by Cue Type (WIDE FORMAT)

All the data from the present study in one data frame, with the Go/No-Go data separated by target type (i.e. either “go” or “no-go”), presented in WIDE FORMAT: “all_data_cue” (click to see more)

  • This data included the following:
    • participant, track_date, track_time, location, power, condition, balance, exclude, reason, pos_out, experimenter, ospan_ID, ospan_absolute_score, ospan_total_corr, ospan_math_err_tot, ospan_math_err_speed, ospan_math_err_accuracy, ospan_math_percent_corr, ospan_math_criteria_85, age_long, lang_long, trial_tot_v, score_v, resp_tot_v, no_resp_tot_v, err_tot_v, err_com_v, err_omi_v, rt_av_v, exclude_v, trial_tot_h, score_h, resp_tot_h, no_resp_tot_h, err_tot_h, err_com_h, err_omi_h, rt_av_h, exclude_h, date_start, date_end, duration.s., date_rec, gender, program, year, SUQ_use_1, SUQ_use_2, SUQ_use_3, SUQ_use_4, SUQ_use_5, SUQ_use_6, SUQ_use_7, SUQ_exp_1, SUQ_exp_2, SUQ_exp_3, SUQ_exp_4, SAD_1, SAD_2, SAD_3, SAD_4, SAD_5, SAD_6, SAD_7, SAD_8, SAD_9, SAD_10, SAD_11, SAD_12, SAD_13

This code organized the raw data into one data frame. (click to expand)

# use the list of all the participants to remove -- "all_remove" -- to filter the raw gng long data
  # for the "go" targets
  gng_v_final = dplyr::filter(gng_data_extracted_v, !participant_long %in% all_remove$all_participants)
  # for the "no-go" targets
  gng_h_final = dplyr::filter(gng_data_extracted_h, !participant_long %in% all_remove$all_participants)

# Combine all the final data into 1 data frame with the following:
  # use the final participant list -- "all_par" -- as the 1st column in the data frames

  # to use the merge function, change the respective "participant" column name in each data frame to "participant"
    # this was already done for the other data frames (e.g. ospan_final, survey_final)
    # for the "vertical" targets
    colnames(gng_v_final)[which(names(gng_v_final) == "participant_long")] = c("participant")
    # for the "horizontal" targets
    colnames(gng_h_final)[which(names(gng_h_final) == "participant_long")] = c("participant")

# Merge all 4 data frames into 1 data frame -- "all_data_cue"
  all_data_cue = Reduce(function(x, y) merge(x, y, by="participant"), list(track_final, ospan_final, gng_v_final, dplyr::select(gng_h_final, -c(age_long, lang_long)), dplyr::select(survey_final, -c(sur_location, sur_power, sur_condition))))
    # rename the tracking sheet columns for the location, power, and condition 
    colnames(all_data_cue)[which(names(all_data_cue) == c("track_location", "track_power", "track_condition"))] = c("location", "power", "condition")
    

3. All Data - Go/No-Go separated by Cue Type (LONG FORMAT)

All the data from the present study in one data frame, with the Go/No-Go data separated by target type (i.e. either “go” or “no-go”), presented in LONG FORMAT: “all_data_cue_long” (click to see more)

  • This data included the following:
    • cue, participant, track_date, track_time, location, power, condition, balance, exclude, reason, pos_out, experimenter, ospan_ID, ospan_absolute_score, ospan_total_corr, ospan_math_err_tot, ospan_math_err_speed, ospan_math_err_accuracy, ospan_math_percent_corr, ospan_math_criteria_85, age_long, lang_long, gng_trial_tot_long, gng_score_long, gng_resp_tot_long, gng_no_resp_tot_long, gng_err_tot_long, gng_err_com_long, gng_err_omi_long, gng_rt_av_long, gng_exclude_long, date_start, date_end, duration.s., date_rec, gender, program, year, SUQ_use_1, SUQ_use_2, SUQ_use_3, SUQ_use_4, SUQ_use_5, SUQ_use_6, SUQ_use_7, SUQ_exp_1, SUQ_exp_2, SUQ_exp_3, SUQ_exp_4, SAD_1, SAD_2, SAD_3, SAD_4, SAD_5, SAD_6, SAD_7, SAD_8, SAD_9, SAD_10, SAD_11, SAD_12, SAD_13

This code organized the raw data into one data frame. (click to expand)

# Re-structure the data into 1 data frame in a long format for a repeated measures analysis

  # using the "final" data frames of all the data, make 2 data frames, one for the "vertical" (all_data_v) and one for the "horizontal" (all_data_h) targets
    # for the "vertical" targets -- all_data_v
    all_data_v = Reduce(function(x, y) merge(x, y, by="participant"), list(track_final, ospan_final, gng_v_final, dplyr::select(survey_final, -c(sur_location, sur_power, sur_condition))))
      # rename the tracking sheet columns for the location, power, and condition 
      colnames(all_data_v)[which(names(all_data_v) == c("track_location", "track_power", "track_condition"))] = c("location", "power", "condition")
    # for the "horizontal" targets -- all_data_h
    all_data_h = Reduce(function(x, y) merge(x, y, by="participant"), list(track_final, ospan_final, gng_h_final, dplyr::select(survey_final, -c(sur_location, sur_power, sur_condition))))
      # rename the tracking sheet columns for the location, power, and condition 
      colnames(all_data_h)[which(names(all_data_h) == c("track_location", "track_power", "track_condition"))] = c("location", "power", "condition")

  # rename target-specific columns for both data frames (to bind)
    # for the "go" trials
    names(all_data_v)[names(all_data_v) == "trial_tot_v"] = "gng_trial_tot_long" 
    names(all_data_v)[names(all_data_v) == "score_v"] = "gng_score_long" 
    names(all_data_v)[names(all_data_v) == "resp_tot_v"] = "gng_resp_tot_long" 
    names(all_data_v)[names(all_data_v) == "no_resp_tot_v"] = "gng_no_resp_tot_long" 
    names(all_data_v)[names(all_data_v) == "err_tot_v"] = "gng_err_tot_long" 
    names(all_data_v)[names(all_data_v) == "err_com_v"] = "gng_err_com_long" 
    names(all_data_v)[names(all_data_v) == "err_omi_v"] = "gng_err_omi_long" 
    names(all_data_v)[names(all_data_v) == "rt_av_v"] = "gng_rt_av_long" 
    names(all_data_v)[names(all_data_v) == "exclude_v"] = "gng_exclude_long"
    # for the "no-go" trials
    names(all_data_h)[names(all_data_h) == "trial_tot_h"] = "gng_trial_tot_long" 
    names(all_data_h)[names(all_data_h) == "score_h"] = "gng_score_long" 
    names(all_data_h)[names(all_data_h) == "resp_tot_h"] = "gng_resp_tot_long" 
    names(all_data_h)[names(all_data_h) == "no_resp_tot_h"] = "gng_no_resp_tot_long" 
    names(all_data_h)[names(all_data_h) == "err_tot_h"] = "gng_err_tot_long" 
    names(all_data_h)[names(all_data_h) == "err_com_h"] = "gng_err_com_long" 
    names(all_data_h)[names(all_data_h) == "err_omi_h"] = "gng_err_omi_long" 
    names(all_data_h)[names(all_data_h) == "rt_av_h"] = "gng_rt_av_long" 
    names(all_data_h)[names(all_data_h) == "exclude_h"] = "gng_exclude_long"
  
  # Create a dataframe depicting the target type: either "go" (coded as 1) or "no-go" (coded as 2)
  cue_type = as.data.frame(c(rep(1, length(all_data_v$participant)), rep(2, length(all_data_h$participant))))
    colnames(cue_type) = c("cue")  

  # Bind the go and no-go dataframes into 1 (in long format)
  gng_cue_bind = dplyr::bind_rows(all_data_v, all_data_h)
  
  # add the target type column depicting the target type: either "go" (coded as 1) or "no-go" (coded as 2)
  all_data_cue_long = dplyr::bind_cols(cue_type, gng_cue_bind)
    

4. OSpan Analysis

All the data related to the OSpan Analysis from the present study in one data frame: “ospan_analysis” (click to see more)

  • This data included the following:
    • participant, age, gender, lang, program, year, location, power, balance, ospan_absolute_score, ospan_math_percent_corr, ospan_math_criteria_85

This code organized the final data into the ospan-related data frame. (click to expand)


# make a new data frame for the ospan analysis
ospan_analysis = dplyr::select(all_data, participant, age, gender, lang, program, year, location, power, balance, ospan_absolute_score, ospan_math_percent_corr, ospan_math_criteria_85)

5. Go/No-Go: Error Analysis

All the data related to the Go/No-Go Error Analysis from the present study in one data frame: “gng_err_analysis”

Note: this data is in a long format for a repeated measures analysis (i.e. based on target type: either “go” or “no-go”). (click to see more)

  • This data included the following:
    • participant, age_long, gender, lang_long, program, year, location, power, balance, cue, gng_exclude_long, gng_trial_tot_long, gng_resp_tot_long, gng_no_resp_tot_long, gng_err_tot_long, gng_err_com_long, gng_err_omi_long

This code organized the final long data into a data frame for the Go/No-Go Error Analysis. (click to expand)

# make a new data frame for the gng error analysis
gng_err_analysis = dplyr::select(all_data_cue_long, participant, age_long, gender, lang_long, program, year, location, power, balance, cue, gng_exclude_long, gng_trial_tot_long, gng_resp_tot_long, gng_no_resp_tot_long, gng_err_tot_long, gng_err_com_long, gng_err_omi_long)

6. Go/No-Go: Accuracy Analysis

All the data related to the Go/No-Go Accuracy Analysis from the present study in one data frame: “gng_ac_analysis” (click to see more)

  • This data included the following:
    • participant, age, gender, lang, program, year, location, power, balance, gng_trial_tot, gng_resp_tot, gng_no_resp_tot, gng_rt_av

This code organized the final data into a data frame related to the Go/No-Go Accuracy Analysis. (click to expand)


# make a new data frame for the gng accuracy analysis
gng_ac_analysis = dplyr::select(all_data, participant, age, gender, lang, program, year, location, power, balance, gng_trial_tot, gng_resp_tot, gng_no_resp_tot, gng_rt_av) 

7. SAD: Factor Analysis

All the data related to the Factor Analysis from the present study in one data frame: “factor_analysis” (click to see more)

  • This data included the following:
    • participant, age, gender, lang, program, year, location, power, balance, SAD_1, SAD_2, SAD_3, SAD_4, SAD_5, SAD_6, SAD_7, SAD_8, SAD_9, SAD_10, SAD_11, SAD_12, SAD_13

This code organized the final data into the factor analysis-related data frame. (click to expand)


# make a new data frame for the factor analysis
factor_analysis = dplyr::select(all_data, participant, age, gender, lang, program, year, location, power, balance, SAD_1:SAD_13)

8. SAD: Generalized Linear Model

All the data related to the GLM Analysis from the present study in one data frame: “glm_analysis” (click to see more)

  • This data included the following:
    • participant, age, gender, lang, program, year, location, power, balance, SAD_1, SAD_2, SAD_3, SAD_4, SAD_5, SAD_6, SAD_7, SAD_8, SAD_9, SAD_10, SAD_11, SAD_12, SAD_13

This code organized the final data into the GLM-related data frame. (click to expand)


# make a new data frame for the glm analysis
glm_analysis = dplyr::select(all_data, participant, age, gender, lang, program, year, location, power, balance, SAD_1:SAD_13)

Descriptives: Smartphone Use

all_data_des = dplyr::select(all_data, participant, track_date, track_time, age, gender, lang, program, year)

# summary of age
summary(all_data_des$age)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  17.00   18.00   19.00   18.89   19.00   38.00 
# frequency of age
plyr::count(all_data_des$age)

# show frequency for gender
  # define gender as factor
  all_data_des$gender = factor(all_data_des$gender, 
                               levels = c(1, 2), 
                               labels = c("Male", "Female"))
  # show counts
  plyr::count(all_data_des$gender)

# show freq of year of study
plyr::count(all_data_des$year)

# show freq of program
  # first define the program as a factor
    all_data_des$program = factor(all_data_des$program, 
                  levels = c(3, 4, 13, 14, 28, 32, 37, 12, 17, 19, 15, 20, 24, 23, 26, 1, 2, 5, 7, 8, 11, 16, 18, 22, 27, 29, 33, 36, 6, 9, 10, 21, 25, 30, 31, 34, 35),
                  labels = c(rep("Arts & Humanities", 7), "Engineering", rep("Health Sciences", 2), rep("Information & Media Studies", 3), "Medicine & Dentistry", "Music", rep("Science", 13), rep("Social Science", 9)))
  # then show counts
  plyr::count(all_data_des$program)
NA
NA

Planned Analysis

The following analyses were completed based on a pre-registered direct replication on OSF (view registration: https://osf.io/5fq4r) of Ward et al.’s (2017) second experiment. The analyses tested the three main hypotheses in the present study: (1) the location effect hypothesis, (2) the power effect hypothesis, and (3) the moderation effect hypothesis.

Each analysis contains the following:

  1. Descriptive Statistics
  2. Analysis (including any relevant assumption tests)
  3. Visualizations

Testing the Location and Power Hypotheses:

OSpan Task

A 3(smartphone location: desk, pocket/bag, outside) x 2(smartphone power: ON, OFF) between-subjects ANOVA was conducted (DV = OSpan absolute score).

Prior to completing the analysis, planned exclusion critera was applied to the data. Exclusion criteria for this analysis helped to control for any participants who did not follow the instructions, specifically, that participant payed attention to both the math component and letter recall component of the task. Only data from those who scored 85% or higher on the math component of the task were included.

  • Exclude data from any partitipants with (1) missing data and/or (2) the math criteria (i.e. minimum 85% on math accuracy). There was a total of 389 participants in the OSpan analysis.
    • Missing Data: 3 participants were removed due to missing ospan data.
    • Math Criteria (min. 85%): 20 participants were removed because they did not meet the math criteria.
# filter any participants with missing OSpan data for the analysis  
    # for all ps, excluding any p with missing data in the OSpan Absolute Score ONLY
    ospan_analysis_noNA = ospan_analysis[!is.na(ospan_analysis$ospan_absolute_score), ] 
    # for all ps, excluding any that do not meet the math criteria (min 85% accuracy)
    ospan_analysis_final = ospan_analysis_noNA[ospan_analysis_noNA[,"ospan_math_criteria_85"] == 1,]

Descriptive Statistics

The following table depicts the descriptive statistics for the OSpan analysis: the mean (M), standard deviation (SD), minimum score (min.), maximum score (max.), and the sample size (n).


# create a data frame with the descriptives of all the data, grouped by the location & power conditions
  # this creates information for the 6 possible combined conditions
  ospan_des = psych::describeBy(ospan_analysis_final, list(ospan_analysis_final$location, ospan_analysis_final$power), mat = TRUE)  
  
# organize the data into a new data frame depicting the M, SD, min., max., and n.
  ospan_des_t = rbind((cbind(t(ospan_des["ospan_absolute_score1",c("mean", "sd", "min", "max", "n")]),
                             t(ospan_des["ospan_absolute_score2",c("mean", "sd", "min", "max", "n")]),
                             t(ospan_des["ospan_absolute_score3",c("mean", "sd", "min", "max", "n")]))), 
                      (cbind(t(ospan_des["ospan_absolute_score4",c("mean", "sd", "min", "max", "n")]),
                             t(ospan_des["ospan_absolute_score5",c("mean", "sd", "min", "max", "n")]),
                             t(ospan_des["ospan_absolute_score6",c("mean", "sd", "min", "max", "n")]))))
    colnames(ospan_des_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(ospan_des_t) = rep(c("M", "SD", "min.", "max.", "n"), 2)
    
# use kable to show the descriptives table
  kable(ospan_des_t, caption = "Descriptive Statistics: Absolute Score on the OSpan Task", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
  add_header_above(c(" ", "Smartphone Location" = 3)) %>%
  group_rows(index = c("Smartphone Power ON" = 5, "Smartphone Power OFF" = 5))

Descriptive Statistics: Absolute Score on the OSpan Task
Smartphone Location
On Desk In Pocket/Bag Outside
Smartphone Power ON
M 41.4571 42.7353 38.6393
SD 16.2157 15.3259 18.1338
min. 6.0000 6.0000 4.0000
max. 75.0000 75.0000 75.0000
n 70.0000 68.0000 61.0000
Smartphone Power OFF
M 40.7458 40.7761 43.6250
SD 18.7650 17.5187 15.6788
min. 0.0000 3.0000 0.0000
max. 75.0000 75.0000 75.0000
n 59.0000 67.0000 64.0000

NA

Analysis

To assess if OSpan absolute score statistically differed, we conducted a 3x2 ANOVA with the between-subjects factors of smartphone location (i.e. on desk, in pocket/bag, or outside) and power (i.e. on or off). Since there are unequal sample sizes, we used Type III sum of squares.

Assumptions

The ANOVA made three assumptions. All assumptions were met (click to see details).

1. Independent Random Sampling

This assumption was met during testing.

2. Normality

This assumption was tested by visualizing the residuals, applying a Shapiro-Wilk test to the resdiuals, and observing the Skewness and Kurtosis of the data (extracted from the ANOVA output).


# get the required data from the ospan_analysis data: participant, location, power, and score
ospan_anova_data = ospan_analysis_final[, c("participant", "location", "power", "balance", "ospan_absolute_score")]
    colnames(ospan_anova_data) = c("participant", "location", "power", "balance", "score")
    rownames(ospan_anova_data) = NULL
    # reformat location,  power, and balance as factors  
    ospan_anova_data$location = factor(ospan_anova_data$location, 
                  levels = c(1, 2, 3),
                  labels = c("On Desk", "Pocket/Bag", "Outside"))
    ospan_anova_data$power = factor(ospan_anova_data$power, 
                  levels = c(1, 2),
                  labels = c("ON", "OFF"))
    ospan_anova_data$balance = factor(ospan_anova_data$balance, 
                  levels = c(1, 2),
                  labels = c("Ospan First", "Go/No-Go First"))

# run between-subjects ANOVA (IV: Smartphone Power & Location, Balance; DV: OSpan Abolute Score)
ospan_anova = ezANOVA(
  data = ospan_anova_data
  , dv = .(score)
  , wid = .(participant)
  , between = .(location, power, balance)
  , type = 3 # unequal sample sizes, therfore use type 3
  , detailed = TRUE
  , return_aov = TRUE
)

# calculate & extract the residuals from the ANOVA
ospan_res = data.frame("residuals" = proj(ospan_anova$aov)[,"Residuals"])   
  • It appears that the residuals lie closely to a straight line, which suggests normality (see visualization below).

qqnorm(ospan_res$residuals, main = "Q-Q Plot of the OSpan Residuals") 
qqline(ospan_res$residuals)

  • It appears that residuals tend to follow the shape of a normal distribution, with a slight skew to the right (see visualization below).

qplot(ospan_res$residuals, main = "Histogram of Ospan Residuals") + 
  theme_classic()

  • The Shapiro-Wilk test of normality was significant (based on \(\alpha = 0.05\)), W = 0.99, p = .004 (see code below).

ospan_shap = shapiro.test(ospan_res$residuals)
ospan_shap

    Shapiro-Wilk normality test

data:  ospan_res$residuals
W = 0.98848, p-value = 0.003638
  • The data’s Skewness and Kurtosis was examined and showed that both the Skewness (range: -0.42 to -0.01) and Kurtosis (range: -0.83 to 0.1) were within the acceptable range of \(\pm 2.0\) and \(\pm 9.0\), respectively (Schmider, Ziegler, Danay, Beyer, & Bühner, 2010) (see table below).
# use the "ospan_des" data frame from the descriptives

# organize the data into a new data frame depicting the Skew, kurtosis, and sample size (n).
  ospan_sk_t = rbind((cbind(t(ospan_des["ospan_absolute_score1", c("skew", "kurtosis", "n")]),
                             t(ospan_des["ospan_absolute_score2", c("skew", "kurtosis", "n")]),
                             t(ospan_des["ospan_absolute_score3", c("skew", "kurtosis", "n")]))), 
                      (cbind(t(ospan_des["ospan_absolute_score4", c("skew", "kurtosis", "n")]),
                             t(ospan_des["ospan_absolute_score5", c("skew", "kurtosis", "n")]),
                             t(ospan_des["ospan_absolute_score6", c("skew", "kurtosis", "n")]))))
    colnames(ospan_sk_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(ospan_sk_t) = rep(c("Skewness", "Kurtosis", "n"), 2)
    
# use kable to show the descriptives table
  kable(ospan_sk_t, caption = "Skewness and Kurtosis of the Absolute Score on the OSpan Task", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
  add_header_above(c(" ", "Smartphone Location" = 3)) %>%
  group_rows(index = c("Smartphone Power ON" = 3, "Smartphone Power OFF" = 3))

Skewness and Kurtosis of the Absolute Score on the OSpan Task
Smartphone Location
On Desk In Pocket/Bag Outside
Smartphone Power ON
Skewness -0.2342 -0.4151 -0.0056
Kurtosis -0.7095 -0.2257 -0.8323
n 70.0000 68.0000 61.0000
Smartphone Power OFF
Skewness -0.3900 -0.2216 -0.4169
Kurtosis -0.8277 -0.7885 0.1035
n 59.0000 67.0000 64.0000

NA
  • Therefore, based on all the normality assumption checks, normality was assumed to be within the acceptable range for the ANOVA analysis. Additionally, it should be noted that ANOVA analyses can be robust to violations of normality (Gardner & Tremblay, 2007).

3. Homogeneity of Variance

This assumption was tested by conducting Levene’s Test for Homogeneity of Variance for each between-subjects variable (i.e. smartphone location and smartphone power).

  • The homogeneity assumption was met (based on \(\alpha = 0.05\)) for smartphone location, F(2, 386) = 0.31, p = = .74, smartphone power, F(1, 387) = 0.21, p = .65, and balance, F(1, 387) = 0, p = .99(see code below).

# conduct levene's
  # for location
  ospan_lev_loc = leveneTest(data = ospan_anova_data, score ~ as.factor(location), center = median)
  ospan_lev_loc
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group   2  0.3054  0.737
      386               
  # for power
  ospan_lev_pow = leveneTest(data = ospan_anova_data, score ~ as.factor(power), center = median)
  ospan_lev_pow
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group   1  0.2076 0.6489
      387               
  # for balance
  ospan_lev_bal = leveneTest(data = ospan_anova_data, score ~ as.factor(balance), center = median)
  ospan_lev_bal
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group   1   3e-04 0.9858
      387               
Results

All results were based on \(\alpha = 0.05\). Below are the reported statistics for both main effects and the interactions, followed by a table depicting the ANOVA results.

Main Effect of Smartphone Location

There was no significant main effect of smartphone location on Ospan absolute score, F(2, 377) = 0.12, p = .89, \(\eta^{2}\) = .001.

Main Effect of Smartphone Power

There was no significant main effect of smartphone power on Ospan absolute score, F(1, 377) = 0.05, p = .83, \(\eta^{2}\) < .001.

Interaction of Balance

There was no significant main effect of balance (i.e. which task was completed first) on Ospan absolute score, F(1, 377) = 2.72, p = .1, \(\eta^{2}\) = .01.

Interaction of Smartphone Location & Smartphone Power

There was no significant interaction between smartphone location and smartphone power on Ospan absolute score, F(2, 377) = 1.41, p = .24, \(\eta^{2}\) = .01.

Interaction of Smartphone Location & Balance

There was no significant interaction between smartphone location and balance (i.e. which task was completed first) on Ospan absolute score, F(2, 377) = 2.18, p = .11, \(\eta^{2}\) = .01.

Interaction of Smartphone Power & Balance

There was no significant interaction between smartphone power and balance (i.e. which task was completed first) on Ospan absolute score, F(1, 377) = 1.14, p = .29, \(\eta^{2}\) = .003.

Interaction of Smartphone Location, Smartphone Power, & Balance

There was no significant interaction between smartphone location, smartphone power, and balance (i.e. which task was completed first) on Ospan absolute score, F(2, 377) = 2.64, p = .07, \(\eta^{2}\) = .01.

Post-hoc Tests

Since there was no significant main or interaction effects, no post-hocs were completed.

# show ANOVA results in kable table 
kable(ospan_anova$ANOVA, caption = "3x2 ANOVA on Ospan Absolute Score", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) 

3x2 ANOVA on Ospan Absolute Score
Effect DFn DFd SSn SSd F p p<.05 ges
(Intercept) 1 377 645211.1638 106102.5 2292.5429 0.0000 * 0.8588
location 2 377 67.1897 106102.5 0.1194 0.8875 0.0006
power 1 377 12.6653 106102.5 0.0450 0.8321 0.0001
balance 1 377 764.5825 106102.5 2.7167 0.1001 0.0072
location:power 2 377 794.8131 106102.5 1.4121 0.2449 0.0074
location:balance 2 377 1229.6413 106102.5 2.1846 0.1139 0.0115
power:balance 1 377 321.3575 106102.5 1.1418 0.2859 0.0030
location:power:balance 2 377 1486.1928 106102.5 2.6403 0.0727 0.0138

NA

Visualizations

The following shows a visulization of the Ospan absolute score based on the two smartphone conditions: location and power. Note: Since the balance factor (i.e. which task was completed first) did not have a significant main effect or interaction effect on the data, this factor was not visualized in the plots

Cue-Dependent Go/No-Go Task

An error (i.e. omission errors) and accuracy (i.e. RT) analysis was completed using the omission errors and average RT for each participant.

Error Analysis

A 3(Smartphone location: desk, pocket/bag, outside) x 2(Smartphone power: ON, OFF) x 2(Cue type: Vertical, Horizontal) mixed ANOVA was completed (DV = omission error(s)). The between-subjects factors were smartphone location and power, and the within-subjects factor was pre-target cue type (i.e. “cue type”; either “vertical” or “horizontal”).

Prior to completing the analysis, planned exclusion critera was applied to the data. Exclusion criteria for this analysis helped to control for any participants who did not follow the instructions. Only data from those who scored higher than chance performance (i.e. responded to at least 50% of “Go” trials and withheld response to at least 50% of “No-Go” trials) were used for the final analysis.

  • Exclude data from any partitipants with (1) missing data and/or (2) the response criteria, where participants scored higher than chance performance (i.e. responded to at least 50% of “Go” trials and withheld response to at least 50% of “No-Go” trials). There was a total of 403 participants in the Go/No-Go Error analysis.
    • Missing Data: 0 participants were removed due to missing data.
    • Response Criteria: 6 participants were removed because they did not meet the response criteria.
# filter any participants with missing data or that do not meet the inclusionn criteria

  # for all ps, excluding any p with missing data in the Omission Error 
  gng_err_noNA = gng_err_analysis[!is.na(gng_err_analysis$gng_err_omi_long),]
  
  # for all ps, excluding any that scored below chance performance (i.e. respondd to at least 50% of the "go" trials and withheld response to at least 50% of the "no-go" trials) using the "exclude" column
  gng_err_final = gng_err_noNA[gng_err_noNA$gng_exclude_long == 2,]
Descriptive Statistics

The following table depicts the descriptive statistics for the Go/No-Go Error Analysis: the mean (M), standard deviation (SD), minimum score (min.), maximum score (max.), and the sample size (n).


# create a data frame with the descriptives of all the data, grouped by the location & power conditions
  # this creates information for the 6 possible combined conditions
  # for the "vertical" trials
  gng_err_des_v = describeBy(gng_err_final[gng_err_final$cue == 1,], 
                           list(gng_err_final[gng_err_final$cue == 1,]$location, 
                                gng_err_final[gng_err_final$cue == 1,]$power), mat = TRUE) 
  # for the "horizontal" trials
  gng_err_des_h = describeBy(gng_err_final[gng_err_final$cue == 2,], 
                           list(gng_err_final[gng_err_final$cue == 2,]$location, 
                                gng_err_final[gng_err_final$cue == 2,]$power), mat = TRUE) 
  
# organize the data into a new data frame depicting the M, SD, min., max., and n.
  # for the "vertical" trials
  gng_err_des_v_t = rbind((cbind(t(gng_err_des_v["gng_err_omi_long1",c("mean", "sd", "min", "max", "n")]),
                             t(gng_err_des_v["gng_err_omi_long2",c("mean", "sd", "min", "max", "n")]),
                             t(gng_err_des_v["gng_err_omi_long3",c("mean", "sd", "min", "max", "n")]))), 
                      (cbind(t(gng_err_des_v["gng_err_omi_long4",c("mean", "sd", "min", "max", "n")]),
                             t(gng_err_des_v["gng_err_omi_long5",c("mean", "sd", "min", "max", "n")]),
                             t(gng_err_des_v["gng_err_omi_long6",c("mean", "sd", "min", "max", "n")]))))
    colnames(gng_err_des_v_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(gng_err_des_v_t) = rep(c("M", "SD", "min.", "max.", "n"), 2)
  # for the "horizontal" trials
  gng_err_des_h_t = rbind((cbind(t(gng_err_des_h["gng_err_omi_long1",c("mean", "sd", "min", "max", "n")]),
                             t(gng_err_des_h["gng_err_omi_long2",c("mean", "sd", "min", "max", "n")]),
                             t(gng_err_des_h["gng_err_omi_long3",c("mean", "sd", "min", "max", "n")]))), 
                      (cbind(t(gng_err_des_h["gng_err_omi_long4",c("mean", "sd", "min", "max", "n")]),
                             t(gng_err_des_h["gng_err_omi_long5",c("mean", "sd", "min", "max", "n")]),
                             t(gng_err_des_h["gng_err_omi_long6",c("mean", "sd", "min", "max", "n")]))))
    colnames(gng_err_des_h_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(gng_err_des_h_t) = rep(c("M", "SD", "min.", "max.", "n"), 2)
    
# use kable to show the descriptives table
  gng_err_v_kt = 
    kable(gng_err_des_v_t, caption = "Descriptive Statistics: Omission Errors on the Go/No-Go Task for 'Vertical' Trials", digits = 4, align = 'c') %>%
    kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
    add_header_above(c(" ", "Smartphone Location" = 3)) %>%
    group_rows(index = c("Smartphone Power ON" = 5, "Smartphone Power OFF" = 5))
  
  gng_err_h_kt = 
    kable(gng_err_des_h_t, caption = "Descriptive Statistics: Omission Errors on the Go/No-Go Task for 'Horizontal' Trials", digits = 4, align = 'c') %>%
    kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
    add_header_above(c(" ", "Smartphone Location" = 3)) %>%
    group_rows(index = c("Smartphone Power ON" = 5, "Smartphone Power OFF" = 5))
  
  gng_err_v_kt

Descriptive Statistics: Omission Errors on the Go/No-Go Task for 'Vertical' Trials
Smartphone Location
On Desk In Pocket/Bag Outside
Smartphone Power ON
M 0.6849 0.4085 1.2273
SD 2.1140 0.8877 5.3430
min. 0.0000 0.0000 0.0000
max. 14.0000 4.0000 43.0000
n 73.0000 71.0000 66.0000
Smartphone Power OFF
M 0.9333 0.5522 0.3939
SD 3.0413 2.8830 1.0058
min. 0.0000 0.0000 0.0000
max. 20.0000 23.0000 6.0000
n 60.0000 67.0000 66.0000

  gng_err_h_kt

Descriptive Statistics: Omission Errors on the Go/No-Go Task for 'Horizontal' Trials
Smartphone Location
On Desk In Pocket/Bag Outside
Smartphone Power ON
M 0.1233 0.1268 0.4091
SD 0.3706 0.3753 1.3809
min. 0.0000 0.0000 0.0000
max. 2.0000 2.0000 10.0000
n 73.0000 71.0000 66.0000
Smartphone Power OFF
M 0.1167 0.2090 0.1667
SD 0.4903 0.9135 0.4501
min. 0.0000 0.0000 0.0000
max. 3.0000 7.0000 2.0000
n 60.0000 67.0000 66.0000

NA
Analysis

To assess if the omission errors statistically differed, we conducted a 3x2x2 mixed ANOVA with the between-subjects factors of smartphone location (i.e. on desk, in pocket/bag, or outside) and power (i.e. on or off), and the within-subjects factor of cue type (i.e. “vertical” or “horizontal”). Since there are unequal sample sizes, we used Type III sum of squares.

Assumptions

The mixed ANOVA made four assumptions. The normality assumption was not met. Therefore, a robust ANOVA was completed to assess if the omission errors statistically differed between the factors (i.e. smartphone location, smartphone power, and cue type) (click to see details).

1. Independent Random Sampling

This assumption was met during testing.

2. Normality

This assumption was tested by visualizing the residuals, applying a Shapiro-Wilk test to the resdiuals, and observing the Skewness and Kurtosis of the data (extracted from the ANOVA output).


# get the required data from the gng_err_final data: participant, location, power, and score
gng_err_anova_data = gng_err_final[,c("participant", "location", "power", "cue", "balance", "gng_err_omi_long")]
    colnames(gng_err_anova_data) = c("participant", "location", "power", "cue", "balance", "err_omi")
    rownames(gng_err_anova_data) = NULL
    gng_err_anova_data$location = as.factor(gng_err_anova_data$location)
    gng_err_anova_data$power = as.factor(gng_err_anova_data$power)
    gng_err_anova_data$cue = as.factor(gng_err_anova_data$cue)
    gng_err_anova_data$balance = as.factor(gng_err_anova_data$balance)

# run mixed ANOVA (IV b/w: Smartphone Power & Location; IV w/in: Target Type; DV: Omission Errors)
gng_err_anova = ezANOVA(
  data = gng_err_anova_data
  , dv = .(err_omi)
  , wid = .(participant)
  , within = .(cue)
  , between = .(location, power, balance)
  , type = 3 # unequal sample sizes, therefore use type 3
  , detailed = TRUE
  , return_aov = TRUE
)

# calculate & extract the residuals from the ANOVA
gng_err_res = data.frame("residuals" = proj(gng_err_anova$aov)[[3]][, "Residuals"])
  • It appears that the residuals lie closely to a straight line (i.e. only a couple lie away form the line), which suggests normality (see visualization below).

qqnorm(gng_err_res$residuals, main = "Q-Q Plot of the Go/No-Go Error Residuals") 
qqline(gng_err_res$residuals)

  • It appears that residuals are leptokurtic (i.e. there is a high peak near the center) (see visualization below).

qplot(gng_err_res$residuals, main = "Histogram of Go/No-Go Error Residuals", binwidth = .15) + 
  theme_classic()

  • The Shapiro-Wilk test of normality was significant (based on \(\alpha = 0.05\)), W = 0.42, p < .001 (see code below).

gng_err_shap = shapiro.test(gng_err_res$residuals)
gng_err_shap

    Shapiro-Wilk normality test

data:  gng_err_res$residuals
W = 0.42168, p-value < 2.2e-16
  • The data’s Skewness and Kurtosis was examined. For the vertical cue type, both the Skewness (range: 2.65 to 7.01) and Kurtosis (range: 7.36 to 51.13) were outside of the acceptable range of \(\pm 2.0\) and \(\pm 9.0\), respectively (Schmider, Ziegler, Danay, Beyer, & Bühner, 2010). For the horizontal cue type, both the Skewness (range: 1.73 to 7.54) and Kurtosis (range: 2.45 to 58.7) were outside of the acceptable range of \(\pm 2.0\) and \(\pm 9.0\), respectively (Schmider, Ziegler, Danay, Beyer, & Bühner, 2010) (see table below).
# create & show a table of the skewness & kurtosis for the gng data, separated by cue type (i.e. one for the vertical and horizontal trials)

#--FOR THE VERTICAL CUE TYPE
# use the "gng_err_des_v" data frame from the descriptives

# organize the data into a new data frame depicting the Skew, kurtosis, and sample size (n).
  gng_err_sk_v_t = rbind((cbind(t(gng_err_des_v["gng_err_tot_long1", c("skew", "kurtosis", "n")]),
                             t(gng_err_des_v["gng_err_tot_long2", c("skew", "kurtosis", "n")]),
                             t(gng_err_des_v["gng_err_tot_long3", c("skew", "kurtosis", "n")]))), 
                      (cbind(t(gng_err_des_v["gng_err_tot_long4", c("skew", "kurtosis", "n")]),
                             t(gng_err_des_v["gng_err_tot_long5", c("skew", "kurtosis", "n")]),
                             t(gng_err_des_v["gng_err_tot_long6", c("skew", "kurtosis", "n")]))))
    colnames(gng_err_sk_v_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(gng_err_sk_v_t) = rep(c("Skewness", "Kurtosis", "n"), 2)
    
# use kable to show the descriptives table
  gng_err_sk_v = kable(gng_err_sk_v_t, caption = "Skewness and Kurtosis of the Omission Errors on the Go/No-Go Task for 'Vertical' Trials", digits = 4, align = 'c') %>%
    kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
    add_header_above(c(" ", "Smartphone Location" = 3)) %>%
    group_rows(index = c("Smartphone Power ON" = 3, "Smartphone Power OFF" = 3))
  
#--FOR THE HORIZONTAL CUE TYPE
# use the "gng_err_des_h" data frame from the descriptives

# organize the data into a new data frame depicting the Skew, kurtosis, and sample size (n).
  gng_err_sk_h_t = rbind((cbind(t(gng_err_des_h["gng_err_tot_long1", c("skew", "kurtosis", "n")]),
                             t(gng_err_des_h["gng_err_tot_long2", c("skew", "kurtosis", "n")]),
                             t(gng_err_des_h["gng_err_tot_long3", c("skew", "kurtosis", "n")]))), 
                      (cbind(t(gng_err_des_h["gng_err_tot_long4", c("skew", "kurtosis", "n")]),
                             t(gng_err_des_h["gng_err_tot_long5", c("skew", "kurtosis", "n")]),
                             t(gng_err_des_h["gng_err_tot_long6", c("skew", "kurtosis", "n")]))))
    colnames(gng_err_sk_h_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(gng_err_sk_h_t) = rep(c("Skewness", "Kurtosis", "n"), 2)
    
# use kable to show the descriptives table
  gng_err_sk_h = kable(gng_err_sk_h_t, caption = "Skewness and Kurtosis of the Omission Errors on the Go/No-Go Task for 'Horizonatal' Trials", digits = 4, align = 'c') %>%
    kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
    add_header_above(c(" ", "Smartphone Location" = 3)) %>%
    group_rows(index = c("Smartphone Power ON" = 3, "Smartphone Power OFF" = 3))
  
# show the tables
  # for the Vertical Cue Type
  gng_err_sk_v

Skewness and Kurtosis of the Omission Errors on the Go/No-Go Task for 'Vertical' Trials
Smartphone Location
On Desk In Pocket/Bag Outside
Smartphone Power ON
Skewness 3.4795 2.6488 7.0078
Kurtosis 13.3863 7.3608 51.1329
n 73.0000 71.0000 66.0000
Smartphone Power OFF
Skewness 4.2401 6.9556 2.9178
Kurtosis 20.7613 50.5909 9.9703
n 60.0000 67.0000 66.0000

  # for the Horizonatal Cue Type
  gng_err_sk_h

Skewness and Kurtosis of the Omission Errors on the Go/No-Go Task for 'Horizonatal' Trials
Smartphone Location
On Desk In Pocket/Bag Outside
Smartphone Power ON
Skewness 7.5440 2.7262 3.9242
Kurtosis 58.7026 8.6904 20.5069
n 73.0000 71.0000 66.0000
Smartphone Power OFF
Skewness 2.1496 7.4708 1.7321
Kurtosis 4.8818 56.3296 2.4486
n 60.0000 67.0000 66.0000

NA
  • Therefore, based on all the normality assumption checks, normality was not assumed to be within the acceptable range for the ANOVA analysis.

3. Homogeneity of Variance

  • This assumption was tested by conducting Levene’s Test for Homogeneity of Variance for each between-subjects variable (i.e. smartphone location, smartphone power, and balance).

  • The homogeneity assumption was met (based on \(\alpha = 0.05\)) for both smartphone location, F(2, 803) = 0.77, p = .47, smartphone power, F(1, 804) = 0.41, p = .52, and balance, F(1, 804) = 1.21, p = .27.(see code below).


# conduct levene's
  # for location
  gng_err_lev_loc = leveneTest(data = gng_err_anova_data, err_omi ~ as.factor(location), center = median)
  gng_err_lev_loc
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group   2  0.7651 0.4656
      803               
  # for power
  gng_err_lev_pow = leveneTest(data = gng_err_anova_data, err_omi ~ as.factor(power), center = median)
  gng_err_lev_pow
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group   1  0.4097 0.5223
      804               
  # for balance
  gng_err_lev_bal = leveneTest(data = gng_err_anova_data, err_omi ~ as.factor(balance), center = median)
  gng_err_lev_bal
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group   1  1.2119 0.2713
      804               

4. Sphericity

This assumption was met since sphericity is always met for two levels of a repeated measure factor and is, therefore, unnecessary to evaluate (Girden, 1992).

Results

Since the normality assumption was not met for the mixed ANOVA, a robust ANOVA was completed. This was done using the “welchADF” package (more details on this package: https://journal.r-project.org/archive/2017/RJ-2017-049/index.html)). The results from this analysis are shown below, followed by a table depicting the statistics.


# compute the main effects
gng_err_wel = welchADF.test(formula = err_omi ~ location + power + balance + cue, response = "err_omi", between.s = .(location, power, balance), within.s = .(cue), subject = "participant", contrast = c("omnibus", "all.pairwise"), data = gng_err_anova_data, effect.size = TRUE, trimming = TRUE)

# NOTE:to get the effect sizes, the package will allow you to get the pairwise (i.e. post-hoc) effect sizes 
  # the robust ANOVA above does not automatically get the effect sizes 
  # Note: it must be done for each factor separately with the following as a guide
# welchADF.test(formula = err_omi ~ location + power + balance + cue, response = "err_omi", between.s = .(location, power, balance), within.s = .(cue), subject = "participant", contrast = "all.pairwise", data = gng_err_anova_data, effect.size = TRUE, trimming = TRUE, effect = "cue")

#welchADF.test(formula = err_omi ~ location + power + cue, data = gng_err_anova_data, effect = "cue", contrast = "all.pairwise", trimming = TRUE, effect.size = TRUE)

# add all the interaction effects
gng_err_robust = update.default(gng_err_wel, .~location*power*balance*cue)

All results were base on \(\alpha = 0.05\). Below are the reported statistics for both main effects and the interaction, followed by a table depicting the ANOVA results.

Main Effect of Smartphone Location

There was no significant main effect of smartphone location on omission errors, WJ(2, 117.22) = 1.26, p = .29.

Main Effect of Smartphone Power

There was no significant main effect of smartphone power on omission errors, WJ(1, 193.68) = 0.91, p = .34.

Main Effect of Smartphone Balance

There was no significant main effect of balance (i.e. which task was completed first) on omission errors, WJ(1, 193.68) = 0.81, p = .37`.

Main Effect of Smartphone Cue Type

There was no significant main effect of cue type on omission errors, WJ(1, 193.68) = 3.3, p = .07`.

Interaction of Smartphone Location & Power

There was no significant interaction between smartphone location and power on omission errors, WJ(2, 117.22) = 0.37, p = .69`.

Interaction of Smartphone Location & Balance

There was no significant interaction between smartphone location and balance (i.e. which task was completed first) on omission errors, WJ(2, 117.22) = 0.87, p = .42`.

Interaction of Smartphone Power & Balance

There was no significant interaction between smartphone power and balance (i.e. which task was completed first) on omission errors, WJ(1, 193.68) = 0.59, p = .44`.

Interaction of Smartphone Location & Cue Type

There was no significant interaction between smartphone location and cue type on omission errors, WJ(2, 117.22) = 0.56, p = .57`.

Interaction of Smartphone Power & Cue Type

There was no significant interaction between smartphone power and cue type on omission errors, WJ(1, 193.68) = 0.94, p = .33`.

Interaction of Balance & Cue Type

There was no significant interaction between balance (i.e. which task was completed first) and cue type on omission errors, WJ(1, 193.68) = 0.19, p = .67`.

Interaction of Smartphone Location, Smartphone Power, & Balance

There was no significant interaction between smartphone location, smartphone power, and balance (i.e. which task was completed first) on omission errors, WJ(2, 117.22) = 0.5, p = .61`.

Interaction of Smartphone Location, Smartphone Power, & Cue Type

There was no significant interaction between smartphone location, smartphone power, and cue type on omission errors, WJ(2, 117.22) = 0.39, p = .68`.

Interaction of Smartphone Location, Balance, & Cue Type

There was no significant interaction between smartphone location, balance (i.e. which task was completed first), and cue type on omission errors, WJ(2, 117.22) = 0.43, p = .65`.

Interaction of Smartphone Power, Balance, & Cue Type

There was no significant interaction between smartphone power, balance (i.e. which task was completed first), and cue type on omission errors, WJ(1, 193.68) = 0.62, p = .43`.

Interaction of Smartphone Location, Smartphone Power, Balance, & Cue Type

There was no significant interaction between smartphone location, smartphone power, balance (i.e. which task was completed first), and cue type on omission errors, WJ(2, 117.22) = 0.52, p = .6`.

Post-hoc Tests

Since there was no significant main or interaction effects, no post-hocs were completed.


# create data frame from robust ANOVA results to display
  # get the Numerator DF (DFn)
  gng_err_robust_dfn = as.numeric(c(gng_err_robust$location$numeratorDF, gng_err_robust$power$numeratorDF, 
                                  gng_err_robust$balance$numeratorDF, gng_err_robust$cue$numeratorDF, 
                                  gng_err_robust$`location:power`$numeratorDF, gng_err_robust$`location:balance`$numeratorDF, 
                                  gng_err_robust$`power:balance`$numeratorDF, gng_err_robust$`location:cue`$numeratorDF, 
                                  gng_err_robust$`power:cue`$numeratorDF, gng_err_robust$`balance:cue`$numeratorDF, 
                                  gng_err_robust$`location:power:balance`$numeratorDF,
                                  gng_err_robust$`location:power:cue`$numeratorDF,
                                  gng_err_robust$`location:balance:cue`$numeratorDF, 
                                  gng_err_robust$`power:balance:cue`$numeratorDF, 
                                  gng_err_robust$`location:power:balance:cue`$numeratorDF))
  # get the Denominator DF (DFd)
  gng_err_robust_dfd = as.numeric(c(gng_err_robust$location$denominatorDF, gng_err_robust$power$denominatorDF, 
                                  gng_err_robust$balance$denominatorDF, gng_err_robust$cue$denominatorDF, 
                                  gng_err_robust$`location:power`$denominatorDF, gng_err_robust$`location:balance`$denominatorDF,
                                  gng_err_robust$`power:balance`$denominatorDF, gng_err_robust$`location:cue`$denominatorDF, 
                                  gng_err_robust$`power:cue`$denominatorDF, gng_err_robust$`balance:cue`$denominatorDF, 
                                  gng_err_robust$`location:power:balance`$denominatorDF,
                                  gng_err_robust$`location:power:cue`$denominatorDF,
                                  gng_err_robust$`location:balance:cue`$denominatorDF, 
                                  gng_err_robust$`power:balance:cue`$denominatorDF, 
                                  gng_err_robust$`location:power:balance:cue`$denominatorDF))
  # get the WJ statistic
  gng_err_robust_WJ = as.numeric(c(gng_err_robust$location$welch.T, gng_err_robust$power$welch.T, 
                                  gng_err_robust$balance$welch.T, gng_err_robust$cue$welch.T, 
                                  gng_err_robust$`location:power`$welch.T, gng_err_robust$`location:balance`$welch.T,
                                  gng_err_robust$`power:balance`$welch.T, gng_err_robust$`location:cue`$welch.T, 
                                  gng_err_robust$`power:cue`$welch.T, gng_err_robust$`balance:cue`$welch.T, 
                                  gng_err_robust$`location:power:balance`$welch.T,
                                  gng_err_robust$`location:power:cue`$welch.T,
                                  gng_err_robust$`location:balance:cue`$welch.T, 
                                  gng_err_robust$`power:balance:cue`$welch.T, 
                                  gng_err_robust$`location:power:balance:cue`$welch.T))
  # get the p value
  gng_err_robust_pval = as.numeric(c(gng_err_robust$location$pval, gng_err_robust$power$pval, 
                                  gng_err_robust$balance$pval, gng_err_robust$cue$pval, 
                                  gng_err_robust$`location:power`$pval, gng_err_robust$`location:balance`$pval,
                                  gng_err_robust$`power:balance`$pval, gng_err_robust$`location:cue`$pval, 
                                  gng_err_robust$`power:cue`$pval, gng_err_robust$`balance:cue`$pval, 
                                  gng_err_robust$`location:power:balance`$pval,
                                  gng_err_robust$`location:power:cue`$pval,
                                  gng_err_robust$`location:balance:cue`$pval, 
                                  gng_err_robust$`power:balance:cue`$pval, 
                                  gng_err_robust$`location:power:balance:cue`$pval))
  
  # bind the data into 1 data frame
  gng_err_robust_table = as.data.frame(cbind(gng_err_robust_dfn, gng_err_robust_dfd, gng_err_robust_WJ, gng_err_robust_pval))
    # add columns: (1) to denote the effect, and (2) to denote significance at p < .05 
    gng_err_robust_table = cbind(names(gng_err_robust)[1:15], 
                                 gng_err_robust_table, c(rep("", length(gng_err_robust_pval))))
    colnames(gng_err_robust_table) = c("Effect","DFn", "DFd", "WJ Stat", "p", "p < .05")
    rownames(gng_err_robust_table) = NULL
  
# show ANOVA results in kable table 
kable(gng_err_robust_table, caption = "3x2x2 Robust Mixed ANOVA on Omission Error in the Go/No-Go Task", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) 

3x2x2 Robust Mixed ANOVA on Omission Error in the Go/No-Go Task
Effect DFn DFd WJ Stat p p < .05
location 2 117.2240 1.2612 0.2871
power 1 193.6793 0.9055 0.3425
balance 1 193.6793 0.8056 0.3705
cue 1 193.6793 3.2994 0.0709
location:power 2 117.2240 0.3709 0.6909
location:balance 2 117.2240 0.8711 0.4212
power:balance 1 193.6793 0.5929 0.4423
location:cue 2 117.2240 0.5581 0.5738
power:cue 1 193.6793 0.9445 0.3323
balance:cue 1 193.6793 0.1864 0.6664
location:power:balance 2 117.2240 0.5014 0.6070
location:power:cue 2 117.2240 0.3900 0.6779
location:balance:cue 2 117.2240 0.4301 0.6515
power:balance:cue 1 193.6793 0.6245 0.4304
location:power:balance:cue 2 117.2240 0.5207 0.5955

NA
Visualizations

The following shows a visulization of the Go/No-Go omission error data based on the three factors: smartphone location, smartphone power, and cue type.

To visualize the mixed design, two plots were created (i.e. one for each cue type). Note: Since the balance factor (i.e. which task was completed first) did not have a significant main effect or interaction effect on the data, this factor is not visualized in the plots

#--FOR THE VERTICAL CUE TYPE-- 

# create data frame with location conditions as characters rather than intergers 
  # First, get a subset of the data
  gng_err_bar_v_data = gng_err_final[gng_err_final$cue == 1, c("location", "power", "gng_err_omi_long")]
    colnames(gng_err_bar_v_data) = c("location", "power", "err_omi")
    rownames(gng_err_bar_v_data) = NULL 
  # reformat location & power as factors  
  gng_err_bar_v_data$location = factor(gng_err_bar_v_data$location, 
                  levels = c(1, 2, 3),
                  labels = c("On Desk", "Pocket/Bag", "Outside"))
  gng_err_bar_v_data$power = factor(gng_err_bar_v_data$power, 
                  levels = c(1, 2),
                  labels = c("ON", "OFF"))
       
# create plot
gng_err_bar_v = ggplot(gng_err_bar_v_data, aes(x = location, y = err_omi, fill = power), show.legend = FALSE) +
  geom_bar(stat = "summary", fun.y = "mean", position = "dodge") + 
    guides(shape = FALSE) + 
  scale_fill_manual(values = c("cadetblue3", "deepskyblue4")) + 
  labs(title = "Performance on the Go/No-Go Task: 'Vertical' Cue Type",
       subtitle = "Omission Errors",
       x = "Smartphone Location", 
       y = "Omission Error", 
       fill = "Smartphone Power",
       caption = paste0(strwrap("Figure X. Distributions of scores on the vertical cue type on the Cue-Dependent Go/No-Go Task, arranged by smartphone location (along the x-axis) and smartphone power (different bars). Omission errors occurred when a participant failed to respond to a non-target stimulus. Coloured dots represent individual data points. Black dots and error bars depict means and standard errors, respectively.", width = 80), collapse = "\n")) +
        # the "\n" here denote that you want a new line formed in the text
  scale_y_continuous(limits = c(min(gng_err_bar_v_data$err_omi), max(gng_err_bar_v_data$err_omi))) +
  #scale_colour_manual(values = cols) +
  geom_point(stat = "identity", aes(color = power), size = 1, 
             position = position_jitterdodge(jitter.width = .53), show.legend = FALSE) +
  scale_color_manual(values = c("deepskyblue4", "purple4")) + 
  geom_point(stat="summary", fun.y="mean", position = position_dodge(.9), size = 1.5, show.legend = FALSE) +
  geom_errorbar(data = gng_err_bar_v_data, stat = "summary", fun.ymin = function(x) mean(x) - sd(x)/sqrt(length(x)), 
                fun.ymax = function(x) mean(x) + sd(x)/sqrt(length(x)), size= .5, width= .25, position = position_dodge(.9)) +
  theme_classic() +
  theme(plot.title = element_text(color = "black", size = 14, face = "bold"), 
        plot.subtitle = element_text(color = "black", size = 13), 
        plot.caption = element_text(hjust = 0, size = 12, face = "italic"),
        text = element_text(size = 13))

#--FOR THE HORIZONTAL CUE TYPE-- 

# create data frame with location conditions as characters rather than intergers 
  # First, get a subset of the data
  gng_err_bar_h_data = gng_err_final[gng_err_final$cue == 2, c("location", "power", "gng_err_omi_long")]
    colnames(gng_err_bar_h_data) = c("location", "power", "err_omi")
    rownames(gng_err_bar_h_data) = NULL 
  # reformat location & power as factors  
  gng_err_bar_h_data$location = factor(gng_err_bar_h_data$location, 
                  levels = c(1, 2, 3),
                  labels = c("On Desk", "Pocket/Bag", "Outside"))
  gng_err_bar_h_data$power = factor(gng_err_bar_h_data$power, 
                  levels = c(1, 2),
                  labels = c("ON", "OFF"))
       
# create plot
gng_err_bar_h = ggplot(gng_err_bar_h_data, aes(x = location, y = err_omi, fill = power), show.legend = FALSE) +
  geom_bar(stat = "summary", fun.y = "mean", position = "dodge") + 
    guides(shape = FALSE) + 
  scale_fill_manual(values = c("cadetblue3", "deepskyblue4")) + 
  labs(title = "Performance on the Go/No-Go Task: 'Horizontal' Cue Type",
       subtitle = "Omission Errors",
       x = "Smartphone Location", 
       y = "Omission Error", 
       fill = "Smartphone Power",
       caption = paste0(strwrap("Figure X. Distributions of scores on the horizontal cue type on the Cue-Dependent Go/No-Go Task, arranged by smartphone location (along the x-axis) and smartphone power (different bars). Omission errors occurred when a participant failed to respond to a non-target stimulus. Coloured dots represent individual data points. Black dots and error bars depict means and standard errors, respectively.", width = 80), collapse = "\n")) +
        # the "\n" here denote that you want a new line formed in the text
  scale_y_continuous(limits = c(min(gng_err_bar_h_data$err_omi), max(gng_err_bar_h_data$err_omi))) +
  #scale_colour_manual(values = cols) +
  geom_point(stat = "identity", aes(color = power), size = 1, 
             position = position_jitterdodge(jitter.width = .53), show.legend = FALSE) +
  scale_color_manual(values = c("deepskyblue4", "purple4")) + 
  geom_point(stat="summary", fun.y="mean", position = position_dodge(.9), size = 1.5, show.legend = FALSE) +
  geom_errorbar(data = gng_err_bar_h_data, stat = "summary", fun.ymin = function(x) mean(x) - sd(x)/sqrt(length(x)), 
                fun.ymax = function(x) mean(x) + sd(x)/sqrt(length(x)), size= .5, width= .25, position = position_dodge(.9)) +
  theme_classic() +
  theme(plot.title = element_text(color = "black", size = 14, face = "bold"), 
        plot.subtitle = element_text(color = "black", size = 13), 
        plot.caption = element_text(hjust = 0, size = 12, face = "italic"),
        text = element_text(size = 13))

# Show plots
  # for the Vertical cue type
  gng_err_bar_v

  # for the Horizontal cue type
  gng_err_bar_h

NA
NA

Accuracy Analysis

A 3(smartphone location: desk, pocket/bag, outside) x 2(smartphone power: ON, OFF) between-subjects ANOVA was completed (DV = average RT). The between-subjects factors were smartphone location and power.

Prior to completing the analysis, planned exclusion critera was applied to the data. Exclusion criteria for this analysis helped to control for any participants who did not follow the instructions. Any participants who had a reaction time that was higher than two standard deviations (SD) from the mean reaction time were not included in the final analysis.

  • Exclude data from any partitipants with (1) missing data and/or (2) the reaction time SD criteria (i.e. within two standard devations from the mean RT). There was a total of 395 participants in the Go/No-Go Error analysis.
    • Missing Data: 3 participants were removed due to missing data (note: this also removed data from participants who did not response during the task).
    • Reaction Time SD Criteria: 11 participants were removed because they did not meet the raction time SD criteria. The number of participants removed with respect to their smartphone location and power conditions was as follows:
      • For the power “on” condition: 3 (on desk), 2 (pocket/bag), 1 (outside)
      • For the power “off” condition: 1 (on desk), 4 (pocket/bag), 0 (outside)

# filter any participants with missing data or that do not meet the inclusionn criteria

  # for all ps, excluding any p with missing data in the average reaction time column (gng_rt_av)
  # Note: this also removed participants who did not respond at all during the task
  gng_ac_noNA = gng_ac_analysis[!is.na(gng_ac_analysis$gng_rt_av),]
  
  # for all ps, excluding any that did not meet the reaction time deviation criteria (i.e. within two standard devations from the mean RT)
  # get the mean RT with all the data included, divided by their respective smartphone condition (i.e. either location or power)
    # get the descriptive of the data
    gng_ac_noNA_des = psych::describeBy(gng_ac_noNA, list(gng_ac_noNA$location, gng_ac_noNA$power), mat = TRUE)
    # find the inclusion criteria for each condition (M - 2*SD)
      # power = ON 
        # location = "on desk"
        gng_ac_criteria1 = gng_ac_noNA_des["gng_rt_av1","mean"] + (gng_ac_noNA_des["gng_rt_av1","sd"] * 2)
        # location = "pocket/bag"
        gng_ac_criteria2 = gng_ac_noNA_des["gng_rt_av2","mean"] + (gng_ac_noNA_des["gng_rt_av2","sd"] * 2)
        # location = "outside"
        gng_ac_criteria3 = gng_ac_noNA_des["gng_rt_av3","mean"] + (gng_ac_noNA_des["gng_rt_av3","sd"] * 2)
      # power = OFF 
        # location = "on desk"
        gng_ac_criteria4 = gng_ac_noNA_des["gng_rt_av4","mean"] + (gng_ac_noNA_des["gng_rt_av4","sd"] * 2)
        # location = "pocket/bag"
        gng_ac_criteria5 = gng_ac_noNA_des["gng_rt_av5","mean"] + (gng_ac_noNA_des["gng_rt_av5","sd"] * 2)
        # location = "outside"
        gng_ac_criteria6 = gng_ac_noNA_des["gng_rt_av6","mean"] + (gng_ac_noNA_des["gng_rt_av6","sd"] * 2)
    # find the participants to remove from the data 
      # power = ON 
        # location = "on desk"
        gng_ac_remove1 = (gng_ac_noNA %>% filter(location == 1 & power == 1 & gng_rt_av > gng_ac_criteria1))[,"participant"]
        # location = "pocket/bag"
        gng_ac_remove2 = (gng_ac_noNA %>% filter(location == 2 & power == 1 & gng_rt_av > gng_ac_criteria2))[,"participant"]
        # location = "outside"
        gng_ac_remove3 = (gng_ac_noNA %>% filter(location == 3 & power == 1 & gng_rt_av > gng_ac_criteria3))[,"participant"]
      # power = OFF 
        # location = "on desk"
        gng_ac_remove4 = (gng_ac_noNA %>% filter(location == 1 & power == 2 & gng_rt_av > gng_ac_criteria4))[,"participant"]
        # location = "pocket/bag"
        gng_ac_remove5 = (gng_ac_noNA %>% filter(location == 2 & power == 2 & gng_rt_av > gng_ac_criteria5))[,"participant"]
        # location = "outside"
        gng_ac_remove6 = (gng_ac_noNA %>% filter(location == 3 & power == 3 & gng_rt_av > gng_ac_criteria6))[,"participant"]
    # make a list of all the participant to remove from the data
      gng_ac_all_remove = dplyr::arrange(data.frame("remove" = as.numeric(c(gng_ac_remove1, gng_ac_remove2, gng_ac_remove3, gng_ac_remove4, gng_ac_remove5, gng_ac_remove6))), remove)
        # note: this code also re-orders the list from smallest to largest
  # Filter the data using the final remove list 
  gng_ac_final = dplyr::filter(gng_ac_noNA, !participant %in% gng_ac_all_remove$remove)
Descriptive Statistics

The following table depicts the descriptive statistics for the Go/No-Go Accuracy Analysis: the mean (M), standard deviation (SD), minimum score (min.), maximum score (max.), and the sample size (n).


# create a data frame with the descriptives of all the data, grouped by the location & power conditions
  # this creates information for the 6 possible combined conditions
  gng_ac_des = psych::describeBy(gng_ac_final, list(gng_ac_final$location, gng_ac_final$power), mat = TRUE)  
  
# organize the data into a new data frame depicting the M, SD, min., max., and n.
  gng_ac_des_t = rbind((cbind(t(gng_ac_des["gng_rt_av1",c("mean", "sd", "min", "max", "n")]),
                             t(gng_ac_des["gng_rt_av2",c("mean", "sd", "min", "max", "n")]),
                             t(gng_ac_des["gng_rt_av3",c("mean", "sd", "min", "max", "n")]))), 
                      (cbind(t(gng_ac_des["gng_rt_av4",c("mean", "sd", "min", "max", "n")]),
                             t(gng_ac_des["gng_rt_av5",c("mean", "sd", "min", "max", "n")]),
                             t(gng_ac_des["gng_rt_av6",c("mean", "sd", "min", "max", "n")]))))
    colnames(gng_ac_des_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(gng_ac_des_t) = rep(c("M", "SD", "min.", "max.", "n"), 2)
    
# use kable to show the descriptives table
  kable(gng_ac_des_t, caption = "Descriptive Statistics: Reaction Time (sec.) on the Go/No-Go Task", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
  add_header_above(c(" ", "Smartphone Location" = 3)) %>%
  group_rows(index = c("Smartphone Power ON" = 5, "Smartphone Power OFF" = 5))

Descriptive Statistics: Reaction Time (sec.) on the Go/No-Go Task
Smartphone Location
On Desk In Pocket/Bag Outside
Smartphone Power ON
M 1.6553 1.6617 1.6608
SD 0.0405 0.0516 0.0412
min. 1.5783 1.5618 1.5600
max. 1.7555 1.7730 1.7449
n 70.0000 70.0000 65.0000
Smartphone Power OFF
M 1.6579 1.6506 1.6608
SD 0.0574 0.0511 0.0623
min. 1.5690 1.5604 1.5635
max. 1.8442 1.7749 1.8688
n 60.0000 64.0000 66.0000

NA
Analysis

To assess if the reaction time statistically differed, we conducted a 3x2 ANOVA with the between-subjects factors of smartphone location (i.e. on desk, in pocket/bag, or outside) and power (i.e. on or off). Since there are unequal sample sizes, we used Type III sum of squares.

Assumptions

The ANOVA made three assumptions. The independent random sampling and normality assumptions were met. The homogeneity of variance assumption was not met, therefore, a White correction was done for the relevant effect. (click to see details).

1. Independent Random Sampling

This assumption was met during testing.

2. Normality

This assumption was tested by visualizing the residuals, applying a Shapiro-Wilk test to the resdiuals, and observing the Skewness and Kurtosis of the data (extracted from the ANOVA output).


# get the required data from the ospan_analysis data: participant, location, power, and score
gng_ac_anova_data = gng_ac_final[, c("participant", "location", "power", "balance", "gng_rt_av")]
    colnames(gng_ac_anova_data) = c("participant", "location", "power", "balance", "rt_av")
    rownames(gng_ac_anova_data) = NULL
    # reformat location,  power, and balance as factors  
    gng_ac_anova_data$location = factor(gng_ac_anova_data$location, 
                  levels = c(1, 2, 3),
                  labels = c("On Desk", "Pocket/Bag", "Outside"))
    gng_ac_anova_data$power = factor(gng_ac_anova_data$power, 
                  levels = c(1, 2),
                  labels = c("ON", "OFF"))
    gng_ac_anova_data$balance = factor(gng_ac_anova_data$balance, 
                  levels = c(1, 2),
                  labels = c("Ospan First", "Go/No-Go First"))

# run between-subjects ANOVA (IV: Smartphone Power & Location, Balance; DV: OSpan Abolute Score)
gng_ac_anova = ezANOVA(
  data = gng_ac_anova_data
  , dv = .(rt_av)
  , wid = .(participant)
  , between = .(location, power, balance)
  , type = 3 # unequal sample sizes, therfore use type 3
  , detailed = TRUE
  , return_aov = TRUE
)

# calculate & extract the residuals from the ANOVA
gng_ac_res = data.frame("residuals" = proj(gng_ac_anova$aov)[,"Residuals"])   
  • It appears that the residuals lie closely to a straight line, which suggests normality (see visualization below).

qqnorm(gng_ac_res$residuals, main = "Q-Q Plot of the Go/No-Go Reaction Time Residuals") 
qqline(gng_ac_res$residuals)

  • It appears that residuals tend to follow the shape of a normal distribution, with a slight skew to the left and some data on the far right (see visualization below).

qplot(gng_ac_res$residuals, main = "Histogram of Go/No-Go Reaction Time Residuals") + 
  theme_classic()

  • The Shapiro-Wilk test of normality was significant (based on \(\alpha = 0.05\)), W = 0.98, p < .001 (see code below).

gng_ac_shap = shapiro.test(gng_ac_res$residuals)
gng_ac_shap

    Shapiro-Wilk normality test

data:  gng_ac_res$residuals
W = 0.97715, p-value = 6.914e-06
  • The data’s Skewness and Kurtosis was examined and showed that both the Skewness (range: -0.02 to 1.38) and Kurtosis (range: -0.88 to 1.83) were within the acceptable range of \(\pm 2.0\) and \(\pm 9.0\), respectively (Schmider, Ziegler, Danay, Beyer, & Bühner, 2010) (see table below).
# use the "gng_ac_des" data frame from the descriptives

# organize the data into a new data frame depicting the Skew, kurtosis, and sample size (n).
  gng_ac_sk_t = rbind((cbind(t(gng_ac_des["gng_rt_av1", c("skew", "kurtosis", "n")]),
                             t(gng_ac_des["gng_rt_av2", c("skew", "kurtosis", "n")]),
                             t(gng_ac_des["gng_rt_av3", c("skew", "kurtosis", "n")]))), 
                      (cbind(t(gng_ac_des["gng_rt_av4", c("skew", "kurtosis", "n")]),
                             t(gng_ac_des["gng_rt_av5", c("skew", "kurtosis", "n")]),
                             t(gng_ac_des["gng_rt_av6", c("skew", "kurtosis", "n")]))))
    colnames(gng_ac_sk_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(gng_ac_sk_t) = rep(c("Skewness", "Kurtosis", "n"), 2)
    
# use kable to show the descriptives table
  kable(gng_ac_sk_t, caption = "Skewness and Kurtosis of the Reaction Time on the Go/No-Go Task", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
  add_header_above(c(" ", "Smartphone Location" = 3)) %>%
  group_rows(index = c("Smartphone Power ON" = 3, "Smartphone Power OFF" = 3))

Skewness and Kurtosis of the Reaction Time on the Go/No-Go Task
Smartphone Location
On Desk In Pocket/Bag Outside
Smartphone Power ON
Skewness 0.3923 0.2726 -0.0191
Kurtosis -0.4925 -0.8790 -0.4936
n 70.0000 70.0000 65.0000
Smartphone Power OFF
Skewness 1.3850 0.4283 0.7265
Kurtosis 1.8330 -0.5305 0.2687
n 60.0000 64.0000 66.0000

NA
  • Therefore, based on all the normality assumption checks, normality was assumed to be within the acceptable range for the ANOVA analysis. Additionally, it should be noted that ANOVA analyses can be robust to violations of normality (Gardner & Tremblay, 2007).

3. Homogeneity of Variance

This assumption was tested by conducting Levene’s Test for Homogeneity of Variance for each between-subjects variable (i.e. smartphone location and smartphone power).

  • The homogeneity assumption was met (based on \(\alpha = 0.05\)) for smartphone location, F(2, 392) = 1.12, p = .33 and balance, F(1, 393) = 2.33, p = .13. However, the homogeneity assumption was not met for smartphone power, F(1, 393) = 5.81, p = .02 (see code below).

# conduct levene's
  # for location
  gng_ac_lev_loc = leveneTest(data = gng_ac_anova_data, rt_av ~ as.factor(location), center = median)
  gng_ac_lev_loc
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group   2   1.119 0.3276
      392               
  # for power
  gng_ac_lev_pow = leveneTest(data = gng_ac_anova_data, rt_av ~ as.factor(power), center = median)
  gng_ac_lev_pow
Levene's Test for Homogeneity of Variance (center = median)
       Df F value  Pr(>F)  
group   1  5.8139 0.01636 *
      393                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
  # for balance
  gng_ac_lev_bal = leveneTest(data = gng_ac_anova_data, rt_av ~ as.factor(balance), center = median)
  gng_ac_lev_bal
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group   1  2.3327 0.1275
      393               
  • The homogeneity of variance assumption was not met for the smarphone power condition. Therefore, considering there are unequal sample sizes, a White-corrected F-test was conducted (i.e. if interested in assessing the main effect of power).
# run the corrected ANOVA (IV: Smartphone Power & Location, Balance; DV: OSpan Abolute Score)
# this will be used to report the main effect of smartphone power only 
gng_ac_anova_cor = ezANOVA(
  data = gng_ac_anova_data
  , dv = .(rt_av)
  , wid = .(participant)
  , between = .(location, power, balance)
  , type = 3 # unequal sample sizes, therfore use type 3
  , detailed = TRUE
  , return_aov = TRUE
  , white.adjust = TRUE
)

# Calculate effect size:
# this will be used to report the main effect of smartphone power only 
gng_ac_pow_es = (EtaSq(gng_ac_anova$aov, type = 3, anova = FALSE))[2]
Results

All results were based on \(\alpha = 0.05\). Below are the reported statistics for the main effects and the interactions, followed by a table depicting the ANOVA results.

Main Effect of Smartphone Location

There was no significant main effect of smartphone location on reaction time, F(2, 383) = 0.7, p = .5, \(\eta^{2}\) = .004.

Main Effect of Smartphone Power

There was no significant main effect of smartphone power on reaction time, F(1, 383) = 0.81, p = .37, \(\eta^{2}\) = .01.

Interaction of Balance

There was no significant main effect of balance (i.e. which task was completed first) on reaction time, F(1, 383) = 0.06, p = .8, \(\eta^{2}\) < .001.

Interaction of Smartphone Location & Smartphone Power

There was no significant interaction between smartphone location and smartphone power on reaction time, F(2, 383) = 0.33, p = .72, \(\eta^{2}\) = .002.

Interaction of Smartphone Location & Balance

There was no significant interaction between smartphone location and balance (i.e. which task was completed first) on reaction time, F(2, 383) = 2.07, p = .13, \(\eta^{2}\) = .01.

Interaction of Smartphone Power & Balance

There was no significant interaction between smartphone power and balance (i.e. which task was completed first) on reaction time, F(1, 383) = 1.46, p = .23, \(\eta^{2}\) = .004.

Interaction of Smartphone Location, Smartphone Power, & Balance

There was a significant interaction between smartphone location, smartphone power, and balance (i.e. which task was completed first) on reaction time, F(2, 383) = 5.49, p = .004, \(\eta^{2}\) = .03.

Post-hoc Tests

Since there was a significant three-way interaction (i.e smartphone location, smartphone power, and balance), further analyses were completed (see “Post-Hocs: Simple Two-Way Interactions” below).


# create a table with the anova results including the corrected values for the main effect of power (i.e. since it did not meet the homogeneity of variance assumption)
  # get the original anova data
  gng_ac_t = gng_ac_anova$ANOVA
    # since the corrected data does not have the SS, remove these columns from the original ANOVA table
    gng_ac_t = dplyr::select(gng_ac_t, -SSn, -SSd)
    # chance the data for the main effect of power to corrected numbers
    gng_ac_t[gng_ac_t$Effect == "power",] = c(gng_ac_anova_cor$ANOVA[3,], gng_ac_pow_es)
# show ANOVA results in kable table 
kable(gng_ac_t, caption = "3x2x2 ANOVA on Go/No-Go Reaction Time", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) 

3x2x2 ANOVA on Go/No-Go Reaction Time
Effect DFn DFd F p p<.05 ges
(Intercept) 1 383 417915.0714 0.0000 * 0.9991
location 2 383 0.7043 0.4951 0.0037
power 1 383 0.8121 0.3681 0.0084
balance 1 383 0.0649 0.7991 0.0002
location:power 2 383 0.3301 0.7190 0.0017
location:balance 2 383 2.0740 0.1271 0.0107
power:balance 1 383 1.4648 0.2269 0.0038
location:power:balance 2 383 5.4934 0.0044 * 0.0279

NA
Post-Hocs: Simple Two-Way Interactions

A three-way interaction (i.e. between smartphone location, smartphone power, and balance) suggested that a two-way interaction operated differently depending on the levels of the third factor. In order to interpret this complex interaction, the data was broken down into a subset based on the levels of one of the factors (i.e. “simple two-way interactions”).

The main manipulation in the present study was smartphone location and power, additionally, the balance factor was designed to provide an experimental control for the counter-balanced task order. Therefore, the simple two-way interactions of the smartphone factors (i.e. location and power) were assessed at each level of balance (i.e. OSpan first and Go/No-Go first). Although this required two more analyses, this approach allowed us to disentangle the three-way interaction and therefore interpret where the differences were among the factors. Two new data sets were created for the simple two-way interactions: (1) for the OSpan First Data (gng_ac_ospan_data) and (2) for the Go/No-Go First Data (gng_ac_gng_data).


# get a subset of the gng_ac_anova_data
  # for the OSpan first balance group only
  gng_ac_ospan_data = gng_ac_anova_data[gng_ac_anova_data$balance == "Ospan First", ]

  # for the Go/No-Go first balance group only
  gng_ac_gng_data = gng_ac_anova_data[gng_ac_anova_data$balance == "Go/No-Go First", ]

In order to control for multiple comparisons, a Bonferroni adjustment was used on the p-values to determine significance. This adjustment was completed by dividing the current alpha level (\(\alpha = 0.05\)) by the number of simple two-way interactions being compuetd (i.e. 2), therefore, the the bonferroni-corrected alpha value for statistical significance was 0.025.

OSpan First: Descriptive Statistics

The first simple two-way interaction ANOVA was completed using the “OSpan First” subset of the Balance Factor (i.e. participants who completed the OSpan task first, then the Go/No-Go task). As in the main 3-way ANOVA, the between-subjects factors were smartphone location (i.e. desk, pocket/bag or outside) and power (i.e. ON or OFF), and the dependent variable was accuracy (i.e. average reaction time).

There was a total of 180 participants in the OSpan First analysis. The following table depicts the descriptive statistics: the mean (M), standard deviation (SD), minimum score (min.), maximum score (max.), and the sample size (n).


# create a data frame with the descriptives of all the data, grouped by the location & power conditions
  # this creates information for the 6 possible combined conditions
  gng_ac_ospan_des = psych::describeBy(gng_ac_ospan_data, list(gng_ac_ospan_data$location, gng_ac_ospan_data$power), mat = TRUE)  

# organize the data into a new data frame depicting the M, SD, min., max., and n.
  gng_ac_ospan_des_t = rbind((cbind(t(gng_ac_ospan_des["rt_av1", c("mean", "sd", "min", "max", "n")]),
                             t(gng_ac_ospan_des["rt_av2", c("mean", "sd", "min", "max", "n")]),
                             t(gng_ac_ospan_des["rt_av3", c("mean", "sd", "min", "max", "n")]))), 
                      (cbind(t(gng_ac_ospan_des["rt_av4", c("mean", "sd", "min", "max", "n")]),
                             t(gng_ac_ospan_des["rt_av5", c("mean", "sd", "min", "max", "n")]),
                             t(gng_ac_ospan_des["rt_av6", c("mean", "sd", "min", "max", "n")]))))
    colnames(gng_ac_ospan_des_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(gng_ac_ospan_des_t) = rep(c("M", "SD", "min.", "max.", "n"), 2)
  
# use kable to show the descriptives table
  kable(gng_ac_ospan_des_t, caption = "Ospan First Descriptive Statistics: Reaction Time (sec.) on the Go/No-Go Task", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
  add_header_above(c(" ", "Smartphone Location" = 3)) %>%
  group_rows(index = c("Smartphone Power ON" = 5, "Smartphone Power OFF" = 5))

Ospan First Descriptive Statistics: Reaction Time (sec.) on the Go/No-Go Task
Smartphone Location
On Desk In Pocket/Bag Outside
Smartphone Power ON
M 1.6590 1.6547 1.6726
SD 0.0402 0.0539 0.0378
min. 1.5864 1.5802 1.6030
max. 1.7555 1.7730 1.7431
n 34.0000 31.0000 27.0000
Smartphone Power OFF
M 1.6343 1.6612 1.6585
SD 0.0242 0.0486 0.0595
min. 1.5906 1.5889 1.5723
max. 1.6867 1.7749 1.7820
n 24.0000 32.0000 32.0000

NA
OSpan First: Assumptions

The two-way interaction made three assumptions. The independent random sampling and normality assumptions were met. The homogeneity of variance assumption was not met, therefore, a White correction was done for the relevant effect. (click to see details).

1. Independent Random Sampling

This assumption was met during testing.

2. Normality

This assumption was tested by visualizing the residuals, applying a Shapiro-Wilk test to the resdiuals, and observing the Skewness and Kurtosis of the data (extracted from the ANOVA output).


# run between-subjects ANOVA (IV: Smartphone Power & Location; DV: OSpan Abolute Score)
gng_ac_ospan_anova = ezANOVA(
  data = gng_ac_ospan_data
  , dv = .(rt_av)
  , wid = .(participant)
  , between = .(location, power)
  , type = 3 # unequal sample sizes, therfore use type 3
  , detailed = TRUE
  , return_aov = TRUE
  )
  
# calculate & extract the residuals from the ANOVA
gng_ac_ospan_res = data.frame("residuals" = proj(gng_ac_ospan_anova$aov)[,"Residuals"])  
  • It appears that the residuals lie closely to a straight line, which suggests normality (see visualization below).

qqnorm(gng_ac_ospan_res$residuals, main = "Q-Q Plot of the Go/No-Go Reaction Time Residuals for the OSpan First Group") 
qqline(gng_ac_ospan_res$residuals)

  • It appears that residuals tend to follow the shape of a normal distribution (see visualization below).

qplot(gng_ac_ospan_res$residuals, main = "Histogram of Go/No-Go Reaction Time Residuals for the OSpan First Group") + 
  theme_classic()

  • The Shapiro-Wilk test of normality was significant (based on \(\alpha = 0.05\)), W = 0.98, p = .004 (see code below).

gng_ac_ospan_shap = shapiro.test(gng_ac_ospan_res$residuals)
gng_ac_ospan_shap

    Shapiro-Wilk normality test

data:  gng_ac_ospan_res$residuals
W = 0.97676, p-value = 0.004195
  • The data’s Skewness and Kurtosis was examined and showed that both the Skewness (range: 0.02 to 0.49) and Kurtosis (range: -1.17 to -0.46) were within the acceptable range of \(\pm 2.0\) and \(\pm 9.0\), respectively (Schmider, Ziegler, Danay, Beyer, & Bühner, 2010) (see table below).

# use the descriptives data -- gng_ac_ospan_des

# organize the data into a new data frame depicting the Skew, kurtosis, and sample size (n).
  gng_ac_ospan_sk_t = rbind((cbind(t(gng_ac_ospan_des["rt_av1", c("skew", "kurtosis", "n")]),
                             t(gng_ac_ospan_des["rt_av2", c("skew", "kurtosis", "n")]),
                             t(gng_ac_ospan_des["rt_av3", c("skew", "kurtosis", "n")]))), 
                      (cbind(t(gng_ac_ospan_des["rt_av4", c("skew", "kurtosis", "n")]),
                             t(gng_ac_ospan_des["rt_av5", c("skew", "kurtosis", "n")]),
                             t(gng_ac_ospan_des["rt_av6", c("skew", "kurtosis", "n")]))))
    colnames(gng_ac_ospan_sk_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(gng_ac_ospan_sk_t) = rep(c("Skewness", "Kurtosis", "n"), 2)
    
# use kable to show the descriptives table
  kable(gng_ac_ospan_sk_t, caption = "Skewness and Kurtosis of the Reaction Time on the Go/No-Go Task for the OSpan First Group", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
  add_header_above(c(" ", "Smartphone Location" = 3)) %>%
  group_rows(index = c("Smartphone Power ON" = 3, "Smartphone Power OFF" = 3))

Skewness and Kurtosis of the Reaction Time on the Go/No-Go Task for the OSpan First Group
Smartphone Location
On Desk In Pocket/Bag Outside
Smartphone Power ON
Skewness 0.4543 0.4852 0.0235
Kurtosis -0.4591 -0.8623 -0.9030
n 34.0000 31.0000 27.0000
Smartphone Power OFF
Skewness 0.2582 0.4521 0.3469
Kurtosis -0.6946 -0.6692 -1.1674
n 24.0000 32.0000 32.0000

NA
  • Therefore, based on all the normality assumption checks, normality was assumed to be within the acceptable range for the analysis. Additionally, it should be noted that ANOVA analyses can be robust to violations of normality (Gardner & Tremblay, 2007).

3. Homogeneity of Variance

This assumption was tested by conducting Levene’s Test for Homogeneity of Variance for each between-subjects variable (i.e. smartphone location and smartphone power).

  • The homogeneity assumption was met (based on \(\alpha = 0.05\)) for smartphone power, F(1, 178) = 0.33, p = .57. However, the homogeneity assumption was not met for smartphone location, F(2, 177) = 4.42, p = .01 (see code below).

# conduct levene's
  # for location
  gng_ac_ospan_lev_loc = leveneTest(data = gng_ac_ospan_data, rt_av ~ as.factor(location), center = median)
  gng_ac_ospan_lev_loc
Levene's Test for Homogeneity of Variance (center = median)
       Df F value  Pr(>F)  
group   2  4.4174 0.01342 *
      177                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
  # for power
  gng_ac_ospan_lev_pow = leveneTest(data = gng_ac_ospan_data, rt_av ~ as.factor(power), center = median)
  gng_ac_ospan_lev_pow
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group   1  0.3272  0.568
      178               
  • The homogeneity of variance assumption was not met for the smartphone location condition. Therefore, considering there were unequal sample sizes, a White-corrected F-test was conducted (i.e. if interested in assessing the main effect of location).
# run the corrected ANOVA (IV: Smartphone Power & Location; DV: Go/No-Go RT)
# this will be used to report the main effect of smartphone power only  
gng_ac_ospan_anova_cor = ezANOVA(
  data = gng_ac_ospan_data
  , dv = .(rt_av)
  , wid = .(participant)
  , between = .(location, power)
  , type = 3 # unequal sample sizes, therfore use type 3
  , detailed = TRUE
  , return_aov = TRUE
  , white.adjust = TRUE
)

# Calculate effect size:
# this will be used to report the main effect of smartphone power only 
gng_ac_ospan_loc_es = (EtaSq(gng_ac_ospan_anova_cor$aov, type = 3, anova = FALSE))[2]
OSpan First: Results

All results were based on \(\alpha_{adjusted} = 0.025\). Below are the reported statistics for the main and interaction effect of the simple two-way ANOVA, followed by a table depicting the ANOVA results.

Main Effect of Smartphone Location

There was no significant main effect of smartphone location on reaction time, F(2, 174) = 3.19, p = .04, \(\eta^{2}\) = .02.

Main Effect of Smartphone Power

There was no significant main effect of smartphone power on reaction time, F(1, 174) = 2.39, p = .12, \(\eta^{2}\) = .01.

Interaction of Smartphone Location & Smartphone Power

There was no significant interaction between smartphone location and smartphone power on reaction time, F(2, 174) = 1.76, p = .18, \(\eta^{2}\) = .02.

Post-hoc Tests

Since there was no significant main or interaction effects, no post-hocs were completed.


# create a table with the anova results including the corrected values for the main effect of power (i.e. since it did not meet the homogeneity of variance assumption)
  # get the original anova data
  gng_ac_ospan_t = gng_ac_ospan_anova$ANOVA
    # since the corrected data does not have the SS, remove these columns from the original ANOVA table
    gng_ac_ospan_t = dplyr::select(gng_ac_ospan_t, -SSn, -SSd)
    # change the data for the main effect of location to corrected numbers
    gng_ac_ospan_t[gng_ac_ospan_t$Effect == "location",] = c(gng_ac_ospan_anova_cor$ANOVA[2,], gng_ac_ospan_loc_es)
    # re-define the alpha value based on the bonferroni correction
      # rename the "p<.05" column appropriately -- "p<.025"
      colnames(gng_ac_ospan_t)[6] = "p<.025"
      # change values to fit the data
      gng_ac_ospan_t$`p<.025` = ifelse(gng_ac_ospan_t$p < .025, "*", "")
    
# show ANOVA results in kable table 
kable(gng_ac_ospan_t, caption = "OSpan First: Simple Two-Way Interaction on Reaction Time on the Go/No-Go Task", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) 

OSpan First: Simple Two-Way Interaction on Reaction Time on the Go/No-Go Task
Effect DFn DFd F p p<.025 ges
(Intercept) 1 174 226497.4374 0.0000 * 0.9992
location 2 174 3.1905 0.0436 0.0218
power 1 174 2.3946 0.1236 0.0136
location:power 2 174 1.7570 0.1756 0.0198

NA
Go/No-Go First: Descriptive Statistics

The second simple two-way interaction ANOVA was completed using the “Go/No-Go First” subset of the Balance Factor (i.e. participants who completed the Go/No-Go task first, then the OSpan task). As in the main 3-way ANOVA, the between-subjects factors were smartphone location (i.e. desk, pocket/bag or outside) and power (i.e. ON or OFF), and the dependent variable was accuracy (i.e. average reaction time).

There was a total of 215 participants in the Go/No-Go First analysis. The following table depicts the descriptive statistics: the mean (M), standard deviation (SD), minimum score (min.), maximum score (max.), and the sample size (n).


# create a data frame with the descriptives of all the data, grouped by the location & power conditions
  # this creates information for the 6 possible combined conditions
  gng_ac_gng_des = psych::describeBy(gng_ac_gng_data, list(gng_ac_gng_data$location, gng_ac_gng_data$power), mat = TRUE)  

# organize the data into a new data frame depicting the M, SD, min., max., and n.
  gng_ac_gng_des_t = rbind((cbind(t(gng_ac_gng_des["rt_av1", c("mean", "sd", "min", "max", "n")]),
                             t(gng_ac_gng_des["rt_av2", c("mean", "sd", "min", "max", "n")]),
                             t(gng_ac_gng_des["rt_av3", c("mean", "sd", "min", "max", "n")]))), 
                      (cbind(t(gng_ac_gng_des["rt_av4", c("mean", "sd", "min", "max", "n")]),
                             t(gng_ac_gng_des["rt_av5", c("mean", "sd", "min", "max", "n")]),
                             t(gng_ac_gng_des["rt_av6", c("mean", "sd", "min", "max", "n")]))))
    colnames(gng_ac_gng_des_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(gng_ac_gng_des_t) = rep(c("M", "SD", "min.", "max.", "n"), 2)
  
# use kable to show the descriptives table
  kable(gng_ac_gng_des_t, caption = "Go/No-Go First Descriptive Statistics: Reaction Time (sec.) on the Go/No-Go Task", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
  add_header_above(c(" ", "Smartphone Location" = 3)) %>%
  group_rows(index = c("Smartphone Power ON" = 5, "Smartphone Power OFF" = 5))

Go/No-Go First Descriptive Statistics: Reaction Time (sec.) on the Go/No-Go Task
Smartphone Location
On Desk In Pocket/Bag Outside
Smartphone Power ON
M 1.6519 1.6673 1.6525
SD 0.0411 0.0496 0.0419
min. 1.5783 1.5618 1.5600
max. 1.7472 1.7557 1.7449
n 36.0000 39.0000 38.0000
Smartphone Power OFF
M 1.6735 1.6399 1.6630
SD 0.0674 0.0522 0.0656
min. 1.5690 1.5604 1.5635
max. 1.8442 1.7667 1.8688
n 36.0000 32.0000 34.0000

NA
Go/No-Go First: Assumptions

The two-way interaction made three assumptions. The independent random sampling and normality assumptions were met. The homogeneity of variance assumption was not met, therefore, a White correction was done for the relevant effect. (click to see details).

1. Independent Random Sampling

This assumption was met during testing.

2. Normality

This assumption was tested by visualizing the residuals, applying a Shapiro-Wilk test to the resdiuals, and observing the Skewness and Kurtosis of the data (extracted from the ANOVA output).


# run between-subjects ANOVA (IV: Smartphone Power & Location; DV: OSpan Abolute Score)
gng_ac_gng_anova = ezANOVA(
  data = gng_ac_gng_data
  , dv = .(rt_av)
  , wid = .(participant)
  , between = .(location, power)
  , type = 3 # unequal sample sizes, therfore use type 3
  , detailed = TRUE
  , return_aov = TRUE
  )

# calculate & extract the residuals from the ANOVA
gng_ac_gng_res = data.frame("residuals" = proj(gng_ac_gng_anova$aov)[,"Residuals"])   
  • It appears that the residuals lie closely to a straight line, which suggests normality (see visualization below).

qqnorm(gng_ac_gng_res$residuals, main = "Q-Q Plot of the Go/No-Go Reaction Time Residuals for the Go/No-Go First Group") 
qqline(gng_ac_gng_res$residuals)

  • It appears that residuals tend to follow the shape of a normal distribution (see visualization below).

qplot(gng_ac_gng_res$residuals, main = "Histogram of Go/No-Go Reaction Time Residuals for the Go/No-Go First Group") + 
  theme_classic()

  • The Shapiro-Wilk test of normality was significant (based on \(\alpha = 0.05\)), W = 0.97, p < .001 (see code below).

gng_ac_gng_shap = shapiro.test(gng_ac_gng_res$residuals)
gng_ac_gng_shap

    Shapiro-Wilk normality test

data:  gng_ac_gng_res$residuals
W = 0.97149, p-value = 0.0002423
  • The data’s Skewness and Kurtosis was examined and showed that both the Skewness (range: 0.06 to 0.95) and Kurtosis (range: -0.88 to 0.88) were within the acceptable range of \(\pm 2.0\) and \(\pm 9.0\), respectively (Schmider, Ziegler, Danay, Beyer, & Bühner, 2010) (see table below).

# use the descriptives data -- gng_ac_gng_des

# organize the data into a new data frame depicting the Skew, kurtosis, and sample size (n).
  gng_ac_gng_sk_t = rbind((cbind(t(gng_ac_gng_des["rt_av1", c("skew", "kurtosis", "n")]),
                             t(gng_ac_gng_des["rt_av2", c("skew", "kurtosis", "n")]),
                             t(gng_ac_gng_des["rt_av3", c("skew", "kurtosis", "n")]))), 
                      (cbind(t(gng_ac_gng_des["rt_av4", c("skew", "kurtosis", "n")]),
                             t(gng_ac_gng_des["rt_av5", c("skew", "kurtosis", "n")]),
                             t(gng_ac_gng_des["rt_av6", c("skew", "kurtosis", "n")]))))
    colnames(gng_ac_gng_sk_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(gng_ac_gng_sk_t) = rep(c("Skewness", "Kurtosis", "n"), 2)
    
# use kable to show the descriptives table
  kable(gng_ac_gng_sk_t, caption = "Skewness and Kurtosis of the Reaction Time on the Go/No-Go Task for the Go/No-Go First Group", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
  add_header_above(c(" ", "Smartphone Location" = 3)) %>%
  group_rows(index = c("Smartphone Power ON" = 3, "Smartphone Power OFF" = 3))

Skewness and Kurtosis of the Reaction Time on the Go/No-Go Task for the Go/No-Go First Group
Smartphone Location
On Desk In Pocket/Bag Outside
Smartphone Power ON
Skewness 0.3417 0.1117 0.0623
Kurtosis -0.6968 -0.8811 -0.4550
n 36.0000 39.0000 38.0000
Smartphone Power OFF
Skewness 0.8433 0.5198 0.9459
Kurtosis 0.0585 -0.5200 0.8837
n 36.0000 32.0000 34.0000

NA
  • Therefore, based on all the normality assumption checks, normality was assumed to be within the acceptable range for the analysis. Additionally, it should be noted that ANOVA analyses can be robust to violations of normality (Gardner & Tremblay, 2007).

3. Homogeneity of Variance

This assumption was tested by conducting Levene’s Test for Homogeneity of Variance for each between-subjects variable (i.e. smartphone location and smartphone power).

  • The homogeneity assumption was met (based on \(\alpha = 0.05\)) for smartphone location, F(2, 212) = 0.03, p = .97. However, the homogeneity assumption was not met for smartphone power, F(1, 213) = 6.81, p = .01 (see code below).

# conduct levene's
  # for location
  gng_ac_gng_lev_loc = leveneTest(data = gng_ac_gng_data, rt_av ~ as.factor(location), center = median)
  gng_ac_gng_lev_loc
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group   2  0.0283 0.9721
      212               
  # for power
  gng_ac_gng_lev_pow = leveneTest(data = gng_ac_gng_data, rt_av ~ as.factor(power), center = median)
  gng_ac_gng_lev_pow
Levene's Test for Homogeneity of Variance (center = median)
       Df F value   Pr(>F)   
group   1   6.814 0.009687 **
      213                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
  • The homogeneity of variance assumption was not met for the smartphone power condition. Therefore, considering there were unequal sample sizes, a White-corrected F-test was conducted (i.e. if interested in assessing the main effect of power).
# run the corrected ANOVA (IV: Smartphone Power & Location ; DV: Go/No-Go RT)
# this will be used to report the main effect of smartphone power only  
gng_ac_gng_anova_cor = ezANOVA(
  data = gng_ac_gng_data
  , dv = .(rt_av)
  , wid = .(participant)
  , between = .(location, power)
  , type = 3 # unequal sample sizes, therfore use type 3
  , detailed = TRUE
  , return_aov = TRUE
  , white.adjust = TRUE
)

# Calculate effect size:
# this will be used to report the main effect of smartphone power only 
gng_ac_gng_loc_es = (EtaSq(gng_ac_gng_anova_cor$aov, type = 3, anova = FALSE))[2]
Go/No-Go First: Results

All results were based on \(\alpha = 0.025\). Below are the reported statistics for the main and interaction effect of the simple two-way ANOVA, followed by a table depicting the ANOVA results.

Main Effect of Smartphone Location

There was no significant main effect of smartphone location on reaction time, F(2, 209) = 0.51, p = .6, \(\eta^{2}\) = .005.

Main Effect of Smartphone Power

There was no significant main effect of smartphone power on reaction time, F(1, 209) = 0.05, p = .83, \(\eta^{2}\) = .01.

Interaction of Smartphone Location & Smartphone Power

There was a significant interaction between smartphone location and smartphone power on reaction time, F(2, 209) = 4.05, p = .02, \(\eta^{2}\) = .04.

Post-hoc Tests

Since there was a significant two-way interaction (i.e smartphone location and smartphone power), further analyses were completed (see “Simple Main Effects: Smartphone Location vs. Smartphone Power (for the Go/No-Go First Balance Group)” below).


# create a table with the anova results including the corrected values for the main effect of power (i.e. since it did not meet the homogeneity of variance assumption)
  # get the original anova data
  gng_ac_gng_t = gng_ac_gng_anova$ANOVA
    # since the corrected data does not have the SS, remove these columns from the original ANOVA table
    gng_ac_gng_t = dplyr::select(gng_ac_gng_t, -SSn, -SSd)
    # change the data for the main effect of location to corrected numbers
    gng_ac_gng_t[gng_ac_gng_t$Effect == "power",] = c(gng_ac_gng_anova_cor$ANOVA[3,], gng_ac_gng_loc_es)
    # re-define the alpha value based on the bonferroni correction
      # rename the "p<.05" column appropriately -- "p<.025"
      colnames(gng_ac_gng_t)[6] = "p<.025"
      # change values to fit the data
      gng_ac_gng_t$`p<.025` = ifelse(gng_ac_gng_t$p < 0.025, "*", "")
    
# show ANOVA results in kable table 
kable(gng_ac_gng_t, caption = "Go/No-Go First: Simple Two-Way Interaction on Reaction Time on the Go/No-Go Task", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) 

Go/No-Go First: Simple Two-Way Interaction on Reaction Time on the Go/No-Go Task
Effect DFn DFd F p p<.025 ges
(Intercept) 1 209 204027.9611 0.0000 * 0.9990
location 2 209 0.5138 0.5990 0.0049
power 1 209 0.0475 0.8277 0.0134
location:power 2 209 4.0527 0.0188 * 0.0373

NA
Simple Main Effects: Smartphone Location vs. Smartphone Power (for the Go/No-Go First Balance Group)

The simple two-way interaction showed that, when the Go/No-Go Task was completed first, there was a significant interaction between the smartphone conditions. In order to interpret this effect, simple main effects were completed investigating the effect of smartphone location at each level of smartphone power. Therefore, a simple one-way ANOVA for smartphone location was completed for each smartphone power condition separately.

Two new data sets were created for the simple two-way interactions: (1) for the Power ON Data (gng_ac_gng_ON_data) and (2) for the Power OFF Data (gng_ac_gng_OFF_data).


# get a subset of the gng_ac_gng_data
  # for the ON power group only
  gng_ac_gng_ON_data = gng_ac_gng_data[gng_ac_gng_data$power == "ON", ]

  # for the OFF power group only
  gng_ac_gng_OFF_data = gng_ac_gng_data[gng_ac_gng_data$power == "OFF", ]

To correct the family-wise error rate, a Holm-Bonferroni adjustment was used when assessing the significance of main effects associated with these ANOVAs. The Holm-Bonferroni adjustment defined a corrected alpha level according to the following formula: \[\alpha_{corrected} = \frac{\alpha}{number of comparisons − rank of comparison + 1}\]

Powered ON: Descriptive Statistics

The first simple main effect ANOVA was completed using the “Powered ON” subset of the Power Factor (i.e. participants who completed the Go/No-Go task first with their smartphones powered ON). The between-subjects factor was smartphone location (i.e. desk, pocket/bag or outside) and the dependent variable was accuracy (i.e. average reaction time).

There was a total of 113 participants in the Powered ON analysis. The following table depicts the descriptive statistics: the mean (M), standard deviation (SD), minimum score (min.), maximum score (max.), and the sample size (n).


# create a data frame with the descriptives of all the data, grouped by the location & power conditions
  # this creates information for the 6 possible combined conditions
  gng_ac_gng_ON_des = psych::describeBy(gng_ac_gng_ON_data, gng_ac_gng_ON_data$location, mat = TRUE)  

# organize the data into a new data frame depicting the M, SD, min., max., and n.
  gng_ac_gng_ON_des_t = cbind(t(gng_ac_gng_ON_des["rt_av1", c("mean", "sd", "min", "max", "n")]),
                              t(gng_ac_gng_ON_des["rt_av2", c("mean", "sd", "min", "max", "n")]),
                              t(gng_ac_gng_ON_des["rt_av3", c("mean", "sd", "min", "max", "n")]))
    colnames(gng_ac_gng_ON_des_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(gng_ac_gng_ON_des_t) = c("M", "SD", "min.", "max.", "n")
  
# use kable to show the descriptives table
  kable(gng_ac_gng_ON_des_t, caption = "Powered ON Descriptive Statistics: Reaction Time (sec.) on the Go/No-Go Task", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
  add_header_above(c(" ", "Smartphone Location" = 3))

Powered ON Descriptive Statistics: Reaction Time (sec.) on the Go/No-Go Task
Smartphone Location
On Desk In Pocket/Bag Outside
M 1.6519 1.6673 1.6525
SD 0.0411 0.0496 0.0419
min. 1.5783 1.5618 1.5600
max. 1.7472 1.7557 1.7449
n 36.0000 39.0000 38.0000

NA
Powered ON: Assumptions

The one-way simple main effect ANOVA made three assumptions. All assumptions were met. (click to see details).

1. Independent Random Sampling

This assumption was met during testing.

2. Normality

This assumption was tested by visualizing the residuals, applying a Shapiro-Wilk test to the resdiuals, and observing the Skewness and Kurtosis of the data (extracted from the ANOVA output).


# run between-subjects ANOVA (IV: Smartphone Power & Location; DV: OSpan Abolute Score)
gng_ac_gng_ON_anova = ezANOVA(
  data = gng_ac_gng_ON_data
  , dv = .(rt_av)
  , wid = .(participant)
  , between = .(location)
  , type = 3 # unequal sample sizes, therfore use type 3
  , detailed = TRUE
  , return_aov = TRUE
  )

# calculate & extract the residuals from the ANOVA
gng_ac_gng_ON_res = data.frame("residuals" = proj(gng_ac_gng_ON_anova$aov)[,"Residuals"])   
  • It appears that the residuals lie closely to a straight line, which suggests normality (see visualization below).

qqnorm(gng_ac_gng_ON_res$residuals, main = "Q-Q Plot of the Go/No-Go Reaction Time Residuals for the Powered ON Group") 
qqline(gng_ac_gng_ON_res$residuals)

  • It appears that residuals tend to follow the shape of a normal distribution (see visualization below).

qplot(gng_ac_gng_ON_res$residuals, main = "Histogram of Go/No-Go Reaction Time Residuals for the Powered ON Group") + 
  theme_classic()

  • The Shapiro-Wilk test of normality was not significant (based on \(\alpha = 0.05\)), W = 0.99, p = .33 (see code below).

gng_ac_gng_ON_shap = shapiro.test(gng_ac_gng_ON_res$residuals)
gng_ac_gng_ON_shap

    Shapiro-Wilk normality test

data:  gng_ac_gng_ON_res$residuals
W = 0.98671, p-value = 0.3314
  • The data’s Skewness and Kurtosis was examined and showed that both the Skewness (range: 0.06 to 0.34) and Kurtosis (range: -0.88 to -0.45) were within the acceptable range of \(\pm 2.0\) and \(\pm 9.0\), respectively (Schmider, Ziegler, Danay, Beyer, & Bühner, 2010) (see table below).

# use the descriptives data -- gng_ac_gng_ON_des

# organize the data into a new data frame depicting the Skew, kurtosis, and sample size (n).
  gng_ac_gng_ON_sk_t = cbind(t(gng_ac_gng_ON_des["rt_av1", c("skew", "kurtosis", "n")]),
                             t(gng_ac_gng_ON_des["rt_av2", c("skew", "kurtosis", "n")]),
                             t(gng_ac_gng_ON_des["rt_av3", c("skew", "kurtosis", "n")]))
    colnames(gng_ac_gng_ON_sk_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(gng_ac_gng_ON_sk_t) = c("Skewness", "Kurtosis", "n")
    
# use kable to show the descriptives table
  kable(gng_ac_gng_ON_sk_t, caption = "Skewness and Kurtosis of the Reaction Time on the Go/No-Go Task for the Powered ON Group", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
  add_header_above(c(" ", "Smartphone Location" = 3))

Skewness and Kurtosis of the Reaction Time on the Go/No-Go Task for the Powered ON Group
Smartphone Location
On Desk In Pocket/Bag Outside
Skewness 0.3417 0.1117 0.0623
Kurtosis -0.6968 -0.8811 -0.4550
n 36.0000 39.0000 38.0000

NA
  • Therefore, based on all the normality assumption checks, normality was assumed to be within the acceptable range for the analysis. Additionally, it should be noted that ANOVA analyses can be robust to violations of normality (Gardner & Tremblay, 2007).

3. Homogeneity of Variance

This assumption was tested by conducting Levene’s Test for Homogeneity of Variance for the between-subjects variable.

  • The homogeneity assumption was met (based on \(\alpha = 0.05\)) for smartphone location, F(2, 110) = 0.95, p = .39 (see code below).

# conduct levene's
  # for location
  gng_ac_gng_ON_lev_loc = leveneTest(data = gng_ac_gng_ON_data, rt_av ~ as.factor(location), center = median)
  gng_ac_gng_ON_lev_loc
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group   2  0.9466 0.3912
      110               
Powered OFF: Descriptive Statistics

The second simple main effect ANOVA was completed using the “Powered OFF” subset of the Power Factor (i.e. participants who completed the Go/No-Go task first with their smartphones powered OFF). The between-subjects factor was smartphone location (i.e. desk, pocket/bag or outside) and the dependent variable was accuracy (i.e. average reaction time).

There was a total of 113 participants in the Powered ON analysis. The following table depicts the descriptive statistics: the mean (M), standard deviation (SD), minimum score (min.), maximum score (max.), and the sample size (n).


# create a data frame with the descriptives of all the data, grouped by the location & power conditions
  # this creates information for the 6 possible combined conditions
  gng_ac_gng_OFF_des = psych::describeBy(gng_ac_gng_OFF_data, gng_ac_gng_OFF_data$location, mat = TRUE)  

# organize the data into a new data frame depicting the M, SD, min., max., and n.
  gng_ac_gng_OFF_des_t = cbind(t(gng_ac_gng_OFF_des["rt_av1", c("mean", "sd", "min", "max", "n")]),
                              t(gng_ac_gng_OFF_des["rt_av2", c("mean", "sd", "min", "max", "n")]),
                              t(gng_ac_gng_OFF_des["rt_av3", c("mean", "sd", "min", "max", "n")]))
    colnames(gng_ac_gng_OFF_des_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(gng_ac_gng_OFF_des_t) = c("M", "SD", "min.", "max.", "n")
  
# use kable to show the descriptives table
  kable(gng_ac_gng_OFF_des_t, caption = "Powered OFF Descriptive Statistics: Reaction Time (sec.) on the Go/No-Go Task", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
  add_header_above(c(" ", "Smartphone Location" = 3))

Powered OFF Descriptive Statistics: Reaction Time (sec.) on the Go/No-Go Task
Smartphone Location
On Desk In Pocket/Bag Outside
M 1.6735 1.6399 1.6630
SD 0.0674 0.0522 0.0656
min. 1.5690 1.5604 1.5635
max. 1.8442 1.7667 1.8688
n 36.0000 32.0000 34.0000

NA
Powered ON: Assumptions

The one-way simple main effect ANOVA made three assumptions. All assumptions were met. (click to see details).

1. Independent Random Sampling

This assumption was met during testing.

2. Normality

This assumption was tested by visualizing the residuals, applying a Shapiro-Wilk test to the resdiuals, and observing the Skewness and Kurtosis of the data (extracted from the ANOVA output).


# run between-subjects ANOVA (IV: Smartphone Power & Location; DV: OSpan Abolute Score)
gng_ac_gng_OFF_anova = ezANOVA(
  data = gng_ac_gng_OFF_data
  , dv = .(rt_av)
  , wid = .(participant)
  , between = .(location)
  , type = 3 # unequal sample sizes, therfore use type 3
  , detailed = TRUE
  , return_aov = TRUE
  )

# calculate & extract the residuals from the ANOVA
gng_ac_gng_OFF_res = data.frame("residuals" = proj(gng_ac_gng_OFF_anova$aov)[,"Residuals"])   
  • It appears that the residuals lie closely to a straight line, which suggests normality (see visualization below).

qqnorm(gng_ac_gng_OFF_res$residuals, main = "Q-Q Plot of the Go/No-Go Reaction Time Residuals for the Powered OFF Group") 
qqline(gng_ac_gng_OFF_res$residuals)

  • It appears that residuals tend to follow the shape of a normal distribution (see visualization below).

qplot(gng_ac_gng_OFF_res$residuals, main = "Histogram of Go/No-Go Reaction Time Residuals for the Powered OFF Group") + 
  theme_classic()

  • The Shapiro-Wilk test of normality was significant (based on \(\alpha = 0.05\)), W = 0.95, p = .001 (see code below).

gng_ac_gng_OFF_shap = shapiro.test(gng_ac_gng_OFF_res$residuals)
gng_ac_gng_OFF_shap

    Shapiro-Wilk normality test

data:  gng_ac_gng_OFF_res$residuals
W = 0.94912, p-value = 0.0006317
  • The data’s Skewness and Kurtosis was examined and showed that both the Skewness (range: 0.52 to 0.95) and Kurtosis (range: -0.52 to 0.88) were within the acceptable range of \(\pm 2.0\) and \(\pm 9.0\), respectively (Schmider, Ziegler, Danay, Beyer, & Bühner, 2010) (see table below).

# use the descriptives data -- gng_ac_gng_OFF_des

# organize the data into a new data frame depicting the Skew, kurtosis, and sample size (n).
  gng_ac_gng_OFF_sk_t = cbind(t(gng_ac_gng_OFF_des["rt_av1", c("skew", "kurtosis", "n")]),
                             t(gng_ac_gng_OFF_des["rt_av2", c("skew", "kurtosis", "n")]),
                             t(gng_ac_gng_OFF_des["rt_av3", c("skew", "kurtosis", "n")]))
    colnames(gng_ac_gng_OFF_sk_t) = c("On Desk", "In Pocket/Bag", "Outside")
    rownames(gng_ac_gng_OFF_sk_t) = c("Skewness", "Kurtosis", "n")
    
# use kable to show the descriptives table
  kable(gng_ac_gng_OFF_sk_t, caption = "Skewness and Kurtosis of the Reaction Time on the Go/No-Go Task for the Powered OFF Group", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
  add_header_above(c(" ", "Smartphone Location" = 3))

Skewness and Kurtosis of the Reaction Time on the Go/No-Go Task for the Powered OFF Group
Smartphone Location
On Desk In Pocket/Bag Outside
Skewness 0.8433 0.5198 0.9459
Kurtosis 0.0585 -0.5200 0.8837
n 36.0000 32.0000 34.0000

NA
  • Therefore, based on all the normality assumption checks, normality was assumed to be within the acceptable range for the analysis. Additionally, it should be noted that ANOVA analyses can be robust to violations of normality (Gardner & Tremblay, 2007).

3. Homogeneity of Variance

This assumption was tested by conducting Levene’s Test for Homogeneity of Variance for the between-subjects variable.

  • The homogeneity assumption was met (based on \(\alpha = 0.05\)) for smartphone location, F(2, 99) = 0.65, p = .52 (see code below).

# conduct levene's
  # for location
  gng_ac_gng_OFF_lev_loc = leveneTest(data = gng_ac_gng_OFF_data, rt_av ~ as.factor(location), center = median)
  gng_ac_gng_OFF_lev_loc
Levene's Test for Homogeneity of Variance (center = median)
      Df F value Pr(>F)
group  2   0.649 0.5248
      99               
Simple Main Effects: Results

All results were based on a Holm-Bonferroni adjustment applied to the original p-values. Below are the reported statistics for both analyses (i.e. powered ON and OFF), followed by a table depicting the ANOVA results.

Main Effect of Smartphone Location in the Powered ON Condition

There was no significant main effect of smartphone location on reaction time for those in the powered OFF condition, F(2, 110) = 1.47, p = .24, \(\eta^{2}\) = .03.

Main Effect of Smartphone Location in the Powered OFF Condition

There was no significant main effect of smartphone location on reaction time for those in the powered OFF condition, F(2, 99) = 2.54, p = .17, \(\eta^{2}\) = .05.

Post-hoc Tests

Since there was no significant main or interaction effects, no post-hocs were completed.


# create a table with the anova results including the adjusted p-values 
  # create a table with both power condition data
  gng_ac_gng_POW_t = rbind(gng_ac_gng_ON_anova$ANOVA[gng_ac_gng_ON_anova$ANOVA$Effect == "location",], 
                           gng_ac_gng_OFF_anova$ANOVA[gng_ac_gng_OFF_anova$ANOVA$Effect == "location",])
  # replace the p-values with the adjusted values (Holm-Bonferroni adjustment)
  gng_ac_gng_POW_t$p = p.adjust(c(gng_ac_gng_ON_anova$ANOVA$p[2], gng_ac_gng_OFF_anova$ANOVA$p[2]), method = "holm")
  # adjust the p<.05 column to reflect the new data (if there was any change)
  gng_ac_gng_POW_t$`p<.05` = ifelse(gng_ac_gng_POW_t$p < 0.05, "*", "")
  # replace the names in the effects column with "ON" & "OFF"
  gng_ac_gng_POW_t$Effect = c("ON", "OFF")
  # rename the columns
  colnames(gng_ac_gng_POW_t) = c("Smartphone Power Condition", "DFn", "DFd", "SSn", "SSd", "F", "p", "p<.05", "ges")
  # remove the row names
  rownames(gng_ac_gng_POW_t) = NULL

# show ANOVA results in kable table 
kable(gng_ac_gng_POW_t, caption = "Simple Main Effects Analyses: Reaction Time on the Go/No-Go Task for the Go/No-Go First Balance Group", digits = 4, align = 'c', escape = FALSE) %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) 

Simple Main Effects Analyses: Reaction Time on the Go/No-Go Task for the Go/No-Go First Balance Group
Smartphone Power Condition DFn DFd SSn SSd F p p<.05> ges
ON 2 110 0.0058 0.2178 1.4665 0.2352 0.0260
OFF 2 99 0.0198 0.3850 2.5411 0.1678 0.0488

NA
Visualizations

The following shows a visulization of Accuracy (i.e. reaction time) on the Cue-Dependent Go/No-go Task. There was a significant three-way interaction in the main ANOVA (i.e. between smartphone location, smartphone power, and balance). Additionally, the main factors of interest were the smartphone conditions (i.e. location and power). Therefore, two visualizations are shown depicting the smartphone conditions, one for each of the levels of the balance factor.

Testing the Moderation Hypothesis:

SAD

Factor Analysis

To examine the underlying factors measured by the Smartphone Attachment and Dependecy Inventory (SAD) from Ward et al. (2017), a principal components factor analysis with a Varimax rotation was completed on participant’s SAD data. The analysis was done exploratorily and was compared to Ward et al.’s findings, where they found two factors, smarphone dependence (i.e. six items; items #1-6; 31.02% of the variance) and emotional attachment (i.e. five items; items #8-11; 21.65% of the variance), which explained 52.67% of the total variance. It should be noted that two items (i.e. item #7 and 13) did not strongly load onto a factor and were excluded from subsequent analyses.

To perform the principal components factor analysis, we first examined the data for (1) missing data, (2) correlations between the items, and (3) the factorability of the data.

  1. Missing Data
  • From the descriptives table, it seems that there is no missing or incomplete data. This was confirmed by finding the complete cases, which were equal to the total sample size (i.e. 409). Therefore, no data was removed due to missing values for this analysis (see descriptives table below).

# get a data frame with the SAD items only for the factor analysis
fa_data = dplyr::select(factor_analysis, SAD_1:SAD_13)

# find the total complete cases to find any missing data from the data -- any participant with missing data must be removed
fa_complete = sum(complete.cases(fa_data))

# Show descriptives for the factor analysis data
fa_des = describe(fa_data)

# show descriptives in kable table 
kable(fa_des, caption = "Descriptives for Items in the SAD", digits = 4, align = 'c', escape = FALSE) %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = F) 

Descriptives for Items in the SAD
vars n mean sd median trimmed mad min max range skew kurtosis se
SAD_1 1 409 4.7262 1.7443 5 4.8389 1.4826 1 7 6 -0.5344 -0.7959 0.0862
SAD_2 2 409 4.0709 1.8543 5 4.1033 1.4826 1 7 6 -0.1517 -1.2732 0.0917
SAD_3 3 409 3.7897 1.9097 3 3.7508 2.9652 1 7 6 0.1153 -1.2714 0.0944
SAD_4 4 409 4.6259 1.7821 5 4.7234 1.4826 1 7 6 -0.4991 -0.8988 0.0881
SAD_5 5 409 4.5819 1.7598 5 4.6596 1.4826 1 7 6 -0.4048 -0.9655 0.0870
SAD_6 6 409 4.6039 1.6714 5 4.7021 1.4826 1 7 6 -0.6096 -0.6416 0.0826
SAD_7 7 409 5.7188 1.2154 6 5.9058 1.4826 1 7 6 -1.3640 2.3117 0.0601
SAD_8 8 409 3.3399 1.7944 3 3.2523 2.9652 1 7 6 0.3104 -1.1182 0.0887
SAD_9 9 409 4.0000 1.7864 4 4.0365 1.4826 1 7 6 -0.1570 -1.0538 0.0883
SAD_10 10 409 4.7115 1.4983 5 4.8419 1.4826 1 7 6 -0.7497 0.1181 0.0741
SAD_11 11 409 4.5966 1.4094 5 4.7264 1.4826 1 7 6 -0.6631 0.2059 0.0697
SAD_12 12 409 4.7042 1.7872 5 4.8207 1.4826 1 7 6 -0.5207 -0.7931 0.0884
SAD_13 13 409 5.2665 1.4002 6 5.4347 1.4826 1 7 6 -1.0832 1.0722 0.0692

NA
  1. Correlations between the Items
  • The correlations between the items were examined to determine if they were either not high enough (i.e., r < .30) or too high (i.e., r > .80).
    • The correlations for the 13 items in the SAD ranged from r(407) = .16 to r(407) = .72, p = .001.
    • A visual inspection of the correlations showed that items 12 and 13 might not be correlated enough with the rest of the items (i.e. 11 and 9 correlations below .30, respectively). There were no issues associated with too many high correations for any items.
    • The lower correlations for items 12 and 13 should be kept in mind when completing the factor analysis and these items may be removed.
  • To check for multicollinearity, the determinant of the correlation matrix was calculated. The determinant was greater than the necessary value of 0.00001 (i.e., 0.00452), so, there was no issues with multicollinearity (Field et al., 2012).
  • Therefore, all items in the SAD correlated reasonably with each other and without an excessively large correalation so no items were removed at this stage.

# get the pearson correlations between all items (and corresponding p-values)
fa_cor = rcorr(as.matrix(fa_data), type = "pearson") 

# make a table with the data to display it better
fa_cor_t = as.data.frame(fa_cor$r)
  # include only the lower triangle of the data
  fa_cor_t[upper.tri(fa_cor_t)] = NA
  
# find the determinant of the correlation matrix
fa_det = det(fa_cor$r)

# Print table using kable
  # make any NAs appear as blank within kable
  opts = options(knitr.kable.NA = "")
  # print table
  kable(fa_cor_t, caption = "Pearson Correlations between Items in the SAD", digits = 4, align = 'c', escape = FALSE) %>%
    kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
    add_footnote("p < .001", notation = "alphabet")

Pearson Correlations between Items in the SAD
SAD_1 SAD_2 SAD_3 SAD_4 SAD_5 SAD_6 SAD_7 SAD_8 SAD_9 SAD_10 SAD_11 SAD_12 SAD_13
SAD_1 1.0000
SAD_2 0.7176 1.0000
SAD_3 0.5515 0.6064 1.0000
SAD_4 0.5528 0.5836 0.5537 1.0000
SAD_5 0.4481 0.4733 0.4522 0.5322 1.0000
SAD_6 0.4377 0.4235 0.3724 0.4891 0.5544 1.0000
SAD_7 0.3081 0.3395 0.3018 0.3757 0.4354 0.5025 1.0000
SAD_8 0.3712 0.3691 0.2841 0.4001 0.3866 0.4217 0.3035 1.0000
SAD_9 0.3445 0.4129 0.3291 0.3903 0.4117 0.3152 0.3714 0.4106 1.0000
SAD_10 0.3364 0.3647 0.2683 0.3248 0.3009 0.3986 0.3753 0.5416 0.4579 1.0000
SAD_11 0.3837 0.4564 0.3782 0.3604 0.3350 0.3482 0.2942 0.3422 0.5685 0.5692 1.0000
SAD_12 0.2483 0.2363 0.2460 0.2591 0.2372 0.2585 0.2855 0.2943 0.2180 0.2426 0.2318 1.0000
SAD_13 0.2186 0.1579 0.2007 0.2316 0.2592 0.3133 0.3235 0.2165 0.1685 0.2202 0.1639 0.4939 1
a p < .001

    # restore the original options so that "NA" shows up again
    options(opts)
  • Another way to visualize this is using a Scatter Plot Matrix
    • This shows: (1) a scatter plot bellow the lower diagonal, with a line of best fit (red); (2) a historgram and density plot of the item on the diagonal; and (3) the correlation values (pearson r) above the diagonal, with corresponding significance shown with asterisks. The x-axis in each scatter plot represents the column variable and the y-axis the row variable.
# show a SPLOM (Scatter Plot Matrix) of the Data 
pairs.panels(fa_data, pch = ".", density = TRUE, ellipses = FALSE, lm = TRUE, digits = 2, method = "pearson", jiggle = TRUE, factor = 1, hist.col = "cadetblue3", stars = TRUE, gap = .5, verOdd = TRUE, horOdd = TRUE, main = "Scatter Plot Matrix of Items in the SAD")

  1. Factorability of the Data
  • This assessed if there were meaningful latent factors to be found within the data, which was assessed in two ways: Barlett’s test of sphericity and the Kaiser-Meyer-Olkin measure of sampling adequacy.
    • Barlett’s test of sphericity:
      • This test was statistically significant, which suggested good factorability, \(\chi^{2}\)(78) = 2174.97, p < .001
    • Kaiser-Meyer-Olkin measure of sampling adequacy:
      • This measure showed an overall measure of sampling adequacy (MSA) and an MSA per item. The overall MSA was higher than both the minimum and preferred criterias (0.50 and 0.60, respectively; Kaiser, 1974, Hutcheson & Sofroniou, 1999), \(MSA_{overall}\) = 0.89. Each item’s MSA was also higher than the minimum and preferred criteria, \(MSA_{1-13}\) = 0.79 - 0.94.
  • Therefore, both factorability tests confirmed that the planned factor analysis was appropriate.
# run the Barlett Test
fa_bartest = cortest.bartlett(fa_data)
fa_bartest
$chisq
[1] 2174.971

$p.value
[1] 0

$df
[1] 78
# run the KMO 
fa_kmo = KMO(fa_data)
fa_kmo
Kaiser-Meyer-Olkin factor adequacy
Call: KMO(r = fa_data)
Overall MSA =  0.89
MSA for each item = 
 SAD_1  SAD_2  SAD_3  SAD_4  SAD_5  SAD_6  SAD_7  SAD_8  SAD_9 SAD_10 SAD_11 SAD_12 SAD_13 
  0.89   0.88   0.93   0.94   0.92   0.90   0.91   0.88   0.89   0.84   0.85   0.82   0.79 

Now that factorability was confirmed, we found the appropriate number of factors to extract. This was done using: (1) a parallel analysis scree plot, (2) eigen values (i.e., from the parallel analysis), and (3) the factor structure between the two solutions (i.e., using factor diagrams).

  1. Parralel Analysis Scree Plot.

This plotted the eigenvalues from the data and a parrallel analysis which generated random correlation matrices. The number of factors is then determined by comparing the resulting eigenvalues to the observed data, that is, observed eigenvalues that were higher than the corresponding random eigenvalues were more likely to form meaningful factors.

  • The parrallel analysis scree plot showed that there are 2 appropriate factors (i.e. using the principal components extraction method).
    • From closer inspection of the plot, the last factor was very close to the random eigenvalue cut-off line, therefore, the 2 and 3 factor solutions were compared to determine the best fit (i.e., the eigen values and factor structures were examined).

fa_par = fa.parallel(fa_data, fa = "pc", main = "Parallel Analysis Scree Plot for Items in the SAD")
Parallel analysis suggests that the number of factors =  NA  and the number of components =  2 

  1. Eigen Values

For a sample size greater than 250 (i.e., 409 complete cases) the average communalities (i.e., the proportion of common variance within the items) for the two factor (0.52) and three factor (0.62) solutions were wihtin the acceptable value (i.e., 0.60; Field et al., 2012). Therefore, Kaiser’s criterion (i.e., a meaningful factor has an eigen value greater than 1) was used for the eigen values. It should be noted that although the average communalities were not very high, the scree plot and factor diagrams were used to choose the appropriate number of factors.

  • The eigen values (unrotated solution) showed three meaningful factors (i.e., 5.5, 1.31, 1.19), which supported the three-factor solution as a better representation of the data.
# Eigen values
  # view eigen values from the parallel analysis scree plot
  round(fa_par$pc.values, 3)
 [1] 5.502 1.308 1.186 0.883 0.718 0.589 0.522 0.475 0.463 0.417 0.369 0.304 0.265
  1. Factor Diagrams

A factor diagram for the two- and three-factor solutions (rotated solution) was used to determine which solution represents the most interpretable solution. The diagrams show the factor loadings for each item on the given factor for which they load the highest on. The items were ordered (i.e., descending) based on these loadings.
Note: The factor diagrams are based on the rotated solutions to better distribute the factor loadings

  • The factor diagrams showed that the two factor solution resulted in most items loading onto only one factor and was not easily interpreted. The three factor solution showed a better distribution and was more interpretable.

Therefore, the three factor solution was chosen to better represent the data.

##-- VARIMAX ROTATION  
# run a factor analysis to compare the two- and three-factor solutions (no rotation)
  # 2 factor solution
  fa_two_v = principal(fa_data, nfactors = 2, rotate = "varimax", scores = T)
    # change name in loadings for clarity when visualizing the model
    colnames(fa_two_v$loadings) = c("Factor 1", "Factor 2")
  
  # 3 factor solution
  fa_three_v = principal(fa_data, nfactors = 3, rotate = "varimax", scores = T)
    # change name in loadings for clarity when visualizing the model
    colnames(fa_three_v$loadings) = c("Factor 1", "Factor 2", "Factor 3")

# Factor Diagram
  # 2 factor solution
  fa.diagram(fa_two_v, main = "Two Factor Solution for items in the SAD (Varimax Rotation)", sort = TRUE, adj = 1, digits = 2)


  # 3 factor solution
  fa.diagram(fa_three_v, main = "Three Factor Solution for Items in the SAD (Varimax Rotation)", sort = TRUE, adj = 1, digits = 2)

  
  
##-- OBLIMIN ROTATION  
# run a factor analysis to compare the two- and three-factor solutions (no rotation)
  # 2 factor solution
  fa_two_o = principal(fa_data, nfactors = 2, rotate = "oblimin", scores = T)
    # change name in loadings for clarity when visualizing the model
    colnames(fa_two_o$loadings) = c("Factor 1", "Factor 2")
  
  # 3 factor solution
  fa_three_o = principal(fa_data, nfactors = 3, rotate = "oblimin", scores = T)
    # change name in loadings for clarity when visualizing the model
    colnames(fa_three_o$loadings) = c("Factor 1", "Factor 2", "Factor 3")

# Factor Diagram
  # 2 factor solution
  fa.diagram(fa_two_o, main = "Two Factor Solution for items in the SAD (Oblimin Rotation)", sort = TRUE, adj = 1, digits = 2)


  # 3 factor solution
  fa.diagram(fa_three_o, main = "Three Factor Solution for Items in the SAD (Oblimin Rotation)", sort = TRUE, adj = 1, digits = 2)

Now that we determined the number of factors (i.e., three), we observed the communalities. Each item’s communality was the percentage of variance that was explained by the retained factors for each item. These ranged from 45% to 74%, with an average of 62% (see table for more details).

# get the communalities from the model
fa_com = as.data.frame(fa_three_v$communality)

# create matrix to present communalities in a table
fa_com_t = rbind((fa_com[,1])*100)
  # rename row and column names
  colnames(fa_com_t) = rownames(fa_com)
  rownames(fa_com_t) = NULL

# Print table using kable
  # print table
  kable(fa_com_t, caption = "Communalities for the Three-Factor Solution for Items in the SAD (%)", digits = 4, align = 'c', escape = FALSE) %>%
    kable_styling(bootstrap_options = "striped", "hover", full_width = F) %>%
    add_footnote("Communalities show the percentage of variance explained by each factor for each item on the SAD.", notation = "alphabet")
Communalities for the Three-Factor Solution for Items in the SAD (%)
SAD_1 SAD_2 SAD_3 SAD_4 SAD_5 SAD_6 SAD_7 SAD_8 SAD_9 SAD_10 SAD_11 SAD_12 SAD_13
67.7017 73.8798 63.8423 64.4335 53.2454 51.671 45.0262 50.2766 60.4257 72.1824 64.965 60.1458 71.8026
a Communalities show the percentage of variance explained by each factor for each item on the SAD.

Next, we looked at the percentage of variance accounted for by using the eigenvalues (compute the variance assosiated with the factors). This was done for both the unrotated and rotated (i.e., varimax) three-factor solution. As you can see in the table below, a total of 61.51% of variance was accounted for by the three extracted factors. This variance was mostly accounted for by factor one in the unrotated solution, but was more equally distributed after rotation (see table for more details).


# Run an unrotated three-factor solution
  fa_three = principal(fa_data, nfactors = 3, rotate = "none", scores = T) 
    # change name in loadings for clarity when visualizing the model
    colnames(fa_three$loadings) = c("Factor 1", "Factor 2", "Factor 3") 
    
  
# To find the variace accounted for, you can either (1) calculate it from the eigen values for each factor, or (2) grab the calculated values from the model 
  # Both are shown below, but one is commented out to avoid creating unessesary variables
  # (1) Calculated 
    # For the unrotated solution
    #var_per = 100*fa_three$values[1:3]/length(fa_three$values)
    
    # For the rotated solution
    #var_per_v = 100*(as.numeric(fa_three_v$Vaccounted[1,]))/length(fa_three_v$values)
      
  # (2) The information is found in the "Vaccounted" table from the output, where "SS loadings" (row 1) shows the eigen values and "Proportion Var" (row 2) shows the variance accounted for.
    # For the unrotated solution
    var_per = 100*as.numeric(fa_three$Vaccounted[2,])
    
    # For the rotated solution
    var_per_v = 100*as.numeric(fa_three_v$Vaccounted[2,])

# Create & Show a table with eigen values, percent var explained, and total percent var explained for unrotated & rotated three-factor solutions
    # unrotated solution
    var_per_t = as.data.frame(cbind(rbind(as.numeric(fa_three$Vaccounted[1,]), var_per), 
                                    rbind(as.numeric(fa_three_v$Vaccounted[1,]), var_per_v)))
    # name the columns & rows accordingly
    colnames(var_per_t) = c(rep(c("Factor 1", "Factor 2", "Factor 3"),2))
    rownames(var_per_t) = c("Eigen Values", "Variance Explained (%)")

  # use kable to show the table
  kable(var_per_t, caption = "Eigen Values and Percent of Variance Explained for the Unrotated and Rotated (varimax) for the Three-Factor Solution for Items in the SAD", digits = 4, align = 'c') %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = T) %>%
  add_header_above(c(" ", "Unrotated" = 3, "Varimax Rotation" = 3))

Eigen Values and Percent of Variance Explained for the Unrotated and Rotated (varimax) for the Three-Factor Solution for Items in the SAD
Unrotated
Varimax Rotation
Factor 1 Factor 2 Factor 3 Factor 1 Factor 2 Factor 3
Eigen Values 5.5022 1.3080 1.1857 3.4009 2.6434 1.9516
Variance Explained (%) 42.3250 10.0616 9.1210 26.1611 20.3339 15.0125

NA

Lastly, we looked at the factor loadings of the three-factor solution. Below you can see the rotated (i.e., varimax) and unrotated facter loadings. The loadings are shown with a cut-off of 0.40 and rounded to three decimal places. As we saw in tha factor diagrams, the unrotated factor loadings are difficult to interpret: all items loaded strongly onto factor 1 (i.e., loading was greater than 0.40). The roatated factor loadings were more easy to interpret, with only one item loading onto more than one factor (i.e., item six; see below for more details).


# Unrotated Factor Loadings 
print(fa_three$loadings, cutoff = 0.40, digits = 3)

Loadings:
       Factor 1 Factor 2 Factor 3
SAD_1   0.725                    
SAD_2   0.756                    
SAD_3   0.675                    
SAD_4   0.739                    
SAD_5   0.705                    
SAD_6   0.700                    
SAD_7   0.611                    
SAD_8   0.633                    
SAD_9   0.645            -0.432  
SAD_10  0.639            -0.541  
SAD_11  0.650            -0.470  
SAD_12  0.462    0.585           
SAD_13  0.423    0.669           

               Factor 1 Factor 2 Factor 3
SS loadings       5.502    1.308    1.186
Proportion Var    0.423    0.101    0.091
Cumulative Var    0.423    0.524    0.615
# Rotated (i.e., varimax) Factor Loadings 
print(fa_three_v$loadings, cutoff = 0.40, digits = 3)

Loadings:
       Factor 1 Factor 2 Factor 3
SAD_1  0.788                     
SAD_2  0.809                     
SAD_3  0.780                     
SAD_4  0.744                     
SAD_5  0.613                     
SAD_6  0.491             0.416   
SAD_7                    0.487   
SAD_8           0.611            
SAD_9           0.723            
SAD_10          0.819            
SAD_11          0.754            
SAD_12                   0.754   
SAD_13                   0.841   

               Factor 1 Factor 2 Factor 3
SS loadings       3.401    2.643    1.952
Proportion Var    0.262    0.203    0.150
Cumulative Var    0.262    0.465    0.615

In order to validate the SAD, we completed a reliability analysis (i.e., is the scale consistent) by looking at the split-half reliability using Cronbach’s alpha. This method is the most common measure of scale reliability (Field et al., 2012): the data for each participant is randomly split into two sets, which forms a “half” split for the scale. Then, a correlation is calculated between these sets to determine how similar they are: higher reliability would be seen with highly correlated sets. Since the way that the data is split can impact the correlations, Cronbach’s alpha represents an average of all the possible splits using the following equation:

\[\alpha = \frac{N^2 \overline{Cov}}{\sum s_{item}^2 + \sum Cov_{item}} \] To obtain the best reliability measure, we must divide our data into any subscales, which in this case, are our three factors from our factor analysis. Therefore, we split the data into three sets for the reliability analysis.


# split the data respective to the 3 factors from the FA to perform the reliability analysis
  # factor 1 (items: 1, 2, 3, 4, 5)
  f1_data = fa_data[,c(1, 2, 3, 4, 5)]
  # factor 2 (items: 8, 9, 10, 11)
  f2_data = fa_data[,c(8, 9, 10, 11)]
  # factor 3 (items: 7, 12, 13)
  f3_data = fa_data[,c(7, 12, 13)]

Once we have our subscales, we complete the reliability analysis on each subscale.


# compute reliability analysis for each subscale using "alpha()" function in "psych" package
  # factor 1
  f1_rel = psych::alpha(f1_data)
  # factor 2
  f2_rel = psych::alpha(f2_data)
  # factor 3
  f3_rel = psych::alpha(f3_data)

To view the analysis, we broke it down into three compoenents: (1) The alpha values and overall mean and standard deviation of the subscales, (2) The alpha values if an item was dropped (i.e., Alpha Drop Values), and (3) Item statistics.

  1. Alpha Values
  • The alpha values from the reliability analyses included Cronbach’s \(\alpha\) (i.e., based on the covariances), a standardized \(\alpha\) (i.e., based on the correlations), and Guttman’s Lambda 6. Additionally, the overall average correlation, mean, and standard deviation for the subscale is shown (see table below for more details).
  • As seen in the table, Cronbach’s \(\alpha\) was within the acceptable range (i.e., greater than .70; Kline, 1999) for Factor 1 (\(\alpha_C\) = 0.86) and Factor 2 (\(\alpha_C\) = 0.78), but not for Factor 3 (\(\alpha_C\) = 0.63). The overall correlations for Factor 1, r(407) = .55, and Factor 2, r(407) = .48, were moderate, whereas Factor 3’s correlation, r(407) = .37, was weak-moderate. These statistics were further explored with dropped items.
# show the alpha values from the 3 subscales
  # create data frame with the information from the 3 reliability analyses
  fa_rel_alphas = as.data.frame(rbind("Factor 1" = dplyr::select(f1_rel$total, -c("S/N", "ase", "median_r")), 
                                      "Factor 2" = dplyr::select(f2_rel$total, -c("S/N", "ase", "median_r")), 
                                      "Factor 3" = dplyr::select(f3_rel$total, -c("S/N", "ase", "median_r"))))
  # add an extra column for the "overall" or average alpha
  fa_rel_alphas = cbind("Overall alpha" = c(mean(as.numeric(dplyr::select(f1_rel$total, c("raw_alpha", "std.alpha")))), 
                                            mean(as.numeric(dplyr::select(f2_rel$total, c("raw_alpha", "std.alpha")))), 
                                            mean(as.numeric(dplyr::select(f3_rel$total, c("raw_alpha", "std.alpha"))))), 
                        fa_rel_alphas)

  # use kable to show the table
  kable(fa_rel_alphas, caption = "Reliability Analysis for Subscales in the SAD: Alpha Values", digits = 4, align = 'c', 
        col.names = c("Overall alpha", "Cronbach's alpha", "Standardized alpha", "Guttman's lambda 6", "Average r", "M", "SD")) %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = T)

Reliability Analysis for Subscales in the SAD: Alpha Values
Overall alpha Cronbach's alpha Standardized alpha Guttman's lambda 6 Average r M SD
Factor 1 0.8580 0.8579 0.8580 0.8383 0.5471 4.3589 1.4463
Factor 2 0.7839 0.7798 0.7880 0.7565 0.4817 4.1620 1.2658
Factor 3 0.6332 0.6308 0.6356 0.5519 0.3676 5.2298 1.1277

NA
  1. Alpha Drop Values
  • To further explore the reliability of each subscale, we looked at the alpha values after removing each item. This allowed us to determine whether a given item was reducing the reliability of the subscale. That is, if dropping an item increased \(\alpha\) or the correlation, the removing the item from the analysis should be considered. The data presented in the table below shows Cronbach’s \(\alpha\), standardized \(\alpha\), Guttman’s Lambda 6, and the average correlation.
  • As seen in the table below, dropping an item did not improve reliability for Factor 1 (range of \(\alpha_C\) = 0.81 - 0.85) or Factor 2 (range of \(\alpha_C\) = 0.69 - 0.76). However, removing item #7 did improve reliability for Factor 3 (\(\alpha_{C-drop7}\) = 0.65). With respect to the average correlation, dropping an item did not improve for Factor 2, r(407) = .44 - = .53. However, item #5 for Factor 1, r(407) = .59, and item #7 for Factor 3, r(407) = .49, did show a some improvement in average correlation. This was explored further with the items statistics.
# show the alpha drop values from the 3 subscales
  # create data frame with the information
  fa_rel_adrop = as.data.frame(rbind(dplyr::select(f1_rel$alpha.drop, c("raw_alpha", "std.alpha", "G6(smc)", "average_r")), 
                                     dplyr::select(f2_rel$alpha.drop, c("raw_alpha", "std.alpha", "G6(smc)", "average_r")), 
                                     dplyr::select(f3_rel$alpha.drop, c("raw_alpha", "std.alpha", "G6(smc)", "average_r"))))

  # use kable to show the table
  kable(fa_rel_adrop, caption = "Reliability Analysis for Subscales in the SAD: Alpha Drop Values", digits = 4, align = 'c', 
        col.names = c("Cronbach's alpha", "Standardized alpha", "Guttman's lambda 6", "Average r")) %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = T) %>%
  pack_rows(index = c("Factor 1" = ncol(f1_data), "Factor 2" = ncol(f2_data), "Factor 3" = ncol(f3_data)))

Reliability Analysis for Subscales in the SAD: Alpha Drop Values
Cronbach's alpha Standardized alpha Guttman's lambda 6 Average r
Factor 1
SAD_1 0.8207 0.8207 0.7796 0.5336
SAD_2 0.8091 0.8095 0.7648 0.5151
SAD_3 0.8312 0.8309 0.8018 0.5513
SAD_4 0.8254 0.8253 0.7939 0.5415
SAD_5 0.8536 0.8542 0.8218 0.5942
Factor 2
SAD_8 0.7646 0.7732 0.7003 0.5319
SAD_9 0.7291 0.7380 0.6750 0.4843
SAD_10 0.6938 0.7025 0.6278 0.4404
SAD_11 0.7202 0.7268 0.6450 0.4700
Factor 3
SAD_7 0.6482 0.6612 0.4939 0.4939
SAD_12 0.4852 0.4889 0.3235 0.3235
SAD_13 0.4196 0.4441 0.2855 0.2855

NA
  1. Item Statistics
  • The item statistics were explored to determine whether a certain item did not correlate with the overall subscale. The table below shows: r, which is the correlations between each item and the total score from the subscale (i.e., the item-total correlations), which includes the item itself; and Drop, which is the correlation of an item with the subscale after removing the item (i.e., the item-rest correlation or the corrected item-total correlation). Additionally, the sample size, mean, and standard deviation is shown.
  • No issues were found with the item statistics for Factor 1, r(407) = .57 - = .75; Factor 2, r(407) = .52 - = .66; and Factor 3, r(407) = .35 - = .52. That is, no items had a item-rest correlation (i.e., the drop column in the table below) below the cut-off (i.e., .30; Field et al., 2012).

# show the correlations for the 3 subscales
  # create data frame with the information
  fa_rel_item = as.data.frame(rbind(dplyr::select(f1_rel$item.stats, -c("std.r", "r.cor")), 
                                     dplyr::select(f2_rel$item.stats, -c("std.r", "r.cor")), 
                                     dplyr::select(f3_rel$item.stats, -c("std.r", "r.cor"))))

  # use kable to show the table
  kable(fa_rel_item, caption = "Reliability Analysis for Subscales in the SAD: Item Statistics", digits = 4, align = 'c', 
        col.names = c("N", "r", "Drop", "M", "SD")) %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = T) %>%
  pack_rows(index = c("Factor 1" = ncol(f1_data), "Factor 2" = ncol(f2_data), "Factor 3" = ncol(f3_data)))  

Reliability Analysis for Subscales in the SAD: Item Statistics
N r Drop M SD
Factor 1
SAD_1 409 0.8161 0.7053 4.7262 1.7443
SAD_2 409 0.8487 0.7458 4.0709 1.8543
SAD_3 409 0.7991 0.6648 3.7897 1.9097
SAD_4 409 0.8052 0.6858 4.6259 1.7821
SAD_5 409 0.7234 0.5709 4.5819 1.7598
Factor 2
SAD_8 409 0.7548 0.5210 3.3399 1.7944
SAD_9 409 0.7921 0.5841 4.0000 1.7864
SAD_10 409 0.8078 0.6557 4.7115 1.4983
SAD_11 409 0.7687 0.6083 4.5966 1.4094
Factor 3
SAD_7 409 0.6440 0.3488 5.7188 1.2154
SAD_12 409 0.8352 0.4874 4.7042 1.7872
SAD_13 409 0.7910 0.5248 5.2665 1.4002

NA

Overall, the reliability for Factor 1 and Factor 2 was adequate. However, Factor 3 showed mixed results: item #7 was not as stable as the other items. However, this item did fit the minimum criteria for reliability and was therefore left in the subscale. OR The item met the minimum criteria, but was removed to improve the overall factor analysis fit with the data.

Conclusions

A principal components factor analysis was completed on the 13 items in the SAD (Ward et al., 2017) with an orthogonal rotation (i.e., varimax rotation). Factorability of the data was confirmed using: (1) Bartlett’s test for sphericity, \(\chi^{2}\)(78) = 2174.97, p < .001, which confirmed that correlations between the items were sufficiently large; and (2) the Kaiser-Meyer-Olkin measure for sampling adequacy, \(MSA_{overall}\) = 0.89, \(MSA_{1-13}\) = 0.79 - 0.94, which confirmed that both the overall MSA and each item’s MSA were above their required criteria (0.60 and 0.77, respectively; Kaiser, 1974). The appropriate number of factors (i.e., three) was confirmed using (1) a parallel analysis scree plot, where the two- and three-factor solutions were chosen to compare for th ebest fit for the data; (2) the eigen values (e.g., 5.5022442, 1.3080016, 1.1857354, 0.8831051, for factors 1 to 4, respectively) for the unrotated solution, where three meaningful factors were found using Kaiser’s criterion (i.e., eigen values greater than one); and (3) the factor structure of the two- and three-factor solutions, where the three-factor solution showed a better distribution of the data and was more interpretable. Therefore, the three-factor solution was chosen for the final analysis and explained 61.51% of the variance. Additionally, an orthogonal (i.e., varimax) rotation was chosen for the final analysis. The items in the final factors suggested the following three factors: smartphone dependence, emotional attachment, and smartphone distractability. Smartphone dependence was relate to the degree of dependence on one’s smartphone, it consisted of 5 items and explained 26.16% of the variance (e.g., “I would have trouble getting through a normal day without my smartphone.”, and “I feel like I could not live without my smartphone.”). Emotional attachment was related to one’s smartphone use for emotional support, it consisted of 4 items and explained 20.33% of the variance (e.g., “I feel lonely when my smartphone does not ring or vibrate for several hours.”, and “Using my smartphone makes me feel happy.”). Smartphone distractability was related to one’s smartphone retaining one’s attention, it consisted of 3 items and explained 15.01% of the variance (e.g., “I find it tough to focus whenever my smartphone is nearby.”, and “I become less attentive to my surroundings when I’m using my smartphone.”). One item did not clearly load onto any one factor and was excluded from further analyses (i.e., item 6; Costello & Osborne, 2005). See table below for all items and factor loadings.


# create table with all items, factor loadings, eigen values, % of virance explained, and Cronbach's alpha 

# get factor loadings
  fa_load = as.data.frame(fa_three_v$Structure[1:13,])
  # rename columns
  colnames(fa_load) = c("Factor 1", "Factor 2", "Factor 3")

# make list of the items & other info
  fa_table_list = as.data.frame(c("I would have trouble getting through a normal day without my smartphone.",
                              "It would be painful for me to give up my smartphone for a day.",
                              "I feel like I could not live without my smartphone.",
                              "If I forgot to bring my smartphone with me, I would feel anxious.",
                              "It drives me crazy when my smartphone runs out of battery.",
                              "I am upset and annoyed when I find I do not have reception on my smartphone.",
                              "I feel impatient when the Internet connection speed on my smartphone is slow.",
                              "I feel lonely when my smartphone does not ring or vibrate for several hours.",
                              "Using my smartphone relieves me of my stress.",
                              "I feel excited when I have a new message or notification.",
                              "Using my smartphone makes me feel happy.",
                              "I find it tough to focus whenever my smartphone is nearby.",
                              "I become less attentive to my surroundings when I’m using my smartphone.", 
                              "Eigen Values", 
                              "Variance Explained (%)"))
  
# create the final table
  # bind the loadings and items
    fa_three_t = cbind(fa_table_list, rbind(fa_load, var_per_t[4:6]))
    
    # rename columns & rows
      colnames(fa_three_t) = c("Item", "Factor 1: Smartphone Dependence", "Factor 2: Emotional Attachment", "Factor 3: Smartphone Distractability")
      rownames(fa_three_t)[14:15] = c("", " ") 
      
# use kable to show the table
  kable(fa_three_t, caption = "Summary of exploratory varimax rotated factor analysis results for the 13-Items in the SAD (N = 409)", digits = 4, align = "lccc") %>%
  kable_styling(bootstrap_options = "striped", "hover", full_width = T) %>%
  pack_rows("", 14, 15)

Summary of exploratory varimax rotated factor analysis results for the 13-Items in the SAD (N = 409)
Item Factor 1: Smartphone Dependence Factor 2: Emotional Attachment Factor 3: Smartphone Distractability
SAD_1 I would have trouble getting through a normal day without my smartphone. 0.7883 0.2098 0.1075
SAD_2 It would be painful for me to give up my smartphone for a day. 0.8090 0.2884 0.0343
SAD_3 I feel like I could not live without my smartphone. 0.7804 0.1354 0.1054
SAD_4 If I forgot to bring my smartphone with me, I would feel anxious. 0.7440 0.2265 0.1987
SAD_5 It drives me crazy when my smartphone runs out of battery. 0.6126 0.2608 0.2987
SAD_6 I am upset and annoyed when I find I do not have reception on my smartphone. 0.4907 0.3211 0.4157
SAD_7 I feel impatient when the Internet connection speed on my smartphone is slow. 0.3062 0.3453 0.4872
SAD_8 I feel lonely when my smartphone does not ring or vibrate for several hours. 0.2434 0.6107 0.2656
SAD_9 Using my smartphone relieves me of my stress. 0.2739 0.7235 0.0762
SAD_10 I feel excited when I have a new message or notification. 0.1246 0.8194 0.1867
SAD_11 Using my smartphone makes me feel happy. 0.2836 0.7540 0.0271
SAD_12 I find it tough to focus whenever my smartphone is nearby. 0.1202 0.1339 0.7544
SAD_13 I become less attentive to my surroundings when I’m using my smartphone. 0.0900 0.0445 0.8414
Eigen Values 3.4009 2.6434 1.9516
Variance Explained (%) 26.1611 20.3339 15.0125

NA
NA

Look at a reliability analysis

Generalized Linear Model

  • A univariate generalized linear model was used to examine if smartphone reliance (i.e. SAD score) was a moderator of the relationship between the experimental manipulation and task performance.

Note: These analysis were completed regardless of the results for the location and power hypotheses.

LS0tCnRpdGxlOiAiUmVleGFtaW5pbmcgdGhlIOKAnEJyYWluIERyYWlu4oCdIEVmZmVjdDogRG9lcyBXYXJkIGV0IGFsLiAoMjAxNykgcmVwbGljYXRlPyIKYXV0aG9yOiAiQS4gQy4gUnVpeiBQYXJkbywgSi4gUC4gTWluZGEiIApkYXRlOiAiQXByaWwgMjcsIDIwMjAiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6ICc2JwogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0aGVtZTogbHVtZW4gCiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6ICc2JwogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0aGVtZTogbHVtZW4gCi0tLQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoKYm9keXsgLyogTm9ybWFsICAqLwogICAgICBmb250LXNpemU6IDE1cHg7fQp0ZCB7ICAvKiBUYWJsZSAgKi8KICBmb250LXNpemU6IDE0cHg7fQpoMS50aXRsZSB7CiAgZm9udC1zaXplOiA0MHB4O30KaDEgeyAvKiBIZWFkZXIgMSAqLwogIGZvbnQtc2l6ZTogMzVweDsKICBjb2xvcjogRGFya0JsdWU7fQpoMiB7IC8qIEhlYWRlciAyICovCiAgZm9udC1zaXplOiAzM3B4OwogIGNvbG9yOiBEYXJrQmx1ZTt9CmgzIHsgLyogSGVhZGVyIDMgKi8KICBmb250LXNpemU6IDMxcHg7CiAgY29sb3I6IERhcmtCbHVlO30KaDQgeyAvKiBIZWFkZXIgNCAqLwogIGZvbnQtc2l6ZTogMjlweDsKICBjb2xvcjogRGFya0JsdWU7fQpoNSB7IC8qIEhlYWRlciA1ICovCiAgZm9udC1zaXplOiAyN3B4OwogIGNvbG9yOiBEYXJrQmx1ZTt9Cmg2IHsgLyogSGVhZGVyIDYgKi8KICBmb250LXNpemU6IDI1cHg7CiAgY29sb3I6IERhcmtCbHVlO30KCjwvc3R5bGU+Cgo8ZGl2IHN0eWxlPSJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij4gCgojIEludHJvZHVjdGlvbiAgCgpUaGlzIGRvY3VtZW50IG91dGxpbmVzIHRoZSBhbmFseXNlcyBmcm9tIFN0dWR5IDEgaW4gKippbnNlcnQgYXJ0aWNsZSB0aXRsZSBoZXJlKiogKCoqaW5zZXJ0IGF1dGhvcnMqKiwgMjAyMCkuIFRoZSBwdXJwb3NlIG9mIHRoaXMgc3R1ZHkgd2FzIHRvIGludmVzdGlnYXRlIFdhcmQgZXQgYWwuJ3MgKDIwMTcpIHNlY29uZCBleHBlcmltZW50IGJ5IGNvbXBsZXRpbmcgYSBkaXJlY3QgcmVwbGljYXRpb24uIFRoZXJlZm9yZSwgdGhlIHByZXNlbnQgc3R1ZHkgaW52ZXN0aWdhdGVkIGhvdyB0aGUgbWVyZSBwcmVzY2VuY2Ugb2Ygb25lJ3Mgc21hcnRwaG9uZSBlZmZlY3RzIGNvZ250aWlvbi4gVGhpcyB3YXMgcHJlLXJlZ2lzdGVyZWQgdGhyb3VnaCBPU0YgYW5kIGNhbiBiZSBmb3VuZCBhdCB0aGUgZm9sbG93aW5nIGxpbms6IDxodHRwczovL29zZi5pby81ZnE0cj4uCgpUaGUgbWFpbiBnb2FsIG9mIHRoZSBjdXJyZW50IHN0dWR5IHdhcyB0byBzZWUgaWYgIFdhcmQgZXQgYWwu4oCZcyBmaW5kaW5ncyByZXBsaWNhdGVkIChleHBlcmltZW50IHR3bykuIFRoZXJlZm9yZSwgYXMgaW4gV2FyZCBldCBhbC4sIHBhcnRpY2lwYW50cyB3ZXJlIHJhbmRvbWx5IGFzc2lnbmVkIHRvIG9uZSBvZiAqc2l4KiBwb3NzaWJsZSBjb25kaXRpb25zLiBUaGVzZSBjb25kaXRpb25zIHdlcmUgYmFzZWQgb24gdHdvIGluZGVwZW5kZW50IHZhcmlhYmxlczogKipzbWFydHBob25lIGxvY2F0aW9uKiogYW5kICoqc21hcnRwaG9uZSBwb3dlcioqLiBGb3Igc21hcnRwaG9uZSBsb2NhdGlvbiwgYSBwYXJ0aWNpcGFudCdzIHNtYXJ0cGhvbmUgd2FzIGluIG9uZSBvZiB0aHJlZSBsb2NhdGlvbnM6ICgxKSBvbiB0aGUgcGFydGljaXBhbnTigJlzIGRlc2sgKCJvbiBkZXNrIiksICgyKSBpbiB0aGVpciBwb2NrZXQvYmFnICgicG9ja2V0L2JhZyIpLCBvciAoMykgb3V0c2lkZSB0aGUgdGVzdGluZyByb29tICgib3V0c2lkZSIpLiBGb3Igc21hcnRwaG9uZSBwb3dlciwgYSBwYXJ0aWNpcGFudCdzIHNtYXJ0cGhvbmUgd2FzIGVpdGhlciAoMSkgcG93ZXJlZCBPTiBvciAoMikgcG93ZXJlZCBPRkYsIGluIHRoZWlyIHJlc3BlY3RpdmUgbG9jYXRpb24uIApGb3IgYWxsIGNvbmRpdGlvbnMsIHBhcnRpY2lwYW50cyB3ZXJlIGluc3RydWN0ZWQgdG8ga2VlcCB0aGVpciBzbWFydHBob25lcyBvbiBzaWxlbnQgKGkuZS4sIG5vIHZpcmJhdGlvbnMgaWYgYW55IG5vdGlmaWNhdGlvbnMgYXJlIHJlY2VpdmVkIGR1cmluZyB0aGUgc3R1ZHkpLiBBbHNvLCBhcyBwZXIgV2FyZCBldCBhbC4sIHBhcnRpY2lwYW50cyBpbiB0aGUgIm9uIGRlc2siIGxvY2F0aW9uIGNvbmRpdGlvbnMgd2VyZSBpbnN0cnVjdGVkIHRvIGtlZXAgdGhlaXIgZGV2aWNlcyBmYWNpbmcgdXAuCgpFYWNoIHBhcnRpY2lwYW50IGNvbXBsZXRlZCAqKnR3byBtYWluIHRhc2tzKiogKGNvdW50ZXItYmFsYW5jZWQpOgoKKioxLiBBbiBBdXRvbWF0ZWQgT3BlcmF0aW9uIFNwYW4gKE9TcGFuKSBUYXNrKiogKFVuc3dvcnRoIGV0IGFsLiwgMjAwNSksIHdoaWNoIHJlcXVpcmVkIHBhcnRpY2lwYW50cyB0byByZXRhaW4gbGV0dGVyIHN0cmluZ3MgKGkuZS4gcmFuZ2luZyBmcm9tIHRocmVlIHRvIHNldmVuIGxldHRlcnMgaW4gbGVuZ3RoKSBpbiBtZW1vcnkgd2hpbGUgc29sdmluZyBzb21lIHNpbXBsZSBtYXRoIHByb2JsZW1zIChlLmcuIOKAnCg3LzcpICsgNiA9ID/igJ0pLiBUaGlzIHRhc2sgd2FzIGEgYmVoYXZpb3VyYWwgbWVhc3VyZSBvZiB0aGUgYXR0ZW50aW9uYWwgY29udHJvbCBjb21wb25lbnQgb2Ygd29ya2luZyBtZW1vcnkuIAoKLSBTY29yaW5nOiAKICAgIC0gUGVyZm9ybWFuY2UsIG1lYXN1cmVkIHdpdGggdGhlIE9TcGFuIGFic29sdXRlIHNjb3JlLCB3YXMgc2hvd24gYnkgaG93IG1hbnkgdHJpYWxzIGEgcGFydGljaXBhbnQgY29ycmVjdGx5IHJlY2FsbGVkIGFsbCB0aGUgbGV0dGVycyBpbiBhIGdpdmVuIGJsb2NrICg3NSBibG9ja3MgaW4gdG90YWwpLiBGb3IgZXhhbXBsZSwgYSBwYXJ0aWNpcGFudCB3aG8gcmVjYWxsZWQgdGhyZWUgbGV0dGVycyAoaW4gYSBibG9jayB3aXRoIHRocmVlIGxldHRlcnMpLCBmaXZlIGxldHRlcnMgKGluIGEgYmxvY2sgd2l0aCBmaXZlIGxldHRlcnMpLCBhbmQgdHdvIGxldHRlcnMgKGluIGEgYmxvY2sgd2l0aCBzaXggbGV0dGVycykgd291bGQgaGF2ZSBhbiBPU3BhbiBhYnNvbHV0ZSBzY29yZSBvZiBlaWdodCBmb3IgdGhvc2UgYmxvY2tzIChpLmUuIDMgKyA1ICsgMCA9IDgpLiBUaGVyZWZvcmUsIE9TcGFuIGFic29sdXRlIHNjb3JlIHNob3dlZCBwZXJmb3JtYW5jZSB3aGVyZSBoaWdoZXIgc2NvcmVzIHJlcHJlc2VudGVkIGJldHRlciBwZXJmb3JtYW5jZS4KCioqMi4gVGhlIEN1ZS1EZXBlbmRlbnQgR28vTm8tR28gVGFzayoqIChCZXpkamlhIGV0IGFsLiwgMjAwOSksIHdoaWNoIHJlcXVpcmVkIHBhcnRpY2lwYW50cyB0byByZXNwb25kIHRvICJnbyIgdGFyZ2V0cyAoaS5lLiBncmVlbiByZWN0YW5nbGUpIHdoaWxlIHdpdGhob2xkaW5nIGFueSByZXNwb25zZSB0byAibm8tZ28iIHRhcmdldHMgKGkuZS4gYmx1ZSByZWN0YW5nbGUpLiBUaGlzIHRhc2sgaW5jbHVkZWQgYSBjdWUgY29tcG9uZW50LCB3aGVyZSB2ZXJ0aWNhbCB0YXJnZXRzIChpLmUuLCByZWN0YW5nbGVzKSB3ZXJlIG1vcmUgbGlrZWx5IHRvIGJlICJnbyIgdGFyZ2V0cyAoaS5lLiA4MCUgImdvIiBhbmQgMjAlICJuby1nbyIpIGFuZCBob3Jpem9udGFsIHRhcmdldHMgd2VyZSBtb3JlIGxpa2VseSB0byBiZSAibm8tZ28iIHRhcmdldHMgKGkuZS4gODAlICJuby1nbyIgYW5kIDIwJSAiZ28iKS4gUGFydGljaXBhbnRzIHdlcmUgbm90IGV4cGxpY2l0bHkgbWFkZSBhd2FyZSBvZiB0aGUgY3VlIGNvbXBvbmVudC4gVGhpcyB0YXNrIHdhcyBhIGJlaGF2aW91cmFsIG1lYXN1cmUgb2Ygc3VzdGFpbmVkIGF0dGVudGlvbi4KCi0gU2NvcmluZzoKICAgIC0gUGVyZm9ybWFuY2Ugd2FzIG1lYXN1cmVkIHdpdGggbWVhbiBvbWlzc2lvbiBlcnJvcnMgYW5kIFJULiBJdCBzaG91bGQgYmUgbm90ZWQgdGhhdCBtZWFuIGVycm9ycyBjYW4gYmUgZGl2aWRlZCBpbnRvIHRvdGFsIGVycm9yLCBjb21taXNzaW9uIGVycm9yLCBhbmQgb21pc3Npb24gZXJyb3IuIENvbW1pc3Npb24gZXJyb3JzIG9jY3VycmVkIHdoZW4gYSBwYXJ0aWNpcGFudCByZXNwb25kZWQgdG8gYSB0YXJnZXQgc3RpbXVsdXMuIE9taXNzaW9uIGVycm9ycyBvY2N1cnJlZCB3aGVuIGEgcGFydGljaXBhbnQgZmFpbGVkIHRvIHJlc3BvbmQgdG8gYSBub24tdGFyZ2V0IHN0aW11bHVzLiBUb3RhbCBlcnJvcnMgd2VyZSB0aGUgc3VtIG9mIGNvbW1pc3Npb24gYW5kIG9taXNzaW9uIGVycm9ycy4gVGhlIHByZXNlbnQgc3R1ZHkgZm9jdXNlZCBvbiBtZWFuIG9taXNzaW9uIGVycm9ycy4gVGhlcmVmb3JlLCBmb3IgZWFjaCBwYXJ0aWNpcGFudCwgaGlnaGVyIG1lYW4gb21pc3Npb24gZXJyb3JzIHJlcHJlc2VudGVkIGxvd2VyIHBlcmZvcm1hbmNlLiBBZGRpdGlvbmFsbHksIGhpZ2hlciBtZWFuIFJUIGFsc28gc2hvd2VkIGxvd2VyIHBlcmZvcm1hbmNlIChpLmUuIGluZGljYXRpdmUgb2YgZ3JlYXRlciBpbnRlcmZlcmVuY2UpLgoKRmluYWxseSwgYWZ0ZXIgY29tcGxldGluZyBib3RoIHRhc2tzLCBhbGwgcGFydGljaXBhbnRzIGNvbXBsZXRlZCAqKnRocmVlKiogc3VydmV5IG1lYXN1cmVzOiAgCgoqKjEuIFRoZSBEZW1vZ3JhcGhpYyBRdWVzdGlvbm5haXJlKiosIHdoaWNoIHdhcyBjcmVhdGVkIGZvciB0aGUgcHJlc2VudCBzdHVkeSBhbmQgY29uc2lzdGVkIG9mIGZvdXIgaXRlbXM6IGFnZSAoaS5lLiBpbiB5ZWFycyksIGdlbmRlciAoaS5lLiBtYWxlLCBmZW1hbGUsIG90aGVyLCBvciBwcmVmZXIgbm90IHRvIHNheSksIHByb2dyYW0gKGUuZy4gcHN5Y2hvbG9neSwgZW5naW5lZXJpbmcpLCBhbmQgeWVhciBvZiBzdHVkeSAoZS5nLiBmaXJzdCwgZm91cnRoKS4gVGhlIHB1cnBvc2Ugb2YgdGhlc2UgaXRlbXMgd2FzIHRvIGdpdmUgYSBicmllZiBkZXNjcmlwdGlvbiBvZiB0aGUgc2FtcGxlLiAKCioqMi4gVGhlIFNtYXJ0cGhvbmUgVXNhZ2UgUXVlc3Rpb25uYWlyZSAoU1VRKSoqLCB3aGljaCB3YXMgY3JlYXRlZCBmb3IgdGhlIHByZXNlbnQgc3R1ZHkgYW5kIGNvbnNpc3RlZCBvZiBtb2RpZmllZCBpdGVtcyBmcm9tIFdhcmQgZXQgYWwu4oCZcyBzdXJ2ZXkgbWVhc3VyZXMgKGkuZS4gZm91bmQgaW4gdGhlIOKAnEJSQUlOIERSQUlO4oCdIFdFQiBBUFBFTkRJWOKAnSkuIFNvbWUgaXRlbXMgd2VyZSBmb3JjZWQtY2hvaWNlIGFuZCBzb21lIHdlcmUgb24gYSA3LXBvaW50IGxpa2VydCBzY2FsZSByYW5naW5nIGZyb20gMSAo4oCcTmV2ZXLigJ0pIHRvIDcgKOKAnEFsd2F5c+KAnSkuIFRoZXJlIHdlcmUgMTAgaXRlbXMgaW4gdG90YWwgYW5kIHRoZXJlIHdlcmUgZml2ZSB0eXBlcyBvZiBpdGVtcywgd2hpY2ggbWVhc3VyZWQ6ICgxKSBzbWFydHBob25lIHVzZSBmcmVxdWVuY3kgKHRocmVlIGl0ZW1zOyBlLmcuIOKAnE9uIGF2ZXJhZ2UsIGhvdyBtYW55IHRleHQgbWVzc2FnZXMgZG8geW91IHNlbmQgcGVyIGRheT/igJ0pOyAoMikgc21hcnRwaG9uZSB1c2Ugd2l0aG91dCBleHRlcm5hbCBzdGltdWxhdGlvbiAodHdvIGl0ZW1zOyBlLmcuIOKAnElmIEkgYW0gd2FpdGluZyB0byBtZWV0IGEgZnJpZW5kLCBJIHBhc3MgdGhlIHRpbWUgYnkgdXNpbmcgbXkgc21hcnRwaG9uZS7igJ0pLCBvciBkdXJpbmcgb3RoZXIgYWN0aXZpdGllcyAodHdvIGl0ZW1zOyBlLmcuIOKAnEkgdXNlIG15IHNtYXJ0cGhvbmUgd2hpbGUgZHJpdmluZy7igJ0pOyAoMykgc21hcnRwaG9uZSBzdWJqZWN0aXZlIHZhbHVlIChvbmUgaXRlbTsgZS5nLiDigJxIb3cgbXVjaCBtb25leSB3b3VsZCBpdCB0YWtlIGZvciB5b3UgdG8gZ2l2ZSB1cCB5b3VyIHBob25lIGZvciBhIGZ1bGwgZGF5P+KAnSk7ICg0KSBzbWFydHBob25lIG5vdGlmaWNhdGlvbiB0eXBlIChvbmUgaXRlbTsgZS5nLiDigJxEbyB5b3UgcmVjZWl2ZSBub3RpZmljYXRpb25zIChhIHNvdW5kIG9yIHZpYnJhdGlvbikgb24geW91ciBwaG9uZT8gUGxlYXNlIGluZGljYXRlIGFsbCB0aGF0IGFwcGx5LuKAnSk7IGFuZCAoNSkgcGhhbnRvbSB2aWJyYXRpb25zIChvbmUgaXRlbTsgZS5nLiDigJxIYXZlIHlvdSBldmVyIHRob3VnaHQgeW91IGhlYXJkIHlvdXIgcGhvbmUgcmluZyBvciB0aG91Z2h0IHlvdSBmZWx0IGl0IHZpYnJhdGUsIG9ubHkgdG8gZmluZCBvdXQgeW91IHdlcmUgd3Jvbmc/4oCdKS4gVGhlIHB1cnBvc2Ugb2YgdGhlIFNVUSB3YXMgdG8gbWVhc3VyZSBwYXJ0aWNpcGFudHMnIHR5cGljYWwgc21hcnRwaG9uZSB1c2UuIAoKKiozLiBTbWFydHBob25lIEF0dGFjaG1lbnQgYW5kIERlcGVuZGVuY3kgSW52ZW50b3J5IChTQUQpKiosIHdoaWNoIHdhcyBmcm9tIFdhcmQgZXQgYWwuJ3MgKDIwMTcpIHN0dWR5LiBUaGUgU0FEIHVzZWQgMTMtaXRlbXMgKGkuZS4gNy1wb2ludCBsaWtlcnQgc2NhbGUpIHRoYXQgYXNrZWQgcGFydGljaXBhbnRzIHRvIHJhdGUgKGkuZS4sIGZyb20gMSA9ICpTdHJvbmdseSBEaXNhZ3JlZSogdG8gNyA9ICpTdHJvbmdseSBBZ3JlZSopIGhvdyBtdWNoIHRoZXkgYWdyZWVkIHdpdGggc3RhdGVtZW50cyByZWdhcmRpbmcgdGhlaXIgZW1vdGlvbmFsIGF0dGFjaG1lbnQgYW5kIGRlcGVuZGVuY3kgb24gdGhlaXIgc21hcnRwaG9uZXMuIFRoZSBwdXJwb3NlIG9mIHRoZSBTQUQgd2FzIHRvIG1lYXN1cmUgZWFjaCBwYXJ0aWNpcGFudOKAmXMgcmVsaWFuY2Ugb24gdGhlaXIgc21hcnRwaG9uZS4KCi0gU2NvcmluZzoKICAgIC0gU21hcnRwaG9uZSByZWxpYW5jZSB3YXMgY2FsY3VsYXRlZCB3aXRoIGEgc3VtIHRvdGFsIGZvciBhbGwgaXRlbXMgd2l0aCBhIHJhbmdlIG9mIDEzIHRvIDkxLiBIaWdoZXIgc2NvcmVzIGluZGljYXRlZCBhIGhpZ2hlciBsZXZlbCBvZiByZWxpYW5jZSB3aXRoIHRocmVlIGxldmVsczogbG93IHJlbGlhbmNlICgxMy0zOSksIG1vZGVyYXRlIHJlbGlhbmNlICg0MC02NSksIGFuZCBoaWdoIHJlbGlhbmNlICg2NispLgoKQSB0b3RhbCBvZiAqKmByIGxlbmd0aChhbGxfcGFydGljaXBhbnRzJGFsbF9wYXJ0aWNpcGFudHMpYCoqIHVuZGVyZ3JhZHVhdGUgc3R1ZGVudHMgcGFydGljaXBhdGVkIGluIHRoaXMgc3R1ZHkuIE9mIHRoZSB0b3RhbCBzYW1wbGUgc2l6ZSwgKipgciBsZW5ndGgoYWxsX3JlbW92ZSRhbGxfcGFydGljaXBhbnRzKWAqKiBwYXJ0aWNpcGFudHMgd2VyZSBleGNsdWRlZCBkdWUgdG8gZWl0aGVyIHRlc3RpbmcgZXJyb3IgKGByIGxlbmd0aChhbGxfcmVtb3ZlJGFsbF9wYXJ0aWNpcGFudHNbd2hpY2goYWxsX3JlbW92ZSRyZWFzb25fcmVtb3ZlID09ICJnbmciKV0pYDsgZS5nLiBpbmNvbXBsZXRlIHRhc2sgZGF0YSksIG9yIGV4cGVyaW1lbnRlciBvciBleHRlcm5hbCBjb25mb3VuZHMgKGByIGxlbmd0aChhbGxfcmVtb3ZlJGFsbF9wYXJ0aWNpcGFudHNbd2hpY2goYWxsX3JlbW92ZSRyZWFzb25fcmVtb3ZlID09ICJ0cmFjayIpXSlgOyBlLmcuIGludGVycnVwdGlvbiBkdXJpbmcgdGVzdGluZywgZGlzdHJhY3Rpbmcgbm9pc2UgZHVyaW5nIHRlc3RpbmcpLiBUaGVyZWZvcmUsICoqYHIgbGVuZ3RoKGFsbF9kYXRhJHBhcnRpY2lwYW50KWAqKiBwYXJ0aWNpcGFudHMgd2VyZSBpbmNsdWRlZCBpbiB0aGUgYW5hbHlzZXMgZm9yIHRoZSBsb2NhdGlvbiAob24gZGVzayA9IGByIGxlbmd0aCh3aGljaChhbGxfZGF0YSRsb2NhdGlvbiA9PSAxKSlgOyBwb2NrZXQvYmFnID0gYHIgbGVuZ3RoKHdoaWNoKGFsbF9kYXRhJGxvY2F0aW9uID09IDIpKWA7IG91dHNpZGUgPSBgciBsZW5ndGgod2hpY2goYWxsX2RhdGEkbG9jYXRpb24gPT0gMykpYCkgYW5kIHBvd2VyIChPTiA9IGByIGxlbmd0aCh3aGljaChhbGxfZGF0YSRwb3dlciA9PSAxKSlgOyBPRkYgPSBgciBsZW5ndGgod2hpY2goYWxsX2RhdGEkcG93ZXIgPT0gMikpYCkgY29uZGl0aW9uLgoKIyBEYXRhIEFuYWx5c2lzIFBsYW4gIApUaGUgcHJlc2VudCBzdHVkeSBjb21wbGV0ZWQgYSBwcmUtcmVnaXN0ZXJlZCBkYXRhIGFuYWxseXNpcyAocHJlLXJlZ2lzdGVyZWQgZGlyZWN0IHJlcGxpY2F0aW9uIG9uIE9wZW4gU2NpZW5jZSBGcmFtZXdvcms7IE9TRikuIEJlbG93IGlzIGEgc3VtbWFyeSBvZiB0aGUgZGF0YSBhbmFseXNpcyBwbGFuICh2aWV3IGZ1bGwgdmVyc2lvbiA8aHR0cHM6Ly9vc2YuaW8vZDVlamE+ICYgPGh0dHBzOi8vb3NmLmlvL3B0YzdrLz4pLiAgCgojIyBIeXBvdGhlc2VzCgoxLiBUaGUgKipsb2NhdGlvbiBlZmZlY3QgaHlwb3RoZXNpcyoqIHByZWRpY3RlZCB0aGF0IHRob3NlIHdobyB3ZXJlIGNsb3Nlc3QgaW4gcHJveGltaXR5IHRvIHRoZWlyIHNtYXJ0cGhvbmUgKGkuZS4gdGhvc2Ugd2l0aCB0aGVpciBzbWFydHBob25lcyBvbiB0aGVpciBkZXNrKSB3b3VsZCBzaG93IGxvd2VyIHBlcmZvcm1hbmNlIG9uIHRoZSBPU3BhbiB0YXNrLiAgCgoyLiBUaGUgKipwb3dlciBlZmZlY3QgaHlwb3RoZXNpcyoqIHByZWRpY3RlZCB0aGF0IHNtYXJ0cGhvbmUgcG93ZXIgKGkuZS4gZWl0aGVyIE9OIG9yIE9GRikgd291bGQgbm90IGFmZmVjdCBwZXJmb3JtYW5jZSBvbiBib3RoIGNvZ25pdGl2ZSB0YXNrcy4gIAogIAozLiBUaGUgKiptb2RlcmF0aW9uIGVmZmVjdCBoeXBvdGhlc2lzKiogcHJlZGljdGVkIHRoYXQgc21hcnRwaG9uZSBhdHRhY2htZW50IGFuZCBkZXBlbmRlbmN5IChpLmUuIFNBRCBzY29yZSkgd291bGQgbW9kZXJhdGUgdGhlIGxvY2F0aW9uIGVmZmVjdDogdGhvc2Ugd2hvIHJlcG9ydGVkIGhpZ2hlciBzbWFydHBob25lIGF0dGFjaG1lbnQgYW5kIGRlcGVuZGVuY3kgd291bGQgcGVyZm9ybSB3b3JzZSBvbiB0aGUgT1NwYW4gdGFzay4gIAoKKk5vdGU6IEFsbCBoeXBvdGhlc2VzIHdlcmUgYmFzZWQgb24gdGhlIGZpbmRpbmdzIGZyb20gV2FyZCBldCBhbC4gKDIwMTcpKgoKIyMgSW5jbHVzaW9uIC8gRXhjbHVzaW9uIENyaXRlcmlhCgpUaGVyZSB3ZXJlICoqdHdvKiogZXhjbHVzaW9uIGNyaXRlcmEgaW4gdGhlIHByZXNlbnQgc3R1ZHk6ICAKCioqMS4gT1NwYW4gVGFzayoqIAoKICAtIE9ubHkgZGF0YSBmcm9tIHBhcnRpY2lwYW50cyB3aG8gc2NvcmVkIDg1JSBhY2N1cmFjeSBvbiB0aGUgbWF0aCBjb21wb25lbnQgb3IgYWJvdmUgd2FzIHVzZWQuCiAgICAtIENyaXRlcmlhIGhlbHBlZCBjb250cm9sIGZvciBhbnkgcGFydGljaXBhbnRzIHdobyBkaWQgbm90IGZvbGxvdyBpbnN0cnVjdGlvbnMgYW5kIG5lZ2xlY3RlZCB0aGUgbWF0aCBjb21wb25lbnQgb2YgdGhlIHRhc2suCiAgKk5vdGU6IFRoaXMgd2FzIHRoZSBzYW1lIGNyaXRlcmlhIGFzIGluIFdhcmQgZXQgYWwuICgyMDE3KSogIAogICAgCioqMi4gQ3VlLURlcGVuZGVudCBHby9Oby1HbyBUYXNrKiogIAoKICAtIE9ubHkgZGF0YSBmcm9tIHRob3NlIHdobyBzY29yZWQgaGlnaGVyIHRoYW4gY2hhbmNlIHBlcmZvcm1hbmNlIHdhcyB1c2VkIChlLmcuIHJlcG9uZGVkIHRvIGF0IGxlYXN0IDUwJSBvZiAiR28iIHRyaWFscyBhbmQgd2l0aGhlbGQgcmVzcG9uc2UgdG8gYXQgbGVhc3QgNTAlIG9mICJOby1HbyIgdHJpYWxzKS4KICAgIC0gQ3JpdGVyaWEgaGVscGVkIGNvbnRyb2wgZm9yIGFueSBwYXJ0aWNpcGFudHMgd2hvIGRpZCBub3QgY29tcGxldGUgdGhlIHRhc2sgYXMgaW5zdHJ1Y3RlZCAoZS5nLiBndWVzc2luZykuCiAgKk5vdGU6IFRoZXJlIHdhcyBubyBpbmNsdXNpb24vZXhjbHVzaW9uIGNyaXRlcmlhIGZvciB0aHNpIHRhc2sgaW4gV2FyZCBldCBhbC4gKDIwMTcpKiAgCgojIyBBbmFseXNpcwoKIyMjIFRlc3RpbmcgdGhlIExvY2F0aW9uIGFuZCBQb3dlciBIeXBvdGhlc2VzOiAgCgoqKjEuIE9TcGFuIFRhc2sqKiAgCgotIFRoZSBPU3BhbiBhYnNvbHV0ZSBzY29yZSB3YXMgdXNlZCB0byBtZWFzdXJlIE9TcGFuIHBlcmZvcm1hbmNlLgotIEEgKiozKHNtYXJ0cGhvbmUgbG9jYXRpb246IGRlc2ssIHBvY2tldC9iYWcsIG91dHNpZGUpIHggMihzbWFydHBob25lIHBvd2VyOiBPTiwgT0ZGKSoqIGJldHdlZW4tc3ViamVjdHMgQU5PVkEgd2FzIGNvbmR1Y3RlZCAqKihEViA9IE9TcGFuIGFic29sdXRlIHNjb3JlKSoqLiAgCiAgLSBQb3N0LWhvY3MgY29tcGxldGVkIGlmIHRoZXJlIHdhcyBhIHNpZ25pZmljYW50IEFOT1ZBICgkXGFscGhhID0gMC4wNSQpIHRvIGRldGVybWluZSB3aGljaCBsb2NhdGlvbihzKSBhbmQvb3IgcG93ZXIgc3RhdHVzIHdlcmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQuCiAgCioqMi4gQ3VlLURlcGVuZGVudCBHby9Oby1HbyBUYXNrKiogIAoKLSBBbiBlcnJvciAoaS5lLiBvbWlzc2lvbiBlcnJvcnMpIGFuZCBhY2N1cmFjeSAoaS5lLiBSVCkgYW5hbHlzaXMgd2FzIGNvbXBsZXRlZCB1c2luZyB0aGUgYXZlcmFnZSBvbWlzc2lvbiBlcnJvcnMgYW5kIFJUIGZvciBlYWNoIHBhcnRpY2lwYW50LiAgCgogICoqKGEpIEVycm9yIEFuYWx5c2lzKiogIAogICAgLSBBICoqMyhTbWFydHBob25lIGxvY2F0aW9uOiBkZXNrLCBwb2NrZXQvYmFnLCBvdXRzaWRlKSB4IDIoU21hcnRwaG9uZSBwb3dlcjogT04sIE9GRikgeCAyKEN1ZSB0eXBlOiBHbywgTm8tR28pIG1peGVkIEFOT1ZBKiogd2FzIGNvbXBsZXRlZCAqKihEViA9IGF2ZXJhZ2Ugb21pc3Npb24gZXJyb3IocykpKiouICAKICAgICAgLSBUaGUgYmV0d2Vlbi1zdWJqZWN0cyBmYWN0b3JzOnNtYXJ0cGhvbmUgbG9jYXRpb24gYW5kIHBvd2VyICAKICAgICAgLSBUaGUgd2l0aGluLXN1YmplY3RzIGZhY3RvcjogcHJlLXRhcmdldCBjdWUgdHlwZSAgCiAgICAgIC0gUG9zdC1ob2NzIGNvbXBsZXRlZCBpZiB0aGVyZSB3YXMgYSBzaWduaWZpY2FudCBBTk9WQSAoJFxhbHBoYSA9IDAuMDUkKSB0byBkZXRlcm1pbmUgd2hpY2ggbG9jYXRpb24ocyksIHBvd2VyIHN0YXR1cywgYW5kL29yIGN1ZSB0eXBlKHMpIHdlcmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQuICAKICAgIAogICoqKGIpIEFjY3VyYWN5IEFuYWx5c2lzKiogIAogICAgLSBBICoqMyhzbWFydHBob25lIGxvY2F0aW9uOiBkZXNrLCBwb2NrZXQvYmFnLCBvdXRzaWRlKSB4IDIoc21hcnRwaG9uZSBwb3dlcjogT04sIE9GRikqKiBiZXR3ZWVuLXN1YmplY3RzIEFOT1ZBIHdhcyBjb25kdWN0ZWQgKiooRFYgPSBhdmVyYWdlIFJUKSoqLiAgCiAgICAgIC0gVGhlIGJldHdlZW4tc3ViamVjdHMgZmFjdG9yczpzbWFydHBob25lIGxvY2F0aW9uIGFuZCBwb3dlciAgCiAgICAgIC0gVGhlIHdpdGhpbi1zdWJqZWN0cyBmYWN0b3I6IHByZS10YXJnZXQgY3VlIHR5cGUgIAogICAgICAtIFBvc3QtaG9jcyBjb21wbGV0ZWQgaWYgdGhlcmUgd2FzIGEgc2lnbmlmaWNhbnQgQU5PVkEgKCRcYWxwaGEgPSAwLjA1JCkgdG8gZGV0ZXJtaW5lIHdoaWNoIGxvY2F0aW9uKHMpIGFuZC9vciBwb3dlciBzdGF0dXMgd2VyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudC4gIAoKIyMjIFRlc3RpbmcgdGhlIE1vZGVyYXRpb24gSHlwb3RoZXNpczogIAoKKiozLiBTQUQgKiogIAoKKiooYSkgRmFjdG9yIEFuYWx5c2lzKiogIAoKICAtIEEgcHJpbmNpcGFsIGNvbXBvbmVudHMgZmFjdG9yIGFuYWx5c2lzIHdpdGggYSBWYXJpbWF4IHJvdGF0aW9uIHdhcyBjb21wbGV0ZWQgZm9yIHBhcnRpY2lwYW50J3MgU0FEIHNjb3JlLgogICAgLSBUaGlzIHdhcyBkb25lIHRvIGNvbmZpcm0gdGhlIHR3byBtYWluIGZhY3RvcnMgZm91bmQgYnkgV2FyZCBldCBhbC4gKDIwMTcpOiBzbWFydHBob25lIGRlcGVuZGVuY2UgYW5kIGVtb3Rpb25hbCBhdHRhY2htZW50LiAgCgoqKihiKSBHZW5lcmFsaXplZCBMaW5lYXIgTW9kZWwqKiAgCgogIC0gQSB1bml2YXJpYXRlIGdlbmVyYWxpemVkIGxpbmVhciBtb2RlbCB3YXMgdXNlZCB0byBleGFtaW5lIGlmIHNtYXJ0cGhvbmUgcmVsaWFuY2UgKGkuZS4gU0FEIHNjb3JlKSB3YXMgYSBtb2RlcmF0b3Igb2YgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBleHBlcmltZW50YWwgbWFuaXB1bGF0aW9uIGFuZCB0YXNrIHBlcmZvcm1hbmNlLiAKCipOb3RlOiBUaGVzZSBhbmFseXNpcyB3ZXJlIGNvbXBsZXRlZCByZWdhcmRsZXNzIG9mIHRoZSByZXN1bHRzIGZvciB0aGUgbG9jYXRpb24gYW5kIHBvd2VyIGh5cG90aGVzZXMuKiAgCgojIEFuYWx5c2lzIFByZXAgIAojIyBMb2FkIFJlcXVpcmVkIExpYnJhcmllcwoKVGhlIGZvbGxvd2luZyBwYWNrYWdlcyB3ZXJlIHVzZWQgdG8gY29tcGxldGUgdGhlIGFuYWx5c2VzLCB2aXN1YWxpemF0aW9ucywgZXRjLiBpbiB0aGlzIGRvY3VtZW50LiAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgQ29kZSBoYXMgYmVlbiBjb21tZW50ZWQgb3V0IHRvIHJlZHVjZSBjb21wdXRhdGlvbiB0aW1lLCB1bmNvbW1lbnQgYW55IHRvIHJ1biB0aGUgY29kZQoKIyBsaWJyYXJ5KGRldnRvb2xzKQojIGluc3RhbGxfZ2l0aHViKCJ2cXYvZ2diaXBsb3QiKQpsaWJyYXJ5KGdnYmlwbG90KQpsaWJyYXJ5KHdlbGNoQURGKQpsaWJyYXJ5KHNjaG9Sc2NoKQpsaWJyYXJ5KHBseXIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkobGF0dGljZSkKbGlicmFyeShjYXIpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3B1YnIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShleikKbGlicmFyeShIbWlzYykKbGlicmFyeShyc3RhdGl4KQpsaWJyYXJ5KHB1cnJyKQpsaWJyYXJ5KEZvcm11bGEpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KHBzeWNoKQpsaWJyYXJ5KHN1cnZpdmFsKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShEZXNjVG9vbHMpCmxpYnJhcnkoR1BBcm90YXRpb24pCmxpYnJhcnkoYXBhVGFibGVzKQoKCmBgYAoKIyMgQWRkaXRpb25hbCBGdW5jdGlvbnMKCiMjIyBSb3VuZGluZyBwLXZhbHVlcwoKVGhpcyByb3VuZGluZyBmdW5jdGlvbiB3YXMgYWRhcHRlZCBmcm9tIFtFbWlseSBOaWVsc2VuJ3MgUnB1YnNdKGh0dHBzOi8vcnB1YnMuY29tL2VnbmllbHNlbikuIFRoZSBmdW5jdGlvbiAoIioqcF9yb3VuZCh4KSoqIikgd2FzIGNyZWF0ZWQgdG8gYXNzZXNzIGFuZCBwcmludCBwLXZhbHVlcy4gSWYgJHAgXGdlIC4wMDUkLCB0aGUgZnVuY3Rpb24gd2lsbCBkaXNwbGF5IOKAnCRwID0gJOKAnSBhbmQgdGhlIHZhbHVlIHJvdW5kZWQgdG8gdHdvIGRlY2ltYWwgcGxhY2VzLiBJZiAkIC4wMDA1IFxsZSBwIDwuMDA1JCwgdGhlIGZ1bmN0aW9uIHdpbGwgZGlzcGxheSDigJwkcCA9ICTigJ0gYW5kIHRoZSB2YWx1ZSByb3VuZGVkIHRvIHRocmVlIGRlY2ltYWwgcGxhY2VzLiBJZiAkcCA8IC4wMDA1JCwgdGhlIGZ1bmN0aW9uIHdpbGwgZGlzcGxheSDigJwkcCA8IC4wMDEk4oCdLgoKYGBge3J9CgpwX3JvdW5kIDwtIGZ1bmN0aW9uKHgpewogIGlmKHggPiAuMDA1KQogICAge3gxID0gKHBhc3RlKCI9ICIsIGdzdWIoIjBcXC4iLCJcXC4iLCByb3VuZCh4LCBkaWdpdHMgPSAyKSksIHNlcCA9ICcnKSkKICB9ICAKICBlbHNlIGlmKHggPT0gLjAwNSl7eDEgPSAocGFzdGUoIj0iLCBnc3ViKCIwXFwuIiwiXFwuIiwgMC4wMSkpKQogIH0KICBlbHNlIGlmKHggPiAuMDAwNSAmIHggPCAuMDA1KQogICAge3gxID0gKHBhc3RlKCI9ICIsIGdzdWIoIjBcXC4iLCJcXC4iLCByb3VuZCh4LCBkaWdpdHMgPSAzKSksIHNlcCA9ICcnKSkKICB9ICAKICBlbHNlIGlmKHggPT0gLjAwMDUpe3gxID0gKHBhc3RlKCI9IiwgZ3N1YigiMFxcLiIsIlxcLiIsIDAuMDAxKSkpCiAgfQogIGVsc2V7eDEgPSAocGFzdGUoIjwiLCBnc3ViKCIwXFwuIiwiXFwuIiwgMC4wMDEpKSkKICB9IAogICh4MSkKfQoKYGBgCgojIyBSYXcgRGF0YSAgClRoZXJlIGFyZSAqKmZpdmUqKiByYXcgZGF0YSBmaWxlcyB0aGF0IHdlcmUgaW1wb3J0ZWQgZm9yIHRoZSBwcmVzZW50IHN0dWR5IChzZWUgdGhlICpJbXBvcnQgUmF3IERhdGEqIHNlY3Rpb24pLiAgCgoqKlRhc2sgRGF0YSoqICAKCjEuIE9TcGFuIFJhdyBEYXRhICAKICAgIC0gc3ByZWFkc2hlZXQsIGNvbGxlY3RlZCBtYW51YWxseSBmcm9tIGVhY2ggcGFydGljaXBhbnQKMi4gR28vTm8tR28gUmF3IERhdGEgIAogICAgLSBwc3ljaG9weSBleGNlbCBmaWxlcyAKICAgIC0gKk5vdGU6KiByYXcgZGF0YSB3YXMgZXh0cmFjdGVkIGZyb20gZm9sZGVyIGludG8gb25lIGZpbGUgKHNlZSB0aGUgKkltcG9ydCBSYXcgRGF0YSogc2VjdGlvbikgIAoKKipTdXJ2ZXkgTWVhc3VyZXMqKiAgCgozLiBEZW1vZ3JhcGhpYyAmIFNVUSBSYXcgRGF0YSAgCiAgICAtIGNzdiBmaWxlcyBleHBvcnRlZCBmcm9tIFF1YWx0cmljcwo0LiBTQUQgUmF3IERhdGEgIAogICAgLSBjc3YgZmlsZXMgZXhwb3J0ZWQgZnJvbSBRdWFsdHJpY3MKNS4gVGVzdGluZyBUcmFja2luZyBTaGVldCAgIAogICAgLSBjc3YgZmlsZXMsIGNvbGxlY3RlZCBkdXJpbmcgdGVzdGluZyAgCgojIyMgSW1wb3J0IFJhdyBEYXRhICAKIyMjIyAxLiBPU3BhbiBSYXcgRGF0YSAgCjxkZXRhaWxzPgoKPHN1bW1hcnk+IFRoZSAqKk9TcGFuIFJhdyBEYXRhKiogd2FzIGNvbGxlY3RlZCB1c2luZyB0aGUgSW5xdWlzaXQgNSBzb2Z0d2FyZSAoKipMSU5LKiopLCB3aGljaCB1c2VkIHRoZSBzYW1lIGF1dG9tYXRlZCBPU3BhbiB0YXNrIGFzIGluIFdhcmQgZXQgYWwuICgyMDE3KS4gVGhlIHJhdyBkYXRhIGZyb20gdGhlIE9TcGFuIHdhcyBpbXBvcnRlZCBhcyBhIGRhdGFmcmFtZSwgIioqb3NwYW5fcmF3KioiLCBhbmQgaW5jbHVkZWQgdGhlIGZvbGxvd2luZzogKihjbGljayB0byBzZWUgZGVzY3JpcHRpb24pKiA8L3N1bW1hcnk+ICAKIAotICoqUGFydGljaXBhbnQgbnVtYmVyIFsqb3NwYW5fcGFydGljaXBhbnQqXSoqICAKLSAqKk9TcGFuIElEIFsqb3NwYW5fSUQqXSoqICAKICAtIEEgOS1kaWdpdCBJRCBnaXZlbiBieSB0aGUgSXF1aXNpdCA1IHNvZnR3YXJlCi0gKipPU3BhbiBBYnNvbHV0ZSBTY29yZSBbKm9zcGFuX2Fic29sdXRlX3Njb3JlKl0qKiAgCiAgLSBQZXJmb3JtYW5jZSBtZWFzdXJlZCBieSBob3cgbWFueSB0cmlhbHMgYSBwYXJ0aWNpcGFudCBjb3JyZWN0bHkgcmVjYWxsZWQgYWxsIHRoZSBsZXR0ZXJzIGluIGEgZ2l2ZW4gYmxvY2sgKDc1IGJsb2NrcyBpbiB0b3RhbCkuIEZvciBleGFtcGxlLCBhIHBhcnRpY2lwYW50IHdobyByZWNhbGxlZCB0aHJlZSBsZXR0ZXJzIChpbiBhIGJsb2NrIHdpdGggdGhyZWUgbGV0dGVycyksIGZpdmUgbGV0dGVycyAoaW4gYSBibG9jayB3aXRoIGZpdmUgbGV0dGVycyksIGFuZCB0d28gbGV0dGVycyAoaW4gYSBibG9jayB3aXRoIHNpeCBsZXR0ZXJzKSB3b3VsZCBoYXZlIGFuIE9TcGFuIGFic29sdXRlIHNjb3JlIG9mIGVpZ2h0IGZvciB0aG9zZSBibG9ja3MgKGkuZS4gMyArIDUgKyAwID0gOCkuICAKLSAqKlRvdGFsIExldHRlcnMgUmVjYWxsZWQgWypvc3Bhbl90b3RhbF9jb3JyKl0qKiAgCiAgLSBQZXJmb3JtYW5jZSBtZWFzdXJlZCBieSBob3cgbWFueSBsZXR0ZXJzIHdlcmUgcmVjYWxsZWQgaW4gdG90YWwsIHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciBhbGwgbGV0dGVycyB3ZXJlIGNvcnJlY3Qgd2l0aGluIGEgZ2l2ZW4gYmxvY2suICAgIAotICoqVG90YWwgTWF0aCBFcnJvcnMgWypvc3Bhbl9tYXRoX2Vycl90b3QqXSoqICAKICAtIHRoZSBzdW0gb2YgYWxsIG1hdGggZXJyb3JzIChpLmUuIHNwZWVkIGFuZCBhY2N1cmFjeSkgICAKLSAqKlNwZWVkIEVycm9ycyBbKm9zcGFuX21hdGhfZXJyX3NwZWVkKl0qKiAgCiAgLSB0aGUgc3VtIG9mIHRoZSBzcGVlZCByZWxhdGVkIG1hdGggZXJyb3JzICAKICAgIC0gd2hlcmUgYSBwYXJ0aWNpcGFudCBleGNlZWRlZCB0aGVpciB0aW1lIGxpbWl0IHRvIHJlc3BvbmQgdG8gdGhlIG1hdGggY29tcG9uZW50IG9mIHRoZSB0YXNrICAKLSAqKkFjY3VyYWN5IEVycm9ycyBbKm9zcGFuX21hdGhfZXJyX2FjY3VyYWN5Kl0qKiAgCiAgLSB0aGUgc3VtIG9mIHRoZSBhY2N1cmFjeSByZWxhdGVkIG1hdGggZXJyb3JzICAKICAgIC0gd2hlcmUgYSBwYXJ0aWNpcGFudCBhbnN3ZXJlZCBpbmNvcnJlY3RseSBvbiB0aGUgbWF0aCBjb21wb25lbnQgb2YgdGhlIHRhc2sgIAotICoqTWF0aCBQZXJjZW50YWdlIFsqb3NwYW5fbWF0aF9wZXJjZW50X2NvcnIqXSoqICAKICAtIHRoZSBwZXJjZW50IG9mIGFsbCBtYXRoIHRyaWFscyB0aGF0IHdlcmUgYW5zd2VyZWQgY29ycmVjdGx5ICAKICAgIC0gUGFydGljaXBhbnRzIHdlcmUgYXNrZWQgdG8ga2VlcCB0aGVpciBtYXRoIHBlcmNlbnRhZ2UgYXQgODUlIG9yIGFib3ZlIHRvIGVuc3VyZSBwYXJ0aWNpcGFudHMgZGlkIG5vdCBpZ25vcmUgdGhlIG1hdGggY29tcG9uZW50IG9mIHRoZSB0YXNrIHRvIGltcHJvdmUgb24gdGhlIGxldHRlciByZWNhbGwgY29tcG9uZW50Ci0gKipNYXRoIFBlcmNlbnRhZ2UgQ3JpdGVyaWEgWypvc3Bhbl9tYXRoX2NyaXRlcmlhXzg1Kl0qKiAgCiAgLSB3aGV0aGVyIGEgcGFydGljaXBhbnQgbWV0IHRoZSBtYXRoIGNyaXRlcmlhIChpLmUuIDg1JSBvciBhYm92ZTsgeWVzIG9yIG5vKSAgCiAgPGRldGFpbHM+ICAKICA8c3VtbWFyeT4gY29kaW5nIGluZm9ybWF0aW9uICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PiAgCiAgICAtIDEgPSB5ZXMKICAgIC0gMCA9IG5vICogKmluY2x1ZGluZyBhbnkgcGFydGljaXBhbnQgdGhhdCBkaWQgbm90IGNvbXBsZXRlIHRoZSBPU3BhbiB0YXNrKiAgCgo8L2RldGFpbHM+ICAKPC9kZXRhaWxzPiAKCjxkZXRhaWxzPiAgCjxzdW1tYXJ5PiBUaGlzIGNvZGUgaW1wb3J0ZWQgdGhlIE9TcGFuIHJhdyBkYXRhLiAqKGNsaWNrIHRvIGV4cGFuZCkqIDwvc3VtbWFyeT4gIAoKYGBge3J9Cm9zcGFuX3JhdyA9IHV0aWxzOjpyZWFkLmNzdigicmF3X29zcGFuLmNzdiIsIGhlYWRlciA9IFRSVUUpCgojIHJlb3JnYW5pemUgcm93cyBzbyB0aGF0IHRoZSBkYXRhIGlzIG9yZGVyZWQgYnkgdGhlIHBhcnRpY2lwYW50IG51bWJlciAoZS5nLiAxLCAyLCAzLCA0Li4uKQpvc3Bhbl9yYXcgPSBkcGx5cjo6YXJyYW5nZShvc3Bhbl9yYXcsIG9zcGFuX3BhcnRpY2lwYW50KQpgYGAKCjwvZGV0YWlscz4gIAoKCiMjIyMgMi4gR28vTm8tR28gUmF3IERhdGEgIAo8ZGV0YWlscz4gIAoKPHN1bW1hcnk+IFRoZSAqKkdvL05vLUdvIFJhdyBEYXRhKiogd2FzIGNvbGxlY3RlZCB1c2luZyBQc3ljaG9weSAodmVyc2lvbjogKipYWFhYKiopLiBFYWNoIHBhcnRpY2lwYW50J3MgZGF0YSB3YXMgc3RvcmVkIGluIGEgc2VwYXJhdGUgZm9sZGVyIChkZWZhdWx0IGZyb20gcHN5Y2hvcHkpIGFzIGFuIGV4Y2VsIGZpbGUuIFRoZSBmb2xsb3dpbmcgY29kZSByZS1vcmdhbml6ZWQgdGhlIHJhdyBkYXRhIGludG8gYSBzaW5nbGUgd2lkZSBmb3JtYXQgb2YgdGhlIGRhdGEgYXMgYSBkYXRhZnJhbWUsICIqKmduZ19kYXRhX2V4dHJhY3RlZCoqIiwgYW5kIHR3byBkYXRhIGZyYW1lcyB0aGF0IHNlcGFyYXRlIHRoZSByYXcgZGF0YSBieSBjdWUgdHlwZSAoaS5lLiJ2ZXJ0aWNhbCIgb3IgImhvcml6b250YWwiKSwgIioqZ25nX2RhdGFfZXh0cmFjdGVkX3YqKiIgYW5kICIqKmduZ19kYXRhX2V4dHJhY3RlZF9oKioiLiAqKGNsaWNrIHRvIHNlZSBkZXNjcmlwdGlvbnMpKiA8L3N1bW1hcnk+ICAKCkZvciB0aGUgKipnbmdfZGF0YV9leHRyYWN0ZWQqKiBkYXRhIGZyYW1lOiAgCgotICoqUGFydGljaXBhbnQgbnVtYmVyIFsqZ25nX3BhcnRpY2lwYW50Kl0qKiAgCi0gKipBZ2UgWyphZ2UqXSoqICAKLSAqKkZpcnN0IExhbmd1YWdlIFsqbGFuZypdKiogIAogIC0gc2VsZi1yZXBvcnRlZCB3aGV0aGVyIHRoZWlyIGZpc3QgbGFuZ3VhZ2Ugd2FzIEVuZ2xpc2ggKGkuZS4geWVzIG9yIG5vKSAgCiAgPGRldGFpbHM+ICAKICA8c3VtbWFyeT4gY29kaW5nIGluZm9ybWF0aW9uICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PiAgCgogICAgfCAgICAgICBjb2RlIHwgIDEgIHwgIDIgfAogICAgfC0tLS0tLS0tLS0tOnw6LS0tOnw6LS06fAogICAgfCAqcmVzcG9uc2UqIHwgWWVzIHwgTm8gfAoKLSAqKlRvdGFsIHRyaWFscyBjb21wbGV0ZWQgWypnbmdfdHJpYWxfdG90Kl0qKiAgCi0gKipHbkcgU2NvcmUgWypnbmdfc2NvcmUqXSoqICAKICAtIHRoZSBzdW0gb2YgdGhlIGNvcnJlY3QgYW5zd2VycyAgCi0gKipUb3RhbCBSZXNwb25zZXMgWypnbmdfcmVzcF90b3QqXSoqCiAgLSB0aGUgc3VtIG9mIHRoZSByZXNwb25zZXMgZm9yIGFsbCB0cmlhbHMKLSAqKlRvdGFsIE5vIFJlc3BvbnNlcyBbKmduZ19ub19yZXNwX3RvdCpdKiogIAogIC0gdGhlIHN1bSBvZiB0aGUgdHJpYWxzIHdpdGhvdXQgYSByZXNwb25zZSAgCi0gKipUb3RhbCBFcnJvcnMgWypnbmdfZXJyX3RvdCpdKiogIAogIC0gdGhlIHN1bSBvZiBhbGwgZXJyb3JzIGZvciBhbGwgdHJpYWxzICAKLSAqKkNvbW1pc3Npb24gRXJyb3JzIFsqZ25nX2Vycl9jb20qXSoqICAKICAtIHRoZSBzdW0gb2YgYWxsIGNvbWlzc2lvbiBlcnJvcnMsIGRlZmluZWQgYXM6ICAKICAgIC0gd2hlcmUgYSByZXBvbnNlIHdhcyBtYWRlIGR1cmluZyBhICJuby1nbyIgdHJpYWwgKGkuZS4gY29tbWl0dGluZyBhbiBlcm9ycikgIAotICoqT21pc3Npb24gRXJyb3JzIFsqZ25nX2Vycl9vbWkqXSoqICAKICAtIHRoZSBzdW0gb2YgYWxsIG9taXNzaW9uIGVycm9ycywgZGVmaW5lZCBhczogIAogICAgLSB3aGVyZSBhIHJlcG9uc2Ugd2FzIE5PVCBtYWRlIGR1cmluZyBhICJnbyIgdHJpYWwgKGkuZS4gZmFpbGluZyB0byByZXNwb25kKSAgCi0gKipBdmVyYWdlIFJlYWN0aW9uIFRpbWUgKFJUKSBbKmduZ19ydF9hdipdKiogIAoKRm9yIHRoZSAqKmduZ19kYXRhX2V4dHJhY3RlZF92KiogZGF0YSBmcmFtZTogIAoKLSAqKlBhcnRpY2lwYW50IG51bWJlciBbKmduZ19wYXJ0aWNpcGFudCpdKiogIAotICoqQWdlIFsqYWdlX2xvbmcqXSoqICAKLSAqKkZpcnN0IExhbmd1YWdlIFsqbGFuZ19sb25nKl0qKiAgCiAgLSBzZWxmLXJlcG9ydGVkIHdoZXRoZXIgdGhlaXIgZmlzdCBsYW5ndWFnZSB3YXMgRW5nbGlzaCAoaS5lLiB5ZXMgb3Igbm8pICAKICA8ZGV0YWlscz4gIAogIDxzdW1tYXJ5PiBjb2RpbmcgaW5mb3JtYXRpb24gKihjbGljayB0byBleHBhbmQpKiA8L3N1bW1hcnk+ICAKCiAgICB8ICAgICAgIGNvZGUgfCAgMSAgfCAgMiB8CiAgICB8LS0tLS0tLS0tLS06fDotLS06fDotLTp8CiAgICB8ICpyZXNwb25zZSogfCBZZXMgfCBObyB8CgotICoqVG90YWwgdHJpYWxzIGNvbXBsZXRlZCBbKnRyaWFsX3RvdF92Kl0qKiAgCi0gKipHbkcgU2NvcmUgWypzY29yZV92Kl0qKiAgCiAgLSB0aGUgc3VtIG9mIHRoZSBjb3JyZWN0IGFuc3dlcnMgIAotICoqVG90YWwgUmVzcG9uc2VzIFsqcmVzcF90b3RfdipdKioKICAtIHRoZSBzdW0gb2YgdGhlIHJlc3BvbnNlcyBmb3IgYWxsIHRyaWFscwotICoqVG90YWwgTm8gUmVzcG9uc2VzIFsqbm9fcmVzcF90b3RfdipdKiogIAogIC0gdGhlIHN1bSBvZiB0aGUgdHJpYWxzIHdpdGhvdXQgYSByZXNwb25zZSAgCi0gKipUb3RhbCBFcnJvcnMgWyplcnJfdG90X3YqXSoqICAKICAtIHRoZSBzdW0gb2YgYWxsIGVycm9ycyBmb3IgYWxsIHRyaWFscyAgCi0gKipDb21taXNzaW9uIEVycm9ycyBbKmVycl9jb21fdipdKiogIAogIC0gdGhlIHN1bSBvZiBhbGwgY29taXNzaW9uIGVycm9ycywgZGVmaW5lZCBhczogIAogICAgLSB3aGVyZSBhIHJlcG9uc2Ugd2FzIG1hZGUgZHVyaW5nIGEgIm5vLWdvIiB0cmlhbCAoaS5lLiBjb21taXR0aW5nIGFuIGVyb3JyKSAgCi0gKipPbWlzc2lvbiBFcnJvcnMgWyplcnJfb21pX3YqXSoqICAKICAtIHRoZSBzdW0gb2YgYWxsIG9taXNzaW9uIGVycm9ycywgZGVmaW5lZCBhczogIAogICAgLSB3aGVyZSBhIHJlcG9uc2Ugd2FzIE5PVCBtYWRlIGR1cmluZyBhICJnbyIgdHJpYWwgKGkuZS4gZmFpbGluZyB0byByZXNwb25kKSAgCi0gKipBdmVyYWdlIFJlYWN0aW9uIFRpbWUgKFJUKSBbKnJ0X2F2X3YqXSoqICAKLSAqKlJlc3BvbnNlIEV4Y2x1c2lvbiBDcml0ZXJpYSBbKmV4Y2x1ZGVfdipdKiogIAogIC0gVGhpcyBkZXBpY3RzIHdoZXRoZXIgYSBwYXJ0aWNpcGFudCBzaG91bGQgYmUgZXhjbHVkZWQgZnJvbSBhbmFseXNpcyBiYXNlZCBvbiB0aGUgcmVzcG9uc2UgZXhjbHVzaW9uIGNyaXRlcmlhCiAgICAtIFRvIGJlIGluY2x1ZGVkLCBwYXJ0aWNpcGFudHMgc2hvdWxkIHNjb3JlIGhpZ2hlciB0aGFuIGNoYW5jZSBwZXJmb3JtYW5jZSAoaS5lLiByZXNwb25kZWQgdG8gYXQgbGVhc3QgNTAlIG9mIOKAnEdv4oCdIHRyaWFscyBhbmQgd2l0aGhlbGQgcmVzcG9uc2UgdG8gYXQgbGVhc3QgNTAlIG9mIOKAnE5vLUdv4oCdIHRyaWFscykKICAgIDxkZXRhaWxzPiAgCiAgICA8c3VtbWFyeT4gY29kaW5nIGluZm9ybWF0aW9uICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PiAgCgogICAgICB8ICAgICAgIGNvZGUgfCAgICAgICAgICAgICAgICAxICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgIDIgICAgICAgICAgICAgICB8CiAgICAgIHwtLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tOnwKICAgICAgfCAqcmVzcG9uc2UqIHwgWWVzIChwYXJ0aWNpcGFudCAqKmV4Y2x1ZGVkKiopIHwgTm8gKHBhcnRpY2lwYW50ICoqaW5jbHVkZWQqKikgfCAgCgpGb3IgdGhlICoqZ25nX2RhdGFfZXh0cmFjdGVkX2gqKiBkYXRhIGZyYW1lOiAgCgotICoqUGFydGljaXBhbnQgbnVtYmVyIFsqZ25nX3BhcnRpY2lwYW50Kl0qKiAgCi0gKipBZ2UgWyphZ2VfbG9uZypdKiogIAotICoqRmlyc3QgTGFuZ3VhZ2UgWypsYW5nX2xvbmcqXSoqICAKICAtIHNlbGYtcmVwb3J0ZWQgd2hldGhlciB0aGVpciBmaXN0IGxhbmd1YWdlIHdhcyBFbmdsaXNoIChpLmUuIHllcyBvciBubykgIAogIDxkZXRhaWxzPiAgCiAgPHN1bW1hcnk+IGNvZGluZyBpbmZvcm1hdGlvbiAqKGNsaWNrIHRvIGV4cGFuZCkqIDwvc3VtbWFyeT4gIAoKICAgIHwgICAgICAgY29kZSB8ICAxICB8ICAyIHwKICAgIHwtLS0tLS0tLS0tLTp8Oi0tLTp8Oi0tOnwKICAgIHwgKnJlc3BvbnNlKiB8IFllcyB8IE5vIHwgIAoKLSAqKlRvdGFsIHRyaWFscyBjb21wbGV0ZWQgWyp0cmlhbF90b3RfaCpdKiogIAotICoqR25HIFNjb3JlIFsqc2NvcmVfaCpdKiogIAogIC0gdGhlIHN1bSBvZiB0aGUgY29ycmVjdCBhbnN3ZXJzICAKLSAqKlRvdGFsIFJlc3BvbnNlcyBbKnJlc3BfdG90X2gqXSoqCiAgLSB0aGUgc3VtIG9mIHRoZSByZXNwb25zZXMgZm9yIGFsbCB0cmlhbHMKLSAqKlRvdGFsIE5vIFJlc3BvbnNlcyBbKm5vX3Jlc3BfdG90X2gqXSoqICAKICAtIHRoZSBzdW0gb2YgdGhlIHRyaWFscyB3aXRob3V0IGEgcmVzcG9uc2UgIAotICoqVG90YWwgRXJyb3JzIFsqZXJyX3RvdF9oKl0qKiAgCiAgLSB0aGUgc3VtIG9mIGFsbCBlcnJvcnMgZm9yIGFsbCB0cmlhbHMgIAotICoqQ29tbWlzc2lvbiBFcnJvcnMgWyplcnJfY29tX2gqXSoqICAKICAtIHRoZSBzdW0gb2YgYWxsIGNvbWlzc2lvbiBlcnJvcnMsIGRlZmluZWQgYXM6ICAKICAgIC0gd2hlcmUgYSByZXBvbnNlIHdhcyBtYWRlIGR1cmluZyBhICJuby1nbyIgdHJpYWwgKGkuZS4gY29tbWl0dGluZyBhbiBlcm9ycikgIAotICoqT21pc3Npb24gRXJyb3JzIFsqZXJyX29taV9oKl0qKiAgCiAgLSB0aGUgc3VtIG9mIGFsbCBvbWlzc2lvbiBlcnJvcnMsIGRlZmluZWQgYXM6ICAKICAgIC0gd2hlcmUgYSByZXBvbnNlIHdhcyBOT1QgbWFkZSBkdXJpbmcgYSAiZ28iIHRyaWFsIChpLmUuIGZhaWxpbmcgdG8gcmVzcG9uZCkgIAotICoqQXZlcmFnZSBSZWFjdGlvbiBUaW1lIChSVCkgWypydF9hdl9oKl0qKiAgCi0gKipSZXNwb25zZSBFeGNsdXNpb24gQ3JpdGVyaWEgWypleGNsdWRlX2gqXSoqICAKICAtIFRoaXMgZGVwaWN0cyB3aGV0aGVyIGEgcGFydGljaXBhbnQgc2hvdWxkIGJlIGV4Y2x1ZGVkIGZyb20gYW5hbHlzaXMgYmFzZWQgb24gdGhlIHJlc3BvbnNlIGV4Y2x1c2lvbiBjcml0ZXJpYQogICAgLSBUbyBiZSBpbmNsdWRlZCwgcGFydGljaXBhbnRzIHNob3VsZCBzY29yZSBoaWdoZXIgdGhhbiBjaGFuY2UgcGVyZm9ybWFuY2UgKGkuZS4gcmVzcG9uZGVkIHRvIGF0IGxlYXN0IDUwJSBvZiDigJxHb+KAnSB0cmlhbHMgYW5kIHdpdGhoZWxkIHJlc3BvbnNlIHRvIGF0IGxlYXN0IDUwJSBvZiDigJxOby1Hb+KAnSB0cmlhbHMpCiAgICA8ZGV0YWlscz4gIAogICAgPHN1bW1hcnk+IGNvZGluZyBpbmZvcm1hdGlvbiAqKGNsaWNrIHRvIGV4cGFuZCkqIDwvc3VtbWFyeT4gIAoKICAgICAgfCAgICAgICBjb2RlIHwgICAgICAgICAgICAgICAgMSAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAyICAgICAgICAgICAgICAgfAogICAgICB8LS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTp8CiAgICAgIHwgKnJlc3BvbnNlKiB8IFllcyAocGFydGljaXBhbnQgKipleGNsdWRlZCoqKSB8IE5vIChwYXJ0aWNpcGFudCAqKmluY2x1ZGVkKiopIHwgIAoKPC9kZXRhaWxzPiAKPC9kZXRhaWxzPiAKCjxkZXRhaWxzPgo8c3VtbWFyeT4gVGhpcyBjb2RlIGltcG9ydGVkIHRoZSBHby9Oby1HbyByYXcgZGF0YSB3aXRob3V0IHNlcGFyYXRpbmcgdGhlIGRhdGEgYnkgY3VlIHR5cGUuICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PgoKYGBge3IgZ25nX29yZ2FuaXplLCB3YXJuaW5nPUZBTFNFfQoKIy0tLVdJREUgREFUQSBGUkFNRS0tLSJnbmdfZGF0YV9leHRyYWN0ZWQiICAKCiMtLVRoaXMgY29kZSBjb21wbGV0ZXMgdGhlIGZvbGxvd2luZyB0YXNrczoKIyAoMSkgQ3JlYXRlIGEgZnVuY3Rpb24gdGhhdCBleHRyYWN0cyBhbnkgcmVxdWlyZWQgaW5mb3JtYXRpb24gZnJvbSBhbGwgcHN5Y2hvcHkgZm9sZGVycyBhdCBvbmNlCiMgKDIpIENyZWF0ZSBhIGxpc3Qgb2YgYWxsIHRoZSBkaXJlY3RvcnkgcGF0aHMgdG8gZWFjaCBpbmRpdmlkdWFsIGZpbGUgCiMgKDMpIEFwcGx5IHRoZSBmdW5jdGlvbiB0byB0aGUgZmlsZXMgCiMgKDQpIENyZWF0ZSBhIGRhdGEgZnJhbWUgb2YgdGhlIHJlc3VsdCBvZiB0aGUgZnVuY3Rpb24gb24gdGhlIGZpbGVzCgojLS1UaGUgRklOQUwgT1VUUFVUID0gYSB3aWRlIGZvcm1hdCBvZiB0aGUgcmF3IEduRyBkYXRhIGluY2x1ZGluZzoKIyBwYXJ0aWNpcGFudCwgYWdlLCBsYW5nLCB0cmlhbF90b3QsIHNjb3JlLCByZXNwX3RvdCwgbm9fcmVzcF90b3QsIGVycl90b3QsIGVycl9jb20sIGVycl9vbWksIHJ0X2F2CgojLS1OT1RFUzoKCiMgU3RlcCAoMykgd2lsbCBnaXZlIHdhcm5pbmdzIGlmIHRoZXJlIGlzIGFueSBtaXNzaW5nIGRhdGEgdGhhdCB0aGUgZnVuY3Rpb24gd2FzIG5vdCBzcGVjaWZpZWQgaG93IHRvIGhhbmRsZQojIGV4YW1wbGU6IEFueSBwYXJ0aWNpcGFudCB0aGF0IGRpZCBub3QgcmVzcG9uZCB0byBhbiBpdGVtIG9yIGR1cmluZyBhbGwgdHJpYWxzIHdpbGwgaGF2ZSBhbiAiTkEiIHJlc3BvbnNlIGluIHRoZSBkYXRhCiMgZXhhbXBsZTogQW55IHBhcnRpY2lwYW50IHdobyByZXBvcnRlZCB0aGVpciBhZ2Ugb3IgZmlyc3QgbGFuZ3VhZ2UgaW4gYW4gaXJyZWd1bGFyIG1hbm5lciAoZS5nLiAibmludGVlbiIgcmF0aGVyIHRoYW4gIjE5IikKIyBFaXRoZXIgZXhhbXBsZSB3aWxsIHJlc3VsdCBpbiBhIHdhcm5pbmcsIHNpbmNlIHRoZSBmdW5jdGlvbiB3b3VsZCBoYXZlIHRvIGZvcmNlIHRoYXQgb3V0cHV0IHRvIGJlICJOQSIgYXMgd2VsbAoKIyBJbmRpdmlkdWFsIHBhcnRpY2lwYW50IGZpbGVzIGRvIG5vdCBzdGF5IGluIGNocm9ub2xvZ2ljYWwgb3JkZXIgCiMgKHRoZXkgYXJlIHJlLW9yZGVyZWQgc28gdGhhdCBhbGwgcHMgdGhhdCBzdGFydCB3aXRoIHRoZSBkaWdpdCAiMSIgZ28gZmlyc3QsIHRoZW4gdGhlICIyIi4uLikKCiMtLSgxKSBDcmVhdGUgYSBmdW5jdGlvbiB0aGF0IGV4dHJhY3RzIGFueSByZXF1aXJlZCBpbmZvcm1hdGlvbiBmcm9tIGFsbCBwc3ljaG9weSBmb2xkZXJzIGF0IG9uY2UKCiMgY3JlYXRlIGEgZnVuY3Rpb24gdGhhdCBleHRyYWN0cyBhbGwgdGhlIHJlcXVpcmVkIGluZm9ybWF0aW9uIGZyb20gZWFjaCBleGNlbCBmaWxlCiMgZGV0YWlscyBmb3Igd2hhdCBpcyBleHRyYWN0ZWQgaW4gdGhpcyBmdW5jdGlvbiBpcyBmb3VuZCB3aXRoaW4gaXQsIAojIHRvIHVzZSBpdCB0byBleHRyYWN0IGFueSBvdGhlciAmLyBhZGRpdGlvbmFsIGluZm9ybWF0aW9uLCBlZGl0IHdpdGhpbiB0aGUgZnVuY3Rpb24gaXRzZWxmCmV4dHJhY3RfZ25nID0gZnVuY3Rpb24oZGF0YSkgewogIHRlbXBfZGF0YSA9IHJlYWR4bDo6cmVhZF9leGNlbChkYXRhKQogIAogICMgUGFydGljaXBhbnQgbnVtYmVyIChwYXJ0aWNpcGFudCkKICBwYXJ0aWNpcGFudCA9IGFzLm51bWVyaWModGVtcF9kYXRhW3doaWNoKHRlbXBfZGF0YSA9PSAicGFydGljaXBhbnQiKSwyXSkKICAKICAjIEFnZSAoYWdlKQogIGFnZSA9IGFzLmludGVnZXIodGVtcF9kYXRhW3doaWNoKHRlbXBfZGF0YSA9PSAiQWdlIiksMl0pCiAgCiAgIyBHZW5kZXIgKGdlbmRlcikKICAjIHdpbGwgYmUgcG9wdWxhdGVkIGZyb20gc3VydmV5IG1lYXN1cmVzCiAgCiAgIyBGaXJzdCBMYW5ndWFnZSAobGFuZykKICAjIHRoaXMgZmluZHMgaWYgdGhlIGxhbmd1YWdlIHJlcG9ydGVkIHdhcyBFbmdsaXNoOiBpZiB5ZXMgPSAxOyBubyA9IDAKICBsYW5nID0gaWZlbHNlKHN0cmluZ3I6OnN0cl9kZXRlY3QoYXMuY2hhcmFjdGVyKHRlbXBfZGF0YVt3aGljaCh0ZW1wX2RhdGEgPT0gIkZpcnN0IExhbmd1YWdlIiksMl0pLCBzdHJpbmdyOjpmaXhlZCgiZW5nbGlzaCIsIGlnbm9yZV9jYXNlPVRSVUUpKSwgMSwgMCkKICAKICAjIExvY2F0aW9uIENvbmRpdGlvbiAobG9jYXRpb247IGVpdGhlcjogKDEpIGRlc2ssICgyKSBwb2NrZXQvYmFnLCBvciAoMykgb3V0c2lkZSkKICAjIHdpbGwgYmUgcG9wdWxhdGVkIGZyb20gc3VydmV5IG1lYXN1cmVzCiAgCiAgIyBQb3dlciBDb25kaXRpb24gKHBvd2VyOyBlaXRoZXI6ICgxKSBPTixvciAoMikgT0ZGKQogICMgd2lsbCBiZSBwb3B1bGF0ZWQgZnJvbSBzdXJ2ZXkgbWVhc3VyZXMKICAKICAjIFRvdGFsIHRyaWFscyBjb21wbGV0ZWQgKHRyaWFsX3RvdCkKICAjIGNvdW50IHRoZSAib3JkZXIiIGNvbHVtbiwgd2hpY2ggc2hvd3MgdGhlIG9yZGVyIGluIHdoaWNoIHRoZSB0cmlhbHMgd2VyZSBzaG93ZWQgKHJhbmRvbSBmb3IgZWFjaCBwYXJ0aWNpcGFudCkKICAjIG5vdGU6IG11c3QgaWdub3JlIHRoZSBOQSB2YWx1ZXMKICB0cmlhbF90b3QgPSBzdW0oKGlzLm5hKHRlbXBfZGF0YSRjdWUpID09ICJGQUxTRSIgJiBpcy5uYSh0ZW1wX2RhdGEkb3JkZXIpID09ICJGQUxTRSIpLCBuYS5ybSA9IFRSVUUpICNhbHRlcm5hdGl2ZTogc3VtKGNvbXBsZXRlLmNhc2VzKHRlbXBfZGF0YSRvcmRlcikpCiAgCiAgIyBHbkcgU2NvcmUgKHNjb3JlKQogICMgc3VtIG9mIHRoZSBjb3JyZWN0IGFuc3dlcnMgZnJvbSB0aGUgImtleV9yZXNwX3NsYXNoLmNvcnJfcmF3IiBjb2x1bW4KICAjIG5vdGU6IG11c3QgaWdub3JlIHRoZSBOQSB2YWx1ZXMKICBzY29yZSA9IHN1bSh0ZW1wX2RhdGEka2V5X3Jlc3Bfc2xhc2guY29ycl9yYXcsIG5hLnJtID0gVFJVRSkKICAKICAjIFRvdGFsIFJlc3BvbnNlcyAocmVzcF90b3QpCiAgIyBzdW0gb2YgdGhlIHJlc3BvbnNlcyBmcm9tIHRoZSAia2V5X3Jlc3Bfc2xhc2gua2V5c19yYXciIGNvbHVtbgogICMgbm90ZTogbXVzdCBpZ25vcmUgdGhlIE5BIHZhbHVlcwogIHJlc3BfdG90ID0gc3VtKChpcy5uYSh0ZW1wX2RhdGEkY3VlKSA9PSAiRkFMU0UiICYgaXMubmEodGVtcF9kYXRhJGtleV9yZXNwX3NsYXNoLmtleXNfcmF3KSA9PSAiRkFMU0UiKSwgbmEucm0gPSBUUlVFKSAjYWx0ZXJuYXRpdmU6IHN1bShjb21wbGV0ZS5jYXNlcyh0ZW1wX2RhdGEka2V5X3Jlc3Bfc2xhc2gua2V5c19yYXcpKQogIAogICMgVG90YWwgTm8gUmVzcG9uc2VzIChub19yZXNwX3RvdCkKICAjIHN1YnRyYWN0IHRvdGFsIHJlc3BvbnNlcyBtYWRlIGZyb20gY29tcGxldGVkIHRyaWFscyAKICAjIG5vdGU6IG11c3QgaWdub3JlIHRoZSBOQSB2YWx1ZXMKICBub19yZXNwX3RvdCA9ICh0cmlhbF90b3QgLSByZXNwX3RvdCkKICAKICAjIFRvdGFsIEVycm9ycyAoZXJyX3RvdCkKICAjIHN1bSBvZiB0aGUgaW5jb3JyZWN0IGFuc3dlcnMgZnJvbSB0aGUgImtleV9yZXNwX3NsYXNoLmNvcnJfcmF3IgogIGVycl90b3QgPSBzdW0oKHRlbXBfZGF0YSRrZXlfcmVzcF9zbGFzaC5jb3JyX3JhdyA9PSAiMCIpID09ICJUUlVFIiwgbmEucm0gPSBUUlVFKSAjIGFsdGVybmF0aXZlOiBzdW0oIXRlbXBfZGF0YSRrZXlfcmVzcF9zbGFzaC5jb3JyX3JhdywgbmEucm0gPSBUUlVFKQogIAogICMgQ29tbWlzc2lvbiBFcnJvcnMgKGVycl9jb20pCiAgIyBzdW0gYW55IGNhc2VzIHdoZXJlIGEgcmVwb25zZSB3YXMgbWFkZSAmIHRoZSBhbnN3ZXIgd2FzIGluY29ycmVjdCAoaS5lLiBjb21taXR0aW5nIGFuIGVyb3JyKQogIGVycl9jb20gPSBzdW0oKHRlbXBfZGF0YSRrZXlfcmVzcF9zbGFzaC5jb3JyX3JhdyA9PSAiMCIgJiAhaXMubmEodGVtcF9kYXRhJGtleV9yZXNwX3NsYXNoLmtleXNfcmF3KSkgPT0gIlRSVUUiLCBuYS5ybSA9IFRSVUUpCiAgCiAgIyBPbWlzc2lvbiBFcnJvcnMgKGVycl9vbWkpCiAgIyBzdW0gYW55IGNhc2VzIHdoZXJlIGEgcmVwb25zZSB3YXMgTk9UIG1hZGUgJiB0aGUgYW5zd2VyIHdhcyBpbmNvcnJlY3QgKGkuZS4gZmFpbGluZyB0byByZXNwb25kKQogIGVycl9vbWkgPSBzdW0oKHRlbXBfZGF0YSRrZXlfcmVzcF9zbGFzaC5jb3JyX3JhdyA9PSAiMCIgJiBpcy5uYSh0ZW1wX2RhdGEka2V5X3Jlc3Bfc2xhc2gua2V5c19yYXcpKSA9PSAiVFJVRSIsIG5hLnJtID0gVFJVRSkKICAKICAjIEF2ZXJhZ2UgUmVhY3Rpb24gVGltZSAoUlQpIChydF9hdikKICAjIGNhbGN1bGF0ZSB0aGUgYXZlcmFnZSAvIG1lYW4gUlQgZm9yIGFsbCByZXNwb25zZXMKICAjIE5vdGU6IHRoZSAibm8tZ28iIHRyaWFscyByZXF1aXJlZCBubyByZXNwb25zZSBmb3IgYSBjb3JyZWN0IHRyaWFsIChmb3IgMSwwMDBtcykKICBydF9hdiA9IG1lYW4odGVtcF9kYXRhJGtleV9yZXNwX3NsYXNoLnJ0X3JhdywgbmEucm0gPSBUUlVFKQogIAogIHRlbXBfZGF0YWZyYW1lID0gYXMuZGF0YS5mcmFtZShjKHBhcnRpY2lwYW50LCBhZ2UsIGxhbmcsIHRyaWFsX3RvdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NvcmUsIHJlc3BfdG90LCBub19yZXNwX3RvdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyX3RvdCwgZXJyX2NvbSwgZXJyX29taSwgcnRfYXYpKQp9CgojLS0oMikgQ3JlYXRlIGEgbGlzdCBvZiBhbGwgdGhlIGRpcmVjdG9yeSBwYXRocyB0byBlYWNoIGluZGl2aWR1YWwgZmlsZSAKCiMgRmluZCB0aGUgbG9jYXRpb24gb2YgZWFjaCBleGNlbCAoLnhsc3gpIGZpbGVzCiMgdGhlIGZvbGRlcnMgY29udGFpbmluZyB0aGUgZmlsZXMgc2hvdWxkIGJlIGluIDEgZm9sZGVyIChlLmcuICIiIGluIHRoaXMgY2FzZSkKIyB0aGlzIHJldHVybnMgYSBsaXN0IG9mIGVhY2ggZmlsZSdzIGxvY2F0aW9uCiMgTm90ZTogdGhlIHBhdHRlcm4gaXMgc2V0IHRvIGlnbm9yZSBhbnkgaGlkZGVuIC8gdGVtcG9yYXJ5IGZpbGVzIGJ5IGFkZGluZyB0aGUgc3RhcnQgb2YgZWFjaCBmaWxlIG5hbWUgKGUuZy4gIl5Ob0dvIikKZmlsZXNfcHN5Y2hvcHkgPSBkaXIoIi9Vc2Vycy9hbmFydWl6cGFyZG8vUlN0dWRpby9TbWFydHBob25lX3N0dWR5L1N0dWR5IDEtIFNtYXJ0cGhvbmUgUmVwbGljYXRpb24vRGlzc2VydGF0aW9uICgwNDoyMDoyMCkvUmF3IERhdGEgT3JnYW5pemluZy9nbmdfcmF3X2ZvbGRlcnMiLCAKICAgICAgICAgICAgICAgICAgICAgcmVjdXJzaXZlID0gVFJVRSwgZnVsbC5uYW1lcz1UUlVFLCBwYXR0ZXJuPSJeTm9HbyguKil4bHN4JCIpCgojLS0oMykgQXBwbHkgdGhlIGZ1bmN0aW9uIHRvIHRoZSBmaWxlcyAKCiMgQXBwbHkgdGhlIGZ1bmN0aW9uIHRvIGFsbCBleGNlbCBmaWxlcwpyZXN1bHQgPSBzYXBwbHkoZmlsZXNfcHN5Y2hvcHksIGV4dHJhY3RfZ25nKQoKIy0tKDQpIENyZWF0ZSBhIGRhdGEgZnJhbWUgb2YgdGhlIHJlc3VsdCBvZiB0aGUgZnVuY3Rpb24gb24gdGhlIGZpbGVzCgojIHRha2UgdGhlIGxpc3RzIG9mIHRoZSBleHRyYWN0ZWQgZGF0YSBhbmQgdHVybiBpdCBpbnRvIGEgZGF0YSBmcmFtZQpnbmdfZGF0YV9leHRyYWN0ZWQgPSBkYXRhLmZyYW1lKFJlZHVjZShyYmluZCwgcmVzdWx0KSkgIyBhbHRlcm5hdGl2ZSBtZXRob2Q6IHggPSBkYXRhLmZyYW1lKHQoc2FwcGx5KHJlc3VsdCxjKSkpCiMgcmVuYW1lIHRoZSBjb2x1bW5zCmNvbG5hbWVzKGduZ19kYXRhX2V4dHJhY3RlZCkgPSBjKCJnbmdfcGFydGljaXBhbnQiLCAiYWdlIiwgImxhbmciLCAiZ25nX3RyaWFsX3RvdCIsICJnbmdfc2NvcmUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImduZ19yZXNwX3RvdCIsICJnbmdfbm9fcmVzcF90b3QiLCAiZ25nX2Vycl90b3QiLCAiZ25nX2Vycl9jb20iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImduZ19lcnJfb21pIiwgImduZ19ydF9hdiIpIAojIHJlbW92ZSByb3cgbmFtZXMgdG8gYXZvaWQgY29uZnVzaW9uCnJvd25hbWVzKGduZ19kYXRhX2V4dHJhY3RlZCkgPSBOVUxMCgojIHJlb3JnYW5pemUgcm93cyBzbyB0aGF0IHRoZSBkYXRhIGlzIG9yZGVyZWQgYnkgdGhlIHBhcnRpY2lwYW50IG51bWJlciAoZS5nLiAxLCAyLCAzLCA0Li4uKQpnbmdfZGF0YV9leHRyYWN0ZWQgPSBkcGx5cjo6YXJyYW5nZShnbmdfZGF0YV9leHRyYWN0ZWQsIGduZ19wYXJ0aWNpcGFudCkKCmBgYAoKPC9kZXRhaWxzPiAgCgo8ZGV0YWlscz4KPHN1bW1hcnk+IFRoaXMgY29kZSBpbXBvcnRlZCB0aGUgR28vTm8tR28gcmF3IGRhdGEgYW5kIHNlcGFyYXRlZCB0aGUgZGF0YSBieSBjdWUgdHlwZSAoaS5lLiAidmVydGljYWwiIG9yICJob3Jpem9udGFsIikuICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PgoKYGBge3IgZ25nX29yZ2FuaXplX3RhcmdldCwgd2FybmluZz1GQUxTRX0KCiMtLS0gZm9yIHRoZSBMT05HIERBVEEgRlJBTUUgLSBDVUUgVFlQRSAodmVydGljYWwgdnMuIGhvcml6b250YWwpIC0tLSAiZ25nX2RhdGFfZXh0cmFjdGVkX3YiICYgImduZ19kYXRhX2V4dHJhY3RlZF9oIiAKICAKIy0tIFRoaXMgY29kZSBkaWZmZXJzIGZyb20gdGhlIGFib3ZlIGNvZGUgaW4gdGhhdCBpdCBvcmdhbml6ZXMgdGhlIGduZyBkYXRhIGJhc2VkIHRoZSBDVUUgdHlwZSAoaS5lLiBlaXRoZXIgYSAidmVydGljYWwiICh2KSBvciAiaG9yaXpvbnRhbCIgKGgpKS4KICAjIFRoaXMgbWVhbnMgdGhhdCB0aGUgZGF0YSBpcyBpbiBhIGxvbmcgZm9ybWF0IHRvIHRlc3QgdGhlIHdpdGhpbi1zdWJqZWN0cyBmYWN0b3Igb2YgY3VlIHR5cGUuCgojLS1UaGlzIGNvZGUgY29tcGxldGVzIHRoZSBmb2xsb3dpbmcgdGFza3M6CiMgKDEpIENyZWF0ZSBhIGZ1bmN0aW9uIHRoYXQgZXh0cmFjdHMgYW55IHJlcXVpcmVkIGluZm9ybWF0aW9uIGZyb20gYWxsIHBzeWNob3B5IGZvbGRlcnMgYXQgb25jZQojICgyKSBDcmVhdGUgYSBsaXN0IG9mIGFsbCB0aGUgZGlyZWN0b3J5IHBhdGhzIHRvIGVhY2ggaW5kaXZpZHVhbCBmaWxlIAojICgzKSBBcHBseSB0aGUgZnVuY3Rpb24gdG8gdGhlIGZpbGVzIAojICg0KSBDcmVhdGUgYSBkYXRhIGZyYW1lIG9mIHRoZSByZXN1bHQgb2YgdGhlIGZ1bmN0aW9uIG9uIHRoZSBmaWxlcwojICg1KSBSZS1zdHJ1Y3R1cmUgdGhlIGRhdGEgaW50byAxIGRhdGEgZnJhbWUgaW4gYSBsb25nIGZvcm1hdCBmb3IgYSByZXBlYXRlZCBtZWFzdXJlcyBhbmFseXNpcwoKIy0tVGhlIEZJTkFMIE9VVFBVVCA9IGEgd2lkZSBmb3JtYXQgb2YgdGhlIHJhdyBHbkcgZGF0YSBpbmNsdWRpbmc6CiMgcGFydGljaXBhbnQsIGFnZSwgbGFuZywgdHJpYWxfdG90LCBzY29yZSwgcmVzcF90b3QsIG5vX3Jlc3BfdG90LCBlcnJfdG90LCBlcnJfY29tLCBlcnJfb21pLCBydF9hdgoKIy0tTk9URVM6CgojIFN0ZXAgKDMpIHdpbGwgZ2l2ZSB3YXJuaW5ncyBpZiB0aGVyZSBpcyBhbnkgbWlzc2luZyBkYXRhIHRoYXQgdGhlIGZ1bmN0aW9uIHdhcyBub3Qgc3BlY2lmaWVkIGhvdyB0byBoYW5kbGUKIyBleGFtcGxlOiBBbnkgcGFydGljaXBhbnQgdGhhdCBkaWQgbm90IHJlc3BvbmQgdG8gYW4gaXRlbSBvciBkdXJpbmcgYWxsIHRyaWFscyB3aWxsIGhhdmUgYW4gIk5BIiByZXNwb25zZSBpbiB0aGUgZGF0YQojIGV4YW1wbGU6IEFueSBwYXJ0aWNpcGFudCB3aG8gcmVwb3J0ZWQgdGhlaXIgYWdlIG9yIGZpcnN0IGxhbmd1YWdlIGluIGFuIGlycmVndWxhciBtYW5uZXIgKGUuZy4gIm5pbnRlZW4iIHJhdGhlciB0aGFuICIxOSIpCiMgRWl0aGVyIGV4YW1wbGUgd2lsbCByZXN1bHQgaW4gYSB3YXJuaW5nLCBzaW5jZSB0aGUgZnVuY3Rpb24gd291bGQgaGF2ZSB0byBmb3JjZSB0aGF0IG91dHB1dCB0byBiZSAiTkEiIGFzIHdlbGwKCiMgSW5kaXZpZHVhbCBwYXJ0aWNpcGFudCBmaWxlcyBkbyBub3Qgc3RheSBpbiBjaHJvbm9sb2dpY2FsIG9yZGVyIAojICh0aGV5IGFyZSByZS1vcmRlcmVkIHNvIHRoYXQgYWxsIHBzIHRoYXQgc3RhcnQgd2l0aCB0aGUgZGlnaXQgIjEiIGdvIGZpcnN0LCB0aGVuIHRoZSAiMiIuLi4pCgojLS0oMSkgQ3JlYXRlIGEgZnVuY3Rpb24gdGhhdCBleHRyYWN0cyBhbnkgcmVxdWlyZWQgaW5mb3JtYXRpb24gZnJvbSBhbGwgcHN5Y2hvcHkgZm9sZGVycyBhdCBvbmNlLi4uCiMgZm9yIHRoZSAidmVydGljYWwiICh2KSAoZXh0cmFjdF9nbmdfdikgYW5kICJob3Jpem9udGFsIiAoaCkgKGV4dHJhY3RfZ25nX2gpIHRyaWFscwoKIyBjcmVhdGUgYSBmdW5jdGlvbiB0aGF0IGV4dHJhY3RzIGFsbCB0aGUgcmVxdWlyZWQgaW5mb3JtYXRpb24gZnJvbSBlYWNoIGV4Y2VsIGZpbGUKIyBkZXRhaWxzIGZvciB3aGF0IGlzIGV4dHJhY3RlZCBpbiB0aGlzIGZ1bmN0aW9uIGlzIGZvdW5kIHdpdGhpbiBpdCwgCiMgdG8gdXNlIGl0IHRvIGV4dHJhY3QgYW55IG90aGVyICYvIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24sIGVkaXQgd2l0aGluIHRoZSBmdW5jdGlvbiBpdHNlbGYKIyBOT1RFOiB0aGlzIGZ1bmN0aW9uIGV4dHJhY3RzIDIgdmVyc2lvbnMgb2YgZWFjaCB2YWx1ZTogb25lIGZvciB0aGUgInZlcnRpY2FsIiAodikgdHJpYWxzLCBhbmQgb25lIGZvciB0aGUgImhvcml6b250YWwiIChoKSB0cmlhbHMKCmV4dHJhY3RfZ25nX3YgPSBmdW5jdGlvbihkYXRhKSB7CiAgdGVtcF9kYXRhID0gcmVhZHhsOjpyZWFkX2V4Y2VsKGRhdGEpCiAgCiAgIyBQYXJ0aWNpcGFudCBudW1iZXIgKHBhcnRpY2lwYW50X2xvbmcpCiAgcGFydGljaXBhbnRfbG9uZyA9IGFzLm51bWVyaWModGVtcF9kYXRhW3doaWNoKHRlbXBfZGF0YSA9PSAicGFydGljaXBhbnQiKSwyXSkKICAjIG9ubHkgb25lIGlzIGV4dHJhY3RlZCBzaW5jZSB0aGlzIHdpbGwgbm90IGNoYW5nZSBiL3cgQ1VFIHR5cGUKICAKICAjIEFnZSAoYWdlX2xvbmcpCiAgYWdlX2xvbmcgPSBhcy5pbnRlZ2VyKHRlbXBfZGF0YVt3aGljaCh0ZW1wX2RhdGEgPT0gIkFnZSIpLDJdKQogICMgb25seSBvbmUgaXMgZXh0cmFjdGVkIHNpbmNlIHRoaXMgd2lsbCBub3QgY2hhbmdlIGIvdyBDVUUgdHlwZQogIAogICMgR2VuZGVyIChnZW5kZXIpCiAgIyB3aWxsIGJlIHBvcHVsYXRlZCBmcm9tIHN1cnZleSBtZWFzdXJlcwogICMgb25seSBvbmUgaXMgZXh0cmFjdGVkIHNpbmNlIHRoaXMgd2lsbCBub3QgY2hhbmdlIGIvdyBDVUUgdHlwZQogIAogICMgRmlyc3QgTGFuZ3VhZ2UgKGxhbmdfbG9uZykKICAjIHRoaXMgZmluZHMgaWYgdGhlIGxhbmd1YWdlIHJlcG9ydGVkIHdhcyBFbmdsaXNoOiBpZiB5ZXMgPSAxOyBubyA9IDAKICBsYW5nX2xvbmcgPSBpZmVsc2Uoc3RyaW5ncjo6c3RyX2RldGVjdChhcy5jaGFyYWN0ZXIodGVtcF9kYXRhW3doaWNoKHRlbXBfZGF0YSA9PSAiRmlyc3QgTGFuZ3VhZ2UiKSwyXSksIHN0cmluZ3I6OmZpeGVkKCJlbmdsaXNoIiwgaWdub3JlX2Nhc2U9VFJVRSkpLCAxLCAwKQogICMgb25seSBvbmUgaXMgZXh0cmFjdGVkIHNpbmNlIHRoaXMgd2lsbCBub3QgY2hhbmdlIGIvdyBDVUUgdHlwZQogIAogICMgTG9jYXRpb24gQ29uZGl0aW9uIChsb2NhdGlvbjsgZWl0aGVyOiAoMSkgZGVzaywgKDIpIHBvY2tldC9iYWcsIG9yICgzKSBvdXRzaWRlKQogICMgd2lsbCBiZSBwb3B1bGF0ZWQgZnJvbSBzdXJ2ZXkgbWVhc3VyZXMKICAjIG9ubHkgb25lIGlzIGV4dHJhY3RlZCBzaW5jZSB0aGlzIHdpbGwgbm90IGNoYW5nZSBiL3cgQ1VFIHR5cGUKICAKICAjIFBvd2VyIENvbmRpdGlvbiAocG93ZXI7IGVpdGhlcjogKDEpIE9OLG9yICgyKSBPRkYpCiAgIyB3aWxsIGJlIHBvcHVsYXRlZCBmcm9tIHN1cnZleSBtZWFzdXJlcwogICMgb25seSBvbmUgaXMgZXh0cmFjdGVkIHNpbmNlIHRoaXMgd2lsbCBub3QgY2hhbmdlIGIvdyBDVUUgdHlwZQogIAogICMgVG90YWwgdHJpYWxzIGNvbXBsZXRlZCBmb3IgdGhlICJ2ZXJ0aWNhbCIgKHYpICh0cmlhbF90b3RfdikKICAjIGNvdW50IHRoZSAib3JkZXIiIGNvbHVtbiwgd2hpY2ggc2hvd3MgdGhlIG9yZGVyIGluIHdoaWNoIHRoZSB0cmlhbHMgd2VyZSBzaG93ZWQgKHJhbmRvbSBmb3IgZWFjaCBwYXJ0aWNpcGFudCkKICAjIG5vdGU6IG11c3QgaWdub3JlIHRoZSBOQSB2YWx1ZXMKICB0cmlhbF90b3RfdiA9IHN1bSgodGVtcF9kYXRhJGN1ZSA9PSAidl9iLnBuZyIgJiBpcy5uYSh0ZW1wX2RhdGEkb3JkZXIpID09ICJGQUxTRSIpLCBuYS5ybSA9IFRSVUUpCiAgCiAgIyBHbkcgU2NvcmUgZm9yIHRoZSAidmVydGljYWwiICh2KSAoc2NvcmVfdikgIAogICMgc3VtIG9mIHRoZSBjb3JyZWN0IGFuc3dlcnMgZnJvbSB0aGUgImtleV9yZXNwX3NsYXNoLmNvcnJfcmF3IiBjb2x1bW4KICAjIG5vdGU6IG11c3QgaWdub3JlIHRoZSBOQSB2YWx1ZXMKICBzY29yZV92ID0gc3VtKHRlbXBfZGF0YSRjdWUgPT0gInZfYi5wbmciICYgdGVtcF9kYXRhJGtleV9yZXNwX3NsYXNoLmNvcnJfcmF3LCBuYS5ybSA9IFRSVUUpICAKICAKICAjIFRvdGFsIFJlc3BvbnNlcyBmb3IgdGhlICJ2ZXJ0aWNhbCIgKHYpIChyZXNwX3RvdF92KQogICMgc3VtIG9mIHRoZSByZXNwb25zZXMgZnJvbSB0aGUgImtleV9yZXNwX3NsYXNoLmtleXNfcmF3IiBjb2x1bW4KICAjIG5vdGU6IG11c3QgaWdub3JlIHRoZSBOQSB2YWx1ZXMKICByZXNwX3RvdF92ID0gc3VtKCh0ZW1wX2RhdGEkY3VlID09ICJ2X2IucG5nIiAmIHRlbXBfZGF0YSRrZXlfcmVzcF9zbGFzaC5rZXlzX3JhdyA9PSAiJ3NsYXNoJyIpLCBuYS5ybSA9IFRSVUUpICAKICAKICAjIFRvdGFsIE5vIFJlc3BvbnNlcyBmb3IgdGhlICJ2ZXJ0aWNhbCIgKHYpIChub19yZXNwX3RvdF92KSAgCiAgIyBzdWJ0cmFjdCB0b3RhbCByZXNwb25zZXMgbWFkZSBmcm9tIGNvbXBsZXRlZCB0cmlhbHMgCiAgIyBub3RlOiBtdXN0IGlnbm9yZSB0aGUgTkEgdmFsdWVzCiAgbm9fcmVzcF90b3RfdiA9ICh0cmlhbF90b3RfdiAtIHJlc3BfdG90X3YpICAKICAKICAjIFRvdGFsIEVycm9ycyBmb3IgdGhlICJ2ZXJ0aWNhbCIgKHYpIChlcnJfdG90X3YpIAogICMgc3VtIG9mIHRoZSBpbmNvcnJlY3QgYW5zd2VycyBmcm9tIHRoZSAia2V5X3Jlc3Bfc2xhc2guY29ycl9yYXciCiAgZXJyX3RvdF92ID0gc3VtKCh0ZW1wX2RhdGEkY3VlID09ICJ2X2IucG5nIiAmIHRlbXBfZGF0YSRrZXlfcmVzcF9zbGFzaC5jb3JyX3JhdyA9PSAiMCIpLCBuYS5ybSA9IFRSVUUpICAKICAKICAjIENvbW1pc3Npb24gRXJyb3JzIGZvciB0aGUgInZlcnRpY2FsIiAodikgKGVycl9jb21fdikgCiAgIyBzdW0gYW55IGNhc2VzIHdoZXJlIGEgcmVwb25zZSB3YXMgbWFkZSAmIHRoZSBhbnN3ZXIgd2FzIGluY29ycmVjdCAoaS5lLiBjb21taXR0aW5nIGFuIGVycm9yKQogIGVycl9jb21fdiA9IHN1bSh0ZW1wX2RhdGEkY3VlID09ICJ2X2IucG5nIiAmIHRlbXBfZGF0YSRrZXlfcmVzcF9zbGFzaC5jb3JyX3JhdyA9PSAiMCIgJiAhaXMubmEodGVtcF9kYXRhJGtleV9yZXNwX3NsYXNoLmtleXNfcmF3KSwgbmEucm0gPSBUUlVFKSAgCiAgCiAgIyBPbWlzc2lvbiBFcnJvcnMgZm9yIHRoZSAidmVydGljYWwiICh2KSAoZXJyX29taV92KSAgCiAgIyBzdW0gYW55IGNhc2VzIHdoZXJlIGEgcmVwb25zZSB3YXMgTk9UIG1hZGUgJiB0aGUgYW5zd2VyIHdhcyBpbmNvcnJlY3QgKGkuZS4gZmFpbGluZyB0byByZXNwb25kKQogIGVycl9vbWlfdiA9IHN1bSh0ZW1wX2RhdGEkY3VlID09ICJ2X2IucG5nIiAmIHRlbXBfZGF0YSRrZXlfcmVzcF9zbGFzaC5jb3JyX3JhdyA9PSAiMCIgJiBpcy5uYSh0ZW1wX2RhdGEka2V5X3Jlc3Bfc2xhc2gua2V5c19yYXcpLCBuYS5ybSA9IFRSVUUpICAKCiAgIyBBdmVyYWdlIFJlYWN0aW9uIFRpbWUgKFJUKSBmb3IgdGhlICJ2ZXJ0aWNhbCIgKHYpIChydF9hdl92KSAgCiAgIyBjYWxjdWxhdGUgdGhlIGF2ZXJhZ2UgLyBtZWFuIFJUIGZvciBhbGwgcmVzcG9uc2VzCiAgIyBOb3RlOiB0aGUgIm5vLWdvIiB0cmlhbHMgcmVxdWlyZWQgbm8gcmVzcG9uc2UgZm9yIGEgY29ycmVjdCB0cmlhbCAoZm9yIDEsMDAwbXMpCiAgcnRfYXZfdiA9IG1lYW4odGVtcF9kYXRhJGtleV9yZXNwX3NsYXNoLnJ0X3Jhd1t3aGljaCh0ZW1wX2RhdGEkY3VlID09ICJ2X2IucG5nIildLCBuYS5ybSA9IFRSVUUpICAKICAKICAjIEV4Y2x1c2lvbiBDcml0ZXJpYSBmb3IgdGhlICJ2ZXJ0aWNhbCIgKHYpIChleGNsdWRlX3YpCiAgIyBjYWxjdWxhdGUgd2hldGhlciBwYXJ0aWNpcGFudHMgc2NvcmVkIGhpZ2hlciB0aGFuIGNoYW5jZSBwZXJmb3JtYW5jZSAKICAjIChpLmUuIHJlc3BvbmRlZCB0byBhdCBsZWFzdCA1MCUgb2Yg4oCcR2/igJ0gdHJpYWxzIGFuZCB3aXRoaGVsZCByZXNwb25zZSB0byBhdCBsZWFzdCA1MCUgb2Yg4oCcTm8tR2/igJ0gdHJpYWxzKQogICMgY29kZTogZXhjbHVkZSA9IDE7IGluY2x1ZGUgKGRvIG5vdCBleGNsdWRlKSA9IDIKICAjIE5PVEU6IHRoaXMgY2FsY3VsYXRpb24gaXMgbWVhbnQgdG8gZXhjbHVkZSB0aGUgcGFydGljaXBhbnQgYXMgYSB3aG9sZSwgdGhlcmVmb3JlLCAKICAjIGl0IGRvZXMgbm90IGNhbGN1bGF0ZSBpdCBmb3IgdGhlIGN1ZSB0eXBlIHNwZWNpZmljYWxseQogICAgIyBmaXJzdCwgZ2V0IHRoZSB0b3RhbCB0cmlhbHMgYW5kIHJlc3BvbnNlIHRvdGFscyBmb3IgdGhlICJnbyIgYW5kICJuby1nbyIgdHJpYWxzCiAgICAgICMgImdvIgogICAgICB0cmlhbF90b3RfZ28gPSBzdW0oKHRlbXBfZGF0YSRjb3JyQW5zID09ICJzbGFzaCIgJiBpcy5uYSh0ZW1wX2RhdGEkb3JkZXIpID09ICJGQUxTRSIpLCBuYS5ybSA9IFRSVUUpCiAgICAgIHJlc3BfdG90X2dvID0gc3VtKCh0ZW1wX2RhdGEkY29yckFucyA9PSAic2xhc2giICYgdGVtcF9kYXRhJGtleV9yZXNwX3NsYXNoLmtleXNfcmF3ID09ICInc2xhc2gnIiksIG5hLnJtID0gVFJVRSkKICAgICAgIyAibm8tZ28iCiAgICAgIHRyaWFsX3RvdF9ub2dvID0gc3VtKCh0ZW1wX2RhdGEkY29yckFucyA9PSAibm9uZSIgJiBpcy5uYSh0ZW1wX2RhdGEkb3JkZXIpID09ICJGQUxTRSIpLCBuYS5ybSA9IFRSVUUpCiAgICAgIHJlc3BfdG90X25vZ28gPSBzdW0oKHRlbXBfZGF0YSRjb3JyQW5zID09ICJub25lIiAmIHRlbXBfZGF0YSRrZXlfcmVzcF9zbGFzaC5rZXlzX3JhdyA9PSAiJ3NsYXNoJyIpLCBuYS5ybSA9IFRSVUUpCiAgICAjIG5leHQsIGZpbmQgdGhlIG1pbmltdW0gcmVzcG9uc2UgbmVlZGVkIGJhc2VkIG9uIHRoZSA1MCUgY3JpdGVyaWEKICAgIG1pbl9yZXNwID0gdHJpYWxfdG90X2dvICogLjUwCiAgICAjIGZpbmQgaWYgdGhlIHBhcnRpY2lwYW50IG1lZXRzIGV4Y2x1c2lvbiBjcml0ZXJpYSBmb3IgdGhlICJnbyIgYW5kICJuby1nbyIgdHJpYWxzCiAgICBtZWV0c19taW5fZ28gPSByZXNwX3RvdF9nbyA+IChtaW5fcmVzcCkKICAgIG1lZXRzX21pbl9ub2dvID0gcmVzcF90b3Rfbm9nbyA8IChtaW5fcmVzcCkKICAgICMgZmluZCBpZiB0aGUgcGFydGljaXBhbnQgbWVldHMgZXhjbHVzaW9uIGNyaXRlcmlhIChleGNsdWRlID0gMTsgaW5jbHVkZSA9IDIpCiAgICBleGNsdWRlX3YgPSBpZmVsc2UoKG1lZXRzX21pbl9nbyA9PSAiVFJVRSIgJiBtZWV0c19taW5fbm9nbyA9PSAiVFJVRSIpID09ICJGQUxTRSIsIDEsIDIpCiAgCiAgdGVtcF9kYXRhZnJhbWVfdiA9IGFzLmRhdGEuZnJhbWUoYyhwYXJ0aWNpcGFudF9sb25nLCBhZ2VfbG9uZywgbGFuZ19sb25nLCB0cmlhbF90b3Rfdiwgc2NvcmVfdiwgcmVzcF90b3RfdiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub19yZXNwX3RvdF92LCBlcnJfdG90X3YsIGVycl9jb21fdiwgZXJyX29taV92LCBydF9hdl92LCBleGNsdWRlX3YpKQp9ICAKCmV4dHJhY3RfZ25nX2ggPSBmdW5jdGlvbihkYXRhKSB7CiAgdGVtcF9kYXRhID0gcmVhZHhsOjpyZWFkX2V4Y2VsKGRhdGEpCiAgCiAgIyBQYXJ0aWNpcGFudCBudW1iZXIgKHBhcnRpY2lwYW50X2xvbmcpCiAgcGFydGljaXBhbnRfbG9uZyA9IGFzLm51bWVyaWModGVtcF9kYXRhW3doaWNoKHRlbXBfZGF0YSA9PSAicGFydGljaXBhbnQiKSwyXSkKICAjIG9ubHkgb25lIGlzIGV4dHJhY3RlZCBzaW5jZSB0aGlzIHdpbGwgbm90IGNoYW5nZSBiL3cgQ1VFIHR5cGUKICAKICAjIEFnZSAoYWdlX2xvbmcpCiAgYWdlX2xvbmcgPSBhcy5pbnRlZ2VyKHRlbXBfZGF0YVt3aGljaCh0ZW1wX2RhdGEgPT0gIkFnZSIpLDJdKQogICMgb25seSBvbmUgaXMgZXh0cmFjdGVkIHNpbmNlIHRoaXMgd2lsbCBub3QgY2hhbmdlIGIvdyBDVUUgdHlwZQogIAogICMgR2VuZGVyIChnZW5kZXIpCiAgIyB3aWxsIGJlIHBvcHVsYXRlZCBmcm9tIHN1cnZleSBtZWFzdXJlcwogICMgb25seSBvbmUgaXMgZXh0cmFjdGVkIHNpbmNlIHRoaXMgd2lsbCBub3QgY2hhbmdlIGIvdyBDVUUgdHlwZQogIAogICMgRmlyc3QgTGFuZ3VhZ2UgKGxhbmdfbG9uZykKICAjIHRoaXMgZmluZHMgaWYgdGhlIGxhbmd1YWdlIHJlcG9ydGVkIHdhcyBFbmdsaXNoOiBpZiB5ZXMgPSAxOyBubyA9IDAKICBsYW5nX2xvbmcgPSBpZmVsc2Uoc3RyaW5ncjo6c3RyX2RldGVjdChhcy5jaGFyYWN0ZXIodGVtcF9kYXRhW3doaWNoKHRlbXBfZGF0YSA9PSAiRmlyc3QgTGFuZ3VhZ2UiKSwyXSksIHN0cmluZ3I6OmZpeGVkKCJlbmdsaXNoIiwgaWdub3JlX2Nhc2U9VFJVRSkpLCAxLCAwKQogICMgb25seSBvbmUgaXMgZXh0cmFjdGVkIHNpbmNlIHRoaXMgd2lsbCBub3QgY2hhbmdlIGIvdyBDVUUgdHlwZQogIAogICMgTG9jYXRpb24gQ29uZGl0aW9uIChsb2NhdGlvbjsgZWl0aGVyOiAoMSkgZGVzaywgKDIpIHBvY2tldC9iYWcsIG9yICgzKSBvdXRzaWRlKQogICMgd2lsbCBiZSBwb3B1bGF0ZWQgZnJvbSBzdXJ2ZXkgbWVhc3VyZXMKICAjIG9ubHkgb25lIGlzIGV4dHJhY3RlZCBzaW5jZSB0aGlzIHdpbGwgbm90IGNoYW5nZSBiL3cgQ1VFIHR5cGUKICAKICAjIFBvd2VyIENvbmRpdGlvbiAocG93ZXI7IGVpdGhlcjogKDEpIE9OLG9yICgyKSBPRkYpCiAgIyB3aWxsIGJlIHBvcHVsYXRlZCBmcm9tIHN1cnZleSBtZWFzdXJlcwogICMgb25seSBvbmUgaXMgZXh0cmFjdGVkIHNpbmNlIHRoaXMgd2lsbCBub3QgY2hhbmdlIGIvdyBDVUUgdHlwZQogIAogICMgVG90YWwgdHJpYWxzIGNvbXBsZXRlZCBmb3IgdGhlICJob3Jpem9udGFsIiAoaCkgKHRyaWFsX3RvdF9oKQogICMgY291bnQgdGhlICJvcmRlciIgY29sdW1uLCB3aGljaCBzaG93cyB0aGUgb3JkZXIgaW4gd2hpY2ggdGhlIHRyaWFscyB3ZXJlIHNob3dlZCAocmFuZG9tIGZvciBlYWNoIHBhcnRpY2lwYW50KQogICMgbm90ZTogbXVzdCBpZ25vcmUgdGhlIE5BIHZhbHVlcwogIHRyaWFsX3RvdF9oID0gc3VtKCh0ZW1wX2RhdGEkY3VlID09ICJoX2IucG5nIiAmIGlzLm5hKHRlbXBfZGF0YSRvcmRlcikgPT0gIkZBTFNFIiksIG5hLnJtID0gVFJVRSkKICAKICAjIEduRyBTY29yZSBmb3IgdGhlICJob3Jpem9udGFsIiAoaCkgKHNjb3JlX2gpICAKICAjIHN1bSBvZiB0aGUgY29ycmVjdCBhbnN3ZXJzIGZyb20gdGhlICJrZXlfcmVzcF9zbGFzaC5jb3JyX3JhdyIgY29sdW1uCiAgIyBub3RlOiBtdXN0IGlnbm9yZSB0aGUgTkEgdmFsdWVzCiAgc2NvcmVfaCA9IHN1bSh0ZW1wX2RhdGEkY3VlID09ICJoX2IucG5nIiAmIHRlbXBfZGF0YSRrZXlfcmVzcF9zbGFzaC5jb3JyX3JhdywgbmEucm0gPSBUUlVFKSAgCiAgCiAgIyBUb3RhbCBSZXNwb25zZXMgZm9yIHRoZSAiaG9yaXpvbnRhbCIgKGgpIChyZXNwX3RvdF9oKQogICMgc3VtIG9mIHRoZSByZXNwb25zZXMgZnJvbSB0aGUgImtleV9yZXNwX3NsYXNoLmtleXNfcmF3IiBjb2x1bW4KICAjIG5vdGU6IG11c3QgaWdub3JlIHRoZSBOQSB2YWx1ZXMKICByZXNwX3RvdF9oID0gc3VtKCh0ZW1wX2RhdGEkY3VlID09ICJoX2IucG5nIiAmIHRlbXBfZGF0YSRrZXlfcmVzcF9zbGFzaC5rZXlzX3JhdyA9PSAiJ3NsYXNoJyIpLCBuYS5ybSA9IFRSVUUpICAKICAKICAjIFRvdGFsIE5vIFJlc3BvbnNlcyBmb3IgdGhlICJob3Jpem9udGFsIiAoaCkgKG5vX3Jlc3BfdG90X2gpICAKICAjIHN1YnRyYWN0IHRvdGFsIHJlc3BvbnNlcyBtYWRlIGZyb20gY29tcGxldGVkIHRyaWFscyAKICAjIG5vdGU6IG11c3QgaWdub3JlIHRoZSBOQSB2YWx1ZXMKICBub19yZXNwX3RvdF9oID0gKHRyaWFsX3RvdF9oIC0gcmVzcF90b3RfaCkgIAogIAogICMgVG90YWwgRXJyb3JzIGZvciB0aGUgImhvcml6b250YWwiIChoKSAoZXJyX3RvdF9oKSAKICAjIHN1bSBvZiB0aGUgaW5jb3JyZWN0IGFuc3dlcnMgZnJvbSB0aGUgImtleV9yZXNwX3NsYXNoLmNvcnJfcmF3IgogIGVycl90b3RfaCA9IHN1bSgodGVtcF9kYXRhJGN1ZSA9PSAiaF9iLnBuZyIgJiB0ZW1wX2RhdGEka2V5X3Jlc3Bfc2xhc2guY29ycl9yYXcgPT0gIjAiKSwgbmEucm0gPSBUUlVFKSAgCiAgCiAgIyBDb21taXNzaW9uIEVycm9ycyBmb3IgdGhlICJob3Jpem9udGFsIiAoaCkgKGVycl9jb21faCkgCiAgIyBzdW0gYW55IGNhc2VzIHdoZXJlIGEgcmVwb25zZSB3YXMgbWFkZSAmIHRoZSBhbnN3ZXIgd2FzIGluY29ycmVjdCAoaS5lLiBjb21taXR0aW5nIGFuIGVycm9yKQogIGVycl9jb21faCA9IHN1bSh0ZW1wX2RhdGEkY3VlID09ICJoX2IucG5nIiAmIHRlbXBfZGF0YSRrZXlfcmVzcF9zbGFzaC5jb3JyX3JhdyA9PSAiMCIgJiAhaXMubmEodGVtcF9kYXRhJGtleV9yZXNwX3NsYXNoLmtleXNfcmF3KSwgbmEucm0gPSBUUlVFKSAgCiAgCiAgIyBPbWlzc2lvbiBFcnJvcnMgZm9yIHRoZSAiaG9yaXpvbnRhbCIgKGgpIChlcnJfb21pX2gpICAKICAjIHN1bSBhbnkgY2FzZXMgd2hlcmUgYSByZXBvbnNlIHdhcyBOT1QgbWFkZSAmIHRoZSBhbnN3ZXIgd2FzIGluY29ycmVjdCAoaS5lLiBmYWlsaW5nIHRvIHJlc3BvbmQpCiAgZXJyX29taV9oID0gc3VtKHRlbXBfZGF0YSRjdWUgPT0gImhfYi5wbmciICYgdGVtcF9kYXRhJGtleV9yZXNwX3NsYXNoLmNvcnJfcmF3ID09ICIwIiAmIGlzLm5hKHRlbXBfZGF0YSRrZXlfcmVzcF9zbGFzaC5rZXlzX3JhdyksIG5hLnJtID0gVFJVRSkgIAogIAogICMgQXZlcmFnZSBSZWFjdGlvbiBUaW1lIChSVCkgZm9yIHRoZSAiaG9yaXpvbnRhbCIgKGgpIChydF9hdl9oKSAgCiAgIyBjYWxjdWxhdGUgdGhlIGF2ZXJhZ2UgLyBtZWFuIFJUIGZvciBhbGwgcmVzcG9uc2VzCiAgIyBOb3RlOiB0aGUgIm5vLWdvIiB0cmlhbHMgcmVxdWlyZWQgbm8gcmVzcG9uc2UgZm9yIGEgY29ycmVjdCB0cmlhbCAoZm9yIDEsMDAwbXMpCiAgcnRfYXZfaCA9IG1lYW4odGVtcF9kYXRhJGtleV9yZXNwX3NsYXNoLnJ0X3Jhd1t3aGljaCh0ZW1wX2RhdGEkY3VlID09ICJoX2IucG5nIildLCBuYS5ybSA9IFRSVUUpICAKICAKICAjIEV4Y2x1c2lvbiBDcml0ZXJpYSBmb3IgdGhlICJob3Jpem9udGFsIiAoaCkgKGV4Y2x1ZGVfaCkKICAjIGNhbGN1bGF0ZSB3aGV0aGVyIHBhcnRpY2lwYW50cyBzY29yZWQgaGlnaGVyIHRoYW4gY2hhbmNlIHBlcmZvcm1hbmNlIAogICMgKGkuZS4gcmVzcG9uZGVkIHRvIGF0IGxlYXN0IDUwJSBvZiDigJxHb+KAnSB0cmlhbHMgYW5kIHdpdGhoZWxkIHJlc3BvbnNlIHRvIGF0IGxlYXN0IDUwJSBvZiDigJxOby1Hb+KAnSB0cmlhbHMpCiAgIyBjb2RlOiBleGNsdWRlID0gMTsgaW5jbHVkZSAoZG8gbm90IGV4Y2x1ZGUpID0gMgogICMgTk9URTogdGhpcyBjYWxjdWxhdGlvbiBpcyBtZWFudCB0byBleGNsdWRlIHRoZSBwYXJ0aWNpcGFudCBhcyBhIHdob2xlLCB0aGVyZWZvcmUsIAogICMgaXQgZG9lcyBub3QgY2FsY3VsYXRlIGl0IGZvciB0aGUgY3VlIHR5cGUgc3BlY2lmaWNhbGx5CiAgIyBmaXJzdCwgZ2V0IHRoZSB0b3RhbCB0cmlhbHMgYW5kIHJlc3BvbnNlIHRvdGFscyBmb3IgdGhlICJnbyIgYW5kICJuby1nbyIgdHJpYWxzCiAgIyAiZ28iCiAgdHJpYWxfdG90X2dvID0gc3VtKCh0ZW1wX2RhdGEkY29yckFucyA9PSAic2xhc2giICYgaXMubmEodGVtcF9kYXRhJG9yZGVyKSA9PSAiRkFMU0UiKSwgbmEucm0gPSBUUlVFKQogIHJlc3BfdG90X2dvID0gc3VtKCh0ZW1wX2RhdGEkY29yckFucyA9PSAic2xhc2giICYgdGVtcF9kYXRhJGtleV9yZXNwX3NsYXNoLmtleXNfcmF3ID09ICInc2xhc2gnIiksIG5hLnJtID0gVFJVRSkKICAjICJuby1nbyIKICB0cmlhbF90b3Rfbm9nbyA9IHN1bSgodGVtcF9kYXRhJGNvcnJBbnMgPT0gIm5vbmUiICYgaXMubmEodGVtcF9kYXRhJG9yZGVyKSA9PSAiRkFMU0UiKSwgbmEucm0gPSBUUlVFKQogIHJlc3BfdG90X25vZ28gPSBzdW0oKHRlbXBfZGF0YSRjb3JyQW5zID09ICJub25lIiAmIHRlbXBfZGF0YSRrZXlfcmVzcF9zbGFzaC5rZXlzX3JhdyA9PSAiJ3NsYXNoJyIpLCBuYS5ybSA9IFRSVUUpCiAgIyBuZXh0LCBmaW5kIHRoZSBtaW5pbXVtIHJlc3BvbnNlIG5lZWRlZCBiYXNlZCBvbiB0aGUgNTAlIGNyaXRlcmlhCiAgbWluX3Jlc3AgPSB0cmlhbF90b3RfZ28gKiAuNTAKICAjIGZpbmQgaWYgdGhlIHBhcnRpY2lwYW50IG1lZXRzIGV4Y2x1c2lvbiBjcml0ZXJpYSBmb3IgdGhlICJnbyIgYW5kICJuby1nbyIgdHJpYWxzCiAgbWVldHNfbWluX2dvID0gcmVzcF90b3RfZ28gPiAobWluX3Jlc3ApCiAgbWVldHNfbWluX25vZ28gPSByZXNwX3RvdF9ub2dvIDwgKG1pbl9yZXNwKQogICMgZmluZCBpZiB0aGUgcGFydGljaXBhbnQgbWVldHMgZXhjbHVzaW9uIGNyaXRlcmlhIChleGNsdWRlID0gMTsgaW5jbHVkZSA9IDIpCiAgZXhjbHVkZV9oID0gaWZlbHNlKChtZWV0c19taW5fZ28gPT0gIlRSVUUiICYgbWVldHNfbWluX25vZ28gPT0gIlRSVUUiKSA9PSAiRkFMU0UiLCAxLCAyKQogIAogIHRlbXBfZGF0YWZyYW1lX2ggPSBhcy5kYXRhLmZyYW1lKGMocGFydGljaXBhbnRfbG9uZywgYWdlX2xvbmcsIGxhbmdfbG9uZywgdHJpYWxfdG90X2gsIHNjb3JlX2gsIHJlc3BfdG90X2gsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9fcmVzcF90b3RfaCwgZXJyX3RvdF9oLCBlcnJfY29tX2gsIGVycl9vbWlfaCwgcnRfYXZfaCwgZXhjbHVkZV9oKSkKfSAgCgojLS0oMikgQ3JlYXRlIGEgbGlzdCBvZiBhbGwgdGhlIGRpcmVjdG9yeSBwYXRocyB0byBlYWNoIGluZGl2aWR1YWwgZmlsZSAKCiMgRmluZCB0aGUgbG9jYXRpb24gb2YgZWFjaCBleGNlbCAoLnhsc3gpIGZpbGVzCiMgdGhlIGZvbGRlcnMgY29udGFpbmluZyB0aGUgZmlsZXMgc2hvdWxkIGJlIGluIDEgZm9sZGVyIChlLmcuICIiIGluIHRoaXMgY2FzZSkKIyB0aGlzIHJldHVybnMgYSBsaXN0IG9mIGVhY2ggZmlsZSdzIGxvY2F0aW9uCiMgTm90ZTogdGhlIHBhdHRlcm4gaXMgc2V0IHRvIGlnbm9yZSBhbnkgaGlkZGVuIC8gdGVtcG9yYXJ5IGZpbGVzIGJ5IGFkZGluZyB0aGUgc3RhcnQgb2YgZWFjaCBmaWxlIG5hbWUgKGUuZy4gIl5Ob0dvIikKIyBUSElTIElTIFRIRSBTQU1FIEFTIElOIFRIRSBBQk9WRSBDT0RFLCBTTyBJVCBJUyBDT01NRU5URUQgT1VUIFRPIEFWT0lEIEVYVFJBIENPTVBVVElORyBQT1dFUgoKIyBmaWxlc19wc3ljaG9weSA9IGRpcigiL1VzZXJzL2FuYXJ1aXpwYXJkby9SU3R1ZGlvL1NtYXJ0cGhvbmVfc3R1ZHkvU3R1ZHkgMS0gU21hcnRwaG9uZSBSZXBsaWNhdGlvbi9EaXNzZXJ0YXRpb24gKDA0OjIwOjIwKS9SYXcgRGF0YSBPcmdhbml6aW5nL2duZ19yYXdfZm9sZGVycyIsIAojICAgICAgICAgICAgICAgICAgICAgcmVjdXJzaXZlID0gVFJVRSwgZnVsbC5uYW1lcz1UUlVFLCBwYXR0ZXJuPSJeTm9HbyguKil4bHN4JCIpCgojLS0oMykgQXBwbHkgdGhlIGZ1bmN0aW9uIHRvIHRoZSBmaWxlcyAKCiMgQXBwbHkgdGhlIGZ1bmN0aW9uIHRvIGFsbCBleGNlbCBmaWxlcyBmb3IgdGhlICJ2ZXJ0aWNhbCIgKHYpIGFuZCAiaG9yaXpvbnRhbCIgKGgpIHRyaWFscyAgCnJlc3VsdF92ID0gc2FwcGx5KGZpbGVzX3BzeWNob3B5LCBleHRyYWN0X2duZ192KQpyZXN1bHRfaCA9IHNhcHBseShmaWxlc19wc3ljaG9weSwgZXh0cmFjdF9nbmdfaCkKCiMtLSg0KSBDcmVhdGUgYSBkYXRhIGZyYW1lIG9mIHRoZSByZXN1bHQgb2YgdGhlIGZ1bmN0aW9uIG9uIHRoZSBmaWxlcy4uLgojIGZvciB0aGUgInZlcnRpY2FsIiAoZ25nX2RhdGFfZXh0cmFjdGVkX3YpIGFuZCAiaG9yaXpvbnRhbCIgKGduZ19kYXRhX2V4dHJhY3RlZF9oKSB0cmlhbHMgIAoKIyB0YWtlIHRoZSBsaXN0cyBvZiB0aGUgZXh0cmFjdGVkIGRhdGEgYW5kIHR1cm4gaXQgaW50byBhIGRhdGEgZnJhbWUgZm9yIHRoZSAidmVydGljYWwiIChoKSB0cmlhbHMKZ25nX2RhdGFfZXh0cmFjdGVkX3YgPSBkYXRhLmZyYW1lKFJlZHVjZShyYmluZCwgcmVzdWx0X3YpKSAKIyByZW5hbWUgdGhlIGNvbHVtbnMKY29sbmFtZXMoZ25nX2RhdGFfZXh0cmFjdGVkX3YpID0gYygicGFydGljaXBhbnRfbG9uZyIsICJhZ2VfbG9uZyIsICJsYW5nX2xvbmciLCAidHJpYWxfdG90X3YiLCAic2NvcmVfdiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJyZXNwX3RvdF92IiwgIm5vX3Jlc3BfdG90X3YiLCAiZXJyX3RvdF92IiwgImVycl9jb21fdiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJlcnJfb21pX3YiLCAicnRfYXZfdiIsICJleGNsdWRlX3YiKQoKIyB0YWtlIHRoZSBsaXN0cyBvZiB0aGUgZXh0cmFjdGVkIGRhdGEgYW5kIHR1cm4gaXQgaW50byBhIGRhdGEgZnJhbWUgZm9yIHRoZSAiaG9yaXpvbnRhbCIgKGgpIHRyaWFscwpnbmdfZGF0YV9leHRyYWN0ZWRfaCA9IGRhdGEuZnJhbWUoUmVkdWNlKHJiaW5kLCByZXN1bHRfaCkpIAojIHJlbmFtZSB0aGUgY29sdW1ucwpjb2xuYW1lcyhnbmdfZGF0YV9leHRyYWN0ZWRfaCkgPSBjKCJwYXJ0aWNpcGFudF9sb25nIiwgImFnZV9sb25nIiwgImxhbmdfbG9uZyIsICJ0cmlhbF90b3RfaCIsICJzY29yZV9oIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicmVzcF90b3RfaCIsICJub19yZXNwX3RvdF9oIiwgImVycl90b3RfaCIsICJlcnJfY29tX2giLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJlcnJfb21pX2giLCAicnRfYXZfaCIsICJleGNsdWRlX2giKQojIHJlbW92ZSByb3cgbmFtZXMgdG8gYXZvaWQgY29uZnVzaW9uCnJvd25hbWVzKGduZ19kYXRhX2V4dHJhY3RlZF92KSA9IE5VTEwKcm93bmFtZXMoZ25nX2RhdGFfZXh0cmFjdGVkX2gpID0gTlVMTAoKIyByZW9yZ2FuaXplIHJvd3Mgc28gdGhhdCB0aGUgZGF0YSBpcyBvcmRlcmVkIGJ5IHRoZSBwYXJ0aWNpcGFudCBudW1iZXIgKGUuZy4gMSwgMiwgMywgNC4uLikKZ25nX2RhdGFfZXh0cmFjdGVkX3YgPSBkcGx5cjo6YXJyYW5nZShnbmdfZGF0YV9leHRyYWN0ZWRfdiwgcGFydGljaXBhbnRfbG9uZykKZ25nX2RhdGFfZXh0cmFjdGVkX2ggPSBkcGx5cjo6YXJyYW5nZShnbmdfZGF0YV9leHRyYWN0ZWRfaCwgcGFydGljaXBhbnRfbG9uZykKCmBgYAoKPC9kZXRhaWxzPiAgCgojIyMjIDMuICYgNC4gRGVtb2dyYXBoaWMsIFNVUSwgYW5kIFNBRCBSYXcgRGF0YSAgCgpUaGUgKipEZW1vZ3JhcGhpYyAmIFNVUSBSYXcgRGF0YSBhbmQgU0FEIFJhdyBEYXRhKiogd2FzIGNvbGxlY3RlZCB1c2luZyBRdWFsdHJpY3MgdGhlIElucXVpc2l0IDUgc29mdHdhcmUgKCoqTElOSyoqKSwgd2hpY2ggd2FzIHRoZSBzYW1lIGFzIFdhcmQgZXQgYWwuICgyMDE3KS4gVGhlIHJhdyBkYXRhIGZyb20gdGhlIE9TcGFuIHdhcyBpbXBvcnRlZCBhcyBhIGRhdGFmcmFtZSwgIioqb3NwYW5fcmF3KioiLCBhbmQgaW5jbHVkZWQgdGhlIGZvbGxvd2luZzogKihjbGljayB0byBzZWUgZGVzY3JpcHRpb24pKiAgICAKCjxkZXRhaWxzPiAgCjxzdW1tYXJ5PiA8c3BhbiBzdHlsZT0iY29sb3I6RGFya0JsdWU7IGZvbnQtc2l6ZToxOHB4OyI+R2VuZXJhbCwgTWFuaXB1bGF0aW9uLCBhbmQgRGVtb2dyYXBoaWMgSW5mb3JtYXRpb248L3NwYW4+IDwvc3VtbWFyeT4gIAogIAo8ZGV0YWlscz4gIAo8c3VtbWFyeT4gKipHZW5lcmFsIEluZm9ybWF0aW9uOioqICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PiAgCgotICoqU3RhcnQgRGF0ZSBbKmRhdGVfc3RhcnQqXSoqICAKICAtIFRoZSBkYXRlIGFuZCB0aW1lIHdoZW4gYSBwYXJ0aWNpcGFudCBiZWdhbiB0aGVpciBzdXJ2ZXkgb24gUXVhbHRyaWNzIChZL00vRCBIOk0pICAKLSAqKkVuZCBEYXRlIFsqZGF0ZV9lbmQqXSoqICAKICAtIFRoZSBkYXRlIGFuZCB0aW1lIHdoZW4gYSBwYXJ0aWNpcGFudCBmaW5pc2hlZCB0aGVpciBzdXJ2ZXkgb24gUXVhbHRyaWNzIChZL00vRCBIOk0pICAKLSAqKkR1cmF0aW9uIChpbiBzZWNvbmRzKSBbKmR1cmF0aW9uKHMpKl0qKiAgCiAgLSBUaGUgZHVyYXRpb24gb2YgdGhlIHN1cnZleSBmb3IgdGhlIHBhcnRpY2lwYW50IGluIHNlY29uZHMKLSAqKlJlY29yZGVkIERhdGUgWypkYXRlX3JlYypdKiogIAogIC0gVGhlIGRhdGUgYW5kIHRpbWUgd2hlbiBhIHBhcnRpY2lwYW50J3MgZGF0YSB3YXMgcmVjb3JkZWQgb24gUXVhbHRyaWNzIChZL00vRCBIOk0pICAKLSAqKlBhcnRpY2lwYW50IG51bWJlciBbKnN1cl9wYXJ0aWNpcGFudCpdKiogIAo8L2RldGFpbHM+Cgo8ZGV0YWlscz4gIAo8c3VtbWFyeT4gKipNYW5pcHVsYXRpb24gQ29uZGl0aW9uOioqICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PiAgCgotICoqU21hcnRwaG9uZSBMb2NhdGlvbiBbKnN1cl9sb2NhdGlvbipdKiogIAogIC0gVGhlIHNtYXJ0cGhvbmUgbG9jYXRpb24gYXNzaWduZWQgdG8gdGhlIHBhcnRpY2lwYW50IChpLmUuIGRlc2ssIHBvY2tldC9iYWcsIG9yIG91dHNpZGUpICAKICA8ZGV0YWlscz4gIAogIDxzdW1tYXJ5PiBjb2RpbmcgaW5mb3JtYXRpb24gKihjbGljayB0byBleHBhbmQpKiA8L3N1bW1hcnk+ICAKCiAgICB8ICAgICAgIGNvZGUgfCAgIDEgIHwgICAgICAyICAgICB8ICAgIDMgICAgfAogICAgfC0tLS0tLS0tLS0tOnw6LS0tLTp8Oi0tLS0tLS0tLS06fDotLS0tLS0tOnwKICAgIHwgKnJlc3BvbnNlKiB8IERlc2sgfCBQb2NrZXQvQmFnIHwgT3V0c2lkZSB8CgotICoqU21hcnRwaG9uZSBQb3dlciBbKnN1cl9wb3dlcipdKiogIAogIC0gVGhlIHNtYXJ0cGhvbmUgcG93ZXIgYXNzaWduZWQgdG8gdGhlIHBhcnRpY2lwYW50IChpLmUuIE9OIG9yIE9GRikgIAogIDxkZXRhaWxzPiAgCiAgPHN1bW1hcnk+IGNvZGluZyBpbmZvcm1hdGlvbiAqKGNsaWNrIHRvIGV4cGFuZCkqIDwvc3VtbWFyeT4gIAoKICAgIHwgICAgICAgY29kZSB8ICAxIHwgIDIgIHwKICAgIHwtLS0tLS0tLS0tLTp8Oi0tOnw6LS0tOnwKICAgIHwgKnJlc3BvbnNlKiB8IE9uIHwgT2ZmIHwKCi0gKipTbWFydHBob25lIENvbmRpdGlvbiBbKnN1cl9jb25kaXRpb24qXSoqICAKICAtIFRoZSBzbWFydHBob25lIGNvbmRpdGlvbiAoaS5lLiBjb21iaW5hdGlvbiBvZiBsb2NhdGlvbiAmIHBvd2VyKSBhc3NpZ25lZCB0byB0aGUgcGFydGljaXBhbnQgIAogIDxkZXRhaWxzPiAgCiAgPHN1bW1hcnk+IGNvZGluZyBpbmZvcm1hdGlvbiAqKGNsaWNrIHRvIGV4cGFuZCkqIDwvc3VtbWFyeT4gIAogICAgCiAgICB8ICAgICAgIGNvZGUgfCAgICAgMSAgICAgfCAgICAgICAgMiAgICAgICAgfCAgICAgICAzICAgICAgfCAgICAgIDQgICAgIHwgICAgICAgICA1ICAgICAgICB8ICAgICAgIDYgICAgICAgfAogICAgfC0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tOnwKICAgIHwgKnJlc3BvbnNlKiB8IE9OICYgRGVzayB8IE9OICYgUG9ja2V0L0JhZyB8IE9OICYgT3V0c2lkZSB8IE9GRiAmIERlc2sgfCBPRkYgJiBQb2NrZXQvQmFnIHwgT0ZGICYgT3V0c2lkZSB8Cgo8L2RldGFpbHM+ICAKCgo8ZGV0YWlscz4gIAo8c3VtbWFyeT4gKipEZW1vZ3JhcGhpY3M6KiogKihjbGljayB0byBleHBhbmQpKiA8L3N1bW1hcnk+ICAKCi0gKipHZW5kZXIgWypnZW5kZXIqXSoqICAKICAtIFBhcnRpY2lwYW50J3Mgc2VsZi1yZXBvcnRlZCBnZW5kZXIgKGkuZS4sIG1hbGUsIGZlbWFsZSwgb3RoZXIsIG9yIHByZWZlciBub3QgdG8gc2F5KSAgCiAgPGRldGFpbHM+ICAKICA8c3VtbWFyeT4gY29kaW5nIGluZm9ybWF0aW9uICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PiAgCgogICAgfCAgICAgICBjb2RlIHwgICAxICB8ICAgIDIgICB8ICAgMyAgIHwgICAgICAgICA0ICAgICAgICAgfAogICAgfC0tLS0tLS0tLS0tOnw6LS0tLTp8Oi0tLS0tLTp8Oi0tLS0tOnw6LS0tLS0tLS0tLS0tLS0tLS06fAogICAgfCAqcmVzcG9uc2UqIHwgTWFsZSB8IEZlbWFsZSB8IE90aGVyIHwgUHJlZmVyIG5vdCB0byBzYXkgfAoKLSAqKlllYXIgWyp5ZWFyKl0qKiAgCiAgLSBQYXJ0aWNpcGFudCdzIHNlbGYtcmVwb3J0ZWQgeWVhciBvZiBzdHVkeSBpbiB0aGVpciByZXNwZWN0aXZlIHByb2dyYW0gKGUuZy4gMSwgMiwgMywgNCkgIAotICoqUHJvZ3JhbSBbKnByb2dyYW0qXSoqICAKICAtIFBhcnRpY2lwYW50J3Mgc2VsZi1yZXBvcnRlZCBwcm9ncmFtIG9mIHN0dWR5IChlLmcuLCBiaW9sb2d5LCBCTU9TLCBwc3ljaG9sb2d5KSAgCiAgICA8ZGV0YWlscz4gIAogICAgPHN1bW1hcnk+IGNvZGluZyBpbmZvcm1hdGlvbiAqKGNsaWNrIHRvIGV4cGFuZCkqIDwvc3VtbWFyeT4gIAogIAogICAgICB8ICAgICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICB8CiAgICAgIHwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLXwKICAgICAgfCAxID0gYWN0dWFyaWFsICAgICAgICAgIHwgMTEgPSBlY29ub21pY3MgICAgICAgICAgfCAyMSA9IG1hbmFnZW1lbnQgICAgICAgICAgICB8IDMxID0gcHN5Y2hvbG9neSAgICAgfAogICAgICB8IDIgPSBhbnRocm9wb2xvZ3kgICAgICAgfCBzY2llbmNlICAgICAgICAgICAgICAgICB8IDIyID0gbWF0aGVtYXRpY3MgICAgICAgICAgIHwgMzIgPSBTQVNBSCAgICAgICAgICB8CiAgICAgIHwgMyA9IGFydHMgICAgICAgICAgICAgICB8IDEzID0gZW5nbGlzaCAgICAgICAgICAgIHwgMjMgPSBtZWRpY2FsIHNjaWVuY2UgICAgICAgfCAzMyA9IHNjaWVuY2UgICAgICAgIHwKICAgICAgfCA0ID0gYXJ0cyAmIGh1bWFuaXRpZXMgIHwgMTQgPSBmaWxtICAgICAgICAgICAgICAgfCAyNCA9IE1JVCAgICAgICAgICAgICAgICAgICB8IDM0ID0gc29jaWFsIHNjaWVuY2UgfAogICAgICB8IDUgPSBiaW9sb2d5ICAgICAgICAgICAgfCAxNSA9IEZJTVMgICAgICAgICAgICAgICB8IDI1ID0gTU9TICAgICAgICAgICAgICAgICAgIHwgMzUgPSBzb2Npb2xvZ3kgICAgICB8CiAgICAgIHwgNiA9IEJNT1MgICAgICAgICAgICAgICB8IDE2ID0gZ2VvZ3JhcGh5ICAgICAgICAgIHwgMjYgPSBtdXNpYyAgICAgICAgICAgICAgICAgfCAzNiA9IHNvZnR3YXJlICAgICAgIHwKICAgICAgfCA3ID0gY2hlbWlzdHJ5ICAgICAgICAgIHwgMTcgPSBoZWFsdGggc2NpZW5jZSAgICAgfCAyNyA9IG51dHJpdGlvbiAmIGRpZXRldGljcyB8IDM3ID0gdmlzdWFsIGFydHMgICAgfAogICAgICB8IDggPSBjb21wdXRlciBzY2llbmNlICAgfCAxOCA9IGludGVncmF0ZWQgc2NpZW5jZSB8IDI4ID0gcGhpbG9zb3BoeSAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICB8CiAgICAgIHwgOSA9IGNvbnN1bWVyIGJlaGF2aW91ciB8IDE5ID0ga2luZXNpb2xvZ3kgICAgICAgIHwgMjkgPSBwaHlzaWNzICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwKICAgICAgfCAxMCA9IGNyaW1pbm9sb2d5ICAgICAgIHwgMjAgPSBsaW5ndWlzdGljcyAgICAgICAgfCAzMCA9IHBvbGl0aWNhbCBzY2llbmNlICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgCjwvZGV0YWlscz4gIAo8L2RldGFpbHM+IAo8L2RldGFpbHM+IAogICAKCiMjIyMjIFRoZSBTbWFydHBob25lIFVzZSBRdWVzdGlvbm5haXJlIChTVVEpICAKVGhlIHB1cnBvc2Ugb2YgdGhlIFNVUSB3YXMgdG8gbWVhc3VyZSBwYXJ0aWNpcGFudHMnIHR5cGljYWwgc21hcnRwaG9uZSB1c2UuIFRoZSBTVVEgd2FzIGNyZWF0ZWQgZm9yIHRoZSBwcmVzZW50IHN0dWR5IGFuZCBjb25zaXN0ZWQgb2YgbW9kaWZpZWQgaXRlbXMgZnJvbSBXYXJkIGFuZCBjb2xsZWFndWVz4oCZICgyMDE3KSBzdXJ2ZXkgbWVhc3VyZXMuIChpLmUuIGZvdW5kIGluIHRoZSDigJxCUkFJTiBEUkFJTuKAnSBXRUIgQVBQRU5ESVjigJ0pLiBTb21lIGl0ZW1zIHdlcmUgZm9yY2VkLWNob2ljZSBhbmQgc29tZSB3ZXJlIG9uIGEgNy1wb2ludCBsaWtlcnQgc2NhbGUgcmFuZ2luZyBmcm9tIDEgKOKAnE5ldmVy4oCdKSB0byA3ICjigJxBbHdheXPigJ0pLiBUaGVyZSB3ZXJlIDEwIGl0ZW1zIGluIHRvdGFsIGFuZCB0aGVyZSB3ZXJlICoqZml2ZSB0eXBlcyBvZiBpdGVtcyoqLCB3aGljaCBtZWFzdXJlZDogCgo8ZGV0YWlscz4gIAo8c3VtbWFyeT4gKioxLiBTbWFydHBob25lIFVzZSBGcmVxdWVuY3k6ICgqU1VRX3VzZV8xIC0gU1VRX3VzZV8zKikqKiA8L3N1bW1hcnk+IAoKRWFjaCBvZiB0aGUgZm9sbG93aW5nIGl0ZW1zIHVzZWQgdGhlIGZvbGxvd2luZyBjb2Rpbmc6Cgp8ICAgICBDT0RFIHwgIDEgIHwgICAyICB8ICAgMyAgIHwgIDQgIHwKfC0tLS0tLS0tLTp8Oi0tLTp8Oi0tLS06fDotLS0tLTp8Oi0tLTp8CnwgKnJlc3BvbnNlKiB8IDAtNSB8IDYtMTAgfCAxMS0xNSB8ID4gMTUgfAoKICAtICoqVGV4dCBNZXNzYWdlcyAocGVyIGRheSkgWypTVVFfdXNlXzEqXSoqICAKICAgIC0gQW5zd2VyIHRvIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb246ICIqT24gYXZlcmFnZSwgaG93IG1hbnkgdGV4dCBtZXNzYWdlcyBkbyB5b3Ugc2VuZCBwZXIgZGF5PyoiICAKICAtICoqU29jaWFsIE1lZGlhIE1lc3NhZ2VzIChwZXIgZGF5KSBbKlNVUV91c2VfMipdKiogIAogICAgLSBBbnN3ZXIgdG8gdGhlIGZvbGxvd2luZyBxdWVzdGlvbjogIipPbiBhdmVyYWdlLCBob3cgbWFueSBzb2NpYWwgbWVkaWEgYmFzZWQgbWVzc2FnZXMgZG8geW91IHNlbmQgcGVyIGRheSBmcm9tIHlvdXIgc21hcnRwaG9uZT8gKGlNZXNzYWdlLCBGYWNlYm9vayBNZXNzZW5nZXIsIFdoYXRzQXBwLCBXZUNoYXQsIGRpcmVjdCBtZXNzYWdlcyB3aXRoaW4gc29jaWFsIG1lZGlhIHBsYXRmb3JtcywgZXRjLikqIiAgCiAgLSAqKlNvY2lhbCBNZWRpYSBQb3N0cyAocGVyIGRheSkgWypTVVFfdXNlXzMqXSoqICAKICAgIC0gQW5zd2VyIHRvIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb246ICIqT24gYXZlcmFnZSwgaG93IG1hbnkgc29jaWFsIG1lZGlhIHBvc3RzIChlLmcuIHdyaXR0ZW4gcG9zdCwgcGljdHVyZSwgYXJ0aWNsZSwgZXRjLikgZG8geW91IHNlbmQgcGVyIGRheSBmcm9tIHlvdXIgc21hcnRwaG9uZT8gKEZhY2Vib29rLCBUd2l0dGVyLCBJbnN0YWdyYW0sIGV0Yy4pKiIgIAo8L2RldGFpbHM+IAoKCjxkZXRhaWxzPiAgCjxzdW1tYXJ5PiAqKjIuIFNtYXJ0cGhvbmUgVXNlIFdpdGggRXh0ZXJuYWwgU3RpbXVsYXRpb24gb3IgRHVyaW5nIE90aGVyIEFjdGl2aXRpZXM6ICgqU1VRX3VzZV80IC0gU1VRX3VzZV83KikqKiA8L3N1bW1hcnk+ICAKCkVhY2ggb2YgdGhlIGZvbGxvd2luZyBpdGVtcyB1c2VkIHRoZSBmb2xsb3dpbmcgY29kaW5nOiAgCgp8ICAgICAgICAgICAgICAgICAgIGNvZGUgfCAgIDEgICB8ICAyIHwgIDMgfCAgICAgICAgICAgIDQgICAgICAgICAgICB8IDUgIHwgNiAgfCA3ICAgICAgfAp8LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS06fDotLS0tLTp8Oi0tOnw6LS06fDotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTp8LS0tLXwtLS0tfC0tLS0tLS0tfAp8ICAgICAgICAgICAgICpyZXNwb25zZSogfCBOZXZlciB8IC0tIHwgLS0gfCBBYm91dCBoYWxmIDxicj50aGUgdGltZSB8IC0tIHwgLS0gfCBBbHdheXMgfAp8IC0tICpubyB0ZXh0IHNwZWNpZmllZCogfCAgICAgICB8ICAgIHwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgIHwgICAgfCAgICAgICAgfAoKICAtICoqVGV4dCBNZXNzYWdlcyAocGVyIGRheSkgWypTVVFfdXNlXzQqXSoqICAKICAgIC0gQW5zd2VyIHRvIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb246ICIqSSBsb29rIGF0IG15IHNtYXJ0cGhvbmUgYmVmb3JlIEkgcm9sbCBvdXQgb2YgYmVkIGluIHRoZSBtb3JuaW5nLioiICAKICAtICoqU29jaWFsIE1lZGlhIE1lc3NhZ2VzIChwZXIgZGF5KSBbKlNVUV91c2VfNSpdKiogIAogICAgLSBBbnN3ZXIgdG8gdGhlIGZvbGxvd2luZyBxdWVzdGlvbjogIipJZiBJIGFtIHdhaXRpbmcgdG8gbWVldCBhIGZyaWVuZCwgSSBwYXNzIHRoZSB0aW1lIGJ5IHVzaW5nIG15IHNtYXJ0cGhvbmUuKiIgIAogIC0gKipTb2NpYWwgTWVkaWEgUG9zdHMgKHBlciBkYXkpIFsqU1VRX3VzZV82Kl0qKiAgCiAgICAtIEFuc3dlciB0byB0aGUgZm9sbG93aW5nIHF1ZXN0aW9uOiAiKkkgdXNlIG15IHNtYXJ0cGhvbmUgd2hpbGUgZHJpdmluZy4qIiAgCiAgLSAqKlNvY2lhbCBNZWRpYSBQb3N0cyAocGVyIGRheSkgWypTVVFfdXNlXzcqXSoqICAKICAgIC0gQW5zd2VyIHRvIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb246ICIqSWYgbXkgc21hcnRwaG9uZSByaW5ncyBvciB2aWJyYXRlcyBpbiB0aGUgbWlkZGxlIG9mIHBlcnNvbmFsIGJ1c2luZXNzLCBJIGxvb2sgYXQgaXQuKiIgIAo8L2RldGFpbHM+IAoKCjxkZXRhaWxzPiAgCjxzdW1tYXJ5PiAqKjMuIFNtYXJ0cGhvbmUgU3ViamVjdGl2ZSBWYWx1ZTogKCpTVVFfZXhwXzEqKSoqIDwvc3VtbWFyeT4gIAoKICAtICoqU3ViamVjdGl2ZSBWYWx1ZSBbKlNVUV91c2VfMSpdKiogIAogICAgLSBBbnN3ZXIgdG8gdGhlIGZvbGxvd2luZyBxdWVzdGlvbjogIipIb3cgbXVjaCBtb25leSB3b3VsZCBpdCB0YWtlIGZvciB5b3UgdG8gZ2l2ZSB1cCB5b3VyIHBob25lIGZvciBhIGZ1bGwgZGF5PyoiICAKICAgIDxkZXRhaWxzPiAgCiAgICA8c3VtbWFyeT4gY29kaW5nIGluZm9ybWF0aW9uICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PiAgCgogICAgICB8ICAgICAgIGNvZGUgfCAgICAxICAgfCAgICAyICAgIHwgICAgMyAgICB8ICAgNCAgfAogICAgICB8LS0tLS0tLS0tLS06fDotLS0tLS06fDotLS0tLS0tOnw6LS0tLS0tLTp8Oi0tLS06fAogICAgICB8ICpyZXNwb25zZSogfCAkMC0kMjAgfCAkMjEtJDQwIHwgJDQxLSQ2MCB8ID4gJDYwIHwKCjwvZGV0YWlscz4gIAo8L2RldGFpbHM+ICAKCgo8ZGV0YWlscz4gIAo8c3VtbWFyeT4gKio0LiBTbWFydHBob25lIE5vdGlmaWNhdGlvbiBUeXBlOiAoKlNVUV9leHBfMiAmIFNVUV9leHBfMyopKiogPC9zdW1tYXJ5PiAgCgogIC0gKipOb3RpZmljYXRpb24gVHlwZSBbKlNVUV91c2VfMipdKiogIAogICAgLSBBbnN3ZXIgdG8gdGhlIGZvbGxvd2luZyBxdWVzdGlvbjogIipEbyB5b3UgcmVjZWl2ZSBub3RpZmljYXRpb25zIChhIHNvdW5kIG9yIHZpYnJhdGlvbikgb24geW91ciBwaG9uZT8gUGxlYXNlIGluZGljYXRlIGFsbCB0aGF0IGFwcGx5LioiICAKICAgIDxkZXRhaWxzPiAgCiAgICA8c3VtbWFyeT4gY29kaW5nIGluZm9ybWF0aW9uICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PiAgCiAgICAgIAogICAgICB8ICAgICAgIGNvZGUgfCAgIDEgICB8ICAgICAyICAgIHwgICAgMyAgICB8ICAgICA0ICAgICB8ICAgICA1ICAgIHwgICAgIDYgICAgfCAgICAgICAgNyAgICAgICAgfAogICAgICB8LS0tLS0tLS0tLS06fDotLS0tLTp8Oi0tLS0tLS0tOnw6LS0tLS0tLTp8Oi0tLS0tLS0tLTp8Oi0tLS0tLS0tOnw6LS0tLS0tLS06fDotLS0tLS0tLS0tLS0tLS06fAogICAgICB8ICpyZXNwb25zZSogfCBFbWFpbCB8IEZhY2Vib29rIHwgVHdpdHRlciB8IEluc3RhZ3JhbSB8IExpbmtlZEluIHwgU25hcGNoYXQgfCBPdGhlciAoc3BlY2lmeSkgfAogICAgICAKICAtICoqU3BlY2lmeSBOb3RpZmljYXRpb24gVHlwZSBbKlNVUV9leHBfMypdKioKICAgIC0gQW5zd2VyIHRvIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb246ICIqUGxlYXNlIFNwZWNpZnk6IFdoZXJlIHlvdSByZWNlaXZlIG5vdGlmaWNhdGlvbnMgKGEgc291bmQgb3IgdmlicmF0aW9uKSBvbiB5b3VyIHBob25lPyoiCjwvZGV0YWlscz4gIAo8L2RldGFpbHM+ICAKCgo8ZGV0YWlscz4gIAo8c3VtbWFyeT4gKio1LiBQaGFudG9tIFZpYnJhdGlvbnM6ICgqU1VRX2V4cF80KikqKiA8L3N1bW1hcnk+ICAKCiAgLSAqKlBoYW50b20gVmlicmF0aW9ucyBbKlNVUV91c2VfNCpdKiogIAogICAgLSBBbnN3ZXIgdG8gdGhlIGZvbGxvd2luZyBxdWVzdGlvbjogIipIYXZlIHlvdSBldmVyIHRob3VnaHQgeW91IGhlYXJkIHlvdXIgcGhvbmUgcmluZyBvciB0aG91Z2h0IHlvdSBmZWx0IGl0IHZpYnJhdGUsIG9ubHkgdG8gZmluZCBvdXQgeW91IHdlcmUgd3Jvbmc/KiIgIAogICAgPGRldGFpbHM+ICAKICAgIDxzdW1tYXJ5PiBjb2RpbmcgaW5mb3JtYXRpb24gKihjbGljayB0byBleHBhbmQpKiA8L3N1bW1hcnk+ICAKCiAgICAgIHwgICAgICAgY29kZSB8ICAxICB8ICAyIHwKICAgICAgfC0tLS0tLS0tLS0tOnw6LS0tOnw6LS06fAogICAgICB8ICpyZXNwb25zZSogfCBZZXMgfCBObyB8Cgo8L2RldGFpbHM+ICAKPC9kZXRhaWxzPiAgCgojIyMjIyBUaGUgU21hcnRwaG9uZSBBdHRhY2htZW50IGFuZCBEZXBlbmRlbmN5IEludmVudG9yeSAoU0FEOyBXYXJkIGV0IGFsLiwgMjAxNykgIAoKPGRldGFpbHM+ICAKPHN1bW1hcnk+IFRoZSBTQUQgYXNrZWQgcGFydGljaXBhbnRzIHRvIHJlc3BvbmQgdG8gMTMgaXRlbXMgKiooKlNBRF8xLVNBRF8xMyopKiogdXNpbmcgYSA3LXBvaW50IGxpa2VydCBzY2FsZS4gKihjbGljayB0byBleHBhbmQpKiA8L3N1bW1hcnk+ICAKCnwgICAgICAgY29kZSB8ICAgICAgICAgICAxICAgICAgICAgIHwgICAgIDIgICAgfCAgICAgICAgICAgMyAgICAgICAgICB8ICAgIDQgICAgfCAgICAgICAgIDUgICAgICAgICB8ICAgNiAgIHwgICAgICAgICA3ICAgICAgICAgfAp8LS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tLS0tLS0tLTp8Oi0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tLS0tLS0tLS06fDotLS0tLS0tOnw6LS0tLS0tLS0tLS0tLS0tLS06fDotLS0tLTp8Oi0tLS0tLS0tLS0tLS0tLS0tOnwKfCAqcmVzcG9uc2UqIHwgU3Ryb25nbHk8YnI+RGlzYWdyZWUgfCBEaXNhZ3JlZSB8IFNvbWV3aGF0PGJyPkRpc2FncmVlIHwgTmV1dHJhbCB8IFNvbWV3aGF0PGJyPkFncmVlIHwgQWdyZWUgfCBTdHJvbmdseTxicj5BZ3JlZSB8CgotICoqU0FEXzE6KiogSSB3b3VsZCBoYXZlIHRyb3VibGUgZ2V0dGluZyB0aHJvdWdoIGEgbm9ybWFsIGRheSB3aXRob3V0IG15IHNtYXJ0cGhvbmUuICAKLSAqKlNBRF8yOioqIEl0IHdvdWxkIGJlIHBhaW5mdWwgZm9yIG1lIHRvIGdpdmUgdXAgbXkgc21hcnRwaG9uZSBmb3IgYSBkYXkuICAKLSAqKlNBRF8zOioqIEkgZmVlbCBsaWtlIEkgY291bGQgbm90IGxpdmUgd2l0aG91dCBteSBzbWFydHBob25lLiAgCi0gKipTQURfNDoqKiBJZiBJIGZvcmdvdCB0byBicmluZyBteSBzbWFydHBob25lIHdpdGggbWUsIEkgd291bGQgZmVlbCBhbnhpb3VzLiAgCi0gKipTQURfNToqKiBJdCBkcml2ZXMgbWUgY3Jhenkgd2hlbiBteSBzbWFydHBob25lIHJ1bnMgb3V0IG9mIGJhdHRlcnkuICAKLSAqKlNBRF82OioqIEkgYW0gdXBzZXQgYW5kIGFubm95ZWQgd2hlbiBJIGZpbmQgSSBkbyBub3QgaGF2ZSByZWNlcHRpb24gb24gbXkgc21hcnRwaG9uZS4gIAotICoqU0FEXzc6KiogSSBmZWVsIGltcGF0aWVudCB3aGVuIHRoZSBJbnRlcm5ldCBjb25uZWN0aW9uIHNwZWVkIG9uIG15IHNtYXJ0cGhvbmUgaXMgc2xvdy4gIAotICoqU0FEXzg6KiogSSBmZWVsIGxvbmVseSB3aGVuIG15IHNtYXJ0cGhvbmUgZG9lcyBub3QgcmluZyBvciB2aWJyYXRlIGZvciBzZXZlcmFsIGhvdXJzLiAgCi0gKipTQURfOToqKiBVc2luZyBteSBzbWFydHBob25lIHJlbGlldmVzIG1lIG9mIG15IHN0cmVzcy4gIAotICoqU0FEXzIwOioqIEkgZmVlbCBleGNpdGVkIHdoZW4gSSBoYXZlIGEgbmV3IG1lc3NhZ2Ugb3Igbm90aWZpY2F0aW9uLiAgCi0gKipTQURfMTE6KiogVXNpbmcgbXkgc21hcnRwaG9uZSBtYWtlcyBtZSBmZWVsIGhhcHB5LiAgCi0gKipTQURfMTI6KiogSSBmaW5kIGl0IHRvdWdoIHRvIGZvY3VzIHdoZW5ldmVyIG15IHNtYXJ0cGhvbmUgaXMgbmVhcmJ5LiAgCi0gKipTQURfMTM6KiogSSBiZWNvbWUgbGVzcyBhdHRlbnRpdmUgdG8gbXkgc3Vycm91bmRpbmdzIHdoZW4gSeKAmW0gdXNpbmcgbXkgc21hcnRwaG9uZS4gIAoKPC9kZXRhaWxzPiAKCjwvZGV0YWlscz4KICAKPGRldGFpbHM+CjxzdW1tYXJ5PiBUaGlzIGNvZGUgaW1wb3J0ZWQgdGhlIERlbW9ncmFwaGljLCBTVVEsIGFuZCBTQUQgcmF3IGRhdGEuICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PiAgCgoKYGBge3J9CnN1cnZleV9yYXcgPSB1dGlsczo6cmVhZC5jc3YoInJhd19zdXJ2ZXkuY3N2IiwgaGVhZGVyID0gVFJVRSkKCiMgcmVvcmdhbml6ZSByb3dzIHNvIHRoYXQgdGhlIGRhdGEgaXMgb3JkZXJlZCBieSB0aGUgcGFydGljaXBhbnQgbnVtYmVyIChlLmcuIDEsIDIsIDMsIDQuLi4pCnN1cnZleV9yYXcgPSBkcGx5cjo6YXJyYW5nZShzdXJ2ZXlfcmF3LCBzdXJfcGFydGljaXBhbnQpCmBgYAoKICA8L2RldGFpbHM+ICAKPC9kZXRhaWxzPiAgCgojIyMjIDUuIFRlc3RpbmcgVHJhY2tpbmcgU2hlZXQgUmF3IERhdGEgIAoKPGRldGFpbHM+ICAKCjxzdW1tYXJ5PiBUaGUgKipUZXN0aW5nIFRyYWNraW5nIFNoZWV0IFJhdyBEYXRhKiogd2FzIGNvbGxlY3RlZCBkdXJpbmcgdGVzdGluZyAqYnkgdGhlIGV4cGVyaW1lbnRlciogdG8gc3RvcmUgcmVsZXZhbnQgaW5mb3JtYXRpb24gb24gcGFydGljaXBhbnQncyAoMSkgR2VuZXJhbCBJbmZvcm1hdGlvbiAoZS5nLiB0ZXN0aW5nIHN0YXJ0IGRhdGUpLCAoMikgTWFuaXB1bGF0aW9uIENvbmRpdGlvbiAoZS5nLiBhc3NpZ25lZCBsb2NhdGlvbiBhbmQgcG93ZXIgbWFuaXB1bGF0aW9uKSwgYW5kICgzKSBEYXRhIENsZWFuaW5nIChlLmcuIGV4Y2x1c2lvbiBjcml0ZXJhIGZyb20gdGVzdGluZyBlcnJvciBvciBvdGhlciBub24tdGFzay1zcGVjaWZpYyBjcml0ZXJpYSkuIFRoZSByYXcgZGF0YSBmcm9tIHRoZSB0cmFja2luZyBzaGVldCB3YXMgaW1wb3J0ZWQgYXMgYSBkYXRhZnJhbWUsICIqKnRyYWNrX3JhdyoqIiwgYW5kIGluY2x1ZGVkIHRoZSBmb2xsb3dpbmc6ICooY2xpY2sgdG8gc2VlIGRlc2NyaXB0aW9uKSogPC9zdW1tYXJ5PiAgCgo8ZGV0YWlscz4gIAo8c3VtbWFyeT4gKioxLiBHZW5lcmFsIEluZm9ybWF0aW9uOioqIDwvc3VtbWFyeT4gIAoKLSAqKlRlc3RpbmcgRGF0ZSBbKnRyYWNrX2RhdGUqXSoqICAKICAtIFRoZSBkYXRlIGEgcGFydGljaXBhbnQgY29tcGxldGVkIHRoZSBzdHVkeSAoWS9NL0QpICAKLSAqKlRlc3RpbmcgVGltZSBbKmRhdGVfZW5kKl0qKiAgCiAgLSBUaGUgdGltZSBhIHBhcnRpY2lwYW50IHdhcyBzY2hlZHVsZWQgdG8gY29tcGxldGUgdGhlIHN0dWR5ICgyNGhyLXRpbWUpLiAqTm90ZTogTWFueSBwYXJ0aWNpcGFudHMgd2VyZSB0ZXN0ZWQgYXQgdGhlIHNhbWUgdGltZSwgYnV0IGluIHNlcGFyYXRlIGN1YmljbGUtdHlwZSBkZXNrcyB0byBhdm9pZCBhbnkgZ3JvdXAtdGVzdGluZyBkeW5hbWljKiAgCi0gKipQYXJ0aWNpcGFudCBudW1iZXIgWyp0cmFja19wYXJ0aWNpcGFudCpdKiogIAo8L2RldGFpbHM+ICAKCgo8ZGV0YWlscz4gIAo8c3VtbWFyeT4gKioyLiBNYW51cHVsYXRpb24gQ29uZGl0aW9uOioqIDwvc3VtbWFyeT4gIAoKLSAqKlNtYXJ0cGhvbmUgTG9jYXRpb24gWyp0cmFja19sb2NhdGlvbipdKiogIAogIC0gVGhlIHNtYXJ0cGhvbmUgbG9jYXRpb24gYXNzaWduZWQgdG8gdGhlIHBhcnRpY2lwYW50IChpLmUuIGRlc2ssIHBvY2tldC9iYWcsIG9yIG91dHNpZGUpICAKICA8ZGV0YWlscz4gIAogIDxzdW1tYXJ5PiBjb2RpbmcgaW5mb3JtYXRpb24gKihjbGljayB0byBleHBhbmQpKiA8L3N1bW1hcnk+ICAKCiAgICB8ICAgICAgIGNvZGUgfCAgIDEgIHwgICAgICAyICAgICB8ICAgIDMgICAgfAogICAgfC0tLS0tLS0tLS0tOnw6LS0tLTp8Oi0tLS0tLS0tLS06fDotLS0tLS0tOnwKICAgIHwgKnJlc3BvbnNlKiB8IERlc2sgfCBQb2NrZXQvQmFnIHwgT3V0c2lkZSB8CgotICoqU21hcnRwaG9uZSBQb3dlciBbKnRyYWNrX3Bvd2VyKl0qKiAgCiAgLSBUaGUgc21hcnRwaG9uZSBwb3dlciBhc3NpZ25lZCB0byB0aGUgcGFydGljaXBhbnQgKGkuZS4gT04gb3IgT0ZGKSAgCiAgPGRldGFpbHM+ICAKICA8c3VtbWFyeT4gY29kaW5nIGluZm9ybWF0aW9uICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PiAgCgogICAgfCAgICAgICBjb2RlIHwgIDEgfCAgMiAgfAogICAgfC0tLS0tLS0tLS0tOnw6LS06fDotLS06fAogICAgfCAqcmVzcG9uc2UqIHwgT24gfCBPZmYgfAoKLSAqKlNtYXJ0cGhvbmUgQ29uZGl0aW9uIFsqdHJhY2tfY29uZGl0aW9uKl0qKiAgCiAgLSBUaGUgc21hcnRwaG9uZSBjb25kaXRpb24gKGkuZS4gY29tYmluYXRpb24gb2YgbG9jYXRpb24gJiBwb3dlcikgYXNzaWduZWQgdG8gdGhlIHBhcnRpY2lwYW50ICAKICA8ZGV0YWlscz4gIAogIDxzdW1tYXJ5PiBjb2RpbmcgaW5mb3JtYXRpb24gKihjbGljayB0byBleHBhbmQpKiA8L3N1bW1hcnk+ICAKICAgIAogICAgfCAgICAgICBjb2RlIHwgICAgIDEgICAgIHwgICAgICAgIDIgICAgICAgIHwgICAgICAgMyAgICAgIHwgICAgICA0ICAgICB8ICAgICAgICAgNSAgICAgICAgfCAgICAgICA2ICAgICAgIHwKICAgIHwtLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tLTp8CiAgICB8ICpyZXNwb25zZSogfCBPTiAmIERlc2sgfCBPTiAmIFBvY2tldC9CYWcgfCBPTiAmIE91dHNpZGUgfCBPRkYgJiBEZXNrIHwgT0ZGICYgUG9ja2V0L0JhZyB8IE9GRiAmIE91dHNpZGUgfAoKLSAqKkNvdW50ZXIgQmFsYW5jZWQgT3JkZXIgWypiYWxhbmNlKl0qKiAgCiAgLSBUaGlzIGRlcGljdHMgd2hpY2ggb2YgdGhlIG1haW4gdGFza3MgKGkuZS4gZWl0aGVyIHRoZSBPU3BhbiB0YXNrIG9yIHRoZSBDdWUtRGVwZW5kZW50IEdvL05vLUdvIFRhc2spIHdhcyBjb21wbGV0ZWQgZmlyc3QgIAogIDxkZXRhaWxzPiAgCiAgPHN1bW1hcnk+IGNvZGluZyBpbmZvcm1hdGlvbiAqKGNsaWNrIHRvIGV4cGFuZCkqIDwvc3VtbWFyeT4gIAoKICAgIHwgICAgICAgY29kZSB8ICAgICAgICAgICAgICAxICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgMiAgICAgICAgICAgICAgICAgICAgICB8CiAgICB8LS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS06fAogICAgfCAqcmVzcG9uc2UqIHwgT1NwYW4gVGFzayBjb21wbGV0ZWQgZmlyc3QgfCBDdWUtRGVwZW5kZW50IEdvL05vLUdvIFRhc2sgY29tcGxldGVkIGZpcnN0IHwKICAgIAo8L2RldGFpbHM+ICAKCjxkZXRhaWxzPiAgCjxzdW1tYXJ5PiAqKjMuIERhdGEgQ2xlYW5pbmc6KiogPC9zdW1tYXJ5PiAgCgogIC0gKipFeGNsdWRlIGZyb20gQW5hbHlzaXMgWypleGNsdWRlKl0qKiAgCiAgICAtIFRoaXMgZGVwaWN0cyB3aGV0aGVyIGEgcGFydGljaXBhbnQgc2hvdWxkIGJlIGV4Y2x1ZGVkIGZyb20gYW5hbHlzaXMgZHVlIHRvIHRlc3RpbmcgZXJyb3Igb3Igb3RoZXIgbm9uLXRhc2stc3BlY2lmaWMgY3JpdGVyaWEgKGkuZS4gZm9yIHJlYXNvbnMgb3RoZXIgdGhhbiB0aGUgdGFzayBleGNsdXNpb24gY3JpdGVyaWEgaW4gdGhlIGRhdGEgYW5hbHlzaXMgcGxhbikuIAogICAgPGRldGFpbHM+ICAKICAgIDxzdW1tYXJ5PiBjb2RpbmcgaW5mb3JtYXRpb24gKihjbGljayB0byBleHBhbmQpKiA8L3N1bW1hcnk+ICAKCiAgICAgIHwgICAgICAgY29kZSB8ICAgICAgICAgICAgICAgIDEgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgMiAgICAgICAgICAgICAgIHwKICAgICAgfC0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS06fAogICAgICB8ICpyZXNwb25zZSogfCBZZXMgKHBhcnRpY2lwYW50ICoqZXhjbHVkZWQqKikgfCBObyAocGFydGljaXBhbnQgKippbmNsdWRlZCoqKSB8CgogIC0gKipSZWFzb24gZm9yIEV4Y2x1c2lvbiBmcm9tIEFuYWx5c2lzIFsqcmVhc29uKl0qKiAgCiAgICAtIFRoaXMgZGVwaWN0cyB0aGUgcmVhc29uIChzdW1tYXJpemVkIGludG8gNSBjYXRlZ29yaWVzKSBhIHBhcnRpY2lwYW50IHNob3VsZCBiZSBleGNsdWRlZCBmcm9tIGFuYWx5c2lzIGR1ZSB0byB0ZXN0aW5nIGVycm9yIG9yIG90aGVyIG5vbi10YXNrLXNwZWNpZmljIGNyaXRlcmlhIChpLmUuIGZvciByZWFzb25zIG90aGVyIHRoYW4gdGhlIHRhc2sgZXhjbHVzaW9uIGNyaXRlcmlhIGluIHRoZSBkYXRhIGFuYWx5c2lzIHBsYW4pLiAqTm90ZTogdGhpcyBpbmNsdWRlcyBhIGNhdGVnb3J5IGZvciAibm8gZXhjbHVzaW9uIGlzc3VlcyIsIHdoZXJlIGEgcGFydGljaXBhbnQgd2FzIG5vdCBleGNsdWRlZCogIAogICAgPGRldGFpbHM+ICAKICAgIDxzdW1tYXJ5PiBjb2RpbmcgaW5mb3JtYXRpb24gKihjbGljayB0byBleHBhbmQpKiA8L3N1bW1hcnk+ICAKCiAgICAgIHwgICAgICAgY29kZSB8ICAgICAgICAgIDEgICAgICAgICAgfCAgICAgICAgICAgICAgMiAgICAgICAgICAgICAgfCAgICAgICAgMyAgICAgICB8ICAgICAgNCAgICAgIHwgICAgICAgNSAgICAgICB8CiAgICAgIHwtLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tLTp8CiAgICAgIHwgKnJlc3BvbnNlKiB8IG5vIGV4Y2x1c2lvbiBpc3N1ZXMgfCBleHRlcm5hbCBkaXN0cmFjdG9yIChub2lzZSkgfCBnbmcgaW5jb21wbGV0ZSB8IGduZyBtaXNzaW5nIHwgb3NwYW4gbWlzc2luZyB8CiAgICAgIAogIC0gKipQb3NzaWJsZSBPdXRsaWVyIFsqcG9zX291dCpdKiogIAogICAgLSBUaGlzIGRlcGljdHMgd2hldGhlciBhIHBhcnRpY2lwYW50IGlzIGEgcG9zc2libGUgb3V0bGllciBmb3IgZXhwbG9yYXRvcnkgYW5hbHlzZXMuICpOb3RlOiB0aGlzIHdhcyBub3QgYXBwbGllZCB0byBhbnkgYW5hbHlzaXMgdW5sZXNzIGV4cGxpY2l0bHkgc3RhdGVkKgogICAgPGRldGFpbHM+ICAKICAgIDxzdW1tYXJ5PiBjb2RpbmcgaW5mb3JtYXRpb24gKihjbGljayB0byBleHBhbmQpKiA8L3N1bW1hcnk+ICAKCiAgICAgIHwgICAgICAgY29kZSB8ICAgICAgICAgICAgICAgICAgICAgMSAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgICAyICAgICAgICAgICAgICAgICAgICAgIHwKICAgICAgfC0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS06fAogICAgICB8ICpyZXNwb25zZSogfCBZZXMgKGRvZXMgcXVhbGlmeSBhcyBhIHBvc3NpYmxlIG91dGxpZXIpIHwgTm8gKGRvZXMgbm90IHF1YWxpZnkgYXMgYSBwb3NzaWJsZSBvdXRsaWVyKSB8CiAgICAgIAogIC0gKipFeHBlcmltZW50ZXIgWypleHBlcmltZW50ZXIqXSoqICAKICAgIC0gVGhpcyBkZXBpY3RzIHdoaWNoIGV4cGVyaW1lbnRlciAoMyB0b3RhbCkgY29sbGVjdGVkIHRoZSBkYXRhIGZvciBhIHBhcnRpY2lwYW50LiAqTm90ZTogdGhpcyB3YXMgY29sbGVjdGVkIGZvciBleHBsb3JhdG9yeSBhbmFseXNlcyBhbmQgd2FzIG5vdCB1c2VkIHVubGVzcyBleHBsaWNpdGx5IHN0YXRlZCoKICAgIDxkZXRhaWxzPiAgCiAgICA8c3VtbWFyeT4gY29kaW5nIGluZm9ybWF0aW9uICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PiAgCgogICAgICB8ICAgICAgIGNvZGUgfCAgMSAgfCAgMiB8ICAzIHwKICAgICAgfC0tLS0tLS0tLS0tOnw6LS0tOnw6LS06fDotLTp8CiAgICAgIHwgKnJlc3BvbnNlKiB8IEFSUCB8IFNXIHwgTE0gfAoKPC9kZXRhaWxzPiAgCjwvZGV0YWlscz4gIAoKPGRldGFpbHM+CjxzdW1tYXJ5PiBUaGlzIGNvZGUgaW1wb3J0ZWQgdGhlIHN0dWR5IHRyYWNraW5nIHNoZWV0IHJhdyBkYXRhLiAqKGNsaWNrIHRvIGV4cGFuZCkqIDwvc3VtbWFyeT4gIAoKYGBge3J9CnRyYWNrX3JhdyA9IHV0aWxzOjpyZWFkLmNzdigicmF3X3RyYWNraW5nLmNzdiIsIGhlYWRlciA9IFRSVUUpCgojIHJlb3JnYW5pemUgcm93cyBzbyB0aGF0IHRoZSBkYXRhIGlzIG9yZGVyZWQgYnkgdGhlIHBhcnRpY2lwYW50IG51bWJlciAoZS5nLiAxLCAyLCAzLCA0Li4uKQp0cmFja19yYXcgPSBkcGx5cjo6YXJyYW5nZSh0cmFja19yYXcsIHRyYWNrX3BhcnRpY2lwYW50KQpgYGAKCiAgPC9kZXRhaWxzPiAKPC9kZXRhaWxzPiAgIAoKIyMgQ29uc3RydWN0IFdvcmtpbmcgRGF0YWZyYW1lcyAgCgpJbiBvcmRlciB0byBjb21wbGV0ZSB0aGUgcHJlc2VudCBzdHVkeSdzIGFuYWx5c2VzLCBlaWdodCBkYXRhIGZyYW1lcyB3ZXJlIGNyZWF0ZWQuICAKCiMjIyAxLiBBbGwgRGF0YSAgCgo8ZGV0YWlscz4gIAoKPHN1bW1hcnk+IEFsbCB0aGUgZGF0YSBmcm9tIHRoZSBwcmVzZW50IHN0dWR5IGluIG9uZSBkYXRhIGZyYW1lOiAqKiJhbGxfZGF0YSIqKiAqKGNsaWNrIHRvIHNlZSBtb3JlKSogPC9zdW1tYXJ5PiAgCgotIFRoaXMgZGF0YSBpbmNsdWRlZCB0aGUgZm9sbG93aW5nOiAgIAogIC0gYHIgY29sbmFtZXMoYWxsX2RhdGEpYCAgCgo8ZGV0YWlscz4KPHN1bW1hcnk+IFRoaXMgY29kZSBvcmdhbml6ZWQgdGhlIHJhdyBkYXRhIGludG8gb25lIGRhdGEgZnJhbWUuICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PgoKYGBge3J9CgojIEZpbmQgdGhlIGZpbmFsIHBhcnRpY2lwYW50IGxpc3QgZm9yIHRoZSBhbmFseXNlcyAgCiAgIyBnZXQgYSBsaXN0IG9mIHBhcnRpY2lwYW50cyB0aGF0ICgxKSBjb21wbGV0ZWQgdGhlIGduZyB0YXNrIGFuZCAoMikgYXJlIG5vdCBleGNsdWRlZCAoaS5lLiwgaW5jbHVzaW9uIGxpc3QpIGJhc2VkIG9uIHRoZSAiZXhjbHVkZSIgY29sdW1uIGluIHRoZSB0cmFja2luZyBzaGVldCAgCiAgIyAoMSkgRmlyc3QgZ2V0IHRoZSBnbmcgcGFydGljaXBhbnQgbGlzdCAgCiAgZ25nX3Bhcl9saXN0ID0gZ25nX2RhdGFfZXh0cmFjdGVkJGduZ19wYXJ0aWNpcGFudCAgCiAgIyAoMikgTmV4dCwgZ2V0IHRoZSBpbmNsdXNpb24gbGlzdCAgCiAgaW5jbHVkZV9wYXJfbGlzdCA9IGRhdGEuZnJhbWUodHJhY2tfcmF3JHRyYWNrX3BhcnRpY2lwYW50W3doaWNoKHRyYWNrX3JhdyRleGNsdWRlICVpbiUgMildKSAgCiAgICBjb2xuYW1lcyhpbmNsdWRlX3Bhcl9saXN0KSA9IGMoInBhcl9saXN0IikKICAjIEdldCBhIGxpc3Qgb2YgYWxsIHRoZSBwYXJ0aWNpcGFudHMgd2hvIGNvbXBsZXRlZCB0aGUgc3R1ZHkgKGZyb20gdGhlIHRlc3RpbmcgdHJhY2tpbmcgc2hlZXQpCiAgYWxsX3BhcnRpY2lwYW50cyA9IGFzLmRhdGEuZnJhbWUodHJhY2tfcmF3JHRyYWNrX3BhcnRpY2lwYW50KQogICAgY29sbmFtZXMoYWxsX3BhcnRpY2lwYW50cykgPSBjKCJhbGxfcGFydGljaXBhbnRzIikKICAKIyBmaW5kIHRoZSBwYXJ0aWNpcGFudHMgdG8gcmVtb3ZlIGZyb20gdGhlIGRhdGEKICAjIEZpbHRlciBlYWNoIGRhdGEgbGlzdCBmcm9tIHRoZSBsaXN0IG9mIGFsbCBwYXJ0aWNpcGFudHMgIAogIGduZ19yZW1vdmUgPSBkYXRhLmZyYW1lKCJhbGxfcGFydGljaXBhbnRzIiA9IGZpbHRlcihhbGxfcGFydGljaXBhbnRzLCAhKGFsbF9wYXJ0aWNpcGFudHMgJWluJSBnbmdfcGFyX2xpc3QpKSkKICB0cmFja19yZW1vdmUgPSBkYXRhLmZyYW1lKCJhbGxfcGFydGljaXBhbnRzIiA9IGZpbHRlcihhbGxfcGFydGljaXBhbnRzLCAhKGFsbF9wYXJ0aWNpcGFudHMgJWluJSBpbmNsdWRlX3Bhcl9saXN0JHBhcl9saXN0KSkpCiAgcmVhc29uX3JlbW92ZSA9IGMocmVwKCJnbmciLCBsZW5ndGgoZ25nX3JlbW92ZSRhbGxfcGFydGljaXBhbnRzKSksIHJlcCgidHJhY2siLCBsZW5ndGgodHJhY2tfcmVtb3ZlJGFsbF9wYXJ0aWNpcGFudHMpKSkKICAKICAjIE1ha2UgYSBsaXN0IG9mIGFsbCB0aGUgcmVtb3ZlZCBwYXJ0aWNpcGFudHMgLS0gImFsbF9yZW1vdmUiCiAgYWxsX3JlbW92ZV9ub3RjbGVhbiA9IGRhdGEuZnJhbWUocmJpbmQoZ25nX3JlbW92ZSwgdHJhY2tfcmVtb3ZlKSwgcmVhc29uX3JlbW92ZSkKICAgICMgcmVtb3ZlIGFueSBkdXBsaWNhdGVzIGZyb20gdGhlIGxpc3QKICAgIGFsbF9yZW1vdmVfbm9kdXAgPSBhbGxfcmVtb3ZlX25vdGNsZWFuWyFkdXBsaWNhdGVkKGFsbF9yZW1vdmVfbm90Y2xlYW4kYWxsX3BhcnRpY2lwYW50cyksIF0KICAgICMgcmVvcmdhbml6ZSByb3dzIHNvIHRoYXQgdGhlIGRhdGEgaXMgb3JkZXJlZCBieSB0aGUgcGFydGljaXBhbnQgbnVtYmVyIChlLmcuIDEsIDIsIDMsIDQuLi4pICAKICAgIGFsbF9yZW1vdmUgPSBkcGx5cjo6YXJyYW5nZShhbGxfcmVtb3ZlX25vZHVwLCBhbGxfcGFydGljaXBhbnRzKSAgCiAgICAKIyBGaWx0ZXIgcmF3IGRhdGEgdXNpbmcgdGhlIGZpbmFsIHBhcnRpY2lwYW50IGxpc3QgZm9yOiBvc3Bhbl9yYXcsIGduZ19yYXcsIHN1cnZleV9yYXcsIGFuZCB0cmFja19yYXcKICAjIFRoaXMgd2lsbCBub3cgdGhlIHRoZSB3b3JraW5nIGRhdGEgZm9yIHRoZSBzdHVkeSAoaS5lLiB0aGUgImZpbmFsIiBkYXRhKSAgCiAgICAjIE9TcGFuIERhdGEgIAogICAgb3NwYW5fZmluYWwgPSBkcGx5cjo6ZmlsdGVyKG9zcGFuX3JhdywgIW9zcGFuX3BhcnRpY2lwYW50ICVpbiUgYWxsX3JlbW92ZSRhbGxfcGFydGljaXBhbnRzKQogICAgIyBHbmcgRGF0YSAgCiAgICBnbmdfZmluYWwgPSBkcGx5cjo6ZmlsdGVyKGduZ19kYXRhX2V4dHJhY3RlZCwgIWduZ19wYXJ0aWNpcGFudCAlaW4lIGFsbF9yZW1vdmUkYWxsX3BhcnRpY2lwYW50cykKICAgICMgU3VydmV5IERhdGEgIAogICAgc3VydmV5X2ZpbmFsID0gZHBseXI6OmZpbHRlcihzdXJ2ZXlfcmF3LCAhc3VyX3BhcnRpY2lwYW50ICVpbiUgYWxsX3JlbW92ZSRhbGxfcGFydGljaXBhbnRzKQogICAgIyBUcmFja2luZyBEYXRhICAKICAgIHRyYWNrX2ZpbmFsID0gZHBseXI6OmZpbHRlcih0cmFja19yYXcsICF0cmFja19wYXJ0aWNpcGFudCAlaW4lIGFsbF9yZW1vdmUkYWxsX3BhcnRpY2lwYW50cykKCiMgQ29tYmluZSBhbGwgdGhlIGZpbmFsIGRhdGEgaW50byAxIGRhdGEgZnJhbWUgd2l0aCB0aGUgZm9sbG93aW5nOgogICMgU3RhcnQgYnkgY3JlYXRpbmcgYSBkYXRhIGZyYW1lIHdpdGggdGhlIGZpbmFsIHBhcnRpY2lwYW50IGxpc3QgaW4gdGhlIDFzdCBjb2x1bW46ICJwYXJ0aWNpcGFudCIKICBhbGxfcGFyID0gYXMuZGF0YS5mcmFtZSh0cmFja19maW5hbCR0cmFja19wYXJ0aWNpcGFudCkKICAgIGNvbG5hbWVzKGFsbF9wYXIpID0gYygicGFydGljaXBhbnQiKQoKICAjIHRvIHVzZSB0aGUgbWVyZ2UgZnVuY3Rpb24sIGNoYW5nZSB0aGUgcmVzcGVjdGl2ZSAicGFydGljaXBhbnQiIGNvbHVtbiBuYW1lIGluIGVhY2ggZGF0YSBmcmFtZSB0byAicGFydGljaXBhbnQiCiAgICAjIE9TcGFuIERhdGEKICAgIGNvbG5hbWVzKG9zcGFuX2ZpbmFsKVt3aGljaChuYW1lcyhvc3Bhbl9maW5hbCkgPT0gIm9zcGFuX3BhcnRpY2lwYW50IildID0gYygicGFydGljaXBhbnQiKQogICAgIyBHbmcgRGF0YQogICAgY29sbmFtZXMoZ25nX2ZpbmFsKVt3aGljaChuYW1lcyhnbmdfZmluYWwpID09ICJnbmdfcGFydGljaXBhbnQiKV0gPSBjKCJwYXJ0aWNpcGFudCIpCiAgICAjIFN1cnZleSBEYXRhCiAgICBjb2xuYW1lcyhzdXJ2ZXlfZmluYWwpW3doaWNoKG5hbWVzKHN1cnZleV9maW5hbCkgPT0gInN1cl9wYXJ0aWNpcGFudCIpXSA9IGMoInBhcnRpY2lwYW50IikKICAgICMgVHJhY2tpbmcgRGF0YQogICAgY29sbmFtZXModHJhY2tfZmluYWwpW3doaWNoKG5hbWVzKHRyYWNrX2ZpbmFsKSA9PSAidHJhY2tfcGFydGljaXBhbnQiKV0gPSBjKCJwYXJ0aWNpcGFudCIpCgojIE1lcmdlIGFsbCA0IGRhdGEgZnJhbWVzIGludG8gMSBkYXRhIGZyYW1lIC0tICJhbGxfZGF0YSIKICBhbGxfZGF0YSA9IFJlZHVjZShmdW5jdGlvbih4LCB5KSBtZXJnZSh4LCB5LCBieT0icGFydGljaXBhbnQiKSwgbGlzdCh0cmFja19maW5hbCwgb3NwYW5fZmluYWwsIGduZ19maW5hbCwgZHBseXI6OnNlbGVjdChzdXJ2ZXlfZmluYWwsIC1jKHN1cl9sb2NhdGlvbiwgc3VyX3Bvd2VyLCBzdXJfY29uZGl0aW9uKSkpKQogICAgIyByZW5hbWUgdGhlIHRyYWNraW5nIHNoZWV0IGNvbHVtbnMgZm9yIHRoZSBsb2NhdGlvbiwgcG93ZXIsIGFuZCBjb25kaXRpb24gCiAgICBjb2xuYW1lcyhhbGxfZGF0YSlbd2hpY2gobmFtZXMoYWxsX2RhdGEpID09IGMoInRyYWNrX2xvY2F0aW9uIiwgInRyYWNrX3Bvd2VyIiwgInRyYWNrX2NvbmRpdGlvbiIpKV0gPSBjKCJsb2NhdGlvbiIsICJwb3dlciIsICJjb25kaXRpb24iKQoKYGBgCiAgCjwvZGV0YWlscz4KCjwvZGV0YWlscz4KICAKCiMjIyAyLiBBbGwgRGF0YSAtIEdvL05vLUdvIHNlcGFyYXRlZCBieSBDdWUgVHlwZSAoV0lERSBGT1JNQVQpCgo8ZGV0YWlscz4gIAoKPHN1bW1hcnk+IEFsbCB0aGUgZGF0YSBmcm9tIHRoZSBwcmVzZW50IHN0dWR5IGluIG9uZSBkYXRhIGZyYW1lLCB3aXRoIHRoZSBHby9Oby1HbyBkYXRhIHNlcGFyYXRlZCBieSB0YXJnZXQgdHlwZSAoaS5lLiBlaXRoZXIgImdvIiBvciAibm8tZ28iKSwgcHJlc2VudGVkIGluIFdJREUgRk9STUFUOiAqKiJhbGxfZGF0YV9jdWUiKiogKihjbGljayB0byBzZWUgbW9yZSkqIDwvc3VtbWFyeT4gIAoKLSBUaGlzIGRhdGEgaW5jbHVkZWQgdGhlIGZvbGxvd2luZzogICAKICAtIGByIGNvbG5hbWVzKGFsbF9kYXRhX2N1ZSlgICAKCjxkZXRhaWxzPgo8c3VtbWFyeT4gVGhpcyBjb2RlIG9yZ2FuaXplZCB0aGUgcmF3IGRhdGEgaW50byBvbmUgZGF0YSBmcmFtZS4gKihjbGljayB0byBleHBhbmQpKiA8L3N1bW1hcnk+CmBgYHtyIHdhcm5pbmc9RkFMU0V9CiMgdXNlIHRoZSBsaXN0IG9mIGFsbCB0aGUgcGFydGljaXBhbnRzIHRvIHJlbW92ZSAtLSAiYWxsX3JlbW92ZSIgLS0gdG8gZmlsdGVyIHRoZSByYXcgZ25nIGxvbmcgZGF0YQogICMgZm9yIHRoZSAiZ28iIHRhcmdldHMKICBnbmdfdl9maW5hbCA9IGRwbHlyOjpmaWx0ZXIoZ25nX2RhdGFfZXh0cmFjdGVkX3YsICFwYXJ0aWNpcGFudF9sb25nICVpbiUgYWxsX3JlbW92ZSRhbGxfcGFydGljaXBhbnRzKQogICMgZm9yIHRoZSAibm8tZ28iIHRhcmdldHMKICBnbmdfaF9maW5hbCA9IGRwbHlyOjpmaWx0ZXIoZ25nX2RhdGFfZXh0cmFjdGVkX2gsICFwYXJ0aWNpcGFudF9sb25nICVpbiUgYWxsX3JlbW92ZSRhbGxfcGFydGljaXBhbnRzKQoKIyBDb21iaW5lIGFsbCB0aGUgZmluYWwgZGF0YSBpbnRvIDEgZGF0YSBmcmFtZSB3aXRoIHRoZSBmb2xsb3dpbmc6CiAgIyB1c2UgdGhlIGZpbmFsIHBhcnRpY2lwYW50IGxpc3QgLS0gImFsbF9wYXIiIC0tIGFzIHRoZSAxc3QgY29sdW1uIGluIHRoZSBkYXRhIGZyYW1lcwoKICAjIHRvIHVzZSB0aGUgbWVyZ2UgZnVuY3Rpb24sIGNoYW5nZSB0aGUgcmVzcGVjdGl2ZSAicGFydGljaXBhbnQiIGNvbHVtbiBuYW1lIGluIGVhY2ggZGF0YSBmcmFtZSB0byAicGFydGljaXBhbnQiCiAgICAjIHRoaXMgd2FzIGFscmVhZHkgZG9uZSBmb3IgdGhlIG90aGVyIGRhdGEgZnJhbWVzIChlLmcuIG9zcGFuX2ZpbmFsLCBzdXJ2ZXlfZmluYWwpCiAgICAjIGZvciB0aGUgInZlcnRpY2FsIiB0YXJnZXRzCiAgICBjb2xuYW1lcyhnbmdfdl9maW5hbClbd2hpY2gobmFtZXMoZ25nX3ZfZmluYWwpID09ICJwYXJ0aWNpcGFudF9sb25nIildID0gYygicGFydGljaXBhbnQiKQogICAgIyBmb3IgdGhlICJob3Jpem9udGFsIiB0YXJnZXRzCiAgICBjb2xuYW1lcyhnbmdfaF9maW5hbClbd2hpY2gobmFtZXMoZ25nX2hfZmluYWwpID09ICJwYXJ0aWNpcGFudF9sb25nIildID0gYygicGFydGljaXBhbnQiKQoKIyBNZXJnZSBhbGwgNCBkYXRhIGZyYW1lcyBpbnRvIDEgZGF0YSBmcmFtZSAtLSAiYWxsX2RhdGFfY3VlIgogIGFsbF9kYXRhX2N1ZSA9IFJlZHVjZShmdW5jdGlvbih4LCB5KSBtZXJnZSh4LCB5LCBieT0icGFydGljaXBhbnQiKSwgbGlzdCh0cmFja19maW5hbCwgb3NwYW5fZmluYWwsIGduZ192X2ZpbmFsLCBkcGx5cjo6c2VsZWN0KGduZ19oX2ZpbmFsLCAtYyhhZ2VfbG9uZywgbGFuZ19sb25nKSksIGRwbHlyOjpzZWxlY3Qoc3VydmV5X2ZpbmFsLCAtYyhzdXJfbG9jYXRpb24sIHN1cl9wb3dlciwgc3VyX2NvbmRpdGlvbikpKSkKICAgICMgcmVuYW1lIHRoZSB0cmFja2luZyBzaGVldCBjb2x1bW5zIGZvciB0aGUgbG9jYXRpb24sIHBvd2VyLCBhbmQgY29uZGl0aW9uIAogICAgY29sbmFtZXMoYWxsX2RhdGFfY3VlKVt3aGljaChuYW1lcyhhbGxfZGF0YV9jdWUpID09IGMoInRyYWNrX2xvY2F0aW9uIiwgInRyYWNrX3Bvd2VyIiwgInRyYWNrX2NvbmRpdGlvbiIpKV0gPSBjKCJsb2NhdGlvbiIsICJwb3dlciIsICJjb25kaXRpb24iKQogICAgCmBgYAoKPC9kZXRhaWxzPiAgCjwvZGV0YWlscz4gIAogIAojIyMgMy4gQWxsIERhdGEgLSBHby9Oby1HbyBzZXBhcmF0ZWQgYnkgQ3VlIFR5cGUgKExPTkcgRk9STUFUKQoKPGRldGFpbHM+ICAKCjxzdW1tYXJ5PiBBbGwgdGhlIGRhdGEgZnJvbSB0aGUgcHJlc2VudCBzdHVkeSBpbiBvbmUgZGF0YSBmcmFtZSwgd2l0aCB0aGUgR28vTm8tR28gZGF0YSBzZXBhcmF0ZWQgYnkgdGFyZ2V0IHR5cGUgKGkuZS4gZWl0aGVyICJnbyIgb3IgIm5vLWdvIiksIHByZXNlbnRlZCBpbiBMT05HIEZPUk1BVDogKioiYWxsX2RhdGFfY3VlX2xvbmciKiogKihjbGljayB0byBzZWUgbW9yZSkqIDwvc3VtbWFyeT4gIAoKLSBUaGlzIGRhdGEgaW5jbHVkZWQgdGhlIGZvbGxvd2luZzogICAKICAtIGByIGNvbG5hbWVzKGFsbF9kYXRhX2N1ZV9sb25nKWAgIAoKPGRldGFpbHM+CjxzdW1tYXJ5PiBUaGlzIGNvZGUgb3JnYW5pemVkIHRoZSByYXcgZGF0YSBpbnRvIG9uZSBkYXRhIGZyYW1lLiAqKGNsaWNrIHRvIGV4cGFuZCkqIDwvc3VtbWFyeT4KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBSZS1zdHJ1Y3R1cmUgdGhlIGRhdGEgaW50byAxIGRhdGEgZnJhbWUgaW4gYSBsb25nIGZvcm1hdCBmb3IgYSByZXBlYXRlZCBtZWFzdXJlcyBhbmFseXNpcwoKICAjIHVzaW5nIHRoZSAiZmluYWwiIGRhdGEgZnJhbWVzIG9mIGFsbCB0aGUgZGF0YSwgbWFrZSAyIGRhdGEgZnJhbWVzLCBvbmUgZm9yIHRoZSAidmVydGljYWwiIChhbGxfZGF0YV92KSBhbmQgb25lIGZvciB0aGUgImhvcml6b250YWwiIChhbGxfZGF0YV9oKSB0YXJnZXRzCiAgICAjIGZvciB0aGUgInZlcnRpY2FsIiB0YXJnZXRzIC0tIGFsbF9kYXRhX3YKICAgIGFsbF9kYXRhX3YgPSBSZWR1Y2UoZnVuY3Rpb24oeCwgeSkgbWVyZ2UoeCwgeSwgYnk9InBhcnRpY2lwYW50IiksIGxpc3QodHJhY2tfZmluYWwsIG9zcGFuX2ZpbmFsLCBnbmdfdl9maW5hbCwgZHBseXI6OnNlbGVjdChzdXJ2ZXlfZmluYWwsIC1jKHN1cl9sb2NhdGlvbiwgc3VyX3Bvd2VyLCBzdXJfY29uZGl0aW9uKSkpKQogICAgICAjIHJlbmFtZSB0aGUgdHJhY2tpbmcgc2hlZXQgY29sdW1ucyBmb3IgdGhlIGxvY2F0aW9uLCBwb3dlciwgYW5kIGNvbmRpdGlvbiAKICAgICAgY29sbmFtZXMoYWxsX2RhdGFfdilbd2hpY2gobmFtZXMoYWxsX2RhdGFfdikgPT0gYygidHJhY2tfbG9jYXRpb24iLCAidHJhY2tfcG93ZXIiLCAidHJhY2tfY29uZGl0aW9uIikpXSA9IGMoImxvY2F0aW9uIiwgInBvd2VyIiwgImNvbmRpdGlvbiIpCiAgICAjIGZvciB0aGUgImhvcml6b250YWwiIHRhcmdldHMgLS0gYWxsX2RhdGFfaAogICAgYWxsX2RhdGFfaCA9IFJlZHVjZShmdW5jdGlvbih4LCB5KSBtZXJnZSh4LCB5LCBieT0icGFydGljaXBhbnQiKSwgbGlzdCh0cmFja19maW5hbCwgb3NwYW5fZmluYWwsIGduZ19oX2ZpbmFsLCBkcGx5cjo6c2VsZWN0KHN1cnZleV9maW5hbCwgLWMoc3VyX2xvY2F0aW9uLCBzdXJfcG93ZXIsIHN1cl9jb25kaXRpb24pKSkpCiAgICAgICMgcmVuYW1lIHRoZSB0cmFja2luZyBzaGVldCBjb2x1bW5zIGZvciB0aGUgbG9jYXRpb24sIHBvd2VyLCBhbmQgY29uZGl0aW9uIAogICAgICBjb2xuYW1lcyhhbGxfZGF0YV9oKVt3aGljaChuYW1lcyhhbGxfZGF0YV9oKSA9PSBjKCJ0cmFja19sb2NhdGlvbiIsICJ0cmFja19wb3dlciIsICJ0cmFja19jb25kaXRpb24iKSldID0gYygibG9jYXRpb24iLCAicG93ZXIiLCAiY29uZGl0aW9uIikKCiAgIyByZW5hbWUgdGFyZ2V0LXNwZWNpZmljIGNvbHVtbnMgZm9yIGJvdGggZGF0YSBmcmFtZXMgKHRvIGJpbmQpCiAgICAjIGZvciB0aGUgImdvIiB0cmlhbHMKICAgIG5hbWVzKGFsbF9kYXRhX3YpW25hbWVzKGFsbF9kYXRhX3YpID09ICJ0cmlhbF90b3RfdiJdID0gImduZ190cmlhbF90b3RfbG9uZyIgCiAgICBuYW1lcyhhbGxfZGF0YV92KVtuYW1lcyhhbGxfZGF0YV92KSA9PSAic2NvcmVfdiJdID0gImduZ19zY29yZV9sb25nIiAKICAgIG5hbWVzKGFsbF9kYXRhX3YpW25hbWVzKGFsbF9kYXRhX3YpID09ICJyZXNwX3RvdF92Il0gPSAiZ25nX3Jlc3BfdG90X2xvbmciIAogICAgbmFtZXMoYWxsX2RhdGFfdilbbmFtZXMoYWxsX2RhdGFfdikgPT0gIm5vX3Jlc3BfdG90X3YiXSA9ICJnbmdfbm9fcmVzcF90b3RfbG9uZyIgCiAgICBuYW1lcyhhbGxfZGF0YV92KVtuYW1lcyhhbGxfZGF0YV92KSA9PSAiZXJyX3RvdF92Il0gPSAiZ25nX2Vycl90b3RfbG9uZyIgCiAgICBuYW1lcyhhbGxfZGF0YV92KVtuYW1lcyhhbGxfZGF0YV92KSA9PSAiZXJyX2NvbV92Il0gPSAiZ25nX2Vycl9jb21fbG9uZyIgCiAgICBuYW1lcyhhbGxfZGF0YV92KVtuYW1lcyhhbGxfZGF0YV92KSA9PSAiZXJyX29taV92Il0gPSAiZ25nX2Vycl9vbWlfbG9uZyIgCiAgICBuYW1lcyhhbGxfZGF0YV92KVtuYW1lcyhhbGxfZGF0YV92KSA9PSAicnRfYXZfdiJdID0gImduZ19ydF9hdl9sb25nIiAKICAgIG5hbWVzKGFsbF9kYXRhX3YpW25hbWVzKGFsbF9kYXRhX3YpID09ICJleGNsdWRlX3YiXSA9ICJnbmdfZXhjbHVkZV9sb25nIgogICAgIyBmb3IgdGhlICJuby1nbyIgdHJpYWxzCiAgICBuYW1lcyhhbGxfZGF0YV9oKVtuYW1lcyhhbGxfZGF0YV9oKSA9PSAidHJpYWxfdG90X2giXSA9ICJnbmdfdHJpYWxfdG90X2xvbmciIAogICAgbmFtZXMoYWxsX2RhdGFfaClbbmFtZXMoYWxsX2RhdGFfaCkgPT0gInNjb3JlX2giXSA9ICJnbmdfc2NvcmVfbG9uZyIgCiAgICBuYW1lcyhhbGxfZGF0YV9oKVtuYW1lcyhhbGxfZGF0YV9oKSA9PSAicmVzcF90b3RfaCJdID0gImduZ19yZXNwX3RvdF9sb25nIiAKICAgIG5hbWVzKGFsbF9kYXRhX2gpW25hbWVzKGFsbF9kYXRhX2gpID09ICJub19yZXNwX3RvdF9oIl0gPSAiZ25nX25vX3Jlc3BfdG90X2xvbmciIAogICAgbmFtZXMoYWxsX2RhdGFfaClbbmFtZXMoYWxsX2RhdGFfaCkgPT0gImVycl90b3RfaCJdID0gImduZ19lcnJfdG90X2xvbmciIAogICAgbmFtZXMoYWxsX2RhdGFfaClbbmFtZXMoYWxsX2RhdGFfaCkgPT0gImVycl9jb21faCJdID0gImduZ19lcnJfY29tX2xvbmciIAogICAgbmFtZXMoYWxsX2RhdGFfaClbbmFtZXMoYWxsX2RhdGFfaCkgPT0gImVycl9vbWlfaCJdID0gImduZ19lcnJfb21pX2xvbmciIAogICAgbmFtZXMoYWxsX2RhdGFfaClbbmFtZXMoYWxsX2RhdGFfaCkgPT0gInJ0X2F2X2giXSA9ICJnbmdfcnRfYXZfbG9uZyIgCiAgICBuYW1lcyhhbGxfZGF0YV9oKVtuYW1lcyhhbGxfZGF0YV9oKSA9PSAiZXhjbHVkZV9oIl0gPSAiZ25nX2V4Y2x1ZGVfbG9uZyIKICAKICAjIENyZWF0ZSBhIGRhdGFmcmFtZSBkZXBpY3RpbmcgdGhlIHRhcmdldCB0eXBlOiBlaXRoZXIgImdvIiAoY29kZWQgYXMgMSkgb3IgIm5vLWdvIiAoY29kZWQgYXMgMikKICBjdWVfdHlwZSA9IGFzLmRhdGEuZnJhbWUoYyhyZXAoMSwgbGVuZ3RoKGFsbF9kYXRhX3YkcGFydGljaXBhbnQpKSwgcmVwKDIsIGxlbmd0aChhbGxfZGF0YV9oJHBhcnRpY2lwYW50KSkpKQogICAgY29sbmFtZXMoY3VlX3R5cGUpID0gYygiY3VlIikgIAoKICAjIEJpbmQgdGhlIGdvIGFuZCBuby1nbyBkYXRhZnJhbWVzIGludG8gMSAoaW4gbG9uZyBmb3JtYXQpCiAgZ25nX2N1ZV9iaW5kID0gZHBseXI6OmJpbmRfcm93cyhhbGxfZGF0YV92LCBhbGxfZGF0YV9oKQogIAogICMgYWRkIHRoZSB0YXJnZXQgdHlwZSBjb2x1bW4gZGVwaWN0aW5nIHRoZSB0YXJnZXQgdHlwZTogZWl0aGVyICJnbyIgKGNvZGVkIGFzIDEpIG9yICJuby1nbyIgKGNvZGVkIGFzIDIpCiAgYWxsX2RhdGFfY3VlX2xvbmcgPSBkcGx5cjo6YmluZF9jb2xzKGN1ZV90eXBlLCBnbmdfY3VlX2JpbmQpCiAgICAKYGBgCgo8L2RldGFpbHM+ICAKPC9kZXRhaWxzPiAgCiAgCiAgICAKIyMjIDQuIE9TcGFuIEFuYWx5c2lzCgo8ZGV0YWlscz4gIAoKPHN1bW1hcnk+IEFsbCB0aGUgZGF0YSByZWxhdGVkIHRvIHRoZSBPU3BhbiBBbmFseXNpcyBmcm9tIHRoZSBwcmVzZW50IHN0dWR5IGluIG9uZSBkYXRhIGZyYW1lOiAqKiJvc3Bhbl9hbmFseXNpcyIqKiAqKGNsaWNrIHRvIHNlZSBtb3JlKSogPC9zdW1tYXJ5PiAgCgotIFRoaXMgZGF0YSBpbmNsdWRlZCB0aGUgZm9sbG93aW5nOiAgIAogIC0gYHIgY29sbmFtZXMob3NwYW5fYW5hbHlzaXMpYCAgCgo8ZGV0YWlscz4gIAo8c3VtbWFyeT4gVGhpcyBjb2RlIG9yZ2FuaXplZCB0aGUgZmluYWwgZGF0YSBpbnRvIHRoZSBvc3Bhbi1yZWxhdGVkIGRhdGEgZnJhbWUuICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PiAgCiAgCmBgYHtyfQoKIyBtYWtlIGEgbmV3IGRhdGEgZnJhbWUgZm9yIHRoZSBvc3BhbiBhbmFseXNpcwpvc3Bhbl9hbmFseXNpcyA9IGRwbHlyOjpzZWxlY3QoYWxsX2RhdGEsIHBhcnRpY2lwYW50LCBhZ2UsIGdlbmRlciwgbGFuZywgcHJvZ3JhbSwgeWVhciwgbG9jYXRpb24sIHBvd2VyLCBiYWxhbmNlLCBvc3Bhbl9hYnNvbHV0ZV9zY29yZSwgb3NwYW5fbWF0aF9wZXJjZW50X2NvcnIsIG9zcGFuX21hdGhfY3JpdGVyaWFfODUpCgpgYGAKICAKPC9kZXRhaWxzPiAgCgo8L2RldGFpbHM+ICAKCiMjIyA1LiBHby9Oby1HbzogRXJyb3IgQW5hbHlzaXMgIAoKPGRldGFpbHM+ICAKCjxzdW1tYXJ5PiBBbGwgdGhlIGRhdGEgcmVsYXRlZCB0byB0aGUgR28vTm8tR28gRXJyb3IgQW5hbHlzaXMgZnJvbSB0aGUgcHJlc2VudCBzdHVkeSBpbiBvbmUgZGF0YSBmcmFtZTogKioiZ25nX2Vycl9hbmFseXNpcyIqKiAKCk5vdGU6IHRoaXMgZGF0YSBpcyBpbiBhIGxvbmcgZm9ybWF0IGZvciBhIHJlcGVhdGVkIG1lYXN1cmVzIGFuYWx5c2lzIChpLmUuIGJhc2VkIG9uIHRhcmdldCB0eXBlOiBlaXRoZXIgImdvIiBvciAibm8tZ28iKS4gKihjbGljayB0byBzZWUgbW9yZSkqIDwvc3VtbWFyeT4gIAoKLSBUaGlzIGRhdGEgaW5jbHVkZWQgdGhlIGZvbGxvd2luZzogICAKICAtIGByIGNvbG5hbWVzKGduZ19lcnJfYW5hbHlzaXMpYCAgCgo8ZGV0YWlscz4gIAo8c3VtbWFyeT4gVGhpcyBjb2RlIG9yZ2FuaXplZCB0aGUgZmluYWwgbG9uZyBkYXRhIGludG8gYSBkYXRhIGZyYW1lIGZvciB0aGUgR28vTm8tR28gRXJyb3IgQW5hbHlzaXMuICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PiAgCiAgCmBgYHtyfQojIG1ha2UgYSBuZXcgZGF0YSBmcmFtZSBmb3IgdGhlIGduZyBlcnJvciBhbmFseXNpcwpnbmdfZXJyX2FuYWx5c2lzID0gZHBseXI6OnNlbGVjdChhbGxfZGF0YV9jdWVfbG9uZywgcGFydGljaXBhbnQsIGFnZV9sb25nLCBnZW5kZXIsIGxhbmdfbG9uZywgcHJvZ3JhbSwgeWVhciwgbG9jYXRpb24sIHBvd2VyLCBiYWxhbmNlLCBjdWUsIGduZ19leGNsdWRlX2xvbmcsIGduZ190cmlhbF90b3RfbG9uZywgZ25nX3Jlc3BfdG90X2xvbmcsIGduZ19ub19yZXNwX3RvdF9sb25nLCBnbmdfZXJyX3RvdF9sb25nLCBnbmdfZXJyX2NvbV9sb25nLCBnbmdfZXJyX29taV9sb25nKQoKYGBgCiAgCjwvZGV0YWlscz4gIAoKPC9kZXRhaWxzPiAgCgojIyMgNi4gR28vTm8tR286IEFjY3VyYWN5IEFuYWx5c2lzICAKCjxkZXRhaWxzPiAgCgo8c3VtbWFyeT4gQWxsIHRoZSBkYXRhIHJlbGF0ZWQgdG8gdGhlIEdvL05vLUdvIEFjY3VyYWN5IEFuYWx5c2lzIGZyb20gdGhlIHByZXNlbnQgc3R1ZHkgaW4gb25lIGRhdGEgZnJhbWU6ICoqImduZ19hY19hbmFseXNpcyIqKiAqKGNsaWNrIHRvIHNlZSBtb3JlKSogPC9zdW1tYXJ5PiAgCgotIFRoaXMgZGF0YSBpbmNsdWRlZCB0aGUgZm9sbG93aW5nOiAgIAogIC0gYHIgY29sbmFtZXMoZ25nX2FjX2FuYWx5c2lzKWAgIAoKPGRldGFpbHM+ICAKPHN1bW1hcnk+IFRoaXMgY29kZSBvcmdhbml6ZWQgdGhlIGZpbmFsIGRhdGEgaW50byBhIGRhdGEgZnJhbWUgcmVsYXRlZCB0byB0aGUgR28vTm8tR28gQWNjdXJhY3kgQW5hbHlzaXMuICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PiAgCiAgCmBgYHtyfQoKIyBtYWtlIGEgbmV3IGRhdGEgZnJhbWUgZm9yIHRoZSBnbmcgYWNjdXJhY3kgYW5hbHlzaXMKZ25nX2FjX2FuYWx5c2lzID0gZHBseXI6OnNlbGVjdChhbGxfZGF0YSwgcGFydGljaXBhbnQsIGFnZSwgZ2VuZGVyLCBsYW5nLCBwcm9ncmFtLCB5ZWFyLCBsb2NhdGlvbiwgcG93ZXIsIGJhbGFuY2UsIGduZ190cmlhbF90b3QsIGduZ19yZXNwX3RvdCwgZ25nX25vX3Jlc3BfdG90LCBnbmdfcnRfYXYpIAoKYGBgCiAgCjwvZGV0YWlscz4gIAoKPC9kZXRhaWxzPiAgCiAgCiMjIyA3LiBTQUQ6IEZhY3RvciBBbmFseXNpcyAgCgo8ZGV0YWlscz4gIAoKPHN1bW1hcnk+IEFsbCB0aGUgZGF0YSByZWxhdGVkIHRvIHRoZSBGYWN0b3IgQW5hbHlzaXMgZnJvbSB0aGUgcHJlc2VudCBzdHVkeSBpbiBvbmUgZGF0YSBmcmFtZTogKioiZmFjdG9yX2FuYWx5c2lzIioqICooY2xpY2sgdG8gc2VlIG1vcmUpKiA8L3N1bW1hcnk+ICAKCi0gVGhpcyBkYXRhIGluY2x1ZGVkIHRoZSBmb2xsb3dpbmc6ICAgCiAgLSBgciBjb2xuYW1lcyhmYWN0b3JfYW5hbHlzaXMpYCAgCgo8ZGV0YWlscz4gIAo8c3VtbWFyeT4gVGhpcyBjb2RlIG9yZ2FuaXplZCB0aGUgZmluYWwgZGF0YSBpbnRvIHRoZSBmYWN0b3IgYW5hbHlzaXMtcmVsYXRlZCBkYXRhIGZyYW1lLiAqKGNsaWNrIHRvIGV4cGFuZCkqIDwvc3VtbWFyeT4gIAogIApgYGB7cn0KCiMgbWFrZSBhIG5ldyBkYXRhIGZyYW1lIGZvciB0aGUgZmFjdG9yIGFuYWx5c2lzCmZhY3Rvcl9hbmFseXNpcyA9IGRwbHlyOjpzZWxlY3QoYWxsX2RhdGEsIHBhcnRpY2lwYW50LCBhZ2UsIGdlbmRlciwgbGFuZywgcHJvZ3JhbSwgeWVhciwgbG9jYXRpb24sIHBvd2VyLCBiYWxhbmNlLCBTQURfMTpTQURfMTMpCgpgYGAKICAKPC9kZXRhaWxzPiAgCgo8L2RldGFpbHM+ICAKICAKIyMjIDguIFNBRDogR2VuZXJhbGl6ZWQgTGluZWFyIE1vZGVsICAKCjxkZXRhaWxzPiAgCgo8c3VtbWFyeT4gQWxsIHRoZSBkYXRhIHJlbGF0ZWQgdG8gdGhlIEdMTSBBbmFseXNpcyBmcm9tIHRoZSBwcmVzZW50IHN0dWR5IGluIG9uZSBkYXRhIGZyYW1lOiAqKiJnbG1fYW5hbHlzaXMiKiogKihjbGljayB0byBzZWUgbW9yZSkqIDwvc3VtbWFyeT4gIAoKLSBUaGlzIGRhdGEgaW5jbHVkZWQgdGhlIGZvbGxvd2luZzogICAKICAtIGByIGNvbG5hbWVzKGdsbV9hbmFseXNpcylgICAKCjxkZXRhaWxzPiAgCjxzdW1tYXJ5PiBUaGlzIGNvZGUgb3JnYW5pemVkIHRoZSBmaW5hbCBkYXRhIGludG8gdGhlIEdMTS1yZWxhdGVkIGRhdGEgZnJhbWUuICooY2xpY2sgdG8gZXhwYW5kKSogPC9zdW1tYXJ5PiAgCiAgCmBgYHtyfQoKIyBtYWtlIGEgbmV3IGRhdGEgZnJhbWUgZm9yIHRoZSBnbG0gYW5hbHlzaXMKZ2xtX2FuYWx5c2lzID0gZHBseXI6OnNlbGVjdChhbGxfZGF0YSwgcGFydGljaXBhbnQsIGFnZSwgZ2VuZGVyLCBsYW5nLCBwcm9ncmFtLCB5ZWFyLCBsb2NhdGlvbiwgcG93ZXIsIGJhbGFuY2UsIFNBRF8xOlNBRF8xMykKCmBgYAogIAo8L2RldGFpbHM+ICAKCjwvZGV0YWlscz4gIAoKIyBEZXNjcmlwdGl2ZXM6IFNtYXJ0cGhvbmUgVXNlCgpgYGB7cn0KYWxsX2RhdGFfZGVzID0gZHBseXI6OnNlbGVjdChhbGxfZGF0YSwgcGFydGljaXBhbnQsIHRyYWNrX2RhdGUsIHRyYWNrX3RpbWUsIGFnZSwgZ2VuZGVyLCBsYW5nLCBwcm9ncmFtLCB5ZWFyKQoKIyBzdW1tYXJ5IG9mIGFnZQpzdW1tYXJ5KGFsbF9kYXRhX2RlcyRhZ2UpCiMgZnJlcXVlbmN5IG9mIGFnZQpwbHlyOjpjb3VudChhbGxfZGF0YV9kZXMkYWdlKQoKIyBzaG93IGZyZXF1ZW5jeSBmb3IgZ2VuZGVyCiAgIyBkZWZpbmUgZ2VuZGVyIGFzIGZhY3RvcgogIGFsbF9kYXRhX2RlcyRnZW5kZXIgPSBmYWN0b3IoYWxsX2RhdGFfZGVzJGdlbmRlciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKDEsIDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk1hbGUiLCAiRmVtYWxlIikpCiAgIyBzaG93IGNvdW50cwogIHBseXI6OmNvdW50KGFsbF9kYXRhX2RlcyRnZW5kZXIpCgojIHNob3cgZnJlcSBvZiB5ZWFyIG9mIHN0dWR5CnBseXI6OmNvdW50KGFsbF9kYXRhX2RlcyR5ZWFyKQoKIyBzaG93IGZyZXEgb2YgcHJvZ3JhbQogICMgZmlyc3QgZGVmaW5lIHRoZSBwcm9ncmFtIGFzIGEgZmFjdG9yCiAgICBhbGxfZGF0YV9kZXMkcHJvZ3JhbSA9IGZhY3RvcihhbGxfZGF0YV9kZXMkcHJvZ3JhbSwgCiAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoMywgNCwgMTMsIDE0LCAyOCwgMzIsIDM3LCAxMiwgMTcsIDE5LCAxNSwgMjAsIDI0LCAyMywgMjYsIDEsIDIsIDUsIDcsIDgsIDExLCAxNiwgMTgsIDIyLCAyNywgMjksIDMzLCAzNiwgNiwgOSwgMTAsIDIxLCAyNSwgMzAsIDMxLCAzNCwgMzUpLAogICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKHJlcCgiQXJ0cyAmIEh1bWFuaXRpZXMiLCA3KSwgIkVuZ2luZWVyaW5nIiwgcmVwKCJIZWFsdGggU2NpZW5jZXMiLCAyKSwgcmVwKCJJbmZvcm1hdGlvbiAmIE1lZGlhIFN0dWRpZXMiLCAzKSwgIk1lZGljaW5lICYgRGVudGlzdHJ5IiwgIk11c2ljIiwgcmVwKCJTY2llbmNlIiwgMTMpLCByZXAoIlNvY2lhbCBTY2llbmNlIiwgOSkpKQogICMgdGhlbiBzaG93IGNvdW50cwogIHBseXI6OmNvdW50KGFsbF9kYXRhX2RlcyRwcm9ncmFtKQoKCmBgYAoKCiMgUGxhbm5lZCBBbmFseXNpcwoKVGhlIGZvbGxvd2luZyBhbmFseXNlcyB3ZXJlIGNvbXBsZXRlZCBiYXNlZCBvbiBhIHByZS1yZWdpc3RlcmVkIGRpcmVjdCByZXBsaWNhdGlvbiBvbiBPU0YgKHZpZXcgcmVnaXN0cmF0aW9uOiA8aHR0cHM6Ly9vc2YuaW8vNWZxNHI+KSBvZiBXYXJkIGV0IGFsLidzICgyMDE3KSBzZWNvbmQgZXhwZXJpbWVudC4gVGhlIGFuYWx5c2VzIHRlc3RlZCB0aGUgdGhyZWUgbWFpbiBoeXBvdGhlc2VzIGluIHRoZSBwcmVzZW50IHN0dWR5OiAoMSkgdGhlIGxvY2F0aW9uIGVmZmVjdCBoeXBvdGhlc2lzLCAoMikgdGhlIHBvd2VyIGVmZmVjdCBoeXBvdGhlc2lzLCBhbmQgKDMpIHRoZSBtb2RlcmF0aW9uIGVmZmVjdCBoeXBvdGhlc2lzLiAgCgpFYWNoIGFuYWx5c2lzIGNvbnRhaW5zIHRoZSBmb2xsb3dpbmc6ICAKCjEuIERlc2NyaXB0aXZlIFN0YXRpc3RpY3MKMi4gQW5hbHlzaXMgKihpbmNsdWRpbmcgYW55IHJlbGV2YW50IGFzc3VtcHRpb24gdGVzdHMpKgozLiBWaXN1YWxpemF0aW9ucwoKIyMgVGVzdGluZyB0aGUgTG9jYXRpb24gYW5kIFBvd2VyIEh5cG90aGVzZXM6ICAKCiMjIyBPU3BhbiBUYXNrICAKCkEgKiozKHNtYXJ0cGhvbmUgbG9jYXRpb246IGRlc2ssIHBvY2tldC9iYWcsIG91dHNpZGUpIHggMihzbWFydHBob25lIHBvd2VyOiBPTiwgT0ZGKSoqIGJldHdlZW4tc3ViamVjdHMgQU5PVkEgd2FzIGNvbmR1Y3RlZCAqKERWID0gT1NwYW4gYWJzb2x1dGUgc2NvcmUpKi4gICAKClByaW9yIHRvIGNvbXBsZXRpbmcgdGhlIGFuYWx5c2lzLCBwbGFubmVkIGV4Y2x1c2lvbiBjcml0ZXJhIHdhcyBhcHBsaWVkIHRvIHRoZSBkYXRhLiBFeGNsdXNpb24gY3JpdGVyaWEgZm9yIHRoaXMgYW5hbHlzaXMgaGVscGVkIHRvIGNvbnRyb2wgZm9yIGFueSBwYXJ0aWNpcGFudHMgd2hvIGRpZCBub3QgZm9sbG93IHRoZSBpbnN0cnVjdGlvbnMsIHNwZWNpZmljYWxseSwgdGhhdCBwYXJ0aWNpcGFudCBwYXllZCBhdHRlbnRpb24gdG8gYm90aCB0aGUgbWF0aCBjb21wb25lbnQgYW5kIGxldHRlciByZWNhbGwgY29tcG9uZW50IG9mIHRoZSB0YXNrLiBPbmx5IGRhdGEgZnJvbSB0aG9zZSB3aG8gc2NvcmVkIDg1JSBvciBoaWdoZXIgb24gdGhlIG1hdGggY29tcG9uZW50IG9mIHRoZSB0YXNrIHdlcmUgaW5jbHVkZWQuICAKCi0gRXhjbHVkZSBkYXRhIGZyb20gYW55IHBhcnRpdGlwYW50cyB3aXRoICgxKSBtaXNzaW5nIGRhdGEgYW5kL29yICgyKSB0aGUgbWF0aCBjcml0ZXJpYSAoaS5lLiBtaW5pbXVtIDg1JSBvbiBtYXRoIGFjY3VyYWN5KS4gVGhlcmUgd2FzIGEgdG90YWwgb2YgKipgciBsZW5ndGgob3NwYW5fYW5hbHlzaXNfZmluYWwkcGFydGljaXBhbnQpYCoqIHBhcnRpY2lwYW50cyBpbiB0aGUgT1NwYW4gYW5hbHlzaXMuIAogIC0gTWlzc2luZyBEYXRhOiBgciBsZW5ndGgod2hpY2goaXMubmEob3NwYW5fYW5hbHlzaXMkb3NwYW5fYWJzb2x1dGVfc2NvcmUpID09IFRSVUUpKWAgcGFydGljaXBhbnRzIHdlcmUgcmVtb3ZlZCBkdWUgdG8gbWlzc2luZyBvc3BhbiBkYXRhLgogIC0gTWF0aCBDcml0ZXJpYSAobWluLiA4NSUpOiBgciBsZW5ndGgod2hpY2gob3NwYW5fYW5hbHlzaXMkb3NwYW5fbWF0aF9jcml0ZXJpYV84NSA9PSAwKSlgIHBhcnRpY2lwYW50cyB3ZXJlIHJlbW92ZWQgYmVjYXVzZSB0aGV5IGRpZCBub3QgbWVldCB0aGUgbWF0aCBjcml0ZXJpYS4KCmBgYHtyfQojIGZpbHRlciBhbnkgcGFydGljaXBhbnRzIHdpdGggbWlzc2luZyBPU3BhbiBkYXRhIGZvciB0aGUgYW5hbHlzaXMgIAogICAgIyBmb3IgYWxsIHBzLCBleGNsdWRpbmcgYW55IHAgd2l0aCBtaXNzaW5nIGRhdGEgaW4gdGhlIE9TcGFuIEFic29sdXRlIFNjb3JlIE9OTFkKICAgIG9zcGFuX2FuYWx5c2lzX25vTkEgPSBvc3Bhbl9hbmFseXNpc1shaXMubmEob3NwYW5fYW5hbHlzaXMkb3NwYW5fYWJzb2x1dGVfc2NvcmUpLCBdIAogICAgIyBmb3IgYWxsIHBzLCBleGNsdWRpbmcgYW55IHRoYXQgZG8gbm90IG1lZXQgdGhlIG1hdGggY3JpdGVyaWEgKG1pbiA4NSUgYWNjdXJhY3kpCiAgICBvc3Bhbl9hbmFseXNpc19maW5hbCA9IG9zcGFuX2FuYWx5c2lzX25vTkFbb3NwYW5fYW5hbHlzaXNfbm9OQVssIm9zcGFuX21hdGhfY3JpdGVyaWFfODUiXSA9PSAxLF0KYGBgCgojIyMjIERlc2NyaXB0aXZlIFN0YXRpc3RpY3MgCgpUaGUgZm9sbG93aW5nIHRhYmxlIGRlcGljdHMgdGhlIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3MgZm9yIHRoZSBPU3BhbiBhbmFseXNpczogdGhlIG1lYW4gKCpNKiksIHN0YW5kYXJkIGRldmlhdGlvbiAoKlNEKiksIG1pbmltdW0gc2NvcmUgKCptaW4uKiksIG1heGltdW0gc2NvcmUgKCptYXguKiksIGFuZCB0aGUgc2FtcGxlIHNpemUgKCpuKikuICAKCmBgYHtyfQoKIyBjcmVhdGUgYSBkYXRhIGZyYW1lIHdpdGggdGhlIGRlc2NyaXB0aXZlcyBvZiBhbGwgdGhlIGRhdGEsIGdyb3VwZWQgYnkgdGhlIGxvY2F0aW9uICYgcG93ZXIgY29uZGl0aW9ucwogICMgdGhpcyBjcmVhdGVzIGluZm9ybWF0aW9uIGZvciB0aGUgNiBwb3NzaWJsZSBjb21iaW5lZCBjb25kaXRpb25zCiAgb3NwYW5fZGVzID0gcHN5Y2g6OmRlc2NyaWJlQnkob3NwYW5fYW5hbHlzaXNfZmluYWwsIGxpc3Qob3NwYW5fYW5hbHlzaXNfZmluYWwkbG9jYXRpb24sIG9zcGFuX2FuYWx5c2lzX2ZpbmFsJHBvd2VyKSwgbWF0ID0gVFJVRSkgIAogIAojIG9yZ2FuaXplIHRoZSBkYXRhIGludG8gYSBuZXcgZGF0YSBmcmFtZSBkZXBpY3RpbmcgdGhlIE0sIFNELCBtaW4uLCBtYXguLCBhbmQgbi4KICBvc3Bhbl9kZXNfdCA9IHJiaW5kKChjYmluZCh0KG9zcGFuX2Rlc1sib3NwYW5fYWJzb2x1dGVfc2NvcmUxIixjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChvc3Bhbl9kZXNbIm9zcGFuX2Fic29sdXRlX3Njb3JlMiIsYygibWVhbiIsICJzZCIsICJtaW4iLCAibWF4IiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQob3NwYW5fZGVzWyJvc3Bhbl9hYnNvbHV0ZV9zY29yZTMiLGMoIm1lYW4iLCAic2QiLCAibWluIiwgIm1heCIsICJuIildKSkpLCAKICAgICAgICAgICAgICAgICAgICAgIChjYmluZCh0KG9zcGFuX2Rlc1sib3NwYW5fYWJzb2x1dGVfc2NvcmU0IixjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChvc3Bhbl9kZXNbIm9zcGFuX2Fic29sdXRlX3Njb3JlNSIsYygibWVhbiIsICJzZCIsICJtaW4iLCAibWF4IiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQob3NwYW5fZGVzWyJvc3Bhbl9hYnNvbHV0ZV9zY29yZTYiLGMoIm1lYW4iLCAic2QiLCAibWluIiwgIm1heCIsICJuIildKSkpKQogICAgY29sbmFtZXMob3NwYW5fZGVzX3QpID0gYygiT24gRGVzayIsICJJbiBQb2NrZXQvQmFnIiwgIk91dHNpZGUiKQogICAgcm93bmFtZXMob3NwYW5fZGVzX3QpID0gcmVwKGMoIk0iLCAiU0QiLCAibWluLiIsICJtYXguIiwgIm4iKSwgMikKICAgIAojIHVzZSBrYWJsZSB0byBzaG93IHRoZSBkZXNjcmlwdGl2ZXMgdGFibGUKICBrYWJsZShvc3Bhbl9kZXNfdCwgY2FwdGlvbiA9ICJEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzOiBBYnNvbHV0ZSBTY29yZSBvbiB0aGUgT1NwYW4gVGFzayIsIGRpZ2l0cyA9IDQsIGFsaWduID0gJ2MnKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCAiaG92ZXIiLCBmdWxsX3dpZHRoID0gRikgJT4lCiAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiwgIlNtYXJ0cGhvbmUgTG9jYXRpb24iID0gMykpICU+JQogIGdyb3VwX3Jvd3MoaW5kZXggPSBjKCJTbWFydHBob25lIFBvd2VyIE9OIiA9IDUsICJTbWFydHBob25lIFBvd2VyIE9GRiIgPSA1KSkKCmBgYAoKIyMjIyBBbmFseXNpcyAKClRvIGFzc2VzcyBpZiBPU3BhbiBhYnNvbHV0ZSBzY29yZSBzdGF0aXN0aWNhbGx5IGRpZmZlcmVkLCB3ZSBjb25kdWN0ZWQgYSAzeDIgQU5PVkEgd2l0aCB0aGUgYmV0d2Vlbi1zdWJqZWN0cyBmYWN0b3JzIG9mIHNtYXJ0cGhvbmUgbG9jYXRpb24gKGkuZS4gb24gZGVzaywgaW4gcG9ja2V0L2JhZywgb3Igb3V0c2lkZSkgYW5kIHBvd2VyIChpLmUuIG9uIG9yIG9mZikuIFNpbmNlIHRoZXJlIGFyZSB1bmVxdWFsIHNhbXBsZSBzaXplcywgd2UgdXNlZCBUeXBlIElJSSBzdW0gb2Ygc3F1YXJlcy4KCiMjIyMjIEFzc3VtcHRpb25zICAKCjxkZXRhaWxzPiAgCjxzdW1tYXJ5PiBUaGUgQU5PVkEgbWFkZSB0aHJlZSBhc3N1bXB0aW9ucy4gQWxsIGFzc3VtcHRpb25zIHdlcmUgbWV0ICooY2xpY2sgdG8gc2VlIGRldGFpbHMpKi4gPC9zdW1tYXJ5PiAgCgo8c3BhbiBzdHlsZT0iY29sb3I6RGFya0JsdWU7IGZvbnQtc2l6ZToxOHB4OyI+MS4gSW5kZXBlbmRlbnQgUmFuZG9tIFNhbXBsaW5nPC9zcGFuPiAgCgpUaGlzIGFzc3VtcHRpb24gd2FzIG1ldCBkdXJpbmcgdGVzdGluZy4gIAogICAgCjxzcGFuIHN0eWxlPSJjb2xvcjpEYXJrQmx1ZTsgZm9udC1zaXplOjE4cHg7Ij4yLiBOb3JtYWxpdHk8L3NwYW4+ICAKClRoaXMgYXNzdW1wdGlvbiB3YXMgdGVzdGVkIGJ5IHZpc3VhbGl6aW5nIHRoZSByZXNpZHVhbHMsIGFwcGx5aW5nIGEgU2hhcGlyby1XaWxrIHRlc3QgdG8gdGhlIHJlc2RpdWFscywgYW5kIG9ic2VydmluZyB0aGUgU2tld25lc3MgYW5kIEt1cnRvc2lzIG9mIHRoZSBkYXRhICooZXh0cmFjdGVkIGZyb20gdGhlIEFOT1ZBIG91dHB1dCkuKiAgCiAgICAKYGBge3IgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBnZXQgdGhlIHJlcXVpcmVkIGRhdGEgZnJvbSB0aGUgb3NwYW5fYW5hbHlzaXMgZGF0YTogcGFydGljaXBhbnQsIGxvY2F0aW9uLCBwb3dlciwgYW5kIHNjb3JlCm9zcGFuX2Fub3ZhX2RhdGEgPSBvc3Bhbl9hbmFseXNpc19maW5hbFssIGMoInBhcnRpY2lwYW50IiwgImxvY2F0aW9uIiwgInBvd2VyIiwgImJhbGFuY2UiLCAib3NwYW5fYWJzb2x1dGVfc2NvcmUiKV0KICAgIGNvbG5hbWVzKG9zcGFuX2Fub3ZhX2RhdGEpID0gYygicGFydGljaXBhbnQiLCAibG9jYXRpb24iLCAicG93ZXIiLCAiYmFsYW5jZSIsICJzY29yZSIpCiAgICByb3duYW1lcyhvc3Bhbl9hbm92YV9kYXRhKSA9IE5VTEwKICAgICMgcmVmb3JtYXQgbG9jYXRpb24sICBwb3dlciwgYW5kIGJhbGFuY2UgYXMgZmFjdG9ycyAgCiAgICBvc3Bhbl9hbm92YV9kYXRhJGxvY2F0aW9uID0gZmFjdG9yKG9zcGFuX2Fub3ZhX2RhdGEkbG9jYXRpb24sIAogICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKDEsIDIsIDMpLAogICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJPbiBEZXNrIiwgIlBvY2tldC9CYWciLCAiT3V0c2lkZSIpKQogICAgb3NwYW5fYW5vdmFfZGF0YSRwb3dlciA9IGZhY3Rvcihvc3Bhbl9hbm92YV9kYXRhJHBvd2VyLCAKICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygxLCAyKSwKICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiT04iLCAiT0ZGIikpCiAgICBvc3Bhbl9hbm92YV9kYXRhJGJhbGFuY2UgPSBmYWN0b3Iob3NwYW5fYW5vdmFfZGF0YSRiYWxhbmNlLCAKICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygxLCAyKSwKICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiT3NwYW4gRmlyc3QiLCAiR28vTm8tR28gRmlyc3QiKSkKCiMgcnVuIGJldHdlZW4tc3ViamVjdHMgQU5PVkEgKElWOiBTbWFydHBob25lIFBvd2VyICYgTG9jYXRpb24sIEJhbGFuY2U7IERWOiBPU3BhbiBBYm9sdXRlIFNjb3JlKQpvc3Bhbl9hbm92YSA9IGV6QU5PVkEoCiAgZGF0YSA9IG9zcGFuX2Fub3ZhX2RhdGEKICAsIGR2ID0gLihzY29yZSkKICAsIHdpZCA9IC4ocGFydGljaXBhbnQpCiAgLCBiZXR3ZWVuID0gLihsb2NhdGlvbiwgcG93ZXIsIGJhbGFuY2UpCiAgLCB0eXBlID0gMyAjIHVuZXF1YWwgc2FtcGxlIHNpemVzLCB0aGVyZm9yZSB1c2UgdHlwZSAzCiAgLCBkZXRhaWxlZCA9IFRSVUUKICAsIHJldHVybl9hb3YgPSBUUlVFCikKCiMgY2FsY3VsYXRlICYgZXh0cmFjdCB0aGUgcmVzaWR1YWxzIGZyb20gdGhlIEFOT1ZBCm9zcGFuX3JlcyA9IGRhdGEuZnJhbWUoInJlc2lkdWFscyIgPSBwcm9qKG9zcGFuX2Fub3ZhJGFvdilbLCJSZXNpZHVhbHMiXSkgICAKCmBgYAogICAgCi0gSXQgYXBwZWFycyB0aGF0IHRoZSByZXNpZHVhbHMgbGllIGNsb3NlbHkgdG8gYSBzdHJhaWdodCBsaW5lLCB3aGljaCBzdWdnZXN0cyBub3JtYWxpdHkgKihzZWUgdmlzdWFsaXphdGlvbiBiZWxvdykqLgogICAgCmBgYHtyfQoKcXFub3JtKG9zcGFuX3JlcyRyZXNpZHVhbHMsIG1haW4gPSAiUS1RIFBsb3Qgb2YgdGhlIE9TcGFuIFJlc2lkdWFscyIpIApxcWxpbmUob3NwYW5fcmVzJHJlc2lkdWFscykKCmBgYAogICAgCi0gSXQgYXBwZWFycyB0aGF0IHJlc2lkdWFscyB0ZW5kIHRvIGZvbGxvdyB0aGUgc2hhcGUgb2YgYSBub3JtYWwgZGlzdHJpYnV0aW9uLCB3aXRoIGEgc2xpZ2h0IHNrZXcgdG8gdGhlIHJpZ2h0ICooc2VlIHZpc3VhbGl6YXRpb24gYmVsb3cpKi4KICAgIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKcXBsb3Qob3NwYW5fcmVzJHJlc2lkdWFscywgbWFpbiA9ICJIaXN0b2dyYW0gb2YgT3NwYW4gUmVzaWR1YWxzIikgKyAKICB0aGVtZV9jbGFzc2ljKCkKCmBgYAogICAKLSBUaGUgU2hhcGlyby1XaWxrIHRlc3Qgb2Ygbm9ybWFsaXR5IHdhcyBzaWduaWZpY2FudCAoYmFzZWQgb24gJFxhbHBoYSA9IDAuMDUkKSwgKlcqID0gYHIgcm91bmQoYXMubnVtZXJpYyhvc3Bhbl9zaGFwJHN0YXRpc3RpY1siVyJdKSwgMilgLCAqcCogYHIgcF9yb3VuZChvc3Bhbl9zaGFwJHAudmFsdWUpYCAqKHNlZSBjb2RlIGJlbG93KSouICAKICAgCmBgYHtyfQoKb3NwYW5fc2hhcCA9IHNoYXBpcm8udGVzdChvc3Bhbl9yZXMkcmVzaWR1YWxzKQpvc3Bhbl9zaGFwCgpgYGAKCi0gVGhlIGRhdGEncyBTa2V3bmVzcyBhbmQgS3VydG9zaXMgd2FzIGV4YW1pbmVkIGFuZCBzaG93ZWQgdGhhdCBib3RoIHRoZSBTa2V3bmVzcyAocmFuZ2U6IGByIHJvdW5kKG1pbihhcy5udW1lcmljKG9zcGFuX3NrX3RbYygxLDQpLF0pKSwgMilgIHRvIGByIHJvdW5kKG1heChhcy5udW1lcmljKG9zcGFuX3NrX3RbYygxLDQpLF0pKSwgMilgKSBhbmQgS3VydG9zaXMgKHJhbmdlOiBgciByb3VuZChtaW4oYXMubnVtZXJpYyhvc3Bhbl9za190W2MoMiw1KSxdKSksIDIpYCB0byBgciByb3VuZChtYXgoYXMubnVtZXJpYyhvc3Bhbl9za190W2MoMiw1KSxdKSksIDIpYCkgd2VyZSB3aXRoaW4gdGhlIGFjY2VwdGFibGUgcmFuZ2Ugb2YgJFxwbSAyLjAkIGFuZCAkXHBtIDkuMCQsIHJlc3BlY3RpdmVseSAoU2NobWlkZXIsIFppZWdsZXIsIERhbmF5LCBCZXllciwgJiBCw7xobmVyLCAyMDEwKSAqKHNlZSB0YWJsZSBiZWxvdykqLiAgCgpgYGB7cn0KIyB1c2UgdGhlICJvc3Bhbl9kZXMiIGRhdGEgZnJhbWUgZnJvbSB0aGUgZGVzY3JpcHRpdmVzCgojIG9yZ2FuaXplIHRoZSBkYXRhIGludG8gYSBuZXcgZGF0YSBmcmFtZSBkZXBpY3RpbmcgdGhlIFNrZXcsIGt1cnRvc2lzLCBhbmQgc2FtcGxlIHNpemUgKG4pLgogIG9zcGFuX3NrX3QgPSByYmluZCgoY2JpbmQodChvc3Bhbl9kZXNbIm9zcGFuX2Fic29sdXRlX3Njb3JlMSIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChvc3Bhbl9kZXNbIm9zcGFuX2Fic29sdXRlX3Njb3JlMiIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChvc3Bhbl9kZXNbIm9zcGFuX2Fic29sdXRlX3Njb3JlMyIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSkpKSwgCiAgICAgICAgICAgICAgICAgICAgICAoY2JpbmQodChvc3Bhbl9kZXNbIm9zcGFuX2Fic29sdXRlX3Njb3JlNCIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChvc3Bhbl9kZXNbIm9zcGFuX2Fic29sdXRlX3Njb3JlNSIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChvc3Bhbl9kZXNbIm9zcGFuX2Fic29sdXRlX3Njb3JlNiIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSkpKSkKICAgIGNvbG5hbWVzKG9zcGFuX3NrX3QpID0gYygiT24gRGVzayIsICJJbiBQb2NrZXQvQmFnIiwgIk91dHNpZGUiKQogICAgcm93bmFtZXMob3NwYW5fc2tfdCkgPSByZXAoYygiU2tld25lc3MiLCAiS3VydG9zaXMiLCAibiIpLCAyKQogICAgCiMgdXNlIGthYmxlIHRvIHNob3cgdGhlIGRlc2NyaXB0aXZlcyB0YWJsZQogIGthYmxlKG9zcGFuX3NrX3QsIGNhcHRpb24gPSAiU2tld25lc3MgYW5kIEt1cnRvc2lzIG9mIHRoZSBBYnNvbHV0ZSBTY29yZSBvbiB0aGUgT1NwYW4gVGFzayIsIGRpZ2l0cyA9IDQsIGFsaWduID0gJ2MnKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCAiaG92ZXIiLCBmdWxsX3dpZHRoID0gRikgJT4lCiAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiwgIlNtYXJ0cGhvbmUgTG9jYXRpb24iID0gMykpICU+JQogIGdyb3VwX3Jvd3MoaW5kZXggPSBjKCJTbWFydHBob25lIFBvd2VyIE9OIiA9IDMsICJTbWFydHBob25lIFBvd2VyIE9GRiIgPSAzKSkKCmBgYAoKLSBUaGVyZWZvcmUsIGJhc2VkIG9uIGFsbCB0aGUgbm9ybWFsaXR5IGFzc3VtcHRpb24gY2hlY2tzLCBub3JtYWxpdHkgd2FzIGFzc3VtZWQgdG8gYmUgd2l0aGluIHRoZSBhY2NlcHRhYmxlIHJhbmdlIGZvciB0aGUgQU5PVkEgYW5hbHlzaXMuIEFkZGl0aW9uYWxseSwgaXQgc2hvdWxkIGJlIG5vdGVkIHRoYXQgQU5PVkEgYW5hbHlzZXMgY2FuIGJlIHJvYnVzdCB0byB2aW9sYXRpb25zIG9mIG5vcm1hbGl0eSAoR2FyZG5lciAmIFRyZW1ibGF5LCAyMDA3KS4KCjxzcGFuIHN0eWxlPSJjb2xvcjpEYXJrQmx1ZTsgZm9udC1zaXplOjE4cHg7Ij4zLiBIb21vZ2VuZWl0eSBvZiBWYXJpYW5jZTwvc3Bhbj4gCgpUaGlzIGFzc3VtcHRpb24gd2FzIHRlc3RlZCBieSBjb25kdWN0aW5nIExldmVuZSdzIFRlc3QgZm9yIEhvbW9nZW5laXR5IG9mIFZhcmlhbmNlIGZvciBlYWNoIGJldHdlZW4tc3ViamVjdHMgdmFyaWFibGUgKGkuZS4gc21hcnRwaG9uZSBsb2NhdGlvbiBhbmQgc21hcnRwaG9uZSBwb3dlcikuICAKCi0gVGhlIGhvbW9nZW5laXR5IGFzc3VtcHRpb24gd2FzIG1ldCAoYmFzZWQgb24gJFxhbHBoYSA9IDAuMDUkKSBmb3Igc21hcnRwaG9uZSBsb2NhdGlvbiwgKkYqKGByIG9zcGFuX2xldl9sb2MkRGZbMV1gLCBgciBvc3Bhbl9sZXZfbG9jJERmWzJdYCkgPSBgciByb3VuZChvc3Bhbl9sZXZfbG9jWzJdWzEsMV0sIDIpYCwgKnAqID0gYHIgcF9yb3VuZChvc3Bhbl9sZXZfbG9jWzNdWzEsMV0pYCwgc21hcnRwaG9uZSBwb3dlciwgKkYqKGByIG9zcGFuX2xldl9wb3ckRGZbMV1gLCBgciBvc3Bhbl9sZXZfcG93JERmWzJdYCkgPSBgciByb3VuZChvc3Bhbl9sZXZfcG93WzJdWzEsMV0sIDIpYCwgKnAqIGByIHBfcm91bmQob3NwYW5fbGV2X3Bvd1szXVsxLDFdKWAsIGFuZCBiYWxhbmNlLCAqRiooYHIgb3NwYW5fbGV2X2JhbCREZlsxXWAsIGByIG9zcGFuX2xldl9iYWwkRGZbMl1gKSA9IGByIHJvdW5kKG9zcGFuX2xldl9iYWxbMl1bMSwxXSwgMilgLCAqcCogYHIgcF9yb3VuZChvc3Bhbl9sZXZfYmFsWzNdWzEsMV0pYCooc2VlIGNvZGUgYmVsb3cpKi4KCmBgYHtyfQoKIyBjb25kdWN0IGxldmVuZSdzCiAgIyBmb3IgbG9jYXRpb24KICBvc3Bhbl9sZXZfbG9jID0gbGV2ZW5lVGVzdChkYXRhID0gb3NwYW5fYW5vdmFfZGF0YSwgc2NvcmUgfiBhcy5mYWN0b3IobG9jYXRpb24pLCBjZW50ZXIgPSBtZWRpYW4pCiAgb3NwYW5fbGV2X2xvYwogICMgZm9yIHBvd2VyCiAgb3NwYW5fbGV2X3BvdyA9IGxldmVuZVRlc3QoZGF0YSA9IG9zcGFuX2Fub3ZhX2RhdGEsIHNjb3JlIH4gYXMuZmFjdG9yKHBvd2VyKSwgY2VudGVyID0gbWVkaWFuKQogIG9zcGFuX2xldl9wb3cKICAjIGZvciBiYWxhbmNlCiAgb3NwYW5fbGV2X2JhbCA9IGxldmVuZVRlc3QoZGF0YSA9IG9zcGFuX2Fub3ZhX2RhdGEsIHNjb3JlIH4gYXMuZmFjdG9yKGJhbGFuY2UpLCBjZW50ZXIgPSBtZWRpYW4pCiAgb3NwYW5fbGV2X2JhbAoKYGBgCjwvZGV0YWlscz4gIAoKIyMjIyMgUmVzdWx0cwoKQWxsIHJlc3VsdHMgd2VyZSBiYXNlZCBvbiAkXGFscGhhID0gMC4wNSQuIEJlbG93IGFyZSB0aGUgcmVwb3J0ZWQgc3RhdGlzdGljcyBmb3IgYm90aCBtYWluIGVmZmVjdHMgYW5kIHRoZSBpbnRlcmFjdGlvbnMsIGZvbGxvd2VkIGJ5IGEgdGFibGUgZGVwaWN0aW5nIHRoZSBBTk9WQSByZXN1bHRzLiAgCgoqKk1haW4gRWZmZWN0IG9mIFNtYXJ0cGhvbmUgTG9jYXRpb24qKiAgCgpUaGVyZSB3YXMgbm8gc2lnbmlmaWNhbnQgbWFpbiBlZmZlY3Qgb2Ygc21hcnRwaG9uZSBsb2NhdGlvbiBvbiBPc3BhbiBhYnNvbHV0ZSBzY29yZSwgKkYqKGByIG9zcGFuX2Fub3ZhJEFOT1ZBWzIsMl1gLCBgciBvc3Bhbl9hbm92YSRBTk9WQVsyLDNdYCkgPSBgciByb3VuZChvc3Bhbl9hbm92YSRBTk9WQVsyLDZdLCAyKWAsICpwKiBgciBwX3JvdW5kKG9zcGFuX2Fub3ZhJEFOT1ZBWzIsN10pYCwgJFxldGFeezJ9JCBgciBwX3JvdW5kKG9zcGFuX2Fub3ZhJEFOT1ZBWzIsOV0pYC4KCioqTWFpbiBFZmZlY3Qgb2YgU21hcnRwaG9uZSBQb3dlcioqICAKClRoZXJlIHdhcyBubyBzaWduaWZpY2FudCBtYWluIGVmZmVjdCBvZiBzbWFydHBob25lIHBvd2VyIG9uIE9zcGFuIGFic29sdXRlIHNjb3JlLCAqRiooYHIgb3NwYW5fYW5vdmEkQU5PVkFbMywyXWAsIGByIG9zcGFuX2Fub3ZhJEFOT1ZBWzMsM11gKSA9IGByIHJvdW5kKG9zcGFuX2Fub3ZhJEFOT1ZBWzMsNl0sIDIpYCwgKnAqIGByIHBfcm91bmQob3NwYW5fYW5vdmEkQU5PVkFbMyw3XSlgLCAkXGV0YV57Mn0kIGByIHBfcm91bmQob3NwYW5fYW5vdmEkQU5PVkFbMyw5XSlgLgoKKipJbnRlcmFjdGlvbiBvZiBCYWxhbmNlKiogIAoKVGhlcmUgd2FzIG5vIHNpZ25pZmljYW50IG1haW4gZWZmZWN0IG9mIGJhbGFuY2UgKGkuZS4gd2hpY2ggdGFzayB3YXMgY29tcGxldGVkIGZpcnN0KSBvbiBPc3BhbiBhYnNvbHV0ZSBzY29yZSwgKkYqKGByIG9zcGFuX2Fub3ZhJEFOT1ZBWzQsMl1gLCBgciBvc3Bhbl9hbm92YSRBTk9WQVs0LDNdYCkgPSBgciByb3VuZChvc3Bhbl9hbm92YSRBTk9WQVs0LDZdLCAyKWAsICpwKiBgciBwX3JvdW5kKG9zcGFuX2Fub3ZhJEFOT1ZBWzQsN10pYCwgJFxldGFeezJ9JCBgciBwX3JvdW5kKG9zcGFuX2Fub3ZhJEFOT1ZBWzQsOV0pYC4KCioqSW50ZXJhY3Rpb24gb2YgU21hcnRwaG9uZSBMb2NhdGlvbiAmIFNtYXJ0cGhvbmUgUG93ZXIqKiAgCgpUaGVyZSB3YXMgbm8gc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gYmV0d2VlbiBzbWFydHBob25lIGxvY2F0aW9uIGFuZCBzbWFydHBob25lIHBvd2VyIG9uIE9zcGFuIGFic29sdXRlIHNjb3JlLCAqRiooYHIgb3NwYW5fYW5vdmEkQU5PVkFbNSwyXWAsIGByIG9zcGFuX2Fub3ZhJEFOT1ZBWzUsM11gKSA9IGByIHJvdW5kKG9zcGFuX2Fub3ZhJEFOT1ZBWzUsNl0sIDIpYCwgKnAqIGByIHBfcm91bmQob3NwYW5fYW5vdmEkQU5PVkFbNSw3XSlgLCAkXGV0YV57Mn0kIGByIHBfcm91bmQob3NwYW5fYW5vdmEkQU5PVkFbNSw5XSlgLgoKKipJbnRlcmFjdGlvbiBvZiBTbWFydHBob25lIExvY2F0aW9uICYgQmFsYW5jZSoqICAKClRoZXJlIHdhcyBubyBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBiZXR3ZWVuIHNtYXJ0cGhvbmUgbG9jYXRpb24gYW5kIGJhbGFuY2UgKGkuZS4gd2hpY2ggdGFzayB3YXMgY29tcGxldGVkIGZpcnN0KSBvbiBPc3BhbiBhYnNvbHV0ZSBzY29yZSwgKkYqKGByIG9zcGFuX2Fub3ZhJEFOT1ZBWzYsMl1gLCBgciBvc3Bhbl9hbm92YSRBTk9WQVs2LDNdYCkgPSBgciByb3VuZChvc3Bhbl9hbm92YSRBTk9WQVs2LDZdLCAyKWAsICpwKiBgciBwX3JvdW5kKG9zcGFuX2Fub3ZhJEFOT1ZBWzYsN10pYCwgJFxldGFeezJ9JCBgciBwX3JvdW5kKG9zcGFuX2Fub3ZhJEFOT1ZBWzYsOV0pYC4KCioqSW50ZXJhY3Rpb24gb2YgU21hcnRwaG9uZSBQb3dlciAmIEJhbGFuY2UqKiAgCgpUaGVyZSB3YXMgbm8gc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gYmV0d2VlbiBzbWFydHBob25lIHBvd2VyIGFuZCBiYWxhbmNlIChpLmUuIHdoaWNoIHRhc2sgd2FzIGNvbXBsZXRlZCBmaXJzdCkgb24gT3NwYW4gYWJzb2x1dGUgc2NvcmUsICpGKihgciBvc3Bhbl9hbm92YSRBTk9WQVs3LDJdYCwgYHIgb3NwYW5fYW5vdmEkQU5PVkFbNywzXWApID0gYHIgcm91bmQob3NwYW5fYW5vdmEkQU5PVkFbNyw2XSwgMilgLCAqcCogYHIgcF9yb3VuZChvc3Bhbl9hbm92YSRBTk9WQVs3LDddKWAsICRcZXRhXnsyfSQgYHIgcF9yb3VuZChvc3Bhbl9hbm92YSRBTk9WQVs3LDldKWAuCgoqKkludGVyYWN0aW9uIG9mIFNtYXJ0cGhvbmUgTG9jYXRpb24sIFNtYXJ0cGhvbmUgUG93ZXIsICYgQmFsYW5jZSoqICAKClRoZXJlIHdhcyBubyBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBiZXR3ZWVuIHNtYXJ0cGhvbmUgbG9jYXRpb24sIHNtYXJ0cGhvbmUgcG93ZXIsIGFuZCBiYWxhbmNlIChpLmUuIHdoaWNoIHRhc2sgd2FzIGNvbXBsZXRlZCBmaXJzdCkgb24gT3NwYW4gYWJzb2x1dGUgc2NvcmUsICpGKihgciBvc3Bhbl9hbm92YSRBTk9WQVs4LDJdYCwgYHIgb3NwYW5fYW5vdmEkQU5PVkFbOCwzXWApID0gYHIgcm91bmQob3NwYW5fYW5vdmEkQU5PVkFbOCw2XSwgMilgLCAqcCogYHIgcF9yb3VuZChvc3Bhbl9hbm92YSRBTk9WQVs4LDddKWAsICRcZXRhXnsyfSQgYHIgcF9yb3VuZChvc3Bhbl9hbm92YSRBTk9WQVs4LDldKWAuCgoqKlBvc3QtaG9jIFRlc3RzKiogIAoKU2luY2UgdGhlcmUgd2FzIG5vIHNpZ25pZmljYW50IG1haW4gb3IgaW50ZXJhY3Rpb24gZWZmZWN0cywgbm8gcG9zdC1ob2NzIHdlcmUgY29tcGxldGVkLgoKYGBge3J9CiMgc2hvdyBBTk9WQSByZXN1bHRzIGluIGthYmxlIHRhYmxlIAprYWJsZShvc3Bhbl9hbm92YSRBTk9WQSwgY2FwdGlvbiA9ICIzeDIgQU5PVkEgb24gT3NwYW4gQWJzb2x1dGUgU2NvcmUiLCBkaWdpdHMgPSA0LCBhbGlnbiA9ICdjJykgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpIAoKYGBgCgoKIyMjIyBWaXN1YWxpemF0aW9ucwoKVGhlIGZvbGxvd2luZyBzaG93cyBhIHZpc3VsaXphdGlvbiBvZiB0aGUgT3NwYW4gYWJzb2x1dGUgc2NvcmUgYmFzZWQgb24gdGhlIHR3byBzbWFydHBob25lIGNvbmRpdGlvbnM6IGxvY2F0aW9uIGFuZCBwb3dlci4gKk5vdGU6IFNpbmNlIHRoZSBiYWxhbmNlIGZhY3RvciAoaS5lLiB3aGljaCB0YXNrIHdhcyBjb21wbGV0ZWQgZmlyc3QpIGRpZCBub3QgaGF2ZSBhIHNpZ25pZmljYW50IG1haW4gZWZmZWN0IG9yIGludGVyYWN0aW9uIGVmZmVjdCBvbiB0aGUgZGF0YSwgdGhpcyBmYWN0b3Igd2FzIG5vdCB2aXN1YWxpemVkIGluIHRoZSBwbG90cyoKCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGNyZWF0ZSBkYXRhIGZyYW1lIHdpdGggbG9jYXRpb24gY29uZGl0aW9ucyBhcyBjaGFyYWN0ZXJzIHJhdGhlciB0aGFuIGludGVyZ2VycyAKICAjIEZpcnN0LCBnZXQgYSBzdWJzZXQgb2YgdGhlIGRlc2NyaXB0aXZlIGRhdGEKICBvc3Bhbl9iYXIgPSBvc3Bhbl9hbmFseXNpc19maW5hbFssIGMoImxvY2F0aW9uIiwgInBvd2VyIiwgIm9zcGFuX2Fic29sdXRlX3Njb3JlIildCiAgICBjb2xuYW1lcyhvc3Bhbl9iYXIpID0gYygibG9jYXRpb24iLCAicG93ZXIiLCAic2NvcmUiKQogICAgcm93bmFtZXMob3NwYW5fYmFyKSA9IE5VTEwgCiAgICAKICBvc3Bhbl9iYXIkbG9jYXRpb24gPSBmYWN0b3Iob3NwYW5fYmFyJGxvY2F0aW9uLCAKICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygxLCAyLCAzKSwKICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiT24gRGVzayIsICJQb2NrZXQvQmFnIiwgIk91dHNpZGUiKSkKICBvc3Bhbl9iYXIkcG93ZXIgPSBmYWN0b3Iob3NwYW5fYmFyJHBvd2VyLCAKICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygxLCAyKSwKICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiT04iLCAiT0ZGIikpCgojbWFpbl9XTVdfcGxvdCA9IHByZWxpbV9ob25fRFRfZGF0YTEKI21haW5fV01XX3Bsb3RbLDJdID0gcmVjb2RlKG1haW5fV01XX3Bsb3QkQ29uZGl0aW9uLCAnMScgPSAiT24gRGVzayIsICczJyA9ICJPdXRzaWRlIikKCiAgICAgICAKIyBwbG90IGJhciBncmFwaCAtIEdPT0QKZ2dwbG90KG9zcGFuX2JhciwgYWVzKHggPSBsb2NhdGlvbiwgeSA9IHNjb3JlLCBmaWxsID0gcG93ZXIpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgZnVuLnkgPSAibWVhbiIsIHBvc2l0aW9uID0gImRvZGdlIikgKyAKICAgIGd1aWRlcyhzaGFwZSA9IEZBTFNFKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImNhZGV0Ymx1ZTMiLCAiZGVlcHNreWJsdWU0IikpICsgCiAgbGFicyh0aXRsZSA9ICJQZXJmb3JtYW5jZSBvbiB0aGUgT1NwYW4gVGFzayIsCiAgICAgICBzdWJ0aXRsZSA9ICJBdmVyYWdlIEFic29sdXRlIE9TcGFuIFNjb3JlIiwKICAgICAgIHggPSAiU21hcnRwaG9uZSBMb2NhdGlvbiIsIAogICAgICAgeSA9ICJTY29yZSIsIAogICAgICAgZmlsbCA9ICJTbWFydHBob25lIFBvd2VyIiwKICAgICAgIGNhcHRpb24gPSAiTm90ZTogU2NvcmUgaXMgdGhlIG51bWJlciBvZiBjb3JyZWN0IGxldHRlcnMgcmVjYWxsZWQgYmFzZWQgXG4gb24gaWYgYWxsIGxldHRlcnMgaW4gYSBnaXZlbiBibG9jayB3ZXJlIHJlY2FsbGVkIGNvcnJlY3RseS4iKSArCiAgICAgICAgIyB0aGUgIlxuIiBoZXJlIGRlbm90ZSB0aGF0IHlvdSB3YW50IGEgbmV3IGxpbmUgZm9ybWVkIGluIHRoZSB0ZXh0CiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMobWluKG9zcGFuX2JhciRzY29yZSksIG1heChvc3Bhbl9iYXIkc2NvcmUpKSwgYnJlYWtzID0gKSArCiAgI3NjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gY29scykgKwogIGdlb21fcG9pbnQoc3RhdCA9ICJpZGVudGl0eSIsIGFlcyhjb2xvciA9IHBvd2VyKSwgc2l6ZSA9IDEsIAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAuNTMpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImRlZXBza3libHVlNCIsICJwdXJwbGU0IikpICsgCiAgZ2VvbV9wb2ludChzdGF0PSJzdW1tYXJ5IiwgZnVuLnk9Im1lYW4iLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKC45KSwgc2l6ZSA9IDEuNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGdlb21fZXJyb3JiYXIoZGF0YSA9IG9zcGFuX2Jhciwgc3RhdCA9ICJzdW1tYXJ5IiwgZnVuLnltaW4gPSBmdW5jdGlvbih4KSBtZWFuKHgpIC0gc2QoeCkvc3FydChsZW5ndGgoeCkpLCAKICAgICAgICAgICAgICAgIGZ1bi55bWF4ID0gZnVuY3Rpb24oeCkgbWVhbih4KSArIHNkKHgpL3NxcnQobGVuZ3RoKHgpKSwgc2l6ZT0gLjUsIHdpZHRoPSAuMjUsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoLjkpKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxMyksIAogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAsIHNpemUgPSAxMiwgZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMykpCgpgYGAKCiMjIyBDdWUtRGVwZW5kZW50IEdvL05vLUdvIFRhc2sgIAoKQW4gZXJyb3IgKGkuZS4gb21pc3Npb24gZXJyb3JzKSBhbmQgYWNjdXJhY3kgKGkuZS4gUlQpIGFuYWx5c2lzIHdhcyBjb21wbGV0ZWQgdXNpbmcgdGhlIG9taXNzaW9uIGVycm9ycyBhbmQgYXZlcmFnZSBSVCBmb3IgZWFjaCBwYXJ0aWNpcGFudC4gIAoKIyMjIyBFcnJvciBBbmFseXNpcyAgCgpBICoqMyhTbWFydHBob25lIGxvY2F0aW9uOiBkZXNrLCBwb2NrZXQvYmFnLCBvdXRzaWRlKSB4IDIoU21hcnRwaG9uZSBwb3dlcjogT04sIE9GRikgeCAyKEN1ZSB0eXBlOiBWZXJ0aWNhbCwgSG9yaXpvbnRhbCkqKiBtaXhlZCBBTk9WQSB3YXMgY29tcGxldGVkICooRFYgPSBvbWlzc2lvbiBlcnJvcihzKSkqLiBUaGUgYmV0d2Vlbi1zdWJqZWN0cyBmYWN0b3JzIHdlcmUgc21hcnRwaG9uZSBsb2NhdGlvbiBhbmQgcG93ZXIsIGFuZCB0aGUgd2l0aGluLXN1YmplY3RzIGZhY3RvciB3YXMgcHJlLXRhcmdldCBjdWUgdHlwZSAoaS5lLiAiY3VlIHR5cGUiOyBlaXRoZXIgInZlcnRpY2FsIiBvciAiaG9yaXpvbnRhbCIpLiAgCgpQcmlvciB0byBjb21wbGV0aW5nIHRoZSBhbmFseXNpcywgcGxhbm5lZCBleGNsdXNpb24gY3JpdGVyYSB3YXMgYXBwbGllZCB0byB0aGUgZGF0YS4gRXhjbHVzaW9uIGNyaXRlcmlhIGZvciB0aGlzIGFuYWx5c2lzIGhlbHBlZCB0byBjb250cm9sIGZvciBhbnkgcGFydGljaXBhbnRzIHdobyBkaWQgbm90IGZvbGxvdyB0aGUgaW5zdHJ1Y3Rpb25zLiBPbmx5IGRhdGEgZnJvbSB0aG9zZSB3aG8gc2NvcmVkIGhpZ2hlciB0aGFuIGNoYW5jZSBwZXJmb3JtYW5jZSAoaS5lLiByZXNwb25kZWQgdG8gYXQgbGVhc3QgNTAlIG9mIOKAnEdv4oCdIHRyaWFscyBhbmQgd2l0aGhlbGQgcmVzcG9uc2UgdG8gYXQgbGVhc3QgNTAlIG9mIOKAnE5vLUdv4oCdIHRyaWFscykgd2VyZSB1c2VkIGZvciB0aGUgZmluYWwgYW5hbHlzaXMuICAKCi0gRXhjbHVkZSBkYXRhIGZyb20gYW55IHBhcnRpdGlwYW50cyB3aXRoICgxKSBtaXNzaW5nIGRhdGEgYW5kL29yICgyKSB0aGUgcmVzcG9uc2UgY3JpdGVyaWEsIHdoZXJlIHBhcnRpY2lwYW50cyBzY29yZWQgaGlnaGVyIHRoYW4gY2hhbmNlIHBlcmZvcm1hbmNlIChpLmUuIHJlc3BvbmRlZCB0byBhdCBsZWFzdCA1MCUgb2Yg4oCcR2/igJ0gdHJpYWxzIGFuZCB3aXRoaGVsZCByZXNwb25zZSB0byBhdCBsZWFzdCA1MCUgb2Yg4oCcTm8tR2/igJ0gdHJpYWxzKS4gVGhlcmUgd2FzIGEgdG90YWwgb2YgKipgciBsZW5ndGgoZ25nX2Vycl9maW5hbCRwYXJ0aWNpcGFudFtnbmdfZXJyX2ZpbmFsJGN1ZSA9PSAxXSlgKiogcGFydGljaXBhbnRzIGluIHRoZSBHby9Oby1HbyBFcnJvciBhbmFseXNpcy4gCiAgLSBNaXNzaW5nIERhdGE6IGByIGFicyhsZW5ndGgoZ25nX2Vycl9ub05BJHBhcnRpY2lwYW50W2duZ19lcnJfbm9OQSRjdWUgPT0gMV0pIC0gbGVuZ3RoKGduZ19lcnJfYW5hbHlzaXMkcGFydGljaXBhbnRbZ25nX2Vycl9hbmFseXNpcyRjdWUgPT0gMV0pKWAgcGFydGljaXBhbnRzIHdlcmUgcmVtb3ZlZCBkdWUgdG8gbWlzc2luZyBkYXRhLgogIC0gUmVzcG9uc2UgQ3JpdGVyaWE6IGByIGFicyhsZW5ndGgoZ25nX2Vycl9ub05BJHBhcnRpY2lwYW50W2duZ19lcnJfbm9OQSRjdWUgPT0gMV0pIC0gbGVuZ3RoKGduZ19lcnJfZmluYWwkcGFydGljaXBhbnRbZ25nX2Vycl9maW5hbCRjdWUgPT0gMV0pKWAgcGFydGljaXBhbnRzIHdlcmUgcmVtb3ZlZCBiZWNhdXNlIHRoZXkgZGlkIG5vdCBtZWV0IHRoZSByZXNwb25zZSBjcml0ZXJpYS4KCmBgYHtyfQojIGZpbHRlciBhbnkgcGFydGljaXBhbnRzIHdpdGggbWlzc2luZyBkYXRhIG9yIHRoYXQgZG8gbm90IG1lZXQgdGhlIGluY2x1c2lvbm4gY3JpdGVyaWEKCiAgIyBmb3IgYWxsIHBzLCBleGNsdWRpbmcgYW55IHAgd2l0aCBtaXNzaW5nIGRhdGEgaW4gdGhlIE9taXNzaW9uIEVycm9yIAogIGduZ19lcnJfbm9OQSA9IGduZ19lcnJfYW5hbHlzaXNbIWlzLm5hKGduZ19lcnJfYW5hbHlzaXMkZ25nX2Vycl9vbWlfbG9uZyksXQogIAogICMgZm9yIGFsbCBwcywgZXhjbHVkaW5nIGFueSB0aGF0IHNjb3JlZCBiZWxvdyBjaGFuY2UgcGVyZm9ybWFuY2UgKGkuZS4gcmVzcG9uZGQgdG8gYXQgbGVhc3QgNTAlIG9mIHRoZSAiZ28iIHRyaWFscyBhbmQgd2l0aGhlbGQgcmVzcG9uc2UgdG8gYXQgbGVhc3QgNTAlIG9mIHRoZSAibm8tZ28iIHRyaWFscykgdXNpbmcgdGhlICJleGNsdWRlIiBjb2x1bW4KICBnbmdfZXJyX2ZpbmFsID0gZ25nX2Vycl9ub05BW2duZ19lcnJfbm9OQSRnbmdfZXhjbHVkZV9sb25nID09IDIsXQoKYGBgCgojIyMjIyBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzIAoKVGhlIGZvbGxvd2luZyB0YWJsZSBkZXBpY3RzIHRoZSBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGZvciB0aGUgR28vTm8tR28gRXJyb3IgQW5hbHlzaXM6IHRoZSBtZWFuICgqTSopLCBzdGFuZGFyZCBkZXZpYXRpb24gKCpTRCopLCBtaW5pbXVtIHNjb3JlICgqbWluLiopLCBtYXhpbXVtIHNjb3JlICgqbWF4LiopLCBhbmQgdGhlIHNhbXBsZSBzaXplICgqbiopLiAgCgpgYGB7cn0KCiMgY3JlYXRlIGEgZGF0YSBmcmFtZSB3aXRoIHRoZSBkZXNjcmlwdGl2ZXMgb2YgYWxsIHRoZSBkYXRhLCBncm91cGVkIGJ5IHRoZSBsb2NhdGlvbiAmIHBvd2VyIGNvbmRpdGlvbnMKICAjIHRoaXMgY3JlYXRlcyBpbmZvcm1hdGlvbiBmb3IgdGhlIDYgcG9zc2libGUgY29tYmluZWQgY29uZGl0aW9ucwogICMgZm9yIHRoZSAidmVydGljYWwiIHRyaWFscwogIGduZ19lcnJfZGVzX3YgPSBkZXNjcmliZUJ5KGduZ19lcnJfZmluYWxbZ25nX2Vycl9maW5hbCRjdWUgPT0gMSxdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdChnbmdfZXJyX2ZpbmFsW2duZ19lcnJfZmluYWwkY3VlID09IDEsXSRsb2NhdGlvbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ25nX2Vycl9maW5hbFtnbmdfZXJyX2ZpbmFsJGN1ZSA9PSAxLF0kcG93ZXIpLCBtYXQgPSBUUlVFKSAKICAjIGZvciB0aGUgImhvcml6b250YWwiIHRyaWFscwogIGduZ19lcnJfZGVzX2ggPSBkZXNjcmliZUJ5KGduZ19lcnJfZmluYWxbZ25nX2Vycl9maW5hbCRjdWUgPT0gMixdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdChnbmdfZXJyX2ZpbmFsW2duZ19lcnJfZmluYWwkY3VlID09IDIsXSRsb2NhdGlvbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ25nX2Vycl9maW5hbFtnbmdfZXJyX2ZpbmFsJGN1ZSA9PSAyLF0kcG93ZXIpLCBtYXQgPSBUUlVFKSAKICAKIyBvcmdhbml6ZSB0aGUgZGF0YSBpbnRvIGEgbmV3IGRhdGEgZnJhbWUgZGVwaWN0aW5nIHRoZSBNLCBTRCwgbWluLiwgbWF4LiwgYW5kIG4uCiAgIyBmb3IgdGhlICJ2ZXJ0aWNhbCIgdHJpYWxzCiAgZ25nX2Vycl9kZXNfdl90ID0gcmJpbmQoKGNiaW5kKHQoZ25nX2Vycl9kZXNfdlsiZ25nX2Vycl9vbWlfbG9uZzEiLGMoIm1lYW4iLCAic2QiLCAibWluIiwgIm1heCIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0KGduZ19lcnJfZGVzX3ZbImduZ19lcnJfb21pX2xvbmcyIixjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChnbmdfZXJyX2Rlc192WyJnbmdfZXJyX29taV9sb25nMyIsYygibWVhbiIsICJzZCIsICJtaW4iLCAibWF4IiwgIm4iKV0pKSksIAogICAgICAgICAgICAgICAgICAgICAgKGNiaW5kKHQoZ25nX2Vycl9kZXNfdlsiZ25nX2Vycl9vbWlfbG9uZzQiLGMoIm1lYW4iLCAic2QiLCAibWluIiwgIm1heCIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0KGduZ19lcnJfZGVzX3ZbImduZ19lcnJfb21pX2xvbmc1IixjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChnbmdfZXJyX2Rlc192WyJnbmdfZXJyX29taV9sb25nNiIsYygibWVhbiIsICJzZCIsICJtaW4iLCAibWF4IiwgIm4iKV0pKSkpCiAgICBjb2xuYW1lcyhnbmdfZXJyX2Rlc192X3QpID0gYygiT24gRGVzayIsICJJbiBQb2NrZXQvQmFnIiwgIk91dHNpZGUiKQogICAgcm93bmFtZXMoZ25nX2Vycl9kZXNfdl90KSA9IHJlcChjKCJNIiwgIlNEIiwgIm1pbi4iLCAibWF4LiIsICJuIiksIDIpCiAgIyBmb3IgdGhlICJob3Jpem9udGFsIiB0cmlhbHMKICBnbmdfZXJyX2Rlc19oX3QgPSByYmluZCgoY2JpbmQodChnbmdfZXJyX2Rlc19oWyJnbmdfZXJyX29taV9sb25nMSIsYygibWVhbiIsICJzZCIsICJtaW4iLCAibWF4IiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2Vycl9kZXNfaFsiZ25nX2Vycl9vbWlfbG9uZzIiLGMoIm1lYW4iLCAic2QiLCAibWluIiwgIm1heCIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0KGduZ19lcnJfZGVzX2hbImduZ19lcnJfb21pX2xvbmczIixjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSkpKSwgCiAgICAgICAgICAgICAgICAgICAgICAoY2JpbmQodChnbmdfZXJyX2Rlc19oWyJnbmdfZXJyX29taV9sb25nNCIsYygibWVhbiIsICJzZCIsICJtaW4iLCAibWF4IiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2Vycl9kZXNfaFsiZ25nX2Vycl9vbWlfbG9uZzUiLGMoIm1lYW4iLCAic2QiLCAibWluIiwgIm1heCIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0KGduZ19lcnJfZGVzX2hbImduZ19lcnJfb21pX2xvbmc2IixjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSkpKSkKICAgIGNvbG5hbWVzKGduZ19lcnJfZGVzX2hfdCkgPSBjKCJPbiBEZXNrIiwgIkluIFBvY2tldC9CYWciLCAiT3V0c2lkZSIpCiAgICByb3duYW1lcyhnbmdfZXJyX2Rlc19oX3QpID0gcmVwKGMoIk0iLCAiU0QiLCAibWluLiIsICJtYXguIiwgIm4iKSwgMikKICAgIAojIHVzZSBrYWJsZSB0byBzaG93IHRoZSBkZXNjcmlwdGl2ZXMgdGFibGUKICBnbmdfZXJyX3Zfa3QgPSAKICAgIGthYmxlKGduZ19lcnJfZGVzX3ZfdCwgY2FwdGlvbiA9ICJEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzOiBPbWlzc2lvbiBFcnJvcnMgb24gdGhlIEdvL05vLUdvIFRhc2sgZm9yICdWZXJ0aWNhbCcgVHJpYWxzIiwgZGlnaXRzID0gNCwgYWxpZ24gPSAnYycpICU+JQogICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpICU+JQogICAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiwgIlNtYXJ0cGhvbmUgTG9jYXRpb24iID0gMykpICU+JQogICAgZ3JvdXBfcm93cyhpbmRleCA9IGMoIlNtYXJ0cGhvbmUgUG93ZXIgT04iID0gNSwgIlNtYXJ0cGhvbmUgUG93ZXIgT0ZGIiA9IDUpKQogIAogIGduZ19lcnJfaF9rdCA9IAogICAga2FibGUoZ25nX2Vycl9kZXNfaF90LCBjYXB0aW9uID0gIkRlc2NyaXB0aXZlIFN0YXRpc3RpY3M6IE9taXNzaW9uIEVycm9ycyBvbiB0aGUgR28vTm8tR28gVGFzayBmb3IgJ0hvcml6b250YWwnIFRyaWFscyIsIGRpZ2l0cyA9IDQsIGFsaWduID0gJ2MnKSAlPiUKICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsICJob3ZlciIsIGZ1bGxfd2lkdGggPSBGKSAlPiUKICAgIGFkZF9oZWFkZXJfYWJvdmUoYygiICIsICJTbWFydHBob25lIExvY2F0aW9uIiA9IDMpKSAlPiUKICAgIGdyb3VwX3Jvd3MoaW5kZXggPSBjKCJTbWFydHBob25lIFBvd2VyIE9OIiA9IDUsICJTbWFydHBob25lIFBvd2VyIE9GRiIgPSA1KSkKICAKICBnbmdfZXJyX3Zfa3QKICBnbmdfZXJyX2hfa3QKCmBgYAoKIyMjIyMgQW5hbHlzaXMgCgpUbyBhc3Nlc3MgaWYgdGhlIG9taXNzaW9uIGVycm9ycyBzdGF0aXN0aWNhbGx5IGRpZmZlcmVkLCB3ZSBjb25kdWN0ZWQgYSAzeDJ4MiBtaXhlZCBBTk9WQSB3aXRoIHRoZSBiZXR3ZWVuLXN1YmplY3RzIGZhY3RvcnMgb2Ygc21hcnRwaG9uZSBsb2NhdGlvbiAoaS5lLiBvbiBkZXNrLCBpbiBwb2NrZXQvYmFnLCBvciBvdXRzaWRlKSBhbmQgcG93ZXIgKGkuZS4gb24gb3Igb2ZmKSwgYW5kIHRoZSB3aXRoaW4tc3ViamVjdHMgZmFjdG9yIG9mIGN1ZSB0eXBlIChpLmUuICJ2ZXJ0aWNhbCIgb3IgImhvcml6b250YWwiKS4gU2luY2UgdGhlcmUgYXJlIHVuZXF1YWwgc2FtcGxlIHNpemVzLCB3ZSB1c2VkIFR5cGUgSUlJIHN1bSBvZiBzcXVhcmVzLgoKIyMjIyMjIEFzc3VtcHRpb25zICAKCjxkZXRhaWxzPiAgCjxzdW1tYXJ5PiBUaGUgbWl4ZWQgQU5PVkEgbWFkZSBmb3VyIGFzc3VtcHRpb25zLiBUaGUgbm9ybWFsaXR5IGFzc3VtcHRpb24gd2FzIG5vdCBtZXQuIFRoZXJlZm9yZSwgYSByb2J1c3QgQU5PVkEgd2FzIGNvbXBsZXRlZCB0byBhc3Nlc3MgaWYgdGhlIG9taXNzaW9uIGVycm9ycyBzdGF0aXN0aWNhbGx5IGRpZmZlcmVkIGJldHdlZW4gdGhlIGZhY3RvcnMgKGkuZS4gc21hcnRwaG9uZSBsb2NhdGlvbiwgc21hcnRwaG9uZSBwb3dlciwgYW5kIGN1ZSB0eXBlKSAqKGNsaWNrIHRvIHNlZSBkZXRhaWxzKSouIDwvc3VtbWFyeT4gIAoKPHNwYW4gc3R5bGU9ImNvbG9yOkRhcmtCbHVlOyBmb250LXNpemU6MThweDsiPjEuIEluZGVwZW5kZW50IFJhbmRvbSBTYW1wbGluZzwvc3Bhbj4gIAoKVGhpcyBhc3N1bXB0aW9uIHdhcyBtZXQgZHVyaW5nIHRlc3RpbmcuIAogICAgCjxzcGFuIHN0eWxlPSJjb2xvcjpEYXJrQmx1ZTsgZm9udC1zaXplOjE4cHg7Ij4yLiBOb3JtYWxpdHk8L3NwYW4+ICAKClRoaXMgYXNzdW1wdGlvbiB3YXMgdGVzdGVkIGJ5IHZpc3VhbGl6aW5nIHRoZSByZXNpZHVhbHMsIGFwcGx5aW5nIGEgU2hhcGlyby1XaWxrIHRlc3QgdG8gdGhlIHJlc2RpdWFscywgYW5kIG9ic2VydmluZyB0aGUgU2tld25lc3MgYW5kIEt1cnRvc2lzIG9mIHRoZSBkYXRhICooZXh0cmFjdGVkIGZyb20gdGhlIEFOT1ZBIG91dHB1dCkuKiAgCgpgYGB7ciBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGdldCB0aGUgcmVxdWlyZWQgZGF0YSBmcm9tIHRoZSBnbmdfZXJyX2ZpbmFsIGRhdGE6IHBhcnRpY2lwYW50LCBsb2NhdGlvbiwgcG93ZXIsIGFuZCBzY29yZQpnbmdfZXJyX2Fub3ZhX2RhdGEgPSBnbmdfZXJyX2ZpbmFsWyxjKCJwYXJ0aWNpcGFudCIsICJsb2NhdGlvbiIsICJwb3dlciIsICJjdWUiLCAiYmFsYW5jZSIsICJnbmdfZXJyX29taV9sb25nIildCiAgICBjb2xuYW1lcyhnbmdfZXJyX2Fub3ZhX2RhdGEpID0gYygicGFydGljaXBhbnQiLCAibG9jYXRpb24iLCAicG93ZXIiLCAiY3VlIiwgImJhbGFuY2UiLCAiZXJyX29taSIpCiAgICByb3duYW1lcyhnbmdfZXJyX2Fub3ZhX2RhdGEpID0gTlVMTAogICAgZ25nX2Vycl9hbm92YV9kYXRhJGxvY2F0aW9uID0gYXMuZmFjdG9yKGduZ19lcnJfYW5vdmFfZGF0YSRsb2NhdGlvbikKICAgIGduZ19lcnJfYW5vdmFfZGF0YSRwb3dlciA9IGFzLmZhY3RvcihnbmdfZXJyX2Fub3ZhX2RhdGEkcG93ZXIpCiAgICBnbmdfZXJyX2Fub3ZhX2RhdGEkY3VlID0gYXMuZmFjdG9yKGduZ19lcnJfYW5vdmFfZGF0YSRjdWUpCiAgICBnbmdfZXJyX2Fub3ZhX2RhdGEkYmFsYW5jZSA9IGFzLmZhY3RvcihnbmdfZXJyX2Fub3ZhX2RhdGEkYmFsYW5jZSkKCiMgcnVuIG1peGVkIEFOT1ZBIChJViBiL3c6IFNtYXJ0cGhvbmUgUG93ZXIgJiBMb2NhdGlvbjsgSVYgdy9pbjogVGFyZ2V0IFR5cGU7IERWOiBPbWlzc2lvbiBFcnJvcnMpCmduZ19lcnJfYW5vdmEgPSBlekFOT1ZBKAogIGRhdGEgPSBnbmdfZXJyX2Fub3ZhX2RhdGEKICAsIGR2ID0gLihlcnJfb21pKQogICwgd2lkID0gLihwYXJ0aWNpcGFudCkKICAsIHdpdGhpbiA9IC4oY3VlKQogICwgYmV0d2VlbiA9IC4obG9jYXRpb24sIHBvd2VyLCBiYWxhbmNlKQogICwgdHlwZSA9IDMgIyB1bmVxdWFsIHNhbXBsZSBzaXplcywgdGhlcmVmb3JlIHVzZSB0eXBlIDMKICAsIGRldGFpbGVkID0gVFJVRQogICwgcmV0dXJuX2FvdiA9IFRSVUUKKQoKIyBjYWxjdWxhdGUgJiBleHRyYWN0IHRoZSByZXNpZHVhbHMgZnJvbSB0aGUgQU5PVkEKZ25nX2Vycl9yZXMgPSBkYXRhLmZyYW1lKCJyZXNpZHVhbHMiID0gcHJvaihnbmdfZXJyX2Fub3ZhJGFvdilbWzNdXVssICJSZXNpZHVhbHMiXSkKCmBgYAogICAgCi0gSXQgYXBwZWFycyB0aGF0IHRoZSByZXNpZHVhbHMgbGllIGNsb3NlbHkgdG8gYSBzdHJhaWdodCBsaW5lIChpLmUuIG9ubHkgYSBjb3VwbGUgbGllIGF3YXkgZm9ybSB0aGUgbGluZSksIHdoaWNoIHN1Z2dlc3RzIG5vcm1hbGl0eSAqKHNlZSB2aXN1YWxpemF0aW9uIGJlbG93KSouCiAgICAKYGBge3J9CgpxcW5vcm0oZ25nX2Vycl9yZXMkcmVzaWR1YWxzLCBtYWluID0gIlEtUSBQbG90IG9mIHRoZSBHby9Oby1HbyBFcnJvciBSZXNpZHVhbHMiKSAKcXFsaW5lKGduZ19lcnJfcmVzJHJlc2lkdWFscykKCmBgYAogICAgCi0gSXQgYXBwZWFycyB0aGF0IHJlc2lkdWFscyBhcmUgbGVwdG9rdXJ0aWMgKGkuZS4gdGhlcmUgaXMgYSBoaWdoIHBlYWsgbmVhciB0aGUgY2VudGVyKSAqKHNlZSB2aXN1YWxpemF0aW9uIGJlbG93KSouCiAgICAKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCnFwbG90KGduZ19lcnJfcmVzJHJlc2lkdWFscywgbWFpbiA9ICJIaXN0b2dyYW0gb2YgR28vTm8tR28gRXJyb3IgUmVzaWR1YWxzIiwgYmlud2lkdGggPSAuMTUpICsgCiAgdGhlbWVfY2xhc3NpYygpCgpgYGAKICAgCi0gVGhlIFNoYXBpcm8tV2lsayB0ZXN0IG9mIG5vcm1hbGl0eSB3YXMgc2lnbmlmaWNhbnQgKGJhc2VkIG9uICRcYWxwaGEgPSAwLjA1JCksICpXKiA9IGByIHJvdW5kKGFzLm51bWVyaWMoZ25nX2Vycl9zaGFwJHN0YXRpc3RpY1siVyJdKSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfZXJyX3NoYXAkcC52YWx1ZSlgICooc2VlIGNvZGUgYmVsb3cpKi4gCiAgIApgYGB7cn0KCmduZ19lcnJfc2hhcCA9IHNoYXBpcm8udGVzdChnbmdfZXJyX3JlcyRyZXNpZHVhbHMpCmduZ19lcnJfc2hhcAoKYGBgCgotIFRoZSBkYXRhJ3MgU2tld25lc3MgYW5kIEt1cnRvc2lzIHdhcyBleGFtaW5lZC4gRm9yIHRoZSB2ZXJ0aWNhbCBjdWUgdHlwZSwgYm90aCB0aGUgU2tld25lc3MgKHJhbmdlOiBgciByb3VuZChtaW4oYXMubnVtZXJpYyhnbmdfZXJyX3NrX3ZfdFtjKDEsNCksXSkpLCAyKWAgdG8gYHIgcm91bmQobWF4KGFzLm51bWVyaWMoZ25nX2Vycl9za192X3RbYygxLDQpLF0pKSwgMilgKSBhbmQgS3VydG9zaXMgKHJhbmdlOiBgciByb3VuZChtaW4oYXMubnVtZXJpYyhnbmdfZXJyX3NrX3ZfdFtjKDIsNSksXSkpLCAyKWAgdG8gYHIgcm91bmQobWF4KGFzLm51bWVyaWMoZ25nX2Vycl9za192X3RbYygyLDUpLF0pKSwgMilgKSB3ZXJlIG91dHNpZGUgb2YgdGhlIGFjY2VwdGFibGUgcmFuZ2Ugb2YgJFxwbSAyLjAkIGFuZCAkXHBtIDkuMCQsIHJlc3BlY3RpdmVseSAoU2NobWlkZXIsIFppZWdsZXIsIERhbmF5LCBCZXllciwgJiBCw7xobmVyLCAyMDEwKS4gRm9yIHRoZSBob3Jpem9udGFsIGN1ZSB0eXBlLCBib3RoIHRoZSBTa2V3bmVzcyAocmFuZ2U6IGByIHJvdW5kKG1pbihhcy5udW1lcmljKGduZ19lcnJfc2tfaF90W2MoMSw0KSxdKSksIDIpYCB0byBgciByb3VuZChtYXgoYXMubnVtZXJpYyhnbmdfZXJyX3NrX2hfdFtjKDEsNCksXSkpLCAyKWApIGFuZCBLdXJ0b3NpcyAocmFuZ2U6IGByIHJvdW5kKG1pbihhcy5udW1lcmljKGduZ19lcnJfc2tfaF90W2MoMiw1KSxdKSksIDIpYCB0byBgciByb3VuZChtYXgoYXMubnVtZXJpYyhnbmdfZXJyX3NrX2hfdFtjKDIsNSksXSkpLCAyKWApIHdlcmUgb3V0c2lkZSBvZiB0aGUgYWNjZXB0YWJsZSByYW5nZSBvZiAkXHBtIDIuMCQgYW5kICRccG0gOS4wJCwgcmVzcGVjdGl2ZWx5IChTY2htaWRlciwgWmllZ2xlciwgRGFuYXksIEJleWVyLCAmIELDvGhuZXIsIDIwMTApICooc2VlIHRhYmxlIGJlbG93KSouICAKCmBgYHtyfQojIGNyZWF0ZSAmIHNob3cgYSB0YWJsZSBvZiB0aGUgc2tld25lc3MgJiBrdXJ0b3NpcyBmb3IgdGhlIGduZyBkYXRhLCBzZXBhcmF0ZWQgYnkgY3VlIHR5cGUgKGkuZS4gb25lIGZvciB0aGUgdmVydGljYWwgYW5kIGhvcml6b250YWwgdHJpYWxzKQoKIy0tRk9SIFRIRSBWRVJUSUNBTCBDVUUgVFlQRQojIHVzZSB0aGUgImduZ19lcnJfZGVzX3YiIGRhdGEgZnJhbWUgZnJvbSB0aGUgZGVzY3JpcHRpdmVzCgojIG9yZ2FuaXplIHRoZSBkYXRhIGludG8gYSBuZXcgZGF0YSBmcmFtZSBkZXBpY3RpbmcgdGhlIFNrZXcsIGt1cnRvc2lzLCBhbmQgc2FtcGxlIHNpemUgKG4pLgogIGduZ19lcnJfc2tfdl90ID0gcmJpbmQoKGNiaW5kKHQoZ25nX2Vycl9kZXNfdlsiZ25nX2Vycl90b3RfbG9uZzEiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2Vycl9kZXNfdlsiZ25nX2Vycl90b3RfbG9uZzIiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2Vycl9kZXNfdlsiZ25nX2Vycl90b3RfbG9uZzMiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pKSksIAogICAgICAgICAgICAgICAgICAgICAgKGNiaW5kKHQoZ25nX2Vycl9kZXNfdlsiZ25nX2Vycl90b3RfbG9uZzQiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2Vycl9kZXNfdlsiZ25nX2Vycl90b3RfbG9uZzUiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2Vycl9kZXNfdlsiZ25nX2Vycl90b3RfbG9uZzYiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pKSkpCiAgICBjb2xuYW1lcyhnbmdfZXJyX3NrX3ZfdCkgPSBjKCJPbiBEZXNrIiwgIkluIFBvY2tldC9CYWciLCAiT3V0c2lkZSIpCiAgICByb3duYW1lcyhnbmdfZXJyX3NrX3ZfdCkgPSByZXAoYygiU2tld25lc3MiLCAiS3VydG9zaXMiLCAibiIpLCAyKQogICAgCiMgdXNlIGthYmxlIHRvIHNob3cgdGhlIGRlc2NyaXB0aXZlcyB0YWJsZQogIGduZ19lcnJfc2tfdiA9IGthYmxlKGduZ19lcnJfc2tfdl90LCBjYXB0aW9uID0gIlNrZXduZXNzIGFuZCBLdXJ0b3NpcyBvZiB0aGUgT21pc3Npb24gRXJyb3JzIG9uIHRoZSBHby9Oby1HbyBUYXNrIGZvciAnVmVydGljYWwnIFRyaWFscyIsIGRpZ2l0cyA9IDQsIGFsaWduID0gJ2MnKSAlPiUKICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsICJob3ZlciIsIGZ1bGxfd2lkdGggPSBGKSAlPiUKICAgIGFkZF9oZWFkZXJfYWJvdmUoYygiICIsICJTbWFydHBob25lIExvY2F0aW9uIiA9IDMpKSAlPiUKICAgIGdyb3VwX3Jvd3MoaW5kZXggPSBjKCJTbWFydHBob25lIFBvd2VyIE9OIiA9IDMsICJTbWFydHBob25lIFBvd2VyIE9GRiIgPSAzKSkKICAKIy0tRk9SIFRIRSBIT1JJWk9OVEFMIENVRSBUWVBFCiMgdXNlIHRoZSAiZ25nX2Vycl9kZXNfaCIgZGF0YSBmcmFtZSBmcm9tIHRoZSBkZXNjcmlwdGl2ZXMKCiMgb3JnYW5pemUgdGhlIGRhdGEgaW50byBhIG5ldyBkYXRhIGZyYW1lIGRlcGljdGluZyB0aGUgU2tldywga3VydG9zaXMsIGFuZCBzYW1wbGUgc2l6ZSAobikuCiAgZ25nX2Vycl9za19oX3QgPSByYmluZCgoY2JpbmQodChnbmdfZXJyX2Rlc19oWyJnbmdfZXJyX3RvdF9sb25nMSIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChnbmdfZXJyX2Rlc19oWyJnbmdfZXJyX3RvdF9sb25nMiIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChnbmdfZXJyX2Rlc19oWyJnbmdfZXJyX3RvdF9sb25nMyIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSkpKSwgCiAgICAgICAgICAgICAgICAgICAgICAoY2JpbmQodChnbmdfZXJyX2Rlc19oWyJnbmdfZXJyX3RvdF9sb25nNCIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChnbmdfZXJyX2Rlc19oWyJnbmdfZXJyX3RvdF9sb25nNSIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChnbmdfZXJyX2Rlc19oWyJnbmdfZXJyX3RvdF9sb25nNiIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSkpKSkKICAgIGNvbG5hbWVzKGduZ19lcnJfc2tfaF90KSA9IGMoIk9uIERlc2siLCAiSW4gUG9ja2V0L0JhZyIsICJPdXRzaWRlIikKICAgIHJvd25hbWVzKGduZ19lcnJfc2tfaF90KSA9IHJlcChjKCJTa2V3bmVzcyIsICJLdXJ0b3NpcyIsICJuIiksIDIpCiAgICAKIyB1c2Uga2FibGUgdG8gc2hvdyB0aGUgZGVzY3JpcHRpdmVzIHRhYmxlCiAgZ25nX2Vycl9za19oID0ga2FibGUoZ25nX2Vycl9za19oX3QsIGNhcHRpb24gPSAiU2tld25lc3MgYW5kIEt1cnRvc2lzIG9mIHRoZSBPbWlzc2lvbiBFcnJvcnMgb24gdGhlIEdvL05vLUdvIFRhc2sgZm9yICdIb3Jpem9uYXRhbCcgVHJpYWxzIiwgZGlnaXRzID0gNCwgYWxpZ24gPSAnYycpICU+JQogICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpICU+JQogICAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiwgIlNtYXJ0cGhvbmUgTG9jYXRpb24iID0gMykpICU+JQogICAgZ3JvdXBfcm93cyhpbmRleCA9IGMoIlNtYXJ0cGhvbmUgUG93ZXIgT04iID0gMywgIlNtYXJ0cGhvbmUgUG93ZXIgT0ZGIiA9IDMpKQogIAojIHNob3cgdGhlIHRhYmxlcwogICMgZm9yIHRoZSBWZXJ0aWNhbCBDdWUgVHlwZQogIGduZ19lcnJfc2tfdgogICMgZm9yIHRoZSBIb3Jpem9uYXRhbCBDdWUgVHlwZQogIGduZ19lcnJfc2tfaAoKYGBgCgotIFRoZXJlZm9yZSwgYmFzZWQgb24gYWxsIHRoZSBub3JtYWxpdHkgYXNzdW1wdGlvbiBjaGVja3MsIG5vcm1hbGl0eSB3YXMgbm90IGFzc3VtZWQgdG8gYmUgd2l0aGluIHRoZSBhY2NlcHRhYmxlIHJhbmdlIGZvciB0aGUgQU5PVkEgYW5hbHlzaXMuIAoKPHNwYW4gc3R5bGU9ImNvbG9yOkRhcmtCbHVlOyBmb250LXNpemU6MThweDsiPjMuIEhvbW9nZW5laXR5IG9mIFZhcmlhbmNlPC9zcGFuPiAgCgogIC0gVGhpcyBhc3N1bXB0aW9uIHdhcyB0ZXN0ZWQgYnkgY29uZHVjdGluZyBMZXZlbmUncyBUZXN0IGZvciBIb21vZ2VuZWl0eSBvZiBWYXJpYW5jZSBmb3IgZWFjaCBiZXR3ZWVuLXN1YmplY3RzIHZhcmlhYmxlIChpLmUuIHNtYXJ0cGhvbmUgbG9jYXRpb24sIHNtYXJ0cGhvbmUgcG93ZXIsIGFuZCBiYWxhbmNlKS4KCiAgLSBUaGUgaG9tb2dlbmVpdHkgYXNzdW1wdGlvbiB3YXMgbWV0IChiYXNlZCBvbiAkXGFscGhhID0gMC4wNSQpIGZvciBib3RoIHNtYXJ0cGhvbmUgbG9jYXRpb24sICpGKihgciBnbmdfZXJyX2xldl9sb2MkRGZbMV1gLCBgciBnbmdfZXJyX2xldl9sb2MkRGZbMl1gKSA9IGByIHJvdW5kKGduZ19lcnJfbGV2X2xvY1syXVsxLDFdLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19lcnJfbGV2X2xvY1szXVsxLDFdKWAsIHNtYXJ0cGhvbmUgcG93ZXIsICpGKihgciBnbmdfZXJyX2xldl9wb3ckRGZbMV1gLCBgciBnbmdfZXJyX2xldl9wb3ckRGZbMl1gKSA9IGByIHJvdW5kKGduZ19lcnJfbGV2X3Bvd1syXVsxLDFdLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19lcnJfbGV2X3Bvd1szXVsxLDFdKWAsIGFuZCBiYWxhbmNlLCAqRiooYHIgZ25nX2Vycl9sZXZfYmFsJERmWzFdYCwgYHIgZ25nX2Vycl9sZXZfYmFsJERmWzJdYCkgPSBgciByb3VuZChnbmdfZXJyX2xldl9iYWxbMl1bMSwxXSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfZXJyX2xldl9iYWxbM11bMSwxXSlgLiooc2VlIGNvZGUgYmVsb3cpKi4KCmBgYHtyfQoKIyBjb25kdWN0IGxldmVuZSdzCiAgIyBmb3IgbG9jYXRpb24KICBnbmdfZXJyX2xldl9sb2MgPSBsZXZlbmVUZXN0KGRhdGEgPSBnbmdfZXJyX2Fub3ZhX2RhdGEsIGVycl9vbWkgfiBhcy5mYWN0b3IobG9jYXRpb24pLCBjZW50ZXIgPSBtZWRpYW4pCiAgZ25nX2Vycl9sZXZfbG9jCiAgIyBmb3IgcG93ZXIKICBnbmdfZXJyX2xldl9wb3cgPSBsZXZlbmVUZXN0KGRhdGEgPSBnbmdfZXJyX2Fub3ZhX2RhdGEsIGVycl9vbWkgfiBhcy5mYWN0b3IocG93ZXIpLCBjZW50ZXIgPSBtZWRpYW4pCiAgZ25nX2Vycl9sZXZfcG93CiAgIyBmb3IgYmFsYW5jZQogIGduZ19lcnJfbGV2X2JhbCA9IGxldmVuZVRlc3QoZGF0YSA9IGduZ19lcnJfYW5vdmFfZGF0YSwgZXJyX29taSB+IGFzLmZhY3RvcihiYWxhbmNlKSwgY2VudGVyID0gbWVkaWFuKQogIGduZ19lcnJfbGV2X2JhbAoKYGBgCgo8c3BhbiBzdHlsZT0iY29sb3I6RGFya0JsdWU7IGZvbnQtc2l6ZToxOHB4OyI+NC4gU3BoZXJpY2l0eTwvc3Bhbj4gICAKClRoaXMgYXNzdW1wdGlvbiB3YXMgbWV0IHNpbmNlIHNwaGVyaWNpdHkgaXMgYWx3YXlzIG1ldCBmb3IgdHdvIGxldmVscyBvZiBhIHJlcGVhdGVkIG1lYXN1cmUgZmFjdG9yIGFuZCBpcywgdGhlcmVmb3JlLCB1bm5lY2Vzc2FyeSB0byBldmFsdWF0ZSAoR2lyZGVuLCAxOTkyKS4gCgo8L2RldGFpbHM+ICAKCgojIyMjIyMgUmVzdWx0cwoKU2luY2UgdGhlIG5vcm1hbGl0eSBhc3N1bXB0aW9uIHdhcyBub3QgbWV0IGZvciB0aGUgbWl4ZWQgQU5PVkEsIGEgcm9idXN0IEFOT1ZBIHdhcyBjb21wbGV0ZWQuIFRoaXMgd2FzIGRvbmUgdXNpbmcgdGhlICJ3ZWxjaEFERiIgcGFja2FnZSAobW9yZSBkZXRhaWxzIG9uIHRoaXMgcGFja2FnZTogPGh0dHBzOi8vam91cm5hbC5yLXByb2plY3Qub3JnL2FyY2hpdmUvMjAxNy9SSi0yMDE3LTA0OS9pbmRleC5odG1sKT4pLiBUaGUgcmVzdWx0cyBmcm9tIHRoaXMgYW5hbHlzaXMgYXJlIHNob3duIGJlbG93LCBmb2xsb3dlZCBieSBhIHRhYmxlIGRlcGljdGluZyB0aGUgc3RhdGlzdGljcy4gICAKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CgojIGNvbXB1dGUgdGhlIG1haW4gZWZmZWN0cwpnbmdfZXJyX3dlbCA9IHdlbGNoQURGLnRlc3QoZm9ybXVsYSA9IGVycl9vbWkgfiBsb2NhdGlvbiArIHBvd2VyICsgYmFsYW5jZSArIGN1ZSwgcmVzcG9uc2UgPSAiZXJyX29taSIsIGJldHdlZW4ucyA9IC4obG9jYXRpb24sIHBvd2VyLCBiYWxhbmNlKSwgd2l0aGluLnMgPSAuKGN1ZSksIHN1YmplY3QgPSAicGFydGljaXBhbnQiLCBjb250cmFzdCA9IGMoIm9tbmlidXMiLCAiYWxsLnBhaXJ3aXNlIiksIGRhdGEgPSBnbmdfZXJyX2Fub3ZhX2RhdGEsIGVmZmVjdC5zaXplID0gVFJVRSwgdHJpbW1pbmcgPSBUUlVFKQoKIyBOT1RFOnRvIGdldCB0aGUgZWZmZWN0IHNpemVzLCB0aGUgcGFja2FnZSB3aWxsIGFsbG93IHlvdSB0byBnZXQgdGhlIHBhaXJ3aXNlIChpLmUuIHBvc3QtaG9jKSBlZmZlY3Qgc2l6ZXMgCiAgIyB0aGUgcm9idXN0IEFOT1ZBIGFib3ZlIGRvZXMgbm90IGF1dG9tYXRpY2FsbHkgZ2V0IHRoZSBlZmZlY3Qgc2l6ZXMgCiAgIyBOb3RlOiBpdCBtdXN0IGJlIGRvbmUgZm9yIGVhY2ggZmFjdG9yIHNlcGFyYXRlbHkgd2l0aCB0aGUgZm9sbG93aW5nIGFzIGEgZ3VpZGUKIyB3ZWxjaEFERi50ZXN0KGZvcm11bGEgPSBlcnJfb21pIH4gbG9jYXRpb24gKyBwb3dlciArIGJhbGFuY2UgKyBjdWUsIHJlc3BvbnNlID0gImVycl9vbWkiLCBiZXR3ZWVuLnMgPSAuKGxvY2F0aW9uLCBwb3dlciwgYmFsYW5jZSksIHdpdGhpbi5zID0gLihjdWUpLCBzdWJqZWN0ID0gInBhcnRpY2lwYW50IiwgY29udHJhc3QgPSAiYWxsLnBhaXJ3aXNlIiwgZGF0YSA9IGduZ19lcnJfYW5vdmFfZGF0YSwgZWZmZWN0LnNpemUgPSBUUlVFLCB0cmltbWluZyA9IFRSVUUsIGVmZmVjdCA9ICJjdWUiKQoKI3dlbGNoQURGLnRlc3QoZm9ybXVsYSA9IGVycl9vbWkgfiBsb2NhdGlvbiArIHBvd2VyICsgY3VlLCBkYXRhID0gZ25nX2Vycl9hbm92YV9kYXRhLCBlZmZlY3QgPSAiY3VlIiwgY29udHJhc3QgPSAiYWxsLnBhaXJ3aXNlIiwgdHJpbW1pbmcgPSBUUlVFLCBlZmZlY3Quc2l6ZSA9IFRSVUUpCgojIGFkZCBhbGwgdGhlIGludGVyYWN0aW9uIGVmZmVjdHMKZ25nX2Vycl9yb2J1c3QgPSB1cGRhdGUuZGVmYXVsdChnbmdfZXJyX3dlbCwgLn5sb2NhdGlvbipwb3dlcipiYWxhbmNlKmN1ZSkKCmBgYAoKQWxsIHJlc3VsdHMgd2VyZSBiYXNlIG9uICRcYWxwaGEgPSAwLjA1JC4gQmVsb3cgYXJlIHRoZSByZXBvcnRlZCBzdGF0aXN0aWNzIGZvciBib3RoIG1haW4gZWZmZWN0cyBhbmQgdGhlIGludGVyYWN0aW9uLCBmb2xsb3dlZCBieSBhIHRhYmxlIGRlcGljdGluZyB0aGUgQU5PVkEgcmVzdWx0cy4gIAoKKipNYWluIEVmZmVjdCBvZiBTbWFydHBob25lIExvY2F0aW9uKiogIAoKVGhlcmUgd2FzIG5vIHNpZ25pZmljYW50IG1haW4gZWZmZWN0IG9mIHNtYXJ0cGhvbmUgbG9jYXRpb24gb24gb21pc3Npb24gZXJyb3JzLCAqV0oqKGByIGduZ19lcnJfcm9idXN0X3RhYmxlJERGblsxXWAsIGByIHJvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlJERGZFsxXSwgMilgKSA9IGByIHJvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlWzEsNF0sIDIpYCwgKnAqIGByIHBfcm91bmQoZ25nX2Vycl9yb2J1c3RfdGFibGUkcFsxXSlgLgoKKipNYWluIEVmZmVjdCBvZiBTbWFydHBob25lIFBvd2VyKiogIAoKVGhlcmUgd2FzIG5vIHNpZ25pZmljYW50IG1haW4gZWZmZWN0IG9mIHNtYXJ0cGhvbmUgcG93ZXIgb24gb21pc3Npb24gZXJyb3JzLCAqV0oqKGByIGduZ19lcnJfcm9idXN0X3RhYmxlJERGblsyXWAsIGByIHJvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlJERGZFsyXSwgMilgKSA9IGByIHJvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlWzIsNF0sIDIpYCwgKnAqIGByIHBfcm91bmQoZ25nX2Vycl9yb2J1c3RfdGFibGUkcFsyXSlgLiAgCgoqKk1haW4gRWZmZWN0IG9mIFNtYXJ0cGhvbmUgQmFsYW5jZSoqICAKClRoZXJlIHdhcyBubyBzaWduaWZpY2FudCBtYWluIGVmZmVjdCBvZiBiYWxhbmNlIChpLmUuIHdoaWNoIHRhc2sgd2FzIGNvbXBsZXRlZCBmaXJzdCkgb24gb21pc3Npb24gZXJyb3JzLCAqV0oqKGByIGduZ19lcnJfcm9idXN0X3RhYmxlJERGblszXWAsIGByIHJvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlJERGZFszXSwgMilgKSA9IGByIHJvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlWzMsNF0sIDIpYCwgKnAqIGByIHBfcm91bmQoZ25nX2Vycl9yb2J1c3RfdGFibGUkcFszXSlgYC4KCioqTWFpbiBFZmZlY3Qgb2YgU21hcnRwaG9uZSBDdWUgVHlwZSoqICAKClRoZXJlIHdhcyBubyBzaWduaWZpY2FudCBtYWluIGVmZmVjdCBvZiBjdWUgdHlwZSBvbiBvbWlzc2lvbiBlcnJvcnMsICpXSiooYHIgZ25nX2Vycl9yb2J1c3RfdGFibGUkREZuWzRdYCwgYHIgcm91bmQoZ25nX2Vycl9yb2J1c3RfdGFibGUkREZkWzRdLCAyKWApID0gYHIgcm91bmQoZ25nX2Vycl9yb2J1c3RfdGFibGVbNCw0XSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZSRwWzRdKWBgLiAgCgoqKkludGVyYWN0aW9uIG9mIFNtYXJ0cGhvbmUgTG9jYXRpb24gJiBQb3dlcioqICAKClRoZXJlIHdhcyBubyBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBiZXR3ZWVuIHNtYXJ0cGhvbmUgbG9jYXRpb24gYW5kIHBvd2VyIG9uIG9taXNzaW9uIGVycm9ycywgKldKKihgciBnbmdfZXJyX3JvYnVzdF90YWJsZSRERm5bNV1gLCBgciByb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZSRERmRbNV0sIDIpYCkgPSBgciByb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZVs1LDRdLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlJHBbNV0pYGAuCgoqKkludGVyYWN0aW9uIG9mIFNtYXJ0cGhvbmUgTG9jYXRpb24gJiBCYWxhbmNlKiogIAoKVGhlcmUgd2FzIG5vIHNpZ25pZmljYW50IGludGVyYWN0aW9uIGJldHdlZW4gc21hcnRwaG9uZSBsb2NhdGlvbiBhbmQgYmFsYW5jZSAoaS5lLiB3aGljaCB0YXNrIHdhcyBjb21wbGV0ZWQgZmlyc3QpIG9uIG9taXNzaW9uIGVycm9ycywgKldKKihgciBnbmdfZXJyX3JvYnVzdF90YWJsZSRERm5bNl1gLCBgciByb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZSRERmRbNl0sIDIpYCkgPSBgciByb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZVs2LDRdLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlJHBbNl0pYGAuCgoqKkludGVyYWN0aW9uIG9mIFNtYXJ0cGhvbmUgUG93ZXIgJiBCYWxhbmNlKiogIAoKVGhlcmUgd2FzIG5vIHNpZ25pZmljYW50IGludGVyYWN0aW9uIGJldHdlZW4gc21hcnRwaG9uZSBwb3dlciBhbmQgYmFsYW5jZSAoaS5lLiB3aGljaCB0YXNrIHdhcyBjb21wbGV0ZWQgZmlyc3QpIG9uIG9taXNzaW9uIGVycm9ycywgKldKKihgciBnbmdfZXJyX3JvYnVzdF90YWJsZSRERm5bN11gLCBgciByb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZSRERmRbN10sIDIpYCkgPSBgciByb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZVs3LDRdLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlJHBbN10pYGAuIAoKKipJbnRlcmFjdGlvbiBvZiBTbWFydHBob25lIExvY2F0aW9uICYgQ3VlIFR5cGUqKiAgCgpUaGVyZSB3YXMgbm8gc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gYmV0d2VlbiBzbWFydHBob25lIGxvY2F0aW9uIGFuZCBjdWUgdHlwZSBvbiBvbWlzc2lvbiBlcnJvcnMsICpXSiooYHIgZ25nX2Vycl9yb2J1c3RfdGFibGUkREZuWzhdYCwgYHIgcm91bmQoZ25nX2Vycl9yb2J1c3RfdGFibGUkREZkWzhdLCAyKWApID0gYHIgcm91bmQoZ25nX2Vycl9yb2J1c3RfdGFibGVbOCw0XSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZSRwWzhdKWBgLiAKCioqSW50ZXJhY3Rpb24gb2YgU21hcnRwaG9uZSBQb3dlciAmIEN1ZSBUeXBlKiogIAoKVGhlcmUgd2FzIG5vIHNpZ25pZmljYW50IGludGVyYWN0aW9uIGJldHdlZW4gc21hcnRwaG9uZSBwb3dlciBhbmQgY3VlIHR5cGUgb24gb21pc3Npb24gZXJyb3JzLCAqV0oqKGByIGduZ19lcnJfcm9idXN0X3RhYmxlJERGbls5XWAsIGByIHJvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlJERGZFs5XSwgMilgKSA9IGByIHJvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlWzksNF0sIDIpYCwgKnAqIGByIHBfcm91bmQoZ25nX2Vycl9yb2J1c3RfdGFibGUkcFs5XSlgYC4gCgoqKkludGVyYWN0aW9uIG9mIEJhbGFuY2UgJiBDdWUgVHlwZSoqICAKClRoZXJlIHdhcyBubyBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBiZXR3ZWVuIGJhbGFuY2UgKGkuZS4gd2hpY2ggdGFzayB3YXMgY29tcGxldGVkIGZpcnN0KSBhbmQgY3VlIHR5cGUgb24gb21pc3Npb24gZXJyb3JzLCAqV0oqKGByIGduZ19lcnJfcm9idXN0X3RhYmxlJERGblsxMF1gLCBgciByb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZSRERmRbMTBdLCAyKWApID0gYHIgcm91bmQoZ25nX2Vycl9yb2J1c3RfdGFibGVbMTAsNF0sIDIpYCwgKnAqIGByIHBfcm91bmQoZ25nX2Vycl9yb2J1c3RfdGFibGUkcFsxMF0pYGAuIAoKKipJbnRlcmFjdGlvbiBvZiBTbWFydHBob25lIExvY2F0aW9uLCBTbWFydHBob25lIFBvd2VyLCAmIEJhbGFuY2UqKiAgCgpUaGVyZSB3YXMgbm8gc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gYmV0d2VlbiBzbWFydHBob25lIGxvY2F0aW9uLCBzbWFydHBob25lIHBvd2VyLCBhbmQgYmFsYW5jZSAoaS5lLiB3aGljaCB0YXNrIHdhcyBjb21wbGV0ZWQgZmlyc3QpIG9uIG9taXNzaW9uIGVycm9ycywgKldKKihgciBnbmdfZXJyX3JvYnVzdF90YWJsZSRERm5bMTFdYCwgYHIgcm91bmQoZ25nX2Vycl9yb2J1c3RfdGFibGUkREZkWzExXSwgMilgKSA9IGByIHJvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlWzExLDRdLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlJHBbMTFdKWBgLiAKCioqSW50ZXJhY3Rpb24gb2YgU21hcnRwaG9uZSBMb2NhdGlvbiwgU21hcnRwaG9uZSBQb3dlciwgJiBDdWUgVHlwZSoqICAKClRoZXJlIHdhcyBubyBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBiZXR3ZWVuIHNtYXJ0cGhvbmUgbG9jYXRpb24sIHNtYXJ0cGhvbmUgcG93ZXIsIGFuZCBjdWUgdHlwZSBvbiBvbWlzc2lvbiBlcnJvcnMsICpXSiooYHIgZ25nX2Vycl9yb2J1c3RfdGFibGUkREZuWzEyXWAsIGByIHJvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlJERGZFsxMl0sIDIpYCkgPSBgciByb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZVsxMiw0XSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZSRwWzEyXSlgYC4gCgoqKkludGVyYWN0aW9uIG9mIFNtYXJ0cGhvbmUgTG9jYXRpb24sIEJhbGFuY2UsICYgQ3VlIFR5cGUqKiAgCgpUaGVyZSB3YXMgbm8gc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gYmV0d2VlbiBzbWFydHBob25lIGxvY2F0aW9uLCBiYWxhbmNlIChpLmUuIHdoaWNoIHRhc2sgd2FzIGNvbXBsZXRlZCBmaXJzdCksIGFuZCBjdWUgdHlwZSBvbiBvbWlzc2lvbiBlcnJvcnMsICpXSiooYHIgZ25nX2Vycl9yb2J1c3RfdGFibGUkREZuWzEzXWAsIGByIHJvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlJERGZFsxM10sIDIpYCkgPSBgciByb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZVsxMyw0XSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZSRwWzEzXSlgYC4gCgoqKkludGVyYWN0aW9uIG9mIFNtYXJ0cGhvbmUgUG93ZXIsIEJhbGFuY2UsICYgQ3VlIFR5cGUqKiAgCgpUaGVyZSB3YXMgbm8gc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gYmV0d2VlbiBzbWFydHBob25lIHBvd2VyLCBiYWxhbmNlIChpLmUuIHdoaWNoIHRhc2sgd2FzIGNvbXBsZXRlZCBmaXJzdCksIGFuZCBjdWUgdHlwZSBvbiBvbWlzc2lvbiBlcnJvcnMsICpXSiooYHIgZ25nX2Vycl9yb2J1c3RfdGFibGUkREZuWzE0XWAsIGByIHJvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlJERGZFsxNF0sIDIpYCkgPSBgciByb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZVsxNCw0XSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZSRwWzE0XSlgYC4gCgoqKkludGVyYWN0aW9uIG9mIFNtYXJ0cGhvbmUgTG9jYXRpb24sIFNtYXJ0cGhvbmUgUG93ZXIsIEJhbGFuY2UsICYgQ3VlIFR5cGUqKiAgCgpUaGVyZSB3YXMgbm8gc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gYmV0d2VlbiBzbWFydHBob25lIGxvY2F0aW9uLCBzbWFydHBob25lIHBvd2VyLCBiYWxhbmNlIChpLmUuIHdoaWNoIHRhc2sgd2FzIGNvbXBsZXRlZCBmaXJzdCksIGFuZCBjdWUgdHlwZSBvbiBvbWlzc2lvbiBlcnJvcnMsICpXSiooYHIgZ25nX2Vycl9yb2J1c3RfdGFibGUkREZuWzE1XWAsIGByIHJvdW5kKGduZ19lcnJfcm9idXN0X3RhYmxlJERGZFsxNV0sIDIpYCkgPSBgciByb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZVsxNSw0XSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfZXJyX3JvYnVzdF90YWJsZSRwWzE1XSlgYC4gCgoqKlBvc3QtaG9jIFRlc3RzKiogIAoKU2luY2UgdGhlcmUgd2FzIG5vIHNpZ25pZmljYW50IG1haW4gb3IgaW50ZXJhY3Rpb24gZWZmZWN0cywgbm8gcG9zdC1ob2NzIHdlcmUgY29tcGxldGVkLgoKYGBge3J9CgojIGNyZWF0ZSBkYXRhIGZyYW1lIGZyb20gcm9idXN0IEFOT1ZBIHJlc3VsdHMgdG8gZGlzcGxheQogICMgZ2V0IHRoZSBOdW1lcmF0b3IgREYgKERGbikKICBnbmdfZXJyX3JvYnVzdF9kZm4gPSBhcy5udW1lcmljKGMoZ25nX2Vycl9yb2J1c3QkbG9jYXRpb24kbnVtZXJhdG9yREYsIGduZ19lcnJfcm9idXN0JHBvd2VyJG51bWVyYXRvckRGLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGduZ19lcnJfcm9idXN0JGJhbGFuY2UkbnVtZXJhdG9yREYsIGduZ19lcnJfcm9idXN0JGN1ZSRudW1lcmF0b3JERiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbmdfZXJyX3JvYnVzdCRgbG9jYXRpb246cG93ZXJgJG51bWVyYXRvckRGLCBnbmdfZXJyX3JvYnVzdCRgbG9jYXRpb246YmFsYW5jZWAkbnVtZXJhdG9yREYsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ25nX2Vycl9yb2J1c3QkYHBvd2VyOmJhbGFuY2VgJG51bWVyYXRvckRGLCBnbmdfZXJyX3JvYnVzdCRgbG9jYXRpb246Y3VlYCRudW1lcmF0b3JERiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbmdfZXJyX3JvYnVzdCRgcG93ZXI6Y3VlYCRudW1lcmF0b3JERiwgZ25nX2Vycl9yb2J1c3QkYGJhbGFuY2U6Y3VlYCRudW1lcmF0b3JERiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbmdfZXJyX3JvYnVzdCRgbG9jYXRpb246cG93ZXI6YmFsYW5jZWAkbnVtZXJhdG9yREYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbmdfZXJyX3JvYnVzdCRgbG9jYXRpb246cG93ZXI6Y3VlYCRudW1lcmF0b3JERiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGduZ19lcnJfcm9idXN0JGBsb2NhdGlvbjpiYWxhbmNlOmN1ZWAkbnVtZXJhdG9yREYsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ25nX2Vycl9yb2J1c3QkYHBvd2VyOmJhbGFuY2U6Y3VlYCRudW1lcmF0b3JERiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbmdfZXJyX3JvYnVzdCRgbG9jYXRpb246cG93ZXI6YmFsYW5jZTpjdWVgJG51bWVyYXRvckRGKSkKICAjIGdldCB0aGUgRGVub21pbmF0b3IgREYgKERGZCkKICBnbmdfZXJyX3JvYnVzdF9kZmQgPSBhcy5udW1lcmljKGMoZ25nX2Vycl9yb2J1c3QkbG9jYXRpb24kZGVub21pbmF0b3JERiwgZ25nX2Vycl9yb2J1c3QkcG93ZXIkZGVub21pbmF0b3JERiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbmdfZXJyX3JvYnVzdCRiYWxhbmNlJGRlbm9taW5hdG9yREYsIGduZ19lcnJfcm9idXN0JGN1ZSRkZW5vbWluYXRvckRGLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGduZ19lcnJfcm9idXN0JGBsb2NhdGlvbjpwb3dlcmAkZGVub21pbmF0b3JERiwgZ25nX2Vycl9yb2J1c3QkYGxvY2F0aW9uOmJhbGFuY2VgJGRlbm9taW5hdG9yREYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbmdfZXJyX3JvYnVzdCRgcG93ZXI6YmFsYW5jZWAkZGVub21pbmF0b3JERiwgZ25nX2Vycl9yb2J1c3QkYGxvY2F0aW9uOmN1ZWAkZGVub21pbmF0b3JERiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbmdfZXJyX3JvYnVzdCRgcG93ZXI6Y3VlYCRkZW5vbWluYXRvckRGLCBnbmdfZXJyX3JvYnVzdCRgYmFsYW5jZTpjdWVgJGRlbm9taW5hdG9yREYsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ25nX2Vycl9yb2J1c3QkYGxvY2F0aW9uOnBvd2VyOmJhbGFuY2VgJGRlbm9taW5hdG9yREYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbmdfZXJyX3JvYnVzdCRgbG9jYXRpb246cG93ZXI6Y3VlYCRkZW5vbWluYXRvckRGLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ25nX2Vycl9yb2J1c3QkYGxvY2F0aW9uOmJhbGFuY2U6Y3VlYCRkZW5vbWluYXRvckRGLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGduZ19lcnJfcm9idXN0JGBwb3dlcjpiYWxhbmNlOmN1ZWAkZGVub21pbmF0b3JERiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbmdfZXJyX3JvYnVzdCRgbG9jYXRpb246cG93ZXI6YmFsYW5jZTpjdWVgJGRlbm9taW5hdG9yREYpKQogICMgZ2V0IHRoZSBXSiBzdGF0aXN0aWMKICBnbmdfZXJyX3JvYnVzdF9XSiA9IGFzLm51bWVyaWMoYyhnbmdfZXJyX3JvYnVzdCRsb2NhdGlvbiR3ZWxjaC5ULCBnbmdfZXJyX3JvYnVzdCRwb3dlciR3ZWxjaC5ULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGduZ19lcnJfcm9idXN0JGJhbGFuY2Ukd2VsY2guVCwgZ25nX2Vycl9yb2J1c3QkY3VlJHdlbGNoLlQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ25nX2Vycl9yb2J1c3QkYGxvY2F0aW9uOnBvd2VyYCR3ZWxjaC5ULCBnbmdfZXJyX3JvYnVzdCRgbG9jYXRpb246YmFsYW5jZWAkd2VsY2guVCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGduZ19lcnJfcm9idXN0JGBwb3dlcjpiYWxhbmNlYCR3ZWxjaC5ULCBnbmdfZXJyX3JvYnVzdCRgbG9jYXRpb246Y3VlYCR3ZWxjaC5ULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGduZ19lcnJfcm9idXN0JGBwb3dlcjpjdWVgJHdlbGNoLlQsIGduZ19lcnJfcm9idXN0JGBiYWxhbmNlOmN1ZWAkd2VsY2guVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbmdfZXJyX3JvYnVzdCRgbG9jYXRpb246cG93ZXI6YmFsYW5jZWAkd2VsY2guVCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGduZ19lcnJfcm9idXN0JGBsb2NhdGlvbjpwb3dlcjpjdWVgJHdlbGNoLlQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbmdfZXJyX3JvYnVzdCRgbG9jYXRpb246YmFsYW5jZTpjdWVgJHdlbGNoLlQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ25nX2Vycl9yb2J1c3QkYHBvd2VyOmJhbGFuY2U6Y3VlYCR3ZWxjaC5ULCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGduZ19lcnJfcm9idXN0JGBsb2NhdGlvbjpwb3dlcjpiYWxhbmNlOmN1ZWAkd2VsY2guVCkpCiAgIyBnZXQgdGhlIHAgdmFsdWUKICBnbmdfZXJyX3JvYnVzdF9wdmFsID0gYXMubnVtZXJpYyhjKGduZ19lcnJfcm9idXN0JGxvY2F0aW9uJHB2YWwsIGduZ19lcnJfcm9idXN0JHBvd2VyJHB2YWwsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ25nX2Vycl9yb2J1c3QkYmFsYW5jZSRwdmFsLCBnbmdfZXJyX3JvYnVzdCRjdWUkcHZhbCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbmdfZXJyX3JvYnVzdCRgbG9jYXRpb246cG93ZXJgJHB2YWwsIGduZ19lcnJfcm9idXN0JGBsb2NhdGlvbjpiYWxhbmNlYCRwdmFsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ25nX2Vycl9yb2J1c3QkYHBvd2VyOmJhbGFuY2VgJHB2YWwsIGduZ19lcnJfcm9idXN0JGBsb2NhdGlvbjpjdWVgJHB2YWwsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ25nX2Vycl9yb2J1c3QkYHBvd2VyOmN1ZWAkcHZhbCwgZ25nX2Vycl9yb2J1c3QkYGJhbGFuY2U6Y3VlYCRwdmFsLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGduZ19lcnJfcm9idXN0JGBsb2NhdGlvbjpwb3dlcjpiYWxhbmNlYCRwdmFsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ25nX2Vycl9yb2J1c3QkYGxvY2F0aW9uOnBvd2VyOmN1ZWAkcHZhbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGduZ19lcnJfcm9idXN0JGBsb2NhdGlvbjpiYWxhbmNlOmN1ZWAkcHZhbCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbmdfZXJyX3JvYnVzdCRgcG93ZXI6YmFsYW5jZTpjdWVgJHB2YWwsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ25nX2Vycl9yb2J1c3QkYGxvY2F0aW9uOnBvd2VyOmJhbGFuY2U6Y3VlYCRwdmFsKSkKICAKICAjIGJpbmQgdGhlIGRhdGEgaW50byAxIGRhdGEgZnJhbWUKICBnbmdfZXJyX3JvYnVzdF90YWJsZSA9IGFzLmRhdGEuZnJhbWUoY2JpbmQoZ25nX2Vycl9yb2J1c3RfZGZuLCBnbmdfZXJyX3JvYnVzdF9kZmQsIGduZ19lcnJfcm9idXN0X1dKLCBnbmdfZXJyX3JvYnVzdF9wdmFsKSkKICAgICMgYWRkIGNvbHVtbnM6ICgxKSB0byBkZW5vdGUgdGhlIGVmZmVjdCwgYW5kICgyKSB0byBkZW5vdGUgc2lnbmlmaWNhbmNlIGF0IHAgPCAuMDUgCiAgICBnbmdfZXJyX3JvYnVzdF90YWJsZSA9IGNiaW5kKG5hbWVzKGduZ19lcnJfcm9idXN0KVsxOjE1XSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGduZ19lcnJfcm9idXN0X3RhYmxlLCBjKHJlcCgiIiwgbGVuZ3RoKGduZ19lcnJfcm9idXN0X3B2YWwpKSkpCiAgICBjb2xuYW1lcyhnbmdfZXJyX3JvYnVzdF90YWJsZSkgPSBjKCJFZmZlY3QiLCJERm4iLCAiREZkIiwgIldKIFN0YXQiLCAicCIsICJwIDwgLjA1IikKICAgIHJvd25hbWVzKGduZ19lcnJfcm9idXN0X3RhYmxlKSA9IE5VTEwKICAKIyBzaG93IEFOT1ZBIHJlc3VsdHMgaW4ga2FibGUgdGFibGUgCmthYmxlKGduZ19lcnJfcm9idXN0X3RhYmxlLCBjYXB0aW9uID0gIjN4MngyIFJvYnVzdCBNaXhlZCBBTk9WQSBvbiBPbWlzc2lvbiBFcnJvciBpbiB0aGUgR28vTm8tR28gVGFzayIsIGRpZ2l0cyA9IDQsIGFsaWduID0gJ2MnKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCAiaG92ZXIiLCBmdWxsX3dpZHRoID0gRikgCgpgYGAKCiMjIyMjIFZpc3VhbGl6YXRpb25zCgpUaGUgZm9sbG93aW5nIHNob3dzIGEgdmlzdWxpemF0aW9uIG9mIHRoZSBHby9Oby1HbyBvbWlzc2lvbiBlcnJvciBkYXRhIGJhc2VkIG9uIHRoZSB0aHJlZSBmYWN0b3JzOiBzbWFydHBob25lIGxvY2F0aW9uLCBzbWFydHBob25lIHBvd2VyLCBhbmQgY3VlIHR5cGUuCgpUbyB2aXN1YWxpemUgdGhlIG1peGVkIGRlc2lnbiwgdHdvIHBsb3RzIHdlcmUgY3JlYXRlZCAoaS5lLiBvbmUgZm9yIGVhY2ggY3VlIHR5cGUpLiAqTm90ZTogU2luY2UgdGhlIGJhbGFuY2UgZmFjdG9yIChpLmUuIHdoaWNoIHRhc2sgd2FzIGNvbXBsZXRlZCBmaXJzdCkgZGlkIG5vdCBoYXZlIGEgc2lnbmlmaWNhbnQgbWFpbiBlZmZlY3Qgb3IgaW50ZXJhY3Rpb24gZWZmZWN0IG9uIHRoZSBkYXRhLCB0aGlzIGZhY3RvciBpcyBub3QgdmlzdWFsaXplZCBpbiB0aGUgcGxvdHMqCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojLS1GT1IgVEhFIFZFUlRJQ0FMIENVRSBUWVBFLS0gCgojIGNyZWF0ZSBkYXRhIGZyYW1lIHdpdGggbG9jYXRpb24gY29uZGl0aW9ucyBhcyBjaGFyYWN0ZXJzIHJhdGhlciB0aGFuIGludGVyZ2VycyAKICAjIEZpcnN0LCBnZXQgYSBzdWJzZXQgb2YgdGhlIGRhdGEKICBnbmdfZXJyX2Jhcl92X2RhdGEgPSBnbmdfZXJyX2ZpbmFsW2duZ19lcnJfZmluYWwkY3VlID09IDEsIGMoImxvY2F0aW9uIiwgInBvd2VyIiwgImduZ19lcnJfb21pX2xvbmciKV0KICAgIGNvbG5hbWVzKGduZ19lcnJfYmFyX3ZfZGF0YSkgPSBjKCJsb2NhdGlvbiIsICJwb3dlciIsICJlcnJfb21pIikKICAgIHJvd25hbWVzKGduZ19lcnJfYmFyX3ZfZGF0YSkgPSBOVUxMIAogICMgcmVmb3JtYXQgbG9jYXRpb24gJiBwb3dlciBhcyBmYWN0b3JzICAKICBnbmdfZXJyX2Jhcl92X2RhdGEkbG9jYXRpb24gPSBmYWN0b3IoZ25nX2Vycl9iYXJfdl9kYXRhJGxvY2F0aW9uLCAKICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygxLCAyLCAzKSwKICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiT24gRGVzayIsICJQb2NrZXQvQmFnIiwgIk91dHNpZGUiKSkKICBnbmdfZXJyX2Jhcl92X2RhdGEkcG93ZXIgPSBmYWN0b3IoZ25nX2Vycl9iYXJfdl9kYXRhJHBvd2VyLCAKICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygxLCAyKSwKICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiT04iLCAiT0ZGIikpCiAgICAgICAKIyBjcmVhdGUgcGxvdApnbmdfZXJyX2Jhcl92ID0gZ2dwbG90KGduZ19lcnJfYmFyX3ZfZGF0YSwgYWVzKHggPSBsb2NhdGlvbiwgeSA9IGVycl9vbWksIGZpbGwgPSBwb3dlciksIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBnZW9tX2JhcihzdGF0ID0gInN1bW1hcnkiLCBmdW4ueSA9ICJtZWFuIiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArIAogICAgZ3VpZGVzKHNoYXBlID0gRkFMU0UpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiY2FkZXRibHVlMyIsICJkZWVwc2t5Ymx1ZTQiKSkgKyAKICBsYWJzKHRpdGxlID0gIlBlcmZvcm1hbmNlIG9uIHRoZSBHby9Oby1HbyBUYXNrOiAnVmVydGljYWwnIEN1ZSBUeXBlIiwKICAgICAgIHN1YnRpdGxlID0gIk9taXNzaW9uIEVycm9ycyIsCiAgICAgICB4ID0gIlNtYXJ0cGhvbmUgTG9jYXRpb24iLCAKICAgICAgIHkgPSAiT21pc3Npb24gRXJyb3IiLCAKICAgICAgIGZpbGwgPSAiU21hcnRwaG9uZSBQb3dlciIsCiAgICAgICBjYXB0aW9uID0gcGFzdGUwKHN0cndyYXAoIkZpZ3VyZSBYLiBEaXN0cmlidXRpb25zIG9mIHNjb3JlcyBvbiB0aGUgdmVydGljYWwgY3VlIHR5cGUgb24gdGhlIEN1ZS1EZXBlbmRlbnQgR28vTm8tR28gVGFzaywgYXJyYW5nZWQgYnkgc21hcnRwaG9uZSBsb2NhdGlvbiAoYWxvbmcgdGhlIHgtYXhpcykgYW5kIHNtYXJ0cGhvbmUgcG93ZXIgKGRpZmZlcmVudCBiYXJzKS4gT21pc3Npb24gZXJyb3JzIG9jY3VycmVkIHdoZW4gYSBwYXJ0aWNpcGFudCBmYWlsZWQgdG8gcmVzcG9uZCB0byBhIG5vbi10YXJnZXQgc3RpbXVsdXMuIENvbG91cmVkIGRvdHMgcmVwcmVzZW50IGluZGl2aWR1YWwgZGF0YSBwb2ludHMuIEJsYWNrIGRvdHMgYW5kIGVycm9yIGJhcnMgZGVwaWN0IG1lYW5zIGFuZCBzdGFuZGFyZCBlcnJvcnMsIHJlc3BlY3RpdmVseS4iLCB3aWR0aCA9IDgwKSwgY29sbGFwc2UgPSAiXG4iKSkgKwogICAgICAgICMgdGhlICJcbiIgaGVyZSBkZW5vdGUgdGhhdCB5b3Ugd2FudCBhIG5ldyBsaW5lIGZvcm1lZCBpbiB0aGUgdGV4dAogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKG1pbihnbmdfZXJyX2Jhcl92X2RhdGEkZXJyX29taSksIG1heChnbmdfZXJyX2Jhcl92X2RhdGEkZXJyX29taSkpKSArCiAgI3NjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gY29scykgKwogIGdlb21fcG9pbnQoc3RhdCA9ICJpZGVudGl0eSIsIGFlcyhjb2xvciA9IHBvd2VyKSwgc2l6ZSA9IDEsIAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAuNTMpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImRlZXBza3libHVlNCIsICJwdXJwbGU0IikpICsgCiAgZ2VvbV9wb2ludChzdGF0PSJzdW1tYXJ5IiwgZnVuLnk9Im1lYW4iLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKC45KSwgc2l6ZSA9IDEuNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGdlb21fZXJyb3JiYXIoZGF0YSA9IGduZ19lcnJfYmFyX3ZfZGF0YSwgc3RhdCA9ICJzdW1tYXJ5IiwgZnVuLnltaW4gPSBmdW5jdGlvbih4KSBtZWFuKHgpIC0gc2QoeCkvc3FydChsZW5ndGgoeCkpLCAKICAgICAgICAgICAgICAgIGZ1bi55bWF4ID0gZnVuY3Rpb24oeCkgbWVhbih4KSArIHNkKHgpL3NxcnQobGVuZ3RoKHgpKSwgc2l6ZT0gLjUsIHdpZHRoPSAuMjUsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoLjkpKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxMyksIAogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAsIHNpemUgPSAxMiwgZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMykpCgojLS1GT1IgVEhFIEhPUklaT05UQUwgQ1VFIFRZUEUtLSAKCiMgY3JlYXRlIGRhdGEgZnJhbWUgd2l0aCBsb2NhdGlvbiBjb25kaXRpb25zIGFzIGNoYXJhY3RlcnMgcmF0aGVyIHRoYW4gaW50ZXJnZXJzIAogICMgRmlyc3QsIGdldCBhIHN1YnNldCBvZiB0aGUgZGF0YQogIGduZ19lcnJfYmFyX2hfZGF0YSA9IGduZ19lcnJfZmluYWxbZ25nX2Vycl9maW5hbCRjdWUgPT0gMiwgYygibG9jYXRpb24iLCAicG93ZXIiLCAiZ25nX2Vycl9vbWlfbG9uZyIpXQogICAgY29sbmFtZXMoZ25nX2Vycl9iYXJfaF9kYXRhKSA9IGMoImxvY2F0aW9uIiwgInBvd2VyIiwgImVycl9vbWkiKQogICAgcm93bmFtZXMoZ25nX2Vycl9iYXJfaF9kYXRhKSA9IE5VTEwgCiAgIyByZWZvcm1hdCBsb2NhdGlvbiAmIHBvd2VyIGFzIGZhY3RvcnMgIAogIGduZ19lcnJfYmFyX2hfZGF0YSRsb2NhdGlvbiA9IGZhY3RvcihnbmdfZXJyX2Jhcl9oX2RhdGEkbG9jYXRpb24sIAogICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKDEsIDIsIDMpLAogICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJPbiBEZXNrIiwgIlBvY2tldC9CYWciLCAiT3V0c2lkZSIpKQogIGduZ19lcnJfYmFyX2hfZGF0YSRwb3dlciA9IGZhY3RvcihnbmdfZXJyX2Jhcl9oX2RhdGEkcG93ZXIsIAogICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKDEsIDIpLAogICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJPTiIsICJPRkYiKSkKICAgICAgIAojIGNyZWF0ZSBwbG90CmduZ19lcnJfYmFyX2ggPSBnZ3Bsb3QoZ25nX2Vycl9iYXJfaF9kYXRhLCBhZXMoeCA9IGxvY2F0aW9uLCB5ID0gZXJyX29taSwgZmlsbCA9IHBvd2VyKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGdlb21fYmFyKHN0YXQgPSAic3VtbWFyeSIsIGZ1bi55ID0gIm1lYW4iLCBwb3NpdGlvbiA9ICJkb2RnZSIpICsgCiAgICBndWlkZXMoc2hhcGUgPSBGQUxTRSkgKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJjYWRldGJsdWUzIiwgImRlZXBza3libHVlNCIpKSArIAogIGxhYnModGl0bGUgPSAiUGVyZm9ybWFuY2Ugb24gdGhlIEdvL05vLUdvIFRhc2s6ICdIb3Jpem9udGFsJyBDdWUgVHlwZSIsCiAgICAgICBzdWJ0aXRsZSA9ICJPbWlzc2lvbiBFcnJvcnMiLAogICAgICAgeCA9ICJTbWFydHBob25lIExvY2F0aW9uIiwgCiAgICAgICB5ID0gIk9taXNzaW9uIEVycm9yIiwgCiAgICAgICBmaWxsID0gIlNtYXJ0cGhvbmUgUG93ZXIiLAogICAgICAgY2FwdGlvbiA9IHBhc3RlMChzdHJ3cmFwKCJGaWd1cmUgWC4gRGlzdHJpYnV0aW9ucyBvZiBzY29yZXMgb24gdGhlIGhvcml6b250YWwgY3VlIHR5cGUgb24gdGhlIEN1ZS1EZXBlbmRlbnQgR28vTm8tR28gVGFzaywgYXJyYW5nZWQgYnkgc21hcnRwaG9uZSBsb2NhdGlvbiAoYWxvbmcgdGhlIHgtYXhpcykgYW5kIHNtYXJ0cGhvbmUgcG93ZXIgKGRpZmZlcmVudCBiYXJzKS4gT21pc3Npb24gZXJyb3JzIG9jY3VycmVkIHdoZW4gYSBwYXJ0aWNpcGFudCBmYWlsZWQgdG8gcmVzcG9uZCB0byBhIG5vbi10YXJnZXQgc3RpbXVsdXMuIENvbG91cmVkIGRvdHMgcmVwcmVzZW50IGluZGl2aWR1YWwgZGF0YSBwb2ludHMuIEJsYWNrIGRvdHMgYW5kIGVycm9yIGJhcnMgZGVwaWN0IG1lYW5zIGFuZCBzdGFuZGFyZCBlcnJvcnMsIHJlc3BlY3RpdmVseS4iLCB3aWR0aCA9IDgwKSwgY29sbGFwc2UgPSAiXG4iKSkgKwogICAgICAgICMgdGhlICJcbiIgaGVyZSBkZW5vdGUgdGhhdCB5b3Ugd2FudCBhIG5ldyBsaW5lIGZvcm1lZCBpbiB0aGUgdGV4dAogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKG1pbihnbmdfZXJyX2Jhcl9oX2RhdGEkZXJyX29taSksIG1heChnbmdfZXJyX2Jhcl9oX2RhdGEkZXJyX29taSkpKSArCiAgI3NjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gY29scykgKwogIGdlb21fcG9pbnQoc3RhdCA9ICJpZGVudGl0eSIsIGFlcyhjb2xvciA9IHBvd2VyKSwgc2l6ZSA9IDEsIAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAuNTMpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImRlZXBza3libHVlNCIsICJwdXJwbGU0IikpICsgCiAgZ2VvbV9wb2ludChzdGF0PSJzdW1tYXJ5IiwgZnVuLnk9Im1lYW4iLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKC45KSwgc2l6ZSA9IDEuNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGdlb21fZXJyb3JiYXIoZGF0YSA9IGduZ19lcnJfYmFyX2hfZGF0YSwgc3RhdCA9ICJzdW1tYXJ5IiwgZnVuLnltaW4gPSBmdW5jdGlvbih4KSBtZWFuKHgpIC0gc2QoeCkvc3FydChsZW5ndGgoeCkpLCAKICAgICAgICAgICAgICAgIGZ1bi55bWF4ID0gZnVuY3Rpb24oeCkgbWVhbih4KSArIHNkKHgpL3NxcnQobGVuZ3RoKHgpKSwgc2l6ZT0gLjUsIHdpZHRoPSAuMjUsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoLjkpKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxMyksIAogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAsIHNpemUgPSAxMiwgZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMykpCgojIFNob3cgcGxvdHMKICAjIGZvciB0aGUgVmVydGljYWwgY3VlIHR5cGUKICBnbmdfZXJyX2Jhcl92CiAgIyBmb3IgdGhlIEhvcml6b250YWwgY3VlIHR5cGUKICBnbmdfZXJyX2Jhcl9oCgoKYGBgCgojIyMjIEFjY3VyYWN5IEFuYWx5c2lzICAKCkEgKiozKHNtYXJ0cGhvbmUgbG9jYXRpb246IGRlc2ssIHBvY2tldC9iYWcsIG91dHNpZGUpIHggMihzbWFydHBob25lIHBvd2VyOiBPTiwgT0ZGKSoqIGJldHdlZW4tc3ViamVjdHMgQU5PVkEgd2FzIGNvbXBsZXRlZCAqKERWID0gYXZlcmFnZSBSVCkqLiBUaGUgYmV0d2Vlbi1zdWJqZWN0cyBmYWN0b3JzIHdlcmUgc21hcnRwaG9uZSBsb2NhdGlvbiBhbmQgcG93ZXIuICAKClByaW9yIHRvIGNvbXBsZXRpbmcgdGhlIGFuYWx5c2lzLCBwbGFubmVkIGV4Y2x1c2lvbiBjcml0ZXJhIHdhcyBhcHBsaWVkIHRvIHRoZSBkYXRhLiBFeGNsdXNpb24gY3JpdGVyaWEgZm9yIHRoaXMgYW5hbHlzaXMgaGVscGVkIHRvIGNvbnRyb2wgZm9yIGFueSBwYXJ0aWNpcGFudHMgd2hvIGRpZCBub3QgZm9sbG93IHRoZSBpbnN0cnVjdGlvbnMuIEFueSBwYXJ0aWNpcGFudHMgd2hvIGhhZCBhIHJlYWN0aW9uIHRpbWUgdGhhdCB3YXMgaGlnaGVyIHRoYW4gdHdvIHN0YW5kYXJkIGRldmlhdGlvbnMgKFNEKSBmcm9tIHRoZSBtZWFuIHJlYWN0aW9uIHRpbWUgd2VyZSBub3QgaW5jbHVkZWQgaW4gdGhlIGZpbmFsIGFuYWx5c2lzLiAgCgotIEV4Y2x1ZGUgZGF0YSBmcm9tIGFueSBwYXJ0aXRpcGFudHMgd2l0aCAoMSkgbWlzc2luZyBkYXRhIGFuZC9vciAoMikgdGhlIHJlYWN0aW9uIHRpbWUgU0QgY3JpdGVyaWEgKGkuZS4gd2l0aGluIHR3byBzdGFuZGFyZCBkZXZhdGlvbnMgZnJvbSB0aGUgbWVhbiBSVCkuIFRoZXJlIHdhcyBhIHRvdGFsIG9mICoqYHIgbGVuZ3RoKGduZ19hY19maW5hbCRwYXJ0aWNpcGFudClgKiogcGFydGljaXBhbnRzIGluIHRoZSBHby9Oby1HbyBFcnJvciBhbmFseXNpcy4gCiAgLSBNaXNzaW5nIERhdGE6IGByIGFicyhucm93KGduZ19hY19hbmFseXNpcykgLSBucm93KGduZ19hY19ub05BKSlgIHBhcnRpY2lwYW50cyB3ZXJlIHJlbW92ZWQgZHVlIHRvIG1pc3NpbmcgZGF0YSAoKm5vdGU6IHRoaXMgYWxzbyByZW1vdmVkIGRhdGEgZnJvbSBwYXJ0aWNpcGFudHMgd2hvIGRpZCBub3QgcmVzcG9uc2UgZHVyaW5nIHRoZSB0YXNrKikuCiAgLSBSZWFjdGlvbiBUaW1lIFNEIENyaXRlcmlhOiBgciBucm93KGduZ19hY19hbGxfcmVtb3ZlKWAgcGFydGljaXBhbnRzIHdlcmUgcmVtb3ZlZCBiZWNhdXNlIHRoZXkgZGlkIG5vdCBtZWV0IHRoZSByYWN0aW9uIHRpbWUgU0QgY3JpdGVyaWEuIFRoZSBudW1iZXIgb2YgcGFydGljaXBhbnRzIHJlbW92ZWQgd2l0aCByZXNwZWN0IHRvIHRoZWlyIHNtYXJ0cGhvbmUgbG9jYXRpb24gYW5kIHBvd2VyIGNvbmRpdGlvbnMgd2FzIGFzIGZvbGxvd3M6IAogICAgLSBGb3IgdGhlIHBvd2VyICJvbiIgY29uZGl0aW9uOiBgciBsZW5ndGgoZ25nX2FjX3JlbW92ZTEpYCAob24gZGVzayksIGByIGxlbmd0aChnbmdfYWNfcmVtb3ZlMilgIChwb2NrZXQvYmFnKSwgYHIgbGVuZ3RoKGduZ19hY19yZW1vdmUzKWAgKG91dHNpZGUpCiAgICAtIEZvciB0aGUgcG93ZXIgIm9mZiIgY29uZGl0aW9uOiBgciBsZW5ndGgoZ25nX2FjX3JlbW92ZTQpYCAob24gZGVzayksIGByIGxlbmd0aChnbmdfYWNfcmVtb3ZlNSlgIChwb2NrZXQvYmFnKSwgYHIgbGVuZ3RoKGduZ19hY19yZW1vdmU2KWAgKG91dHNpZGUpCgoKYGBge3J9CgojIGZpbHRlciBhbnkgcGFydGljaXBhbnRzIHdpdGggbWlzc2luZyBkYXRhIG9yIHRoYXQgZG8gbm90IG1lZXQgdGhlIGluY2x1c2lvbm4gY3JpdGVyaWEKCiAgIyBmb3IgYWxsIHBzLCBleGNsdWRpbmcgYW55IHAgd2l0aCBtaXNzaW5nIGRhdGEgaW4gdGhlIGF2ZXJhZ2UgcmVhY3Rpb24gdGltZSBjb2x1bW4gKGduZ19ydF9hdikKICAjIE5vdGU6IHRoaXMgYWxzbyByZW1vdmVkIHBhcnRpY2lwYW50cyB3aG8gZGlkIG5vdCByZXNwb25kIGF0IGFsbCBkdXJpbmcgdGhlIHRhc2sKICBnbmdfYWNfbm9OQSA9IGduZ19hY19hbmFseXNpc1shaXMubmEoZ25nX2FjX2FuYWx5c2lzJGduZ19ydF9hdiksXQogIAogICMgZm9yIGFsbCBwcywgZXhjbHVkaW5nIGFueSB0aGF0IGRpZCBub3QgbWVldCB0aGUgcmVhY3Rpb24gdGltZSBkZXZpYXRpb24gY3JpdGVyaWEgKGkuZS4gd2l0aGluIHR3byBzdGFuZGFyZCBkZXZhdGlvbnMgZnJvbSB0aGUgbWVhbiBSVCkKICAjIGdldCB0aGUgbWVhbiBSVCB3aXRoIGFsbCB0aGUgZGF0YSBpbmNsdWRlZCwgZGl2aWRlZCBieSB0aGVpciByZXNwZWN0aXZlIHNtYXJ0cGhvbmUgY29uZGl0aW9uIChpLmUuIGVpdGhlciBsb2NhdGlvbiBvciBwb3dlcikKICAgICMgZ2V0IHRoZSBkZXNjcmlwdGl2ZSBvZiB0aGUgZGF0YQogICAgZ25nX2FjX25vTkFfZGVzID0gcHN5Y2g6OmRlc2NyaWJlQnkoZ25nX2FjX25vTkEsIGxpc3QoZ25nX2FjX25vTkEkbG9jYXRpb24sIGduZ19hY19ub05BJHBvd2VyKSwgbWF0ID0gVFJVRSkKICAgICMgZmluZCB0aGUgaW5jbHVzaW9uIGNyaXRlcmlhIGZvciBlYWNoIGNvbmRpdGlvbiAoTSAtIDIqU0QpCiAgICAgICMgcG93ZXIgPSBPTiAKICAgICAgICAjIGxvY2F0aW9uID0gIm9uIGRlc2siCiAgICAgICAgZ25nX2FjX2NyaXRlcmlhMSA9IGduZ19hY19ub05BX2Rlc1siZ25nX3J0X2F2MSIsIm1lYW4iXSArIChnbmdfYWNfbm9OQV9kZXNbImduZ19ydF9hdjEiLCJzZCJdICogMikKICAgICAgICAjIGxvY2F0aW9uID0gInBvY2tldC9iYWciCiAgICAgICAgZ25nX2FjX2NyaXRlcmlhMiA9IGduZ19hY19ub05BX2Rlc1siZ25nX3J0X2F2MiIsIm1lYW4iXSArIChnbmdfYWNfbm9OQV9kZXNbImduZ19ydF9hdjIiLCJzZCJdICogMikKICAgICAgICAjIGxvY2F0aW9uID0gIm91dHNpZGUiCiAgICAgICAgZ25nX2FjX2NyaXRlcmlhMyA9IGduZ19hY19ub05BX2Rlc1siZ25nX3J0X2F2MyIsIm1lYW4iXSArIChnbmdfYWNfbm9OQV9kZXNbImduZ19ydF9hdjMiLCJzZCJdICogMikKICAgICAgIyBwb3dlciA9IE9GRiAKICAgICAgICAjIGxvY2F0aW9uID0gIm9uIGRlc2siCiAgICAgICAgZ25nX2FjX2NyaXRlcmlhNCA9IGduZ19hY19ub05BX2Rlc1siZ25nX3J0X2F2NCIsIm1lYW4iXSArIChnbmdfYWNfbm9OQV9kZXNbImduZ19ydF9hdjQiLCJzZCJdICogMikKICAgICAgICAjIGxvY2F0aW9uID0gInBvY2tldC9iYWciCiAgICAgICAgZ25nX2FjX2NyaXRlcmlhNSA9IGduZ19hY19ub05BX2Rlc1siZ25nX3J0X2F2NSIsIm1lYW4iXSArIChnbmdfYWNfbm9OQV9kZXNbImduZ19ydF9hdjUiLCJzZCJdICogMikKICAgICAgICAjIGxvY2F0aW9uID0gIm91dHNpZGUiCiAgICAgICAgZ25nX2FjX2NyaXRlcmlhNiA9IGduZ19hY19ub05BX2Rlc1siZ25nX3J0X2F2NiIsIm1lYW4iXSArIChnbmdfYWNfbm9OQV9kZXNbImduZ19ydF9hdjYiLCJzZCJdICogMikKICAgICMgZmluZCB0aGUgcGFydGljaXBhbnRzIHRvIHJlbW92ZSBmcm9tIHRoZSBkYXRhIAogICAgICAjIHBvd2VyID0gT04gCiAgICAgICAgIyBsb2NhdGlvbiA9ICJvbiBkZXNrIgogICAgICAgIGduZ19hY19yZW1vdmUxID0gKGduZ19hY19ub05BICU+JSBmaWx0ZXIobG9jYXRpb24gPT0gMSAmIHBvd2VyID09IDEgJiBnbmdfcnRfYXYgPiBnbmdfYWNfY3JpdGVyaWExKSlbLCJwYXJ0aWNpcGFudCJdCiAgICAgICAgIyBsb2NhdGlvbiA9ICJwb2NrZXQvYmFnIgogICAgICAgIGduZ19hY19yZW1vdmUyID0gKGduZ19hY19ub05BICU+JSBmaWx0ZXIobG9jYXRpb24gPT0gMiAmIHBvd2VyID09IDEgJiBnbmdfcnRfYXYgPiBnbmdfYWNfY3JpdGVyaWEyKSlbLCJwYXJ0aWNpcGFudCJdCiAgICAgICAgIyBsb2NhdGlvbiA9ICJvdXRzaWRlIgogICAgICAgIGduZ19hY19yZW1vdmUzID0gKGduZ19hY19ub05BICU+JSBmaWx0ZXIobG9jYXRpb24gPT0gMyAmIHBvd2VyID09IDEgJiBnbmdfcnRfYXYgPiBnbmdfYWNfY3JpdGVyaWEzKSlbLCJwYXJ0aWNpcGFudCJdCiAgICAgICMgcG93ZXIgPSBPRkYgCiAgICAgICAgIyBsb2NhdGlvbiA9ICJvbiBkZXNrIgogICAgICAgIGduZ19hY19yZW1vdmU0ID0gKGduZ19hY19ub05BICU+JSBmaWx0ZXIobG9jYXRpb24gPT0gMSAmIHBvd2VyID09IDIgJiBnbmdfcnRfYXYgPiBnbmdfYWNfY3JpdGVyaWE0KSlbLCJwYXJ0aWNpcGFudCJdCiAgICAgICAgIyBsb2NhdGlvbiA9ICJwb2NrZXQvYmFnIgogICAgICAgIGduZ19hY19yZW1vdmU1ID0gKGduZ19hY19ub05BICU+JSBmaWx0ZXIobG9jYXRpb24gPT0gMiAmIHBvd2VyID09IDIgJiBnbmdfcnRfYXYgPiBnbmdfYWNfY3JpdGVyaWE1KSlbLCJwYXJ0aWNpcGFudCJdCiAgICAgICAgIyBsb2NhdGlvbiA9ICJvdXRzaWRlIgogICAgICAgIGduZ19hY19yZW1vdmU2ID0gKGduZ19hY19ub05BICU+JSBmaWx0ZXIobG9jYXRpb24gPT0gMyAmIHBvd2VyID09IDMgJiBnbmdfcnRfYXYgPiBnbmdfYWNfY3JpdGVyaWE2KSlbLCJwYXJ0aWNpcGFudCJdCiAgICAjIG1ha2UgYSBsaXN0IG9mIGFsbCB0aGUgcGFydGljaXBhbnQgdG8gcmVtb3ZlIGZyb20gdGhlIGRhdGEKICAgICAgZ25nX2FjX2FsbF9yZW1vdmUgPSBkcGx5cjo6YXJyYW5nZShkYXRhLmZyYW1lKCJyZW1vdmUiID0gYXMubnVtZXJpYyhjKGduZ19hY19yZW1vdmUxLCBnbmdfYWNfcmVtb3ZlMiwgZ25nX2FjX3JlbW92ZTMsIGduZ19hY19yZW1vdmU0LCBnbmdfYWNfcmVtb3ZlNSwgZ25nX2FjX3JlbW92ZTYpKSksIHJlbW92ZSkKICAgICAgICAjIG5vdGU6IHRoaXMgY29kZSBhbHNvIHJlLW9yZGVycyB0aGUgbGlzdCBmcm9tIHNtYWxsZXN0IHRvIGxhcmdlc3QKICAjIEZpbHRlciB0aGUgZGF0YSB1c2luZyB0aGUgZmluYWwgcmVtb3ZlIGxpc3QgCiAgZ25nX2FjX2ZpbmFsID0gZHBseXI6OmZpbHRlcihnbmdfYWNfbm9OQSwgIXBhcnRpY2lwYW50ICVpbiUgZ25nX2FjX2FsbF9yZW1vdmUkcmVtb3ZlKQoKYGBgCgojIyMjIyBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzIAoKVGhlIGZvbGxvd2luZyB0YWJsZSBkZXBpY3RzIHRoZSBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGZvciB0aGUgR28vTm8tR28gQWNjdXJhY3kgQW5hbHlzaXM6IHRoZSBtZWFuICgqTSopLCBzdGFuZGFyZCBkZXZpYXRpb24gKCpTRCopLCBtaW5pbXVtIHNjb3JlICgqbWluLiopLCBtYXhpbXVtIHNjb3JlICgqbWF4LiopLCBhbmQgdGhlIHNhbXBsZSBzaXplICgqbiopLiAgCgpgYGB7cn0KCiMgY3JlYXRlIGEgZGF0YSBmcmFtZSB3aXRoIHRoZSBkZXNjcmlwdGl2ZXMgb2YgYWxsIHRoZSBkYXRhLCBncm91cGVkIGJ5IHRoZSBsb2NhdGlvbiAmIHBvd2VyIGNvbmRpdGlvbnMKICAjIHRoaXMgY3JlYXRlcyBpbmZvcm1hdGlvbiBmb3IgdGhlIDYgcG9zc2libGUgY29tYmluZWQgY29uZGl0aW9ucwogIGduZ19hY19kZXMgPSBwc3ljaDo6ZGVzY3JpYmVCeShnbmdfYWNfZmluYWwsIGxpc3QoZ25nX2FjX2ZpbmFsJGxvY2F0aW9uLCBnbmdfYWNfZmluYWwkcG93ZXIpLCBtYXQgPSBUUlVFKSAgCiAgCiMgb3JnYW5pemUgdGhlIGRhdGEgaW50byBhIG5ldyBkYXRhIGZyYW1lIGRlcGljdGluZyB0aGUgTSwgU0QsIG1pbi4sIG1heC4sIGFuZCBuLgogIGduZ19hY19kZXNfdCA9IHJiaW5kKChjYmluZCh0KGduZ19hY19kZXNbImduZ19ydF9hdjEiLGMoIm1lYW4iLCAic2QiLCAibWluIiwgIm1heCIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0KGduZ19hY19kZXNbImduZ19ydF9hdjIiLGMoIm1lYW4iLCAic2QiLCAibWluIiwgIm1heCIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0KGduZ19hY19kZXNbImduZ19ydF9hdjMiLGMoIm1lYW4iLCAic2QiLCAibWluIiwgIm1heCIsICJuIildKSkpLCAKICAgICAgICAgICAgICAgICAgICAgIChjYmluZCh0KGduZ19hY19kZXNbImduZ19ydF9hdjQiLGMoIm1lYW4iLCAic2QiLCAibWluIiwgIm1heCIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0KGduZ19hY19kZXNbImduZ19ydF9hdjUiLGMoIm1lYW4iLCAic2QiLCAibWluIiwgIm1heCIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0KGduZ19hY19kZXNbImduZ19ydF9hdjYiLGMoIm1lYW4iLCAic2QiLCAibWluIiwgIm1heCIsICJuIildKSkpKQogICAgY29sbmFtZXMoZ25nX2FjX2Rlc190KSA9IGMoIk9uIERlc2siLCAiSW4gUG9ja2V0L0JhZyIsICJPdXRzaWRlIikKICAgIHJvd25hbWVzKGduZ19hY19kZXNfdCkgPSByZXAoYygiTSIsICJTRCIsICJtaW4uIiwgIm1heC4iLCAibiIpLCAyKQogICAgCiMgdXNlIGthYmxlIHRvIHNob3cgdGhlIGRlc2NyaXB0aXZlcyB0YWJsZQogIGthYmxlKGduZ19hY19kZXNfdCwgY2FwdGlvbiA9ICJEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzOiBSZWFjdGlvbiBUaW1lIChzZWMuKSBvbiB0aGUgR28vTm8tR28gVGFzayIsIGRpZ2l0cyA9IDQsIGFsaWduID0gJ2MnKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCAiaG92ZXIiLCBmdWxsX3dpZHRoID0gRikgJT4lCiAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiwgIlNtYXJ0cGhvbmUgTG9jYXRpb24iID0gMykpICU+JQogIGdyb3VwX3Jvd3MoaW5kZXggPSBjKCJTbWFydHBob25lIFBvd2VyIE9OIiA9IDUsICJTbWFydHBob25lIFBvd2VyIE9GRiIgPSA1KSkKCmBgYAoKIyMjIyMgQW5hbHlzaXMgCgpUbyBhc3Nlc3MgaWYgdGhlIHJlYWN0aW9uIHRpbWUgc3RhdGlzdGljYWxseSBkaWZmZXJlZCwgd2UgY29uZHVjdGVkIGEgM3gyIEFOT1ZBIHdpdGggdGhlIGJldHdlZW4tc3ViamVjdHMgZmFjdG9ycyBvZiBzbWFydHBob25lIGxvY2F0aW9uIChpLmUuIG9uIGRlc2ssIGluIHBvY2tldC9iYWcsIG9yIG91dHNpZGUpIGFuZCBwb3dlciAoaS5lLiBvbiBvciBvZmYpLiBTaW5jZSB0aGVyZSBhcmUgdW5lcXVhbCBzYW1wbGUgc2l6ZXMsIHdlIHVzZWQgVHlwZSBJSUkgc3VtIG9mIHNxdWFyZXMuCgojIyMjIyMgQXNzdW1wdGlvbnMgIAoKPGRldGFpbHM+ICAKPHN1bW1hcnk+IFRoZSBBTk9WQSBtYWRlIHRocmVlIGFzc3VtcHRpb25zLiBUaGUgaW5kZXBlbmRlbnQgcmFuZG9tIHNhbXBsaW5nIGFuZCBub3JtYWxpdHkgYXNzdW1wdGlvbnMgd2VyZSBtZXQuIFRoZSBob21vZ2VuZWl0eSBvZiB2YXJpYW5jZSBhc3N1bXB0aW9uIHdhcyBub3QgbWV0LCB0aGVyZWZvcmUsIGEgV2hpdGUgY29ycmVjdGlvbiB3YXMgZG9uZSBmb3IgdGhlIHJlbGV2YW50IGVmZmVjdC4gKihjbGljayB0byBzZWUgZGV0YWlscykqLiA8L3N1bW1hcnk+ICAKCjxzcGFuIHN0eWxlPSJjb2xvcjpEYXJrQmx1ZTsgZm9udC1zaXplOjE4cHg7Ij4xLiBJbmRlcGVuZGVudCBSYW5kb20gU2FtcGxpbmc8L3NwYW4+ICAKClRoaXMgYXNzdW1wdGlvbiB3YXMgbWV0IGR1cmluZyB0ZXN0aW5nLiAgCiAgICAKPHNwYW4gc3R5bGU9ImNvbG9yOkRhcmtCbHVlOyBmb250LXNpemU6MThweDsiPjIuIE5vcm1hbGl0eTwvc3Bhbj4gIAoKVGhpcyBhc3N1bXB0aW9uIHdhcyB0ZXN0ZWQgYnkgdmlzdWFsaXppbmcgdGhlIHJlc2lkdWFscywgYXBwbHlpbmcgYSBTaGFwaXJvLVdpbGsgdGVzdCB0byB0aGUgcmVzZGl1YWxzLCBhbmQgb2JzZXJ2aW5nIHRoZSBTa2V3bmVzcyBhbmQgS3VydG9zaXMgb2YgdGhlIGRhdGEgKihleHRyYWN0ZWQgZnJvbSB0aGUgQU5PVkEgb3V0cHV0KS4qICAKICAgIApgYGB7ciBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGdldCB0aGUgcmVxdWlyZWQgZGF0YSBmcm9tIHRoZSBvc3Bhbl9hbmFseXNpcyBkYXRhOiBwYXJ0aWNpcGFudCwgbG9jYXRpb24sIHBvd2VyLCBhbmQgc2NvcmUKZ25nX2FjX2Fub3ZhX2RhdGEgPSBnbmdfYWNfZmluYWxbLCBjKCJwYXJ0aWNpcGFudCIsICJsb2NhdGlvbiIsICJwb3dlciIsICJiYWxhbmNlIiwgImduZ19ydF9hdiIpXQogICAgY29sbmFtZXMoZ25nX2FjX2Fub3ZhX2RhdGEpID0gYygicGFydGljaXBhbnQiLCAibG9jYXRpb24iLCAicG93ZXIiLCAiYmFsYW5jZSIsICJydF9hdiIpCiAgICByb3duYW1lcyhnbmdfYWNfYW5vdmFfZGF0YSkgPSBOVUxMCiAgICAjIHJlZm9ybWF0IGxvY2F0aW9uLCAgcG93ZXIsIGFuZCBiYWxhbmNlIGFzIGZhY3RvcnMgIAogICAgZ25nX2FjX2Fub3ZhX2RhdGEkbG9jYXRpb24gPSBmYWN0b3IoZ25nX2FjX2Fub3ZhX2RhdGEkbG9jYXRpb24sIAogICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKDEsIDIsIDMpLAogICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJPbiBEZXNrIiwgIlBvY2tldC9CYWciLCAiT3V0c2lkZSIpKQogICAgZ25nX2FjX2Fub3ZhX2RhdGEkcG93ZXIgPSBmYWN0b3IoZ25nX2FjX2Fub3ZhX2RhdGEkcG93ZXIsIAogICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKDEsIDIpLAogICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJPTiIsICJPRkYiKSkKICAgIGduZ19hY19hbm92YV9kYXRhJGJhbGFuY2UgPSBmYWN0b3IoZ25nX2FjX2Fub3ZhX2RhdGEkYmFsYW5jZSwgCiAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoMSwgMiksCiAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk9zcGFuIEZpcnN0IiwgIkdvL05vLUdvIEZpcnN0IikpCgojIHJ1biBiZXR3ZWVuLXN1YmplY3RzIEFOT1ZBIChJVjogU21hcnRwaG9uZSBQb3dlciAmIExvY2F0aW9uLCBCYWxhbmNlOyBEVjogT1NwYW4gQWJvbHV0ZSBTY29yZSkKZ25nX2FjX2Fub3ZhID0gZXpBTk9WQSgKICBkYXRhID0gZ25nX2FjX2Fub3ZhX2RhdGEKICAsIGR2ID0gLihydF9hdikKICAsIHdpZCA9IC4ocGFydGljaXBhbnQpCiAgLCBiZXR3ZWVuID0gLihsb2NhdGlvbiwgcG93ZXIsIGJhbGFuY2UpCiAgLCB0eXBlID0gMyAjIHVuZXF1YWwgc2FtcGxlIHNpemVzLCB0aGVyZm9yZSB1c2UgdHlwZSAzCiAgLCBkZXRhaWxlZCA9IFRSVUUKICAsIHJldHVybl9hb3YgPSBUUlVFCikKCiMgY2FsY3VsYXRlICYgZXh0cmFjdCB0aGUgcmVzaWR1YWxzIGZyb20gdGhlIEFOT1ZBCmduZ19hY19yZXMgPSBkYXRhLmZyYW1lKCJyZXNpZHVhbHMiID0gcHJvaihnbmdfYWNfYW5vdmEkYW92KVssIlJlc2lkdWFscyJdKSAgIAoKYGBgCiAgICAKLSBJdCBhcHBlYXJzIHRoYXQgdGhlIHJlc2lkdWFscyBsaWUgY2xvc2VseSB0byBhIHN0cmFpZ2h0IGxpbmUsIHdoaWNoIHN1Z2dlc3RzIG5vcm1hbGl0eSAqKHNlZSB2aXN1YWxpemF0aW9uIGJlbG93KSouCiAgICAKYGBge3J9CgpxcW5vcm0oZ25nX2FjX3JlcyRyZXNpZHVhbHMsIG1haW4gPSAiUS1RIFBsb3Qgb2YgdGhlIEdvL05vLUdvIFJlYWN0aW9uIFRpbWUgUmVzaWR1YWxzIikgCnFxbGluZShnbmdfYWNfcmVzJHJlc2lkdWFscykKCmBgYAogICAgCi0gSXQgYXBwZWFycyB0aGF0IHJlc2lkdWFscyB0ZW5kIHRvIGZvbGxvdyB0aGUgc2hhcGUgb2YgYSBub3JtYWwgZGlzdHJpYnV0aW9uLCB3aXRoIGEgc2xpZ2h0IHNrZXcgdG8gdGhlIGxlZnQgYW5kIHNvbWUgZGF0YSBvbiB0aGUgZmFyIHJpZ2h0ICooc2VlIHZpc3VhbGl6YXRpb24gYmVsb3cpKi4KICAgIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKcXBsb3QoZ25nX2FjX3JlcyRyZXNpZHVhbHMsIG1haW4gPSAiSGlzdG9ncmFtIG9mIEdvL05vLUdvIFJlYWN0aW9uIFRpbWUgUmVzaWR1YWxzIikgKyAKICB0aGVtZV9jbGFzc2ljKCkKCmBgYAogICAKLSBUaGUgU2hhcGlyby1XaWxrIHRlc3Qgb2Ygbm9ybWFsaXR5IHdhcyBzaWduaWZpY2FudCAoYmFzZWQgb24gJFxhbHBoYSA9IDAuMDUkKSwgKlcqID0gYHIgcm91bmQoYXMubnVtZXJpYyhnbmdfYWNfc2hhcCRzdGF0aXN0aWNbIlciXSksIDIpYCwgKnAqIGByIHBfcm91bmQoZ25nX2FjX3NoYXAkcC52YWx1ZSlgICooc2VlIGNvZGUgYmVsb3cpKi4gIAogICAKYGBge3J9CgpnbmdfYWNfc2hhcCA9IHNoYXBpcm8udGVzdChnbmdfYWNfcmVzJHJlc2lkdWFscykKZ25nX2FjX3NoYXAKCmBgYAoKLSBUaGUgZGF0YSdzIFNrZXduZXNzIGFuZCBLdXJ0b3NpcyB3YXMgZXhhbWluZWQgYW5kIHNob3dlZCB0aGF0IGJvdGggdGhlIFNrZXduZXNzIChyYW5nZTogYHIgcm91bmQobWluKGFzLm51bWVyaWMoZ25nX2FjX3NrX3RbYygxLDQpLF0pKSwgMilgIHRvIGByIHJvdW5kKG1heChhcy5udW1lcmljKGduZ19hY19za190W2MoMSw0KSxdKSksIDIpYCkgYW5kIEt1cnRvc2lzIChyYW5nZTogYHIgcm91bmQobWluKGFzLm51bWVyaWMoZ25nX2FjX3NrX3RbYygyLDUpLF0pKSwgMilgIHRvIGByIHJvdW5kKG1heChhcy5udW1lcmljKGduZ19hY19za190W2MoMiw1KSxdKSksIDIpYCkgd2VyZSB3aXRoaW4gdGhlIGFjY2VwdGFibGUgcmFuZ2Ugb2YgJFxwbSAyLjAkIGFuZCAkXHBtIDkuMCQsIHJlc3BlY3RpdmVseSAoU2NobWlkZXIsIFppZWdsZXIsIERhbmF5LCBCZXllciwgJiBCw7xobmVyLCAyMDEwKSAqKHNlZSB0YWJsZSBiZWxvdykqLiAgCgpgYGB7cn0KIyB1c2UgdGhlICJnbmdfYWNfZGVzIiBkYXRhIGZyYW1lIGZyb20gdGhlIGRlc2NyaXB0aXZlcwoKIyBvcmdhbml6ZSB0aGUgZGF0YSBpbnRvIGEgbmV3IGRhdGEgZnJhbWUgZGVwaWN0aW5nIHRoZSBTa2V3LCBrdXJ0b3NpcywgYW5kIHNhbXBsZSBzaXplIChuKS4KICBnbmdfYWNfc2tfdCA9IHJiaW5kKChjYmluZCh0KGduZ19hY19kZXNbImduZ19ydF9hdjEiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2FjX2Rlc1siZ25nX3J0X2F2MiIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChnbmdfYWNfZGVzWyJnbmdfcnRfYXYzIiwgYygic2tldyIsICJrdXJ0b3NpcyIsICJuIildKSkpLCAKICAgICAgICAgICAgICAgICAgICAgIChjYmluZCh0KGduZ19hY19kZXNbImduZ19ydF9hdjQiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2FjX2Rlc1siZ25nX3J0X2F2NSIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChnbmdfYWNfZGVzWyJnbmdfcnRfYXY2IiwgYygic2tldyIsICJrdXJ0b3NpcyIsICJuIildKSkpKQogICAgY29sbmFtZXMoZ25nX2FjX3NrX3QpID0gYygiT24gRGVzayIsICJJbiBQb2NrZXQvQmFnIiwgIk91dHNpZGUiKQogICAgcm93bmFtZXMoZ25nX2FjX3NrX3QpID0gcmVwKGMoIlNrZXduZXNzIiwgIkt1cnRvc2lzIiwgIm4iKSwgMikKICAgIAojIHVzZSBrYWJsZSB0byBzaG93IHRoZSBkZXNjcmlwdGl2ZXMgdGFibGUKICBrYWJsZShnbmdfYWNfc2tfdCwgY2FwdGlvbiA9ICJTa2V3bmVzcyBhbmQgS3VydG9zaXMgb2YgdGhlIFJlYWN0aW9uIFRpbWUgb24gdGhlIEdvL05vLUdvIFRhc2siLCBkaWdpdHMgPSA0LCBhbGlnbiA9ICdjJykgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpICU+JQogIGFkZF9oZWFkZXJfYWJvdmUoYygiICIsICJTbWFydHBob25lIExvY2F0aW9uIiA9IDMpKSAlPiUKICBncm91cF9yb3dzKGluZGV4ID0gYygiU21hcnRwaG9uZSBQb3dlciBPTiIgPSAzLCAiU21hcnRwaG9uZSBQb3dlciBPRkYiID0gMykpCgpgYGAKCi0gVGhlcmVmb3JlLCBiYXNlZCBvbiBhbGwgdGhlIG5vcm1hbGl0eSBhc3N1bXB0aW9uIGNoZWNrcywgbm9ybWFsaXR5IHdhcyBhc3N1bWVkIHRvIGJlIHdpdGhpbiB0aGUgYWNjZXB0YWJsZSByYW5nZSBmb3IgdGhlIEFOT1ZBIGFuYWx5c2lzLiBBZGRpdGlvbmFsbHksIGl0IHNob3VsZCBiZSBub3RlZCB0aGF0IEFOT1ZBIGFuYWx5c2VzIGNhbiBiZSByb2J1c3QgdG8gdmlvbGF0aW9ucyBvZiBub3JtYWxpdHkgKEdhcmRuZXIgJiBUcmVtYmxheSwgMjAwNykuCgo8c3BhbiBzdHlsZT0iY29sb3I6RGFya0JsdWU7IGZvbnQtc2l6ZToxOHB4OyI+My4gSG9tb2dlbmVpdHkgb2YgVmFyaWFuY2U8L3NwYW4+IAoKVGhpcyBhc3N1bXB0aW9uIHdhcyB0ZXN0ZWQgYnkgY29uZHVjdGluZyBMZXZlbmUncyBUZXN0IGZvciBIb21vZ2VuZWl0eSBvZiBWYXJpYW5jZSBmb3IgZWFjaCBiZXR3ZWVuLXN1YmplY3RzIHZhcmlhYmxlIChpLmUuIHNtYXJ0cGhvbmUgbG9jYXRpb24gYW5kIHNtYXJ0cGhvbmUgcG93ZXIpLiAgCgotIFRoZSBob21vZ2VuZWl0eSBhc3N1bXB0aW9uIHdhcyBtZXQgKGJhc2VkIG9uICRcYWxwaGEgPSAwLjA1JCkgZm9yIHNtYXJ0cGhvbmUgbG9jYXRpb24sICpGKihgciBnbmdfYWNfbGV2X2xvYyREZlsxXWAsIGByIGduZ19hY19sZXZfbG9jJERmWzJdYCkgPSBgciByb3VuZChnbmdfYWNfbGV2X2xvY1syXVsxLDFdLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19hY19sZXZfbG9jWzNdWzEsMV0pYCBhbmQgYmFsYW5jZSwgKkYqKGByIGduZ19hY19sZXZfYmFsJERmWzFdYCwgYHIgZ25nX2FjX2xldl9iYWwkRGZbMl1gKSA9IGByIHJvdW5kKGduZ19hY19sZXZfYmFsWzJdWzEsMV0sIDIpYCwgKnAqIGByIHBfcm91bmQoZ25nX2FjX2xldl9iYWxbM11bMSwxXSlgLiBIb3dldmVyLCB0aGUgaG9tb2dlbmVpdHkgYXNzdW1wdGlvbiB3YXMgbm90IG1ldCBmb3Igc21hcnRwaG9uZSBwb3dlciwgKkYqKGByIGduZ19hY19sZXZfcG93JERmWzFdYCwgYHIgZ25nX2FjX2xldl9wb3ckRGZbMl1gKSA9IGByIHJvdW5kKGduZ19hY19sZXZfcG93WzJdWzEsMV0sIDIpYCwgKnAqIGByIHBfcm91bmQoZ25nX2FjX2xldl9wb3dbM11bMSwxXSlgICooc2VlIGNvZGUgYmVsb3cpKi4KCmBgYHtyfQoKIyBjb25kdWN0IGxldmVuZSdzCiAgIyBmb3IgbG9jYXRpb24KICBnbmdfYWNfbGV2X2xvYyA9IGxldmVuZVRlc3QoZGF0YSA9IGduZ19hY19hbm92YV9kYXRhLCBydF9hdiB+IGFzLmZhY3Rvcihsb2NhdGlvbiksIGNlbnRlciA9IG1lZGlhbikKICBnbmdfYWNfbGV2X2xvYwogICMgZm9yIHBvd2VyCiAgZ25nX2FjX2xldl9wb3cgPSBsZXZlbmVUZXN0KGRhdGEgPSBnbmdfYWNfYW5vdmFfZGF0YSwgcnRfYXYgfiBhcy5mYWN0b3IocG93ZXIpLCBjZW50ZXIgPSBtZWRpYW4pCiAgZ25nX2FjX2xldl9wb3cKICAjIGZvciBiYWxhbmNlCiAgZ25nX2FjX2xldl9iYWwgPSBsZXZlbmVUZXN0KGRhdGEgPSBnbmdfYWNfYW5vdmFfZGF0YSwgcnRfYXYgfiBhcy5mYWN0b3IoYmFsYW5jZSksIGNlbnRlciA9IG1lZGlhbikKICBnbmdfYWNfbGV2X2JhbAoKYGBgCgotIFRoZSBob21vZ2VuZWl0eSBvZiB2YXJpYW5jZSBhc3N1bXB0aW9uIHdhcyBub3QgbWV0IGZvciB0aGUgc21hcnBob25lIHBvd2VyIGNvbmRpdGlvbi4gVGhlcmVmb3JlLCBjb25zaWRlcmluZyB0aGVyZSBhcmUgdW5lcXVhbCBzYW1wbGUgc2l6ZXMsIGEgV2hpdGUtY29ycmVjdGVkIEYtdGVzdCB3YXMgY29uZHVjdGVkIChpLmUuIGlmIGludGVyZXN0ZWQgaW4gYXNzZXNzaW5nIHRoZSBtYWluIGVmZmVjdCBvZiBwb3dlcikuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIHJ1biB0aGUgY29ycmVjdGVkIEFOT1ZBIChJVjogU21hcnRwaG9uZSBQb3dlciAmIExvY2F0aW9uLCBCYWxhbmNlOyBEVjogT1NwYW4gQWJvbHV0ZSBTY29yZSkKIyB0aGlzIHdpbGwgYmUgdXNlZCB0byByZXBvcnQgdGhlIG1haW4gZWZmZWN0IG9mIHNtYXJ0cGhvbmUgcG93ZXIgb25seSAKZ25nX2FjX2Fub3ZhX2NvciA9IGV6QU5PVkEoCiAgZGF0YSA9IGduZ19hY19hbm92YV9kYXRhCiAgLCBkdiA9IC4ocnRfYXYpCiAgLCB3aWQgPSAuKHBhcnRpY2lwYW50KQogICwgYmV0d2VlbiA9IC4obG9jYXRpb24sIHBvd2VyLCBiYWxhbmNlKQogICwgdHlwZSA9IDMgIyB1bmVxdWFsIHNhbXBsZSBzaXplcywgdGhlcmZvcmUgdXNlIHR5cGUgMwogICwgZGV0YWlsZWQgPSBUUlVFCiAgLCByZXR1cm5fYW92ID0gVFJVRQogICwgd2hpdGUuYWRqdXN0ID0gVFJVRQopCgojIENhbGN1bGF0ZSBlZmZlY3Qgc2l6ZToKIyB0aGlzIHdpbGwgYmUgdXNlZCB0byByZXBvcnQgdGhlIG1haW4gZWZmZWN0IG9mIHNtYXJ0cGhvbmUgcG93ZXIgb25seSAKZ25nX2FjX3Bvd19lcyA9IChFdGFTcShnbmdfYWNfYW5vdmEkYW92LCB0eXBlID0gMywgYW5vdmEgPSBGQUxTRSkpWzJdCgpgYGAKCjwvZGV0YWlscz4gIAoKCiMjIyMjIyBSZXN1bHRzCgpBbGwgcmVzdWx0cyB3ZXJlIGJhc2VkIG9uICRcYWxwaGEgPSAwLjA1JC4gQmVsb3cgYXJlIHRoZSByZXBvcnRlZCBzdGF0aXN0aWNzIGZvciB0aGUgbWFpbiBlZmZlY3RzIGFuZCB0aGUgaW50ZXJhY3Rpb25zLCBmb2xsb3dlZCBieSBhIHRhYmxlIGRlcGljdGluZyB0aGUgQU5PVkEgcmVzdWx0cy4gIAoKKipNYWluIEVmZmVjdCBvZiBTbWFydHBob25lIExvY2F0aW9uKiogIAoKVGhlcmUgd2FzIG5vIHNpZ25pZmljYW50IG1haW4gZWZmZWN0IG9mIHNtYXJ0cGhvbmUgbG9jYXRpb24gb24gcmVhY3Rpb24gdGltZSwgKkYqKGByIGduZ19hY190WzIsMl1gLCBgciBnbmdfYWNfdFsyLDNdYCkgPSBgciByb3VuZChnbmdfYWNfdFsyLDRdLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19hY190WzIsNV0pYCwgJFxldGFeezJ9JCBgciBwX3JvdW5kKGduZ19hY190WzIsN10pYC4KCioqTWFpbiBFZmZlY3Qgb2YgU21hcnRwaG9uZSBQb3dlcioqICAKClRoZXJlIHdhcyBubyBzaWduaWZpY2FudCBtYWluIGVmZmVjdCBvZiBzbWFydHBob25lIHBvd2VyIG9uIHJlYWN0aW9uIHRpbWUsICpGKihgciBnbmdfYWNfdFszLDJdYCwgYHIgZ25nX2FjX3RbMywzXWApID0gYHIgcm91bmQoZ25nX2FjX3RbMyw0XSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfYWNfdFszLDVdKWAsICRcZXRhXnsyfSQgYHIgcF9yb3VuZChnbmdfYWNfdFszLDddKWAuCgoqKkludGVyYWN0aW9uIG9mIEJhbGFuY2UqKiAgCgpUaGVyZSB3YXMgbm8gc2lnbmlmaWNhbnQgbWFpbiBlZmZlY3Qgb2YgYmFsYW5jZSAoaS5lLiB3aGljaCB0YXNrIHdhcyBjb21wbGV0ZWQgZmlyc3QpIG9uIHJlYWN0aW9uIHRpbWUsICpGKihgciBnbmdfYWNfdFs0LDJdYCwgYHIgZ25nX2FjX3RbNCwzXWApID0gYHIgcm91bmQoZ25nX2FjX3RbNCw0XSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfYWNfdFs0LDVdKWAsICRcZXRhXnsyfSQgYHIgcF9yb3VuZChnbmdfYWNfdFs0LDddKWAuCgoqKkludGVyYWN0aW9uIG9mIFNtYXJ0cGhvbmUgTG9jYXRpb24gJiBTbWFydHBob25lIFBvd2VyKiogIAoKVGhlcmUgd2FzIG5vIHNpZ25pZmljYW50IGludGVyYWN0aW9uIGJldHdlZW4gc21hcnRwaG9uZSBsb2NhdGlvbiBhbmQgc21hcnRwaG9uZSBwb3dlciBvbiByZWFjdGlvbiB0aW1lLCAqRiooYHIgZ25nX2FjX3RbNSwyXWAsIGByIGduZ19hY190WzUsM11gKSA9IGByIHJvdW5kKGduZ19hY190WzUsNF0sIDIpYCwgKnAqIGByIHBfcm91bmQoZ25nX2FjX3RbNSw1XSlgLCAkXGV0YV57Mn0kIGByIHBfcm91bmQoZ25nX2FjX3RbNSw3XSlgLgoKKipJbnRlcmFjdGlvbiBvZiBTbWFydHBob25lIExvY2F0aW9uICYgQmFsYW5jZSoqICAKClRoZXJlIHdhcyBubyBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBiZXR3ZWVuIHNtYXJ0cGhvbmUgbG9jYXRpb24gYW5kIGJhbGFuY2UgKGkuZS4gd2hpY2ggdGFzayB3YXMgY29tcGxldGVkIGZpcnN0KSBvbiByZWFjdGlvbiB0aW1lLCAqRiooYHIgZ25nX2FjX3RbNiwyXWAsIGByIGduZ19hY190WzYsM11gKSA9IGByIHJvdW5kKGduZ19hY190WzYsNF0sIDIpYCwgKnAqIGByIHBfcm91bmQoZ25nX2FjX3RbNiw1XSlgLCAkXGV0YV57Mn0kIGByIHBfcm91bmQoZ25nX2FjX3RbNiw3XSlgLgoKKipJbnRlcmFjdGlvbiBvZiBTbWFydHBob25lIFBvd2VyICYgQmFsYW5jZSoqICAKClRoZXJlIHdhcyBubyBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBiZXR3ZWVuIHNtYXJ0cGhvbmUgcG93ZXIgYW5kIGJhbGFuY2UgKGkuZS4gd2hpY2ggdGFzayB3YXMgY29tcGxldGVkIGZpcnN0KSBvbiByZWFjdGlvbiB0aW1lLCAqRiooYHIgZ25nX2FjX3RbNywyXWAsIGByIGduZ19hY190WzcsM11gKSA9IGByIHJvdW5kKGduZ19hY190WzcsNF0sIDIpYCwgKnAqIGByIHBfcm91bmQoZ25nX2FjX3RbNyw1XSlgLCAkXGV0YV57Mn0kIGByIHBfcm91bmQoZ25nX2FjX3RbNyw3XSlgLgoKKipJbnRlcmFjdGlvbiBvZiBTbWFydHBob25lIExvY2F0aW9uLCBTbWFydHBob25lIFBvd2VyLCAmIEJhbGFuY2UqKiAgCgpUaGVyZSB3YXMgYSBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBiZXR3ZWVuIHNtYXJ0cGhvbmUgbG9jYXRpb24sIHNtYXJ0cGhvbmUgcG93ZXIsIGFuZCBiYWxhbmNlIChpLmUuIHdoaWNoIHRhc2sgd2FzIGNvbXBsZXRlZCBmaXJzdCkgb24gcmVhY3Rpb24gdGltZSwgKkYqKGByIGduZ19hY190WzgsMl1gLCBgciBnbmdfYWNfdFs4LDNdYCkgPSBgciByb3VuZChnbmdfYWNfdFs4LDRdLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19hY190WzgsNV0pYCwgJFxldGFeezJ9JCBgciBwX3JvdW5kKGduZ19hY190WzgsN10pYC4KCioqUG9zdC1ob2MgVGVzdHMqKiAgCgpTaW5jZSB0aGVyZSB3YXMgYSBzaWduaWZpY2FudCB0aHJlZS13YXkgaW50ZXJhY3Rpb24gKGkuZSBzbWFydHBob25lIGxvY2F0aW9uLCBzbWFydHBob25lIHBvd2VyLCBhbmQgYmFsYW5jZSksIGZ1cnRoZXIgYW5hbHlzZXMgd2VyZSBjb21wbGV0ZWQgKihzZWUgIlBvc3QtSG9jczogU2ltcGxlIFR3by1XYXkgSW50ZXJhY3Rpb25zIiBiZWxvdykqLiAgIAoKYGBge3J9CgojIGNyZWF0ZSBhIHRhYmxlIHdpdGggdGhlIGFub3ZhIHJlc3VsdHMgaW5jbHVkaW5nIHRoZSBjb3JyZWN0ZWQgdmFsdWVzIGZvciB0aGUgbWFpbiBlZmZlY3Qgb2YgcG93ZXIgKGkuZS4gc2luY2UgaXQgZGlkIG5vdCBtZWV0IHRoZSBob21vZ2VuZWl0eSBvZiB2YXJpYW5jZSBhc3N1bXB0aW9uKQogICMgZ2V0IHRoZSBvcmlnaW5hbCBhbm92YSBkYXRhCiAgZ25nX2FjX3QgPSBnbmdfYWNfYW5vdmEkQU5PVkEKICAgICMgc2luY2UgdGhlIGNvcnJlY3RlZCBkYXRhIGRvZXMgbm90IGhhdmUgdGhlIFNTLCByZW1vdmUgdGhlc2UgY29sdW1ucyBmcm9tIHRoZSBvcmlnaW5hbCBBTk9WQSB0YWJsZQogICAgZ25nX2FjX3QgPSBkcGx5cjo6c2VsZWN0KGduZ19hY190LCAtU1NuLCAtU1NkKQogICAgIyBjaGFuY2UgdGhlIGRhdGEgZm9yIHRoZSBtYWluIGVmZmVjdCBvZiBwb3dlciB0byBjb3JyZWN0ZWQgbnVtYmVycwogICAgZ25nX2FjX3RbZ25nX2FjX3QkRWZmZWN0ID09ICJwb3dlciIsXSA9IGMoZ25nX2FjX2Fub3ZhX2NvciRBTk9WQVszLF0sIGduZ19hY19wb3dfZXMpCiMgc2hvdyBBTk9WQSByZXN1bHRzIGluIGthYmxlIHRhYmxlIAprYWJsZShnbmdfYWNfdCwgY2FwdGlvbiA9ICIzeDJ4MiBBTk9WQSBvbiBHby9Oby1HbyBSZWFjdGlvbiBUaW1lIiwgZGlnaXRzID0gNCwgYWxpZ24gPSAnYycpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsICJob3ZlciIsIGZ1bGxfd2lkdGggPSBGKSAKCmBgYAoKCiMjIyMjIFBvc3QtSG9jczogU2ltcGxlIFR3by1XYXkgSW50ZXJhY3Rpb25zICAKCkEgdGhyZWUtd2F5IGludGVyYWN0aW9uIChpLmUuIGJldHdlZW4gc21hcnRwaG9uZSBsb2NhdGlvbiwgc21hcnRwaG9uZSBwb3dlciwgYW5kIGJhbGFuY2UpIHN1Z2dlc3RlZCB0aGF0IGEgdHdvLXdheSBpbnRlcmFjdGlvbiBvcGVyYXRlZCBkaWZmZXJlbnRseSBkZXBlbmRpbmcgb24gdGhlIGxldmVscyBvZiB0aGUgdGhpcmQgZmFjdG9yLiBJbiBvcmRlciB0byBpbnRlcnByZXQgdGhpcyBjb21wbGV4IGludGVyYWN0aW9uLCB0aGUgZGF0YSB3YXMgYnJva2VuIGRvd24gaW50byBhIHN1YnNldCBiYXNlZCBvbiB0aGUgbGV2ZWxzIG9mIG9uZSBvZiB0aGUgZmFjdG9ycyAoaS5lLiAic2ltcGxlIHR3by13YXkgaW50ZXJhY3Rpb25zIikuIAoKVGhlIG1haW4gbWFuaXB1bGF0aW9uIGluIHRoZSBwcmVzZW50IHN0dWR5IHdhcyBzbWFydHBob25lIGxvY2F0aW9uIGFuZCBwb3dlciwgYWRkaXRpb25hbGx5LCB0aGUgYmFsYW5jZSBmYWN0b3Igd2FzIGRlc2lnbmVkIHRvIHByb3ZpZGUgYW4gZXhwZXJpbWVudGFsIGNvbnRyb2wgZm9yIHRoZSBjb3VudGVyLWJhbGFuY2VkIHRhc2sgb3JkZXIuIFRoZXJlZm9yZSwgdGhlIHNpbXBsZSB0d28td2F5IGludGVyYWN0aW9ucyBvZiB0aGUgc21hcnRwaG9uZSBmYWN0b3JzIChpLmUuIGxvY2F0aW9uIGFuZCBwb3dlcikgd2VyZSBhc3Nlc3NlZCBhdCBlYWNoIGxldmVsIG9mIGJhbGFuY2UgKGkuZS4gT1NwYW4gZmlyc3QgYW5kIEdvL05vLUdvIGZpcnN0KS4gQWx0aG91Z2ggdGhpcyByZXF1aXJlZCB0d28gbW9yZSBhbmFseXNlcywgdGhpcyBhcHByb2FjaCBhbGxvd2VkIHVzIHRvIGRpc2VudGFuZ2xlIHRoZSB0aHJlZS13YXkgaW50ZXJhY3Rpb24gYW5kIHRoZXJlZm9yZSBpbnRlcnByZXQgd2hlcmUgdGhlIGRpZmZlcmVuY2VzIHdlcmUgYW1vbmcgdGhlIGZhY3RvcnMuIFR3byBuZXcgZGF0YSBzZXRzIHdlcmUgY3JlYXRlZCBmb3IgdGhlIHNpbXBsZSB0d28td2F5IGludGVyYWN0aW9uczogKDEpIGZvciB0aGUgT1NwYW4gRmlyc3QgRGF0YSAoKmduZ19hY19vc3Bhbl9kYXRhKikgYW5kICgyKSBmb3IgdGhlIEdvL05vLUdvIEZpcnN0IERhdGEgKCpnbmdfYWNfZ25nX2RhdGEqKS4KCmBgYHtyfQoKIyBnZXQgYSBzdWJzZXQgb2YgdGhlIGduZ19hY19hbm92YV9kYXRhCiAgIyBmb3IgdGhlIE9TcGFuIGZpcnN0IGJhbGFuY2UgZ3JvdXAgb25seQogIGduZ19hY19vc3Bhbl9kYXRhID0gZ25nX2FjX2Fub3ZhX2RhdGFbZ25nX2FjX2Fub3ZhX2RhdGEkYmFsYW5jZSA9PSAiT3NwYW4gRmlyc3QiLCBdCgogICMgZm9yIHRoZSBHby9Oby1HbyBmaXJzdCBiYWxhbmNlIGdyb3VwIG9ubHkKICBnbmdfYWNfZ25nX2RhdGEgPSBnbmdfYWNfYW5vdmFfZGF0YVtnbmdfYWNfYW5vdmFfZGF0YSRiYWxhbmNlID09ICJHby9Oby1HbyBGaXJzdCIsIF0KCmBgYAoKCkluIG9yZGVyIHRvIGNvbnRyb2wgZm9yIG11bHRpcGxlIGNvbXBhcmlzb25zLCBhIEJvbmZlcnJvbmkgYWRqdXN0bWVudCB3YXMgdXNlZCBvbiB0aGUgcC12YWx1ZXMgdG8gZGV0ZXJtaW5lIHNpZ25pZmljYW5jZS4gVGhpcyBhZGp1c3RtZW50IHdhcyBjb21wbGV0ZWQgYnkgZGl2aWRpbmcgdGhlIGN1cnJlbnQgYWxwaGEgbGV2ZWwgKCRcYWxwaGEgPSAwLjA1JCkgYnkgdGhlIG51bWJlciBvZiBzaW1wbGUgdHdvLXdheSBpbnRlcmFjdGlvbnMgYmVpbmcgY29tcHVldGQgKGkuZS4gMiksIHRoZXJlZm9yZSwgdGhlIHRoZSBib25mZXJyb25pLWNvcnJlY3RlZCBhbHBoYSB2YWx1ZSBmb3Igc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlIHdhcyBgciAwLjA1LzJgLgoKCiMjIyMjIyBPU3BhbiBGaXJzdDogRGVzY3JpcHRpdmUgU3RhdGlzdGljcyAKClRoZSBmaXJzdCBzaW1wbGUgdHdvLXdheSBpbnRlcmFjdGlvbiBBTk9WQSB3YXMgY29tcGxldGVkIHVzaW5nIHRoZSAiT1NwYW4gRmlyc3QiIHN1YnNldCBvZiB0aGUgQmFsYW5jZSBGYWN0b3IgKGkuZS4gcGFydGljaXBhbnRzIHdobyBjb21wbGV0ZWQgdGhlIE9TcGFuIHRhc2sgZmlyc3QsIHRoZW4gdGhlIEdvL05vLUdvIHRhc2spLiBBcyBpbiB0aGUgbWFpbiAzLXdheSBBTk9WQSwgdGhlIGJldHdlZW4tc3ViamVjdHMgZmFjdG9ycyB3ZXJlIHNtYXJ0cGhvbmUgbG9jYXRpb24gKGkuZS4gZGVzaywgcG9ja2V0L2JhZyBvciBvdXRzaWRlKSBhbmQgcG93ZXIgKGkuZS4gT04gb3IgT0ZGKSwgYW5kIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgd2FzIGFjY3VyYWN5IChpLmUuIGF2ZXJhZ2UgcmVhY3Rpb24gdGltZSkuCgpUaGVyZSB3YXMgYSB0b3RhbCBvZiBgciBsZW5ndGgoZ25nX2FjX29zcGFuX2RhdGEkcGFydGljaXBhbnQpYCBwYXJ0aWNpcGFudHMgaW4gdGhlIE9TcGFuIEZpcnN0IGFuYWx5c2lzLiBUaGUgZm9sbG93aW5nIHRhYmxlIGRlcGljdHMgdGhlIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3M6IHRoZSBtZWFuICgqTSopLCBzdGFuZGFyZCBkZXZpYXRpb24gKCpTRCopLCBtaW5pbXVtIHNjb3JlICgqbWluLiopLCBtYXhpbXVtIHNjb3JlICgqbWF4LiopLCBhbmQgdGhlIHNhbXBsZSBzaXplICgqbiopLiAgCgpgYGB7cn0KCiMgY3JlYXRlIGEgZGF0YSBmcmFtZSB3aXRoIHRoZSBkZXNjcmlwdGl2ZXMgb2YgYWxsIHRoZSBkYXRhLCBncm91cGVkIGJ5IHRoZSBsb2NhdGlvbiAmIHBvd2VyIGNvbmRpdGlvbnMKICAjIHRoaXMgY3JlYXRlcyBpbmZvcm1hdGlvbiBmb3IgdGhlIDYgcG9zc2libGUgY29tYmluZWQgY29uZGl0aW9ucwogIGduZ19hY19vc3Bhbl9kZXMgPSBwc3ljaDo6ZGVzY3JpYmVCeShnbmdfYWNfb3NwYW5fZGF0YSwgbGlzdChnbmdfYWNfb3NwYW5fZGF0YSRsb2NhdGlvbiwgZ25nX2FjX29zcGFuX2RhdGEkcG93ZXIpLCBtYXQgPSBUUlVFKSAgCgojIG9yZ2FuaXplIHRoZSBkYXRhIGludG8gYSBuZXcgZGF0YSBmcmFtZSBkZXBpY3RpbmcgdGhlIE0sIFNELCBtaW4uLCBtYXguLCBhbmQgbi4KICBnbmdfYWNfb3NwYW5fZGVzX3QgPSByYmluZCgoY2JpbmQodChnbmdfYWNfb3NwYW5fZGVzWyJydF9hdjEiLCBjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChnbmdfYWNfb3NwYW5fZGVzWyJydF9hdjIiLCBjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChnbmdfYWNfb3NwYW5fZGVzWyJydF9hdjMiLCBjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSkpKSwgCiAgICAgICAgICAgICAgICAgICAgICAoY2JpbmQodChnbmdfYWNfb3NwYW5fZGVzWyJydF9hdjQiLCBjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChnbmdfYWNfb3NwYW5fZGVzWyJydF9hdjUiLCBjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChnbmdfYWNfb3NwYW5fZGVzWyJydF9hdjYiLCBjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSkpKSkKICAgIGNvbG5hbWVzKGduZ19hY19vc3Bhbl9kZXNfdCkgPSBjKCJPbiBEZXNrIiwgIkluIFBvY2tldC9CYWciLCAiT3V0c2lkZSIpCiAgICByb3duYW1lcyhnbmdfYWNfb3NwYW5fZGVzX3QpID0gcmVwKGMoIk0iLCAiU0QiLCAibWluLiIsICJtYXguIiwgIm4iKSwgMikKICAKIyB1c2Uga2FibGUgdG8gc2hvdyB0aGUgZGVzY3JpcHRpdmVzIHRhYmxlCiAga2FibGUoZ25nX2FjX29zcGFuX2Rlc190LCBjYXB0aW9uID0gIk9zcGFuIEZpcnN0IERlc2NyaXB0aXZlIFN0YXRpc3RpY3M6IFJlYWN0aW9uIFRpbWUgKHNlYy4pIG9uIHRoZSBHby9Oby1HbyBUYXNrIiwgZGlnaXRzID0gNCwgYWxpZ24gPSAnYycpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsICJob3ZlciIsIGZ1bGxfd2lkdGggPSBGKSAlPiUKICBhZGRfaGVhZGVyX2Fib3ZlKGMoIiAiLCAiU21hcnRwaG9uZSBMb2NhdGlvbiIgPSAzKSkgJT4lCiAgZ3JvdXBfcm93cyhpbmRleCA9IGMoIlNtYXJ0cGhvbmUgUG93ZXIgT04iID0gNSwgIlNtYXJ0cGhvbmUgUG93ZXIgT0ZGIiA9IDUpKQoKYGBgCgoKIyMjIyMjIE9TcGFuIEZpcnN0OiBBc3N1bXB0aW9ucyAgCgo8ZGV0YWlscz4gIAo8c3VtbWFyeT4gVGhlIHR3by13YXkgaW50ZXJhY3Rpb24gbWFkZSB0aHJlZSBhc3N1bXB0aW9ucy4gVGhlIGluZGVwZW5kZW50IHJhbmRvbSBzYW1wbGluZyBhbmQgbm9ybWFsaXR5IGFzc3VtcHRpb25zIHdlcmUgbWV0LiBUaGUgaG9tb2dlbmVpdHkgb2YgdmFyaWFuY2UgYXNzdW1wdGlvbiB3YXMgbm90IG1ldCwgdGhlcmVmb3JlLCBhIFdoaXRlIGNvcnJlY3Rpb24gd2FzIGRvbmUgZm9yIHRoZSByZWxldmFudCBlZmZlY3QuICooY2xpY2sgdG8gc2VlIGRldGFpbHMpKi4gPC9zdW1tYXJ5PiAgCgo8c3BhbiBzdHlsZT0iY29sb3I6RGFya0JsdWU7IGZvbnQtc2l6ZToxOHB4OyI+MS4gSW5kZXBlbmRlbnQgUmFuZG9tIFNhbXBsaW5nPC9zcGFuPiAgCgpUaGlzIGFzc3VtcHRpb24gd2FzIG1ldCBkdXJpbmcgdGVzdGluZy4gIAogICAgCjxzcGFuIHN0eWxlPSJjb2xvcjpEYXJrQmx1ZTsgZm9udC1zaXplOjE4cHg7Ij4yLiBOb3JtYWxpdHk8L3NwYW4+ICAKClRoaXMgYXNzdW1wdGlvbiB3YXMgdGVzdGVkIGJ5IHZpc3VhbGl6aW5nIHRoZSByZXNpZHVhbHMsIGFwcGx5aW5nIGEgU2hhcGlyby1XaWxrIHRlc3QgdG8gdGhlIHJlc2RpdWFscywgYW5kIG9ic2VydmluZyB0aGUgU2tld25lc3MgYW5kIEt1cnRvc2lzIG9mIHRoZSBkYXRhICooZXh0cmFjdGVkIGZyb20gdGhlIEFOT1ZBIG91dHB1dCkuKiAgCiAgICAKYGBge3IgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBydW4gYmV0d2Vlbi1zdWJqZWN0cyBBTk9WQSAoSVY6IFNtYXJ0cGhvbmUgUG93ZXIgJiBMb2NhdGlvbjsgRFY6IE9TcGFuIEFib2x1dGUgU2NvcmUpCmduZ19hY19vc3Bhbl9hbm92YSA9IGV6QU5PVkEoCiAgZGF0YSA9IGduZ19hY19vc3Bhbl9kYXRhCiAgLCBkdiA9IC4ocnRfYXYpCiAgLCB3aWQgPSAuKHBhcnRpY2lwYW50KQogICwgYmV0d2VlbiA9IC4obG9jYXRpb24sIHBvd2VyKQogICwgdHlwZSA9IDMgIyB1bmVxdWFsIHNhbXBsZSBzaXplcywgdGhlcmZvcmUgdXNlIHR5cGUgMwogICwgZGV0YWlsZWQgPSBUUlVFCiAgLCByZXR1cm5fYW92ID0gVFJVRQogICkKICAKIyBjYWxjdWxhdGUgJiBleHRyYWN0IHRoZSByZXNpZHVhbHMgZnJvbSB0aGUgQU5PVkEKZ25nX2FjX29zcGFuX3JlcyA9IGRhdGEuZnJhbWUoInJlc2lkdWFscyIgPSBwcm9qKGduZ19hY19vc3Bhbl9hbm92YSRhb3YpWywiUmVzaWR1YWxzIl0pICAKCmBgYAogICAgCi0gSXQgYXBwZWFycyB0aGF0IHRoZSByZXNpZHVhbHMgbGllIGNsb3NlbHkgdG8gYSBzdHJhaWdodCBsaW5lLCB3aGljaCBzdWdnZXN0cyBub3JtYWxpdHkgKihzZWUgdmlzdWFsaXphdGlvbiBiZWxvdykqLgogICAgCmBgYHtyfQoKcXFub3JtKGduZ19hY19vc3Bhbl9yZXMkcmVzaWR1YWxzLCBtYWluID0gIlEtUSBQbG90IG9mIHRoZSBHby9Oby1HbyBSZWFjdGlvbiBUaW1lIFJlc2lkdWFscyBmb3IgdGhlIE9TcGFuIEZpcnN0IEdyb3VwIikgCnFxbGluZShnbmdfYWNfb3NwYW5fcmVzJHJlc2lkdWFscykKCmBgYAogICAgCi0gSXQgYXBwZWFycyB0aGF0IHJlc2lkdWFscyB0ZW5kIHRvIGZvbGxvdyB0aGUgc2hhcGUgb2YgYSBub3JtYWwgZGlzdHJpYnV0aW9uICooc2VlIHZpc3VhbGl6YXRpb24gYmVsb3cpKi4KICAgIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKcXBsb3QoZ25nX2FjX29zcGFuX3JlcyRyZXNpZHVhbHMsIG1haW4gPSAiSGlzdG9ncmFtIG9mIEdvL05vLUdvIFJlYWN0aW9uIFRpbWUgUmVzaWR1YWxzIGZvciB0aGUgT1NwYW4gRmlyc3QgR3JvdXAiKSArIAogIHRoZW1lX2NsYXNzaWMoKQoKYGBgCiAgIAotIFRoZSBTaGFwaXJvLVdpbGsgdGVzdCBvZiBub3JtYWxpdHkgd2FzIHNpZ25pZmljYW50IChiYXNlZCBvbiAkXGFscGhhID0gMC4wNSQpLCAqVyogPSBgciByb3VuZChhcy5udW1lcmljKGduZ19hY19vc3Bhbl9zaGFwJHN0YXRpc3RpY1siVyJdKSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfYWNfb3NwYW5fc2hhcCRwLnZhbHVlKWAgKihzZWUgY29kZSBiZWxvdykqLiAgCiAgIApgYGB7cn0KCmduZ19hY19vc3Bhbl9zaGFwID0gc2hhcGlyby50ZXN0KGduZ19hY19vc3Bhbl9yZXMkcmVzaWR1YWxzKQpnbmdfYWNfb3NwYW5fc2hhcAoKYGBgCgotIFRoZSBkYXRhJ3MgU2tld25lc3MgYW5kIEt1cnRvc2lzIHdhcyBleGFtaW5lZCBhbmQgc2hvd2VkIHRoYXQgYm90aCB0aGUgU2tld25lc3MgKHJhbmdlOiBgciByb3VuZChtaW4oYXMubnVtZXJpYyhnbmdfYWNfb3NwYW5fc2tfdFtjKDEsNCksXSkpLCAyKWAgdG8gYHIgcm91bmQobWF4KGFzLm51bWVyaWMoZ25nX2FjX29zcGFuX3NrX3RbYygxLDQpLF0pKSwgMilgKSBhbmQgS3VydG9zaXMgKHJhbmdlOiBgciByb3VuZChtaW4oYXMubnVtZXJpYyhnbmdfYWNfb3NwYW5fc2tfdFtjKDIsNSksXSkpLCAyKWAgdG8gYHIgcm91bmQobWF4KGFzLm51bWVyaWMoZ25nX2FjX29zcGFuX3NrX3RbYygyLDUpLF0pKSwgMilgKSB3ZXJlIHdpdGhpbiB0aGUgYWNjZXB0YWJsZSByYW5nZSBvZiAkXHBtIDIuMCQgYW5kICRccG0gOS4wJCwgcmVzcGVjdGl2ZWx5IChTY2htaWRlciwgWmllZ2xlciwgRGFuYXksIEJleWVyLCAmIELDvGhuZXIsIDIwMTApICooc2VlIHRhYmxlIGJlbG93KSouICAKCmBgYHtyfQoKIyB1c2UgdGhlIGRlc2NyaXB0aXZlcyBkYXRhIC0tIGduZ19hY19vc3Bhbl9kZXMKCiMgb3JnYW5pemUgdGhlIGRhdGEgaW50byBhIG5ldyBkYXRhIGZyYW1lIGRlcGljdGluZyB0aGUgU2tldywga3VydG9zaXMsIGFuZCBzYW1wbGUgc2l6ZSAobikuCiAgZ25nX2FjX29zcGFuX3NrX3QgPSByYmluZCgoY2JpbmQodChnbmdfYWNfb3NwYW5fZGVzWyJydF9hdjEiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2FjX29zcGFuX2Rlc1sicnRfYXYyIiwgYygic2tldyIsICJrdXJ0b3NpcyIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0KGduZ19hY19vc3Bhbl9kZXNbInJ0X2F2MyIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSkpKSwgCiAgICAgICAgICAgICAgICAgICAgICAoY2JpbmQodChnbmdfYWNfb3NwYW5fZGVzWyJydF9hdjQiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2FjX29zcGFuX2Rlc1sicnRfYXY1IiwgYygic2tldyIsICJrdXJ0b3NpcyIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0KGduZ19hY19vc3Bhbl9kZXNbInJ0X2F2NiIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSkpKSkKICAgIGNvbG5hbWVzKGduZ19hY19vc3Bhbl9za190KSA9IGMoIk9uIERlc2siLCAiSW4gUG9ja2V0L0JhZyIsICJPdXRzaWRlIikKICAgIHJvd25hbWVzKGduZ19hY19vc3Bhbl9za190KSA9IHJlcChjKCJTa2V3bmVzcyIsICJLdXJ0b3NpcyIsICJuIiksIDIpCiAgICAKIyB1c2Uga2FibGUgdG8gc2hvdyB0aGUgZGVzY3JpcHRpdmVzIHRhYmxlCiAga2FibGUoZ25nX2FjX29zcGFuX3NrX3QsIGNhcHRpb24gPSAiU2tld25lc3MgYW5kIEt1cnRvc2lzIG9mIHRoZSBSZWFjdGlvbiBUaW1lIG9uIHRoZSBHby9Oby1HbyBUYXNrIGZvciB0aGUgT1NwYW4gRmlyc3QgR3JvdXAiLCBkaWdpdHMgPSA0LCBhbGlnbiA9ICdjJykgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpICU+JQogIGFkZF9oZWFkZXJfYWJvdmUoYygiICIsICJTbWFydHBob25lIExvY2F0aW9uIiA9IDMpKSAlPiUKICBncm91cF9yb3dzKGluZGV4ID0gYygiU21hcnRwaG9uZSBQb3dlciBPTiIgPSAzLCAiU21hcnRwaG9uZSBQb3dlciBPRkYiID0gMykpCgpgYGAKCi0gVGhlcmVmb3JlLCBiYXNlZCBvbiBhbGwgdGhlIG5vcm1hbGl0eSBhc3N1bXB0aW9uIGNoZWNrcywgbm9ybWFsaXR5IHdhcyBhc3N1bWVkIHRvIGJlIHdpdGhpbiB0aGUgYWNjZXB0YWJsZSByYW5nZSBmb3IgdGhlIGFuYWx5c2lzLiBBZGRpdGlvbmFsbHksIGl0IHNob3VsZCBiZSBub3RlZCB0aGF0IEFOT1ZBIGFuYWx5c2VzIGNhbiBiZSByb2J1c3QgdG8gdmlvbGF0aW9ucyBvZiBub3JtYWxpdHkgKEdhcmRuZXIgJiBUcmVtYmxheSwgMjAwNykuCgo8c3BhbiBzdHlsZT0iY29sb3I6RGFya0JsdWU7IGZvbnQtc2l6ZToxOHB4OyI+My4gSG9tb2dlbmVpdHkgb2YgVmFyaWFuY2U8L3NwYW4+IAoKVGhpcyBhc3N1bXB0aW9uIHdhcyB0ZXN0ZWQgYnkgY29uZHVjdGluZyBMZXZlbmUncyBUZXN0IGZvciBIb21vZ2VuZWl0eSBvZiBWYXJpYW5jZSBmb3IgZWFjaCBiZXR3ZWVuLXN1YmplY3RzIHZhcmlhYmxlIChpLmUuIHNtYXJ0cGhvbmUgbG9jYXRpb24gYW5kIHNtYXJ0cGhvbmUgcG93ZXIpLiAgCgotIFRoZSBob21vZ2VuZWl0eSBhc3N1bXB0aW9uIHdhcyBtZXQgKGJhc2VkIG9uICRcYWxwaGEgPSAwLjA1JCkgZm9yIHNtYXJ0cGhvbmUgcG93ZXIsICpGKihgciBnbmdfYWNfb3NwYW5fbGV2X3BvdyREZlsxXWAsIGByIGduZ19hY19vc3Bhbl9sZXZfcG93JERmWzJdYCkgPSBgciByb3VuZChnbmdfYWNfb3NwYW5fbGV2X3Bvd1syXVsxLDFdLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19hY19vc3Bhbl9sZXZfcG93WzNdWzEsMV0pYC4gSG93ZXZlciwgdGhlIGhvbW9nZW5laXR5IGFzc3VtcHRpb24gd2FzIG5vdCBtZXQgZm9yIHNtYXJ0cGhvbmUgbG9jYXRpb24sICpGKihgciBnbmdfYWNfb3NwYW5fbGV2X2xvYyREZlsxXWAsIGByIGduZ19hY19vc3Bhbl9sZXZfbG9jJERmWzJdYCkgPSBgciByb3VuZChnbmdfYWNfb3NwYW5fbGV2X2xvY1syXVsxLDFdLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19hY19vc3Bhbl9sZXZfbG9jWzNdWzEsMV0pYCAqKHNlZSBjb2RlIGJlbG93KSouCgpgYGB7cn0KCiMgY29uZHVjdCBsZXZlbmUncwogICMgZm9yIGxvY2F0aW9uCiAgZ25nX2FjX29zcGFuX2xldl9sb2MgPSBsZXZlbmVUZXN0KGRhdGEgPSBnbmdfYWNfb3NwYW5fZGF0YSwgcnRfYXYgfiBhcy5mYWN0b3IobG9jYXRpb24pLCBjZW50ZXIgPSBtZWRpYW4pCiAgZ25nX2FjX29zcGFuX2xldl9sb2MKICAjIGZvciBwb3dlcgogIGduZ19hY19vc3Bhbl9sZXZfcG93ID0gbGV2ZW5lVGVzdChkYXRhID0gZ25nX2FjX29zcGFuX2RhdGEsIHJ0X2F2IH4gYXMuZmFjdG9yKHBvd2VyKSwgY2VudGVyID0gbWVkaWFuKQogIGduZ19hY19vc3Bhbl9sZXZfcG93CgpgYGAKCi0gVGhlIGhvbW9nZW5laXR5IG9mIHZhcmlhbmNlIGFzc3VtcHRpb24gd2FzIG5vdCBtZXQgZm9yIHRoZSBzbWFydHBob25lIGxvY2F0aW9uIGNvbmRpdGlvbi4gVGhlcmVmb3JlLCBjb25zaWRlcmluZyB0aGVyZSB3ZXJlIHVuZXF1YWwgc2FtcGxlIHNpemVzLCBhIFdoaXRlLWNvcnJlY3RlZCBGLXRlc3Qgd2FzIGNvbmR1Y3RlZCAoaS5lLiBpZiBpbnRlcmVzdGVkIGluIGFzc2Vzc2luZyB0aGUgbWFpbiBlZmZlY3Qgb2YgbG9jYXRpb24pLgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBydW4gdGhlIGNvcnJlY3RlZCBBTk9WQSAoSVY6IFNtYXJ0cGhvbmUgUG93ZXIgJiBMb2NhdGlvbjsgRFY6IEdvL05vLUdvIFJUKQojIHRoaXMgd2lsbCBiZSB1c2VkIHRvIHJlcG9ydCB0aGUgbWFpbiBlZmZlY3Qgb2Ygc21hcnRwaG9uZSBwb3dlciBvbmx5ICAKZ25nX2FjX29zcGFuX2Fub3ZhX2NvciA9IGV6QU5PVkEoCiAgZGF0YSA9IGduZ19hY19vc3Bhbl9kYXRhCiAgLCBkdiA9IC4ocnRfYXYpCiAgLCB3aWQgPSAuKHBhcnRpY2lwYW50KQogICwgYmV0d2VlbiA9IC4obG9jYXRpb24sIHBvd2VyKQogICwgdHlwZSA9IDMgIyB1bmVxdWFsIHNhbXBsZSBzaXplcywgdGhlcmZvcmUgdXNlIHR5cGUgMwogICwgZGV0YWlsZWQgPSBUUlVFCiAgLCByZXR1cm5fYW92ID0gVFJVRQogICwgd2hpdGUuYWRqdXN0ID0gVFJVRQopCgojIENhbGN1bGF0ZSBlZmZlY3Qgc2l6ZToKIyB0aGlzIHdpbGwgYmUgdXNlZCB0byByZXBvcnQgdGhlIG1haW4gZWZmZWN0IG9mIHNtYXJ0cGhvbmUgcG93ZXIgb25seSAKZ25nX2FjX29zcGFuX2xvY19lcyA9IChFdGFTcShnbmdfYWNfb3NwYW5fYW5vdmFfY29yJGFvdiwgdHlwZSA9IDMsIGFub3ZhID0gRkFMU0UpKVsyXQoKYGBgCgo8L2RldGFpbHM+ICAKCiMjIyMjIyBPU3BhbiBGaXJzdDogUmVzdWx0cyAgCgpBbGwgcmVzdWx0cyB3ZXJlIGJhc2VkIG9uICRcYWxwaGFfe2FkanVzdGVkfSA9IDAuMDI1JC4gQmVsb3cgYXJlIHRoZSByZXBvcnRlZCBzdGF0aXN0aWNzIGZvciB0aGUgbWFpbiBhbmQgaW50ZXJhY3Rpb24gZWZmZWN0IG9mIHRoZSBzaW1wbGUgdHdvLXdheSBBTk9WQSwgZm9sbG93ZWQgYnkgYSB0YWJsZSBkZXBpY3RpbmcgdGhlIEFOT1ZBIHJlc3VsdHMuCgoqKk1haW4gRWZmZWN0IG9mIFNtYXJ0cGhvbmUgTG9jYXRpb24qKiAgCgpUaGVyZSB3YXMgbm8gc2lnbmlmaWNhbnQgbWFpbiBlZmZlY3Qgb2Ygc21hcnRwaG9uZSBsb2NhdGlvbiBvbiByZWFjdGlvbiB0aW1lLCAqRiooYHIgZ25nX2FjX29zcGFuX3RbMiwyXWAsIGByIGduZ19hY19vc3Bhbl90WzIsM11gKSA9IGByIHJvdW5kKGduZ19hY19vc3Bhbl90WzIsNF0sIDIpYCwgKnAqIGByIHBfcm91bmQoZ25nX2FjX29zcGFuX3RbMiw1XSlgLCAkXGV0YV57Mn0kIGByIHBfcm91bmQoZ25nX2FjX29zcGFuX3RbMiw3XSlgLgoKKipNYWluIEVmZmVjdCBvZiBTbWFydHBob25lIFBvd2VyKiogIAoKVGhlcmUgd2FzIG5vIHNpZ25pZmljYW50IG1haW4gZWZmZWN0IG9mIHNtYXJ0cGhvbmUgcG93ZXIgb24gcmVhY3Rpb24gdGltZSwgKkYqKGByIGduZ19hY19vc3Bhbl90WzMsMl1gLCBgciBnbmdfYWNfb3NwYW5fdFszLDNdYCkgPSBgciByb3VuZChnbmdfYWNfb3NwYW5fdFszLDRdLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19hY19vc3Bhbl90WzMsNV0pYCwgJFxldGFeezJ9JCBgciBwX3JvdW5kKGduZ19hY19vc3Bhbl90WzMsN10pYC4KCioqSW50ZXJhY3Rpb24gb2YgU21hcnRwaG9uZSBMb2NhdGlvbiAmIFNtYXJ0cGhvbmUgUG93ZXIqKiAgCgpUaGVyZSB3YXMgbm8gc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gYmV0d2VlbiBzbWFydHBob25lIGxvY2F0aW9uIGFuZCBzbWFydHBob25lIHBvd2VyIG9uIHJlYWN0aW9uIHRpbWUsICpGKihgciBnbmdfYWNfb3NwYW5fdFs0LDJdYCwgYHIgZ25nX2FjX29zcGFuX3RbNCwzXWApID0gYHIgcm91bmQoZ25nX2FjX29zcGFuX3RbNCw0XSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfYWNfb3NwYW5fdFs0LDVdKWAsICRcZXRhXnsyfSQgYHIgcF9yb3VuZChnbmdfYWNfb3NwYW5fdFs0LDddKWAuCgoqKlBvc3QtaG9jIFRlc3RzKiogIAoKU2luY2UgdGhlcmUgd2FzIG5vIHNpZ25pZmljYW50IG1haW4gb3IgaW50ZXJhY3Rpb24gZWZmZWN0cywgbm8gcG9zdC1ob2NzIHdlcmUgY29tcGxldGVkLgoKCmBgYHtyfQoKIyBjcmVhdGUgYSB0YWJsZSB3aXRoIHRoZSBhbm92YSByZXN1bHRzIGluY2x1ZGluZyB0aGUgY29ycmVjdGVkIHZhbHVlcyBmb3IgdGhlIG1haW4gZWZmZWN0IG9mIHBvd2VyIChpLmUuIHNpbmNlIGl0IGRpZCBub3QgbWVldCB0aGUgaG9tb2dlbmVpdHkgb2YgdmFyaWFuY2UgYXNzdW1wdGlvbikKICAjIGdldCB0aGUgb3JpZ2luYWwgYW5vdmEgZGF0YQogIGduZ19hY19vc3Bhbl90ID0gZ25nX2FjX29zcGFuX2Fub3ZhJEFOT1ZBCiAgICAjIHNpbmNlIHRoZSBjb3JyZWN0ZWQgZGF0YSBkb2VzIG5vdCBoYXZlIHRoZSBTUywgcmVtb3ZlIHRoZXNlIGNvbHVtbnMgZnJvbSB0aGUgb3JpZ2luYWwgQU5PVkEgdGFibGUKICAgIGduZ19hY19vc3Bhbl90ID0gZHBseXI6OnNlbGVjdChnbmdfYWNfb3NwYW5fdCwgLVNTbiwgLVNTZCkKICAgICMgY2hhbmdlIHRoZSBkYXRhIGZvciB0aGUgbWFpbiBlZmZlY3Qgb2YgbG9jYXRpb24gdG8gY29ycmVjdGVkIG51bWJlcnMKICAgIGduZ19hY19vc3Bhbl90W2duZ19hY19vc3Bhbl90JEVmZmVjdCA9PSAibG9jYXRpb24iLF0gPSBjKGduZ19hY19vc3Bhbl9hbm92YV9jb3IkQU5PVkFbMixdLCBnbmdfYWNfb3NwYW5fbG9jX2VzKQogICAgIyByZS1kZWZpbmUgdGhlIGFscGhhIHZhbHVlIGJhc2VkIG9uIHRoZSBib25mZXJyb25pIGNvcnJlY3Rpb24KICAgICAgIyByZW5hbWUgdGhlICJwPC4wNSIgY29sdW1uIGFwcHJvcHJpYXRlbHkgLS0gInA8LjAyNSIKICAgICAgY29sbmFtZXMoZ25nX2FjX29zcGFuX3QpWzZdID0gInA8LjAyNSIKICAgICAgIyBjaGFuZ2UgdmFsdWVzIHRvIGZpdCB0aGUgZGF0YQogICAgICBnbmdfYWNfb3NwYW5fdCRgcDwuMDI1YCA9IGlmZWxzZShnbmdfYWNfb3NwYW5fdCRwIDwgLjAyNSwgIioiLCAiIikKICAgIAojIHNob3cgQU5PVkEgcmVzdWx0cyBpbiBrYWJsZSB0YWJsZSAKa2FibGUoZ25nX2FjX29zcGFuX3QsIGNhcHRpb24gPSAiT1NwYW4gRmlyc3Q6IFNpbXBsZSBUd28tV2F5IEludGVyYWN0aW9uIG9uIFJlYWN0aW9uIFRpbWUgb24gdGhlIEdvL05vLUdvIFRhc2siLCBkaWdpdHMgPSA0LCBhbGlnbiA9ICdjJykgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpIAoKYGBgCgoKIyMjIyMjIEdvL05vLUdvIEZpcnN0OiBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzICAKClRoZSBzZWNvbmQgc2ltcGxlIHR3by13YXkgaW50ZXJhY3Rpb24gQU5PVkEgd2FzIGNvbXBsZXRlZCB1c2luZyB0aGUgIkdvL05vLUdvIEZpcnN0IiBzdWJzZXQgb2YgdGhlIEJhbGFuY2UgRmFjdG9yIChpLmUuIHBhcnRpY2lwYW50cyB3aG8gY29tcGxldGVkIHRoZSBHby9Oby1HbyB0YXNrIGZpcnN0LCB0aGVuIHRoZSBPU3BhbiB0YXNrKS4gQXMgaW4gdGhlIG1haW4gMy13YXkgQU5PVkEsIHRoZSBiZXR3ZWVuLXN1YmplY3RzIGZhY3RvcnMgd2VyZSBzbWFydHBob25lIGxvY2F0aW9uIChpLmUuIGRlc2ssIHBvY2tldC9iYWcgb3Igb3V0c2lkZSkgYW5kIHBvd2VyIChpLmUuIE9OIG9yIE9GRiksIGFuZCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIHdhcyBhY2N1cmFjeSAoaS5lLiBhdmVyYWdlIHJlYWN0aW9uIHRpbWUpLgoKVGhlcmUgd2FzIGEgdG90YWwgb2YgYHIgbGVuZ3RoKGduZ19hY19nbmdfZGF0YSRwYXJ0aWNpcGFudClgIHBhcnRpY2lwYW50cyBpbiB0aGUgR28vTm8tR28gRmlyc3QgYW5hbHlzaXMuIFRoZSBmb2xsb3dpbmcgdGFibGUgZGVwaWN0cyB0aGUgZGVzY3JpcHRpdmUgc3RhdGlzdGljczogdGhlIG1lYW4gKCpNKiksIHN0YW5kYXJkIGRldmlhdGlvbiAoKlNEKiksIG1pbmltdW0gc2NvcmUgKCptaW4uKiksIG1heGltdW0gc2NvcmUgKCptYXguKiksIGFuZCB0aGUgc2FtcGxlIHNpemUgKCpuKikuICAKCmBgYHtyfQoKIyBjcmVhdGUgYSBkYXRhIGZyYW1lIHdpdGggdGhlIGRlc2NyaXB0aXZlcyBvZiBhbGwgdGhlIGRhdGEsIGdyb3VwZWQgYnkgdGhlIGxvY2F0aW9uICYgcG93ZXIgY29uZGl0aW9ucwogICMgdGhpcyBjcmVhdGVzIGluZm9ybWF0aW9uIGZvciB0aGUgNiBwb3NzaWJsZSBjb21iaW5lZCBjb25kaXRpb25zCiAgZ25nX2FjX2duZ19kZXMgPSBwc3ljaDo6ZGVzY3JpYmVCeShnbmdfYWNfZ25nX2RhdGEsIGxpc3QoZ25nX2FjX2duZ19kYXRhJGxvY2F0aW9uLCBnbmdfYWNfZ25nX2RhdGEkcG93ZXIpLCBtYXQgPSBUUlVFKSAgCgojIG9yZ2FuaXplIHRoZSBkYXRhIGludG8gYSBuZXcgZGF0YSBmcmFtZSBkZXBpY3RpbmcgdGhlIE0sIFNELCBtaW4uLCBtYXguLCBhbmQgbi4KICBnbmdfYWNfZ25nX2Rlc190ID0gcmJpbmQoKGNiaW5kKHQoZ25nX2FjX2duZ19kZXNbInJ0X2F2MSIsIGMoIm1lYW4iLCAic2QiLCAibWluIiwgIm1heCIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0KGduZ19hY19nbmdfZGVzWyJydF9hdjIiLCBjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChnbmdfYWNfZ25nX2Rlc1sicnRfYXYzIiwgYygibWVhbiIsICJzZCIsICJtaW4iLCAibWF4IiwgIm4iKV0pKSksIAogICAgICAgICAgICAgICAgICAgICAgKGNiaW5kKHQoZ25nX2FjX2duZ19kZXNbInJ0X2F2NCIsIGMoIm1lYW4iLCAic2QiLCAibWluIiwgIm1heCIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0KGduZ19hY19nbmdfZGVzWyJydF9hdjUiLCBjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChnbmdfYWNfZ25nX2Rlc1sicnRfYXY2IiwgYygibWVhbiIsICJzZCIsICJtaW4iLCAibWF4IiwgIm4iKV0pKSkpCiAgICBjb2xuYW1lcyhnbmdfYWNfZ25nX2Rlc190KSA9IGMoIk9uIERlc2siLCAiSW4gUG9ja2V0L0JhZyIsICJPdXRzaWRlIikKICAgIHJvd25hbWVzKGduZ19hY19nbmdfZGVzX3QpID0gcmVwKGMoIk0iLCAiU0QiLCAibWluLiIsICJtYXguIiwgIm4iKSwgMikKICAKIyB1c2Uga2FibGUgdG8gc2hvdyB0aGUgZGVzY3JpcHRpdmVzIHRhYmxlCiAga2FibGUoZ25nX2FjX2duZ19kZXNfdCwgY2FwdGlvbiA9ICJHby9Oby1HbyBGaXJzdCBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzOiBSZWFjdGlvbiBUaW1lIChzZWMuKSBvbiB0aGUgR28vTm8tR28gVGFzayIsIGRpZ2l0cyA9IDQsIGFsaWduID0gJ2MnKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCAiaG92ZXIiLCBmdWxsX3dpZHRoID0gRikgJT4lCiAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiwgIlNtYXJ0cGhvbmUgTG9jYXRpb24iID0gMykpICU+JQogIGdyb3VwX3Jvd3MoaW5kZXggPSBjKCJTbWFydHBob25lIFBvd2VyIE9OIiA9IDUsICJTbWFydHBob25lIFBvd2VyIE9GRiIgPSA1KSkKCmBgYAoKCiMjIyMjIyBHby9Oby1HbyBGaXJzdDogQXNzdW1wdGlvbnMgIAoKPGRldGFpbHM+ICAKPHN1bW1hcnk+IFRoZSB0d28td2F5IGludGVyYWN0aW9uIG1hZGUgdGhyZWUgYXNzdW1wdGlvbnMuIFRoZSBpbmRlcGVuZGVudCByYW5kb20gc2FtcGxpbmcgYW5kIG5vcm1hbGl0eSBhc3N1bXB0aW9ucyB3ZXJlIG1ldC4gVGhlIGhvbW9nZW5laXR5IG9mIHZhcmlhbmNlIGFzc3VtcHRpb24gd2FzIG5vdCBtZXQsIHRoZXJlZm9yZSwgYSBXaGl0ZSBjb3JyZWN0aW9uIHdhcyBkb25lIGZvciB0aGUgcmVsZXZhbnQgZWZmZWN0LiAqKGNsaWNrIHRvIHNlZSBkZXRhaWxzKSouIDwvc3VtbWFyeT4gIAoKPHNwYW4gc3R5bGU9ImNvbG9yOkRhcmtCbHVlOyBmb250LXNpemU6MThweDsiPjEuIEluZGVwZW5kZW50IFJhbmRvbSBTYW1wbGluZzwvc3Bhbj4gIAoKVGhpcyBhc3N1bXB0aW9uIHdhcyBtZXQgZHVyaW5nIHRlc3RpbmcuICAKICAgIAo8c3BhbiBzdHlsZT0iY29sb3I6RGFya0JsdWU7IGZvbnQtc2l6ZToxOHB4OyI+Mi4gTm9ybWFsaXR5PC9zcGFuPiAgCgpUaGlzIGFzc3VtcHRpb24gd2FzIHRlc3RlZCBieSB2aXN1YWxpemluZyB0aGUgcmVzaWR1YWxzLCBhcHBseWluZyBhIFNoYXBpcm8tV2lsayB0ZXN0IHRvIHRoZSByZXNkaXVhbHMsIGFuZCBvYnNlcnZpbmcgdGhlIFNrZXduZXNzIGFuZCBLdXJ0b3NpcyBvZiB0aGUgZGF0YSAqKGV4dHJhY3RlZCBmcm9tIHRoZSBBTk9WQSBvdXRwdXQpLiogIAogICAgCmBgYHtyIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgcnVuIGJldHdlZW4tc3ViamVjdHMgQU5PVkEgKElWOiBTbWFydHBob25lIFBvd2VyICYgTG9jYXRpb247IERWOiBPU3BhbiBBYm9sdXRlIFNjb3JlKQpnbmdfYWNfZ25nX2Fub3ZhID0gZXpBTk9WQSgKICBkYXRhID0gZ25nX2FjX2duZ19kYXRhCiAgLCBkdiA9IC4ocnRfYXYpCiAgLCB3aWQgPSAuKHBhcnRpY2lwYW50KQogICwgYmV0d2VlbiA9IC4obG9jYXRpb24sIHBvd2VyKQogICwgdHlwZSA9IDMgIyB1bmVxdWFsIHNhbXBsZSBzaXplcywgdGhlcmZvcmUgdXNlIHR5cGUgMwogICwgZGV0YWlsZWQgPSBUUlVFCiAgLCByZXR1cm5fYW92ID0gVFJVRQogICkKCiMgY2FsY3VsYXRlICYgZXh0cmFjdCB0aGUgcmVzaWR1YWxzIGZyb20gdGhlIEFOT1ZBCmduZ19hY19nbmdfcmVzID0gZGF0YS5mcmFtZSgicmVzaWR1YWxzIiA9IHByb2ooZ25nX2FjX2duZ19hbm92YSRhb3YpWywiUmVzaWR1YWxzIl0pICAgCgpgYGAKICAgIAotIEl0IGFwcGVhcnMgdGhhdCB0aGUgcmVzaWR1YWxzIGxpZSBjbG9zZWx5IHRvIGEgc3RyYWlnaHQgbGluZSwgd2hpY2ggc3VnZ2VzdHMgbm9ybWFsaXR5ICooc2VlIHZpc3VhbGl6YXRpb24gYmVsb3cpKi4KICAgIApgYGB7cn0KCnFxbm9ybShnbmdfYWNfZ25nX3JlcyRyZXNpZHVhbHMsIG1haW4gPSAiUS1RIFBsb3Qgb2YgdGhlIEdvL05vLUdvIFJlYWN0aW9uIFRpbWUgUmVzaWR1YWxzIGZvciB0aGUgR28vTm8tR28gRmlyc3QgR3JvdXAiKSAKcXFsaW5lKGduZ19hY19nbmdfcmVzJHJlc2lkdWFscykKCmBgYAogICAgCi0gSXQgYXBwZWFycyB0aGF0IHJlc2lkdWFscyB0ZW5kIHRvIGZvbGxvdyB0aGUgc2hhcGUgb2YgYSBub3JtYWwgZGlzdHJpYnV0aW9uICooc2VlIHZpc3VhbGl6YXRpb24gYmVsb3cpKi4KICAgIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKcXBsb3QoZ25nX2FjX2duZ19yZXMkcmVzaWR1YWxzLCBtYWluID0gIkhpc3RvZ3JhbSBvZiBHby9Oby1HbyBSZWFjdGlvbiBUaW1lIFJlc2lkdWFscyBmb3IgdGhlIEdvL05vLUdvIEZpcnN0IEdyb3VwIikgKyAKICB0aGVtZV9jbGFzc2ljKCkKCmBgYAogICAKLSBUaGUgU2hhcGlyby1XaWxrIHRlc3Qgb2Ygbm9ybWFsaXR5IHdhcyBzaWduaWZpY2FudCAoYmFzZWQgb24gJFxhbHBoYSA9IDAuMDUkKSwgKlcqID0gYHIgcm91bmQoYXMubnVtZXJpYyhnbmdfYWNfZ25nX3NoYXAkc3RhdGlzdGljWyJXIl0pLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19hY19nbmdfc2hhcCRwLnZhbHVlKWAgKihzZWUgY29kZSBiZWxvdykqLiAgCiAgIApgYGB7cn0KCmduZ19hY19nbmdfc2hhcCA9IHNoYXBpcm8udGVzdChnbmdfYWNfZ25nX3JlcyRyZXNpZHVhbHMpCmduZ19hY19nbmdfc2hhcAoKYGBgCgotIFRoZSBkYXRhJ3MgU2tld25lc3MgYW5kIEt1cnRvc2lzIHdhcyBleGFtaW5lZCBhbmQgc2hvd2VkIHRoYXQgYm90aCB0aGUgU2tld25lc3MgKHJhbmdlOiBgciByb3VuZChtaW4oYXMubnVtZXJpYyhnbmdfYWNfZ25nX3NrX3RbYygxLDQpLF0pKSwgMilgIHRvIGByIHJvdW5kKG1heChhcy5udW1lcmljKGduZ19hY19nbmdfc2tfdFtjKDEsNCksXSkpLCAyKWApIGFuZCBLdXJ0b3NpcyAocmFuZ2U6IGByIHJvdW5kKG1pbihhcy5udW1lcmljKGduZ19hY19nbmdfc2tfdFtjKDIsNSksXSkpLCAyKWAgdG8gYHIgcm91bmQobWF4KGFzLm51bWVyaWMoZ25nX2FjX2duZ19za190W2MoMiw1KSxdKSksIDIpYCkgd2VyZSB3aXRoaW4gdGhlIGFjY2VwdGFibGUgcmFuZ2Ugb2YgJFxwbSAyLjAkIGFuZCAkXHBtIDkuMCQsIHJlc3BlY3RpdmVseSAoU2NobWlkZXIsIFppZWdsZXIsIERhbmF5LCBCZXllciwgJiBCw7xobmVyLCAyMDEwKSAqKHNlZSB0YWJsZSBiZWxvdykqLiAgCgpgYGB7cn0KCiMgdXNlIHRoZSBkZXNjcmlwdGl2ZXMgZGF0YSAtLSBnbmdfYWNfZ25nX2RlcwoKIyBvcmdhbml6ZSB0aGUgZGF0YSBpbnRvIGEgbmV3IGRhdGEgZnJhbWUgZGVwaWN0aW5nIHRoZSBTa2V3LCBrdXJ0b3NpcywgYW5kIHNhbXBsZSBzaXplIChuKS4KICBnbmdfYWNfZ25nX3NrX3QgPSByYmluZCgoY2JpbmQodChnbmdfYWNfZ25nX2Rlc1sicnRfYXYxIiwgYygic2tldyIsICJrdXJ0b3NpcyIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0KGduZ19hY19nbmdfZGVzWyJydF9hdjIiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2FjX2duZ19kZXNbInJ0X2F2MyIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSkpKSwgCiAgICAgICAgICAgICAgICAgICAgICAoY2JpbmQodChnbmdfYWNfZ25nX2Rlc1sicnRfYXY0IiwgYygic2tldyIsICJrdXJ0b3NpcyIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0KGduZ19hY19nbmdfZGVzWyJydF9hdjUiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2FjX2duZ19kZXNbInJ0X2F2NiIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSkpKSkKICAgIGNvbG5hbWVzKGduZ19hY19nbmdfc2tfdCkgPSBjKCJPbiBEZXNrIiwgIkluIFBvY2tldC9CYWciLCAiT3V0c2lkZSIpCiAgICByb3duYW1lcyhnbmdfYWNfZ25nX3NrX3QpID0gcmVwKGMoIlNrZXduZXNzIiwgIkt1cnRvc2lzIiwgIm4iKSwgMikKICAgIAojIHVzZSBrYWJsZSB0byBzaG93IHRoZSBkZXNjcmlwdGl2ZXMgdGFibGUKICBrYWJsZShnbmdfYWNfZ25nX3NrX3QsIGNhcHRpb24gPSAiU2tld25lc3MgYW5kIEt1cnRvc2lzIG9mIHRoZSBSZWFjdGlvbiBUaW1lIG9uIHRoZSBHby9Oby1HbyBUYXNrIGZvciB0aGUgR28vTm8tR28gRmlyc3QgR3JvdXAiLCBkaWdpdHMgPSA0LCBhbGlnbiA9ICdjJykgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpICU+JQogIGFkZF9oZWFkZXJfYWJvdmUoYygiICIsICJTbWFydHBob25lIExvY2F0aW9uIiA9IDMpKSAlPiUKICBncm91cF9yb3dzKGluZGV4ID0gYygiU21hcnRwaG9uZSBQb3dlciBPTiIgPSAzLCAiU21hcnRwaG9uZSBQb3dlciBPRkYiID0gMykpCgpgYGAKCi0gVGhlcmVmb3JlLCBiYXNlZCBvbiBhbGwgdGhlIG5vcm1hbGl0eSBhc3N1bXB0aW9uIGNoZWNrcywgbm9ybWFsaXR5IHdhcyBhc3N1bWVkIHRvIGJlIHdpdGhpbiB0aGUgYWNjZXB0YWJsZSByYW5nZSBmb3IgdGhlIGFuYWx5c2lzLiBBZGRpdGlvbmFsbHksIGl0IHNob3VsZCBiZSBub3RlZCB0aGF0IEFOT1ZBIGFuYWx5c2VzIGNhbiBiZSByb2J1c3QgdG8gdmlvbGF0aW9ucyBvZiBub3JtYWxpdHkgKEdhcmRuZXIgJiBUcmVtYmxheSwgMjAwNykuCgo8c3BhbiBzdHlsZT0iY29sb3I6RGFya0JsdWU7IGZvbnQtc2l6ZToxOHB4OyI+My4gSG9tb2dlbmVpdHkgb2YgVmFyaWFuY2U8L3NwYW4+IAoKVGhpcyBhc3N1bXB0aW9uIHdhcyB0ZXN0ZWQgYnkgY29uZHVjdGluZyBMZXZlbmUncyBUZXN0IGZvciBIb21vZ2VuZWl0eSBvZiBWYXJpYW5jZSBmb3IgZWFjaCBiZXR3ZWVuLXN1YmplY3RzIHZhcmlhYmxlIChpLmUuIHNtYXJ0cGhvbmUgbG9jYXRpb24gYW5kIHNtYXJ0cGhvbmUgcG93ZXIpLiAgCgotIFRoZSBob21vZ2VuZWl0eSBhc3N1bXB0aW9uIHdhcyBtZXQgKGJhc2VkIG9uICRcYWxwaGEgPSAwLjA1JCkgZm9yIHNtYXJ0cGhvbmUgbG9jYXRpb24sICpGKihgciBnbmdfYWNfZ25nX2xldl9sb2MkRGZbMV1gLCBgciBnbmdfYWNfZ25nX2xldl9sb2MkRGZbMl1gKSA9IGByIHJvdW5kKGduZ19hY19nbmdfbGV2X2xvY1syXVsxLDFdLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19hY19nbmdfbGV2X2xvY1szXVsxLDFdKWAuIEhvd2V2ZXIsIHRoZSBob21vZ2VuZWl0eSBhc3N1bXB0aW9uIHdhcyBub3QgbWV0IGZvciBzbWFydHBob25lIHBvd2VyLCAqRiooYHIgZ25nX2FjX2duZ19sZXZfcG93JERmWzFdYCwgYHIgZ25nX2FjX2duZ19sZXZfcG93JERmWzJdYCkgPSBgciByb3VuZChnbmdfYWNfZ25nX2xldl9wb3dbMl1bMSwxXSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfYWNfZ25nX2xldl9wb3dbM11bMSwxXSlgICooc2VlIGNvZGUgYmVsb3cpKi4KCmBgYHtyfQoKIyBjb25kdWN0IGxldmVuZSdzCiAgIyBmb3IgbG9jYXRpb24KICBnbmdfYWNfZ25nX2xldl9sb2MgPSBsZXZlbmVUZXN0KGRhdGEgPSBnbmdfYWNfZ25nX2RhdGEsIHJ0X2F2IH4gYXMuZmFjdG9yKGxvY2F0aW9uKSwgY2VudGVyID0gbWVkaWFuKQogIGduZ19hY19nbmdfbGV2X2xvYwogICMgZm9yIHBvd2VyCiAgZ25nX2FjX2duZ19sZXZfcG93ID0gbGV2ZW5lVGVzdChkYXRhID0gZ25nX2FjX2duZ19kYXRhLCBydF9hdiB+IGFzLmZhY3Rvcihwb3dlciksIGNlbnRlciA9IG1lZGlhbikKICBnbmdfYWNfZ25nX2xldl9wb3cKCmBgYAoKLSBUaGUgaG9tb2dlbmVpdHkgb2YgdmFyaWFuY2UgYXNzdW1wdGlvbiB3YXMgbm90IG1ldCBmb3IgdGhlIHNtYXJ0cGhvbmUgcG93ZXIgY29uZGl0aW9uLiBUaGVyZWZvcmUsIGNvbnNpZGVyaW5nIHRoZXJlIHdlcmUgdW5lcXVhbCBzYW1wbGUgc2l6ZXMsIGEgV2hpdGUtY29ycmVjdGVkIEYtdGVzdCB3YXMgY29uZHVjdGVkIChpLmUuIGlmIGludGVyZXN0ZWQgaW4gYXNzZXNzaW5nIHRoZSBtYWluIGVmZmVjdCBvZiBwb3dlcikuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIHJ1biB0aGUgY29ycmVjdGVkIEFOT1ZBIChJVjogU21hcnRwaG9uZSBQb3dlciAmIExvY2F0aW9uIDsgRFY6IEdvL05vLUdvIFJUKQojIHRoaXMgd2lsbCBiZSB1c2VkIHRvIHJlcG9ydCB0aGUgbWFpbiBlZmZlY3Qgb2Ygc21hcnRwaG9uZSBwb3dlciBvbmx5ICAKZ25nX2FjX2duZ19hbm92YV9jb3IgPSBlekFOT1ZBKAogIGRhdGEgPSBnbmdfYWNfZ25nX2RhdGEKICAsIGR2ID0gLihydF9hdikKICAsIHdpZCA9IC4ocGFydGljaXBhbnQpCiAgLCBiZXR3ZWVuID0gLihsb2NhdGlvbiwgcG93ZXIpCiAgLCB0eXBlID0gMyAjIHVuZXF1YWwgc2FtcGxlIHNpemVzLCB0aGVyZm9yZSB1c2UgdHlwZSAzCiAgLCBkZXRhaWxlZCA9IFRSVUUKICAsIHJldHVybl9hb3YgPSBUUlVFCiAgLCB3aGl0ZS5hZGp1c3QgPSBUUlVFCikKCiMgQ2FsY3VsYXRlIGVmZmVjdCBzaXplOgojIHRoaXMgd2lsbCBiZSB1c2VkIHRvIHJlcG9ydCB0aGUgbWFpbiBlZmZlY3Qgb2Ygc21hcnRwaG9uZSBwb3dlciBvbmx5IApnbmdfYWNfZ25nX2xvY19lcyA9IChFdGFTcShnbmdfYWNfZ25nX2Fub3ZhX2NvciRhb3YsIHR5cGUgPSAzLCBhbm92YSA9IEZBTFNFKSlbMl0KCmBgYAoKPC9kZXRhaWxzPiAgCgojIyMjIyMgR28vTm8tR28gRmlyc3Q6IFJlc3VsdHMgIAoKQWxsIHJlc3VsdHMgd2VyZSBiYXNlZCBvbiAkXGFscGhhID0gMC4wMjUkLiBCZWxvdyBhcmUgdGhlIHJlcG9ydGVkIHN0YXRpc3RpY3MgZm9yIHRoZSBtYWluIGFuZCBpbnRlcmFjdGlvbiBlZmZlY3Qgb2YgdGhlIHNpbXBsZSB0d28td2F5IEFOT1ZBLCBmb2xsb3dlZCBieSBhIHRhYmxlIGRlcGljdGluZyB0aGUgQU5PVkEgcmVzdWx0cy4KCioqTWFpbiBFZmZlY3Qgb2YgU21hcnRwaG9uZSBMb2NhdGlvbioqICAKClRoZXJlIHdhcyBubyBzaWduaWZpY2FudCBtYWluIGVmZmVjdCBvZiBzbWFydHBob25lIGxvY2F0aW9uIG9uIHJlYWN0aW9uIHRpbWUsICpGKihgciBnbmdfYWNfZ25nX3RbMiwyXWAsIGByIGduZ19hY19nbmdfdFsyLDNdYCkgPSBgciByb3VuZChnbmdfYWNfZ25nX3RbMiw0XSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfYWNfZ25nX3RbMiw1XSlgLCAkXGV0YV57Mn0kIGByIHBfcm91bmQoZ25nX2FjX2duZ190WzIsN10pYC4KCioqTWFpbiBFZmZlY3Qgb2YgU21hcnRwaG9uZSBQb3dlcioqICAKClRoZXJlIHdhcyBubyBzaWduaWZpY2FudCBtYWluIGVmZmVjdCBvZiBzbWFydHBob25lIHBvd2VyIG9uIHJlYWN0aW9uIHRpbWUsICpGKihgciBnbmdfYWNfZ25nX3RbMywyXWAsIGByIGduZ19hY19nbmdfdFszLDNdYCkgPSBgciByb3VuZChnbmdfYWNfZ25nX3RbMyw0XSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfYWNfZ25nX3RbMyw1XSlgLCAkXGV0YV57Mn0kIGByIHBfcm91bmQoZ25nX2FjX2duZ190WzMsN10pYC4KCioqSW50ZXJhY3Rpb24gb2YgU21hcnRwaG9uZSBMb2NhdGlvbiAmIFNtYXJ0cGhvbmUgUG93ZXIqKiAgCgpUaGVyZSB3YXMgYSBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBiZXR3ZWVuIHNtYXJ0cGhvbmUgbG9jYXRpb24gYW5kIHNtYXJ0cGhvbmUgcG93ZXIgb24gcmVhY3Rpb24gdGltZSwgKkYqKGByIGduZ19hY19nbmdfdFs0LDJdYCwgYHIgZ25nX2FjX2duZ190WzQsM11gKSA9IGByIHJvdW5kKGduZ19hY19nbmdfdFs0LDRdLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19hY19nbmdfdFs0LDVdKWAsICRcZXRhXnsyfSQgYHIgcF9yb3VuZChnbmdfYWNfZ25nX3RbNCw3XSlgLgoKKipQb3N0LWhvYyBUZXN0cyoqICAKClNpbmNlIHRoZXJlIHdhcyBhIHNpZ25pZmljYW50IHR3by13YXkgaW50ZXJhY3Rpb24gKGkuZSBzbWFydHBob25lIGxvY2F0aW9uIGFuZCBzbWFydHBob25lIHBvd2VyKSwgZnVydGhlciBhbmFseXNlcyB3ZXJlIGNvbXBsZXRlZCAqKHNlZSDigJxTaW1wbGUgTWFpbiBFZmZlY3RzOiBTbWFydHBob25lIExvY2F0aW9uIHZzLiBTbWFydHBob25lIFBvd2VyIChmb3IgdGhlIEdvL05vLUdvIEZpcnN0IEJhbGFuY2UgR3JvdXAp4oCdIGJlbG93KSouCgoKYGBge3J9CgojIGNyZWF0ZSBhIHRhYmxlIHdpdGggdGhlIGFub3ZhIHJlc3VsdHMgaW5jbHVkaW5nIHRoZSBjb3JyZWN0ZWQgdmFsdWVzIGZvciB0aGUgbWFpbiBlZmZlY3Qgb2YgcG93ZXIgKGkuZS4gc2luY2UgaXQgZGlkIG5vdCBtZWV0IHRoZSBob21vZ2VuZWl0eSBvZiB2YXJpYW5jZSBhc3N1bXB0aW9uKQogICMgZ2V0IHRoZSBvcmlnaW5hbCBhbm92YSBkYXRhCiAgZ25nX2FjX2duZ190ID0gZ25nX2FjX2duZ19hbm92YSRBTk9WQQogICAgIyBzaW5jZSB0aGUgY29ycmVjdGVkIGRhdGEgZG9lcyBub3QgaGF2ZSB0aGUgU1MsIHJlbW92ZSB0aGVzZSBjb2x1bW5zIGZyb20gdGhlIG9yaWdpbmFsIEFOT1ZBIHRhYmxlCiAgICBnbmdfYWNfZ25nX3QgPSBkcGx5cjo6c2VsZWN0KGduZ19hY19nbmdfdCwgLVNTbiwgLVNTZCkKICAgICMgY2hhbmdlIHRoZSBkYXRhIGZvciB0aGUgbWFpbiBlZmZlY3Qgb2YgbG9jYXRpb24gdG8gY29ycmVjdGVkIG51bWJlcnMKICAgIGduZ19hY19nbmdfdFtnbmdfYWNfZ25nX3QkRWZmZWN0ID09ICJwb3dlciIsXSA9IGMoZ25nX2FjX2duZ19hbm92YV9jb3IkQU5PVkFbMyxdLCBnbmdfYWNfZ25nX2xvY19lcykKICAgICMgcmUtZGVmaW5lIHRoZSBhbHBoYSB2YWx1ZSBiYXNlZCBvbiB0aGUgYm9uZmVycm9uaSBjb3JyZWN0aW9uCiAgICAgICMgcmVuYW1lIHRoZSAicDwuMDUiIGNvbHVtbiBhcHByb3ByaWF0ZWx5IC0tICJwPC4wMjUiCiAgICAgIGNvbG5hbWVzKGduZ19hY19nbmdfdClbNl0gPSAicDwuMDI1IgogICAgICAjIGNoYW5nZSB2YWx1ZXMgdG8gZml0IHRoZSBkYXRhCiAgICAgIGduZ19hY19nbmdfdCRgcDwuMDI1YCA9IGlmZWxzZShnbmdfYWNfZ25nX3QkcCA8IDAuMDI1LCAiKiIsICIiKQogICAgCiMgc2hvdyBBTk9WQSByZXN1bHRzIGluIGthYmxlIHRhYmxlIAprYWJsZShnbmdfYWNfZ25nX3QsIGNhcHRpb24gPSAiR28vTm8tR28gRmlyc3Q6IFNpbXBsZSBUd28tV2F5IEludGVyYWN0aW9uIG9uIFJlYWN0aW9uIFRpbWUgb24gdGhlIEdvL05vLUdvIFRhc2siLCBkaWdpdHMgPSA0LCBhbGlnbiA9ICdjJykgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpIAoKYGBgCgoKIyMjIyMgU2ltcGxlIE1haW4gRWZmZWN0czogU21hcnRwaG9uZSBMb2NhdGlvbiB2cy4gU21hcnRwaG9uZSBQb3dlciAoZm9yIHRoZSBHby9Oby1HbyBGaXJzdCBCYWxhbmNlIEdyb3VwKSAgClRoZSBzaW1wbGUgdHdvLXdheSBpbnRlcmFjdGlvbiBzaG93ZWQgdGhhdCwgd2hlbiB0aGUgR28vTm8tR28gVGFzayB3YXMgY29tcGxldGVkIGZpcnN0LCB0aGVyZSB3YXMgYSBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBiZXR3ZWVuIHRoZSBzbWFydHBob25lIGNvbmRpdGlvbnMuIEluIG9yZGVyIHRvIGludGVycHJldCB0aGlzIGVmZmVjdCwgc2ltcGxlIG1haW4gZWZmZWN0cyB3ZXJlIGNvbXBsZXRlZCBpbnZlc3RpZ2F0aW5nIHRoZSBlZmZlY3Qgb2Ygc21hcnRwaG9uZSBsb2NhdGlvbiBhdCBlYWNoIGxldmVsIG9mIHNtYXJ0cGhvbmUgcG93ZXIuIFRoZXJlZm9yZSwgYSBzaW1wbGUgb25lLXdheSBBTk9WQSBmb3Igc21hcnRwaG9uZSBsb2NhdGlvbiB3YXMgY29tcGxldGVkIGZvciBlYWNoIHNtYXJ0cGhvbmUgcG93ZXIgY29uZGl0aW9uIHNlcGFyYXRlbHkuIAoKVHdvIG5ldyBkYXRhIHNldHMgd2VyZSBjcmVhdGVkIGZvciB0aGUgc2ltcGxlIHR3by13YXkgaW50ZXJhY3Rpb25zOiAoMSkgZm9yIHRoZSBQb3dlciBPTiBEYXRhICgqZ25nX2FjX2duZ19PTl9kYXRhKikgYW5kICgyKSBmb3IgdGhlIFBvd2VyIE9GRiBEYXRhICgqZ25nX2FjX2duZ19PRkZfZGF0YSopLiAgCgoKYGBge3J9CgojIGdldCBhIHN1YnNldCBvZiB0aGUgZ25nX2FjX2duZ19kYXRhCiAgIyBmb3IgdGhlIE9OIHBvd2VyIGdyb3VwIG9ubHkKICBnbmdfYWNfZ25nX09OX2RhdGEgPSBnbmdfYWNfZ25nX2RhdGFbZ25nX2FjX2duZ19kYXRhJHBvd2VyID09ICJPTiIsIF0KCiAgIyBmb3IgdGhlIE9GRiBwb3dlciBncm91cCBvbmx5CiAgZ25nX2FjX2duZ19PRkZfZGF0YSA9IGduZ19hY19nbmdfZGF0YVtnbmdfYWNfZ25nX2RhdGEkcG93ZXIgPT0gIk9GRiIsIF0KCmBgYAoKClRvIGNvcnJlY3QgdGhlIGZhbWlseS13aXNlIGVycm9yIHJhdGUsIGEgSG9sbS1Cb25mZXJyb25pIGFkanVzdG1lbnQgd2FzIHVzZWQgd2hlbiBhc3Nlc3NpbmcgdGhlIHNpZ25pZmljYW5jZSBvZiBtYWluIGVmZmVjdHMgYXNzb2NpYXRlZCB3aXRoIHRoZXNlIEFOT1ZBcy4gVGhlIEhvbG0tQm9uZmVycm9uaSBhZGp1c3RtZW50IGRlZmluZWQgYSBjb3JyZWN0ZWQgYWxwaGEgbGV2ZWwgYWNjb3JkaW5nIHRvIHRoZSBmb2xsb3dpbmcgZm9ybXVsYTogCiQkXGFscGhhX3tjb3JyZWN0ZWR9ID0gXGZyYWN7XGFscGhhfXtudW1iZXIgb2YgY29tcGFyaXNvbnMg4oiSIHJhbmsgb2YgY29tcGFyaXNvbiArIDF9JCQKCiMjIyMjIyBQb3dlcmVkIE9OOiBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzIAoKVGhlIGZpcnN0IHNpbXBsZSBtYWluIGVmZmVjdCBBTk9WQSB3YXMgY29tcGxldGVkIHVzaW5nIHRoZSAiUG93ZXJlZCBPTiIgc3Vic2V0IG9mIHRoZSBQb3dlciBGYWN0b3IgKGkuZS4gcGFydGljaXBhbnRzIHdobyBjb21wbGV0ZWQgdGhlIEdvL05vLUdvIHRhc2sgZmlyc3Qgd2l0aCB0aGVpciBzbWFydHBob25lcyBwb3dlcmVkIE9OKS4gVGhlIGJldHdlZW4tc3ViamVjdHMgZmFjdG9yIHdhcyBzbWFydHBob25lIGxvY2F0aW9uIChpLmUuIGRlc2ssIHBvY2tldC9iYWcgb3Igb3V0c2lkZSkgYW5kIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgd2FzIGFjY3VyYWN5IChpLmUuIGF2ZXJhZ2UgcmVhY3Rpb24gdGltZSkuCgpUaGVyZSB3YXMgYSB0b3RhbCBvZiBgciBsZW5ndGgoZ25nX2FjX2duZ19PTl9kYXRhJHBhcnRpY2lwYW50KWAgcGFydGljaXBhbnRzIGluIHRoZSBQb3dlcmVkIE9OIGFuYWx5c2lzLiBUaGUgZm9sbG93aW5nIHRhYmxlIGRlcGljdHMgdGhlIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3M6IHRoZSBtZWFuICgqTSopLCBzdGFuZGFyZCBkZXZpYXRpb24gKCpTRCopLCBtaW5pbXVtIHNjb3JlICgqbWluLiopLCBtYXhpbXVtIHNjb3JlICgqbWF4LiopLCBhbmQgdGhlIHNhbXBsZSBzaXplICgqbiopLiAgCgpgYGB7cn0KCiMgY3JlYXRlIGEgZGF0YSBmcmFtZSB3aXRoIHRoZSBkZXNjcmlwdGl2ZXMgb2YgYWxsIHRoZSBkYXRhLCBncm91cGVkIGJ5IHRoZSBsb2NhdGlvbiAmIHBvd2VyIGNvbmRpdGlvbnMKICAjIHRoaXMgY3JlYXRlcyBpbmZvcm1hdGlvbiBmb3IgdGhlIDYgcG9zc2libGUgY29tYmluZWQgY29uZGl0aW9ucwogIGduZ19hY19nbmdfT05fZGVzID0gcHN5Y2g6OmRlc2NyaWJlQnkoZ25nX2FjX2duZ19PTl9kYXRhLCBnbmdfYWNfZ25nX09OX2RhdGEkbG9jYXRpb24sIG1hdCA9IFRSVUUpICAKCiMgb3JnYW5pemUgdGhlIGRhdGEgaW50byBhIG5ldyBkYXRhIGZyYW1lIGRlcGljdGluZyB0aGUgTSwgU0QsIG1pbi4sIG1heC4sIGFuZCBuLgogIGduZ19hY19nbmdfT05fZGVzX3QgPSBjYmluZCh0KGduZ19hY19nbmdfT05fZGVzWyJydF9hdjEiLCBjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2FjX2duZ19PTl9kZXNbInJ0X2F2MiIsIGMoIm1lYW4iLCAic2QiLCAibWluIiwgIm1heCIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdChnbmdfYWNfZ25nX09OX2Rlc1sicnRfYXYzIiwgYygibWVhbiIsICJzZCIsICJtaW4iLCAibWF4IiwgIm4iKV0pKQogICAgY29sbmFtZXMoZ25nX2FjX2duZ19PTl9kZXNfdCkgPSBjKCJPbiBEZXNrIiwgIkluIFBvY2tldC9CYWciLCAiT3V0c2lkZSIpCiAgICByb3duYW1lcyhnbmdfYWNfZ25nX09OX2Rlc190KSA9IGMoIk0iLCAiU0QiLCAibWluLiIsICJtYXguIiwgIm4iKQogIAojIHVzZSBrYWJsZSB0byBzaG93IHRoZSBkZXNjcmlwdGl2ZXMgdGFibGUKICBrYWJsZShnbmdfYWNfZ25nX09OX2Rlc190LCBjYXB0aW9uID0gIlBvd2VyZWQgT04gRGVzY3JpcHRpdmUgU3RhdGlzdGljczogUmVhY3Rpb24gVGltZSAoc2VjLikgb24gdGhlIEdvL05vLUdvIFRhc2siLCBkaWdpdHMgPSA0LCBhbGlnbiA9ICdjJykgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpICU+JQogIGFkZF9oZWFkZXJfYWJvdmUoYygiICIsICJTbWFydHBob25lIExvY2F0aW9uIiA9IDMpKQoKYGBgCgojIyMjIyMgUG93ZXJlZCBPTjogQXNzdW1wdGlvbnMgIAoKPGRldGFpbHM+ICAKPHN1bW1hcnk+IFRoZSBvbmUtd2F5IHNpbXBsZSBtYWluIGVmZmVjdCBBTk9WQSBtYWRlIHRocmVlIGFzc3VtcHRpb25zLiBBbGwgYXNzdW1wdGlvbnMgd2VyZSBtZXQuICooY2xpY2sgdG8gc2VlIGRldGFpbHMpKi4gPC9zdW1tYXJ5PiAgCgo8c3BhbiBzdHlsZT0iY29sb3I6RGFya0JsdWU7IGZvbnQtc2l6ZToxOHB4OyI+MS4gSW5kZXBlbmRlbnQgUmFuZG9tIFNhbXBsaW5nPC9zcGFuPiAgCgpUaGlzIGFzc3VtcHRpb24gd2FzIG1ldCBkdXJpbmcgdGVzdGluZy4gIAogICAgCjxzcGFuIHN0eWxlPSJjb2xvcjpEYXJrQmx1ZTsgZm9udC1zaXplOjE4cHg7Ij4yLiBOb3JtYWxpdHk8L3NwYW4+ICAKClRoaXMgYXNzdW1wdGlvbiB3YXMgdGVzdGVkIGJ5IHZpc3VhbGl6aW5nIHRoZSByZXNpZHVhbHMsIGFwcGx5aW5nIGEgU2hhcGlyby1XaWxrIHRlc3QgdG8gdGhlIHJlc2RpdWFscywgYW5kIG9ic2VydmluZyB0aGUgU2tld25lc3MgYW5kIEt1cnRvc2lzIG9mIHRoZSBkYXRhICooZXh0cmFjdGVkIGZyb20gdGhlIEFOT1ZBIG91dHB1dCkuKiAgCiAgICAKYGBge3IgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBydW4gYmV0d2Vlbi1zdWJqZWN0cyBBTk9WQSAoSVY6IFNtYXJ0cGhvbmUgUG93ZXIgJiBMb2NhdGlvbjsgRFY6IE9TcGFuIEFib2x1dGUgU2NvcmUpCmduZ19hY19nbmdfT05fYW5vdmEgPSBlekFOT1ZBKAogIGRhdGEgPSBnbmdfYWNfZ25nX09OX2RhdGEKICAsIGR2ID0gLihydF9hdikKICAsIHdpZCA9IC4ocGFydGljaXBhbnQpCiAgLCBiZXR3ZWVuID0gLihsb2NhdGlvbikKICAsIHR5cGUgPSAzICMgdW5lcXVhbCBzYW1wbGUgc2l6ZXMsIHRoZXJmb3JlIHVzZSB0eXBlIDMKICAsIGRldGFpbGVkID0gVFJVRQogICwgcmV0dXJuX2FvdiA9IFRSVUUKICApCgojIGNhbGN1bGF0ZSAmIGV4dHJhY3QgdGhlIHJlc2lkdWFscyBmcm9tIHRoZSBBTk9WQQpnbmdfYWNfZ25nX09OX3JlcyA9IGRhdGEuZnJhbWUoInJlc2lkdWFscyIgPSBwcm9qKGduZ19hY19nbmdfT05fYW5vdmEkYW92KVssIlJlc2lkdWFscyJdKSAgIAoKYGBgCiAgICAKLSBJdCBhcHBlYXJzIHRoYXQgdGhlIHJlc2lkdWFscyBsaWUgY2xvc2VseSB0byBhIHN0cmFpZ2h0IGxpbmUsIHdoaWNoIHN1Z2dlc3RzIG5vcm1hbGl0eSAqKHNlZSB2aXN1YWxpemF0aW9uIGJlbG93KSouCiAgICAKYGBge3J9CgpxcW5vcm0oZ25nX2FjX2duZ19PTl9yZXMkcmVzaWR1YWxzLCBtYWluID0gIlEtUSBQbG90IG9mIHRoZSBHby9Oby1HbyBSZWFjdGlvbiBUaW1lIFJlc2lkdWFscyBmb3IgdGhlIFBvd2VyZWQgT04gR3JvdXAiKSAKcXFsaW5lKGduZ19hY19nbmdfT05fcmVzJHJlc2lkdWFscykKCmBgYAogICAgCi0gSXQgYXBwZWFycyB0aGF0IHJlc2lkdWFscyB0ZW5kIHRvIGZvbGxvdyB0aGUgc2hhcGUgb2YgYSBub3JtYWwgZGlzdHJpYnV0aW9uICooc2VlIHZpc3VhbGl6YXRpb24gYmVsb3cpKi4KICAgIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKcXBsb3QoZ25nX2FjX2duZ19PTl9yZXMkcmVzaWR1YWxzLCBtYWluID0gIkhpc3RvZ3JhbSBvZiBHby9Oby1HbyBSZWFjdGlvbiBUaW1lIFJlc2lkdWFscyBmb3IgdGhlIFBvd2VyZWQgT04gR3JvdXAiKSArIAogIHRoZW1lX2NsYXNzaWMoKQoKYGBgCiAgIAotIFRoZSBTaGFwaXJvLVdpbGsgdGVzdCBvZiBub3JtYWxpdHkgd2FzIG5vdCBzaWduaWZpY2FudCAoYmFzZWQgb24gJFxhbHBoYSA9IDAuMDUkKSwgKlcqID0gYHIgcm91bmQoYXMubnVtZXJpYyhnbmdfYWNfZ25nX09OX3NoYXAkc3RhdGlzdGljWyJXIl0pLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19hY19nbmdfT05fc2hhcCRwLnZhbHVlKWAgKihzZWUgY29kZSBiZWxvdykqLiAgCiAgIApgYGB7cn0KCmduZ19hY19nbmdfT05fc2hhcCA9IHNoYXBpcm8udGVzdChnbmdfYWNfZ25nX09OX3JlcyRyZXNpZHVhbHMpCmduZ19hY19nbmdfT05fc2hhcAoKYGBgCgotIFRoZSBkYXRhJ3MgU2tld25lc3MgYW5kIEt1cnRvc2lzIHdhcyBleGFtaW5lZCBhbmQgc2hvd2VkIHRoYXQgYm90aCB0aGUgU2tld25lc3MgKHJhbmdlOiBgciByb3VuZChtaW4oZ25nX2FjX2duZ19PTl9za190WzEsXSksIDIpYCB0byBgciByb3VuZChtYXgoZ25nX2FjX2duZ19PTl9za190WzEsXSksIDIpYCkgYW5kIEt1cnRvc2lzIChyYW5nZTogYHIgcm91bmQobWluKGduZ19hY19nbmdfT05fc2tfdFsyLF0pLCAyKWAgdG8gYHIgcm91bmQobWF4KGduZ19hY19nbmdfT05fc2tfdFsyLF0pLCAyKWApIHdlcmUgd2l0aGluIHRoZSBhY2NlcHRhYmxlIHJhbmdlIG9mICRccG0gMi4wJCBhbmQgJFxwbSA5LjAkLCByZXNwZWN0aXZlbHkgKFNjaG1pZGVyLCBaaWVnbGVyLCBEYW5heSwgQmV5ZXIsICYgQsO8aG5lciwgMjAxMCkgKihzZWUgdGFibGUgYmVsb3cpKi4gIAoKYGBge3J9CgojIHVzZSB0aGUgZGVzY3JpcHRpdmVzIGRhdGEgLS0gZ25nX2FjX2duZ19PTl9kZXMKCiMgb3JnYW5pemUgdGhlIGRhdGEgaW50byBhIG5ldyBkYXRhIGZyYW1lIGRlcGljdGluZyB0aGUgU2tldywga3VydG9zaXMsIGFuZCBzYW1wbGUgc2l6ZSAobikuCiAgZ25nX2FjX2duZ19PTl9za190ID0gY2JpbmQodChnbmdfYWNfZ25nX09OX2Rlc1sicnRfYXYxIiwgYygic2tldyIsICJrdXJ0b3NpcyIsICJuIildKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0KGduZ19hY19nbmdfT05fZGVzWyJydF9hdjIiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2FjX2duZ19PTl9kZXNbInJ0X2F2MyIsIGMoInNrZXciLCAia3VydG9zaXMiLCAibiIpXSkpCiAgICBjb2xuYW1lcyhnbmdfYWNfZ25nX09OX3NrX3QpID0gYygiT24gRGVzayIsICJJbiBQb2NrZXQvQmFnIiwgIk91dHNpZGUiKQogICAgcm93bmFtZXMoZ25nX2FjX2duZ19PTl9za190KSA9IGMoIlNrZXduZXNzIiwgIkt1cnRvc2lzIiwgIm4iKQogICAgCiMgdXNlIGthYmxlIHRvIHNob3cgdGhlIGRlc2NyaXB0aXZlcyB0YWJsZQogIGthYmxlKGduZ19hY19nbmdfT05fc2tfdCwgY2FwdGlvbiA9ICJTa2V3bmVzcyBhbmQgS3VydG9zaXMgb2YgdGhlIFJlYWN0aW9uIFRpbWUgb24gdGhlIEdvL05vLUdvIFRhc2sgZm9yIHRoZSBQb3dlcmVkIE9OIEdyb3VwIiwgZGlnaXRzID0gNCwgYWxpZ24gPSAnYycpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsICJob3ZlciIsIGZ1bGxfd2lkdGggPSBGKSAlPiUKICBhZGRfaGVhZGVyX2Fib3ZlKGMoIiAiLCAiU21hcnRwaG9uZSBMb2NhdGlvbiIgPSAzKSkKCmBgYAoKLSBUaGVyZWZvcmUsIGJhc2VkIG9uIGFsbCB0aGUgbm9ybWFsaXR5IGFzc3VtcHRpb24gY2hlY2tzLCBub3JtYWxpdHkgd2FzIGFzc3VtZWQgdG8gYmUgd2l0aGluIHRoZSBhY2NlcHRhYmxlIHJhbmdlIGZvciB0aGUgYW5hbHlzaXMuIEFkZGl0aW9uYWxseSwgaXQgc2hvdWxkIGJlIG5vdGVkIHRoYXQgQU5PVkEgYW5hbHlzZXMgY2FuIGJlIHJvYnVzdCB0byB2aW9sYXRpb25zIG9mIG5vcm1hbGl0eSAoR2FyZG5lciAmIFRyZW1ibGF5LCAyMDA3KS4KCjxzcGFuIHN0eWxlPSJjb2xvcjpEYXJrQmx1ZTsgZm9udC1zaXplOjE4cHg7Ij4zLiBIb21vZ2VuZWl0eSBvZiBWYXJpYW5jZTwvc3Bhbj4gCgpUaGlzIGFzc3VtcHRpb24gd2FzIHRlc3RlZCBieSBjb25kdWN0aW5nIExldmVuZSdzIFRlc3QgZm9yIEhvbW9nZW5laXR5IG9mIFZhcmlhbmNlIGZvciB0aGUgYmV0d2Vlbi1zdWJqZWN0cyB2YXJpYWJsZS4gIAoKLSBUaGUgaG9tb2dlbmVpdHkgYXNzdW1wdGlvbiB3YXMgbWV0IChiYXNlZCBvbiAkXGFscGhhID0gMC4wNSQpIGZvciBzbWFydHBob25lIGxvY2F0aW9uLCAqRiooYHIgZ25nX2FjX2duZ19PTl9sZXZfbG9jJERmWzFdYCwgYHIgZ25nX2FjX2duZ19PTl9sZXZfbG9jJERmWzJdYCkgPSBgciByb3VuZChnbmdfYWNfZ25nX09OX2xldl9sb2NbMl1bMSwxXSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfYWNfZ25nX09OX2xldl9sb2NbM11bMSwxXSlgICooc2VlIGNvZGUgYmVsb3cpKi4KCmBgYHtyfQoKIyBjb25kdWN0IGxldmVuZSdzCiAgIyBmb3IgbG9jYXRpb24KICBnbmdfYWNfZ25nX09OX2xldl9sb2MgPSBsZXZlbmVUZXN0KGRhdGEgPSBnbmdfYWNfZ25nX09OX2RhdGEsIHJ0X2F2IH4gYXMuZmFjdG9yKGxvY2F0aW9uKSwgY2VudGVyID0gbWVkaWFuKQogIGduZ19hY19nbmdfT05fbGV2X2xvYwoKYGBgCgo8L2RldGFpbHM+ICAKCiMjIyMjIyBQb3dlcmVkIE9GRjogRGVzY3JpcHRpdmUgU3RhdGlzdGljcyAKClRoZSBzZWNvbmQgc2ltcGxlIG1haW4gZWZmZWN0IEFOT1ZBIHdhcyBjb21wbGV0ZWQgdXNpbmcgdGhlICJQb3dlcmVkIE9GRiIgc3Vic2V0IG9mIHRoZSBQb3dlciBGYWN0b3IgKGkuZS4gcGFydGljaXBhbnRzIHdobyBjb21wbGV0ZWQgdGhlIEdvL05vLUdvIHRhc2sgZmlyc3Qgd2l0aCB0aGVpciBzbWFydHBob25lcyBwb3dlcmVkIE9GRikuIFRoZSBiZXR3ZWVuLXN1YmplY3RzIGZhY3RvciB3YXMgc21hcnRwaG9uZSBsb2NhdGlvbiAoaS5lLiBkZXNrLCBwb2NrZXQvYmFnIG9yIG91dHNpZGUpIGFuZCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIHdhcyBhY2N1cmFjeSAoaS5lLiBhdmVyYWdlIHJlYWN0aW9uIHRpbWUpLgoKVGhlcmUgd2FzIGEgdG90YWwgb2YgYHIgbGVuZ3RoKGduZ19hY19nbmdfT05fZGF0YSRwYXJ0aWNpcGFudClgIHBhcnRpY2lwYW50cyBpbiB0aGUgUG93ZXJlZCBPTiBhbmFseXNpcy4gVGhlIGZvbGxvd2luZyB0YWJsZSBkZXBpY3RzIHRoZSBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzOiB0aGUgbWVhbiAoKk0qKSwgc3RhbmRhcmQgZGV2aWF0aW9uICgqU0QqKSwgbWluaW11bSBzY29yZSAoKm1pbi4qKSwgbWF4aW11bSBzY29yZSAoKm1heC4qKSwgYW5kIHRoZSBzYW1wbGUgc2l6ZSAoKm4qKS4gIAoKYGBge3J9CgojIGNyZWF0ZSBhIGRhdGEgZnJhbWUgd2l0aCB0aGUgZGVzY3JpcHRpdmVzIG9mIGFsbCB0aGUgZGF0YSwgZ3JvdXBlZCBieSB0aGUgbG9jYXRpb24gJiBwb3dlciBjb25kaXRpb25zCiAgIyB0aGlzIGNyZWF0ZXMgaW5mb3JtYXRpb24gZm9yIHRoZSA2IHBvc3NpYmxlIGNvbWJpbmVkIGNvbmRpdGlvbnMKICBnbmdfYWNfZ25nX09GRl9kZXMgPSBwc3ljaDo6ZGVzY3JpYmVCeShnbmdfYWNfZ25nX09GRl9kYXRhLCBnbmdfYWNfZ25nX09GRl9kYXRhJGxvY2F0aW9uLCBtYXQgPSBUUlVFKSAgCgojIG9yZ2FuaXplIHRoZSBkYXRhIGludG8gYSBuZXcgZGF0YSBmcmFtZSBkZXBpY3RpbmcgdGhlIE0sIFNELCBtaW4uLCBtYXguLCBhbmQgbi4KICBnbmdfYWNfZ25nX09GRl9kZXNfdCA9IGNiaW5kKHQoZ25nX2FjX2duZ19PRkZfZGVzWyJydF9hdjEiLCBjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2FjX2duZ19PRkZfZGVzWyJydF9hdjIiLCBjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2FjX2duZ19PRkZfZGVzWyJydF9hdjMiLCBjKCJtZWFuIiwgInNkIiwgIm1pbiIsICJtYXgiLCAibiIpXSkpCiAgICBjb2xuYW1lcyhnbmdfYWNfZ25nX09GRl9kZXNfdCkgPSBjKCJPbiBEZXNrIiwgIkluIFBvY2tldC9CYWciLCAiT3V0c2lkZSIpCiAgICByb3duYW1lcyhnbmdfYWNfZ25nX09GRl9kZXNfdCkgPSBjKCJNIiwgIlNEIiwgIm1pbi4iLCAibWF4LiIsICJuIikKICAKIyB1c2Uga2FibGUgdG8gc2hvdyB0aGUgZGVzY3JpcHRpdmVzIHRhYmxlCiAga2FibGUoZ25nX2FjX2duZ19PRkZfZGVzX3QsIGNhcHRpb24gPSAiUG93ZXJlZCBPRkYgRGVzY3JpcHRpdmUgU3RhdGlzdGljczogUmVhY3Rpb24gVGltZSAoc2VjLikgb24gdGhlIEdvL05vLUdvIFRhc2siLCBkaWdpdHMgPSA0LCBhbGlnbiA9ICdjJykgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpICU+JQogIGFkZF9oZWFkZXJfYWJvdmUoYygiICIsICJTbWFydHBob25lIExvY2F0aW9uIiA9IDMpKQoKYGBgCgojIyMjIyMgUG93ZXJlZCBPTjogQXNzdW1wdGlvbnMgIAoKPGRldGFpbHM+ICAKPHN1bW1hcnk+IFRoZSBvbmUtd2F5IHNpbXBsZSBtYWluIGVmZmVjdCBBTk9WQSBtYWRlIHRocmVlIGFzc3VtcHRpb25zLiBBbGwgYXNzdW1wdGlvbnMgd2VyZSBtZXQuICooY2xpY2sgdG8gc2VlIGRldGFpbHMpKi4gPC9zdW1tYXJ5PiAgCgo8c3BhbiBzdHlsZT0iY29sb3I6RGFya0JsdWU7IGZvbnQtc2l6ZToxOHB4OyI+MS4gSW5kZXBlbmRlbnQgUmFuZG9tIFNhbXBsaW5nPC9zcGFuPiAgCgpUaGlzIGFzc3VtcHRpb24gd2FzIG1ldCBkdXJpbmcgdGVzdGluZy4gIAogICAgCjxzcGFuIHN0eWxlPSJjb2xvcjpEYXJrQmx1ZTsgZm9udC1zaXplOjE4cHg7Ij4yLiBOb3JtYWxpdHk8L3NwYW4+ICAKClRoaXMgYXNzdW1wdGlvbiB3YXMgdGVzdGVkIGJ5IHZpc3VhbGl6aW5nIHRoZSByZXNpZHVhbHMsIGFwcGx5aW5nIGEgU2hhcGlyby1XaWxrIHRlc3QgdG8gdGhlIHJlc2RpdWFscywgYW5kIG9ic2VydmluZyB0aGUgU2tld25lc3MgYW5kIEt1cnRvc2lzIG9mIHRoZSBkYXRhICooZXh0cmFjdGVkIGZyb20gdGhlIEFOT1ZBIG91dHB1dCkuKiAgCiAgICAKYGBge3IgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBydW4gYmV0d2Vlbi1zdWJqZWN0cyBBTk9WQSAoSVY6IFNtYXJ0cGhvbmUgUG93ZXIgJiBMb2NhdGlvbjsgRFY6IE9TcGFuIEFib2x1dGUgU2NvcmUpCmduZ19hY19nbmdfT0ZGX2Fub3ZhID0gZXpBTk9WQSgKICBkYXRhID0gZ25nX2FjX2duZ19PRkZfZGF0YQogICwgZHYgPSAuKHJ0X2F2KQogICwgd2lkID0gLihwYXJ0aWNpcGFudCkKICAsIGJldHdlZW4gPSAuKGxvY2F0aW9uKQogICwgdHlwZSA9IDMgIyB1bmVxdWFsIHNhbXBsZSBzaXplcywgdGhlcmZvcmUgdXNlIHR5cGUgMwogICwgZGV0YWlsZWQgPSBUUlVFCiAgLCByZXR1cm5fYW92ID0gVFJVRQogICkKCiMgY2FsY3VsYXRlICYgZXh0cmFjdCB0aGUgcmVzaWR1YWxzIGZyb20gdGhlIEFOT1ZBCmduZ19hY19nbmdfT0ZGX3JlcyA9IGRhdGEuZnJhbWUoInJlc2lkdWFscyIgPSBwcm9qKGduZ19hY19nbmdfT0ZGX2Fub3ZhJGFvdilbLCJSZXNpZHVhbHMiXSkgICAKCmBgYAogICAgCi0gSXQgYXBwZWFycyB0aGF0IHRoZSByZXNpZHVhbHMgbGllIGNsb3NlbHkgdG8gYSBzdHJhaWdodCBsaW5lLCB3aGljaCBzdWdnZXN0cyBub3JtYWxpdHkgKihzZWUgdmlzdWFsaXphdGlvbiBiZWxvdykqLgogICAgCmBgYHtyfQoKcXFub3JtKGduZ19hY19nbmdfT0ZGX3JlcyRyZXNpZHVhbHMsIG1haW4gPSAiUS1RIFBsb3Qgb2YgdGhlIEdvL05vLUdvIFJlYWN0aW9uIFRpbWUgUmVzaWR1YWxzIGZvciB0aGUgUG93ZXJlZCBPRkYgR3JvdXAiKSAKcXFsaW5lKGduZ19hY19nbmdfT0ZGX3JlcyRyZXNpZHVhbHMpCgpgYGAKICAgIAotIEl0IGFwcGVhcnMgdGhhdCByZXNpZHVhbHMgdGVuZCB0byBmb2xsb3cgdGhlIHNoYXBlIG9mIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiAqKHNlZSB2aXN1YWxpemF0aW9uIGJlbG93KSouCiAgICAKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCnFwbG90KGduZ19hY19nbmdfT0ZGX3JlcyRyZXNpZHVhbHMsIG1haW4gPSAiSGlzdG9ncmFtIG9mIEdvL05vLUdvIFJlYWN0aW9uIFRpbWUgUmVzaWR1YWxzIGZvciB0aGUgUG93ZXJlZCBPRkYgR3JvdXAiKSArIAogIHRoZW1lX2NsYXNzaWMoKQoKYGBgCiAgIAotIFRoZSBTaGFwaXJvLVdpbGsgdGVzdCBvZiBub3JtYWxpdHkgd2FzIHNpZ25pZmljYW50IChiYXNlZCBvbiAkXGFscGhhID0gMC4wNSQpLCAqVyogPSBgciByb3VuZChhcy5udW1lcmljKGduZ19hY19nbmdfT0ZGX3NoYXAkc3RhdGlzdGljWyJXIl0pLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19hY19nbmdfT0ZGX3NoYXAkcC52YWx1ZSlgICooc2VlIGNvZGUgYmVsb3cpKi4gIAogICAKYGBge3J9CgpnbmdfYWNfZ25nX09GRl9zaGFwID0gc2hhcGlyby50ZXN0KGduZ19hY19nbmdfT0ZGX3JlcyRyZXNpZHVhbHMpCmduZ19hY19nbmdfT0ZGX3NoYXAKCmBgYAoKLSBUaGUgZGF0YSdzIFNrZXduZXNzIGFuZCBLdXJ0b3NpcyB3YXMgZXhhbWluZWQgYW5kIHNob3dlZCB0aGF0IGJvdGggdGhlIFNrZXduZXNzIChyYW5nZTogYHIgcm91bmQobWluKGduZ19hY19nbmdfT0ZGX3NrX3RbMSxdKSwgMilgIHRvIGByIHJvdW5kKG1heChnbmdfYWNfZ25nX09GRl9za190WzEsXSksIDIpYCkgYW5kIEt1cnRvc2lzIChyYW5nZTogYHIgcm91bmQobWluKGduZ19hY19nbmdfT0ZGX3NrX3RbMixdKSwgMilgIHRvIGByIHJvdW5kKG1heChnbmdfYWNfZ25nX09GRl9za190WzIsXSksIDIpYCkgd2VyZSB3aXRoaW4gdGhlIGFjY2VwdGFibGUgcmFuZ2Ugb2YgJFxwbSAyLjAkIGFuZCAkXHBtIDkuMCQsIHJlc3BlY3RpdmVseSAoU2NobWlkZXIsIFppZWdsZXIsIERhbmF5LCBCZXllciwgJiBCw7xobmVyLCAyMDEwKSAqKHNlZSB0YWJsZSBiZWxvdykqLiAgCgpgYGB7cn0KCiMgdXNlIHRoZSBkZXNjcmlwdGl2ZXMgZGF0YSAtLSBnbmdfYWNfZ25nX09GRl9kZXMKCiMgb3JnYW5pemUgdGhlIGRhdGEgaW50byBhIG5ldyBkYXRhIGZyYW1lIGRlcGljdGluZyB0aGUgU2tldywga3VydG9zaXMsIGFuZCBzYW1wbGUgc2l6ZSAobikuCiAgZ25nX2FjX2duZ19PRkZfc2tfdCA9IGNiaW5kKHQoZ25nX2FjX2duZ19PRkZfZGVzWyJydF9hdjEiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2FjX2duZ19PRkZfZGVzWyJydF9hdjIiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQoZ25nX2FjX2duZ19PRkZfZGVzWyJydF9hdjMiLCBjKCJza2V3IiwgImt1cnRvc2lzIiwgIm4iKV0pKQogICAgY29sbmFtZXMoZ25nX2FjX2duZ19PRkZfc2tfdCkgPSBjKCJPbiBEZXNrIiwgIkluIFBvY2tldC9CYWciLCAiT3V0c2lkZSIpCiAgICByb3duYW1lcyhnbmdfYWNfZ25nX09GRl9za190KSA9IGMoIlNrZXduZXNzIiwgIkt1cnRvc2lzIiwgIm4iKQogICAgCiMgdXNlIGthYmxlIHRvIHNob3cgdGhlIGRlc2NyaXB0aXZlcyB0YWJsZQogIGthYmxlKGduZ19hY19nbmdfT0ZGX3NrX3QsIGNhcHRpb24gPSAiU2tld25lc3MgYW5kIEt1cnRvc2lzIG9mIHRoZSBSZWFjdGlvbiBUaW1lIG9uIHRoZSBHby9Oby1HbyBUYXNrIGZvciB0aGUgUG93ZXJlZCBPRkYgR3JvdXAiLCBkaWdpdHMgPSA0LCBhbGlnbiA9ICdjJykgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpICU+JQogIGFkZF9oZWFkZXJfYWJvdmUoYygiICIsICJTbWFydHBob25lIExvY2F0aW9uIiA9IDMpKQoKYGBgCgotIFRoZXJlZm9yZSwgYmFzZWQgb24gYWxsIHRoZSBub3JtYWxpdHkgYXNzdW1wdGlvbiBjaGVja3MsIG5vcm1hbGl0eSB3YXMgYXNzdW1lZCB0byBiZSB3aXRoaW4gdGhlIGFjY2VwdGFibGUgcmFuZ2UgZm9yIHRoZSBhbmFseXNpcy4gQWRkaXRpb25hbGx5LCBpdCBzaG91bGQgYmUgbm90ZWQgdGhhdCBBTk9WQSBhbmFseXNlcyBjYW4gYmUgcm9idXN0IHRvIHZpb2xhdGlvbnMgb2Ygbm9ybWFsaXR5IChHYXJkbmVyICYgVHJlbWJsYXksIDIwMDcpLgoKPHNwYW4gc3R5bGU9ImNvbG9yOkRhcmtCbHVlOyBmb250LXNpemU6MThweDsiPjMuIEhvbW9nZW5laXR5IG9mIFZhcmlhbmNlPC9zcGFuPiAKClRoaXMgYXNzdW1wdGlvbiB3YXMgdGVzdGVkIGJ5IGNvbmR1Y3RpbmcgTGV2ZW5lJ3MgVGVzdCBmb3IgSG9tb2dlbmVpdHkgb2YgVmFyaWFuY2UgZm9yIHRoZSBiZXR3ZWVuLXN1YmplY3RzIHZhcmlhYmxlLiAgCgotIFRoZSBob21vZ2VuZWl0eSBhc3N1bXB0aW9uIHdhcyBtZXQgKGJhc2VkIG9uICRcYWxwaGEgPSAwLjA1JCkgZm9yIHNtYXJ0cGhvbmUgbG9jYXRpb24sICpGKihgciBnbmdfYWNfZ25nX09GRl9sZXZfbG9jJERmWzFdYCwgYHIgZ25nX2FjX2duZ19PRkZfbGV2X2xvYyREZlsyXWApID0gYHIgcm91bmQoZ25nX2FjX2duZ19PRkZfbGV2X2xvY1syXVsxLDFdLCAyKWAsICpwKiBgciBwX3JvdW5kKGduZ19hY19nbmdfT0ZGX2xldl9sb2NbM11bMSwxXSlgICooc2VlIGNvZGUgYmVsb3cpKi4KCmBgYHtyfQoKIyBjb25kdWN0IGxldmVuZSdzCiAgIyBmb3IgbG9jYXRpb24KICBnbmdfYWNfZ25nX09GRl9sZXZfbG9jID0gbGV2ZW5lVGVzdChkYXRhID0gZ25nX2FjX2duZ19PRkZfZGF0YSwgcnRfYXYgfiBhcy5mYWN0b3IobG9jYXRpb24pLCBjZW50ZXIgPSBtZWRpYW4pCiAgZ25nX2FjX2duZ19PRkZfbGV2X2xvYwoKYGBgCgo8L2RldGFpbHM+ICAKCiMjIyMjIyBTaW1wbGUgTWFpbiBFZmZlY3RzOiBSZXN1bHRzICAKCkFsbCByZXN1bHRzIHdlcmUgYmFzZWQgb24gYSBIb2xtLUJvbmZlcnJvbmkgYWRqdXN0bWVudCBhcHBsaWVkIHRvIHRoZSBvcmlnaW5hbCBwLXZhbHVlcy4gQmVsb3cgYXJlIHRoZSByZXBvcnRlZCBzdGF0aXN0aWNzIGZvciBib3RoIGFuYWx5c2VzIChpLmUuIHBvd2VyZWQgT04gYW5kIE9GRiksIGZvbGxvd2VkIGJ5IGEgdGFibGUgZGVwaWN0aW5nIHRoZSBBTk9WQSByZXN1bHRzLgoKKipNYWluIEVmZmVjdCBvZiBTbWFydHBob25lIExvY2F0aW9uIGluIHRoZSBQb3dlcmVkIE9OIENvbmRpdGlvbioqCgpUaGVyZSB3YXMgbm8gc2lnbmlmaWNhbnQgbWFpbiBlZmZlY3Qgb2Ygc21hcnRwaG9uZSBsb2NhdGlvbiBvbiByZWFjdGlvbiB0aW1lIGZvciB0aG9zZSBpbiB0aGUgcG93ZXJlZCBPRkYgY29uZGl0aW9uLCAqRiooYHIgZ25nX2FjX2duZ19QT1dfdFsxLDJdYCwgYHIgZ25nX2FjX2duZ19QT1dfdFsxLDNdYCkgPSBgciByb3VuZChnbmdfYWNfZ25nX1BPV190WzEsNl0sIDIpYCwgKnAqIGByIHBfcm91bmQoZ25nX2FjX2duZ19QT1dfdFsxLDddKWAsICRcZXRhXnsyfSQgYHIgcF9yb3VuZChnbmdfYWNfZ25nX1BPV190WzEsOV0pYC4KCioqTWFpbiBFZmZlY3Qgb2YgU21hcnRwaG9uZSBMb2NhdGlvbiBpbiB0aGUgUG93ZXJlZCBPRkYgQ29uZGl0aW9uKioKClRoZXJlIHdhcyBubyBzaWduaWZpY2FudCBtYWluIGVmZmVjdCBvZiBzbWFydHBob25lIGxvY2F0aW9uIG9uIHJlYWN0aW9uIHRpbWUgZm9yIHRob3NlIGluIHRoZSBwb3dlcmVkIE9GRiBjb25kaXRpb24sICpGKihgciBnbmdfYWNfZ25nX1BPV190WzIsMl1gLCBgciBnbmdfYWNfZ25nX1BPV190WzIsM11gKSA9IGByIHJvdW5kKGduZ19hY19nbmdfUE9XX3RbMiw2XSwgMilgLCAqcCogYHIgcF9yb3VuZChnbmdfYWNfZ25nX1BPV190WzIsN10pYCwgJFxldGFeezJ9JCBgciBwX3JvdW5kKGduZ19hY19nbmdfUE9XX3RbMiw5XSlgLgoKKipQb3N0LWhvYyBUZXN0cyoqICAKClNpbmNlIHRoZXJlIHdhcyBubyBzaWduaWZpY2FudCBtYWluIG9yIGludGVyYWN0aW9uIGVmZmVjdHMsIG5vIHBvc3QtaG9jcyB3ZXJlIGNvbXBsZXRlZC4KCgpgYGB7cn0KCiMgY3JlYXRlIGEgdGFibGUgd2l0aCB0aGUgYW5vdmEgcmVzdWx0cyBpbmNsdWRpbmcgdGhlIGFkanVzdGVkIHAtdmFsdWVzIAogICMgY3JlYXRlIGEgdGFibGUgd2l0aCBib3RoIHBvd2VyIGNvbmRpdGlvbiBkYXRhCiAgZ25nX2FjX2duZ19QT1dfdCA9IHJiaW5kKGduZ19hY19nbmdfT05fYW5vdmEkQU5PVkFbZ25nX2FjX2duZ19PTl9hbm92YSRBTk9WQSRFZmZlY3QgPT0gImxvY2F0aW9uIixdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgZ25nX2FjX2duZ19PRkZfYW5vdmEkQU5PVkFbZ25nX2FjX2duZ19PRkZfYW5vdmEkQU5PVkEkRWZmZWN0ID09ICJsb2NhdGlvbiIsXSkKICAjIHJlcGxhY2UgdGhlIHAtdmFsdWVzIHdpdGggdGhlIGFkanVzdGVkIHZhbHVlcyAoSG9sbS1Cb25mZXJyb25pIGFkanVzdG1lbnQpCiAgZ25nX2FjX2duZ19QT1dfdCRwID0gcC5hZGp1c3QoYyhnbmdfYWNfZ25nX09OX2Fub3ZhJEFOT1ZBJHBbMl0sIGduZ19hY19nbmdfT0ZGX2Fub3ZhJEFOT1ZBJHBbMl0pLCBtZXRob2QgPSAiaG9sbSIpCiAgIyBhZGp1c3QgdGhlIHA8LjA1IGNvbHVtbiB0byByZWZsZWN0IHRoZSBuZXcgZGF0YSAoaWYgdGhlcmUgd2FzIGFueSBjaGFuZ2UpCiAgZ25nX2FjX2duZ19QT1dfdCRgcDwuMDVgID0gaWZlbHNlKGduZ19hY19nbmdfUE9XX3QkcCA8IDAuMDUsICIqIiwgIiIpCiAgIyByZXBsYWNlIHRoZSBuYW1lcyBpbiB0aGUgZWZmZWN0cyBjb2x1bW4gd2l0aCAiT04iICYgIk9GRiIKICBnbmdfYWNfZ25nX1BPV190JEVmZmVjdCA9IGMoIk9OIiwgIk9GRiIpCiAgIyByZW5hbWUgdGhlIGNvbHVtbnMKICBjb2xuYW1lcyhnbmdfYWNfZ25nX1BPV190KSA9IGMoIlNtYXJ0cGhvbmUgUG93ZXIgQ29uZGl0aW9uIiwgIkRGbiIsICJERmQiLCAiU1NuIiwgIlNTZCIsICJGIiwgInAiLCAicDwuMDUiLCAiZ2VzIikKICAjIHJlbW92ZSB0aGUgcm93IG5hbWVzCiAgcm93bmFtZXMoZ25nX2FjX2duZ19QT1dfdCkgPSBOVUxMCgojIHNob3cgQU5PVkEgcmVzdWx0cyBpbiBrYWJsZSB0YWJsZSAKa2FibGUoZ25nX2FjX2duZ19QT1dfdCwgY2FwdGlvbiA9ICJTaW1wbGUgTWFpbiBFZmZlY3RzIEFuYWx5c2VzOiBSZWFjdGlvbiBUaW1lIG9uIHRoZSBHby9Oby1HbyBUYXNrIGZvciB0aGUgR28vTm8tR28gRmlyc3QgQmFsYW5jZSBHcm91cCIsIGRpZ2l0cyA9IDQsIGFsaWduID0gJ2MnLCBlc2NhcGUgPSBGQUxTRSkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpIAoKYGBgCgoKIyMjIyMgVmlzdWFsaXphdGlvbnMKClRoZSBmb2xsb3dpbmcgc2hvd3MgYSB2aXN1bGl6YXRpb24gb2YgQWNjdXJhY3kgKGkuZS4gcmVhY3Rpb24gdGltZSkgb24gdGhlIEN1ZS1EZXBlbmRlbnQgR28vTm8tZ28gVGFzay4gVGhlcmUgd2FzIGEgc2lnbmlmaWNhbnQgdGhyZWUtd2F5IGludGVyYWN0aW9uIGluIHRoZSBtYWluIEFOT1ZBIChpLmUuIGJldHdlZW4gc21hcnRwaG9uZSBsb2NhdGlvbiwgc21hcnRwaG9uZSBwb3dlciwgYW5kIGJhbGFuY2UpLiBBZGRpdGlvbmFsbHksIHRoZSBtYWluIGZhY3RvcnMgb2YgaW50ZXJlc3Qgd2VyZSB0aGUgc21hcnRwaG9uZSBjb25kaXRpb25zIChpLmUuIGxvY2F0aW9uIGFuZCBwb3dlcikuIFRoZXJlZm9yZSwgdHdvIHZpc3VhbGl6YXRpb25zIGFyZSBzaG93biBkZXBpY3RpbmcgdGhlIHNtYXJ0cGhvbmUgY29uZGl0aW9ucywgb25lIGZvciBlYWNoIG9mIHRoZSBsZXZlbHMgb2YgdGhlIGJhbGFuY2UgZmFjdG9yLiAgCgpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIy0tRm9yIHRoZSAiT1NwYW4gRmlyc3QiIEJhbGFuY2UgQ29uZGl0aW9uCiMgdXNlIHRoZSBkYXRhIHN1YnNldHMgZnJvbSB0aGUgcG9zdC1ob2MgYW5hbHlzZXMgKGkuZS4gdGhlIHNpbXBsZSB0d28td2F5IGludGVyYWN0aW9ucykgLS0gZ25nX2FjX29zcGFuX2RhdGEgIApnbmdfYWNfYmFyX29zcGFuX2RhdGEgPSBzZWxlY3QoZ25nX2FjX29zcGFuX2RhdGEsIC1wYXJ0aWNpcGFudCwgLWJhbGFuY2UpCiAgIyByZW1vdmUgcm93IG5hbWVzCiAgcm93bmFtZXMoZ25nX2FjX2Jhcl9vc3Bhbl9kYXRhKSA9IE5VTEwgIAogICAgICAgCiMgcGxvdCBiYXIgZ3JhcGggLSBHT09ECmduZ19hY19iYXJfb3NwYW4gPSAKICBnZ3Bsb3QoZ25nX2FjX2Jhcl9vc3Bhbl9kYXRhLCBhZXMoeCA9IGxvY2F0aW9uLCB5ID0gcnRfYXYsIGZpbGwgPSBwb3dlciksIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBnZW9tX2JhcihzdGF0ID0gInN1bW1hcnkiLCBmdW4ueSA9ICJtZWFuIiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArIAogICAgZ3VpZGVzKHNoYXBlID0gRkFMU0UpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiY2FkZXRibHVlMyIsICJkZWVwc2t5Ymx1ZTQiKSkgKyAKICBsYWJzKHRpdGxlID0gIlBlcmZvcm1hbmNlIG9uIHRoZSBHby9Oby1HbyBUYXNrIFxuZm9yIHRoZSBPU3BhbiBGaXJzdCBCYWxhbmNlIENvbmRpdGlvbiIsCiAgICAgICBzdWJ0aXRsZSA9ICJBY2N1cmFjeSAoYXZlcmFnZSByZWFjdGlvbiB0aW1lKSIsCiAgICAgICB4ID0gIlNtYXJ0cGhvbmUgTG9jYXRpb24iLCAKICAgICAgIHkgPSAiQXZlcmFnZSBSZWFjdGlvbiBUaW1lIChzZWMuKSIsIAogICAgICAgZmlsbCA9ICJTbWFydHBob25lIFBvd2VyIiwKICAgICAgIGNhcHRpb24gPSAiTm90ZTogLi4uIikgKwogICAgICAgICMgdGhlICJcbiIgaGVyZSBkZW5vdGUgdGhhdCB5b3Ugd2FudCBhIG5ldyBsaW5lIGZvcm1lZCBpbiB0aGUgdGV4dAogIGdlb21fcG9pbnQoc3RhdCA9ICJpZGVudGl0eSIsIGFlcyhjb2xvciA9IHBvd2VyKSwgc2l6ZSA9IDEsIAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAuNTMpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImRlZXBza3libHVlNCIsICJwdXJwbGU0IikpICsgCiAgZ2VvbV9wb2ludChzdGF0PSJzdW1tYXJ5IiwgZnVuLnk9Im1lYW4iLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKC45KSwgc2l6ZSA9IDEuNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGdlb21fZXJyb3JiYXIoZGF0YSA9IGduZ19hY19iYXJfb3NwYW5fZGF0YSwgc3RhdCA9ICJzdW1tYXJ5IiwgZnVuLnltaW4gPSBmdW5jdGlvbih4KSBtZWFuKHgpIC0gc2QoeCkvc3FydChsZW5ndGgoeCkpLCAKICAgICAgICAgICAgICAgIGZ1bi55bWF4ID0gZnVuY3Rpb24oeCkgbWVhbih4KSArIHNkKHgpL3NxcnQobGVuZ3RoKHgpKSwgc2l6ZT0gLjUsIHdpZHRoPSAuMjUsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoLjkpKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxMyksIAogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAsIHNpemUgPSAxMiwgZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMykpICMrCiAgI3NjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKG1pbihnbmdfYWNfYmFyX29zcGFuX2RhdGEkcnRfYXYpLCBtYXgoZ25nX2FjX2Jhcl9vc3Bhbl9kYXRhJHJ0X2F2KSkpCgojLS1Gb3IgdGhlICJHby9Oby1HbyBGaXJzdCIgQmFsYW5jZSBDb25kaXRpb24KIyB1c2UgdGhlIGRhdGEgc3Vic2V0cyBmcm9tIHRoZSBwb3N0LWhvYyBhbmFseXNlcyAoaS5lLiB0aGUgc2ltcGxlIHR3by13YXkgaW50ZXJhY3Rpb25zKSAtLSBnbmdfYWNfZ25nX2RhdGEgIApnbmdfYWNfYmFyX2duZ19kYXRhID0gc2VsZWN0KGduZ19hY19nbmdfZGF0YSwgLXBhcnRpY2lwYW50LCAtYmFsYW5jZSkKICAjIHJlbW92ZSByb3cgbmFtZXMKICByb3duYW1lcyhnbmdfYWNfYmFyX2duZ19kYXRhKSA9IE5VTEwgIAogICAgICAgCiMgcGxvdCBiYXIgZ3JhcGggLSBHT09ECmduZ19hY19iYXJfZ25nID0gCiAgZ2dwbG90KGduZ19hY19iYXJfZ25nX2RhdGEsIGFlcyh4ID0gbG9jYXRpb24sIHkgPSBydF9hdiwgZmlsbCA9IHBvd2VyKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGdlb21fYmFyKHN0YXQgPSAic3VtbWFyeSIsIGZ1bi55ID0gIm1lYW4iLCBwb3NpdGlvbiA9ICJkb2RnZSIpICsgCiAgICBndWlkZXMoc2hhcGUgPSBGQUxTRSkgKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJjYWRldGJsdWUzIiwgImRlZXBza3libHVlNCIpKSArIAogIGxhYnModGl0bGUgPSAiUGVyZm9ybWFuY2Ugb24gdGhlIEdvL05vLUdvIFRhc2sgXG5mb3IgdGhlIEdvL05vLUdvIEZpcnN0IEJhbGFuY2UgQ29uZGl0aW9uIiwKICAgICAgIHN1YnRpdGxlID0gIkFjY3VyYWN5IChhdmVyYWdlIHJlYWN0aW9uIHRpbWUpIiwKICAgICAgIHggPSAiU21hcnRwaG9uZSBMb2NhdGlvbiIsIAogICAgICAgeSA9ICJBdmVyYWdlIFJlYWN0aW9uIFRpbWUgKHNlYy4pIiwgCiAgICAgICBmaWxsID0gIlNtYXJ0cGhvbmUgUG93ZXIiLAogICAgICAgY2FwdGlvbiA9ICJOb3RlOiAuLi4iKSArCiAgICAgICAgIyB0aGUgIlxuIiBoZXJlIGRlbm90ZSB0aGF0IHlvdSB3YW50IGEgbmV3IGxpbmUgZm9ybWVkIGluIHRoZSB0ZXh0CiAgZ2VvbV9wb2ludChzdGF0ID0gImlkZW50aXR5IiwgYWVzKGNvbG9yID0gcG93ZXIpLCBzaXplID0gMSwgCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IC41MyksIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiZGVlcHNreWJsdWU0IiwgInB1cnBsZTQiKSkgKyAKICBnZW9tX3BvaW50KHN0YXQ9InN1bW1hcnkiLCBmdW4ueT0ibWVhbiIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoLjkpLCBzaXplID0gMS41LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZ2VvbV9lcnJvcmJhcihkYXRhID0gZ25nX2FjX2Jhcl9nbmdfZGF0YSwgc3RhdCA9ICJzdW1tYXJ5IiwgZnVuLnltaW4gPSBmdW5jdGlvbih4KSBtZWFuKHgpIC0gc2QoeCkvc3FydChsZW5ndGgoeCkpLCAKICAgICAgICAgICAgICAgIGZ1bi55bWF4ID0gZnVuY3Rpb24oeCkgbWVhbih4KSArIHNkKHgpL3NxcnQobGVuZ3RoKHgpKSwgc2l6ZT0gLjUsIHdpZHRoPSAuMjUsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoLjkpKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxMyksIAogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAsIHNpemUgPSAxMiwgZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMykpICMrCiAgI3NjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKG1pbihnbmdfYWNfYmFyX2duZ19kYXRhJHJ0X2F2KSwgbWF4KGduZ19hY19iYXJfZ25nX2RhdGEkcnRfYXYpKSkKCiMgc2hvdyB0aGUgZmlndXJlcwogICMgZm9yIHRoZSBPU3BhbiBGaXJzdCBCYWxhbmNlIENvbmRpdGlvbgogIGduZ19hY19iYXJfb3NwYW4KICAjIGZvciB0aGUgR28vTm8tR28gRmlyc3QgQmFsYW5jZSBDb25kaXRpb24KICBnbmdfYWNfYmFyX2duZwoKYGBgCgojIyBUZXN0aW5nIHRoZSBNb2RlcmF0aW9uIEh5cG90aGVzaXM6ICAKCiMjIyBTQUQgIAoKIyMjIyBGYWN0b3IgQW5hbHlzaXMgIAoKVG8gZXhhbWluZSB0aGUgdW5kZXJseWluZyBmYWN0b3JzIG1lYXN1cmVkIGJ5IHRoZSBTbWFydHBob25lIEF0dGFjaG1lbnQgYW5kIERlcGVuZGVjeSBJbnZlbnRvcnkgKFNBRCkgZnJvbSBXYXJkIGV0IGFsLiAoMjAxNyksIGEgcHJpbmNpcGFsIGNvbXBvbmVudHMgZmFjdG9yIGFuYWx5c2lzIHdpdGggYSBWYXJpbWF4IHJvdGF0aW9uIHdhcyBjb21wbGV0ZWQgb24gcGFydGljaXBhbnQncyBTQUQgZGF0YS4gVGhlIGFuYWx5c2lzIHdhcyBkb25lIGV4cGxvcmF0b3JpbHkgYW5kIHdhcyBjb21wYXJlZCB0byBXYXJkIGV0IGFsLidzIGZpbmRpbmdzLCB3aGVyZSB0aGV5IGZvdW5kIHR3byBmYWN0b3JzLCBzbWFycGhvbmUgZGVwZW5kZW5jZSAoaS5lLiBzaXggaXRlbXM7IGl0ZW1zICMxLTY7IDMxLjAyJSBvZiB0aGUgdmFyaWFuY2UpIGFuZCBlbW90aW9uYWwgYXR0YWNobWVudCAoaS5lLiBmaXZlIGl0ZW1zOyBpdGVtcyAjOC0xMTsgMjEuNjUlIG9mIHRoZSB2YXJpYW5jZSksIHdoaWNoIGV4cGxhaW5lZCA1Mi42NyUgb2YgdGhlIHRvdGFsIHZhcmlhbmNlLiBJdCBzaG91bGQgYmUgbm90ZWQgdGhhdCB0d28gaXRlbXMgKGkuZS4gaXRlbSAjNyBhbmQgMTMpIGRpZCBub3Qgc3Ryb25nbHkgbG9hZCBvbnRvIGEgZmFjdG9yIGFuZCB3ZXJlIGV4Y2x1ZGVkIGZyb20gc3Vic2VxdWVudCBhbmFseXNlcy4KClRvIHBlcmZvcm0gdGhlIHByaW5jaXBhbCBjb21wb25lbnRzIGZhY3RvciBhbmFseXNpcywgd2UgZmlyc3QgZXhhbWluZWQgdGhlIGRhdGEgZm9yICgxKSBtaXNzaW5nIGRhdGEsICgyKSBjb3JyZWxhdGlvbnMgYmV0d2VlbiB0aGUgaXRlbXMsIGFuZCAoMykgdGhlIGZhY3RvcmFiaWxpdHkgb2YgdGhlIGRhdGEuCgoxLiBNaXNzaW5nIERhdGEKCiAgLSBGcm9tIHRoZSBkZXNjcmlwdGl2ZXMgdGFibGUsIGl0IHNlZW1zIHRoYXQgdGhlcmUgaXMgbm8gbWlzc2luZyBvciBpbmNvbXBsZXRlIGRhdGEuIFRoaXMgd2FzIGNvbmZpcm1lZCBieSBmaW5kaW5nIHRoZSBjb21wbGV0ZSBjYXNlcywgd2hpY2ggd2VyZSBlcXVhbCB0byB0aGUgdG90YWwgc2FtcGxlIHNpemUgKGkuZS4gYHIgZmFfY29tcGxldGVgKS4gVGhlcmVmb3JlLCBubyBkYXRhIHdhcyByZW1vdmVkIGR1ZSB0byBtaXNzaW5nIHZhbHVlcyBmb3IgdGhpcyBhbmFseXNpcyAqKHNlZSBkZXNjcmlwdGl2ZXMgdGFibGUgYmVsb3cpKi4KICAgIApgYGB7cn0KCiMgZ2V0IGEgZGF0YSBmcmFtZSB3aXRoIHRoZSBTQUQgaXRlbXMgb25seSBmb3IgdGhlIGZhY3RvciBhbmFseXNpcwpmYV9kYXRhID0gZHBseXI6OnNlbGVjdChmYWN0b3JfYW5hbHlzaXMsIFNBRF8xOlNBRF8xMykKCiMgZmluZCB0aGUgdG90YWwgY29tcGxldGUgY2FzZXMgdG8gZmluZCBhbnkgbWlzc2luZyBkYXRhIGZyb20gdGhlIGRhdGEgLS0gYW55IHBhcnRpY2lwYW50IHdpdGggbWlzc2luZyBkYXRhIG11c3QgYmUgcmVtb3ZlZApmYV9jb21wbGV0ZSA9IHN1bShjb21wbGV0ZS5jYXNlcyhmYV9kYXRhKSkKCiMgU2hvdyBkZXNjcmlwdGl2ZXMgZm9yIHRoZSBmYWN0b3IgYW5hbHlzaXMgZGF0YQpmYV9kZXMgPSBkZXNjcmliZShmYV9kYXRhKQoKIyBzaG93IGRlc2NyaXB0aXZlcyBpbiBrYWJsZSB0YWJsZSAKa2FibGUoZmFfZGVzLCBjYXB0aW9uID0gIkRlc2NyaXB0aXZlcyBmb3IgSXRlbXMgaW4gdGhlIFNBRCIsIGRpZ2l0cyA9IDQsIGFsaWduID0gJ2MnLCBlc2NhcGUgPSBGQUxTRSkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpIAoKYGBgCgoKMi4gQ29ycmVsYXRpb25zIGJldHdlZW4gdGhlIEl0ZW1zCgogIC0gVGhlIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIHRoZSBpdGVtcyB3ZXJlIGV4YW1pbmVkIHRvIGRldGVybWluZSBpZiB0aGV5IHdlcmUgZWl0aGVyIG5vdCBoaWdoIGVub3VnaCAoaS5lLiwgciA8IC4zMCkgb3IgdG9vIGhpZ2ggKGkuZS4sIHIgPiAuODApLiAKICAgIC0gVGhlIGNvcnJlbGF0aW9ucyBmb3IgdGhlIDEzIGl0ZW1zIGluIHRoZSBTQUQgcmFuZ2VkIGZyb20gKnIqKGByIGZhX2NvciRuWzEsMV0gLSAyYCkgYHIgcF9yb3VuZChtaW4oZmFfY29yJHJbd2hpY2goZmFfY29yJHIgPCAxKV0pKWAgdG8gKnIqKGByIGZhX2NvciRuWzEsMV0gLSAyYCkgYHIgcF9yb3VuZChtYXgoZmFfY29yJHJbd2hpY2goZmFfY29yJHIgPCAxKV0pKWAsICpwKiBgciBwX3JvdW5kKG1heChmYV9jb3IkUFt3aGljaCghaXMubmEoZmFfY29yJFApKV0pKWAuCiAgICAtIEEgdmlzdWFsIGluc3BlY3Rpb24gb2YgdGhlIGNvcnJlbGF0aW9ucyBzaG93ZWQgdGhhdCBpdGVtcyAxMiBhbmQgMTMgbWlnaHQgbm90IGJlIGNvcnJlbGF0ZWQgZW5vdWdoIHdpdGggdGhlIHJlc3Qgb2YgdGhlIGl0ZW1zIChpLmUuIGByIGxlbmd0aCh3aGljaChmYV9jb3IkclssMTJdIDwgLjMwKSlgIGFuZCBgciBsZW5ndGgod2hpY2goZmFfY29yJHJbLDEzXSA8IC4zMCkpYCBjb3JyZWxhdGlvbnMgYmVsb3cgLjMwLCByZXNwZWN0aXZlbHkpLiBUaGVyZSB3ZXJlIG5vIGlzc3VlcyBhc3NvY2lhdGVkIHdpdGggdG9vIG1hbnkgaGlnaCBjb3JyZWF0aW9ucyBmb3IgYW55IGl0ZW1zLiAKICAgIC0gVGhlIGxvd2VyIGNvcnJlbGF0aW9ucyBmb3IgaXRlbXMgMTIgYW5kIDEzIHNob3VsZCBiZSBrZXB0IGluIG1pbmQgd2hlbiBjb21wbGV0aW5nIHRoZSBmYWN0b3IgYW5hbHlzaXMgYW5kIHRoZXNlIGl0ZW1zIG1heSBiZSByZW1vdmVkLiAgCiAgLSBUbyBjaGVjayBmb3IgbXVsdGljb2xsaW5lYXJpdHksIHRoZSBkZXRlcm1pbmFudCBvZiB0aGUgY29ycmVsYXRpb24gbWF0cml4IHdhcyBjYWxjdWxhdGVkLiBUaGUgZGV0ZXJtaW5hbnQgd2FzIGdyZWF0ZXIgdGhhbiB0aGUgbmVjZXNzYXJ5IHZhbHVlIG9mIDAuMDAwMDEgKGkuZS4sIGByIHJvdW5kKGZhX2RldCwgNSlgKSwgc28sIHRoZXJlIHdhcyBubyBpc3N1ZXMgd2l0aCBtdWx0aWNvbGxpbmVhcml0eSAoRmllbGQgZXQgYWwuLCAyMDEyKS4KICAtIFRoZXJlZm9yZSwgYWxsIGl0ZW1zIGluIHRoZSBTQUQgY29ycmVsYXRlZCByZWFzb25hYmx5IHdpdGggZWFjaCBvdGhlciBhbmQgd2l0aG91dCBhbiBleGNlc3NpdmVseSBsYXJnZSBjb3JyZWFsYXRpb24gc28gbm8gaXRlbXMgd2VyZSByZW1vdmVkIGF0IHRoaXMgc3RhZ2UuCgpgYGB7cn0KCiMgZ2V0IHRoZSBwZWFyc29uIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIGFsbCBpdGVtcyAoYW5kIGNvcnJlc3BvbmRpbmcgcC12YWx1ZXMpCmZhX2NvciA9IHJjb3JyKGFzLm1hdHJpeChmYV9kYXRhKSwgdHlwZSA9ICJwZWFyc29uIikgCgojIG1ha2UgYSB0YWJsZSB3aXRoIHRoZSBkYXRhIHRvIGRpc3BsYXkgaXQgYmV0dGVyCmZhX2Nvcl90ID0gYXMuZGF0YS5mcmFtZShmYV9jb3IkcikKICAjIGluY2x1ZGUgb25seSB0aGUgbG93ZXIgdHJpYW5nbGUgb2YgdGhlIGRhdGEKICBmYV9jb3JfdFt1cHBlci50cmkoZmFfY29yX3QpXSA9IE5BCiAgCiMgZmluZCB0aGUgZGV0ZXJtaW5hbnQgb2YgdGhlIGNvcnJlbGF0aW9uIG1hdHJpeApmYV9kZXQgPSBkZXQoZmFfY29yJHIpCgojIFByaW50IHRhYmxlIHVzaW5nIGthYmxlCiAgIyBtYWtlIGFueSBOQXMgYXBwZWFyIGFzIGJsYW5rIHdpdGhpbiBrYWJsZQogIG9wdHMgPSBvcHRpb25zKGtuaXRyLmthYmxlLk5BID0gIiIpCiAgIyBwcmludCB0YWJsZQogIGthYmxlKGZhX2Nvcl90LCBjYXB0aW9uID0gIlBlYXJzb24gQ29ycmVsYXRpb25zIGJldHdlZW4gSXRlbXMgaW4gdGhlIFNBRCIsIGRpZ2l0cyA9IDQsIGFsaWduID0gJ2MnLCBlc2NhcGUgPSBGQUxTRSkgJT4lCiAgICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCAiaG92ZXIiLCBmdWxsX3dpZHRoID0gRikgJT4lCiAgICBhZGRfZm9vdG5vdGUoInAgPCAuMDAxIiwgbm90YXRpb24gPSAiYWxwaGFiZXQiKQogICAgIyByZXN0b3JlIHRoZSBvcmlnaW5hbCBvcHRpb25zIHNvIHRoYXQgIk5BIiBzaG93cyB1cCBhZ2FpbgogICAgb3B0aW9ucyhvcHRzKQoKYGBgCiAKICAtIEFub3RoZXIgd2F5IHRvIHZpc3VhbGl6ZSB0aGlzIGlzIHVzaW5nIGEgU2NhdHRlciBQbG90IE1hdHJpeAogICAgLSBUaGlzIHNob3dzOiAoMSkgYSBzY2F0dGVyIHBsb3QgYmVsbG93IHRoZSBsb3dlciBkaWFnb25hbCwgd2l0aCBhIGxpbmUgb2YgYmVzdCBmaXQgKHJlZCk7ICgyKSBhIGhpc3RvcmdyYW0gYW5kIGRlbnNpdHkgcGxvdCBvZiB0aGUgaXRlbSBvbiB0aGUgZGlhZ29uYWw7IGFuZCAoMykgdGhlIGNvcnJlbGF0aW9uIHZhbHVlcyAocGVhcnNvbiByKSBhYm92ZSB0aGUgZGlhZ29uYWwsIHdpdGggY29ycmVzcG9uZGluZyBzaWduaWZpY2FuY2Ugc2hvd24gd2l0aCBhc3Rlcmlza3MuIFRoZSB4LWF4aXMgaW4gZWFjaCBzY2F0dGVyIHBsb3QgcmVwcmVzZW50cyB0aGUgY29sdW1uIHZhcmlhYmxlIGFuZCB0aGUgeS1heGlzIHRoZSByb3cgdmFyaWFibGUuIAoKYGBge3J9CiMgc2hvdyBhIFNQTE9NIChTY2F0dGVyIFBsb3QgTWF0cml4KSBvZiB0aGUgRGF0YSAKcGFpcnMucGFuZWxzKGZhX2RhdGEsIHBjaCA9ICIuIiwgZGVuc2l0eSA9IFRSVUUsIGVsbGlwc2VzID0gRkFMU0UsIGxtID0gVFJVRSwgZGlnaXRzID0gMiwgbWV0aG9kID0gInBlYXJzb24iLCBqaWdnbGUgPSBUUlVFLCBmYWN0b3IgPSAxLCBoaXN0LmNvbCA9ICJjYWRldGJsdWUzIiwgc3RhcnMgPSBUUlVFLCBnYXAgPSAuNSwgdmVyT2RkID0gVFJVRSwgaG9yT2RkID0gVFJVRSwgbWFpbiA9ICJTY2F0dGVyIFBsb3QgTWF0cml4IG9mIEl0ZW1zIGluIHRoZSBTQUQiKQoKYGBgIAoKMy4gRmFjdG9yYWJpbGl0eSBvZiB0aGUgRGF0YQoKICAtIFRoaXMgYXNzZXNzZWQgaWYgdGhlcmUgd2VyZSBtZWFuaW5nZnVsIGxhdGVudCBmYWN0b3JzIHRvIGJlIGZvdW5kIHdpdGhpbiB0aGUgZGF0YSwgd2hpY2ggd2FzIGFzc2Vzc2VkIGluIHR3byB3YXlzOiBCYXJsZXR0J3MgdGVzdCBvZiBzcGhlcmljaXR5IGFuZCB0aGUgS2Fpc2VyLU1leWVyLU9sa2luIG1lYXN1cmUgb2Ygc2FtcGxpbmcgYWRlcXVhY3kuCiAgICAtIEJhcmxldHQncyB0ZXN0IG9mIHNwaGVyaWNpdHk6CiAgICAgIC0gVGhpcyB0ZXN0IHdhcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LCB3aGljaCBzdWdnZXN0ZWQgZ29vZCBmYWN0b3JhYmlsaXR5LCAkXGNoaV57Mn0kKGByIGZhX2JhcnRlc3QkZGZgKSA9IGByIHJvdW5kKGZhX2JhcnRlc3QkY2hpc3EsIDIpYCwgKnAqIGByIHBfcm91bmQoZmFfYmFydGVzdCRwLnZhbHVlKWAKICAgIC0gS2Fpc2VyLU1leWVyLU9sa2luIG1lYXN1cmUgb2Ygc2FtcGxpbmcgYWRlcXVhY3k6CiAgICAgIC0gVGhpcyBtZWFzdXJlIHNob3dlZCBhbiBvdmVyYWxsIG1lYXN1cmUgb2Ygc2FtcGxpbmcgYWRlcXVhY3kgKE1TQSkgYW5kIGFuIE1TQSBwZXIgaXRlbS4gVGhlIG92ZXJhbGwgTVNBIHdhcyBoaWdoZXIgdGhhbiBib3RoIHRoZSBtaW5pbXVtIGFuZCBwcmVmZXJyZWQgY3JpdGVyaWFzICgwLjUwIGFuZCAwLjYwLCByZXNwZWN0aXZlbHk7IEthaXNlciwgMTk3NCwgSHV0Y2hlc29uICYgU29mcm9uaW91LCAxOTk5KSwgJE1TQV97b3ZlcmFsbH0kID0gYHIgcm91bmQoZmFfa21vJE1TQSwgMilgLiBFYWNoIGl0ZW0ncyBNU0Egd2FzIGFsc28gaGlnaGVyIHRoYW4gdGhlIG1pbmltdW0gYW5kIHByZWZlcnJlZCBjcml0ZXJpYSwgJE1TQV97MS0xM30kID0gYHIgbWluKHJvdW5kKGZhX2ttbyRNU0FpLCAyKSlgIC0gYHIgbWF4KHJvdW5kKGZhX2ttbyRNU0FpLCAyKSlgLgogIC0gVGhlcmVmb3JlLCBib3RoIGZhY3RvcmFiaWxpdHkgdGVzdHMgY29uZmlybWVkIHRoYXQgdGhlIHBsYW5uZWQgZmFjdG9yIGFuYWx5c2lzIHdhcyBhcHByb3ByaWF0ZS4gCiAgICAKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBydW4gdGhlIEJhcmxldHQgVGVzdApmYV9iYXJ0ZXN0ID0gY29ydGVzdC5iYXJ0bGV0dChmYV9kYXRhKQpmYV9iYXJ0ZXN0CgojIHJ1biB0aGUgS01PIApmYV9rbW8gPSBLTU8oZmFfZGF0YSkKZmFfa21vCgpgYGAKCk5vdyB0aGF0IGZhY3RvcmFiaWxpdHkgd2FzIGNvbmZpcm1lZCwgd2UgZm91bmQgdGhlIGFwcHJvcHJpYXRlIG51bWJlciBvZiBmYWN0b3JzIHRvIGV4dHJhY3QuIFRoaXMgd2FzIGRvbmUgdXNpbmc6ICgxKSBhIHBhcmFsbGVsIGFuYWx5c2lzIHNjcmVlIHBsb3QsICgyKSBlaWdlbiB2YWx1ZXMgKGkuZS4sIGZyb20gdGhlIHBhcmFsbGVsIGFuYWx5c2lzKSwgYW5kICgzKSB0aGUgZmFjdG9yIHN0cnVjdHVyZSBiZXR3ZWVuIHRoZSB0d28gc29sdXRpb25zIChpLmUuLCB1c2luZyBmYWN0b3IgZGlhZ3JhbXMpLgoKMS4gUGFycmFsZWwgQW5hbHlzaXMgU2NyZWUgUGxvdC4gCgpUaGlzIHBsb3R0ZWQgdGhlIGVpZ2VudmFsdWVzIGZyb20gdGhlIGRhdGEgYW5kIGEgcGFycmFsbGVsIGFuYWx5c2lzIHdoaWNoIGdlbmVyYXRlZCByYW5kb20gY29ycmVsYXRpb24gbWF0cmljZXMuIFRoZSBudW1iZXIgb2YgZmFjdG9ycyBpcyB0aGVuIGRldGVybWluZWQgYnkgY29tcGFyaW5nIHRoZSByZXN1bHRpbmcgZWlnZW52YWx1ZXMgdG8gdGhlIG9ic2VydmVkIGRhdGEsIHRoYXQgaXMsIG9ic2VydmVkIGVpZ2VudmFsdWVzIHRoYXQgd2VyZSBoaWdoZXIgdGhhbiB0aGUgY29ycmVzcG9uZGluZyByYW5kb20gZWlnZW52YWx1ZXMgd2VyZSBtb3JlIGxpa2VseSB0byBmb3JtIG1lYW5pbmdmdWwgZmFjdG9ycy4KCi0gVGhlIHBhcnJhbGxlbCBhbmFseXNpcyBzY3JlZSBwbG90IHNob3dlZCB0aGF0IHRoZXJlIGFyZSBgciBmYV9wYXIkbmNvbXBgIGFwcHJvcHJpYXRlIGZhY3RvcnMgKGkuZS4gdXNpbmcgdGhlIHByaW5jaXBhbCBjb21wb25lbnRzIGV4dHJhY3Rpb24gbWV0aG9kKS4KICAtIEZyb20gY2xvc2VyIGluc3BlY3Rpb24gb2YgdGhlIHBsb3QsIHRoZSBsYXN0IGZhY3RvciB3YXMgdmVyeSBjbG9zZSB0byB0aGUgcmFuZG9tIGVpZ2VudmFsdWUgY3V0LW9mZiBsaW5lLCB0aGVyZWZvcmUsIHRoZSAyIGFuZCAzIGZhY3RvciBzb2x1dGlvbnMgd2VyZSBjb21wYXJlZCB0byBkZXRlcm1pbmUgdGhlIGJlc3QgZml0IChpLmUuLCB0aGUgZWlnZW4gdmFsdWVzIGFuZCBmYWN0b3Igc3RydWN0dXJlcyB3ZXJlIGV4YW1pbmVkKS4gCgpgYGB7cn0KCmZhX3BhciA9IGZhLnBhcmFsbGVsKGZhX2RhdGEsIGZhID0gInBjIiwgbWFpbiA9ICJQYXJhbGxlbCBBbmFseXNpcyBTY3JlZSBQbG90IGZvciBJdGVtcyBpbiB0aGUgU0FEIikKCmBgYAoKMi4gRWlnZW4gVmFsdWVzCgpGb3IgYSBzYW1wbGUgc2l6ZSBncmVhdGVyIHRoYW4gMjUwIChpLmUuLCBgciBmYV9jb21wbGV0ZWAgY29tcGxldGUgY2FzZXMpIHRoZSBhdmVyYWdlIGNvbW11bmFsaXRpZXMgKGkuZS4sIHRoZSBwcm9wb3J0aW9uIG9mIGNvbW1vbiB2YXJpYW5jZSB3aXRoaW4gdGhlIGl0ZW1zKSBmb3IgdGhlIHR3byBmYWN0b3IgKGByIHJvdW5kKG1lYW4oZmFfdHdvX3YkY29tbXVuYWxpdHkpLCAyKWApIGFuZCB0aHJlZSBmYWN0b3IgKGByIHJvdW5kKG1lYW4oZmFfdGhyZWVfdiRjb21tdW5hbGl0eSksIDIpYCkgc29sdXRpb25zIHdlcmUgd2lodGluIHRoZSBhY2NlcHRhYmxlIHZhbHVlIChpLmUuLCAwLjYwOyBGaWVsZCBldCBhbC4sIDIwMTIpLiBUaGVyZWZvcmUsIEthaXNlcidzIGNyaXRlcmlvbiAoaS5lLiwgYSBtZWFuaW5nZnVsIGZhY3RvciBoYXMgYW4gZWlnZW4gdmFsdWUgZ3JlYXRlciB0aGFuIDEpIHdhcyB1c2VkIGZvciB0aGUgZWlnZW4gdmFsdWVzLiBJdCBzaG91bGQgYmUgbm90ZWQgdGhhdCBhbHRob3VnaCB0aGUgYXZlcmFnZSBjb21tdW5hbGl0aWVzIHdlcmUgbm90IHZlcnkgaGlnaCwgdGhlIHNjcmVlIHBsb3QgYW5kIGZhY3RvciBkaWFncmFtcyB3ZXJlIHVzZWQgdG8gY2hvb3NlIHRoZSBhcHByb3ByaWF0ZSBudW1iZXIgb2YgZmFjdG9ycy4gIAoKLSBUaGUgZWlnZW4gdmFsdWVzICh1bnJvdGF0ZWQgc29sdXRpb24pIHNob3dlZCB0aHJlZSBtZWFuaW5nZnVsIGZhY3RvcnMgKGkuZS4sIGByIHJvdW5kKGZhX3BhciRwYy52YWx1ZXNbMTozXSwgMilgKSwgd2hpY2ggKnN1cHBvcnRlZCB0aGUgdGhyZWUtZmFjdG9yIHNvbHV0aW9uKiBhcyBhIGJldHRlciByZXByZXNlbnRhdGlvbiBvZiB0aGUgZGF0YS4gIAoKYGBge3J9CiMgRWlnZW4gdmFsdWVzCiAgIyB2aWV3IGVpZ2VuIHZhbHVlcyBmcm9tIHRoZSBwYXJhbGxlbCBhbmFseXNpcyBzY3JlZSBwbG90CiAgcm91bmQoZmFfcGFyJHBjLnZhbHVlcywgMykKYGBgCgozLiBGYWN0b3IgRGlhZ3JhbXMKCkEgZmFjdG9yIGRpYWdyYW0gZm9yIHRoZSB0d28tIGFuZCB0aHJlZS1mYWN0b3Igc29sdXRpb25zIChyb3RhdGVkIHNvbHV0aW9uKSB3YXMgdXNlZCB0byBkZXRlcm1pbmUgd2hpY2ggc29sdXRpb24gcmVwcmVzZW50cyB0aGUgbW9zdCBpbnRlcnByZXRhYmxlIHNvbHV0aW9uLiBUaGUgZGlhZ3JhbXMgc2hvdyB0aGUgZmFjdG9yIGxvYWRpbmdzIGZvciBlYWNoIGl0ZW0gb24gdGhlIGdpdmVuIGZhY3RvciBmb3Igd2hpY2ggdGhleSBsb2FkIHRoZSBoaWdoZXN0IG9uLiBUaGUgaXRlbXMgd2VyZSBvcmRlcmVkIChpLmUuLCBkZXNjZW5kaW5nKSBiYXNlZCBvbiB0aGVzZSBsb2FkaW5ncy4gIAogICpOb3RlOiBUaGUgZmFjdG9yIGRpYWdyYW1zIGFyZSBiYXNlZCBvbiB0aGUgcm90YXRlZCBzb2x1dGlvbnMgdG8gYmV0dGVyIGRpc3RyaWJ1dGUgdGhlIGZhY3RvciBsb2FkaW5ncyoKICAKLSBUaGUgZmFjdG9yIGRpYWdyYW1zIHNob3dlZCB0aGF0IHRoZSB0d28gZmFjdG9yIHNvbHV0aW9uIHJlc3VsdGVkIGluIG1vc3QgaXRlbXMgbG9hZGluZyBvbnRvIG9ubHkgb25lIGZhY3RvciBhbmQgd2FzIG5vdCBlYXNpbHkgaW50ZXJwcmV0ZWQuIFRoZSB0aHJlZSBmYWN0b3Igc29sdXRpb24gc2hvd2VkIGEgYmV0dGVyIGRpc3RyaWJ1dGlvbiBhbmQgd2FzIG1vcmUgaW50ZXJwcmV0YWJsZS4gICAKClRoZXJlZm9yZSwgdGhlICoqdGhyZWUgZmFjdG9yIHNvbHV0aW9uKiogd2FzIGNob3NlbiB0byBiZXR0ZXIgcmVwcmVzZW50IHRoZSBkYXRhLiAKCmBgYHtyfQojIy0tIFZBUklNQVggUk9UQVRJT04gIAojIHJ1biBhIGZhY3RvciBhbmFseXNpcyB0byBjb21wYXJlIHRoZSB0d28tIGFuZCB0aHJlZS1mYWN0b3Igc29sdXRpb25zIChubyByb3RhdGlvbikKICAjIDIgZmFjdG9yIHNvbHV0aW9uCiAgZmFfdHdvX3YgPSBwcmluY2lwYWwoZmFfZGF0YSwgbmZhY3RvcnMgPSAyLCByb3RhdGUgPSAidmFyaW1heCIsIHNjb3JlcyA9IFQpCiAgICAjIGNoYW5nZSBuYW1lIGluIGxvYWRpbmdzIGZvciBjbGFyaXR5IHdoZW4gdmlzdWFsaXppbmcgdGhlIG1vZGVsCiAgICBjb2xuYW1lcyhmYV90d29fdiRsb2FkaW5ncykgPSBjKCJGYWN0b3IgMSIsICJGYWN0b3IgMiIpCiAgCiAgIyAzIGZhY3RvciBzb2x1dGlvbgogIGZhX3RocmVlX3YgPSBwcmluY2lwYWwoZmFfZGF0YSwgbmZhY3RvcnMgPSAzLCByb3RhdGUgPSAidmFyaW1heCIsIHNjb3JlcyA9IFQpCiAgICAjIGNoYW5nZSBuYW1lIGluIGxvYWRpbmdzIGZvciBjbGFyaXR5IHdoZW4gdmlzdWFsaXppbmcgdGhlIG1vZGVsCiAgICBjb2xuYW1lcyhmYV90aHJlZV92JGxvYWRpbmdzKSA9IGMoIkZhY3RvciAxIiwgIkZhY3RvciAyIiwgIkZhY3RvciAzIikKCiMgRmFjdG9yIERpYWdyYW0KICAjIDIgZmFjdG9yIHNvbHV0aW9uCiAgZmEuZGlhZ3JhbShmYV90d29fdiwgbWFpbiA9ICJUd28gRmFjdG9yIFNvbHV0aW9uIGZvciBpdGVtcyBpbiB0aGUgU0FEIChWYXJpbWF4IFJvdGF0aW9uKSIsIHNvcnQgPSBUUlVFLCBhZGogPSAxLCBkaWdpdHMgPSAyKQoKICAjIDMgZmFjdG9yIHNvbHV0aW9uCiAgZmEuZGlhZ3JhbShmYV90aHJlZV92LCBtYWluID0gIlRocmVlIEZhY3RvciBTb2x1dGlvbiBmb3IgSXRlbXMgaW4gdGhlIFNBRCAoVmFyaW1heCBSb3RhdGlvbikiLCBzb3J0ID0gVFJVRSwgYWRqID0gMSwgZGlnaXRzID0gMikKICAKICAKIyMtLSBPQkxJTUlOIFJPVEFUSU9OICAKIyBydW4gYSBmYWN0b3IgYW5hbHlzaXMgdG8gY29tcGFyZSB0aGUgdHdvLSBhbmQgdGhyZWUtZmFjdG9yIHNvbHV0aW9ucyAobm8gcm90YXRpb24pCiAgIyAyIGZhY3RvciBzb2x1dGlvbgogIGZhX3R3b19vID0gcHJpbmNpcGFsKGZhX2RhdGEsIG5mYWN0b3JzID0gMiwgcm90YXRlID0gIm9ibGltaW4iLCBzY29yZXMgPSBUKQogICAgIyBjaGFuZ2UgbmFtZSBpbiBsb2FkaW5ncyBmb3IgY2xhcml0eSB3aGVuIHZpc3VhbGl6aW5nIHRoZSBtb2RlbAogICAgY29sbmFtZXMoZmFfdHdvX28kbG9hZGluZ3MpID0gYygiRmFjdG9yIDEiLCAiRmFjdG9yIDIiKQogIAogICMgMyBmYWN0b3Igc29sdXRpb24KICBmYV90aHJlZV9vID0gcHJpbmNpcGFsKGZhX2RhdGEsIG5mYWN0b3JzID0gMywgcm90YXRlID0gIm9ibGltaW4iLCBzY29yZXMgPSBUKQogICAgIyBjaGFuZ2UgbmFtZSBpbiBsb2FkaW5ncyBmb3IgY2xhcml0eSB3aGVuIHZpc3VhbGl6aW5nIHRoZSBtb2RlbAogICAgY29sbmFtZXMoZmFfdGhyZWVfbyRsb2FkaW5ncykgPSBjKCJGYWN0b3IgMSIsICJGYWN0b3IgMiIsICJGYWN0b3IgMyIpCgojIEZhY3RvciBEaWFncmFtCiAgIyAyIGZhY3RvciBzb2x1dGlvbgogIGZhLmRpYWdyYW0oZmFfdHdvX28sIG1haW4gPSAiVHdvIEZhY3RvciBTb2x1dGlvbiBmb3IgaXRlbXMgaW4gdGhlIFNBRCAoT2JsaW1pbiBSb3RhdGlvbikiLCBzb3J0ID0gVFJVRSwgYWRqID0gMSwgZGlnaXRzID0gMikKCiAgIyAzIGZhY3RvciBzb2x1dGlvbgogIGZhLmRpYWdyYW0oZmFfdGhyZWVfbywgbWFpbiA9ICJUaHJlZSBGYWN0b3IgU29sdXRpb24gZm9yIEl0ZW1zIGluIHRoZSBTQUQgKE9ibGltaW4gUm90YXRpb24pIiwgc29ydCA9IFRSVUUsIGFkaiA9IDEsIGRpZ2l0cyA9IDIpCmBgYAoKTm93IHRoYXQgd2UgZGV0ZXJtaW5lZCB0aGUgbnVtYmVyIG9mIGZhY3RvcnMgKGkuZS4sIHRocmVlKSwgd2Ugb2JzZXJ2ZWQgdGhlICoqY29tbXVuYWxpdGllcy4qKiBFYWNoIGl0ZW0ncyBjb21tdW5hbGl0eSB3YXMgdGhlIHBlcmNlbnRhZ2Ugb2YgdmFyaWFuY2UgdGhhdCB3YXMgZXhwbGFpbmVkIGJ5IHRoZSByZXRhaW5lZCBmYWN0b3JzIGZvciBlYWNoIGl0ZW0uIFRoZXNlIHJhbmdlZCBmcm9tIGByIHBlcmNlbnQobWluKGZhX2NvbSkpYCB0byBgciBwZXJjZW50KG1heChmYV9jb20pKWAsIHdpdGggYW4gYXZlcmFnZSBvZiBgciBwZXJjZW50KG1lYW4oZmFfY29tWywxXSkpYCAoc2VlIHRhYmxlIGZvciBtb3JlIGRldGFpbHMpLiAKCmBgYHtyfQojIGdldCB0aGUgY29tbXVuYWxpdGllcyBmcm9tIHRoZSBtb2RlbApmYV9jb20gPSBhcy5kYXRhLmZyYW1lKGZhX3RocmVlX3YkY29tbXVuYWxpdHkpCgojIGNyZWF0ZSBtYXRyaXggdG8gcHJlc2VudCBjb21tdW5hbGl0aWVzIGluIGEgdGFibGUKZmFfY29tX3QgPSByYmluZCgoZmFfY29tWywxXSkqMTAwKQogICMgcmVuYW1lIHJvdyBhbmQgY29sdW1uIG5hbWVzCiAgY29sbmFtZXMoZmFfY29tX3QpID0gcm93bmFtZXMoZmFfY29tKQogIHJvd25hbWVzKGZhX2NvbV90KSA9IE5VTEwKCiMgUHJpbnQgdGFibGUgdXNpbmcga2FibGUKICAjIHByaW50IHRhYmxlCiAga2FibGUoZmFfY29tX3QsIGNhcHRpb24gPSAiQ29tbXVuYWxpdGllcyBmb3IgdGhlIFRocmVlLUZhY3RvciBTb2x1dGlvbiBmb3IgSXRlbXMgaW4gdGhlIFNBRCAoJSkiLCBkaWdpdHMgPSA0LCBhbGlnbiA9ICdjJywgZXNjYXBlID0gRkFMU0UpICU+JQogICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpICU+JQogICAgYWRkX2Zvb3Rub3RlKCJDb21tdW5hbGl0aWVzIHNob3cgdGhlIHBlcmNlbnRhZ2Ugb2YgdmFyaWFuY2UgZXhwbGFpbmVkIGJ5IGVhY2ggZmFjdG9yIGZvciBlYWNoIGl0ZW0gb24gdGhlIFNBRC4iLCBub3RhdGlvbiA9ICJhbHBoYWJldCIpCmBgYAoKTmV4dCwgd2UgbG9va2VkIGF0IHRoZSAqKnBlcmNlbnRhZ2Ugb2YgdmFyaWFuY2UgYWNjb3VudGVkIGZvcioqIGJ5IHVzaW5nIHRoZSBlaWdlbnZhbHVlcyAoY29tcHV0ZSB0aGUgdmFyaWFuY2UgYXNzb3NpYXRlZCB3aXRoIHRoZSBmYWN0b3JzKS4gVGhpcyB3YXMgZG9uZSBmb3IgYm90aCB0aGUgdW5yb3RhdGVkIGFuZCByb3RhdGVkIChpLmUuLCB2YXJpbWF4KSB0aHJlZS1mYWN0b3Igc29sdXRpb24uIEFzIHlvdSBjYW4gc2VlIGluIHRoZSB0YWJsZSBiZWxvdywgYSB0b3RhbCBvZiBgciByb3VuZChzdW0odmFyX3BlciksMilgJSBvZiB2YXJpYW5jZSB3YXMgYWNjb3VudGVkIGZvciBieSB0aGUgdGhyZWUgZXh0cmFjdGVkIGZhY3RvcnMuIFRoaXMgdmFyaWFuY2Ugd2FzIG1vc3RseSBhY2NvdW50ZWQgZm9yIGJ5IGZhY3RvciBvbmUgaW4gdGhlIHVucm90YXRlZCBzb2x1dGlvbiwgYnV0IHdhcyBtb3JlIGVxdWFsbHkgZGlzdHJpYnV0ZWQgYWZ0ZXIgcm90YXRpb24gKHNlZSB0YWJsZSBmb3IgbW9yZSBkZXRhaWxzKS4KCmBgYHtyfQoKIyBSdW4gYW4gdW5yb3RhdGVkIHRocmVlLWZhY3RvciBzb2x1dGlvbgogIGZhX3RocmVlID0gcHJpbmNpcGFsKGZhX2RhdGEsIG5mYWN0b3JzID0gMywgcm90YXRlID0gIm5vbmUiLCBzY29yZXMgPSBUKSAKICAgICMgY2hhbmdlIG5hbWUgaW4gbG9hZGluZ3MgZm9yIGNsYXJpdHkgd2hlbiB2aXN1YWxpemluZyB0aGUgbW9kZWwKICAgIGNvbG5hbWVzKGZhX3RocmVlJGxvYWRpbmdzKSA9IGMoIkZhY3RvciAxIiwgIkZhY3RvciAyIiwgIkZhY3RvciAzIikgCiAgICAKICAKIyBUbyBmaW5kIHRoZSB2YXJpYWNlIGFjY291bnRlZCBmb3IsIHlvdSBjYW4gZWl0aGVyICgxKSBjYWxjdWxhdGUgaXQgZnJvbSB0aGUgZWlnZW4gdmFsdWVzIGZvciBlYWNoIGZhY3Rvciwgb3IgKDIpIGdyYWIgdGhlIGNhbGN1bGF0ZWQgdmFsdWVzIGZyb20gdGhlIG1vZGVsIAogICMgQm90aCBhcmUgc2hvd24gYmVsb3csIGJ1dCBvbmUgaXMgY29tbWVudGVkIG91dCB0byBhdm9pZCBjcmVhdGluZyB1bmVzc2VzYXJ5IHZhcmlhYmxlcwogICMgKDEpIENhbGN1bGF0ZWQgCiAgICAjIEZvciB0aGUgdW5yb3RhdGVkIHNvbHV0aW9uCiAgICAjdmFyX3BlciA9IDEwMCpmYV90aHJlZSR2YWx1ZXNbMTozXS9sZW5ndGgoZmFfdGhyZWUkdmFsdWVzKQogICAgCiAgICAjIEZvciB0aGUgcm90YXRlZCBzb2x1dGlvbgogICAgI3Zhcl9wZXJfdiA9IDEwMCooYXMubnVtZXJpYyhmYV90aHJlZV92JFZhY2NvdW50ZWRbMSxdKSkvbGVuZ3RoKGZhX3RocmVlX3YkdmFsdWVzKQogICAgICAKICAjICgyKSBUaGUgaW5mb3JtYXRpb24gaXMgZm91bmQgaW4gdGhlICJWYWNjb3VudGVkIiB0YWJsZSBmcm9tIHRoZSBvdXRwdXQsIHdoZXJlICJTUyBsb2FkaW5ncyIgKHJvdyAxKSBzaG93cyB0aGUgZWlnZW4gdmFsdWVzIGFuZCAiUHJvcG9ydGlvbiBWYXIiIChyb3cgMikgc2hvd3MgdGhlIHZhcmlhbmNlIGFjY291bnRlZCBmb3IuCiAgICAjIEZvciB0aGUgdW5yb3RhdGVkIHNvbHV0aW9uCiAgICB2YXJfcGVyID0gMTAwKmFzLm51bWVyaWMoZmFfdGhyZWUkVmFjY291bnRlZFsyLF0pCiAgICAKICAgICMgRm9yIHRoZSByb3RhdGVkIHNvbHV0aW9uCiAgICB2YXJfcGVyX3YgPSAxMDAqYXMubnVtZXJpYyhmYV90aHJlZV92JFZhY2NvdW50ZWRbMixdKQoKIyBDcmVhdGUgJiBTaG93IGEgdGFibGUgd2l0aCBlaWdlbiB2YWx1ZXMsIHBlcmNlbnQgdmFyIGV4cGxhaW5lZCwgYW5kIHRvdGFsIHBlcmNlbnQgdmFyIGV4cGxhaW5lZCBmb3IgdW5yb3RhdGVkICYgcm90YXRlZCB0aHJlZS1mYWN0b3Igc29sdXRpb25zCiAgICAjIHVucm90YXRlZCBzb2x1dGlvbgogICAgdmFyX3Blcl90ID0gYXMuZGF0YS5mcmFtZShjYmluZChyYmluZChhcy5udW1lcmljKGZhX3RocmVlJFZhY2NvdW50ZWRbMSxdKSwgdmFyX3BlciksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYmluZChhcy5udW1lcmljKGZhX3RocmVlX3YkVmFjY291bnRlZFsxLF0pLCB2YXJfcGVyX3YpKSkKICAgICMgbmFtZSB0aGUgY29sdW1ucyAmIHJvd3MgYWNjb3JkaW5nbHkKICAgIGNvbG5hbWVzKHZhcl9wZXJfdCkgPSBjKHJlcChjKCJGYWN0b3IgMSIsICJGYWN0b3IgMiIsICJGYWN0b3IgMyIpLDIpKQogICAgcm93bmFtZXModmFyX3Blcl90KSA9IGMoIkVpZ2VuIFZhbHVlcyIsICJWYXJpYW5jZSBFeHBsYWluZWQgKCUpIikKCiAgIyB1c2Uga2FibGUgdG8gc2hvdyB0aGUgdGFibGUKICBrYWJsZSh2YXJfcGVyX3QsIGNhcHRpb24gPSAiRWlnZW4gVmFsdWVzIGFuZCBQZXJjZW50IG9mIFZhcmlhbmNlIEV4cGxhaW5lZCBmb3IgdGhlIFVucm90YXRlZCBhbmQgUm90YXRlZCAodmFyaW1heCkgZm9yIHRoZSBUaHJlZS1GYWN0b3IgU29sdXRpb24gZm9yIEl0ZW1zIGluIHRoZSBTQUQiLCBkaWdpdHMgPSA0LCBhbGlnbiA9ICdjJykgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IFQpICU+JQogIGFkZF9oZWFkZXJfYWJvdmUoYygiICIsICJVbnJvdGF0ZWQiID0gMywgIlZhcmltYXggUm90YXRpb24iID0gMykpCgpgYGAKCkxhc3RseSwgd2UgbG9va2VkIGF0IHRoZSAqKmZhY3RvciBsb2FkaW5ncyoqIG9mIHRoZSB0aHJlZS1mYWN0b3Igc29sdXRpb24uIEJlbG93IHlvdSBjYW4gc2VlIHRoZSByb3RhdGVkIChpLmUuLCB2YXJpbWF4KSBhbmQgdW5yb3RhdGVkIGZhY3RlciBsb2FkaW5ncy4gVGhlIGxvYWRpbmdzIGFyZSBzaG93biB3aXRoIGEgY3V0LW9mZiBvZiAwLjQwIGFuZCByb3VuZGVkIHRvIHRocmVlIGRlY2ltYWwgcGxhY2VzLiBBcyB3ZSBzYXcgaW4gdGhhIGZhY3RvciBkaWFncmFtcywgdGhlIHVucm90YXRlZCBmYWN0b3IgbG9hZGluZ3MgYXJlIGRpZmZpY3VsdCB0byBpbnRlcnByZXQ6IGFsbCBpdGVtcyBsb2FkZWQgc3Ryb25nbHkgb250byBmYWN0b3IgMSAoaS5lLiwgbG9hZGluZyB3YXMgZ3JlYXRlciB0aGFuIDAuNDApLiBUaGUgcm9hdGF0ZWQgZmFjdG9yIGxvYWRpbmdzIHdlcmUgbW9yZSBlYXN5IHRvIGludGVycHJldCwgd2l0aCBvbmx5IG9uZSBpdGVtIGxvYWRpbmcgb250byBtb3JlIHRoYW4gb25lIGZhY3RvciAoaS5lLiwgaXRlbSBzaXg7IHNlZSBiZWxvdyBmb3IgbW9yZSBkZXRhaWxzKS4KCmBgYHtyfQoKIyBVbnJvdGF0ZWQgRmFjdG9yIExvYWRpbmdzIApwcmludChmYV90aHJlZSRsb2FkaW5ncywgY3V0b2ZmID0gMC40MCwgZGlnaXRzID0gMykKCiMgUm90YXRlZCAoaS5lLiwgdmFyaW1heCkgRmFjdG9yIExvYWRpbmdzIApwcmludChmYV90aHJlZV92JGxvYWRpbmdzLCBjdXRvZmYgPSAwLjQwLCBkaWdpdHMgPSAzKQoKYGBgCgpJbiBvcmRlciB0byB2YWxpZGF0ZSB0aGUgU0FELCB3ZSBjb21wbGV0ZWQgYSByZWxpYWJpbGl0eSBhbmFseXNpcyAoaS5lLiwgaXMgdGhlIHNjYWxlIGNvbnNpc3RlbnQpIGJ5IGxvb2tpbmcgYXQgdGhlIHNwbGl0LWhhbGYgcmVsaWFiaWxpdHkgdXNpbmcgQ3JvbmJhY2gncyBhbHBoYS4gVGhpcyBtZXRob2QgaXMgdGhlIG1vc3QgY29tbW9uIG1lYXN1cmUgb2Ygc2NhbGUgcmVsaWFiaWxpdHkgKEZpZWxkIGV0IGFsLiwgMjAxMik6IHRoZSBkYXRhIGZvciBlYWNoIHBhcnRpY2lwYW50IGlzIHJhbmRvbWx5IHNwbGl0IGludG8gdHdvIHNldHMsIHdoaWNoIGZvcm1zIGEgImhhbGYiIHNwbGl0IGZvciB0aGUgc2NhbGUuIFRoZW4sIGEgY29ycmVsYXRpb24gaXMgY2FsY3VsYXRlZCBiZXR3ZWVuIHRoZXNlIHNldHMgdG8gZGV0ZXJtaW5lIGhvdyBzaW1pbGFyIHRoZXkgYXJlOiBoaWdoZXIgcmVsaWFiaWxpdHkgd291bGQgYmUgc2VlbiB3aXRoIGhpZ2hseSBjb3JyZWxhdGVkIHNldHMuIFNpbmNlIHRoZSB3YXkgdGhhdCB0aGUgZGF0YSBpcyBzcGxpdCBjYW4gaW1wYWN0IHRoZSBjb3JyZWxhdGlvbnMsIENyb25iYWNoJ3MgYWxwaGEgcmVwcmVzZW50cyBhbiBhdmVyYWdlIG9mIGFsbCB0aGUgcG9zc2libGUgc3BsaXRzIHVzaW5nIHRoZSBmb2xsb3dpbmcgZXF1YXRpb246CgokJFxhbHBoYSA9ICBcZnJhY3tOXjIgXG92ZXJsaW5le0Nvdn19e1xzdW0gc197aXRlbX1eMiArIFxzdW0gQ292X3tpdGVtfX0gJCQKVG8gb2J0YWluIHRoZSBiZXN0IHJlbGlhYmlsaXR5IG1lYXN1cmUsIHdlIG11c3QgZGl2aWRlIG91ciBkYXRhIGludG8gYW55IHN1YnNjYWxlcywgd2hpY2ggaW4gdGhpcyBjYXNlLCBhcmUgb3VyIHRocmVlIGZhY3RvcnMgZnJvbSBvdXIgZmFjdG9yIGFuYWx5c2lzLiBUaGVyZWZvcmUsIHdlIHNwbGl0IHRoZSBkYXRhIGludG8gdGhyZWUgc2V0cyBmb3IgdGhlIHJlbGlhYmlsaXR5IGFuYWx5c2lzLgoKYGBge3J9CgojIHNwbGl0IHRoZSBkYXRhIHJlc3BlY3RpdmUgdG8gdGhlIDMgZmFjdG9ycyBmcm9tIHRoZSBGQSB0byBwZXJmb3JtIHRoZSByZWxpYWJpbGl0eSBhbmFseXNpcwogICMgZmFjdG9yIDEgKGl0ZW1zOiAxLCAyLCAzLCA0LCA1KQogIGYxX2RhdGEgPSBmYV9kYXRhWyxjKDEsIDIsIDMsIDQsIDUpXQogICMgZmFjdG9yIDIgKGl0ZW1zOiA4LCA5LCAxMCwgMTEpCiAgZjJfZGF0YSA9IGZhX2RhdGFbLGMoOCwgOSwgMTAsIDExKV0KICAjIGZhY3RvciAzIChpdGVtczogNywgMTIsIDEzKQogIGYzX2RhdGEgPSBmYV9kYXRhWyxjKDcsIDEyLCAxMyldCgpgYGAKCk9uY2Ugd2UgaGF2ZSBvdXIgc3Vic2NhbGVzLCB3ZSBjb21wbGV0ZSB0aGUgcmVsaWFiaWxpdHkgYW5hbHlzaXMgb24gZWFjaCBzdWJzY2FsZS4KCmBgYHtyfQoKIyBjb21wdXRlIHJlbGlhYmlsaXR5IGFuYWx5c2lzIGZvciBlYWNoIHN1YnNjYWxlIHVzaW5nICJhbHBoYSgpIiBmdW5jdGlvbiBpbiAicHN5Y2giIHBhY2thZ2UKICAjIGZhY3RvciAxCiAgZjFfcmVsID0gcHN5Y2g6OmFscGhhKGYxX2RhdGEpCiAgIyBmYWN0b3IgMgogIGYyX3JlbCA9IHBzeWNoOjphbHBoYShmMl9kYXRhKQogICMgZmFjdG9yIDMKICBmM19yZWwgPSBwc3ljaDo6YWxwaGEoZjNfZGF0YSkKCmBgYAoKVG8gdmlldyB0aGUgYW5hbHlzaXMsIHdlIGJyb2tlIGl0IGRvd24gaW50byB0aHJlZSBjb21wb2VuZW50czogKDEpIFRoZSBhbHBoYSB2YWx1ZXMgYW5kIG92ZXJhbGwgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSBzdWJzY2FsZXMsICgyKSBUaGUgYWxwaGEgdmFsdWVzIGlmIGFuIGl0ZW0gd2FzIGRyb3BwZWQgKGkuZS4sIEFscGhhIERyb3AgVmFsdWVzKSwgYW5kICgzKSBJdGVtIHN0YXRpc3RpY3MuIAoKKDEpIEFscGhhIFZhbHVlcwoKLSBUaGUgYWxwaGEgdmFsdWVzIGZyb20gdGhlIHJlbGlhYmlsaXR5IGFuYWx5c2VzIGluY2x1ZGVkIENyb25iYWNoJ3MgJFxhbHBoYSQgKGkuZS4sIGJhc2VkIG9uIHRoZSBjb3ZhcmlhbmNlcyksIGEgc3RhbmRhcmRpemVkICRcYWxwaGEkIChpLmUuLCBiYXNlZCBvbiB0aGUgY29ycmVsYXRpb25zKSwgYW5kIEd1dHRtYW4ncyBMYW1iZGEgNi4gQWRkaXRpb25hbGx5LCB0aGUgb3ZlcmFsbCBhdmVyYWdlIGNvcnJlbGF0aW9uLCBtZWFuLCBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIGZvciB0aGUgc3Vic2NhbGUgaXMgc2hvd24gKHNlZSB0YWJsZSBiZWxvdyBmb3IgbW9yZSBkZXRhaWxzKS4KLSBBcyBzZWVuIGluIHRoZSB0YWJsZSwgQ3JvbmJhY2gncyAkXGFscGhhJCB3YXMgd2l0aGluIHRoZSBhY2NlcHRhYmxlIHJhbmdlIChpLmUuLCBncmVhdGVyIHRoYW4gLjcwOyBLbGluZSwgMTk5OSkgZm9yIEZhY3RvciAxICgkXGFscGhhX0MkID0gYHIgcm91bmQoZmFfcmVsX2FscGhhcyRyYXdfYWxwaGFbMV0sIDIpYCkgYW5kIEZhY3RvciAyICgkXGFscGhhX0MkID0gYHIgcm91bmQoZmFfcmVsX2FscGhhcyRyYXdfYWxwaGFbMl0sIDIpYCksIGJ1dCBub3QgZm9yIEZhY3RvciAzICgkXGFscGhhX0MkID0gYHIgcm91bmQoZmFfcmVsX2FscGhhcyRyYXdfYWxwaGFbM10sIDIpYCkuIFRoZSBvdmVyYWxsIGNvcnJlbGF0aW9ucyBmb3IgRmFjdG9yIDEsICpyKihgciBmMV9yZWwkaXRlbS5zdGF0c1sxLCAibiJdIC0gMmApIGByIHBfcm91bmQoZmFfcmVsX2FscGhhcyRhdmVyYWdlX3JbMV0pYCwgYW5kIEZhY3RvciAyLCAqciooYHIgZjJfcmVsJGl0ZW0uc3RhdHNbMSwgIm4iXSAtIDJgKSBgciBwX3JvdW5kKGZhX3JlbF9hbHBoYXMkYXZlcmFnZV9yWzJdKWAsIHdlcmUgbW9kZXJhdGUsIHdoZXJlYXMgRmFjdG9yIDMncyBjb3JyZWxhdGlvbiwgKnIqKGByIGYzX3JlbCRpdGVtLnN0YXRzWzEsICJuIl0gLSAyYCkgYHIgcF9yb3VuZChmYV9yZWxfYWxwaGFzJGF2ZXJhZ2VfclszXSlgLCB3YXMgd2Vhay1tb2RlcmF0ZS4gVGhlc2Ugc3RhdGlzdGljcyB3ZXJlIGZ1cnRoZXIgZXhwbG9yZWQgd2l0aCBkcm9wcGVkIGl0ZW1zLiAKCmBgYHtyfQojIHNob3cgdGhlIGFscGhhIHZhbHVlcyBmcm9tIHRoZSAzIHN1YnNjYWxlcwogICMgY3JlYXRlIGRhdGEgZnJhbWUgd2l0aCB0aGUgaW5mb3JtYXRpb24gZnJvbSB0aGUgMyByZWxpYWJpbGl0eSBhbmFseXNlcwogIGZhX3JlbF9hbHBoYXMgPSBhcy5kYXRhLmZyYW1lKHJiaW5kKCJGYWN0b3IgMSIgPSBkcGx5cjo6c2VsZWN0KGYxX3JlbCR0b3RhbCwgLWMoIlMvTiIsICJhc2UiLCAibWVkaWFuX3IiKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGYWN0b3IgMiIgPSBkcGx5cjo6c2VsZWN0KGYyX3JlbCR0b3RhbCwgLWMoIlMvTiIsICJhc2UiLCAibWVkaWFuX3IiKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGYWN0b3IgMyIgPSBkcGx5cjo6c2VsZWN0KGYzX3JlbCR0b3RhbCwgLWMoIlMvTiIsICJhc2UiLCAibWVkaWFuX3IiKSkpKQogICMgYWRkIGFuIGV4dHJhIGNvbHVtbiBmb3IgdGhlICJvdmVyYWxsIiBvciBhdmVyYWdlIGFscGhhCiAgZmFfcmVsX2FscGhhcyA9IGNiaW5kKCJPdmVyYWxsIGFscGhhIiA9IGMobWVhbihhcy5udW1lcmljKGRwbHlyOjpzZWxlY3QoZjFfcmVsJHRvdGFsLCBjKCJyYXdfYWxwaGEiLCAic3RkLmFscGhhIikpKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4oYXMubnVtZXJpYyhkcGx5cjo6c2VsZWN0KGYyX3JlbCR0b3RhbCwgYygicmF3X2FscGhhIiwgInN0ZC5hbHBoYSIpKSkpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuKGFzLm51bWVyaWMoZHBseXI6OnNlbGVjdChmM19yZWwkdG90YWwsIGMoInJhd19hbHBoYSIsICJzdGQuYWxwaGEiKSkpKSksIAogICAgICAgICAgICAgICAgICAgICAgICBmYV9yZWxfYWxwaGFzKQoKICAjIHVzZSBrYWJsZSB0byBzaG93IHRoZSB0YWJsZQogIGthYmxlKGZhX3JlbF9hbHBoYXMsIGNhcHRpb24gPSAiUmVsaWFiaWxpdHkgQW5hbHlzaXMgZm9yIFN1YnNjYWxlcyBpbiB0aGUgU0FEOiBBbHBoYSBWYWx1ZXMiLCBkaWdpdHMgPSA0LCBhbGlnbiA9ICdjJywgCiAgICAgICAgY29sLm5hbWVzID0gYygiT3ZlcmFsbCBhbHBoYSIsICJDcm9uYmFjaCdzIGFscGhhIiwgIlN0YW5kYXJkaXplZCBhbHBoYSIsICJHdXR0bWFuJ3MgbGFtYmRhIDYiLCAiQXZlcmFnZSByIiwgIk0iLCAiU0QiKSkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IFQpCiAgCmBgYAoKKDIpIEFscGhhIERyb3AgVmFsdWVzIAoKLSBUbyBmdXJ0aGVyIGV4cGxvcmUgdGhlIHJlbGlhYmlsaXR5IG9mIGVhY2ggc3Vic2NhbGUsIHdlIGxvb2tlZCBhdCB0aGUgYWxwaGEgdmFsdWVzIGFmdGVyIHJlbW92aW5nIGVhY2ggaXRlbS4gVGhpcyBhbGxvd2VkIHVzIHRvIGRldGVybWluZSB3aGV0aGVyIGEgZ2l2ZW4gaXRlbSB3YXMgcmVkdWNpbmcgdGhlIHJlbGlhYmlsaXR5IG9mIHRoZSBzdWJzY2FsZS4gVGhhdCBpcywgaWYgZHJvcHBpbmcgYW4gaXRlbSBpbmNyZWFzZWQgJFxhbHBoYSQgb3IgdGhlIGNvcnJlbGF0aW9uLCB0aGUgcmVtb3ZpbmcgdGhlIGl0ZW0gZnJvbSB0aGUgYW5hbHlzaXMgc2hvdWxkIGJlIGNvbnNpZGVyZWQuIFRoZSBkYXRhIHByZXNlbnRlZCBpbiB0aGUgdGFibGUgYmVsb3cgc2hvd3MgQ3JvbmJhY2gncyAkXGFscGhhJCwgc3RhbmRhcmRpemVkICRcYWxwaGEkLCBHdXR0bWFuJ3MgTGFtYmRhIDYsIGFuZCB0aGUgYXZlcmFnZSBjb3JyZWxhdGlvbi4KLSBBcyBzZWVuIGluIHRoZSB0YWJsZSBiZWxvdywgZHJvcHBpbmcgYW4gaXRlbSBkaWQgbm90IGltcHJvdmUgcmVsaWFiaWxpdHkgZm9yIEZhY3RvciAxIChyYW5nZSBvZiAkXGFscGhhX0MkID0gYHIgcm91bmQobWluKGZhX3JlbF9hZHJvcCRyYXdfYWxwaGFbMTo1XSksIDIpYCAtIGByIHJvdW5kKG1heChmYV9yZWxfYWRyb3AkcmF3X2FscGhhWzE6NV0pLCAyKWApIG9yIEZhY3RvciAyIChyYW5nZSBvZiAkXGFscGhhX0MkID0gYHIgcm91bmQobWluKGZhX3JlbF9hZHJvcCRyYXdfYWxwaGFbNjo5XSksIDIpYCAtIGByIHJvdW5kKG1heChmYV9yZWxfYWRyb3AkcmF3X2FscGhhWzY6OV0pLCAyKWApLiBIb3dldmVyLCByZW1vdmluZyBpdGVtICM3IGRpZCBpbXByb3ZlIHJlbGlhYmlsaXR5IGZvciBGYWN0b3IgMyAoJFxhbHBoYV97Qy1kcm9wN30kID0gYHIgcm91bmQoZmFfcmVsX2Fkcm9wJHJhd19hbHBoYVsxMF0sIDIpYCkuIFdpdGggcmVzcGVjdCB0byB0aGUgYXZlcmFnZSBjb3JyZWxhdGlvbiwgZHJvcHBpbmcgYW4gaXRlbSBkaWQgbm90IGltcHJvdmUgZm9yIEZhY3RvciAyLCAqciooYHIgZjJfcmVsJGl0ZW0uc3RhdHNbMSwgIm4iXSAtIDJgKSBgciBwX3JvdW5kKG1pbihmYV9yZWxfYWRyb3AkYXZlcmFnZV9yWzY6OV0pKWAgLSBgciBwX3JvdW5kKG1heChmYV9yZWxfYWRyb3AkYXZlcmFnZV9yWzY6OV0pKWAuIEhvd2V2ZXIsIGl0ZW0gIzUgZm9yIEZhY3RvciAxLCAqciooYHIgZjFfcmVsJGl0ZW0uc3RhdHNbMSwgIm4iXSAtIDJgKSBgciBwX3JvdW5kKG1pbihmYV9yZWxfYWRyb3AkYXZlcmFnZV9yWzVdKSlgLCBhbmQgaXRlbSAjNyBmb3IgRmFjdG9yIDMsICpyKihgciBmM19yZWwkaXRlbS5zdGF0c1sxLCAibiJdIC0gMmApIGByIHBfcm91bmQobWluKGZhX3JlbF9hZHJvcCRhdmVyYWdlX3JbMTBdKSlgLCBkaWQgc2hvdyBhIHNvbWUgaW1wcm92ZW1lbnQgaW4gYXZlcmFnZSBjb3JyZWxhdGlvbi4gVGhpcyB3YXMgZXhwbG9yZWQgZnVydGhlciB3aXRoIHRoZSBpdGVtcyBzdGF0aXN0aWNzLgoKYGBge3J9CiMgc2hvdyB0aGUgYWxwaGEgZHJvcCB2YWx1ZXMgZnJvbSB0aGUgMyBzdWJzY2FsZXMKICAjIGNyZWF0ZSBkYXRhIGZyYW1lIHdpdGggdGhlIGluZm9ybWF0aW9uCiAgZmFfcmVsX2Fkcm9wID0gYXMuZGF0YS5mcmFtZShyYmluZChkcGx5cjo6c2VsZWN0KGYxX3JlbCRhbHBoYS5kcm9wLCBjKCJyYXdfYWxwaGEiLCAic3RkLmFscGhhIiwgIkc2KHNtYykiLCAiYXZlcmFnZV9yIikpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3QoZjJfcmVsJGFscGhhLmRyb3AsIGMoInJhd19hbHBoYSIsICJzdGQuYWxwaGEiLCAiRzYoc21jKSIsICJhdmVyYWdlX3IiKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdChmM19yZWwkYWxwaGEuZHJvcCwgYygicmF3X2FscGhhIiwgInN0ZC5hbHBoYSIsICJHNihzbWMpIiwgImF2ZXJhZ2VfciIpKSkpCgogICMgdXNlIGthYmxlIHRvIHNob3cgdGhlIHRhYmxlCiAga2FibGUoZmFfcmVsX2Fkcm9wLCBjYXB0aW9uID0gIlJlbGlhYmlsaXR5IEFuYWx5c2lzIGZvciBTdWJzY2FsZXMgaW4gdGhlIFNBRDogQWxwaGEgRHJvcCBWYWx1ZXMiLCBkaWdpdHMgPSA0LCBhbGlnbiA9ICdjJywgCiAgICAgICAgY29sLm5hbWVzID0gYygiQ3JvbmJhY2gncyBhbHBoYSIsICJTdGFuZGFyZGl6ZWQgYWxwaGEiLCAiR3V0dG1hbidzIGxhbWJkYSA2IiwgIkF2ZXJhZ2UgciIpKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCAiaG92ZXIiLCBmdWxsX3dpZHRoID0gVCkgJT4lCiAgcGFja19yb3dzKGluZGV4ID0gYygiRmFjdG9yIDEiID0gbmNvbChmMV9kYXRhKSwgIkZhY3RvciAyIiA9IG5jb2woZjJfZGF0YSksICJGYWN0b3IgMyIgPSBuY29sKGYzX2RhdGEpKSkKCmBgYAoKKDMpIEl0ZW0gU3RhdGlzdGljcwoKLSBUaGUgaXRlbSBzdGF0aXN0aWNzIHdlcmUgZXhwbG9yZWQgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgYSBjZXJ0YWluIGl0ZW0gZGlkIG5vdCBjb3JyZWxhdGUgd2l0aCB0aGUgb3ZlcmFsbCBzdWJzY2FsZS4gVGhlIHRhYmxlIGJlbG93IHNob3dzOiAqciosIHdoaWNoIGlzIHRoZSBjb3JyZWxhdGlvbnMgYmV0d2VlbiBlYWNoIGl0ZW0gYW5kIHRoZSB0b3RhbCBzY29yZSBmcm9tIHRoZSBzdWJzY2FsZSAoaS5lLiwgdGhlIGl0ZW0tdG90YWwgY29ycmVsYXRpb25zKSwgd2hpY2ggaW5jbHVkZXMgdGhlIGl0ZW0gaXRzZWxmOyBhbmQgKkRyb3AqLCB3aGljaCBpcyB0aGUgY29ycmVsYXRpb24gb2YgYW4gaXRlbSB3aXRoIHRoZSBzdWJzY2FsZSBhZnRlciByZW1vdmluZyB0aGUgaXRlbSAoaS5lLiwgdGhlIGl0ZW0tcmVzdCBjb3JyZWxhdGlvbiBvciB0aGUgY29ycmVjdGVkIGl0ZW0tdG90YWwgY29ycmVsYXRpb24pLiBBZGRpdGlvbmFsbHksIHRoZSBzYW1wbGUgc2l6ZSwgbWVhbiwgYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBpcyBzaG93bi4gCi0gTm8gaXNzdWVzIHdlcmUgZm91bmQgd2l0aCB0aGUgaXRlbSBzdGF0aXN0aWNzIGZvciBGYWN0b3IgMSwgKnIqKGByIGYxX3JlbCRpdGVtLnN0YXRzWzEsICJuIl0gLSAyYCkgYHIgcF9yb3VuZChtaW4oZmFfcmVsX2l0ZW0kci5kcm9wWzE6NV0pKWAgLSBgciBwX3JvdW5kKG1heChmYV9yZWxfaXRlbSRyLmRyb3BbMTo1XSkpYDsgRmFjdG9yIDIsICpyKihgciBmMl9yZWwkaXRlbS5zdGF0c1sxLCAibiJdIC0gMmApIGByIHBfcm91bmQobWluKGZhX3JlbF9pdGVtJHIuZHJvcFs2OjldKSlgIC0gYHIgcF9yb3VuZChtYXgoZmFfcmVsX2l0ZW0kci5kcm9wWzY6OV0pKWA7IGFuZCBGYWN0b3IgMywgKnIqKGByIGYzX3JlbCRpdGVtLnN0YXRzWzEsICJuIl0gLSAyYCkgYHIgcF9yb3VuZChtaW4oZmFfcmVsX2l0ZW0kci5kcm9wWzEwOjEyXSkpYCAtIGByIHBfcm91bmQobWF4KGZhX3JlbF9pdGVtJHIuZHJvcFsxMDoxMl0pKWAuIFRoYXQgaXMsIG5vIGl0ZW1zIGhhZCBhIGl0ZW0tcmVzdCBjb3JyZWxhdGlvbiAoaS5lLiwgdGhlIGRyb3AgY29sdW1uIGluIHRoZSB0YWJsZSBiZWxvdykgYmVsb3cgdGhlIGN1dC1vZmYgKGkuZS4sIC4zMDsgRmllbGQgZXQgYWwuLCAyMDEyKS4gCgpgYGB7cn0KCiMgc2hvdyB0aGUgY29ycmVsYXRpb25zIGZvciB0aGUgMyBzdWJzY2FsZXMKICAjIGNyZWF0ZSBkYXRhIGZyYW1lIHdpdGggdGhlIGluZm9ybWF0aW9uCiAgZmFfcmVsX2l0ZW0gPSBhcy5kYXRhLmZyYW1lKHJiaW5kKGRwbHlyOjpzZWxlY3QoZjFfcmVsJGl0ZW0uc3RhdHMsIC1jKCJzdGQuciIsICJyLmNvciIpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KGYyX3JlbCRpdGVtLnN0YXRzLCAtYygic3RkLnIiLCAici5jb3IiKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdChmM19yZWwkaXRlbS5zdGF0cywgLWMoInN0ZC5yIiwgInIuY29yIikpKSkKCiAgIyB1c2Uga2FibGUgdG8gc2hvdyB0aGUgdGFibGUKICBrYWJsZShmYV9yZWxfaXRlbSwgY2FwdGlvbiA9ICJSZWxpYWJpbGl0eSBBbmFseXNpcyBmb3IgU3Vic2NhbGVzIGluIHRoZSBTQUQ6IEl0ZW0gU3RhdGlzdGljcyIsIGRpZ2l0cyA9IDQsIGFsaWduID0gJ2MnLCAKICAgICAgICBjb2wubmFtZXMgPSBjKCJOIiwgInIiLCAiRHJvcCIsICJNIiwgIlNEIikpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsICJob3ZlciIsIGZ1bGxfd2lkdGggPSBUKSAlPiUKICBwYWNrX3Jvd3MoaW5kZXggPSBjKCJGYWN0b3IgMSIgPSBuY29sKGYxX2RhdGEpLCAiRmFjdG9yIDIiID0gbmNvbChmMl9kYXRhKSwgIkZhY3RvciAzIiA9IG5jb2woZjNfZGF0YSkpKSAgCgpgYGAKCk92ZXJhbGwsIHRoZSByZWxpYWJpbGl0eSBmb3IgRmFjdG9yIDEgYW5kIEZhY3RvciAyIHdhcyBhZGVxdWF0ZS4gSG93ZXZlciwgRmFjdG9yIDMgc2hvd2VkIG1peGVkIHJlc3VsdHM6IGl0ZW0gIzcgd2FzIG5vdCBhcyBzdGFibGUgYXMgdGhlIG90aGVyIGl0ZW1zLiAqKkhvd2V2ZXIsIHRoaXMgaXRlbSBkaWQgZml0IHRoZSBtaW5pbXVtIGNyaXRlcmlhIGZvciByZWxpYWJpbGl0eSBhbmQgd2FzIHRoZXJlZm9yZSBsZWZ0IGluIHRoZSBzdWJzY2FsZS4gT1IgVGhlIGl0ZW0gbWV0IHRoZSBtaW5pbXVtIGNyaXRlcmlhLCBidXQgd2FzIHJlbW92ZWQgdG8gaW1wcm92ZSB0aGUgb3ZlcmFsbCBmYWN0b3IgYW5hbHlzaXMgZml0IHdpdGggdGhlIGRhdGEuKioKCiMjIyMjIyBDb25jbHVzaW9ucwoKQSBwcmluY2lwYWwgY29tcG9uZW50cyBmYWN0b3IgYW5hbHlzaXMgd2FzIGNvbXBsZXRlZCBvbiB0aGUgMTMgaXRlbXMgaW4gdGhlIFNBRCAoV2FyZCBldCBhbC4sIDIwMTcpIHdpdGggYW4gb3J0aG9nb25hbCByb3RhdGlvbiAoaS5lLiwgdmFyaW1heCByb3RhdGlvbikuIEZhY3RvcmFiaWxpdHkgb2YgdGhlIGRhdGEgd2FzIGNvbmZpcm1lZCB1c2luZzogKDEpIEJhcnRsZXR0J3MgdGVzdCBmb3Igc3BoZXJpY2l0eSwgJFxjaGleezJ9JChgciBmYV9iYXJ0ZXN0JGRmYCkgPSBgciByb3VuZChmYV9iYXJ0ZXN0JGNoaXNxLCAyKWAsICpwKiBgciBwX3JvdW5kKGZhX2JhcnRlc3QkcC52YWx1ZSlgLCB3aGljaCBjb25maXJtZWQgdGhhdCBjb3JyZWxhdGlvbnMgYmV0d2VlbiB0aGUgaXRlbXMgd2VyZSBzdWZmaWNpZW50bHkgbGFyZ2U7IGFuZCAoMikgdGhlIEthaXNlci1NZXllci1PbGtpbiBtZWFzdXJlIGZvciBzYW1wbGluZyBhZGVxdWFjeSwgJE1TQV97b3ZlcmFsbH0kID0gYHIgcm91bmQoZmFfa21vJE1TQSwgMilgLCAkTVNBX3sxLTEzfSQgPSBgciBtaW4ocm91bmQoZmFfa21vJE1TQWksIDIpKWAgLSBgciBtYXgocm91bmQoZmFfa21vJE1TQWksIDIpKWAsIHdoaWNoIGNvbmZpcm1lZCB0aGF0IGJvdGggdGhlIG92ZXJhbGwgTVNBIGFuZCBlYWNoIGl0ZW0ncyBNU0Egd2VyZSBhYm92ZSB0aGVpciByZXF1aXJlZCBjcml0ZXJpYSAoMC42MCBhbmQgMC43NywgcmVzcGVjdGl2ZWx5OyBLYWlzZXIsIDE5NzQpLiBUaGUgYXBwcm9wcmlhdGUgbnVtYmVyIG9mIGZhY3RvcnMgKGkuZS4sIHRocmVlKSB3YXMgY29uZmlybWVkIHVzaW5nICgxKSBhIHBhcmFsbGVsIGFuYWx5c2lzIHNjcmVlIHBsb3QsIHdoZXJlIHRoZSB0d28tIGFuZCB0aHJlZS1mYWN0b3Igc29sdXRpb25zIHdlcmUgY2hvc2VuIHRvIGNvbXBhcmUgZm9yIHRoIGViZXN0IGZpdCBmb3IgdGhlIGRhdGE7ICgyKSB0aGUgZWlnZW4gdmFsdWVzIChlLmcuLCBgciBmYV90aHJlZSR2YWx1ZXNbMTo0XWAsIGZvciBmYWN0b3JzIDEgdG8gNCwgcmVzcGVjdGl2ZWx5KSBmb3IgdGhlIHVucm90YXRlZCBzb2x1dGlvbiwgd2hlcmUgdGhyZWUgbWVhbmluZ2Z1bCBmYWN0b3JzIHdlcmUgZm91bmQgdXNpbmcgS2Fpc2VyJ3MgY3JpdGVyaW9uIChpLmUuLCBlaWdlbiB2YWx1ZXMgZ3JlYXRlciB0aGFuIG9uZSk7IGFuZCAoMykgdGhlIGZhY3RvciBzdHJ1Y3R1cmUgb2YgdGhlIHR3by0gYW5kIHRocmVlLWZhY3RvciBzb2x1dGlvbnMsIHdoZXJlIHRoZSB0aHJlZS1mYWN0b3Igc29sdXRpb24gc2hvd2VkIGEgYmV0dGVyIGRpc3RyaWJ1dGlvbiBvZiB0aGUgZGF0YSBhbmQgd2FzIG1vcmUgaW50ZXJwcmV0YWJsZS4gVGhlcmVmb3JlLCB0aGUgdGhyZWUtZmFjdG9yIHNvbHV0aW9uIHdhcyBjaG9zZW4gZm9yIHRoZSBmaW5hbCBhbmFseXNpcyBhbmQgZXhwbGFpbmVkIGByIHJvdW5kKHN1bSh2YXJfcGVyKSwgMilgJSBvZiB0aGUgdmFyaWFuY2UuIEFkZGl0aW9uYWxseSwgYW4gb3J0aG9nb25hbCAoaS5lLiwgdmFyaW1heCkgcm90YXRpb24gd2FzIGNob3NlbiBmb3IgdGhlIGZpbmFsIGFuYWx5c2lzLiBUaGUgaXRlbXMgaW4gdGhlIGZpbmFsIGZhY3RvcnMgc3VnZ2VzdGVkIHRoZSBmb2xsb3dpbmcgdGhyZWUgZmFjdG9yczogc21hcnRwaG9uZSBkZXBlbmRlbmNlLCBlbW90aW9uYWwgYXR0YWNobWVudCwgYW5kIHNtYXJ0cGhvbmUgZGlzdHJhY3RhYmlsaXR5LiBTbWFydHBob25lIGRlcGVuZGVuY2Ugd2FzIHJlbGF0ZSB0byB0aGUgZGVncmVlIG9mIGRlcGVuZGVuY2Ugb24gb25lJ3Mgc21hcnRwaG9uZSwgaXQgY29uc2lzdGVkIG9mIDUgaXRlbXMgYW5kIGV4cGxhaW5lZCBgciByb3VuZCh2YXJfcGVyX3ZbMV0sIDIpYCUgb2YgdGhlIHZhcmlhbmNlIChlLmcuLCAiSSB3b3VsZCBoYXZlIHRyb3VibGUgZ2V0dGluZyB0aHJvdWdoIGEgbm9ybWFsIGRheSB3aXRob3V0IG15IHNtYXJ0cGhvbmUuIiwgYW5kICJJIGZlZWwgbGlrZSBJIGNvdWxkIG5vdCBsaXZlIHdpdGhvdXQgbXkgc21hcnRwaG9uZS4iKS4gRW1vdGlvbmFsIGF0dGFjaG1lbnQgd2FzIHJlbGF0ZWQgdG8gb25lJ3Mgc21hcnRwaG9uZSB1c2UgZm9yIGVtb3Rpb25hbCBzdXBwb3J0LCBpdCBjb25zaXN0ZWQgb2YgNCBpdGVtcyBhbmQgZXhwbGFpbmVkIGByIHJvdW5kKHZhcl9wZXJfdlsyXSwgMilgJSBvZiB0aGUgdmFyaWFuY2UgKGUuZy4sICJJIGZlZWwgbG9uZWx5IHdoZW4gbXkgc21hcnRwaG9uZSBkb2VzIG5vdCByaW5nIG9yIHZpYnJhdGUgZm9yIHNldmVyYWwgaG91cnMuIiwgYW5kICJVc2luZyBteSBzbWFydHBob25lIG1ha2VzIG1lIGZlZWwgaGFwcHkuIikuIFNtYXJ0cGhvbmUgZGlzdHJhY3RhYmlsaXR5IHdhcyByZWxhdGVkIHRvIG9uZSdzIHNtYXJ0cGhvbmUgcmV0YWluaW5nIG9uZSdzIGF0dGVudGlvbiwgaXQgY29uc2lzdGVkIG9mIDMgaXRlbXMgYW5kIGV4cGxhaW5lZCBgciByb3VuZCh2YXJfcGVyX3ZbM10sIDIpYCUgb2YgdGhlIHZhcmlhbmNlIChlLmcuLCAiSSBmaW5kIGl0IHRvdWdoIHRvIGZvY3VzIHdoZW5ldmVyIG15IHNtYXJ0cGhvbmUgaXMgbmVhcmJ5LiIsIGFuZCAiSSBiZWNvbWUgbGVzcyBhdHRlbnRpdmUgdG8gbXkgc3Vycm91bmRpbmdzIHdoZW4gSeKAmW0gdXNpbmcgbXkgc21hcnRwaG9uZS4iKS4gT25lIGl0ZW0gZGlkIG5vdCBjbGVhcmx5IGxvYWQgb250byBhbnkgb25lIGZhY3RvciBhbmQgd2FzIGV4Y2x1ZGVkIGZyb20gZnVydGhlciBhbmFseXNlcyAoaS5lLiwgaXRlbSA2OyBDb3N0ZWxsbyAmIE9zYm9ybmUsIDIwMDUpLiBTZWUgdGFibGUgYmVsb3cgZm9yIGFsbCBpdGVtcyBhbmQgZmFjdG9yIGxvYWRpbmdzLgoKYGBge3J9CgojIGNyZWF0ZSB0YWJsZSB3aXRoIGFsbCBpdGVtcywgZmFjdG9yIGxvYWRpbmdzLCBlaWdlbiB2YWx1ZXMsICUgb2YgdmlyYW5jZSBleHBsYWluZWQsIGFuZCBDcm9uYmFjaCdzIGFscGhhIAoKIyBnZXQgZmFjdG9yIGxvYWRpbmdzCiAgZmFfbG9hZCA9IGFzLmRhdGEuZnJhbWUoZmFfdGhyZWVfdiRTdHJ1Y3R1cmVbMToxMyxdKQogICMgcmVuYW1lIGNvbHVtbnMKICBjb2xuYW1lcyhmYV9sb2FkKSA9IGMoIkZhY3RvciAxIiwgIkZhY3RvciAyIiwgIkZhY3RvciAzIikKCiMgbWFrZSBsaXN0IG9mIHRoZSBpdGVtcyAmIG90aGVyIGluZm8KICBmYV90YWJsZV9saXN0ID0gYXMuZGF0YS5mcmFtZShjKCJJIHdvdWxkIGhhdmUgdHJvdWJsZSBnZXR0aW5nIHRocm91Z2ggYSBub3JtYWwgZGF5IHdpdGhvdXQgbXkgc21hcnRwaG9uZS4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSXQgd291bGQgYmUgcGFpbmZ1bCBmb3IgbWUgdG8gZ2l2ZSB1cCBteSBzbWFydHBob25lIGZvciBhIGRheS4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSSBmZWVsIGxpa2UgSSBjb3VsZCBub3QgbGl2ZSB3aXRob3V0IG15IHNtYXJ0cGhvbmUuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIklmIEkgZm9yZ290IHRvIGJyaW5nIG15IHNtYXJ0cGhvbmUgd2l0aCBtZSwgSSB3b3VsZCBmZWVsIGFueGlvdXMuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkl0IGRyaXZlcyBtZSBjcmF6eSB3aGVuIG15IHNtYXJ0cGhvbmUgcnVucyBvdXQgb2YgYmF0dGVyeS4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSSBhbSB1cHNldCBhbmQgYW5ub3llZCB3aGVuIEkgZmluZCBJIGRvIG5vdCBoYXZlIHJlY2VwdGlvbiBvbiBteSBzbWFydHBob25lLiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJIGZlZWwgaW1wYXRpZW50IHdoZW4gdGhlIEludGVybmV0IGNvbm5lY3Rpb24gc3BlZWQgb24gbXkgc21hcnRwaG9uZSBpcyBzbG93LiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJIGZlZWwgbG9uZWx5IHdoZW4gbXkgc21hcnRwaG9uZSBkb2VzIG5vdCByaW5nIG9yIHZpYnJhdGUgZm9yIHNldmVyYWwgaG91cnMuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVzaW5nIG15IHNtYXJ0cGhvbmUgcmVsaWV2ZXMgbWUgb2YgbXkgc3RyZXNzLiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJIGZlZWwgZXhjaXRlZCB3aGVuIEkgaGF2ZSBhIG5ldyBtZXNzYWdlIG9yIG5vdGlmaWNhdGlvbi4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVXNpbmcgbXkgc21hcnRwaG9uZSBtYWtlcyBtZSBmZWVsIGhhcHB5LiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJIGZpbmQgaXQgdG91Z2ggdG8gZm9jdXMgd2hlbmV2ZXIgbXkgc21hcnRwaG9uZSBpcyBuZWFyYnkuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkkgYmVjb21lIGxlc3MgYXR0ZW50aXZlIHRvIG15IHN1cnJvdW5kaW5ncyB3aGVuIEnigJltIHVzaW5nIG15IHNtYXJ0cGhvbmUuIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFaWdlbiBWYWx1ZXMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlZhcmlhbmNlIEV4cGxhaW5lZCAoJSkiKSkKICAKIyBjcmVhdGUgdGhlIGZpbmFsIHRhYmxlCiAgIyBiaW5kIHRoZSBsb2FkaW5ncyBhbmQgaXRlbXMKICAgIGZhX3RocmVlX3QgPSBjYmluZChmYV90YWJsZV9saXN0LCByYmluZChmYV9sb2FkLCB2YXJfcGVyX3RbNDo2XSkpCiAgICAKICAgICMgcmVuYW1lIGNvbHVtbnMgJiByb3dzCiAgICAgIGNvbG5hbWVzKGZhX3RocmVlX3QpID0gYygiSXRlbSIsICJGYWN0b3IgMTogU21hcnRwaG9uZSBEZXBlbmRlbmNlIiwgIkZhY3RvciAyOiBFbW90aW9uYWwgQXR0YWNobWVudCIsICJGYWN0b3IgMzogU21hcnRwaG9uZSBEaXN0cmFjdGFiaWxpdHkiKQogICAgICByb3duYW1lcyhmYV90aHJlZV90KVsxNDoxNV0gPSBjKCIiLCAiICIpIAogICAgICAKIyB1c2Uga2FibGUgdG8gc2hvdyB0aGUgdGFibGUKICBrYWJsZShmYV90aHJlZV90LCBjYXB0aW9uID0gIlN1bW1hcnkgb2YgZXhwbG9yYXRvcnkgdmFyaW1heCByb3RhdGVkIGZhY3RvciBhbmFseXNpcyByZXN1bHRzIGZvciB0aGUgMTMtSXRlbXMgaW4gdGhlIFNBRCAoTiA9IDQwOSkiLCBkaWdpdHMgPSA0LCBhbGlnbiA9ICJsY2NjIikgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgImhvdmVyIiwgZnVsbF93aWR0aCA9IFQpICU+JQogIHBhY2tfcm93cygiIiwgMTQsIDE1KQoKCmBgYAoKCgoKTG9vayBhdCBhICoqcmVsaWFiaWxpdHkgYW5hbHlzaXMqKi4uLiAKCgoKIyMjIyBHZW5lcmFsaXplZCBMaW5lYXIgTW9kZWwgIAoKICAtIEEgdW5pdmFyaWF0ZSBnZW5lcmFsaXplZCBsaW5lYXIgbW9kZWwgd2FzIHVzZWQgdG8gZXhhbWluZSBpZiBzbWFydHBob25lIHJlbGlhbmNlIChpLmUuIFNBRCBzY29yZSkgd2FzIGEgbW9kZXJhdG9yIG9mIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgZXhwZXJpbWVudGFsIG1hbmlwdWxhdGlvbiBhbmQgdGFzayBwZXJmb3JtYW5jZS4gCgoqTm90ZTogVGhlc2UgYW5hbHlzaXMgd2VyZSBjb21wbGV0ZWQgcmVnYXJkbGVzcyBvZiB0aGUgcmVzdWx0cyBmb3IgdGhlIGxvY2F0aW9uIGFuZCBwb3dlciBoeXBvdGhlc2VzLiogIAoKCgoKCgogCgoKCg==