Match Bathymetry and Raster Grids
Read in Data
Bathymetry
bathy_og<- raster("Data/raw/Multibeam/ElbowDec2015Cube_2m.tiff") #Original bathymetry
class : RasterLayer
dimensions : 13948, 4908, 68456784 (nrow, ncol, ncell)
resolution : 2, 2 (x, y)
extent : 184571, 194387, 3064261, 3092157 (xmin, xmax, ymin, ymax)
crs : +proj=utm +zone=17 +datum=WGS84 +units=m +no_defs
source : C:/Users/socce/Documents/Grad_School/Research/R_Projects/Elbow_Paper/Data/raw/Multibeam/ElbowDec2015Cube_2m.tiff
names : ElbowDec2015Cube_2m
values : -77.40717, -44.16052 (min, max)
Backscatter
backscatter_og<- raster("Data/raw/Multibeam/EL1_1mTimeSeriesBS_TrimmedtoMosaic_AVG800.tiff")
class : RasterLayer
dimensions : 26788, 8382, 224537016 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : 185107.5, 193489.5, 3064871, 3091659 (xmin, xmax, ymin, ymax)
crs : +proj=utm +zone=17 +datum=WGS84 +units=m +no_defs
source : C:/Users/socce/Documents/Grad_School/Research/R_Projects/Elbow_Paper/Data/raw/Multibeam/EL1_1mTimeSeriesBS_TrimmedtoMosaic_AVG800.tiff
names : EL1_1mTimeSeriesBS_TrimmedtoMosaic_AVG800
values : -13.84911, -5.748498 (min, max)
EL_shp<- readOGR("Data/derived/shapefiles/EL_Shp.shp")
[1] "SpatialPolygonsDataFrame"
attr(,"package")
[1] "sp"
[1] "Extent: 777033 783941 3065379 3090118 (xmin, xmax, ymin, ymax)"
[1] "crs: +proj=utm +zone=16 +datum=WGS84 +units=m +no_defs"
Resample to macthing 10m grid
bathy<- projectRaster(from = bathy_og, res = 10, crs = make_crs("UTM 16N")) #Reproject/resample
bathy<- focal(bathy, w=matrix(data = 1, nrow = 3, ncol = 3), fun=mean, na.rm=TRUE, NAonly=TRUE) #Fill holes
names(bathy)<- "bathy"
backscatter<- projectRaster(from= backscatter_og, to =bathy) #Reproject/resample
backscatter<- focal(backscatter, w=matrix(data = 1, nrow = 3, ncol = 3), fun=mean, na.rm=TRUE, NAonly=TRUE) #Fill holes
names(backscatter)<- "backscatter"
Trim data to mask
bathy<- mask(x = bathy, EL_shp)
backscatter<- mask(x = backscatter, EL_shp)
Finalized Surfaces
Figure S1.2

Calculate Derivative Features
Determine scales of analysis
The Fibonacci sequence is a good way to systematically cover multiple-scales (Wilson, 2007).
my_window_sizes<- 1+ (2*fib_seq(10)[-c(1,2)])
print(my_window_sizes)
[1] 3 5 7 11 17 27 43 69
We will evaluate predictors at 8 different window sizes from 3x3 to 69x69
Bathymetric Derivative Features
Calculate bathymetric derivatives at various scales of analysis. This includes the slope, aspect (split into Northness and Eastness), Topographic Position Index (Whether an area is a local high or low), mean bathymetry, and standard deviation of bathymetry (a measure of rugosity).
slope<- terrain(bathy, opt= "slope", unit = "degrees")
names(slope)<- "slope_native"
aspect<- terrain(bathy, opt = c("aspect"), unit = "radians")
eastness<- sin(aspect)
names(eastness)<- "eastness_native"
northness<- cos(aspect)
names(northness)<- "northness_native"
for (i in my_window_sizes) {
print(i)
w<- matrix(data = 1, nrow = i, ncol = i)
curr_slope<- focal(x = slope$slope_native, w, fun=mean, na.rm=TRUE, pad=TRUE)
names(curr_slope)<- paste0("slope_",as.character(i),"x", as.character(i))
slope<- addLayer(slope, curr_slope)
curr_eastness<- focal(x = eastness$eastness_native, w, fun=mean, na.rm=TRUE, pad=TRUE)
names(curr_eastness)<- paste0("eastness_",as.character(i),"x", as.character(i))
eastness<- addLayer(eastness, curr_eastness)
curr_northness<- focal(x = northness$northness_native, w, fun=mean, na.rm=TRUE, pad=TRUE)
names(curr_northness)<- paste0("northness_",as.character(i),"x", as.character(i))
northness<- addLayer(northness, curr_northness)
curr_tpi<- TPI(bathy, d=c(i,i), na.rm=TRUE, pad = TRUE)
names(curr_tpi)<- paste0("tpi_",as.character(i),"x", as.character(i))
curr_BathyMean<- focal(x = bathy, w, fun=mean, na.rm=TRUE, pad=TRUE)
names(curr_BathyMean)<- paste0("BathyMean_",as.character(i),"x", as.character(i))
curr_BathySD<- focal(x = bathy, w, fun=sd, na.rm=TRUE, pad=TRUE)
names(curr_BathySD)<- paste0("BathySD_",as.character(i),"x", as.character(i))
if(i==3){
tpi<- curr_tpi
BathyMean<- curr_BathyMean
BathySD<- curr_BathySD
} else{
tpi<- addLayer(tpi, curr_tpi)
BathyMean<- addLayer(BathyMean, curr_BathyMean)
BathySD<- addLayer(BathySD, curr_BathySD)
}
}
bathy_deriv<- stack(BathyMean, BathySD, tpi, slope, eastness, northness)
bathy_deriv<- mask(x = bathy_deriv, EL_shp) #Trim back down b/c used pad and na.rm
Backscatter Derivative Features
Calculate backscatter derivatives at various scales of analysis. This includes the mean and standard deviation of bathymetry as well as texture metric derived from a Gray Level Co-occurence Matrix (GLCM).
The most common texture metrics from remote sensing were derived using the formulas from (Hall-Beyer 2017). Rotationally Invariant/Directionally Isotropic Harilick Texture Metrics were derived by calculating a symetrical GLCM with 32 gray levels. The texture metrics can be broken down into three groups: The contrast group (contrast, dissimilarity, and homogeneity), the orderliness group (ASM and Entropy), and the descriptive statistics group (mean, variance, and correlation;Hall-Beyer, 2017). At smaller window sizes, the correlation texture can sometimes be undefined (0/0) leading to holes in the resulting raster surfaces, so correlation at 3x3, 5x5, and 7x7 were removed from the analysis to prevent this.
backscatter_quant<- quantize_raster(backscatter, n_levels = 32,method = "equal prob")
for (i in my_window_sizes) {
print(i)
w<- matrix(data = 1, nrow = i, ncol = i)
curr_bs_mean<- focal(backscatter, w, fun=mean, na.rm=TRUE, pad=TRUE)
names(curr_bs_mean)<- "BackscatterMean"
curr_bs_sd<- focal(backscatter, w, fun=sd, na.rm=TRUE, pad=TRUE)
names(curr_bs_sd)<- "BackscatterSD"
curr_BSderiv<- stack(curr_bs_mean,
curr_bs_sd,
glcm_textures(backscatter_quant, w= c(i,i), n_levels=32, shift = list(c(1, 0), c(1, 1), c(0, 1), c(-1, 1)), metrics = c("glcm_contrast", "glcm_dissimilarity", "glcm_homogeneity", "glcm_ASM",
"glcm_entropy", "glcm_mean", "glcm_variance", "glcm_correlation"), quantization= "none", na_opt = "center", pad = TRUE))
names(curr_BSderiv)<- paste0(names(curr_BSderiv), "_", as.character(i), "x", as.character(i))
if(i==3){
backscatter_deriv<- curr_BSderiv} else{
backscatter_deriv<- stack(backscatter_deriv, curr_BSderiv)
rm(curr_BSderiv)
}
}
backscatter_deriv<- mask(backscatter_deriv, EL_shp)
backscatter_deriv<- dropLayer(backscatter_deriv, which(names(backscatter_deriv)=="glcm_correlation_3x3"))
backscatter_deriv<- dropLayer(backscatter_deriv, which(names(backscatter_deriv)=="glcm_correlation_5x5"))
backscatter_deriv<- dropLayer(backscatter_deriv, which(names(backscatter_deriv)=="glcm_correlation_7x7")) #remove these b/c have NA's that create holes due to zero in denominator
Georeference Ground-Truth Data
Transects
Solid lines represent transects for training data, and dashed line represents the transect where observations were withheld in order to test the accuracy of substrate predictions
Figure S1.3

Read in Video Habitat Observations
Read in Timestamps for Camera Images
cam<- read_csv("Data/derived/CBASS/camera.csv")
Read in Position and Ancillary Data Streams
Hypack<- read_hypack(list.files("Data/raw/Hypack/", pattern="\\.RAW$", full.names = TRUE))
cable_out<- read_tsv("Data/raw/payout/payout_Feb&Oct2016.tsv", col_types = list(.default=col_double(), timestamp=col_datetime()))
Lat_Long<- get_HypackPos(Hypack)
names(Lat_Long)[2:3]<- c("ShipLon", "ShipLat")
Ship_Speed<- get_HypackSpeed(Hypack)
T1_oneHz<- make_1hz(alt_path = "Data/raw/CBASS/sensors/T1_D4/altimeter_readings.tsv", compass_path = "Data/raw/CBASS/sensors/T1_D4/compass_readings.tsv", ctd_path = "Data/raw/CBASS/sensors/T1_D4/ctd_redo_sal.tsv", Lat_Long = Lat_Long, Ship_Speed = Ship_Speed, cable_out = cable_out)
T3_oneHz<- make_1hz(alt_path = "Data/raw/CBASS/sensors/T3_D1/altimeter_readings.tsv", compass_path = "Data/raw/CBASS/sensors/T3_D1/compass_readings.tsv", ctd_path = "Data/raw/CBASS/sensors/T3_D1/ctd_redo_sal.tsv", Lat_Long = Lat_Long, Ship_Speed = Ship_Speed, cable_out = cable_out)
T5_oneHz<- make_1hz(alt_path = "Data/raw/CBASS/sensors/T5_D14/altimeter_readings.tsv", compass_path = "Data/raw/CBASS/sensors/T5_D14/compass_readings.tsv", ctd_path = "Data/raw/CBASS/sensors/T5_D14/ctd_redo_sal.tsv", Lat_Long = Lat_Long, Ship_Speed = Ship_Speed, cable_out = cable_out)
T6_oneHz<- make_1hz(alt_path = "Data/raw/CBASS/sensors/T6_D13/altimeter_readings.tsv", compass_path = "Data/raw/CBASS/sensors/T6_D13/compass_readings.tsv", ctd_path = "Data/raw/CBASS/sensors/T6_D13/ctd_redo_sal.tsv", Lat_Long = Lat_Long, Ship_Speed = Ship_Speed, cable_out = cable_out)
one_hz<- bind_rows(mutate(T1_oneHz, Transect="T1"),
mutate(T3_oneHz, Transect="T3"),
mutate(T5_oneHz, Transect="T5"),
mutate(T6_oneHz, Transect="T6"))
one_hz
Estimate C-BASS Position
CBASS Position is estimated using Pythagorean theorem using the cable out (the hypotenuse) and CBASS depth (the height of the triangle). The cable out is zeroed when the the CBASS hits the water so to get true cable out from the trawl block, and the true height of this triangle, the height of the trawl block above the water (~6.1 m) is added to the recorded cable out and CBASS Depth. The layback behind the block is then calculated using pythagorean theorum. The y offset (fore/aft distance; ~24.4 m) between the trawl block and the GPS antenna is then added to this layback to get the layback of the CBASS system behind the logged GPS ship position. CBASS is assumed to follow the ship track but with a time delay. The layback distance is converted to a time delay by dividing the layback distance by the average ship speed over the past minute. To get the CBASS position for a given time, the the ship position from “x” number of seconds ago (the time delay) is grabbed from the table and assigned as the current CBASS position. For more information see the documentation and source code for mytools::calc_layback (arguments used GPS_Source=“Nothstar”, zeroed=“water”, cat_fact=1).
one_hz<- one_hz %>% mutate(Layback_m= calc_layback(payout = payout, depth = depth, GPS_Source = "Northstar", zeroed = "water", cat_fact = 1))
one_hz<- one_hz %>% mutate(Layback_sec= round(Layback_m/Ship_Speed_mps_1minAvg))
one_hz<- one_hz %>% mutate(TimeToMatch=timestamp-dseconds(Layback_sec))
temp_one_hz<- one_hz %>% select(timestamp, Transect, ShipLon, ShipLat)
names(temp_one_hz)<- c("TimeToMatch", "Transect", "CBASSLon", "CBASSLat")
one_hz<- one_hz %>% left_join(temp_one_hz, by=c("TimeToMatch","Transect")) %>% select(-TimeToMatch)
rm(temp_one_hz)
one_hz
write_csv(one_hz, "Data/derived/CBASS/onehz.csv")
Georeference Video Habitat Observations
Calculate Frame number. Videos are 1 minute long at 12 frames per second.
hab<- hab %>% mutate(Frame_num= (Vid * 12 * 60) + Sec*12)
Get timestamp for each frame to nearest second
hab<- hab %>% left_join(select(cam, timestamp, u_second, Frame_num, Transect), by= c("Transect", "Frame_num"))
hab<- hab %>% mutate(timestamp=round_date(timestamp + dmicroseconds(u_second), unit = "second")) %>% select(-u_second)
Link to position by timestamp
hab<- hab %>% left_join(select(one_hz, timestamp, Transect, CBASSLat, CBASSLon), by=c("timestamp", "Transect"))
hab
write_csv(hab, path = "Data/derived/CBASS/hab.csv")
Prepare training and validation set
Only include habitats that were the same as their previous and subsequent observations to remove transitional/mixed areas to create set used for training and validation.
TV_set<- hab %>% group_by(Transect) %>% const_hab("Substrate") %>% ungroup()
print(unique(TV_set$Substrate))
[1] "Sand" "Rock" "No_Vis"
TV_set<- TV_set %>% filter(Substrate!="No_Vis") #Remove bad visibility
TV_set$Substrate<- factor(TV_set$Substrate, levels = c("Rock", "Sand"))
TV_set<- TV_set %>% mutate(Set=ifelse(test = Transect=="T1", yes = "Validation", no = "Training")) #Reserve T1 for validation of results. Use other transects for training data
Create Spatial Object
TV_set<- TV_set %>% filter(!is.na(CBASSLat)) #Remove where there is no positioning data
TV_set<- spTransform(SpatialPointsDataFrame(coords = cbind(TV_set$CBASSLon, TV_set$CBASSLat),
data = as.data.frame(select(TV_set, -c(CBASSLon, CBASSLat))),
proj4string = make_crs("WGS84")), CRSobj = make_crs("UTM 16N"))
TV_set<- TV_set[EL_shp,] #Remove points outside beyond bounds of the study area
The ground-truth dataset consisted of 3680 observations, where each observation was the substrate classification determined from the video at 15 second intervals. This consisted of 473 observations of rock, 3195 observations of sand, and 12 observations where substrate was not discernible. After censoring substrate determinations that differed from their previous and subsequent observations, those where substrate was not visible, and observations beyond the bounds of the multibeam survey or did not have associated positioning data, there were 238 observations of rock and 2533 observations of sand. These data were then split into training and validation sets. The training data set consisted of 210observations of rock and 1947 observations of sand. The validation transect consisted of 28 observations of rock and 586 observations of sand.
Figure S1.4

hab_onehz_joined<- hab %>% left_join(one_hz)
Transects total to 109 km in length
Overlaying vertical relief on substrate
Because higher relief features relatively rare, and are fairly small relative to the error associated with positioning of the CBASS, we did not directly try to predict this in the supervised and unsupervised models. However, we can measure vertical relief as a difference between the minimum and maximum values. Total depth was calculated from the CBASS sensors as CBASS depth + CBASS altitude (where altitude measurements have been adjusted for the pitch of the system). Vertical relief for each 15 second bin was calculated as the maximum change in depth over that 15 second observation window. A box plot of the assigned visual relief class, and the measured vertical relief from the sensors is shown below. In blue, orange, and red are the relief cutoffs for low, moderate, and high relief respectively as proposed by Smith et al (2011) in their reef fish survey of the Florida Keys. This appears to match up fairly well with our observations, so we will use these cutoffs: low relief <= 1m ; 1m < moderate relief <= 2m; high relief > 2m.
Figure S1.13
one_hz<- one_hz %>% mutate(Total_Depth= depth+ altitude*cos(radians(pitch))) #Calculate Total depth
one_hz<- one_hz %>% mutate(vertical_relief_15s = NA_real_)
for (i in 8:(nrow(one_hz)-7)) {
curr_idx<- (i-7):(i+7)
if(length(unique(one_hz$Transect[curr_idx]))!=1){
next() #Prevent averaging across different transects
}
dvalues<- one_hz$Total_Depth[curr_idx]
dmin<- min(dvalues, na.rm=TRUE)
dmax= max(dvalues, na.rm=TRUE)
vrelief<- dmax-dmin
if(is.infinite(vrelief)){vrelief<-NA}
one_hz$vertical_relief_15s[i]<- vrelief
}
hab_relief<- hab %>% left_join(one_hz, by= c("timestamp","Transect")) %>% select(timestamp, Transect, Relief, vertical_relief_15s) %>% filter(Relief!="None" & Relief != "No_Vis")
hab_relief$Relief<- factor(hab_relief$Relief, levels=c("Low_Relief", "Moderate_Relief", "High_Relief"))
visual_relief_plot<- ggplot(data = hab_relief, mapping = aes(x= Relief, y=vertical_relief_15s))+
annotate("rect", xmin = -Inf, xmax = Inf, ymin = 0, ymax = 1, fill= "dodgerblue", alpha=.2)+
annotate("rect", xmin = -Inf, xmax = Inf, ymin = 1, ymax = 2, fill= "orange", alpha=.2)+
annotate("rect", xmin = -Inf, xmax = Inf, ymin = 2, ymax = Inf, fill= "red", alpha=.2)+
geom_boxplot()+
scale_y_continuous(breaks = seq(0, 8, by= 1), expand = c(0,0))+
ylab("Vertical Relief (m) over 15 s")+
xlab("Relief Class")
visual_relief_plot

These thresholds are then used to delineate higher relief areas directly from the bathymetry by calculating the difference between a central pixel and the minimum depth of surrounding pixels using a sliding 3x3 window.
Figure S1.14
w<- matrix(data = 1, nrow = 3,ncol = 3) #3x3 window
w[5]<- NA
min_bathy<- focal(x = bathy, w=w, fun=min, na.rm=TRUE) #Calculate minimum depth around a central pixel
min_bathy[is.infinite(min_bathy)]<- NA #Replace Inf with NA
relief<- bathy-min_bathy #Calculate vertical relief
relief_qrules<- matrix(c(-Inf,1,2, 1, 2, Inf, 1,2,3), nrow = 3,ncol = 3)
relief_classified<- raster::reclassify(relief, relief_qrules, include.lowest=FALSE, right=TRUE)
relief_classified<- as.factor(relief_classified)
levels(relief_classified)[[1]]$Relief_Class<- c("Low","Mod", "High")
Relief_Map_Plot<- tm_shape(relief, raster.downsample = FALSE)+
tm_raster(palette=pal1, midpoint = NA, style="cont", title = "Relief (m)")+
tm_graticules(lines=FALSE)
Relief_Classified_Plot<- tm_shape(st_as_stars(relief_classified, ignore_file=TRUE), raster.downsample = FALSE)+
tm_raster(palette=c("gray", "yellow", "red"), title = "Relief Class")+
tm_graticules(lines=FALSE)
tmap_arrange(Relief_Map_Plot, Relief_Classified_Plot)

Figure S1.15
sub_relief<- (sup_hab*10)+relief_classified
sub_relief[sub_relief==22]<-21
sub_relief[sub_relief==23]<-21 #Collapse sand to one category
sub_relief<- as.factor(sub_relief)
names(sub_relief)<- "Habitat"
levels(sub_relief)[[1]]$habitat<- c("LR Rock", "MR Rock", "HR Rock", "Sand")
sub_relief_plot<- tm_shape(droplevels(st_as_stars(sub_relief, ignore_file=TRUE), exclude=NA), raster.downsample = FALSE)+
tm_raster(palette = c("dodgerblue", "orange", "red", "#FFEBBE"))+
tm_graticules(lines=FALSE)
sub_relief_plot

LS0tDQp0aXRsZTogIkVsYm93IE1hcHBpbmcgQW5hbHlzZXMiDQphdXRob3I6ICJBbGV4YW5kZXIgSWxpY2giDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclQiAlZCwgJVknKWAiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgZmlnX3dpZHRoOiA2DQogICAgZmlnX2hlaWdodDogOQ0KICAgIGRmX3ByaW50OiBwYWdlZA0KZWRpdG9yX29wdGlvbnM6DQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gbm9ybWFsaXplUGF0aCgiLi4iKSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGNhY2hlID0gRkFMU0UsIGRwaSA9IDMwMCwgZmlnLndpZHRoID0gNiwgZmlnLmhlaWdodCA9IDkpICNEZWZhdWx0IGNodW5rIG9wdGlvbnMNCmluc3RhbGxlZF9wYWNrYWdlczwtIGluc3RhbGxlZC5wYWNrYWdlcygpDQpuZWVkZWRfcGFja2FnZXM8LSBjKCJjYXJldCIsICJSQ29sb3JCcmV3ZXIiLCAicGFyYWxsZWwiLCAic25vdyIsICJyYW5nZXIiLCAiQm9ydXRhIiwgImx1YnJpZGF0ZSIsICJyZ2RhbCIsICJzcCIsICJyYXN0ZXIiLCAic3RhcnMiLCAidG1hcCIsICJSU3Rvb2xib3giLA0KICAgICAgICAgICAgICAgICAgICAidGlkeXZlcnNlIiwgInJlYWR4bCIsICJzcGRwbHlyIiwgImNvbG9yUmFtcHMiLCAiZGV2dG9vbHMiKQ0KDQpwYWNrYWdlc190b19pbnN0YWxsPC0gbmVlZGVkX3BhY2thZ2VzWyEobmVlZGVkX3BhY2thZ2VzICVpbiUgaW5zdGFsbGVkX3BhY2thZ2VzKV0NCmlmKGxlbmd0aChwYWNrYWdlc190b19pbnN0YWxsKT4wKXsNCiAgaW5zdGFsbC5wYWNrYWdlcyhwYWNrYWdlc190b19pbnN0YWxsKQ0KICB9DQppZighKCJteXRvb2xzIiAlaW4lIGluc3RhbGxlZF9wYWNrYWdlcykpew0KICBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoImFpbGljaC9teXRvb2xzQHYwLjMxIikgDQogIH0gDQppZighKCJHTENNVGV4dHVyZXMiICVpbiUgaW5zdGFsbGVkX3BhY2thZ2VzKSl7DQogIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiYWlsaWNoL0dMQ01UZXh0dXJlc0AwLjEiKSANCiAgfSAjSW5zdGFsbA0KDQpsaWJyYXJ5KGNhcmV0KSAjTW9kZWxsaW5nDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikgI0NvbG9yIFBhbGV0dGVzDQpsaWJyYXJ5KHBhcmFsbGVsKSAjUGFyYWxsZWwgUHJvY2Vzc2luZw0KbGlicmFyeShzbm93KSAjUGFyYWxsZWwgUHJvY2Vzc2luZw0KbGlicmFyeShyYW5nZXIpICNGb3IgUmFuZG9tIEZvcmVzdCBNb2RlbA0KbGlicmFyeShCb3J1dGEpICNWYXJpYWJsZSBTZWxlY3Rpb24NCmxpYnJhcnkobHVicmlkYXRlKSAjVGltZSBEYXRhDQpsaWJyYXJ5KHJnZGFsKSAjU3BhdGlhbCBEYXRhDQpsaWJyYXJ5KHNwKSAjU3BhdGlhbCBkYXRhDQpsaWJyYXJ5KHJhc3RlcikgI1NwYXRpYWwgRGF0YQ0KbGlicmFyeShzdGFycykgI1NwYXRpYWwgZGF0YQ0KbGlicmFyeSh0bWFwKSAjU3BhdGlhbCBQbG90dGluZw0KbGlicmFyeShSU3Rvb2xib3gpICNTcGF0aWFsIE1vZGVsbGluZw0KbGlicmFyeSh0aWR5dmVyc2UpICNEYXRhIFdyYW5nbGluZw0KbGlicmFyeShyZWFkeGwpICNyZWFkIGV4Y2VsIHNoZWV0cw0KbGlicmFyeShzcGRwbHlyKSAjRGF0YSBXcmFuZ2xpbmcgZm9yIHNwYXRpYWwgZGF0YQ0KbGlicmFyeShHTENNVGV4dHVyZXMpICNHTENNIFRleHR1cmUgTWV0cmljcw0KbGlicmFyeShteXRvb2xzKSAjTXkgZnVuY3Rpb25zDQpvcHRpb25zKHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNClN5cy5zZXRlbnYoVFo9J1VUQycpICNTZXQgdGltZSB0byBkaXNwbGF5IGluIFVUQw0Kb3B0aW9ucyhkaWdpdHMuc2Vjcz0gNikgI1RpbWUgZGlnaXRzIGRpc3BsYXllZCBhbmQgd3JpdHRlbiB0byA2IHBsYWNlcw0KcmFzdGVyT3B0aW9ucyhhZGRoZWFkZXIgPSAiRU5WSSIpICNQcmVzZXJ2ZXMgbmFtZXMgd2hlbiB3cml0aW5nIHJhc3RlciBzdGFja3MgdG8gZmlsZQ0KYGBgDQoNCmBgYHtyIHdhcm5pbmc9VFJVRSwgaW5jbHVkZT1GQUxTRX0NCiNteXRvb2xzIGFuZCBHTENNVGV4dHVyZXMgYXJlIHBhY2thZ2VzIEkgY3JlYXRlZC4gbXl0b29scyBpcyBhc3NvcnRlZCBmdW5jdGlvbnMgSSBoYXZlIG1hZGUgb3ZlciB0aW1lIGFuZCBHTENNVGV4dHVyZXMgY2FsY3VsYXRlcyB0ZXh0dXJlIG1ldHJpY3MNCmlmKHBhY2thZ2VWZXJzaW9uKCJteXRvb2xzIikhPSIwLjMiKXsNCiAgd2FybmluZygibXl0b29scyBpcyBhIGRpZmZlcmVudCB2ZXJzaW9uIHRoYW4gdGhlIG9uZSBJIHVzZWQgdG8gcnVuIHRoaXMgc2NyaXB0IGFuZCBtYXkgcHJvZHVjZSBkaWZmZXJlbnQgcmVzdWx0cyIpDQp9DQppZihwYWNrYWdlVmVyc2lvbigiR0xDTVRleHR1cmVzIikhPSIwLjAuMS4wIil7DQogIHdhcm5pbmcoIkdMQ01UZXh0dXJlcyBpcyBhIGRpZmZlcmVudCB2ZXJzaW9uIHRoYW4gdGhlIG9uZSBJIHVzZWQgdG8gcnVuIHRoaXMgc2NyaXB0IGFuZCBtYXkgcHJvZHVjZSBkaWZmZXJlbnQgcmVzdWx0cyIpDQp9DQpgYGANCg0KYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0NCiNOb3RlIHRvIGxvYWQgdGhlIGVudmlyb25tZW50IGFzIGl0IHdvdWxkIGJlIGF0IHRoZSBlbmQgb2YgdGhlIHNjcmlwdCB3aXRob3V0IHJ1bm5pbmcgaXQsIHJ1biB0aGlzIGxpbmUgb2YgY29kZQ0KbG9hZCgiRGF0YS9SX2Vudmlyb25tZW50L0VsYm93X1JfTWFwcGluZ19FbnZpcm9ubWVudC5SRGF0YSIpDQpgYGANCg0KYGBge3IgRGVmaW5lIEZ1bmN0aW9ucywgaW5jbHVkZT1GQUxTRX0NCiNGdW5jdGlvbiBmb3IgcGFyc2luZyByYXcgZGF0YSBpbnRvIDFIeiB0YWJsZQ0KbWFrZV8xaHo8LSBmdW5jdGlvbihhbHRfcGF0aCwgY29tcGFzc19wYXRoLCBjdGRfcGF0aCwgTGF0X0xvbmcsIFNoaXBfU3BlZWQsIGNhYmxlX291dCl7DQogIExhdF9Mb25nPC0gTGF0X0xvbmcgJT4lIG11dGF0ZSh0aW1lc3RhbXA9IHJvdW5kX2RhdGUodGltZXN0YW1wLCB1bml0ID0gInNlY29uZCIpKSAlPiUNCiAgICBncm91cF9ieSh0aW1lc3RhbXApICU+JQ0KICAgIHN1bW1hcml6ZShTaGlwTG9uPW1lYW4oU2hpcExvbiwgbmEucm09VFJVRSksIFNoaXBMYXQ9bWVhbihTaGlwTGF0LCBuYS5ybT1UUlVFKSwgLmdyb3Vwcz0iZHJvcCIpDQoNCiAgY2FibGVfb3V0PC0gY2FibGVfb3V0ICU+JSBtdXRhdGUodGltZXN0YW1wPSByb3VuZF9kYXRlKHRpbWVzdGFtcCArIGRtaWNyb3NlY29uZHModV9zZWNvbmQpLCB1bml0ID0gInNlY29uZCIpKSAlPiUNCiAgICBncm91cF9ieSh0aW1lc3RhbXApICU+JQ0KICAgIHN1bW1hcml6ZShwYXlvdXQ9bWVhbihwYXlvdXQsIG5hLnJtPVRSVUUpLCAuZ3JvdXBzPSJkcm9wIikNCg0KICBTaGlwX1NwZWVkPC0gU2hpcF9TcGVlZCAlPiUgbXV0YXRlKFNoaXBfU3BlZWRfbXBzPVNwZWVkX2twaCooMTAwMC8oNjAqNjApKSkgI0NvbnZlcnQgdG8gbWV0ZXJzIHBlciBzZWNvbmQNCiAgU2hpcF9TcGVlZDwtIFNoaXBfU3BlZWQgJT4lIG11dGF0ZSh0aW1lc3RhbXA9IHJvdW5kX2RhdGUodGltZXN0YW1wLCB1bml0ID0gInNlY29uZCIpKSAlPiUNCiAgICBncm91cF9ieSh0aW1lc3RhbXApICU+JQ0KICAgIHN1bW1hcml6ZShTaGlwX1NwZWVkX21wcz1tZWFuKFNoaXBfU3BlZWRfbXBzLCBuYS5ybT1UUlVFKSwgLmdyb3Vwcz0iZHJvcCIpDQoNCiAgYWx0PC0gcmVhZF90c3YoYWx0X3BhdGgsIGNvbF90eXBlcyA9IGxpc3QoLmRlZmF1bHQ9Y29sX2RvdWJsZSgpLCB0aW1lc3RhbXA9Y29sX2RhdGV0aW1lKCkpKQ0KICBjb21wYXNzPC0gcmVhZF90c3YoY29tcGFzc19wYXRoLCBjb2xfdHlwZXMgPSBsaXN0KC5kZWZhdWx0PWNvbF9kb3VibGUoKSwgdGltZXN0YW1wPWNvbF9kYXRldGltZSgpKSkNCiAgY3RkPC0gcmVhZF90c3YoY3RkX3BhdGgsIGNvbF90eXBlcyA9IGxpc3QoLmRlZmF1bHQ9Y29sX2RvdWJsZSgpLCB0aW1lc3RhbXA9Y29sX2RhdGV0aW1lKCkpKQ0KDQogIGFsdCRhbHRpdHVkZVthbHQkYWx0aXR1ZGU+PTUwXTwtIE5BICM1MCBpcyBtYXggdmFsdWUgb2YgYWx0aW1ldGVyIDYwIGFueSB2YWx1ZSA1MCBvciBncmVhdGVyIGlzIHJlY29yZGVkIGFzIDUwDQogIGFsdDwtIGFsdCAlPiUgbXV0YXRlKHRpbWVzdGFtcD1yb3VuZF9kYXRlKHRpbWVzdGFtcCtkbWljcm9zZWNvbmRzKHVfc2Vjb25kKSwgdW5pdCA9ICJzZWNvbmQiKSkgJT4lDQogICAgZ3JvdXBfYnkodGltZXN0YW1wKSAlPiUNCiAgICBzdW1tYXJpemUoYWx0aXR1ZGU9bWVkaWFuKGFsdGl0dWRlLCBuYS5ybT1UUlVFKSwgLmdyb3Vwcz0iZHJvcCIpDQoNCiAgY29tcGFzczwtIGNvbXBhc3MgJT4lIG11dGF0ZSh0aW1lc3RhbXA9cm91bmRfZGF0ZSh0aW1lc3RhbXArZG1pY3Jvc2Vjb25kcyh1X3NlY29uZCksIHVuaXQgPSAic2Vjb25kIikpICU+JQ0KICAgIGdyb3VwX2J5KHRpbWVzdGFtcCkgJT4lDQogICAgc3VtbWFyaXplKGhlYWRpbmc9IG1lZGlhbihoZWFkaW5nLCBuYS5ybSA9IFRSVUUpLCBwaXRjaD1tZWRpYW4ocGl0Y2gsIG5hLnJtPVRSVUUpLCByb2xsPW1lZGlhbihyb2xsLCBuYS5ybT1UUlVFKSwgLmdyb3Vwcz0iZHJvcCIpDQoNCiAgY3RkPC0gY3RkICU+JSBtdXRhdGUodGltZXN0YW1wPXJvdW5kX2RhdGUodGltZXN0YW1wK2RtaWNyb3NlY29uZHModV9zZWNvbmQpLCB1bml0ID0gInNlY29uZCIpKSAlPiUNCiAgICBncm91cF9ieSh0aW1lc3RhbXApICU+JQ0KICAgIHN1bW1hcml6ZSh0ZW1wZXJhdHVyZT0gbWVhbih0ZW1wZXJhdHVyZSwgbmEucm09VFJVRSksIGRlcHRoPW1lYW4oZGVwdGgsIG5hLnJtPVRSVUUpLCBzYWxpbml0eT0gbWVhbihzYWxpbml0eSwgbmEucm09VFJVRSksIC5ncm91cHM9ImRyb3AiKQ0KDQogIG9uZV9oejwtIHRpYmJsZSh0aW1lc3RhbXA9c2VxLlBPU0lYdChmcm9tID1taW4oYyhhbHQkdGltZXN0YW1wLCBjb21wYXNzJHRpbWVzdGFtcCwgY3RkJHRpbWVzdGFtcCkpLWRzZWNvbmRzKDE4MCksIHRvID0gbWF4KGMoYWx0JHRpbWVzdGFtcCwgY29tcGFzcyR0aW1lc3RhbXAsIGN0ZCR0aW1lc3RhbXApKSwgYnkgPSAic2VjIikpDQoNCiAgb25lX2h6PC0gb25lX2h6ICU+JQ0KICAgIGxlZnRfam9pbihMYXRfTG9uZywgYnk9InRpbWVzdGFtcCIpICU+JQ0KICAgIGxlZnRfam9pbihTaGlwX1NwZWVkLCBieT0idGltZXN0YW1wIikgJT4lDQogICAgbGVmdF9qb2luKGFsdCwgYnk9InRpbWVzdGFtcCIpICU+JQ0KICAgIGxlZnRfam9pbihjb21wYXNzLCBieT0idGltZXN0YW1wIikgJT4lDQogICAgbGVmdF9qb2luKGN0ZCwgYnk9InRpbWVzdGFtcCIpICU+JQ0KICAgIGxlZnRfam9pbihjYWJsZV9vdXQsIGJ5PSJ0aW1lc3RhbXAiKQ0KDQogIG9uZV9oeiRTaGlwTG9uPC0gaW50ZXJwKG9uZV9oeiRTaGlwTG9uLCBuYS5ybSA9IFRSVUUpDQogIG9uZV9oeiRTaGlwTGF0PC0gaW50ZXJwKG9uZV9oeiRTaGlwTGF0LCBuYS5ybSA9IFRSVUUpDQogIG9uZV9oeiRhbHRpdHVkZTwtIGludGVycChvbmVfaHokYWx0aXR1ZGUsIG5hLnJtID0gVFJVRSkNCiAgb25lX2h6JGFsdGl0dWRlWzE4MF08LSBOQV9yZWFsXw0KICBvbmVfaHokcGl0Y2g8LSBpbnRlcnAob25lX2h6JHBpdGNoLCBuYS5ybSA9IFRSVUUpDQogIG9uZV9oeiRwaXRjaFsxODBdPC0gTkFfcmVhbF8NCiAgb25lX2h6JGRlcHRoPC0gaW50ZXJwKG9uZV9oeiRkZXB0aCwgbmEucm0gPSBUUlVFKQ0KICBvbmVfaHokZGVwdGhbMTgwXTwtIE5BX3JlYWxfDQogIG9uZV9oeiRwYXlvdXQ8LSBpbnRlcnAob25lX2h6JHBheW91dCwgbmEucm0gPSBUUlVFKQ0KDQogIG9uZV9oejwtIG9uZV9oeiAlPiUgbXV0YXRlKFNoaXBfU3BlZWRfbXBzXzFtaW5Bdmc9TkFfcmVhbF8pDQogIGZvciAoaSBpbiA2MDpucm93KG9uZV9oeikpIHsNCiAgICBvbmVfaHokU2hpcF9TcGVlZF9tcHNfMW1pbkF2Z1tpXTwtIG1lYW4ob25lX2h6JFNoaXBfU3BlZWRfbXBzWyhpLTU5KTppXSwgbmEucm09VFJVRSkNCiAgfSAjMSBtaW51dGUgcm9sbGluZyBhdmVyYWdlDQogIHJldHVybihvbmVfaHopDQp9DQoNCmZpYl9zZXE8LSBmdW5jdGlvbihuKXsNCiAgZmliPC0gcmVwKE5BX3JlYWxfLCBuKQ0KICBmaWJbMToyXTwtIGMoMCwxKQ0KICBmb3IgKGkgaW4gMzpsZW5ndGgoZmliKSkgew0KICBmaWJbaV08LSBmaWJbaS0xXStmaWJbaS0yXQ0KICB9DQogIHJldHVybihmaWIpfQ0KDQpleHRyYWN0X3Jhbmdlcl9vb2I8LSBmdW5jdGlvbihvYmosIHRyYWluaW5nRGF0YSwgcmVzcG9uc2VfY29sKXsNCiAgaWYoY2xhc3Mob2JqKVsxXT09InN1cGVyQ2xhc3MiKXsNCiAgICBvYmo8LSBvYmokbW9kZWx9DQogIA0KICBpZihjbGFzcyhvYmopWzFdPT0idHJhaW4iKXsNCiAgICB0cmFpbmluZ0RhdGE8LSBvYmokdHJhaW5pbmdEYXRhDQogICAgcmVzcG9uc2VfY29sPC0gIi5vdXRjb21lIg0KICAgIGZpbmFsX21vZDwtIG9iaiRmaW5hbE1vZGVsDQogIH0gZWxzZXsNCiAgICBmaW5hbF9tb2Q8LSBvYmp9DQogIG5fdHJlZXM8LSBmaW5hbF9tb2QkbnVtLnRyZWVzDQogIG5fY2xhc3NlczwtIGxlbmd0aCh1bmlxdWUodHJhaW5pbmdEYXRhW1tyZXNwb25zZV9jb2xdXSkpDQogIA0KICBUcmVlX09PQjwtIGRhdGEuZnJhbWUoVHJlZT0gcmVwKDE6bl90cmVlcywgZWFjaD0gbl9jbGFzc2VzKzEpLCBPT0IgPSBOQV9yZWFsXykNCiAgajwtMQ0KICBmb3IgKGkgaW4gMTpuX3RyZWVzKSB7DQogICAgaWR4PC0gZmluYWxfbW9kJGluYmFnLmNvdW50c1tbaV1dPT0wDQogICAgT09CX2RhdGE8LSB0cmFpbmluZ0RhdGFbaWR4LF0NCiAgICBPT0I8LSBzdGF0czo6cHJlZGljdChmaW5hbF9tb2QsIE9PQl9kYXRhKQ0KICAgIE9PQl9wcmVkaWN0aW9uPC0gYXMuZGF0YS5mcmFtZShPT0IkcHJlZGljdGlvbnMpDQogICAgDQogICAgaWYobmNvbChPT0JfcHJlZGljdGlvbik+MSl7DQogICAgICBPT0JfcHJlZGljdGlvbjwtIE9PQl9wcmVkaWN0aW9uICU+JSBtdXRhdGUoSUQ9MTpucm93KGFsbF9vZihPT0JfcHJlZGljdGlvbikpKQ0KICAgICAgT09CX3ByZWRpY3Rpb248LSBPT0JfcHJlZGljdGlvbiAlPiUgcGl2b3RfbG9uZ2VyKC1JRCkNCiAgICAgIE9PQl9wcmVkaWN0aW9uPC0gT09CX3ByZWRpY3Rpb24gJT4lIGdyb3VwX2J5KElEKSAlPiUgZmlsdGVyKHZhbHVlPT1tYXgodmFsdWUpKSAlPiUgc2FtcGxlX24oMSkgJT4lIHVuZ3JvdXAoKSAlPiUgYXJyYW5nZShJRCkNCiAgICAgIE9PQl9wcmVkaWN0aW9uPC0gT09CX3ByZWRpY3Rpb24gJT4lIHNlbGVjdChuYW1lKQ0KICAgICAgbmFtZXMoT09CX3ByZWRpY3Rpb24pPC0gIlYxIg0KICAgICAgT09CX3ByZWRpY3Rpb248LSBPT0JfcHJlZGljdGlvbiRWMQ0KICAgICAgfSAjUmVmb3JtYXQgaWYgd2FzIGluIHByb2JhaWxpdHkgaW5zdGVhZCBvZiBjbGFzc2lmaWNhdGlvbiBtb2RlDQoNCiAgICBPYnNlcnZlZF92c19QcmVkaWN0ZWQ8LSBkYXRhLmZyYW1lKE9ic2VydmVkPSBPT0JfZGF0YVtbcmVzcG9uc2VfY29sXV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQcmVkaWN0ZWQ9IE9PQl9wcmVkaWN0aW9uKSANCiAgICBUcmVlX09PQiRPT0Jbal08LSBzdW0oT2JzZXJ2ZWRfdnNfUHJlZGljdGVkJE9ic2VydmVkIT1PYnNlcnZlZF92c19QcmVkaWN0ZWQkUHJlZGljdGVkKS9ucm93KE9ic2VydmVkX3ZzX1ByZWRpY3RlZCkNCiAgICBUcmVlX09PQiRUeXBlW2pdPC0gIk92ZXJhbGwiDQogICAgYnlfY2xhc3NPT0I8LSBPYnNlcnZlZF92c19QcmVkaWN0ZWQgJT4lIGdyb3VwX2J5KE9ic2VydmVkLCAuZHJvcD1GQUxTRSkgJT4lIHN1bW1hcml6ZShPT0I9IHN1bShPYnNlcnZlZCE9UHJlZGljdGVkKS9uKCksIC5ncm91cHM9ImRyb3AiKQ0KICAgIFRyZWVfT09CJE9PQlsoaisxKTooaituX2NsYXNzZXMpXTwtIGJ5X2NsYXNzT09CJE9PQg0KICAgIFRyZWVfT09CJFR5cGVbKGorMSk6KGorbl9jbGFzc2VzKV08LSBhcy5jaGFyYWN0ZXIoYnlfY2xhc3NPT0IkT2JzZXJ2ZWQpDQogICAgajwtIGorbl9jbGFzc2VzKzENCiAgfQ0KICBUcmVlX09PQjwtIFRyZWVfT09CICU+JSBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gVHlwZSwgdmFsdWVzX2Zyb209T09CKQ0KICBNZWFuX09PQjwtIGRhdGEuZnJhbWUobnRyZWVzPSAxOm5fdHJlZXMpDQogIGZvciAoayBpbiAyOm5jb2woVHJlZV9PT0IpKSB7DQogICAgTkFfaWR4PC0gaXMubmEoVHJlZV9PT0JbLGtdKQ0KICAgIE1lYW5fT09CX3RlbXA8LSBUcmVlX09PQlshTkFfaWR4LGMoMSxrKV0NCiAgICBNZWFuX09PQl90ZW1wWywyXTwtIGN1bW1lYW4oYXMuZGF0YS5mcmFtZShNZWFuX09PQl90ZW1wKVssMl0pDQogICAgTWVhbl9PT0I8LSBNZWFuX09PQiAlPiUgbGVmdF9qb2luKE1lYW5fT09CX3RlbXAsIGJ5PWMoIm50cmVlcyI9IlRyZWUiKSkNCiAgfQ0KICByZXR1cm4oTWVhbl9PT0IpDQp9DQpgYGANCg0KIyBTdHVkeSBBcmVhDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KRkxfc2hwPC0gcmVhZE9HUigiRGF0YS9kZXJpdmVkL3NoYXBlZmlsZXMvRmxvcmlkYV9TaG9yZWxpbmVfXzFfdG9fMiUyQzAwMCUyQzAwMF9TY2FsZV8uc2hwIikgI1NvdXJjZTogaHR0cHM6Ly9nZW9kYXRhLm15ZndjLmNvbS9kYXRhc2V0cy9mbG9yaWRhLXNob3JlbGluZS0xLXRvLTIwMDAwMDAtc2NhbGU/Z2VvbWV0cnk9LTEwMi4zNjYlMkMyNC4zNTYlMkMtNjUuMjk4JTJDMzEuMTU2DQpFTF9zaHA8LSByZWFkT0dSKCJEYXRhL2Rlcml2ZWQvc2hhcGVmaWxlcy9FTF9TaHAuc2hwIikNCmBgYA0KVGhlIHN0dWR5IGFyZWEgaXMgbWFya2VkIGluIHJlZCwgYW5kIGlzIGtub3cgYXMgIlRoZSBFbGJvdy4iIEl0IGlzIGFib3V0IDE0NSBrbSB3ZXN0LW5vcnRod2VzdCBvZiBUYW1wYSBCYXksIEZsb3JpZGEuIFRoZSBhcmVhIGlzIGEgcG9wdWxhciBvZmZzaG9yZSBmaXNoaW5nIGFyZWEgdGhhdCBjb250YWlucyBjb250YWlucyBoYXJkIGJvdHRvbSByaWRnZXMgYW5kIGlzIGh5cG90aGVzaXplZCB0byBiZSBhIHBhbGVvc2hvcmVsaW5lIHNoYXBlZCBieSB3YXZlIGFjdGlvbiBhcHByb3hpbWF0ZWx5IDEyLDAwMCB5ZWFycyBhZ28uDQoNCkZpZ3VyZSBTMS4xDQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTZ9DQp0bV9zaGFwZShGTF9zaHApKw0KICB0bV9maWxsKCkrDQogIHRtX3NoYXBlKEVMX3NocCkrDQogIHRtX2ZpbGwoY29sPSJyZWQiKSsNCiAgdG1fZ3JhdGljdWxlcyhsaW5lcz1GQUxTRSkrDQogIHRtX2NyZWRpdHMoImh0dHBzOi8vZ2VvZGF0YS5teWZ3Yy5jb20vZGF0YXNldHMiLCBwb3NpdGlvbiA9IGMoImxlZnQiLCAiYm90dG9tIikpDQpgYGANCg0KIyBNYXRjaCBCYXRoeW1ldHJ5IGFuZCBSYXN0ZXIgR3JpZHMNCg0KIyMgUmVhZCBpbiBEYXRhDQoNCkJhdGh5bWV0cnkNCmBgYHtyIH0NCmJhdGh5X29nPC0gcmFzdGVyKCJEYXRhL3Jhdy9NdWx0aWJlYW0vRWxib3dEZWMyMDE1Q3ViZV8ybS50aWZmIikgI09yaWdpbmFsIGJhdGh5bWV0cnkNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KYmF0aHlfb2cNCmBgYA0KQmFja3NjYXR0ZXINCmBgYHtyIH0NCmJhY2tzY2F0dGVyX29nPC0gcmFzdGVyKCJEYXRhL3Jhdy9NdWx0aWJlYW0vRUwxXzFtVGltZVNlcmllc0JTX1RyaW1tZWR0b01vc2FpY19BVkc4MDAudGlmZiIpDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRX0NCmJhY2tzY2F0dGVyX29nDQpgYGANCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQ0KRUxfc2hwPC0gcmVhZE9HUigiRGF0YS9kZXJpdmVkL3NoYXBlZmlsZXMvRUxfU2hwLnNocCIpDQpgYGANCmBgYHtyIGVjaG89RkFMU0V9DQpwcmludChzdW1tYXJ5KEVMX3NocCkkY2xhc3MpDQpwcmludChwYXN0ZSgiRXh0ZW50OiIsIHBhc3RlKGFzLmNoYXJhY3Rlcihyb3VuZChhcy52ZWN0b3IodChzdW1tYXJ5KEVMX3NocCkkYmJveCkpKSksIGNvbGxhcHNlPSIgIiksICIoeG1pbiwgeG1heCwgeW1pbiwgeW1heCkiKSkNCnByaW50KHBhc3RlKCJjcnM6Iiwgc3VtbWFyeShFTF9zaHApJHByb2o0c3RyaW5nKSkNCmBgYA0KDQojIyBSZXNhbXBsZSB0byBtYWN0aGluZyAxMG0gZ3JpZA0KYGBge3IgfQ0KYmF0aHk8LSBwcm9qZWN0UmFzdGVyKGZyb20gPSBiYXRoeV9vZywgcmVzID0gMTAsIGNycyA9IG1ha2VfY3JzKCJVVE0gMTZOIikpICNSZXByb2plY3QvcmVzYW1wbGUNCmJhdGh5PC0gZm9jYWwoYmF0aHksIHc9bWF0cml4KGRhdGEgPSAxLCBucm93ID0gMywgbmNvbCA9IDMpLCBmdW49bWVhbiwgbmEucm09VFJVRSwgTkFvbmx5PVRSVUUpICNGaWxsIGhvbGVzICAgDQpuYW1lcyhiYXRoeSk8LSAiYmF0aHkiDQpiYWNrc2NhdHRlcjwtIHByb2plY3RSYXN0ZXIoZnJvbT0gYmFja3NjYXR0ZXJfb2csIHRvID1iYXRoeSkgI1JlcHJvamVjdC9yZXNhbXBsZQ0KYmFja3NjYXR0ZXI8LSBmb2NhbChiYWNrc2NhdHRlciwgdz1tYXRyaXgoZGF0YSA9IDEsIG5yb3cgPSAzLCBuY29sID0gMyksIGZ1bj1tZWFuLCBuYS5ybT1UUlVFLCBOQW9ubHk9VFJVRSkgI0ZpbGwgaG9sZXMgICANCm5hbWVzKGJhY2tzY2F0dGVyKTwtICJiYWNrc2NhdHRlciINCmBgYA0KDQpUcmltIGRhdGEgdG8gbWFzaw0KYGBge3IgfQ0KYmF0aHk8LSBtYXNrKHggPSBiYXRoeSwgRUxfc2hwKQ0KYmFja3NjYXR0ZXI8LSBtYXNrKHggPSBiYWNrc2NhdHRlciwgRUxfc2hwKQ0KYGBgDQoNCiMjIEZpbmFsaXplZCBTdXJmYWNlcw0KDQpGaWd1cmUgUzEuMg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcud2lkdGg9MTAsIGluY2x1ZGU9VFJVRX0NCnBhbDE8LSBjb2xvclJhbXBzOjptYXRsYWIubGlrZSgxMDApDQoNCmJhdGh5X3Bsb3Q8LSB0bV9zaGFwZShiYXRoeSwgcmFzdGVyLmRvd25zYW1wbGUgPSBGQUxTRSkgKw0KICB0bV9yYXN0ZXIocGFsZXR0ZSA9IHBhbDEsIHN0eWxlPSAiY29udCIsIHRpdGxlID0gIkJhdGh5bWV0cnkgKG0pIikrDQogIHRtX2NvbXBhc3ModHlwZSA9ICI4c3RhciIsIHBvc2l0aW9uID0gYygicmlnaHQiLCAidG9wIikpKw0KICB0bV9zY2FsZV9iYXIoYnJlYWtzPSBjKDAsIDIuNSwgNSksIHRleHQuc2l6ZT0xKSsNCiAgdG1fY3JlZGl0cyh0ZXh0ID0gImEpIiwgcG9zaXRpb24gPSBjKCJsZWZ0IiwgImJvdHRvbSIpLCBzaXplID0gMSkrDQogIHRtX2dyYXRpY3VsZXMobGluZXM9RkFMU0UpDQoNCmJhY2tzY2F0dGVyX3Bsb3Q8LSB0bV9zaGFwZShiYWNrc2NhdHRlciwgcmFzdGVyLmRvd25zYW1wbGUgPSBGQUxTRSkrDQogIHRtX3Jhc3RlcihwYWxldHRlID0gZ3JleS5jb2xvcnMoMTAwKSwgc3R5bGU9ICJjb250IiwgdGl0bGUgPSAiQmFja3NjYXR0ZXIgSW50ZW5zaXR5IChkQikiKSsNCiAgdG1fY29tcGFzcyh0eXBlID0gIjhzdGFyIiwgcG9zaXRpb24gPSBjKCJyaWdodCIsICJ0b3AiKSkrDQogIHRtX3NjYWxlX2JhcihicmVha3M9IGMoMCwgMi41LCA1KSwgdGV4dC5zaXplPTEpKw0KICB0bV9jcmVkaXRzKHRleHQgPSAiYikiLCBwb3NpdGlvbiA9IGMoImxlZnQiLCAiYm90dG9tIiksIHNpemUgPSAxKSsNCiAgdG1fZ3JhdGljdWxlcyhsaW5lcz1GQUxTRSkNCg0KdG1hcF9hcnJhbmdlKGJhdGh5X3Bsb3QsIGJhY2tzY2F0dGVyX3Bsb3QpDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCndyaXRlUmFzdGVyKHggPSBiYXRoeSwgZmlsZW5hbWUgPSAiRGF0YS9kZXJpdmVkL011bHRpYmVhbS9iYXRoeS50aWYiLCBvdmVyd3JpdGU9VFJVRSkNCndyaXRlUmFzdGVyKHggPSBiYXRoeSwgZmlsZW5hbWUgPSAiRGF0YS9kZXJpdmVkL011bHRpYmVhbS9iYXRoeS5ncmQiLCBvdmVyd3JpdGU9VFJVRSkNCmJhdGh5PC0gcmFzdGVyKCJEYXRhL2Rlcml2ZWQvTXVsdGliZWFtL2JhdGh5LmdyZCIpDQp3cml0ZVJhc3Rlcih4ID0gYmFja3NjYXR0ZXIsIGZpbGVuYW1lID0gIkRhdGEvZGVyaXZlZC9NdWx0aWJlYW0vYmFja3NjYXR0ZXIudGlmIiwgb3ZlcndyaXRlPVRSVUUpDQp3cml0ZVJhc3Rlcih4ID0gYmFja3NjYXR0ZXIsIGZpbGVuYW1lID0gIkRhdGEvZGVyaXZlZC9NdWx0aWJlYW0vYmFja3NjYXR0ZXIuZ3JkIiwgb3ZlcndyaXRlPVRSVUUpDQpiYWNrc2NhdHRlcjwtIHJhc3RlcigiRGF0YS9kZXJpdmVkL011bHRpYmVhbS9iYWNrc2NhdHRlci5ncmQiKQ0KYGBgDQoNCiMgQ2FsY3VsYXRlIERlcml2YXRpdmUgRmVhdHVyZXMNCg0KIyMgRGV0ZXJtaW5lIHNjYWxlcyBvZiBhbmFseXNpcw0KVGhlIEZpYm9uYWNjaSBzZXF1ZW5jZSBpcyBhIGdvb2Qgd2F5IHRvIHN5c3RlbWF0aWNhbGx5IGNvdmVyIG11bHRpcGxlLXNjYWxlcyAoV2lsc29uLCAyMDA3KS4NCmBgYHtyfQ0KbXlfd2luZG93X3NpemVzPC0gMSsgKDIqZmliX3NlcSgxMClbLWMoMSwyKV0pDQpwcmludChteV93aW5kb3dfc2l6ZXMpDQpgYGANCldlIHdpbGwgZXZhbHVhdGUgcHJlZGljdG9ycyBhdCBgciBsZW5ndGgobXlfd2luZG93X3NpemVzKWAgZGlmZmVyZW50IHdpbmRvdyBzaXplcyBmcm9tIGByIG1pbihteV93aW5kb3dfc2l6ZXMpYHhgciBtaW4obXlfd2luZG93X3NpemVzKWAgdG8gYHIgbWF4KG15X3dpbmRvd19zaXplcylgeGByIG1heChteV93aW5kb3dfc2l6ZXMpYA0KDQojIyBCYXRoeW1ldHJpYyBEZXJpdmF0aXZlIEZlYXR1cmVzDQpDYWxjdWxhdGUgYmF0aHltZXRyaWMgZGVyaXZhdGl2ZXMgYXQgdmFyaW91cyBzY2FsZXMgb2YgYW5hbHlzaXMuIFRoaXMgaW5jbHVkZXMgdGhlIHNsb3BlLCBhc3BlY3QgKHNwbGl0IGludG8gTm9ydGhuZXNzIGFuZCBFYXN0bmVzcyksIFRvcG9ncmFwaGljIFBvc2l0aW9uIEluZGV4IChXaGV0aGVyIGFuIGFyZWEgaXMgYSBsb2NhbCBoaWdoIG9yIGxvdyksIG1lYW4gYmF0aHltZXRyeSwgYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBiYXRoeW1ldHJ5IChhIG1lYXN1cmUgb2YgcnVnb3NpdHkpLg0KDQpgYGB7ciByZXN1bHRzPSdoaWRlJ30NCnNsb3BlPC0gdGVycmFpbihiYXRoeSwgb3B0PSAic2xvcGUiLCB1bml0ID0gImRlZ3JlZXMiKQ0KbmFtZXMoc2xvcGUpPC0gInNsb3BlX25hdGl2ZSINCmFzcGVjdDwtIHRlcnJhaW4oYmF0aHksIG9wdCA9IGMoImFzcGVjdCIpLCB1bml0ID0gInJhZGlhbnMiKQ0KZWFzdG5lc3M8LSBzaW4oYXNwZWN0KQ0KbmFtZXMoZWFzdG5lc3MpPC0gImVhc3RuZXNzX25hdGl2ZSINCm5vcnRobmVzczwtIGNvcyhhc3BlY3QpDQpuYW1lcyhub3J0aG5lc3MpPC0gIm5vcnRobmVzc19uYXRpdmUiDQoNCmZvciAoaSBpbiBteV93aW5kb3dfc2l6ZXMpIHsNCiAgcHJpbnQoaSkNCiAgdzwtIG1hdHJpeChkYXRhID0gMSwgbnJvdyA9IGksIG5jb2wgPSBpKQ0KICANCiAgY3Vycl9zbG9wZTwtIGZvY2FsKHggPSBzbG9wZSRzbG9wZV9uYXRpdmUsIHcsIGZ1bj1tZWFuLCBuYS5ybT1UUlVFLCBwYWQ9VFJVRSkNCiAgbmFtZXMoY3Vycl9zbG9wZSk8LSBwYXN0ZTAoInNsb3BlXyIsYXMuY2hhcmFjdGVyKGkpLCJ4IiwgYXMuY2hhcmFjdGVyKGkpKQ0KICBzbG9wZTwtIGFkZExheWVyKHNsb3BlLCBjdXJyX3Nsb3BlKQ0KICANCiAgY3Vycl9lYXN0bmVzczwtIGZvY2FsKHggPSBlYXN0bmVzcyRlYXN0bmVzc19uYXRpdmUsIHcsIGZ1bj1tZWFuLCBuYS5ybT1UUlVFLCBwYWQ9VFJVRSkNCiAgbmFtZXMoY3Vycl9lYXN0bmVzcyk8LSBwYXN0ZTAoImVhc3RuZXNzXyIsYXMuY2hhcmFjdGVyKGkpLCJ4IiwgYXMuY2hhcmFjdGVyKGkpKQ0KICBlYXN0bmVzczwtIGFkZExheWVyKGVhc3RuZXNzLCBjdXJyX2Vhc3RuZXNzKQ0KICANCiAgY3Vycl9ub3J0aG5lc3M8LSBmb2NhbCh4ID0gbm9ydGhuZXNzJG5vcnRobmVzc19uYXRpdmUsIHcsIGZ1bj1tZWFuLCBuYS5ybT1UUlVFLCBwYWQ9VFJVRSkNCiAgbmFtZXMoY3Vycl9ub3J0aG5lc3MpPC0gcGFzdGUwKCJub3J0aG5lc3NfIixhcy5jaGFyYWN0ZXIoaSksIngiLCBhcy5jaGFyYWN0ZXIoaSkpDQogIG5vcnRobmVzczwtIGFkZExheWVyKG5vcnRobmVzcywgY3Vycl9ub3J0aG5lc3MpDQogIA0KICBjdXJyX3RwaTwtIFRQSShiYXRoeSwgZD1jKGksaSksIG5hLnJtPVRSVUUsIHBhZCA9IFRSVUUpDQogIG5hbWVzKGN1cnJfdHBpKTwtICBwYXN0ZTAoInRwaV8iLGFzLmNoYXJhY3RlcihpKSwieCIsIGFzLmNoYXJhY3RlcihpKSkNCiAgDQogIGN1cnJfQmF0aHlNZWFuPC0gZm9jYWwoeCA9IGJhdGh5LCB3LCBmdW49bWVhbiwgbmEucm09VFJVRSwgcGFkPVRSVUUpDQogIG5hbWVzKGN1cnJfQmF0aHlNZWFuKTwtICBwYXN0ZTAoIkJhdGh5TWVhbl8iLGFzLmNoYXJhY3RlcihpKSwieCIsIGFzLmNoYXJhY3RlcihpKSkNCiAgDQogIGN1cnJfQmF0aHlTRDwtIGZvY2FsKHggPSBiYXRoeSwgdywgZnVuPXNkLCBuYS5ybT1UUlVFLCBwYWQ9VFJVRSkNCiAgbmFtZXMoY3Vycl9CYXRoeVNEKTwtICBwYXN0ZTAoIkJhdGh5U0RfIixhcy5jaGFyYWN0ZXIoaSksIngiLCBhcy5jaGFyYWN0ZXIoaSkpDQoNCiAgaWYoaT09Myl7DQogICAgdHBpPC0gY3Vycl90cGkNCiAgICBCYXRoeU1lYW48LSBjdXJyX0JhdGh5TWVhbg0KICAgIEJhdGh5U0Q8LSBjdXJyX0JhdGh5U0QgDQogICAgfSBlbHNlew0KICAgICAgdHBpPC0gYWRkTGF5ZXIodHBpLCBjdXJyX3RwaSkNCiAgICAgIEJhdGh5TWVhbjwtIGFkZExheWVyKEJhdGh5TWVhbiwgY3Vycl9CYXRoeU1lYW4pDQogICAgICBCYXRoeVNEPC0gYWRkTGF5ZXIoQmF0aHlTRCwgY3Vycl9CYXRoeVNEKQ0KICAgIH0NCn0NCg0KYmF0aHlfZGVyaXY8LSBzdGFjayhCYXRoeU1lYW4sIEJhdGh5U0QsIHRwaSwgc2xvcGUsIGVhc3RuZXNzLCBub3J0aG5lc3MpDQpiYXRoeV9kZXJpdjwtIG1hc2soeCA9IGJhdGh5X2Rlcml2LCBFTF9zaHApICNUcmltIGJhY2sgZG93biBiL2MgdXNlZCBwYWQgYW5kIG5hLnJtDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCndyaXRlUmFzdGVyKGJhdGh5X2Rlcml2LCAiRGF0YS9kZXJpdmVkL011bHRpYmVhbS9iYXRoeV9kZXJpdi5ncmQiLCBvdmVyd3JpdGU9VFJVRSkNCnJtKHNsb3BlLCBhc3BlY3QsIGVhc3RuZXNzLCBub3J0aG5lc3MsIGN1cnJfc2xvcGUsIGN1cnJfZWFzdG5lc3MsIGN1cnJfbm9ydGhuZXNzLCBjdXJyX3RwaSwgY3Vycl9CYXRoeU1lYW4sIGN1cnJfQmF0aHlTRCwgdHBpLCBCYXRoeU1lYW4sIEJhdGh5U0QpDQpiYXRoeV9kZXJpdjwtIGJyaWNrKCJEYXRhL2Rlcml2ZWQvTXVsdGliZWFtL2JhdGh5X2Rlcml2LmdyZCIpDQpgYGANCg0KIyMgQmFja3NjYXR0ZXIgRGVyaXZhdGl2ZSBGZWF0dXJlcw0KQ2FsY3VsYXRlIGJhY2tzY2F0dGVyIGRlcml2YXRpdmVzIGF0IHZhcmlvdXMgc2NhbGVzIG9mIGFuYWx5c2lzLiBUaGlzIGluY2x1ZGVzIHRoZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgYmF0aHltZXRyeSBhcyB3ZWxsIGFzIHRleHR1cmUgbWV0cmljIGRlcml2ZWQgZnJvbSBhIEdyYXkgTGV2ZWwgQ28tb2NjdXJlbmNlIE1hdHJpeCAoR0xDTSkuIA0KDQpUaGUgbW9zdCBjb21tb24gdGV4dHVyZSBtZXRyaWNzIGZyb20gcmVtb3RlIHNlbnNpbmcgd2VyZSBkZXJpdmVkIHVzaW5nIHRoZSBmb3JtdWxhcyBmcm9tIChIYWxsLUJleWVyIDIwMTcpLiBSb3RhdGlvbmFsbHkgSW52YXJpYW50L0RpcmVjdGlvbmFsbHkgSXNvdHJvcGljIEhhcmlsaWNrIFRleHR1cmUgTWV0cmljcyB3ZXJlIGRlcml2ZWQgYnkgY2FsY3VsYXRpbmcgYSBzeW1ldHJpY2FsIEdMQ00gd2l0aCAzMiBncmF5IGxldmVscy4NClRoZSB0ZXh0dXJlIG1ldHJpY3MgY2FuIGJlIGJyb2tlbiBkb3duIGludG8gdGhyZWUgZ3JvdXBzOiBUaGUgY29udHJhc3QgZ3JvdXAgKGNvbnRyYXN0LCBkaXNzaW1pbGFyaXR5LCBhbmQgaG9tb2dlbmVpdHkpLCB0aGUgb3JkZXJsaW5lc3MgZ3JvdXAgKEFTTSBhbmQgRW50cm9weSksIGFuZCB0aGUgZGVzY3JpcHRpdmUgc3RhdGlzdGljcyBncm91cCAobWVhbiwgdmFyaWFuY2UsIGFuZCBjb3JyZWxhdGlvbjtIYWxsLUJleWVyLCAyMDE3KS4gQXQgc21hbGxlciB3aW5kb3cgc2l6ZXMsIHRoZSBjb3JyZWxhdGlvbiB0ZXh0dXJlIGNhbiBzb21ldGltZXMgYmUgdW5kZWZpbmVkICgwLzApIGxlYWRpbmcgdG8gaG9sZXMgaW4gdGhlIHJlc3VsdGluZyByYXN0ZXIgc3VyZmFjZXMsIHNvIGNvcnJlbGF0aW9uIGF0IDN4MywgNXg1LCBhbmQgN3g3IHdlcmUgcmVtb3ZlZCBmcm9tIHRoZSBhbmFseXNpcyB0byBwcmV2ZW50IHRoaXMuDQoNCmBgYHtyIGNhY2hjZT1UUlVFLCByZXN1bHRzPSdoaWRlJ30NCmJhY2tzY2F0dGVyX3F1YW50PC0gcXVhbnRpemVfcmFzdGVyKGJhY2tzY2F0dGVyLCBuX2xldmVscyA9IDMyLG1ldGhvZCA9ICJlcXVhbCBwcm9iIikNCmZvciAoaSBpbiBteV93aW5kb3dfc2l6ZXMpIHsNCiAgcHJpbnQoaSkNCiAgdzwtIG1hdHJpeChkYXRhID0gMSwgbnJvdyA9IGksIG5jb2wgPSBpKQ0KICANCiAgY3Vycl9ic19tZWFuPC0gZm9jYWwoYmFja3NjYXR0ZXIsIHcsIGZ1bj1tZWFuLCBuYS5ybT1UUlVFLCBwYWQ9VFJVRSkNCiAgbmFtZXMoY3Vycl9ic19tZWFuKTwtICJCYWNrc2NhdHRlck1lYW4iDQogIGN1cnJfYnNfc2Q8LSBmb2NhbChiYWNrc2NhdHRlciwgdywgZnVuPXNkLCBuYS5ybT1UUlVFLCBwYWQ9VFJVRSkgDQogIG5hbWVzKGN1cnJfYnNfc2QpPC0gIkJhY2tzY2F0dGVyU0QiDQogIA0KICBjdXJyX0JTZGVyaXY8LSBzdGFjayhjdXJyX2JzX21lYW4sIA0KICAgICAgICAgICAgICAgICAgICAgICBjdXJyX2JzX3NkLA0KICAgICAgICAgICAgICAgICAgICAgICBnbGNtX3RleHR1cmVzKGJhY2tzY2F0dGVyX3F1YW50LCB3PSBjKGksaSksIG5fbGV2ZWxzPTMyLCAgc2hpZnQgPSBsaXN0KGMoMSwgMCksIGMoMSwgMSksIGMoMCwgMSksIGMoLTEsIDEpKSwgbWV0cmljcyA9IGMoImdsY21fY29udHJhc3QiLCAiZ2xjbV9kaXNzaW1pbGFyaXR5IiwgImdsY21faG9tb2dlbmVpdHkiLCAiZ2xjbV9BU00iLA0KICAgICJnbGNtX2VudHJvcHkiLCAiZ2xjbV9tZWFuIiwgImdsY21fdmFyaWFuY2UiLCAiZ2xjbV9jb3JyZWxhdGlvbiIpLCBxdWFudGl6YXRpb249ICJub25lIiwgbmFfb3B0ID0gImNlbnRlciIsIHBhZCA9IFRSVUUpKQ0KICANCiAgbmFtZXMoY3Vycl9CU2Rlcml2KTwtIHBhc3RlMChuYW1lcyhjdXJyX0JTZGVyaXYpLCAiXyIsIGFzLmNoYXJhY3RlcihpKSwgIngiLCBhcy5jaGFyYWN0ZXIoaSkpDQogIA0KICBpZihpPT0zKXsNCiAgICBiYWNrc2NhdHRlcl9kZXJpdjwtIGN1cnJfQlNkZXJpdn0gZWxzZXsNCiAgICAgIGJhY2tzY2F0dGVyX2Rlcml2PC0gc3RhY2soYmFja3NjYXR0ZXJfZGVyaXYsIGN1cnJfQlNkZXJpdikNCiAgICAgIHJtKGN1cnJfQlNkZXJpdikNCiAgICB9DQp9DQpiYWNrc2NhdHRlcl9kZXJpdjwtIG1hc2soYmFja3NjYXR0ZXJfZGVyaXYsIEVMX3NocCkNCmJhY2tzY2F0dGVyX2Rlcml2PC0gZHJvcExheWVyKGJhY2tzY2F0dGVyX2Rlcml2LCB3aGljaChuYW1lcyhiYWNrc2NhdHRlcl9kZXJpdik9PSJnbGNtX2NvcnJlbGF0aW9uXzN4MyIpKQ0KYmFja3NjYXR0ZXJfZGVyaXY8LSBkcm9wTGF5ZXIoYmFja3NjYXR0ZXJfZGVyaXYsIHdoaWNoKG5hbWVzKGJhY2tzY2F0dGVyX2Rlcml2KT09ImdsY21fY29ycmVsYXRpb25fNXg1IikpDQpiYWNrc2NhdHRlcl9kZXJpdjwtIGRyb3BMYXllcihiYWNrc2NhdHRlcl9kZXJpdiwgd2hpY2gobmFtZXMoYmFja3NjYXR0ZXJfZGVyaXYpPT0iZ2xjbV9jb3JyZWxhdGlvbl83eDciKSkgI3JlbW92ZSB0aGVzZSBiL2MgaGF2ZSBOQSdzIHRoYXQgY3JlYXRlIGhvbGVzIGR1ZSB0byB6ZXJvIGluIGRlbm9taW5hdG9yDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCndyaXRlUmFzdGVyKGJhY2tzY2F0dGVyX2Rlcml2LCAiRGF0YS9kZXJpdmVkL011bHRpYmVhbS9iYWNrc2NhdHRlcl9kZXJpdi5ncmQiLCBvdmVyd3JpdGU9VFJVRSkNCnJtKGJhY2tzY2F0dGVyX3F1YW50LCBjdXJyX2JzX21lYW4sIGN1cnJfYnNfc2QpDQpiYWNrc2NhdHRlcl9kZXJpdjwtIGJyaWNrKCJEYXRhL2Rlcml2ZWQvTXVsdGliZWFtL2JhY2tzY2F0dGVyX2Rlcml2LmdyZCIpDQpgYGANCg0KIyBHZW9yZWZlcmVuY2UgR3JvdW5kLVRydXRoIERhdGENCg0KIyMgVHJhbnNlY3RzDQoNCmBgYHtyIGVjaG89RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQ0KVDE8LSBzcFRyYW5zZm9ybShyZWFkT0dSKCJEYXRhL2Rlcml2ZWQvc2hhcGVmaWxlcy9FTFQxX1NoaXB0cmFjay5zaHAiKSwgQ1JTb2JqID0gbWFrZV9jcnMoIlVUTSAxNk4iKSkNClQzPC0gc3BUcmFuc2Zvcm0ocmVhZE9HUigiRGF0YS9kZXJpdmVkL3NoYXBlZmlsZXMvRUxUM19TaGlwdHJhY2suc2hwIiksIENSU29iaiA9IG1ha2VfY3JzKCJVVE0gMTZOIikpDQpUNTwtIHNwVHJhbnNmb3JtKHJlYWRPR1IoIkRhdGEvZGVyaXZlZC9zaGFwZWZpbGVzL0VMVDVfU2hpcHRyYWNrLnNocCIpLCBDUlNvYmogPSBtYWtlX2NycygiVVRNIDE2TiIpKQ0KVDY8LSBzcFRyYW5zZm9ybShyZWFkT0dSKCJEYXRhL2Rlcml2ZWQvc2hhcGVmaWxlcy9FTFQ2X1NoaXB0cmFjay5zaHAiKSwgQ1JTb2JqID0gbWFrZV9jcnMoIlVUTSAxNk4iKSkNCmBgYA0KDQpTb2xpZCBsaW5lcyByZXByZXNlbnQgdHJhbnNlY3RzIGZvciB0cmFpbmluZyBkYXRhLCBhbmQgZGFzaGVkIGxpbmUgcmVwcmVzZW50cyB0aGUgdHJhbnNlY3Qgd2hlcmUgb2JzZXJ2YXRpb25zIHdlcmUgd2l0aGhlbGQgaW4gb3JkZXIgdG8gdGVzdCB0aGUgYWNjdXJhY3kgb2Ygc3Vic3RyYXRlIHByZWRpY3Rpb25zDQoNCkZpZ3VyZSBTMS4zDQoNCmBgYHtyIGVjaG89RkFMU0V9DQp0cmFuc2VjdF9wbG90PC0gdG1fc2hhcGUoYmF0aHksIHJhc3Rlci5kb3duc2FtcGxlID0gRkFMU0UpKw0KICB0bV9yYXN0ZXIocGFsZXR0ZSA9IHBhbDEsIHN0eWxlPSAiY29udCIsIHRpdGxlID0gIiIsIGxlZ2VuZC5zaG93ID0gRkFMU0UpKw0KICB0bV9zaGFwZShyYmluZChUMyxUNSxUNikpKw0KICB0bV9saW5lcygpKw0KICB0bV9zaGFwZShUMSkrDQogIHRtX2xpbmVzKGx0eT0iZGFzaGVkIikrDQogIHRtX2dyYXRpY3VsZXMobGluZXM9RkFMU0UpDQp0cmFuc2VjdF9wbG90DQpgYGANCg0KIyMgUmVhZCBpbiBWaWRlbyBIYWJpdGF0IE9ic2VydmF0aW9ucw0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KVDFfaGFiPC0gcmVhZF94bHN4KCJEYXRhL3Jhdy9DQkFTUy9oYWJpdGF0L1QxX0Q0X3F1aWNraGFiMi54bHN4IikNClQxX2hhYjwtIFQxX2hhYlt3aGljaChUMV9oYWIkQ29tbWVudHM9PSJCb3R0b20iKTpucm93KFQxX2hhYiksXQ0KDQpUM19oYWI8LSByZWFkX3hsc3goIkRhdGEvcmF3L0NCQVNTL2hhYml0YXQvVDNfRDFfcXVpY2toYWIyLnhsc3giKQ0KVDNfaGFiPC0gVDNfaGFiW3doaWNoKFQzX2hhYiRDb21tZW50cz09IkJvdHRvbSIpOm5yb3coVDNfaGFiKSxdDQoNClQ1X2hhYjwtIHJlYWRfeGxzeCgiRGF0YS9yYXcvQ0JBU1MvaGFiaXRhdC9UNV9EMTRfcXVpY2toYWIyLnhsc3giKQ0KVDVfaGFiPC0gVDVfaGFiW3doaWNoKFQ1X2hhYiRDb21tZW50cz09IkJvdHRvbSIpOm5yb3coVDVfaGFiKSxdDQoNClQ2X2hhYjwtIHJlYWRfeGxzeCgiRGF0YS9yYXcvQ0JBU1MvaGFiaXRhdC9UNl9EMTNfcXVpY2toYWIyLnhsc3giKQ0KVDZfaGFiPC0gVDZfaGFiW3doaWNoKFQ2X2hhYiRDb21tZW50cz09IkJvdHRvbSIpOm5yb3coVDZfaGFiKSxdDQoNCmhhYjwtIGJpbmRfcm93cyhUMV9oYWIsIFQzX2hhYiwgVDVfaGFiLCBUNl9oYWIpDQpybShUMV9oYWIsVDNfaGFiLFQ1X2hhYiwgVDZfaGFiKQ0KaGFiPC0gaGFiICU+JSBtdXRhdGUoU3Vic3RyYXRlPSBpZmVsc2UodGVzdCA9IGlzLm5hKEdlbyksIHllcyA9ICJTYW5kIiwgbm8gPSAiUm9jayIpKQ0KaGFiJFN1YnN0cmF0ZVtoYWIkR2VvPT0iTm9fVmlzIl08LSAiTm9fVmlzIg0KaGFiPC0gaGFiICU+JSBtdXRhdGUoUmVsaWVmPSBpZmVsc2UodGVzdCA9IGlzLm5hKEdlbyksIHllcyA9ICJOb25lIiwgbm8gPSBHZW8pKQ0KaGFiPC0gaGFiICU+JSBzZWxlY3QoVHJhbnNlY3QsIFZpZCwgU2VjLCBTdWJzdHJhdGUsIFJlbGllZikNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KaGFiDQpgYGANCg0KIyMgUmVhZCBpbiBUaW1lc3RhbXBzIGZvciBDYW1lcmEgSW1hZ2VzDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpmaWxlX2xpc3Q8LSBsaXN0LmZpbGVzKCJEYXRhL3Jhdy9DQkFTUy9jYW1lcmEiLCBmdWxsLm5hbWVzID0gVFJVRSkNCmZvciAoaSBpbiAxOmxlbmd0aChmaWxlX2xpc3QpKSB7DQogIGN1cnJfY2FtPC0gcmVhZF90c3YoZmlsZV9saXN0W2ldKQ0KICByZWM8LSBjdXJyX2NhbSAlPiUgDQogICAgbXV0YXRlKHJlY29yZGluZz1zdHJfZXh0cmFjdChzdHJpbmcgPSBmaWxlX3BhdGgsIHBhdHRlcm4gPSAiXFxkezh9LVxcZHs2fSIpKSAlPiUNCiAgICBncm91cF9ieShyZWNvcmRpbmcpICU+JQ0KICAgIHN1bW1hcmlzZShDT1VOVD1uKCkpICU+JQ0KICAgIHVuZ3JvdXAoKQ0KICAgIGNob3Nlbl9yZWNvcmRpbmc8LSByZWMkcmVjb3JkaW5nW3doaWNoLm1heChyZWMkQ09VTlQpXQ0KICAgIGN1cnJfY2FtPC0gY3Vycl9jYW0gJT4lIA0KICAgICAgZmlsdGVyKHN0cl9kZXRlY3Qoc3RyaW5nID0gZmlsZV9wYXRoLCBwYXR0ZXJuID0gY2hvc2VuX3JlY29yZGluZykpICU+JQ0KICAgICAgZmlsdGVyKHN0cl9kZXRlY3Qoc3RyaW5nID0gZmlsZV9wYXRoLCBwYXR0ZXJuID0gIlxcLmpwZyQiKSkNCiAgICBjdXJyX2NhbTwtIGN1cnJfY2FtICU+JSBtdXRhdGUoRnJhbWVfSUQ9IGFzLm51bWVyaWMoc3RyX2V4dHJhY3Qoc3RyX2V4dHJhY3Qoc3RyaW5nID0gZmlsZV9wYXRoLCBwYXR0ZXJuID0gIkdpZ0VHcmFiRXgtXFxkezd9XFwuanBnJCIpLCBwYXR0ZXJuID0gIlxcZHs3fSIpKSkNCiAgICBjdXJyX2NhbTwtIGN1cnJfY2FtICU+JSBtdXRhdGUoVHJhbnNlY3Q9c3RyX2V4dHJhY3Qoc3RyaW5nID0gZmlsZV9saXN0W2ldLCBwYXR0ZXJuID0gIlRcXGQiKSkNCiAgICBwcmludChjaGVja19qdW1ibGVkKGN1cnJfY2FtKT09RkFMU0UpDQogICAgaWYoaT09MSl7Y2FtPC0gY3Vycl9jYW19IGVsc2V7DQogICAgICBjYW08LSBjYW0gJT4lIGJpbmRfcm93cyhjdXJyX2NhbSl9DQp9ICNDbGVhbiBkYXRhIGJ5IHJlbW92aW5nIHNob3J0IHJlY29yZGluZ3Mgbm90IGluY2x1ZGVkIGluIG1vc2FpY2VkIHZpZGVvIGFuZCBmaWx0ZXJpbmcgZm9yIG9ubHkgaGVuIGltYWdlcyB3ZXJlIHdyaXR0ZW4NCmNhbTwtIGNhbSAlPiUgZ3JvdXBfYnkoVHJhbnNlY3QpICU+JSBtdXRhdGUoRnJhbWVfbnVtPSBGcmFtZV9JRC1taW4oRnJhbWVfSUQpKSAlPiUgdW5ncm91cCgpICNTb21ldGltZXMgZnJhbWUgZmlsZW5hbWVzIHdlcmUgbm90IHJlc2V0IGJhY2sgdG8gemVybywgc28gc3VidHJhY3QgbWluaW11bSBmcmFtZSBvZiBhIHRyYW5zZWN0IHNvIHRoYXQgeW91IGNhbiBhc3NvY2lhdGUgdmlkZW8gZnJhbWUgIyB3aXRoIGFuIGltYWdlIGZyYW1lICMNCmNhbTwtIGNhbSAlPiUgc2VsZWN0KHRpbWVzdGFtcCwgdV9zZWNvbmQsZmlsZV9wYXRoLCBUcmFuc2VjdCwgRnJhbWVfSUQsIEZyYW1lX251bSkNCndyaXRlX2NzdihjYW0sIHBhdGggPSAiRGF0YS9kZXJpdmVkL0NCQVNTL2NhbWVyYS5jc3YiKQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIGVjaG89VFJVRX0NCmNhbTwtIHJlYWRfY3N2KCJEYXRhL2Rlcml2ZWQvQ0JBU1MvY2FtZXJhLmNzdiIpDQpgYGANCmBgYHtyIGVjaG89RkFMU0V9DQpjYW0NCmBgYA0KDQojIyBSZWFkIGluIFBvc2l0aW9uIGFuZCBBbmNpbGxhcnkgRGF0YSBTdHJlYW1zDQoNCmBgYHtyIGluY2x1ZGU9VFJVRSwgbWVzc2FnZT1GQUxTRX0NCkh5cGFjazwtIHJlYWRfaHlwYWNrKGxpc3QuZmlsZXMoIkRhdGEvcmF3L0h5cGFjay8iLCBwYXR0ZXJuPSJcXC5SQVckIiwgZnVsbC5uYW1lcyA9IFRSVUUpKQ0KY2FibGVfb3V0PC0gcmVhZF90c3YoIkRhdGEvcmF3L3BheW91dC9wYXlvdXRfRmViJk9jdDIwMTYudHN2IiwgY29sX3R5cGVzID0gbGlzdCguZGVmYXVsdD1jb2xfZG91YmxlKCksIHRpbWVzdGFtcD1jb2xfZGF0ZXRpbWUoKSkpDQpMYXRfTG9uZzwtIGdldF9IeXBhY2tQb3MoSHlwYWNrKQ0KbmFtZXMoTGF0X0xvbmcpWzI6M108LSBjKCJTaGlwTG9uIiwgIlNoaXBMYXQiKQ0KU2hpcF9TcGVlZDwtIGdldF9IeXBhY2tTcGVlZChIeXBhY2spDQoNClQxX29uZUh6PC0gbWFrZV8xaHooYWx0X3BhdGggPSAiRGF0YS9yYXcvQ0JBU1Mvc2Vuc29ycy9UMV9ENC9hbHRpbWV0ZXJfcmVhZGluZ3MudHN2IiwgY29tcGFzc19wYXRoID0gIkRhdGEvcmF3L0NCQVNTL3NlbnNvcnMvVDFfRDQvY29tcGFzc19yZWFkaW5ncy50c3YiLCBjdGRfcGF0aCA9ICJEYXRhL3Jhdy9DQkFTUy9zZW5zb3JzL1QxX0Q0L2N0ZF9yZWRvX3NhbC50c3YiLCBMYXRfTG9uZyA9IExhdF9Mb25nLCBTaGlwX1NwZWVkID0gU2hpcF9TcGVlZCwgY2FibGVfb3V0ID0gY2FibGVfb3V0KQ0KDQpUM19vbmVIejwtIG1ha2VfMWh6KGFsdF9wYXRoID0gIkRhdGEvcmF3L0NCQVNTL3NlbnNvcnMvVDNfRDEvYWx0aW1ldGVyX3JlYWRpbmdzLnRzdiIsIGNvbXBhc3NfcGF0aCA9ICJEYXRhL3Jhdy9DQkFTUy9zZW5zb3JzL1QzX0QxL2NvbXBhc3NfcmVhZGluZ3MudHN2IiwgY3RkX3BhdGggPSAiRGF0YS9yYXcvQ0JBU1Mvc2Vuc29ycy9UM19EMS9jdGRfcmVkb19zYWwudHN2IiwgTGF0X0xvbmcgPSBMYXRfTG9uZywgU2hpcF9TcGVlZCA9IFNoaXBfU3BlZWQsIGNhYmxlX291dCA9IGNhYmxlX291dCkNCg0KVDVfb25lSHo8LSBtYWtlXzFoeihhbHRfcGF0aCA9ICJEYXRhL3Jhdy9DQkFTUy9zZW5zb3JzL1Q1X0QxNC9hbHRpbWV0ZXJfcmVhZGluZ3MudHN2IiwgY29tcGFzc19wYXRoID0gIkRhdGEvcmF3L0NCQVNTL3NlbnNvcnMvVDVfRDE0L2NvbXBhc3NfcmVhZGluZ3MudHN2IiwgY3RkX3BhdGggPSAiRGF0YS9yYXcvQ0JBU1Mvc2Vuc29ycy9UNV9EMTQvY3RkX3JlZG9fc2FsLnRzdiIsIExhdF9Mb25nID0gTGF0X0xvbmcsIFNoaXBfU3BlZWQgPSBTaGlwX1NwZWVkLCBjYWJsZV9vdXQgPSBjYWJsZV9vdXQpDQoNClQ2X29uZUh6PC0gbWFrZV8xaHooYWx0X3BhdGggPSAiRGF0YS9yYXcvQ0JBU1Mvc2Vuc29ycy9UNl9EMTMvYWx0aW1ldGVyX3JlYWRpbmdzLnRzdiIsIGNvbXBhc3NfcGF0aCA9ICJEYXRhL3Jhdy9DQkFTUy9zZW5zb3JzL1Q2X0QxMy9jb21wYXNzX3JlYWRpbmdzLnRzdiIsIGN0ZF9wYXRoID0gIkRhdGEvcmF3L0NCQVNTL3NlbnNvcnMvVDZfRDEzL2N0ZF9yZWRvX3NhbC50c3YiLCBMYXRfTG9uZyA9IExhdF9Mb25nLCBTaGlwX1NwZWVkID0gU2hpcF9TcGVlZCwgY2FibGVfb3V0ID0gY2FibGVfb3V0KQ0KDQpvbmVfaHo8LSBiaW5kX3Jvd3MobXV0YXRlKFQxX29uZUh6LCBUcmFuc2VjdD0iVDEiKSwNCiAgICAgICAgICAgICAgICBtdXRhdGUoVDNfb25lSHosIFRyYW5zZWN0PSJUMyIpLA0KICAgICAgICAgICAgICAgIG11dGF0ZShUNV9vbmVIeiwgVHJhbnNlY3Q9IlQ1IiksDQogICAgICAgICAgICAgICAgbXV0YXRlKFQ2X29uZUh6LCBUcmFuc2VjdD0iVDYiKSkNCm9uZV9oeg0KYGBgDQoNCiMjIEVzdGltYXRlIEMtQkFTUyBQb3NpdGlvbg0KDQpDQkFTUyBQb3NpdGlvbiBpcyBlc3RpbWF0ZWQgdXNpbmcgUHl0aGFnb3JlYW4gdGhlb3JlbSB1c2luZyB0aGUgY2FibGUgb3V0ICh0aGUgaHlwb3RlbnVzZSkgYW5kIENCQVNTIGRlcHRoICh0aGUgaGVpZ2h0IG9mIHRoZSB0cmlhbmdsZSkuIFRoZSBjYWJsZSBvdXQgaXMgemVyb2VkIHdoZW4gdGhlIHRoZSBDQkFTUyBoaXRzIHRoZSB3YXRlciBzbyB0byBnZXQgdHJ1ZSBjYWJsZSBvdXQgZnJvbSB0aGUgdHJhd2wgYmxvY2ssIGFuZCB0aGUgdHJ1ZSBoZWlnaHQgb2YgdGhpcyB0cmlhbmdsZSwgdGhlIGhlaWdodCBvZiB0aGUgdHJhd2wgYmxvY2sgYWJvdmUgdGhlIHdhdGVyIChcfjYuMSBtKSBpcyBhZGRlZCB0byB0aGUgcmVjb3JkZWQgY2FibGUgb3V0IGFuZCBDQkFTUyBEZXB0aC4gVGhlIGxheWJhY2sgYmVoaW5kIHRoZSBibG9jayBpcyB0aGVuIGNhbGN1bGF0ZWQgdXNpbmcgcHl0aGFnb3JlYW4gdGhlb3J1bS4gVGhlIHkgb2Zmc2V0IChmb3JlL2FmdCBkaXN0YW5jZTsgXH4yNC40IG0pIGJldHdlZW4gdGhlIHRyYXdsIGJsb2NrIGFuZCB0aGUgR1BTIGFudGVubmEgaXMgdGhlbiBhZGRlZCB0byB0aGlzIGxheWJhY2sgdG8gZ2V0IHRoZSBsYXliYWNrIG9mIHRoZSBDQkFTUyBzeXN0ZW0gYmVoaW5kIHRoZSBsb2dnZWQgR1BTIHNoaXAgcG9zaXRpb24uIENCQVNTIGlzIGFzc3VtZWQgdG8gZm9sbG93IHRoZSBzaGlwIHRyYWNrIGJ1dCB3aXRoIGEgdGltZSBkZWxheS4gVGhlIGxheWJhY2sgZGlzdGFuY2UgaXMgY29udmVydGVkIHRvIGEgdGltZSBkZWxheSBieSBkaXZpZGluZyB0aGUgbGF5YmFjayBkaXN0YW5jZSBieSB0aGUgYXZlcmFnZSBzaGlwIHNwZWVkIG92ZXIgdGhlIHBhc3QgbWludXRlLiBUbyBnZXQgdGhlIENCQVNTIHBvc2l0aW9uIGZvciBhIGdpdmVuIHRpbWUsIHRoZSB0aGUgc2hpcCBwb3NpdGlvbiBmcm9tICJ4IiBudW1iZXIgb2Ygc2Vjb25kcyBhZ28gKHRoZSB0aW1lIGRlbGF5KSBpcyBncmFiYmVkIGZyb20gdGhlIHRhYmxlIGFuZCBhc3NpZ25lZCBhcyB0aGUgY3VycmVudCBDQkFTUyBwb3NpdGlvbi4gRm9yIG1vcmUgaW5mb3JtYXRpb24gc2VlIHRoZSBkb2N1bWVudGF0aW9uIGFuZCBzb3VyY2UgY29kZSBmb3IgbXl0b29sczo6Y2FsY1xfbGF5YmFjayAoYXJndW1lbnRzIHVzZWQgR1BTXF9Tb3VyY2U9Ik5vdGhzdGFyIiwgemVyb2VkPSJ3YXRlciIsIGNhdFxfZmFjdD0xKS4NCg0KYGBge3Igd2FybmluZz1GQUxTRX0NCm9uZV9oejwtIG9uZV9oeiAlPiUgbXV0YXRlKExheWJhY2tfbT0gY2FsY19sYXliYWNrKHBheW91dCA9IHBheW91dCwgZGVwdGggPSBkZXB0aCwgR1BTX1NvdXJjZSA9ICJOb3J0aHN0YXIiLCB6ZXJvZWQgPSAid2F0ZXIiLCBjYXRfZmFjdCA9IDEpKQ0Kb25lX2h6PC0gb25lX2h6ICU+JSBtdXRhdGUoTGF5YmFja19zZWM9IHJvdW5kKExheWJhY2tfbS9TaGlwX1NwZWVkX21wc18xbWluQXZnKSkNCm9uZV9oejwtIG9uZV9oeiAlPiUgbXV0YXRlKFRpbWVUb01hdGNoPXRpbWVzdGFtcC1kc2Vjb25kcyhMYXliYWNrX3NlYykpDQp0ZW1wX29uZV9oejwtIG9uZV9oeiAlPiUgc2VsZWN0KHRpbWVzdGFtcCwgVHJhbnNlY3QsIFNoaXBMb24sIFNoaXBMYXQpDQpuYW1lcyh0ZW1wX29uZV9oeik8LSBjKCJUaW1lVG9NYXRjaCIsICJUcmFuc2VjdCIsICJDQkFTU0xvbiIsICJDQkFTU0xhdCIpDQpvbmVfaHo8LSBvbmVfaHogJT4lIGxlZnRfam9pbih0ZW1wX29uZV9oeiwgYnk9YygiVGltZVRvTWF0Y2giLCJUcmFuc2VjdCIpKSAlPiUgc2VsZWN0KC1UaW1lVG9NYXRjaCkNCnJtKHRlbXBfb25lX2h6KQ0Kb25lX2h6DQp3cml0ZV9jc3Yob25lX2h6LCAiRGF0YS9kZXJpdmVkL0NCQVNTL29uZWh6LmNzdiIpDQpgYGANCg0KIyMgR2VvcmVmZXJlbmNlIFZpZGVvIEhhYml0YXQgT2JzZXJ2YXRpb25zDQoNCkNhbGN1bGF0ZSBGcmFtZSBudW1iZXIuIFZpZGVvcyBhcmUgMSBtaW51dGUgbG9uZyBhdCAxMiBmcmFtZXMgcGVyIHNlY29uZC4NCg0KYGBge3J9DQpoYWI8LSBoYWIgJT4lIG11dGF0ZShGcmFtZV9udW09IChWaWQgKiAxMiAqIDYwKSArIFNlYyoxMikNCmBgYA0KDQpHZXQgdGltZXN0YW1wIGZvciBlYWNoIGZyYW1lIHRvIG5lYXJlc3Qgc2Vjb25kDQoNCmBgYHtyfQ0KaGFiPC0gaGFiICU+JSBsZWZ0X2pvaW4oc2VsZWN0KGNhbSwgdGltZXN0YW1wLCB1X3NlY29uZCwgRnJhbWVfbnVtLCBUcmFuc2VjdCksIGJ5PSBjKCJUcmFuc2VjdCIsICJGcmFtZV9udW0iKSkNCmhhYjwtIGhhYiAlPiUgbXV0YXRlKHRpbWVzdGFtcD1yb3VuZF9kYXRlKHRpbWVzdGFtcCArIGRtaWNyb3NlY29uZHModV9zZWNvbmQpLCB1bml0ID0gInNlY29uZCIpKSAlPiUgc2VsZWN0KC11X3NlY29uZCkNCmBgYA0KDQpMaW5rIHRvIHBvc2l0aW9uIGJ5IHRpbWVzdGFtcA0KDQpgYGB7ciBpbmNsdWRlPVRSVUV9DQpoYWI8LSBoYWIgJT4lIGxlZnRfam9pbihzZWxlY3Qob25lX2h6LCB0aW1lc3RhbXAsIFRyYW5zZWN0LCBDQkFTU0xhdCwgQ0JBU1NMb24pLCBieT1jKCJ0aW1lc3RhbXAiLCAiVHJhbnNlY3QiKSkNCmBgYA0KYGBge3IgZWNobz1UUlVFfQ0KaGFiDQpgYGANCmBgYHtyfQ0Kd3JpdGVfY3N2KGhhYiwgcGF0aCA9ICJEYXRhL2Rlcml2ZWQvQ0JBU1MvaGFiLmNzdiIpDQpgYGANCg0KIyMgUHJlcGFyZSB0cmFpbmluZyBhbmQgdmFsaWRhdGlvbiBzZXQNCg0KT25seSBpbmNsdWRlIGhhYml0YXRzIHRoYXQgd2VyZSB0aGUgc2FtZSBhcyB0aGVpciBwcmV2aW91cyBhbmQgc3Vic2VxdWVudCBvYnNlcnZhdGlvbnMgdG8gcmVtb3ZlIHRyYW5zaXRpb25hbC9taXhlZCBhcmVhcyB0byBjcmVhdGUgc2V0IHVzZWQgZm9yIHRyYWluaW5nIGFuZCB2YWxpZGF0aW9uLg0KDQpgYGB7cn0NClRWX3NldDwtIGhhYiAlPiUgZ3JvdXBfYnkoVHJhbnNlY3QpICU+JSBjb25zdF9oYWIoIlN1YnN0cmF0ZSIpICU+JSB1bmdyb3VwKCkNCnByaW50KHVuaXF1ZShUVl9zZXQkU3Vic3RyYXRlKSkNClRWX3NldDwtIFRWX3NldCAlPiUgZmlsdGVyKFN1YnN0cmF0ZSE9Ik5vX1ZpcyIpICNSZW1vdmUgYmFkIHZpc2liaWxpdHkNClRWX3NldCRTdWJzdHJhdGU8LSBmYWN0b3IoVFZfc2V0JFN1YnN0cmF0ZSwgbGV2ZWxzID0gYygiUm9jayIsICJTYW5kIikpDQpUVl9zZXQ8LSBUVl9zZXQgJT4lIG11dGF0ZShTZXQ9aWZlbHNlKHRlc3QgPSBUcmFuc2VjdD09IlQxIiwgeWVzID0gIlZhbGlkYXRpb24iLCBubyA9ICJUcmFpbmluZyIpKSAjUmVzZXJ2ZSBUMSBmb3IgdmFsaWRhdGlvbiBvZiByZXN1bHRzLiBVc2Ugb3RoZXIgdHJhbnNlY3RzIGZvciB0cmFpbmluZyBkYXRhDQpgYGANCg0KIyMjIENyZWF0ZSBTcGF0aWFsIE9iamVjdA0KDQpgYGB7cn0NClRWX3NldDwtIFRWX3NldCAlPiUgZmlsdGVyKCFpcy5uYShDQkFTU0xhdCkpICNSZW1vdmUgd2hlcmUgdGhlcmUgaXMgbm8gcG9zaXRpb25pbmcgZGF0YQ0KVFZfc2V0PC0gc3BUcmFuc2Zvcm0oU3BhdGlhbFBvaW50c0RhdGFGcmFtZShjb29yZHMgPSBjYmluZChUVl9zZXQkQ0JBU1NMb24sIFRWX3NldCRDQkFTU0xhdCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBhcy5kYXRhLmZyYW1lKHNlbGVjdChUVl9zZXQsIC1jKENCQVNTTG9uLCBDQkFTU0xhdCkpKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2o0c3RyaW5nID0gbWFrZV9jcnMoIldHUzg0IikpLCBDUlNvYmogPSBtYWtlX2NycygiVVRNIDE2TiIpKQ0KVFZfc2V0PC0gVFZfc2V0W0VMX3NocCxdICNSZW1vdmUgcG9pbnRzIG91dHNpZGUgYmV5b25kIGJvdW5kcyBvZiB0aGUgc3R1ZHkgYXJlYQ0KYGBgDQoNClRoZSBncm91bmQtdHJ1dGggZGF0YXNldCBjb25zaXN0ZWQgb2YgYHIgbnJvdyhoYWIpYCBvYnNlcnZhdGlvbnMsIHdoZXJlIGVhY2ggb2JzZXJ2YXRpb24gd2FzIHRoZSBzdWJzdHJhdGUgY2xhc3NpZmljYXRpb24gZGV0ZXJtaW5lZCBmcm9tIHRoZSB2aWRlbyBhdCAxNSBzZWNvbmQgaW50ZXJ2YWxzLiBUaGlzIGNvbnNpc3RlZCBvZiBgciBzdW0oaGFiJFN1YnN0cmF0ZT09IlJvY2siKWAgb2JzZXJ2YXRpb25zIG9mIHJvY2ssIGByIHN1bShoYWIkU3Vic3RyYXRlPT0iU2FuZCIpYCBvYnNlcnZhdGlvbnMgb2Ygc2FuZCwgYW5kIGByIHN1bShoYWIkU3Vic3RyYXRlPT0iTm9fVmlzIilgIG9ic2VydmF0aW9ucyB3aGVyZSBzdWJzdHJhdGUgd2FzIG5vdCBkaXNjZXJuaWJsZS4gQWZ0ZXIgY2Vuc29yaW5nIHN1YnN0cmF0ZSBkZXRlcm1pbmF0aW9ucyB0aGF0IGRpZmZlcmVkIGZyb20gdGhlaXIgcHJldmlvdXMgYW5kIHN1YnNlcXVlbnQgb2JzZXJ2YXRpb25zLCB0aG9zZSB3aGVyZSBzdWJzdHJhdGUgd2FzIG5vdCB2aXNpYmxlLCBhbmQgb2JzZXJ2YXRpb25zIGJleW9uZCB0aGUgYm91bmRzIG9mIHRoZSBtdWx0aWJlYW0gc3VydmV5IG9yIGRpZCBub3QgaGF2ZSBhc3NvY2lhdGVkIHBvc2l0aW9uaW5nIGRhdGEsIHRoZXJlIHdlcmUgYHIgVFZfc2V0ICU+JSBmaWx0ZXIoU3Vic3RyYXRlPT0iUm9jayIpICU+JSBucm93KClgIG9ic2VydmF0aW9ucyBvZiByb2NrIGFuZCBgciBUVl9zZXQgJT4lIGZpbHRlcihTdWJzdHJhdGU9PSJTYW5kIikgJT4lIG5yb3coKWAgb2JzZXJ2YXRpb25zIG9mIHNhbmQuIFRoZXNlIGRhdGEgd2VyZSB0aGVuIHNwbGl0IGludG8gdHJhaW5pbmcgYW5kIHZhbGlkYXRpb24gc2V0cy4gVGhlIHRyYWluaW5nIGRhdGEgc2V0IGNvbnNpc3RlZCBvZiBgciBUVl9zZXQgJT4lIGZpbHRlcihTZXQ9PSJUcmFpbmluZyIgJiBTdWJzdHJhdGU9PSJSb2NrIikgJT4lIG5yb3coKWBvYnNlcnZhdGlvbnMgb2Ygcm9jayBhbmQgYHIgVFZfc2V0ICU+JSBmaWx0ZXIoU2V0PT0iVHJhaW5pbmciICYgU3Vic3RyYXRlPT0iU2FuZCIpICU+JSBucm93KClgIG9ic2VydmF0aW9ucyBvZiBzYW5kLiBUaGUgdmFsaWRhdGlvbiB0cmFuc2VjdCBjb25zaXN0ZWQgb2YgYHIgVFZfc2V0ICU+JSBmaWx0ZXIoU2V0PT0iVmFsaWRhdGlvbiIgJiBTdWJzdHJhdGU9PSJSb2NrIikgJT4lIG5yb3coKWAgb2JzZXJ2YXRpb25zIG9mIHJvY2sgYW5kIGByIFRWX3NldCAlPiUgZmlsdGVyKFNldD09IlZhbGlkYXRpb24iICYgU3Vic3RyYXRlPT0iU2FuZCIpICU+JSBucm93KClgIG9ic2VydmF0aW9ucyBvZiBzYW5kLg0KDQpGaWd1cmUgUzEuNA0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KdHJhaW5pbmdfcGxvdDwtIHRtX3NoYXBlKEVMX3NocCkgKw0KICB0bV9wb2x5Z29ucyh0aXRsZSA9ICJUcmFpbmluZyIsIGNvbCA9ICJjYWRldGJsdWUxIiwgbGVnZW5kLnNob3cgPSBGQUxTRSkrDQp0bV9zaGFwZShmaWx0ZXIoVFZfc2V0LCBTZXQ9PSJUcmFpbmluZyIpKSsNCiAgdG1fZG90cyhjb2w9IlN1YnN0cmF0ZSIsIHBhbGV0dGU9YygicmVkIiwgIiNGRkVCQkUiKSwgbGVnZW5kLnNob3cgPSBUUlVFKSsNCiAgdG1fbGF5b3V0KGxlZ2VuZC5iZy5jb2xvciA9ICJncmF5IikrDQogICAgdG1fY3JlZGl0cyh0ZXh0ID0gImEpIiwgcG9zaXRpb24gPSBjKCJyaWdodCIsICJib3R0b20iKSwgc2l6ZSA9IDEpKw0KICAgdG1fZ3JhdGljdWxlcyhsaW5lcz1GQUxTRSkrDQogICAgdG1fbGF5b3V0KG1haW4udGl0bGUgPSAiVHJhaW5pbmciLCBtYWluLnRpdGxlLnBvc2l0aW9uID0gLjQzKSANCg0KdmFsaWRhdGlvbl9wbG90PC0gdG1fc2hhcGUoRUxfc2hwKSArDQogIHRtX3BvbHlnb25zKHRpdGxlID0gIlZhbGlkYXRpb24iLCBjb2wgPSAiY2FkZXRibHVlMSIsIGxlZ2VuZC5zaG93ID0gRkFMU0UpKw0KICB0bV9zaGFwZShmaWx0ZXIoVFZfc2V0LCBTZXQ9PSJWYWxpZGF0aW9uIikpKw0KICB0bV9kb3RzKGNvbD0iU3Vic3RyYXRlIiwgcGFsZXR0ZT1jKCJyZWQiLCAiI0ZGRUJCRSIpLCBsZWdlbmQuc2hvdyA9IEZBTFNFKSsNCiAgdG1fY3JlZGl0cyh0ZXh0ID0gImIpIiwgcG9zaXRpb24gPSBjKCJyaWdodCIsICJib3R0b20iKSwgc2l6ZSA9IDEpKw0KICAgdG1fZ3JhdGljdWxlcyhsaW5lcz1GQUxTRSkrDQogICAgdG1fbGF5b3V0KG1haW4udGl0bGUgPSAiVmFsaWRhdGlvbiIsIG1haW4udGl0bGUucG9zaXRpb24gPSAuMzkpIA0KDQoNCmd0cnV0aF9wbG90PC0gdG1hcF9hcnJhbmdlKHRyYWluaW5nX3Bsb3QsIHZhbGlkYXRpb25fcGxvdCkNCmd0cnV0aF9wbG90DQpgYGANCg0KYGBge3J9DQpoYWJfb25laHpfam9pbmVkPC0gaGFiICU+JSBsZWZ0X2pvaW4ob25lX2h6KQ0KYGBgDQogDQpUcmFuc2VjdHMgdG90YWwgdG8gYHIgaGFiX29uZWh6X2pvaW5lZCAlPiUgZ3JvdXBfYnkoVHJhbnNlY3QpICU+JSBzdW1tYXJpemUoc3RfdGltZT1taW4odGltZXN0YW1wLCBuYS5ybT1UUlVFKSwgZW5kX3RpbWU9bWF4KHRpbWVzdGFtcCwgbmEucm09VFJVRSksIGF2Z19zcGVlZF9tcHM9IG1lYW4oU2hpcF9TcGVlZF9tcHMsIG5hLnJtPVRSVUUpLCAuZ3JvdXBzPSJkcm9wIikgJT4lIG11dGF0ZSh0cmFuc2VjdF9kdXJhdGlvbj1hcy5udW1lcmljKGRpZmZ0aW1lKGVuZF90aW1lLCBzdF90aW1lLCB1bml0cyA9ICJzZWNzIikpKSAlPiUgbXV0YXRlKHRyYW5zZWN0X2xlbnRoX2ttPSAodHJhbnNlY3RfZHVyYXRpb24qYXZnX3NwZWVkX21wcykvMTAwMCkgJT4lIHB1bGwodHJhbnNlY3RfbGVudGhfa20pICU+JSBzdW0oKSAlPiUgcm91bmQoKWAga20gaW4gbGVuZ3RoDQoNCg0KIyBQcmVkaWN0aXZlIEhhYml0YXQgTWFwcGluZw0KDQpgYGB7cn0NCnByZWRpY3Rvcl92YXJzPC0gc3RhY2soYmF0aHksIGJhdGh5X2Rlcml2LCBiYWNrc2NhdHRlciwgYmFja3NjYXR0ZXJfZGVyaXYpDQpuX3ByZWRpY3RvcnM8LW5sYXllcnMocHJlZGljdG9yX3ZhcnMpDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCndyaXRlUmFzdGVyKHByZWRpY3Rvcl92YXJzLCAiRGF0YS9kZXJpdmVkL011bHRpYmVhbS9wcmVkaWN0b3JfdmFycy5ncmQiLG92ZXJ3cml0ZT1UUlVFKQ0KcHJlZGljdG9yX3ZhcnM8LSBicmljaygiRGF0YS9kZXJpdmVkL011bHRpYmVhbS9wcmVkaWN0b3JfdmFycy5ncmQiKQ0KYGBgDQoNCiMjIFN1cGVydmlzZWQgQ2xhc3NpZmljYXRpb24gKFJhbmRvbSBGb3Jlc3QpDQoNCiMjIyBWYXJpYWJsZSBTZWxlY3Rpb24NClRoZXJlIGFyZSBgciBuX3ByZWRpY3RvcnNgIHByZWRpY3RvciB2YXJpYWJsZXMgaW4gdG90YWwuIFRvIGRlY2lkZSBvbiB3aGljaCB2YXJpYWJsZXMgdG8gcmV0YWluIGluIHRoZSBmaW5hbCBtb2RlbCwgd2UgZmlyc3QgdXNlIHRoZSBCb3J1dGEgZmVhdHVyZSBzZWxlY3Rpb24gYWxnb3JpdGhtLCB3aGljaCB0aHJvdWdoIGFuIGl0ZXJhdGl2ZSBwcm9jZWR1cmUgZGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBpbXBvcnRhbmNlIG9mIGEgcHJlZGljdG9yIGlzIHNpZ25pZmljYW50bHkgZ3JlYXRlciAocF9ib25mZXJyb25pIDwgMC4wNSkgdGhhbiB6ZXJvLiBBbnkgcHJlZGljdG9ycyB0aGF0IGRvIG5vdCBoYXZlIGFuIGltcG9ydGFuY2Ugc2lnbmlmaWNhbnRseSBncmVhdGVyIHRoYW4gemVybyBhcmUgcmVtb3ZlZCBmcm9tIHRoZSBtb2RlbC4gV2UgdGhlbiByZWR1Y2UgY28tbGluZWFyaXR5IGFtb25nIHByZWRpY3RvcnMgYW5kIHJlbW92ZSByZWR1bmRhbnQgdmFyaWFibGVzIGJ5IGVsaW1pbmF0aW5nIGFueSBwcmVkaWN0b3IgaWYgaXQgaXMgaGlnaGx5IGNvcnJlbGF0ZWQgKHxyfCA+IDAuOCkgd2l0aCBhbnkgdmFyaWFibGUgdGhhdCBoYWQgYSBoaWdoZXIgdmFyaWFibGUgaW1wb3J0YW5jZSBzY29yZS4NCg0KYGBge3IgfQ0KZGF0YV9kZjwtIHJhc3Rlcjo6ZXh0cmFjdCh4ID0gcHJlZGljdG9yX3ZhcnMsIHkgPSBmaWx0ZXIoVFZfc2V0LCBTZXQ9PSJUcmFpbmluZyIpLCBtZXRob2Q9InNpbXBsZSIsIGZhY3RvcnM9VFJVRSwgc3A9VFJVRSlAZGF0YQ0KZGF0YV9kZiRTdWJzdHJhdGU8LSBmYWN0b3IoZGF0YV9kZiRTdWJzdHJhdGUsIGxldmVscz1jKCJSb2NrIiwgIlNhbmQiKSkNCnNhbXBsZV9mcmFjdGlvbjwtIGRhdGFfZGYgJT4lIGNvdW50KFN1YnN0cmF0ZSkgJT4lIG11dGF0ZShwcm9wPW4vc3VtKG4pKSAlPiUgcHVsbChwcm9wKSAlPiUgbWluKCkgI0Rvd25zYW1wbGUgdG8gbWlub3JpdHkgY2xhc3MNCmRhdGFfZGY8LSBkYXRhX2RmICU+JSBzZWxlY3QoLWMoVHJhbnNlY3QsIFZpZCwgU2VjLCB0aW1lc3RhbXAsIFJlbGllZiwgRnJhbWVfbnVtLCBTZXQpKSAlPiUgbmEub21pdCgpIA0KDQpzZXQuc2VlZCg0KQ0KQm9ydXRhX29iajwtIEJvcnV0YShTdWJzdHJhdGUgfiAuICwgZGF0YT1kYXRhX2RmLCBwVmFsdWUgPSAuMDUsIG1jQWRqID0gVFJVRSwgbWF4UnVucyA9IDUwMDAsIGdldEltcD0gZ2V0SW1wUmZSYXcsIHNhbXBsZS5mcmFjdGlvbj1jKHNhbXBsZV9mcmFjdGlvbixzYW1wbGVfZnJhY3Rpb24pKQ0KQm9ydXRhX29iajwtIFRlbnRhdGl2ZVJvdWdoRml4KHggPSBCb3J1dGFfb2JqKQ0KUHJlZGljdG9yX0RlY2lzaW9uczwtZGF0YS5mcmFtZShEZWNpc2lvbiA9IEJvcnV0YV9vYmpbWyJmaW5hbERlY2lzaW9uIl1dKQ0KUHJlZGljdG9yX0RlY2lzaW9uczwtIFByZWRpY3Rvcl9EZWNpc2lvbnMgJT4lIG11dGF0ZShWYXJpYWJsZT0gcm93bmFtZXMoUHJlZGljdG9yX0RlY2lzaW9ucykpICU+JSBzZWxlY3QoVmFyaWFibGUsIERlY2lzaW9uKQ0KQm9ydXRhX0ltcDwtIGFzLmRhdGEuZnJhbWUoQm9ydXRhX29ialtbIkltcEhpc3RvcnkiXV0pICU+JSBzdW1tYXJpemUoYWNyb3NzKGV2ZXJ5dGhpbmcoKSwgLmZucz1tZWFuKSkgJT4lIHBpdm90X2xvbmdlcihjb2xzID0gZXZlcnl0aGluZygpLCBuYW1lc190byA9ICJWYXJpYWJsZSIsIHZhbHVlc190bz0gIkltcG9ydGFuY2UiKQ0Kc3VwX3JldGFpbmVkX3ByZWRpY3RvcnNfZGY8LSBQcmVkaWN0b3JfRGVjaXNpb25zICU+JSBmaWx0ZXIoRGVjaXNpb249PSJDb25maXJtZWQiKSAlPiUgbGVmdF9qb2luKEJvcnV0YV9JbXAsIGJ5PSJWYXJpYWJsZSIpICU+JSBhcnJhbmdlKGRlc2MoSW1wb3J0YW5jZSkpDQoNCnN1cF9yZXRhaW5lZF9wcmVkaWN0b3JzPC0gcHJlZGljdG9yX3ZhcnNbW3doaWNoKG5hbWVzKHByZWRpY3Rvcl92YXJzKSAlaW4lIHN1cF9yZXRhaW5lZF9wcmVkaWN0b3JzX2RmJFZhcmlhYmxlKV1dDQpjb3JyX3ZhbHM8LSBsYXllclN0YXRzKHN1cF9yZXRhaW5lZF9wcmVkaWN0b3JzLCAncGVhcnNvbicsIG5hLnJtPVRSVUUpDQpjb3JyX3ZhbHM8LSBhcy5kYXRhLmZyYW1lKGNvcnJfdmFscyRgcGVhcnNvbiBjb3JyZWxhdGlvbiBjb2VmZmljaWVudGApICU+JSBtdXRhdGUoVjE9cm93Lm5hbWVzKGNvcnJfdmFscyRgcGVhcnNvbiBjb3JyZWxhdGlvbiBjb2VmZmljaWVudGApKQ0KY29ycl92YWxzPC0gY29ycl92YWxzICU+JSBwaXZvdF9sb25nZXIoY29scz0gLVYxLCBuYW1lc190byA9ICJWMiIsIHZhbHVlc190bz0iY29ycmVsYXRpb24iKQ0KY29ycl92YWxzPC0gY29ycl92YWxzICU+JSBmaWx0ZXIoVjEhPVYyKQ0Kc3VwX3JldGFpbmVkX3ByZWRpY3RvcnNfZGY8LSBzdXBfcmV0YWluZWRfcHJlZGljdG9yc19kZiAlPiUgbXV0YXRlKEtlZXA9VFJVRSkNCmZvciAoaSBpbiBucm93KHN1cF9yZXRhaW5lZF9wcmVkaWN0b3JzX2RmKToyKSB7DQogIGN1cnJfdmFyPC0gc3VwX3JldGFpbmVkX3ByZWRpY3RvcnNfZGYkVmFyaWFibGVbaV0NCiAgbW9yZV9pbXBvcnRhbnRfcHJlZGljdG9yczwtIHN1cF9yZXRhaW5lZF9wcmVkaWN0b3JzX2RmWzE6KGktMSksICJWYXJpYWJsZSJdDQogIG1heF9jb3JyPC0gY29ycl92YWxzICU+JSBmaWx0ZXIoKFYxPT1jdXJyX3ZhcikgJiAoVjIgJWluJSBtb3JlX2ltcG9ydGFudF9wcmVkaWN0b3JzKSkgJT4lIHB1bGwoY29ycmVsYXRpb24pICU+JSBhYnMoKSAlPiUgbWF4KCkNCiAgaWYobWF4X2NvcnIgPiAwLjgpe3N1cF9yZXRhaW5lZF9wcmVkaWN0b3JzX2RmJEtlZXBbaV08LSBGQUxTRX0NCiAgfQ0Kc3VwX3JldGFpbmVkX3ByZWRpY3RvcnNfZGY8LSBzdXBfcmV0YWluZWRfcHJlZGljdG9yc19kZiAlPiUgZmlsdGVyKEtlZXA9PVRSVUUpDQpzdXBfcmV0YWluZWRfcHJlZGljdG9yczwtIHN1cF9yZXRhaW5lZF9wcmVkaWN0b3JzW1t3aGljaChuYW1lcyhzdXBfcmV0YWluZWRfcHJlZGljdG9ycykgJWluJSBzdXBfcmV0YWluZWRfcHJlZGljdG9yc19kZiRWYXJpYWJsZSldXQ0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQp3cml0ZVJhc3RlcihzdXBfcmV0YWluZWRfcHJlZGljdG9ycywgIkRhdGEvZGVyaXZlZC9NdWx0aWJlYW0vcmV0YWluZWRfcHJlZGljdG9ycy5ncmQiLG92ZXJ3cml0ZT1UUlVFKQ0Kc3VwX3JldGFpbmVkX3ByZWRpY3RvcnM8LSBicmljaygiRGF0YS9kZXJpdmVkL011bHRpYmVhbS9yZXRhaW5lZF9wcmVkaWN0b3JzLmdyZCIpDQpgYGANCg0KIyMjIFBsb3Qgb2YgUmV0YWluZWQgVmFyaWFibGVzDQoNCkZpZ3VyZSBTMS41DQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD04LCBtZXNzYWdlPUZBTFNFfQ0Kc3VwX3JldGFpbmVkX3Zhcl9wbG90X2xpc3Q8LSB2ZWN0b3IobW9kZT0ibGlzdCIsIGxlbmd0aCA9IG5sYXllcnMoc3VwX3JldGFpbmVkX3ByZWRpY3RvcnMpKQ0Kc3VwX3JldGFpbmVkX3ByZWRpY3RvcnNfc3RhcnM8LSBzdF9hc19zdGFycyhzdXBfcmV0YWluZWRfcHJlZGljdG9ycywgaWdub3JlX2ZpbGU9VFJVRSkNCmZvciAoaSBpbiAxOmxlbmd0aChzdXBfcmV0YWluZWRfdmFyX3Bsb3RfbGlzdCkpIHsNCiAgY3Vycl92YXI8LSBuYW1lcyhzdXBfcmV0YWluZWRfcHJlZGljdG9ycylbaV0NCiAgaWYgKGdyZXBsKHBhdHRlcm4gPSAiKF5ub3J0aG5lc3MpfCheZWFzdG5lc3MpfChjb3JyZWxhdGlvbikiLCBjdXJyX3ZhcikpIHsNCiAgICBjdXJyX3BhbDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiYmx1ZSIsICJncmF5IiwgInJlZCIpKSgxMDApDQogICAgYnJlYWtzPC0gYygtMSwwLDEpDQogICAgbWlkcG9pbnQ8LSAwDQogIH0gZWxzZSBpZihncmVwbChwYXR0ZXJuID0gIihedHBpKSIsIGN1cnJfdmFyKSkgew0KICAgIGN1cnJfcGFsPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJibHVlIiwgImdyYXkiLCAicmVkIikpKDEwMCkNCiAgICBicmVha3M8LSBjKGZsb29yKG1pblZhbHVlKHN1cF9yZXRhaW5lZF9wcmVkaWN0b3JzW1tpXV0pKSwgMCwgY2VpbGluZyhtYXhWYWx1ZShzdXBfcmV0YWluZWRfcHJlZGljdG9yc1tbaV1dKSkpDQogICAgbWlkcG9pbnQ8LSAwDQogICAgfSBlbHNlew0KICAgIGN1cnJfcGFsPC0gcGFsMQ0KICAgIGJyZWFrczwtIE5VTEwNCiAgICBtaWRwb2ludDwtIE5VTEwNCiAgfQ0KICBjdXJyX3N0YXJzPC0gc3VwX3JldGFpbmVkX3ByZWRpY3RvcnNfc3RhcnNbLCwsaV0NCiAgc3VwX3JldGFpbmVkX3Zhcl9wbG90X2xpc3RbW2ldXTwtIHRtX3NoYXBlKGN1cnJfc3RhcnMsIHJhc3Rlci5kb3duc2FtcGxlID0gRkFMU0UpICsNCiAgdG1fcmFzdGVyKHBhbGV0dGUgPSBjdXJyX3BhbCwgc3R5bGU9ICJjb250IiwgdGl0bGUgPSAiIiwgYnJlYWtzID0gYnJlYWtzLCBtaWRwb2ludCA9IG1pZHBvaW50KSsNCiAgICB0bV9sYXlvdXQobWFpbi50aXRsZSA9IGN1cnJfdmFyLCANCiAgICBtYWluLnRpdGxlLnBvc2l0aW9uID0gImNlbnRlciIsDQogICAgbWFpbi50aXRsZS5zaXplPTAuNzUpDQp9DQpzdXBfcmV0YWluZWRfdmFyX3Bsb3Q8LSB0bWFwX2FycmFuZ2Uoc3VwX3JldGFpbmVkX3Zhcl9wbG90X2xpc3QsIG5jb2w9NCkNCnN1cF9yZXRhaW5lZF92YXJfcGxvdA0KYGBgDQoNCiMjIyBGaXQgYW5kIHJ1biBtb2RlbA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30NCiNGaXQgYW5kIHByZWRpY3QgdXNpbmcgcmFuZG9tIGZvcmVzdA0Kbl9yZXRhaW5lZF9wcmVkPC0gbmxheWVycyhzdXBfcmV0YWluZWRfcHJlZGljdG9ycykNCmJlZ2luQ2x1c3RlcihkZXRlY3RDb3Jlcyhsb2dpY2FsID0gRkFMU0UpLTEpDQpzZXQuc2VlZCg1KQ0Kc3VwX21vZGVsPC0gc3VwZXJDbGFzcyhpbWcgPXN1cF9yZXRhaW5lZF9wcmVkaWN0b3JzLCB0cmFpbkRhdGEgPSBmaWx0ZXIoVFZfc2V0LCBTZXQ9PSJUcmFpbmluZyIpLCByZXNwb25zZUNvbCA9ICJTdWJzdHJhdGUiLCBtb2RlbCA9ICJyYW5nZXIiLCBtb2RlID0gImNsYXNzaWZpY2F0aW9uIiwgdmFsRGF0YSA9IGZpbHRlcihUVl9zZXQsIFNldD09IlZhbGlkYXRpb24iKSwgcHJlZGljdCA9IEZBTFNFLCBwcmVkVHlwZSA9ICJwcm9iIiwga2ZvbGQ9NSwgbWluRGlzdCA9IDAsIG1ldHJpYz0gIkthcHBhIiwgbnVtLnRyZWVzPTMwMDAsIHR1bmVHcmlkID0gZGF0YS5mcmFtZShtdHJ5PTI6KG5fcmV0YWluZWRfcHJlZC0xKSwgbWluLm5vZGUuc2l6ZT0xLCBzcGxpdHJ1bGU9ImdpbmkiKSwga2VlcC5pbmJhZyA9IFRSVUUsIHNhbXBsZS5mcmFjdGlvbj0gYyhzYW1wbGVfZnJhY3Rpb24sc2FtcGxlX2ZyYWN0aW9uKSwgc2NhbGUucGVybXV0YXRpb24uaW1wb3J0YW5jZSA9IEZBTFNFLCBpbXBvcnRhbmNlPSAicGVybXV0YXRpb24iLCBsb2NhbC5pbXBvcnRhbmNlID0gVFJVRSwgdmVyYm9zZSA9IEZBTFNFKQ0KZW5kQ2x1c3RlcigpDQoNCnN1cF9oYWI8LSBSU3Rvb2xib3g6OjpwcmVkaWN0LnN1cGVyQ2xhc3Mob2JqZWN0ID0gc3VwX21vZGVsLCBpbWcgPSBzdXBfcmV0YWluZWRfcHJlZGljdG9ycywgcHJlZFR5cGU9InJhdyIpDQpuYW1lcyhzdXBfaGFiKTwtICJTdWJzdHJhdGUiDQpzdXBfaGFiPC0gYXMuZmFjdG9yKHN1cF9oYWIpDQpsZXZlbHMoc3VwX2hhYilbWzFdXSRTdWJzdHJhdGU8LSBjKCJSb2NrIiwgIlNhbmQiKQ0KDQojVW5jZXJ0YWludHkNCnN1cF9oYWJfcHJvYjwtIFJTdG9vbGJveDo6OnByZWRpY3Quc3VwZXJDbGFzcyhzdXBfbW9kZWwsIHN1cF9yZXRhaW5lZF9wcmVkaWN0b3JzLCBwcmVkVHlwZSA9ICJwcm9iIikNCm5hbWVzKHN1cF9oYWJfcHJvYik8LSBjKCJSb2NrIiwgIlNhbmQiKQ0Kc3VwX2hhYl9lbnRyb3B5PC0gbXl0b29sczo6Y2FsY19lbnRyb3B5KHN1cF9oYWJfcHJvYikNCm5hbWVzKHN1cF9oYWJfZW50cm9weSk8LSAiU2hhbm5vbl9FbnRyb3B5Ig0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQp3cml0ZVJhc3RlcihzdXBfaGFiLCBmaWxlbmFtZSA9ICJQcm9kdWN0cy9NYXBwaW5nL0VsYm93X1N1YnN0cmF0ZV9TdXBlcnZpc2VkLnRpZiIsIG92ZXJ3cml0ZT1UUlVFKQ0Kd3JpdGVSYXN0ZXIoc3VwX2hhYiwgZmlsZW5hbWUgPSAiUHJvZHVjdHMvTWFwcGluZy9FbGJvd19TdWJzdHJhdGVfU3VwZXJ2aXNlZC5ncmQiLCBvdmVyd3JpdGU9VFJVRSkNCnN1cF9oYWI8LSByYXN0ZXIoIlByb2R1Y3RzL01hcHBpbmcvRWxib3dfU3Vic3RyYXRlX1N1cGVydmlzZWQuZ3JkIikNCg0Kd3JpdGVSYXN0ZXIoc3VwX2hhYl9wcm9iLCBmaWxlbmFtZSA9ICJQcm9kdWN0cy9NYXBwaW5nL0VsYm93X1N1YnN0cmF0ZV9TdXBlcnZpc2VkX1Byb2IuZ3JkIiwgb3ZlcndyaXRlPVRSVUUpDQpzdXBfaGFiX3Byb2I8LSBicmljaygiUHJvZHVjdHMvTWFwcGluZy9FbGJvd19TdWJzdHJhdGVfU3VwZXJ2aXNlZF9Qcm9iLmdyZCIpDQoNCndyaXRlUmFzdGVyKHN1cF9oYWJfZW50cm9weSwgZmlsZW5hbWUgPSAiUHJvZHVjdHMvTWFwcGluZy9FbGJvd19TdWJzdHJhdGVfU3VwZXJ2aXNlZF9FbnRyb3B5LnRpZiIsIG92ZXJ3cml0ZT1UUlVFKQ0Kd3JpdGVSYXN0ZXIoc3VwX2hhYl9lbnRyb3B5LCBmaWxlbmFtZSA9ICJQcm9kdWN0cy9NYXBwaW5nL0VsYm93X1N1YnN0cmF0ZV9TdXBlcnZpc2VkX0VudHJvcHkuZ3JkIiwgb3ZlcndyaXRlPVRSVUUpDQpzdXBfaGFiX2VudHJvcHk8LSByYXN0ZXIoIlByb2R1Y3RzL01hcHBpbmcvRWxib3dfU3Vic3RyYXRlX1N1cGVydmlzZWRfRW50cm9weS5ncmQiKQ0KYGBgDQoNCiMjIyBNb2RlbCBEaWFnbm9zdGljcw0KTW9kZWwgZGlhZ25vc3RpY3Mgc2hvd2luZyB0aGF0IHRoZSBvdmVyYWxsIE91dC1PZi1CYWcgZXJyb3IgcmF0ZSBwbGF0ZWF1cywgbWVhbmluZyB0aGF0IGEgc3VmZmljaWVudCBudW1iZXIgb2YgZGVjaXNpb24gdHJlZXMgaGF2ZSBiZWVuIHVzZWQgaW4gdGhlIG1vZGVsDQoNCkZpZ3VyZSBTMS42DQoNCmBgYHtyIGVjaG89RkFMU0V9DQpPT0JfZGY8LSBleHRyYWN0X3Jhbmdlcl9vb2Ioc3VwX21vZGVsKQ0KZXJyX3ZzX250cmVlPC0gZ2dwbG90KGRhdGEgPSBPT0JfZGYsIGFlcyh4PW50cmVlcywgeT1PdmVyYWxsKSkrDQogIGdlb21fbGluZSgpK3lsYWIoIkVycm9yIikrZ2d0aXRsZSgiT3V0LU9mLUJhZyBFcnJvciB2cyBOdW1iZXIgb2YgVHJlZXMiKSt4bGFiKCJOdW1iZXIgb2YgVHJlZXMiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnRfZm9ybWF0KCkpKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0PS41KSkNCmBgYA0KYGBge3IgZWNobz1GQUxTRSwgLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQ0KZXJyX3ZzX250cmVlDQpgYGANCg0KDQojIyMgUmVzdWx0aW5nIE1hcHMNCg0KVGhlIGxlZnQgcGFuZWwgc2hvd3MgdGhlIHByZWRpY3RlZCBzdWJzdHJhdGUgYWNyb3NzIHRoZSBzdHVkeSBhcmVhIGJhc2VkIG9uIG91ciBzdXBlcnZpc2VkIGNsYXNzaWZpY2F0aW9uIG1vZGVsLiBJbiBhZGRpdGlvbiB0byB0aGUgcHJlZGljdGlvbnMsIHRoZSByYW5kb20gZm9yZXN0IG1vZGVsIGFsbG93cyBmb3IgYW4gZW50cm9weSBtYXAgd2hpY2ggcGxvdHMgdGhlIHVuY2VydGFpbnR5IGFzc29jaWF0ZWQgd2l0aCB0aGUgY2xhc3NpZmljYXRpb24gZm9yIGVhY2ggcGl4ZWwgYnkgcXVhbnRpZnlpbmcgdGhlIGxldmVsIG9mIGRpc2FncmVlbWVudCBhbW9uZyB0aGUgYWxsIHRoZSBkaWZmZXJlbnQgZGVjaXNpb24gdHJlZXMgaW4gb3VyIHJhbmRvbSBmb3Jlc3QgbW9kZWwuDQoNCkZpZ3VyZSBTMS43DQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTh9DQpzdXBfc3ViX3Bsb3Q8LSB0bV9zaGFwZShzdF9hc19zdGFycyhzdXBfaGFiLCBpZ25vcmVfZmlsZT1UUlVFKSwgcmFzdGVyLmRvd25zYW1wbGUgPSBGQUxTRSkrDQogIHRtX3Jhc3Rlcihjb2w9IlN1YnN0cmF0ZSIsIHBhbGV0dGUgPSBjKCJyZWQiICwgIiNGRkVCQkUiKSwgdGl0bGUgPSAiU3VwZXJ2aXNlZCBTdWJzdHJhdGUiLCBzdHlsZSA9ICJjYXQiKSsNCiAgdG1fY3JlZGl0cyh0ZXh0ID0gImEpIiwgcG9zaXRpb24gPSBjKCJyaWdodCIsICJ0b3AiKSwgc2l6ZSA9IDEpKw0KICAgdG1fZ3JhdGljdWxlcyhsaW5lcz1GQUxTRSkNCg0KZW50X3BhbDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiYmx1ZSIsICJ5ZWxsb3ciLCAicmVkIikpDQpzdXBfZW50X3Bsb3Q8LSB0bV9zaGFwZShzdXBfaGFiX2VudHJvcHksIHJhc3Rlci5kb3duc2FtcGxlID0gRkFMU0UpKw0KICB0bV9yYXN0ZXIocGFsZXR0ZT1lbnRfcGFsKDEwMCksIHN0eWxlID0gImNvbnQiLCB0aXRsZSA9ICJTaGFubm9uIEVudHJvcHkiKSsNCiAgICB0bV9jcmVkaXRzKHRleHQgPSAiYikiLCBwb3NpdGlvbiA9IGMoInJpZ2h0IiwgInRvcCIpLCBzaXplID0gMSkrDQogICB0bV9ncmF0aWN1bGVzKGxpbmVzPUZBTFNFKSNFbnRyb3B5IE1hcCB0byBsb29rIGF0IHVuY2VydGFpbnR5DQoNCnRtYXBfYXJyYW5nZShzdXBfc3ViX3Bsb3QsIHN1cF9lbnRfcGxvdCkNCmBgYA0KDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpzdXBfYXJlYTwtIGFzLmRhdGEuZnJhbWUoZnJlcShzdXBfaGFiLCB1c2VOQT0ibm8iLCBtZXJnZT1UUlVFKSkNCnN1cF9hcmVhJFN1YnN0cmF0ZT1jKCJSb2NrIiwgIlNhbmQiKQ0Kc3VwX2FyZWE8LSBzdXBfYXJlYSAlPiUgbXV0YXRlKEFyZWFfbTI9IGNvdW50KihyZXMoYWxsX29mKHN1cF9oYWIpKVsxXSkqKHJlcyhhbGxfb2Yoc3VwX2hhYikpWzJdKSkNCnN1cF9hcmVhPC0gc3VwX2FyZWEgJT4lIG11dGF0ZShBcmVhX2ttMj1BcmVhX20yLzFlNikNCnN1cF9hcmVhICU+JSBzZWxlY3QoU3Vic3RyYXRlLCBBcmVhX2ttMikgJT4lIG11dGF0ZShBcmVhX2ttMj1yb3VuZChBcmVhX2ttMiwyKSkNCmBgYA0KDQoNCiMjIyBWYXJpYWJsZSBJbXBvcnRhbmNlDQoNCkZpZ3VyZSBTMS44DQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD00fQ0KdmFyX2ltcDwtIGFzLmRhdGEuZnJhbWUoc3VwX21vZGVsJG1vZGVsJGZpbmFsTW9kZWwkdmFyaWFibGUuaW1wb3J0YW5jZSkNCm5hbWVzKHZhcl9pbXApPC0gIk1EQSINCnZhcl9pbXAkUHJlZGljdG9yPC0gcm93bmFtZXModmFyX2ltcCkNCnZhcl9pbXA8LSB2YXJfaW1wICU+JSBhcnJhbmdlKGRlc2MoTURBKSkNCg0KdmFyX2ltcF9wbG90PC0gZ2dwbG90KGRhdGEgPSB2YXJfaW1wLCBtYXBwaW5nID0gYWVzKHg9cmVvcmRlcihQcmVkaWN0b3IsIE1EQSksIHk9IE1EQSkpICsNCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSsNCiAgeGxhYigiVmFyaWFibGUiKSArDQogIHlsYWIoIk1lYW4gRGVjcmVhc2UgaW4gQWNjdXJhY3kiKSsNCiAgZ2d0aXRsZSgiVmFyaWFibGUgSW1wb3J0YW5jZSIpKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0PS41KSkrDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQsIGV4cGFuZD1jKDAsMCkpKw0KICBjb29yZF9mbGlwKCkNCnZhcl9pbXBfcGxvdA0KYGBgDQoNCg0KIyMjIEFjdXJhY2N5IEFzc2Vzc21lbnQNCg0KQWNjdXJhY3kgYXNzZXNzbWVudCB3YXMgcGVyZm9ybWVkIGJ5IGNvbXBhcmluZyB0aGUgcHJlZGljdGlvbnMgdG8gdGhlIG9ic2VydmVkIGdyb3VuZC10cnV0aCBoYWJpdGF0IG9ic2VydmF0aW9ucyBvbiB0aGUgdHJhbnNlY3QgdGhhdCB3YXMgcmVzZXJ2ZWQgZm9yIHZhbGlkYXRpb24gYW5kIG5vdCB1c2VkIHRvIGZpdCB0aGUgbW9kZWwuDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpwcmludChzdXBfbW9kZWwkdmFsaWRhdGlvbiRwZXJmb3JtYW5jZSR0YWJsZSkNCmFncmVlbWVudF9sZXZlbHM8LSBkYXRhLmZyYW1lKG1pbl9rPWMoLUluZiwgMCwgMC4yLCAuNCwgLjYsIC44KSwgbWF4X2s9YygwLC4yLC40LC42LC44LDEpLCBBZ3JlZW1lbnQ9YygicG9vciIsICJzbGlnaHQiLCAiZmFpciIsICJtb2RlcmF0ZSIsICJzdWJzdGFudGlhbCIsICJhbG1vc3QgcGVyZmVjdCIpKQ0KYGBgDQpPdmVyYWxsIEFjY3VyYWN5ID0gYHIgcm91bmQoc3VwX21vZGVsJHZhbGlkYXRpb24kcGVyZm9ybWFuY2Ukb3ZlcmFsbFtbIkFjY3VyYWN5Il1dICoxMDAsMSlgJSANCg0KS2FwcGEgPSBgciByb3VuZChzdXBfbW9kZWwkdmFsaWRhdGlvbiRwZXJmb3JtYW5jZSRvdmVyYWxsW1siS2FwcGEiXV0sMilgDQoNCkEgS2FwcGEgc2NvcmUgb2YgZ3JlYXRlciB0aGFuIGByIGFncmVlbWVudF9sZXZlbHMkbWluX2tbbWF4KHdoaWNoKHN1cF9tb2RlbCR2YWxpZGF0aW9uJHBlcmZvcm1hbmNlJG92ZXJhbGxbWyJLYXBwYSJdXT5hZ3JlZW1lbnRfbGV2ZWxzJG1pbl9rKSldYCBpbmRpY2F0ZXMgYHIgYWdyZWVtZW50X2xldmVscyRBZ3JlZW1lbnRbbWF4KHdoaWNoKHN1cF9tb2RlbCR2YWxpZGF0aW9uJHBlcmZvcm1hbmNlJG92ZXJhbGxbWyJLYXBwYSJdXT5hZ3JlZW1lbnRfbGV2ZWxzJG1pbl9rKSldYCBhZ3JlZW1lbnQgYmV0d2VlbiBwcmVkaWN0aW9ucyBhbmQgb2JzZXJ2YXRpb25zLg0KDQojIyBVbnN1cGVydmllZCBDbGFzc2lmaWNhdGlvbg0KDQojIyMgUHJpbmNpcGFsIENvbXBvbmVudHMgQW5hbHlzaXMNCg0KRmlyc3QsIHdlIGNvbmR1Y3QgYSBQcmluY2lwYWwgQ29tcG9uZW50IEFuYWx5c2lzIG9uIFotc2NvcmUgbm9ybWFsaXplZCB2YXJpYWJsZXMgKHNwY2E9VFJVRSkgdG8gcmVtb3ZlIGNvLWxpbmVhcml0eS4NCg0KYGBge3IgfQ0KUENBX2xheWVyczwtIHJhc3RlclBDQShwcmVkaWN0b3JfdmFycywgc3BjYSA9IFRSVUUpDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCndyaXRlUmFzdGVyKFBDQV9sYXllcnMkbWFwLCAiRGF0YS9kZXJpdmVkL011bHRpYmVhbS9QQ0FfbWFwLmdyZCIsIG92ZXJ3cml0ZT1UUlVFKQ0KUENBX2xheWVycyRtYXA8LSBicmljaygiRGF0YS9kZXJpdmVkL011bHRpYmVhbS9QQ0FfbWFwLmdyZCIpDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NClBDQV9jb21wX2RmPC0gdGliYmxlKFBDPTE6bmxheWVycyhQQ0FfbGF5ZXJzJG1hcCksIE9ic2VydmVkPVBDQV9sYXllcnMkbW9kZWwkc2Rldl4yLCBTaW11bGF0ZWQ9YnJva2VuX3N0aWNrKG5sYXllcnMoUENBX2xheWVycyRtYXApKSkgI2RhdGFmcmFtZSBjb21wYXJpbmcgZWlnZW52YWx1ZXMgdG8gdGhvc2Ugb2YgcmFuZG9tIGRhdGENCm5fcGNzPC0gKHdoaWNoKFBDQV9jb21wX2RmJFNpbXVsYXRlZD5QQ0FfY29tcF9kZiRPYnNlcnZlZCAmIFBDQV9jb21wX2RmJFBDPjEpWzFdKS0xDQpuYW1lcyhuX3Bjcyk8LSBOVUxMDQpgYGANCg0KQXMgZWFjaCBzZXF1ZW50aWFsIHByaW5jaXBhbCBjb21wb25lbnQgZXhwbGFpbnMgYSBzbWFsbGVyIHBlcmNlbnRhZ2Ugb2YgdGhlIHZhcmlhdGlvbiBpbiB0aGUgZGF0YSwgbmV4dCB3ZSBtdXN0IGRldGVybWluZSBob3cgbWFueSBwcmluY2lwYWwgY29tcG9uZW50cyB0byByZXRhaW4uIFdlIHdpbGwgcmV0YWluIG9ubHkgYSBzdWJzZXQgdGhhdCBhcmUgZGV0ZXJtaW5lZCB0byBiZSBpbXBvcnRhbnQuIFRoZXJlIGFyZSBzZXZlcmFsIG1ldGhvZHMgdXNlZCB0byBpZGVudGlmeSB0aGUgYXBwcm9wcmlhdGUgbnVtYmVyIG9mIHByaW5jaXBhbCBjb21wb25lbnRzIHRvIHJldGFpbiAoSmFja3NvbiwgMTk5MykuIFdlIGNvbXBhcmVkIHRoZSB2YXJpYXRpb24gZXhwbGFpbmVkIGJ5IGVhY2ggUHJpbmNpcGFsIENvbXBvbmVudCBhbmQgdGhlIHZhcmlhdGlvbiBleHBlY3RlZCB0byBiZSBleHBsYWluZWQgYnkgc2ltdWxhdGVkIGRhdGEgaW4gd2hpY2ggdGhlIHZhcmlhbmNlIHdhcyBkaXN0cmlidXRlZCByYW5kb21seSBhbW9uZyB0aGUgcHJpbmNpcGFsIGNvbXBvbmVudHMgYXMgbW9kZWxlZCBieSBhIGJyb2tlbi1zdGljayBkaXN0cmlidXRpb24gKEZyb250aWVyLCAxOTc2KS4gVGhlIGZpcnN0IGByIG5fcGNzYCBleHBsYWluZWQgbW9yZSB0aGFuIGNvdWxkIGJlIGV4cGVjdGVkIGJ5IHJhbmRvbSBjaGFuY2Ugc28gdGhlIGZpcnN0IGByIG5fcGNzYCBwcmluY2lwYWwgY29tcG9uZW50cyB3ZXJlIHJldGFpbmVkLiBUaGVzZSBmaXJzdCBgciBuX3Bjc2AgcHJpbmNpcGFsIGNvbXBvbmVudHMgZXhwbGFpbiBgciByb3VuZCgoMTAwKmN1bXN1bShQQ0FfY29tcF9kZiRPYnNlcnZlZCkvc3VtKFBDQV9jb21wX2RmJE9ic2VydmVkKSlbbl9wY3NdKWAlIG9mIHRoZSB2YXJpYXRpb24gaW4gdGhlIG9yaWdpbmFsIGRhdGEuDQoNCg0KRmlndXJlIFMxLjkNCg0KYGBge3IgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9NH0NClBDQV92YXJfcGxvdDwtIGdncGxvdChkYXRhID0gZ2F0aGVyKFBDQV9jb21wX2RmLCBrZXkgPSAiRGF0YSIsIHZhbHVlID0gIlZhcmlhbmNlIiwgT2JzZXJ2ZWQsIFNpbXVsYXRlZCksIG1hcHBpbmcgPSBhZXMoeD1QQywgeSA9IFZhcmlhbmNlLCBjb2xvcj1EYXRhKSkrDQogIGdlb21fcG9pbnQoKSsNCiAgZ2VvbV9saW5lKCkrDQogIHhsYWIoIlByaW5jaXBhbCBDb21wb25lbnQiKSsNCiAgZ2d0aXRsZSgiVmFyaWFuY2UgRXhwbGFpbmVkIHZzIFByaW5jaXBhbCBDb21wb25lbnQgTnVtYmVyIikrDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShmcm9tID0gMCwgdG8gPSBtYXgoUENBX2NvbXBfZGYkUEMpLCBieT0xMCksbGltaXRzID0gYygxLE5BKSkNClBDQV92YXJfcGxvdA0KYGBgDQoNClBsb3Qgb2YgdGhlIHJldGFpbmVkIHByaW5jaXBhbCBjb21wb25lbnRzDQpGaWd1cmUgUzEuMTANCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTh9DQpyZXRfUENBX3Bsb3Q8LSB0bV9zaGFwZShzdF9hc19zdGFycyhQQ0FfbGF5ZXJzJG1hcFtbMTpuX3Bjc11dLCBpZ25vcmVfZmlsZT1UUlVFKSwgcmFzdGVyLmRvd25zYW1wbGUgPSBGQUxTRSkrDQogIHRtX3Jhc3RlcihwYWxldHRlID0gcGFsMSwgc3R5bGU9ICJjb250IiwgdGl0bGUgPSAiIiwgbWlkcG9pbnQgPSBOQSkgKw0KICB0bV9mYWNldHMoZnJlZS5zY2FsZXMgPSBUUlVFLCBuY29sID0gMykNCnJldF9QQ0FfcGxvdA0KYGBgDQoNCiMjIyBSdW4gY2x1c3RlcmluZyBvbiB0aGUgcmV0YWluZWQgcHJpbmNpcGFsIGNvbXBvbmVudHMNCg0KYGBge3IgfQ0KYmVnaW5DbHVzdGVyKGRldGVjdENvcmVzKGxvZ2ljYWwgPSBGQUxTRSktMSkNCnNldC5zZWVkKDUpDQp1bnN1cDwtIHVuc3VwZXJDbGFzcyhpbWcgPVBDQV9sYXllcnMkbWFwW1sxOm5fcGNzXV0sIG5DbGFzc2VzID0gNCwgbnN0YXJ0cz0xMDAsIG5JdGVyID0gMTAwMCwgY2x1c3Rlck1hcCA9IEZBTFNFLCBhbGdvcml0aG0gPSAiTWFjUXVlZW4iKQ0KZW5kQ2x1c3RlcigpDQpuYW1lcyh1bnN1cCRtYXApPC0gIkFjb3VzdGljX0NsdXN0ZXIiDQp1bnN1cCRtYXA8LSBhcy5mYWN0b3IodW5zdXAkbWFwKQ0KbGV2ZWxzKHVuc3VwJG1hcClbWzFdXSRDbHVzdGVyPC0gYygiMSIsICIyIiwgIjMiLCAiNCIpDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCndyaXRlUmFzdGVyKHVuc3VwJG1hcCwgZmlsZW5hbWUgPSAiUHJvZHVjdHMvTWFwcGluZy9FbGJvd19BY291c3RpY0NsdXN0ZXJzX1Vuc3VwZXJ2aXNlZC50aWYiLCBvdmVyd3JpdGU9VFJVRSkNCndyaXRlUmFzdGVyKHVuc3VwJG1hcCwgZmlsZW5hbWUgPSAiUHJvZHVjdHMvTWFwcGluZy9FbGJvd19BY291c3RpY0NsdXN0ZXJzX1Vuc3VwZXJ2aXNlZC5ncmQiLCBvdmVyd3JpdGU9VFJVRSkNCnVuc3VwJG1hcDwtIHJhc3RlcigiUHJvZHVjdHMvTWFwcGluZy9FbGJvd19BY291c3RpY0NsdXN0ZXJzX1Vuc3VwZXJ2aXNlZC5ncmQiKQ0KYGBgDQoNCiMjIyBJbnRlcnByZXQgQWNvdXN0aWMgY2x1c3RlcnMNCg0KVXNpbmcgdGhlIGdyb3VuZC10cnV0aCBkYXRhIHBvaW50cywgdGhlIHN1YnN0cmF0ZSBvYnNlcnZhdGlvbnMgd2l0aGluIGVhY2ggY2x1c3RlciB3ZXJlIGNvdW50ZWQgdXAgYW5kIGVhY2ggY2x1c3RlciB3YXMgaW50ZXJwcmV0ZWQgYXMgdGhlIHN1YnN0cmF0ZSB0aGF0IG9jY3VyZWQgbW9zdCBvZnRlbiB3aXRoaW4gaXQuIFRoZSBmaXJ0IHBhbmVsIHNob3dzIHRoZSBjbHVzdGVyIG51bWJlciwgYW5kIHRoZSByaWdodCBwYW5lbCBzaG93cyB0aGUgY2xhc3NpZmllZCBtYXAgYmFzZWQgb24gbWFqb3JpdHkgdm90ZSBvZiB0aGUgZ3JvdW5kLXRydXRoIGhhYml0YXQgb2JzZXJ2YXRpb25zIGluIGVhY2ggY2x1c3RlciAoc2VlIHRhYmxlIGJlbG93KS4NCg0KYGBge3IgZWNobz1UUlVFfQ0KYWNvdXN0aWNfY2xhc3M8LSByYXN0ZXI6OmV4dHJhY3QoeCA9IHVuc3VwJG1hcCwgeSA9IGZpbHRlcihUVl9zZXQsIFNldD09IlRyYWluaW5nIiksIG1ldGhvZD0ic2ltcGxlIiwgZmFjdG9ycz1GQUxTRSwgc3A9VFJVRSlAZGF0YQ0KYWNvdXN0aWNfY2xhc3M8LSBhY291c3RpY19jbGFzcyAlPiUgc2VsZWN0KFN1YnN0cmF0ZSwgQWNvdXN0aWNfQ2x1c3RlcikgJT4lIG5hLm9taXQoKQ0Kdm90ZXM8LSBhY291c3RpY19jbGFzcyAlPiUgZ3JvdXBfYnkoQWNvdXN0aWNfQ2x1c3RlcikgJT4lIGNvdW50KFN1YnN0cmF0ZSkgJT4lIHVuZ3JvdXAoKQ0Kdm90ZXNfdGFibGU8LSB2b3RlcyAlPiUgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IFN1YnN0cmF0ZSwgdmFsdWVzX2Zyb209biwgdmFsdWVzX2ZpbGw9MCkNCnZvdGVzX3RhYmxlPC0gdm90ZXNfdGFibGUgJT4lIG11dGF0ZShBc3NpZ25lZF9DbGFzcyA9IGlmZWxzZSh0ZXN0ID0gU2FuZD5Sb2NrLCB5ZXMgPSAiU2FuZCIsIG5vID0gIlJvY2siKSkNCnZvdGVzX3RhYmxlDQpgYGANCg0KRmlndXJlIFMxLjExDQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTh9DQpxX3J1bGVzPC0gdm90ZXNfdGFibGUgJT4lIG11dGF0ZShBc3NpZ25lZF9DbGFzcz0gaWZlbHNlKHRlc3QgPSBBc3NpZ25lZF9DbGFzcz09IlJvY2siLCB5ZXMgPSAxLCBubyA9IDIpKSAlPiUgc2VsZWN0KEFjb3VzdGljX0NsdXN0ZXIsIEFzc2lnbmVkX0NsYXNzKSAlPiUgYXMubWF0cml4KCkNCg0KdW5zdXBfaGFiPC0gcmFzdGVyOjpyZWNsYXNzaWZ5KHVuc3VwJG1hcCwgcmNsPSBxX3J1bGVzKQ0KbmFtZXModW5zdXBfaGFiKTwtICJTdWJzdHJhdGUiDQp1bnN1cF9oYWI8LSBhcy5mYWN0b3IodW5zdXBfaGFiKQ0KbGV2ZWxzKHVuc3VwX2hhYilbWzFdXSRTdWJzdHJhdGU8LSBjKCJSb2NrIiwgIlNhbmQiKQ0KDQp1bnN1cF9jbHVzdGVyX3Bsb3Q8LSB0bV9zaGFwZShzdF9hc19zdGFycyh1bnN1cCRtYXAsIGlnbm9yZV9maWxlPVRSVUUpLCByYXN0ZXIuZG93bnNhbXBsZSA9IEZBTFNFKSsNCiAgdG1fcmFzdGVyKHBhbGV0dGUgPSBjKCJibHVlIiwiZ3JlZW4iLCAicHVycGxlIiwgIm9yYW5nZSIpLCBicmVha3MgPSAxOjUpKw0KICB0bV9ncmF0aWN1bGVzKGxpbmVzPUZBTFNFKSsNCiAgdG1fY3JlZGl0cyh0ZXh0ID0gImEpIiwgcG9zaXRpb24gPSBjKCJyaWdodCIsICJ0b3AiKSwgc2l6ZSA9IDEpDQoNCnVuc3VwX3N1Yl9wbG90PC0gdG1fc2hhcGUodW5zdXBfaGFiLCByYXN0ZXIuZG93bnNhbXBsZSA9IEZBTFNFKSsNCiAgdG1fcmFzdGVyKHBhbGV0dGUgPSBjKCJyZWQiLCIjRkZFQkJFIikpKw0KICB0bV9ncmF0aWN1bGVzKGxpbmVzPUZBTFNFKSsNCiAgdG1fY3JlZGl0cyh0ZXh0ID0gImIpIiwgcG9zaXRpb24gPSBjKCJyaWdodCIsICJ0b3AiKSwgc2l6ZSA9IDEpDQoNCg0KdG1hcF9hcnJhbmdlKHVuc3VwX2NsdXN0ZXJfcGxvdCx1bnN1cF9zdWJfcGxvdCkNCmBgYA0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0Kd3JpdGVSYXN0ZXIodW5zdXBfaGFiLCBmaWxlbmFtZSA9ICJQcm9kdWN0cy9NYXBwaW5nL0VsYm93X1N1YnN0cmF0ZV9VbnN1cGVydmlzZWQudGlmIiwgb3ZlcndyaXRlPVRSVUUpDQp3cml0ZVJhc3Rlcih1bnN1cF9oYWIsIGZpbGVuYW1lID0gIlByb2R1Y3RzL01hcHBpbmcvRWxib3dfU3Vic3RyYXRlX1Vuc3VwZXJ2aXNlZC5ncmQiLCBvdmVyd3JpdGU9VFJVRSkNCnVuc3VwX2hhYjwtIHJhc3RlcigiUHJvZHVjdHMvTWFwcGluZy9FbGJvd19TdWJzdHJhdGVfVW5zdXBlcnZpc2VkLmdyZCIpDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRX0NCnVuc3VwX2FyZWE8LSBhcy5kYXRhLmZyYW1lKGZyZXEodW5zdXBfaGFiLCB1c2VOQT0ibm8iLCBtZXJnZT1UUlVFKSkNCnVuc3VwX2FyZWEkU3Vic3RyYXRlPWMoIlJvY2siLCAiU2FuZCIpDQp1bnN1cF9hcmVhPC0gdW5zdXBfYXJlYSAlPiUgbXV0YXRlKEFyZWFfbTI9IGNvdW50KihyZXMoYWxsX29mKHVuc3VwX2hhYikpWzFdKSoocmVzKGFsbF9vZih1bnN1cF9oYWIpKVsyXSkpDQp1bnN1cF9hcmVhPC0gdW5zdXBfYXJlYSAlPiUgbXV0YXRlKEFyZWFfa20yPUFyZWFfbTIvMWU2KQ0KdW5zdXBfYXJlYSAlPiUgc2VsZWN0KFN1YnN0cmF0ZSwgQXJlYV9rbTIpICU+JSBtdXRhdGUoQXJlYV9rbTI9cm91bmQoQXJlYV9rbTIsMikpDQpgYGANCg0KIyMjIEFjdXJhY2N5IEFzc2Vzc21lbnQNCg0KQWNjdXJhY3kgYXNzZXNzbWVudCB3YXMgcGVyZm9ybWVkIGJ5IGNvbXBhcmluZyB0aGUgcHJlZGljdGlvbnMgdG8gdGhlIG9ic2VydmVkIGdyb3VuZC10cnV0aCBoYWJpdGF0IG9ic2VydmF0aW9ucyBvbiB0aGUgdHJhbnNlY3QgdGhhdCB3YXMgcmVzZXJ2ZWQgZm9yIHZhbGlkYXRpb24gYW5kIG5vdCB1c2VkIHRvIGZpdCB0aGUgbW9kZWwuDQoNCmBgYHtyIGVjaG89VFJVRX0NCnVuc3VwX3ZhbDwtIHZhbGlkYXRlTWFwKG1hcCA9IHVuc3VwX2hhYiwgdmFsRGF0YSA9IGZpbHRlcihUVl9zZXQsIFNldD09IlZhbGlkYXRpb24iKSwgcmVzcG9uc2VDb2wgPSAiU3Vic3RyYXRlIiwgbW9kZT0iY2xhc3NpZmljYXRpb24iLCBjbGFzc01hcHBpbmc9ZGF0YS5mcmFtZShjbGFzcz1jKCJSb2NrIiwgIlNhbmQiKSwgY2xhc3NJRD0gYygxLDIpKSkNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcHJpbnQodW5zdXBfdmFsJHBlcmZvcm1hbmNlJHRhYmxlKQ0KYGBgDQpPdmVyYWxsIEFjY3VyYWN5ID0gYHIgcm91bmQodW5zdXBfdmFsJHBlcmZvcm1hbmNlJG92ZXJhbGxbWyJBY2N1cmFjeSJdXSAqMTAwLDEpYCUgDQoNCkthcHBhID0gYHIgcm91bmQodW5zdXBfdmFsJHBlcmZvcm1hbmNlJG92ZXJhbGxbWyJLYXBwYSJdXSwyKWANCg0KQSBLYXBwYSBzY29yZSBvZiBncmVhdGVyIHRoYW4gYHIgYWdyZWVtZW50X2xldmVscyRtaW5fa1ttYXgod2hpY2godW5zdXBfdmFsJHBlcmZvcm1hbmNlJG92ZXJhbGxbWyJLYXBwYSJdXT5hZ3JlZW1lbnRfbGV2ZWxzJG1pbl9rKSldYCBpbmRpY2F0ZXMgYHIgYWdyZWVtZW50X2xldmVscyRBZ3JlZW1lbnRbbWF4KHdoaWNoKHVuc3VwX3ZhbCRwZXJmb3JtYW5jZSRvdmVyYWxsW1siS2FwcGEiXV0+YWdyZWVtZW50X2xldmVscyRtaW5faykpXWAgYWdyZWVtZW50IGJldHdlZW4gcHJlZGljdGlvbnMgYW5kIG9ic2VydmF0aW9ucy4NCg0KDQojIyBDb21wYXJpc29uIG9mIFN1cGVydmlzZWQgYW5kIFVuc3VwZXJ2aXNlZA0KDQojIyMgRGlmZmVyZW5jZSBNYXBzDQoNCkZvciBhcmVhcyBvZiBkaXNhZ3JlZW1lbnQsIHRoZSBsZWdlbmQgaXMgZm9ybWF0dGVkIGFzIHN1cGVydmlzZWQvdW5zdXBlcnZpc2VkLg0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KZGlmZl9tYXA8LSAoc3VwX2hhYioxMCkrdW5zdXBfaGFiDQpkaWZmX21hcFtzdXBfaGFiPT11bnN1cF9oYWJdPC0gMQ0KZGlmZl9tYXA8LSBhcy5mYWN0b3IoZGlmZl9tYXApDQpuYW1lcyhkaWZmX21hcCk8LSAiRGlmZmVyZW5jZSINCmxldmVscyhkaWZmX21hcClbWzFdXSREaWZmZXJlbmNlPC0gYygiQWdyZWVtZW50IiwgIlJvY2svU2FuZCIsICJTYW5kL1JvY2siKQ0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQp3cml0ZVJhc3RlcihkaWZmX21hcCwgZmlsZW5hbWUgPSAiUHJvZHVjdHMvTWFwcGluZy9kaWZmZXJlbmNlX21hcC50aWYiLCBvdmVyd3JpdGU9VFJVRSkNCndyaXRlUmFzdGVyKGRpZmZfbWFwLCBmaWxlbmFtZSA9ICJQcm9kdWN0cy9NYXBwaW5nL2RpZmZlcmVuY2VfbWFwLmdyZCIsIG92ZXJ3cml0ZT1UUlVFKQ0KZGlmZl9tYXA8LSByYXN0ZXIoIlByb2R1Y3RzL01hcHBpbmcvZGlmZmVyZW5jZV9tYXAuZ3JkIikNCmBgYA0KDQpGaWd1cmUgUzEuMTIgIA0KDQpGb3IgYXJlYXMgb2YgZGlzYWdyZWVtZW50LCB0aGUgbGVnZW5kIGlzIGZvcm1hdHRlZCBhcyBzdXBlcnZpc2VkL3Vuc3VwZXJ2aXNlZC4gIA0KDQpgYGB7ciBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD04fQ0KZGlmZl9tYXBfcGxvdDwtIHRtX3NoYXBlKGRyb3BsZXZlbHMoc3RfYXNfc3RhcnMoZGlmZl9tYXAsIGlnbm9yZV9maWxlPVRSVUUpLCBleGNsdWRlPU5BKSwgcmFzdGVyLmRvd25zYW1wbGUgPSBGQUxTRSkrDQogIHRtX3Jhc3RlcihwYWxldHRlID0gYygicGFsZWdyZWVuIiwgInJlZCIsIiNGRkVCQkUiKSwgdGl0bGU9IiIsIGRyb3AubGV2ZWxzID0gVFJVRSkrDQogICB0bV9ncmF0aWN1bGVzKGxpbmVzPUZBTFNFKQ0KZGlmZl9tYXBfcGxvdA0KYGBgDQoNCg0KIyMjIEtoaXN0IGFuZCBLbG9jDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpoYWJfbWFwX2RmPC0gdGliYmxlKHN1cD0gdmFsdWVzKHN1cF9oYWIpLCB1bnN1cD0gdmFsdWVzKHVuc3VwX2hhYikpDQpoYWJfbWFwX2RmPC0gbmEub21pdChoYWJfbWFwX2RmKQ0KaGFiX21hcF9kZiRzdXA8LSBmYWN0b3IoaGFiX21hcF9kZiRzdXAsIGxldmVscyA9IGMoIjEiLCAiMiIpKQ0KaGFiX21hcF9kZiR1bnN1cDwtIGZhY3RvcihoYWJfbWFwX2RmJHVuc3VwLCBsZXZlbHMgPSBjKCIxIiwgIjIiKSkNCmhhYl9tYXBfY29uZl9tYXQ8LSBjb25mdXNpb25NYXRyaXgoZGF0YSA9IGhhYl9tYXBfZGYkdW5zdXAsIHJlZmVyZW5jZSA9IGhhYl9tYXBfZGYkc3VwKSR0YWJsZQ0KDQpQQTwtIHN1bShkaWFnKGhhYl9tYXBfY29uZl9tYXQpL3N1bShoYWJfbWFwX2NvbmZfbWF0KSkNClBFPC0gcmVwKE5BX3JlYWxfLCBucm93KGhhYl9tYXBfY29uZl9tYXQpKQ0KUE1heDwtIHJlcChOQV9yZWFsXywgbnJvdyhoYWJfbWFwX2NvbmZfbWF0KSkNCg0KZm9yIChpIGluIDE6bnJvdyhoYWJfbWFwX2NvbmZfbWF0KSkgew0KICBwX2lUPC0gKHJvd1N1bXMoaGFiX21hcF9jb25mX21hdClbaV0pL3N1bShoYWJfbWFwX2NvbmZfbWF0KQ0KICBwX1RpPC0gKGNvbFN1bXMoaGFiX21hcF9jb25mX21hdClbaV0pL3N1bShoYWJfbWFwX2NvbmZfbWF0KQ0KICBQRVtpXTwtIHBfaVQqcF9UaQ0KICBQTWF4W2ldPC0gbWluKGMocF9pVCxwX1RpKSkNCn0NClBFPC0gc3VtKFBFKQ0KUG1heDwtIHN1bShQTWF4KQ0KSzwtIChQQS1QRSkvKDEtUEUpDQpLbG9jPC0gKFBBLVBFKS8oUG1heC1QRSkNCktoaXN0bzwtIChQbWF4LVBFKS8oMS1QRSkNCmBgYA0KDQpJbiBhZGRpdGlvbiB0byBjb21wYXJpbmcgdGhlIGFncmVlbWVudCBiZXR3ZWVuIGdyb3VuZC10cnV0aCBvYnNlcnZhdGlvbnMgYW5kIHByZWRpY3Rpb25zLCBLYXBwYSBjYW4gYmUgdXNlZCB0byBjb21wYXJlIHRoZSBhZ3JlZW1lbnQgaW4gcHJlZGljdGlvbnMgYmV0d2VlbiB0aGUgdHdvIG1hcHMgYnkgbG9va2luZyBhdCB0aGUgYWdyZWVtZW50IGluIGNvcnJlc3BvbmRpbmcgY2xhc3NpZmljYXRpb25zIGZvciBlYWNoIHBpeGVsLiBBZGRpdGlvbmFsbHkgS2FwcGEgY2FuIGJlIGJyb2tlbiBkb3duIGludG8gdHdvIGNvbXBvbmVudHM6IEtsb2NhdGlvbiBhbmQgS2hpc3RvLCB3aGVyZSBLYXBwYSBpcyBkZWZpbmVkIGFzIHRoZSBwcm9kdWN0IG9mIEtsb2NhdGlvbiBhbmQgS2hpc3RvIChQb250aXVzLCAyMDAwOyBIYWdlbiwgMjAwMjsgU291c2EgZXQgYWwgMjAwMikuIEtsb2NhdGlvbiBpcyBhIG1lYXN1cmUgb2YgdGhlIHNpbWlsYXJpdHkgaW4gdGhlIHNwYXRpYWwgZGlzdHJpYnV0aW9uIG9mIHRoZSBzdWJzdHJhdGUsIGFuZCBLaGlzdG8gaXMgbWVhc3VyZSBvZiB0aGUgc2ltaWxhcml0eSBpbiB0aGUgZnJlcXVlbmN5IG9mIGNsYXNzIHByZWRpY3Rpb25zIChQb250aXVzLCAyMDAwOyBIYWdlbiwgMjAwMjsgU291c2EgZXQgYWwgMjAwMikuIFRoZSB0d28gbWFwcyBoYXZlIGEgS2xvYyB2YWx1ZSBvZiBgciByb3VuZChLbG9jLDMpYCBpbmRpY2F0aW5nIGByIGFncmVlbWVudF9sZXZlbHMkQWdyZWVtZW50W0tsb2MgPiBhZ3JlZW1lbnRfbGV2ZWxzJG1pbl9rICYgS2xvYyA8PSBhZ3JlZW1lbnRfbGV2ZWxzJG1heF9rXWAgYWdyZWVtZW50IGluIHRoZSBzcGF0aWFsIGRpc3RyaWJ1dGlvbiBvZiBjbGFzc2VzLCBhbmQgYSBLaGlzdG8gb2YgYHIgcm91bmQoS2hpc3RvLDMpYCBpbmRpY2F0aW5nIGByIGFncmVlbWVudF9sZXZlbHMkQWdyZWVtZW50W0toaXN0byA+IGFncmVlbWVudF9sZXZlbHMkbWluX2sgJiBLaGlzdG8gPD0gYWdyZWVtZW50X2xldmVscyRtYXhfa11gIGFncmVlbWVudCBpbiB0aGUgZnJlcXVlbmN5IG9mIGNsYXNzIHByZWRpY3Rpb25zLiBPdmVyYWxsIHRoaXMgY29ycmVzcG9uZHMgdG8gYSBLYXBwYSB2YWx1ZSBvZiBgciByb3VuZChLLDMpYCBpbmRpY2F0aW5nIGEgYHIgYWdyZWVtZW50X2xldmVscyRBZ3JlZW1lbnRbSyA+IGFncmVlbWVudF9sZXZlbHMkbWluX2sgJiBLIDw9IGFncmVlbWVudF9sZXZlbHMkbWF4X2tdYCBsZXZlbCBvZiBhZ3JlZW1lbnQgYmV0d2VlbiB0aGUgdHdvIG1hcHMuDQoNCg0KIyMjIE1vbnRlLUNhcmxvIFBlcm11dGF0aW9uIFRlc3QNCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCnZhbF9jb21wPC0gdGliYmxlKHJlZj1wdWxsKGZpbHRlcihUVl9zZXRAZGF0YSwgU2V0PT0iVmFsaWRhdGlvbiIpLCBTdWJzdHJhdGUpLA0KICAgICAgICAgICAgIHN1cD0gcmFzdGVyOjpleHRyYWN0KHggPSBzdXBfaGFiLCB5PWZpbHRlcihUVl9zZXQsIFNldD09ICJWYWxpZGF0aW9uIiksIG5hLnJtPUZBTFNFKSwNCiAgICAgICAgICAgICB1bnN1cD0gcmFzdGVyOjpleHRyYWN0KHggPSB1bnN1cF9oYWIsIHk9ZmlsdGVyKFRWX3NldCwgU2V0PT0gIlZhbGlkYXRpb24iKSwgbmEucm09RkFMU0UsKSkNCnZhbF9jb21wPC0gbmEub21pdCh2YWxfY29tcCkNCnZhbF9jb21wPC0gdmFsX2NvbXAgJT4lIG11dGF0ZShzdXA9aWZlbHNlKHRlc3QgPSBzdXA9PTEsIHllcyA9ICJSb2NrIiwgbm8gPSAiU2FuZCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuc3VwPWlmZWxzZSh0ZXN0ID0gdW5zdXA9PTEsIHllcyA9ICJSb2NrIiwgbm8gPSAiU2FuZCIpKQ0KdmFsX2NvbXA8LSB2YWxfY29tcCAlPiUgbXV0YXRlX2FsbChmYWN0b3IsIGxldmVscz1jKCJSb2NrIiwgIlNhbmQiKSkNCktzdXA8LSBjb25mdXNpb25NYXRyaXgoZGF0YT12YWxfY29tcCRzdXAsIHJlZmVyZW5jZT12YWxfY29tcCRyZWYsIHBvc2l0aXZlID0gIlJvY2siKSRvdmVyYWxsW1siS2FwcGEiXV0NCkt1bnN1cDwtIGNvbmZ1c2lvbk1hdHJpeChkYXRhPXZhbF9jb21wJHVuc3VwLCByZWZlcmVuY2U9dmFsX2NvbXAkcmVmLCBwb3NpdGl2ZSA9ICJSb2NrIikkb3ZlcmFsbFtbIkthcHBhIl1dDQpLYXBwYV9EaWZmPC0gS3N1cC1LdW5zdXANCiMgI01vbnRlIGNhcmxvDQppdGVyPC0gMTAwMA0Ka2FwcGFfcGVybTwtIHRpYmJsZShLMT1yZXAoTkFfcmVhbF8saXRlciksIEsyPSBOQV9yZWFsXykNCmthcHBhX3Blcm0kSzFbMV08LSBLc3VwDQprYXBwYV9wZXJtJEsyWzFdPC0gS3Vuc3VwDQpzZXQuc2VlZCg1KQ0KZm9yIChpIGluIDI6aXRlcikgew0KICByZWZfcGVybTwtIHNhbXBsZSh4ID0gdmFsX2NvbXAkcmVmLCBzaXplID0gbnJvdyh2YWxfY29tcCksIHJlcGxhY2UgPSBGQUxTRSkNCiAga2FwcGFfcGVybSRLMVtpXTwtIGNvbmZ1c2lvbk1hdHJpeChkYXRhPXZhbF9jb21wJHN1cCwgcmVmZXJlbmNlPXJlZl9wZXJtLCBwb3NpdGl2ZSA9ICJSb2NrIikkb3ZlcmFsbFtbIkthcHBhIl1dDQogIGthcHBhX3Blcm0kSzJbaV08LSBjb25mdXNpb25NYXRyaXgoZGF0YT12YWxfY29tcCR1bnN1cCwgcmVmZXJlbmNlPXJlZl9wZXJtLCBwb3NpdGl2ZSA9ICJSb2NrIikkb3ZlcmFsbFtbIkthcHBhIl1dDQogIH0NCmthcHBhX3Blcm08LSAga2FwcGFfcGVybSAlPiUgbXV0YXRlKGtkaWZmPUsxLUsyKQ0KcF92YWw8LSBzdW0oa2FwcGFfcGVybSRrZGlmZj49S2FwcGFfRGlmZikvaXRlcg0KYGBgDQoNCkEgb25lLXRhaWxlZCBNb250ZS1DYXJsbyBwZXJtdXRhdGlvbiB0ZXN0IHdpdGggYHIgaXRlcmAgaXRlcmF0aW9ucyBvbiB0aGUgZGlmZmVyZW5jZSBpbiBLYXBwYSB2YWx1ZXMgd2FzIHBlcmZvcm1lZCAoTWNLZW56aWUgZXQgYWwsIDE5OTYpLiBUaGlzIHJlc3VsdHMgb2YgdGhpcyB0ZXN0IHNob3dlZCB0aGF0IHRoZSBzdXBlcnZpc2VkIGNsYXNzaWZpY2F0aW9uIG1hcCBwcm92aWRlZCBzaWduaWZpY2FudGx5IGhpZ2hlciBhZ3JlZW1lbnQgd2l0aCB0aGUgZ3JvdW5kLXRydXRoIG9ic2VydmF0aW9ucyBhcyBjb21wYXJlZCB0byB0aGUgdW5zdXBlcnZpc2VkIGNsYXNzaWZpY2F0aW9uIG1hcCAocCA8PSBgciBwX3ZhbGApLg0KDQojIE92ZXJsYXlpbmcgdmVydGljYWwgcmVsaWVmIG9uIHN1YnN0cmF0ZQ0KQmVjYXVzZSBoaWdoZXIgcmVsaWVmIGZlYXR1cmVzIHJlbGF0aXZlbHkgcmFyZSwgYW5kIGFyZSBmYWlybHkgc21hbGwgcmVsYXRpdmUgdG8gdGhlIGVycm9yIGFzc29jaWF0ZWQgd2l0aCBwb3NpdGlvbmluZyBvZiB0aGUgQ0JBU1MsIHdlIGRpZCBub3QgZGlyZWN0bHkgdHJ5IHRvIHByZWRpY3QgdGhpcyBpbiB0aGUgc3VwZXJ2aXNlZCBhbmQgdW5zdXBlcnZpc2VkIG1vZGVscy4gSG93ZXZlciwgd2UgY2FuIG1lYXN1cmUgdmVydGljYWwgcmVsaWVmIGFzIGEgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIHZhbHVlcy4gVG90YWwgZGVwdGggd2FzIGNhbGN1bGF0ZWQgZnJvbSB0aGUgQ0JBU1Mgc2Vuc29ycyBhcyBDQkFTUyBkZXB0aCArIENCQVNTIGFsdGl0dWRlICh3aGVyZSBhbHRpdHVkZSBtZWFzdXJlbWVudHMgaGF2ZSBiZWVuIGFkanVzdGVkIGZvciB0aGUgcGl0Y2ggb2YgdGhlIHN5c3RlbSkuIFZlcnRpY2FsIHJlbGllZiBmb3IgZWFjaCAxNSBzZWNvbmQgYmluIHdhcyBjYWxjdWxhdGVkIGFzIHRoZSBtYXhpbXVtIGNoYW5nZSBpbiBkZXB0aCBvdmVyIHRoYXQgMTUgc2Vjb25kIG9ic2VydmF0aW9uIHdpbmRvdy4gQSBib3ggcGxvdCBvZiB0aGUgYXNzaWduZWQgdmlzdWFsIHJlbGllZiBjbGFzcywgYW5kIHRoZSBtZWFzdXJlZCB2ZXJ0aWNhbCByZWxpZWYgZnJvbSB0aGUgc2Vuc29ycyBpcyBzaG93biBiZWxvdy4gSW4gYmx1ZSwgb3JhbmdlLCBhbmQgcmVkIGFyZSB0aGUgcmVsaWVmIGN1dG9mZnMgZm9yIGxvdywgbW9kZXJhdGUsIGFuZCBoaWdoIHJlbGllZiByZXNwZWN0aXZlbHkgYXMgcHJvcG9zZWQgYnkgU21pdGggZXQgYWwgKDIwMTEpIGluIHRoZWlyIHJlZWYgZmlzaCBzdXJ2ZXkgb2YgdGhlIEZsb3JpZGEgS2V5cy4gVGhpcyBhcHBlYXJzIHRvIG1hdGNoIHVwIGZhaXJseSB3ZWxsIHdpdGggb3VyIG9ic2VydmF0aW9ucywgc28gd2Ugd2lsbCB1c2UgdGhlc2UgY3V0b2ZmczoNCmxvdyByZWxpZWYgPD0gMW0gOyAxbSA8IG1vZGVyYXRlIHJlbGllZiA8PSAybTsgaGlnaCByZWxpZWYgPiAybS4NCg0KRmlndXJlIFMxLjEzDQoNCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTR9DQpvbmVfaHo8LSBvbmVfaHogJT4lIG11dGF0ZShUb3RhbF9EZXB0aD0gZGVwdGgrIGFsdGl0dWRlKmNvcyhyYWRpYW5zKHBpdGNoKSkpICNDYWxjdWxhdGUgVG90YWwgZGVwdGgNCg0Kb25lX2h6PC0gb25lX2h6ICU+JSBtdXRhdGUodmVydGljYWxfcmVsaWVmXzE1cyA9IE5BX3JlYWxfKQ0KZm9yIChpIGluIDg6KG5yb3cob25lX2h6KS03KSkgew0KICBjdXJyX2lkeDwtIChpLTcpOihpKzcpDQogIGlmKGxlbmd0aCh1bmlxdWUob25lX2h6JFRyYW5zZWN0W2N1cnJfaWR4XSkpIT0xKXsNCiAgICBuZXh0KCkgI1ByZXZlbnQgYXZlcmFnaW5nIGFjcm9zcyBkaWZmZXJlbnQgdHJhbnNlY3RzDQogICAgfQ0KICBkdmFsdWVzPC0gb25lX2h6JFRvdGFsX0RlcHRoW2N1cnJfaWR4XQ0KICBkbWluPC0gbWluKGR2YWx1ZXMsIG5hLnJtPVRSVUUpDQogIGRtYXg9IG1heChkdmFsdWVzLCBuYS5ybT1UUlVFKQ0KICB2cmVsaWVmPC0gZG1heC1kbWluDQogIGlmKGlzLmluZmluaXRlKHZyZWxpZWYpKXt2cmVsaWVmPC1OQX0NCiAgb25lX2h6JHZlcnRpY2FsX3JlbGllZl8xNXNbaV08LSB2cmVsaWVmDQp9DQoNCmhhYl9yZWxpZWY8LSBoYWIgJT4lIGxlZnRfam9pbihvbmVfaHosIGJ5PSBjKCJ0aW1lc3RhbXAiLCJUcmFuc2VjdCIpKSAlPiUgc2VsZWN0KHRpbWVzdGFtcCwgVHJhbnNlY3QsIFJlbGllZiwgdmVydGljYWxfcmVsaWVmXzE1cykgJT4lIGZpbHRlcihSZWxpZWYhPSJOb25lIiAmIFJlbGllZiAhPSAiTm9fVmlzIikNCmhhYl9yZWxpZWYkUmVsaWVmPC0gZmFjdG9yKGhhYl9yZWxpZWYkUmVsaWVmLCBsZXZlbHM9YygiTG93X1JlbGllZiIsICJNb2RlcmF0ZV9SZWxpZWYiLCAiSGlnaF9SZWxpZWYiKSkNCg0KdmlzdWFsX3JlbGllZl9wbG90PC0gZ2dwbG90KGRhdGEgPSBoYWJfcmVsaWVmLCBtYXBwaW5nID0gYWVzKHg9IFJlbGllZiwgeT12ZXJ0aWNhbF9yZWxpZWZfMTVzKSkrDQogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsIHltaW4gPSAwLCB5bWF4ID0gMSwgZmlsbD0gImRvZGdlcmJsdWUiLCBhbHBoYT0uMikrDQogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsIHltaW4gPSAxLCB5bWF4ID0gMiwgZmlsbD0gIm9yYW5nZSIsIGFscGhhPS4yKSsNCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gLUluZiwgeG1heCA9IEluZiwgeW1pbiA9IDIsIHltYXggPSBJbmYsIGZpbGw9ICJyZWQiLCBhbHBoYT0uMikrDQogIGdlb21fYm94cGxvdCgpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDgsIGJ5PSAxKSwgZXhwYW5kID0gYygwLDApKSsNCiAgeWxhYigiVmVydGljYWwgUmVsaWVmIChtKSBvdmVyIDE1IHMiKSsNCiAgeGxhYigiUmVsaWVmIENsYXNzIikNCnZpc3VhbF9yZWxpZWZfcGxvdA0KYGBgDQoNClRoZXNlIHRocmVzaG9sZHMgYXJlIHRoZW4gdXNlZCB0byBkZWxpbmVhdGUgaGlnaGVyIHJlbGllZiBhcmVhcyBkaXJlY3RseSBmcm9tIHRoZSBiYXRoeW1ldHJ5IGJ5IGNhbGN1bGF0aW5nIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gYSBjZW50cmFsIHBpeGVsIGFuZCB0aGUgbWluaW11bSBkZXB0aCBvZiBzdXJyb3VuZGluZyBwaXhlbHMgdXNpbmcgYSBzbGlkaW5nIDN4MyB3aW5kb3cuDQoNCkZpZ3VyZSBTMS4xNA0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFfQ0KdzwtIG1hdHJpeChkYXRhID0gMSwgbnJvdyA9IDMsbmNvbCA9IDMpICMzeDMgd2luZG93DQp3WzVdPC0gTkENCm1pbl9iYXRoeTwtIGZvY2FsKHggPSBiYXRoeSwgdz13LCBmdW49bWluLCBuYS5ybT1UUlVFKSAjQ2FsY3VsYXRlIG1pbmltdW0gZGVwdGggYXJvdW5kIGEgY2VudHJhbCBwaXhlbA0KbWluX2JhdGh5W2lzLmluZmluaXRlKG1pbl9iYXRoeSldPC0gTkEgI1JlcGxhY2UgSW5mIHdpdGggTkENCnJlbGllZjwtIGJhdGh5LW1pbl9iYXRoeSAjQ2FsY3VsYXRlIHZlcnRpY2FsIHJlbGllZg0KDQpyZWxpZWZfcXJ1bGVzPC0gbWF0cml4KGMoLUluZiwxLDIsIDEsIDIsIEluZiwgMSwyLDMpLCBucm93ID0gMyxuY29sID0gMykNCnJlbGllZl9jbGFzc2lmaWVkPC0gcmFzdGVyOjpyZWNsYXNzaWZ5KHJlbGllZiwgcmVsaWVmX3FydWxlcywgaW5jbHVkZS5sb3dlc3Q9RkFMU0UsIHJpZ2h0PVRSVUUpDQpyZWxpZWZfY2xhc3NpZmllZDwtIGFzLmZhY3RvcihyZWxpZWZfY2xhc3NpZmllZCkNCmxldmVscyhyZWxpZWZfY2xhc3NpZmllZClbWzFdXSRSZWxpZWZfQ2xhc3M8LSBjKCJMb3ciLCJNb2QiLCAiSGlnaCIpDQpgYGANCg0KYGBge3IgaW5jbHVkZT0gRkFMU0V9DQp3cml0ZVJhc3RlcihtaW5fYmF0aHksICJEYXRhL2Rlcml2ZWQvTXVsdGliZWFtL21pbl9iYXRoeS5ncmQiLCBvdmVyd3JpdGU9VFJVRSkNCm1pbl9iYXRoeTwtIHJhc3RlcigiRGF0YS9kZXJpdmVkL011bHRpYmVhbS9taW5fYmF0aHkuZ3JkIikNCndyaXRlUmFzdGVyKHJlbGllZiwgIkRhdGEvZGVyaXZlZC9NdWx0aWJlYW0vcmVsaWVmLmdyZCIsIG92ZXJ3cml0ZT1UUlVFKQ0KcmVsaWVmPC0gcmFzdGVyKCJEYXRhL2Rlcml2ZWQvTXVsdGliZWFtL3JlbGllZi5ncmQiKQ0Kd3JpdGVSYXN0ZXIocmVsaWVmX2NsYXNzaWZpZWQsICJEYXRhL2Rlcml2ZWQvTXVsdGliZWFtL3JlbGllZl9jbGFzc2lmaWVkLmdyZCIsb3ZlcndyaXRlPVRSVUUpDQpyZWxpZWZfY2xhc3NpZmllZDwtIHJhc3RlcigiRGF0YS9kZXJpdmVkL011bHRpYmVhbS9yZWxpZWZfY2xhc3NpZmllZC5ncmQiKQ0KYGBgDQoNCmBgYHtyIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTh9DQpSZWxpZWZfTWFwX1Bsb3Q8LSB0bV9zaGFwZShyZWxpZWYsIHJhc3Rlci5kb3duc2FtcGxlID0gRkFMU0UpKw0KICB0bV9yYXN0ZXIocGFsZXR0ZT1wYWwxLCBtaWRwb2ludCA9IE5BLCBzdHlsZT0iY29udCIsIHRpdGxlID0gIlJlbGllZiAobSkiKSsNCiAgIHRtX2dyYXRpY3VsZXMobGluZXM9RkFMU0UpDQpSZWxpZWZfQ2xhc3NpZmllZF9QbG90PC0gdG1fc2hhcGUoc3RfYXNfc3RhcnMocmVsaWVmX2NsYXNzaWZpZWQsIGlnbm9yZV9maWxlPVRSVUUpLCByYXN0ZXIuZG93bnNhbXBsZSA9IEZBTFNFKSsNCiAgdG1fcmFzdGVyKHBhbGV0dGU9YygiZ3JheSIsICJ5ZWxsb3ciLCAicmVkIiksIHRpdGxlID0gIlJlbGllZiBDbGFzcyIpKw0KICAgdG1fZ3JhdGljdWxlcyhsaW5lcz1GQUxTRSkNCnRtYXBfYXJyYW5nZShSZWxpZWZfTWFwX1Bsb3QsIFJlbGllZl9DbGFzc2lmaWVkX1Bsb3QpDQpgYGANCg0KDQpGaWd1cmUgUzEuMTUNCmBgYHtyIH0NCnN1Yl9yZWxpZWY8LSAoc3VwX2hhYioxMCkrcmVsaWVmX2NsYXNzaWZpZWQNCnN1Yl9yZWxpZWZbc3ViX3JlbGllZj09MjJdPC0yMQ0Kc3ViX3JlbGllZltzdWJfcmVsaWVmPT0yM108LTIxICNDb2xsYXBzZSBzYW5kIHRvIG9uZSBjYXRlZ29yeQ0Kc3ViX3JlbGllZjwtIGFzLmZhY3RvcihzdWJfcmVsaWVmKQ0KbmFtZXMoc3ViX3JlbGllZik8LSAiSGFiaXRhdCINCmxldmVscyhzdWJfcmVsaWVmKVtbMV1dJGhhYml0YXQ8LSAgYygiTFIgUm9jayIsICJNUiBSb2NrIiwgIkhSIFJvY2siLCAiU2FuZCIpDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCndyaXRlUmFzdGVyKHN1Yl9yZWxpZWYsIGZpbGVuYW1lID0gIlByb2R1Y3RzL01hcHBpbmcvRWxib3dfU3VwZXJ2aXNlZF9IYWJSZWxpZWYudGlmIiwgb3ZlcndyaXRlPVRSVUUpDQp3cml0ZVJhc3RlcihzdWJfcmVsaWVmLCBmaWxlbmFtZSA9ICJQcm9kdWN0cy9NYXBwaW5nL0VsYm93X1N1cGVydmlzZWRfSGFiUmVsaWVmLmdyZCIsIG92ZXJ3cml0ZT1UUlVFKQ0Kc3ViX3JlbGllZjwtIHJhc3RlcigiUHJvZHVjdHMvTWFwcGluZy9FbGJvd19TdXBlcnZpc2VkX0hhYlJlbGllZi5ncmQiKQ0KYGBgDQoNCmBgYHtyfQ0Kc3ViX3JlbGllZl9wbG90PC0gdG1fc2hhcGUoZHJvcGxldmVscyhzdF9hc19zdGFycyhzdWJfcmVsaWVmLCBpZ25vcmVfZmlsZT1UUlVFKSwgZXhjbHVkZT1OQSksIHJhc3Rlci5kb3duc2FtcGxlID0gRkFMU0UpKw0KICB0bV9yYXN0ZXIocGFsZXR0ZSA9IGMoImRvZGdlcmJsdWUiLCAib3JhbmdlIiwgInJlZCIsICIjRkZFQkJFIikpKw0KICAgdG1fZ3JhdGljdWxlcyhsaW5lcz1GQUxTRSkNCnN1Yl9yZWxpZWZfcGxvdA0KYGBgDQoNCg0KYGBge3IgZWNobz1GQUxTRX0NCmhhYl9hcmVhPC0gYXMuZGF0YS5mcmFtZShmcmVxKHN1Yl9yZWxpZWYsIHVzZU5BPSJubyIsIG1lcmdlPVRSVUUpKQ0KaGFiX2FyZWEkaGFiaXRhdDwtIGMoIkxSX1JvY2siLCAiTVJfUm9jayIsICJIUl9Sb2NrIiwgIlNhbmQiKQ0KaGFiX2FyZWE8LSBoYWJfYXJlYSAlPiUgbXV0YXRlKEFyZWFfbTI9IGNvdW50KihyZXMoYWxsX29mKHN1Yl9yZWxpZWYpKVsxXSkqKHJlcyhhbGxfb2Yoc3ViX3JlbGllZikpWzJdKSkNCmhhYl9hcmVhPC0gaGFiX2FyZWEgJT4lIG11dGF0ZShBcmVhX2ttMj1BcmVhX20yLzFlNikNCmhhYl9hcmVhPC0gaGFiX2FyZWEgJT4lIG11dGF0ZShBcmVhX3BlcmNlbnQ9MTAwKkFyZWFfa20yL3N1bShBcmVhX2ttMikpDQpoYWJfYXJlYSAlPiUgc2VsZWN0KGhhYml0YXQsIEFyZWFfa20yLCBBcmVhX3BlcmNlbnQpICU+JSBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCAuZm5zPXJvdW5kLCAyKSkNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0Kc2F2ZS5pbWFnZShmaWxlID0gJ0RhdGEvUl9lbnZpcm9ubWVudC9FbGJvd19SX01hcHBpbmdfRW52aXJvbm1lbnQuUkRhdGEnKQ0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQp0bWFwX3NhdmUodG09Z3RydXRoX3Bsb3QsDQogICAgICAgICAgZmlsZW5hbWUgPSAiUHJvZHVjdHMvZmlndXJlcy9ndHJ1dGhfcGxvdC50aWZmIiwNCiAgICAgICAgICB3aWR0aD04LA0KICAgICAgICAgIGhlaWdodCA9IDgsDQogICAgICAgICAgdW5pdHM9ImluIiwNCiAgICAgICAgICBkcGk9MzAwKQ0KDQp0bWFwX3NhdmUodG09c3VwX3JldGFpbmVkX3Zhcl9wbG90LA0KICAgICAgICAgIGZpbGVuYW1lID0gIlByb2R1Y3RzL2ZpZ3VyZXMvc3VwX3JldGFpbmVkX3Zhcl9wbG90LnRpZmYiLA0KICAgICAgICAgIHdpZHRoPTcsDQogICAgICAgICAgaGVpZ2h0ID0gOCwNCiAgICAgICAgICB1bml0cz0iaW4iLA0KICAgICAgICAgIGRwaT0zMDApDQoNCnRtYXBfc2F2ZSh0bT0gdG1hcF9hcnJhbmdlKHN1cF9zdWJfcGxvdCwgc3VwX2VudF9wbG90KSwNCiAgICAgICAgICBmaWxlbmFtZSA9ICJQcm9kdWN0cy9maWd1cmVzL1N1cFN1YkVudC50aWZmIiwNCiAgICAgICAgICB3aWR0aD04LA0KICAgICAgICAgIGhlaWdodCA9IDgsDQogICAgICAgICAgdW5pdHM9ImluIiwNCiAgICAgICAgICBkcGk9MzAwKQ0KDQpnZ3NhdmUoZmlsZW5hbWUgPSAidmFyX2ltcF9wbG90LnRpZmYiLA0KICAgICAgIHBsb3QgPSB2YXJfaW1wX3Bsb3QrdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNykpLCANCiAgICAgICBkZXZpY2UgPSAidGlmZiIsIA0KICAgICAgIHBhdGggPSAiUHJvZHVjdHMvZmlndXJlcyIsIA0KICAgICAgIHdpZHRoID0gNiwgDQogICAgICAgaGVpZ2h0ID0gNCwgDQogICAgICAgdW5pdHMgPSAiaW4iLCANCiAgICAgICBkcGkgPSAzMDApDQoNCmdnc2F2ZShmaWxlbmFtZSA9ICJlcnJfdnNfbnRyZWUudGlmZiIsDQogICAgICAgcGxvdCA9IGVycl92c19udHJlZSt0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3KSksIA0KICAgICAgIGRldmljZSA9ICJ0aWZmIiwgDQogICAgICAgcGF0aCA9ICJQcm9kdWN0cy9maWd1cmVzIiwgDQogICAgICAgd2lkdGggPSA2LCANCiAgICAgICBoZWlnaHQgPSA0LCANCiAgICAgICB1bml0cyA9ICJpbiIsIA0KICAgICAgIGRwaSA9IDMwMCkNCg0KZ2dzYXZlKGZpbGVuYW1lID0gIlBDQV92YXJfcGxvdC50aWZmIiwNCiAgICAgICBwbG90ID0gUENBX3Zhcl9wbG90K3RoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpKSAgLCANCiAgICAgICBkZXZpY2UgPSAidGlmZiIsIA0KICAgICAgIHBhdGggPSAiUHJvZHVjdHMvZmlndXJlcyIsIA0KICAgICAgIHdpZHRoID0gNiwgDQogICAgICAgaGVpZ2h0ID0gNCwgDQogICAgICAgdW5pdHMgPSAiaW4iLCANCiAgICAgICBkcGkgPSAzMDApDQoNCnRtYXBfc2F2ZSh0bT1yZXRfUENBX3Bsb3QsDQogICAgICAgICAgZmlsZW5hbWUgPSAiUHJvZHVjdHMvZmlndXJlcy9yZXRfUENBX3Bsb3QudGlmZiIsDQogICAgICAgICAgd2lkdGg9NiwNCiAgICAgICAgICBoZWlnaHQgPSA4LA0KICAgICAgICAgIHVuaXRzPSJpbiIsDQogICAgICAgICAgZHBpPTMwMCkNCg0KdG1hcF9zYXZlKHRtPXRtYXBfYXJyYW5nZSh1bnN1cF9jbHVzdGVyX3Bsb3QsdW5zdXBfc3ViX3Bsb3QpLA0KICAgICAgICAgIGZpbGVuYW1lID0gIlByb2R1Y3RzL2ZpZ3VyZXMvY2x1c3RfdW5zdXBfX3Bsb3QudGlmZiIsDQogICAgICAgICAgd2lkdGg9OCwNCiAgICAgICAgICBoZWlnaHQgPSA4LA0KICAgICAgICAgIHVuaXRzPSJpbiIsDQogICAgICAgICAgZHBpPTMwMCkNCg0KdG1hcF9zYXZlKHRtPWRpZmZfbWFwX3Bsb3QsDQogICAgICAgICAgZmlsZW5hbWUgPSAiUHJvZHVjdHMvZmlndXJlcy9kaWZmX21hcF9wbG90LnRpZmYiLA0KICAgICAgICAgIHdpZHRoPTYsDQogICAgICAgICAgaGVpZ2h0ID0gOCwNCiAgICAgICAgICB1bml0cz0iaW4iLA0KICAgICAgICAgIGRwaT0zMDApDQoNCnRtYXBfc2F2ZSh0bT10bWFwX2FycmFuZ2UoUmVsaWVmX01hcF9QbG90LCBSZWxpZWZfQ2xhc3NpZmllZF9QbG90KSwNCiAgICAgICAgICBmaWxlbmFtZSA9ICJQcm9kdWN0cy9maWd1cmVzL3JlbGllZl9tYXBfcGxvdC50aWZmIiwNCiAgICAgICAgICB3aWR0aD04LA0KICAgICAgICAgIGhlaWdodCA9IDgsDQogICAgICAgICAgdW5pdHM9ImluIiwNCiAgICAgICAgICBkcGk9MzAwKQ0KDQp0bWFwX3NhdmUodG09c3ViX3JlbGllZl9wbG90LA0KICAgICAgICAgIGZpbGVuYW1lID0gIlByb2R1Y3RzL2ZpZ3VyZXMvc3ViX3JlbGllZl9wbG90LnRpZmYiLA0KICAgICAgICAgIHdpZHRoPTYsDQogICAgICAgICAgaGVpZ2h0ID0gOCwNCiAgICAgICAgICB1bml0cz0iaW4iLA0KICAgICAgICAgIGRwaT0zMDApDQoNCmdnc2F2ZShmaWxlbmFtZSA9ICJ2aXN1YWxfcmVsaWVmX3Bsb3QudGlmZiIsDQogICAgICAgcGxvdCA9IHZpc3VhbF9yZWxpZWZfcGxvdCwgDQogICAgICAgZGV2aWNlID0gInRpZmYiLCANCiAgICAgICBwYXRoID0gIlByb2R1Y3RzL2ZpZ3VyZXMiLCANCiAgICAgICB3aWR0aCA9IDYsIA0KICAgICAgIGhlaWdodCA9IDYsIA0KICAgICAgIHVuaXRzID0gImluIiwgDQogICAgICAgZHBpID0gMzAwKQ0KYGBgDQoNCg==