Our main question of
interest
The data structure hs_macr contains our primary macrophages, which
are, as shown above, the data we can really sink our teeth into.
Note, we expect some errors when running the combine_de_tables()
because not all methods I use are comfortable using the ratio or ratios
contrasts we added in the ‘extras’ argument. As a result, when we
combine them into the larger output tables, those peculiar contrasts
fail. This does not stop it from writing the rest of the results,
however.
#test = deseq_pairwise(normalize_se(hs_macr, filter=TRUE),
# model_svs = "svaseq", filter = TRUE,
# extra_contrasts = tmrc2_human_extra)
hs_macr_de_noextra <- all_pairwise(hs_macr, model_svs = "svaseq",
model_fstring = "~ 0 + condition", filter = TRUE)
## inf_sb_z22 inf_sb_z23 inf_z22 inf_z23 uninf_none
## 12 11 11 12 4
## uninf_sb_none
## 4
## Running normalize_se.
## Removing 9725 low-count genes (11756 remaining).
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## I think this is failing? SummarizedExperiment
## Basic step 0/3: Transforming data.
## Running normalize_se.
## Setting 40036 entries to zero.
## This received a matrix of SVs.
## converting counts to integer mode
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## Warning in createContrastL(objFlt$formula, objFlt$data, L): Contrasts with only
## a single non-zero term are already evaluated by default.
## conditions
## inf_sb_z22 inf_sb_z23 inf_z22 inf_z23 uninf_none
## 12 11 11 12 4
## uninf_sb_none
## 4
## conditions
## inf_sb_z22 inf_sb_z23 inf_z22 inf_z23 uninf_none
## 12 11 11 12 4
## uninf_sb_none
## 4
## conditions
## inf_sb_z22 inf_sb_z23 inf_z22 inf_z23 uninf_none
## 12 11 11 12 4
## uninf_sb_none
## 4

hs_macr_de <- all_pairwise(hs_macr, model_svs = "svaseq", model_fstring = "~ 0 + condition",
filter = TRUE, extra_contrasts = tmrc2_human_extra)
## inf_sb_z22 inf_sb_z23 inf_z22 inf_z23 uninf_none
## 12 11 11 12 4
## uninf_sb_none
## 4
## Running normalize_se.
## Removing 9725 low-count genes (11756 remaining).
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## I think this is failing? SummarizedExperiment
## Basic step 0/3: Transforming data.
## Running normalize_se.
## Setting 40036 entries to zero.
## This received a matrix of SVs.
## converting counts to integer mode
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## The contrast z23drugnodrug is not in the results.
## If this is not an extra contrast, then this is an error.
## The contrast z23z22drug is not in the results.
## If this is not an extra contrast, then this is an error.
## Warning in createContrastL(objFlt$formula, objFlt$data, L): Contrasts with only
## a single non-zero term are already evaluated by default.
## conditions
## inf_sb_z22 inf_sb_z23 inf_z22 inf_z23 uninf_none
## 12 11 11 12 4
## uninf_sb_none
## 4
## conditions
## inf_sb_z22 inf_sb_z23 inf_z22 inf_z23 uninf_none
## 12 11 11 12 4
## uninf_sb_none
## 4
## conditions
## inf_sb_z22 inf_sb_z23 inf_z22 inf_z23 uninf_none
## 12 11 11 12 4
## uninf_sb_none
## 4
## A pairwise differential expression with results from: basic, deseq, ebseq, edger, limma, noiseq.
## This used a surrogate/batch estimate from: svaseq.
## The primary analysis performed 15 comparisons.
hs_single_table <- combine_de_tables(
hs_macr_de, keepers = single_tmrc2_keeper,
excel = glue("analyses/macrophage_de/de_tables/hs_macr_drug_zymo_z22sb_sb-v{ver}.xlsx"))
hs_single_table
## A set of combined differential expression results.
## table deseq_sigup deseq_sigdown edger_sigup
## 1 uninf_sb_none_vs_inf_sb_z22-inverted 33 0 32
## edger_sigdown limma_sigup limma_sigdown
## 1 0 2 0
## Only z22sb_vs_sb_up has information, cannot create an UpSet.
## Plot describing unique/shared genes in a differential expression table.
## NULL
hs_macr_table <- combine_de_tables(
hs_macr_de, keepers = tmrc2_human_keepers,
excel = glue("analyses/macrophage_de/de_tables/hs_macr_drug_zymo_table_macr_only-v{ver}.xlsx"))
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_z2322 using basic does not appear in the pairwise data.
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_z2322 using ebseq does not appear in the pairwise data.
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_z2322 using noiseq does not appear in the pairwise data.
## Error : subscript contains invalid names
## coefficient limma did not find z22drugnodrug or z23drugnodrug.
## coefficient edger did not find conditionz22drugnodrug or conditionz23drugnodrug.
## coefficient limma did not find z22drugnodrug or z23drugnodrug.
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_drugnodrug using basic does not appear in the pairwise
## data.
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_drugnodrug using ebseq does not appear in the pairwise
## data.
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_drugnodrug using noiseq does not appear in the pairwise
## data.
## Error : subscript contains invalid names
## coefficient limma did not find z23z22nodrug or z23z22drug.
## coefficient edger did not find conditionz23z22nodrug or conditionz23z22drug.
## coefficient limma did not find z23z22nodrug or z23z22drug.
## A set of combined differential expression results.
## table deseq_sigup deseq_sigdown edger_sigup
## 1 uninf_none_vs_inf_z23-inverted 478 265 470
## 2 uninf_none_vs_inf_z22-inverted 359 6 340
## 3 inf_z23_vs_inf_z22 349 539 359
## 4 inf_sb_z23_vs_inf_sb_z22 343 252 339
## 5 inf_z23_vs_inf_sb_z23-inverted 619 828 625
## 6 inf_z22_vs_inf_sb_z22-inverted 505 1040 520
## 7 uninf_sb_none_vs_inf_sb_z23-inverted 461 247 461
## 8 uninf_sb_none_vs_inf_sb_z22-inverted 33 0 32
## 9 uninf_none_vs_inf_sb_z23-inverted 839 923 854
## 10 uninf_none_vs_inf_sb_z22-inverted 660 746 672
## 11 uninf_sb_none_vs_uninf_none 561 748 563
## 12 FALSE 0 0 329
## 13 FALSE 0 0 329
## edger_sigdown limma_sigup limma_sigdown
## 1 270 392 251
## 2 6 264 71
## 3 528 450 390
## 4 253 377 215
## 5 821 571 746
## 6 1009 671 925
## 7 249 374 232
## 8 0 2 0
## 9 906 805 914
## 10 733 555 744
## 11 742 513 696
## 12 63 243 135
## 13 63 243 135
## Plot describing unique/shared genes in a differential expression table.

#combined_to_tsv(hs_macr_table, "macrophage")
hs_macr_sig <- extract_significant_genes(
hs_macr_table,
excel = glue("analyses/macrophage_de/sig_tables/hs_macr_drug_zymo_sig-v{ver}.xlsx"))
## There is no deseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no deseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no ebseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no ebseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no basic_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no basic_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
## limma_up limma_down edger_up edger_down deseq_up deseq_down
## z23nosb_vs_uninf 392 251 470 270 478 265
## z22nosb_vs_uninf 264 71 340 6 359 6
## z23nosb_vs_z22nosb 450 390 359 528 349 539
## z23sb_vs_z22sb 377 215 339 253 343 252
## z23sb_vs_z23nosb 571 746 625 821 619 828
## z22sb_vs_z22nosb 671 925 520 1009 505 1040
## z23sb_vs_sb 374 232 461 249 461 247
## z22sb_vs_sb 2 0 32 0 33 0
## z23sb_vs_uninf 805 914 854 906 839 923
## z22sb_vs_uninf 555 744 672 733 660 746
## sb_vs_uninf 513 696 563 742 561 748
## extra_z2322 243 135 329 63 0 0
## extra_drugnodrug 243 135 329 63 0 0
## ebseq_up ebseq_down basic_up basic_down
## z23nosb_vs_uninf 111 112 0 0
## z22nosb_vs_uninf 160 2 0 0
## z23nosb_vs_z22nosb 257 408 281 259
## z23sb_vs_z22sb 106 108 117 44
## z23sb_vs_z23nosb 412 699 371 540
## z22sb_vs_z22nosb 458 886 437 680
## z23sb_vs_sb 33 58 0 0
## z22sb_vs_sb 25 0 0 0
## z23sb_vs_uninf 280 767 350 489
## z22sb_vs_uninf 444 551 276 396
## sb_vs_uninf 316 495 0 0
## extra_z2322 0 0 0 0
## extra_drugnodrug 0 0 0 0

hs_macr_highsig <- extract_significant_genes(
hs_macr_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
excel = glue("analyses/macrophage_de/sig_tables/hs_macr_drug_zymo_highsig-v{ver}.xlsx"))
## Warning in get_sig_genes(this_table, lfc = lfc, p = p, z = z, n = n, column =
## this_fc_column, : The column deseq_basemean does not appears to be in the
## table, cannot filter by expression.
## Warning in get_sig_genes(this_table, lfc = lfc, p = p, z = z, n = n, column =
## this_fc_column, : The column deseq_basemean does not appears to be in the
## table, cannot filter by expression.
## Warning in get_sig_genes(this_table, lfc = lfc, p = p, z = z, n = n, column =
## this_fc_column, : The column deseq_basemean does not appears to be in the
## table, cannot filter by expression.
## Warning in get_sig_genes(this_table, lfc = lfc, p = p, z = z, n = n, column =
## this_fc_column, : The column deseq_basemean does not appears to be in the
## table, cannot filter by expression.
## There is no deseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no deseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no ebseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no ebseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no basic_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no basic_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
## limma_up limma_down edger_up edger_down deseq_up deseq_down
## z23nosb_vs_uninf 269 139 317 139 314 138
## z22nosb_vs_uninf 103 4 110 0 115 0
## z23nosb_vs_z22nosb 221 154 247 174 238 178
## z23sb_vs_z22sb 211 105 210 86 211 84
## z23sb_vs_z23nosb 305 482 306 566 303 570
## z22sb_vs_z22nosb 330 545 301 572 288 598
## z23sb_vs_sb 250 130 278 140 274 140
## z22sb_vs_sb 2 0 9 0 13 0
## z23sb_vs_uninf 499 603 491 605 482 618
## z22sb_vs_uninf 310 479 318 501 303 513
## sb_vs_uninf 291 459 294 495 291 498
## extra_z2322 243 135 329 63 0 0
## extra_drugnodrug 243 135 329 63 0 0
## ebseq_up ebseq_down basic_up basic_down
## z23nosb_vs_uninf 87 64 0 0
## z22nosb_vs_uninf 41 0 0 0
## z23nosb_vs_z22nosb 207 140 214 169
## z23sb_vs_z22sb 80 37 99 35
## z23sb_vs_z23nosb 212 529 293 465
## z22sb_vs_z22nosb 276 519 326 540
## z23sb_vs_sb 21 28 0 0
## z22sb_vs_sb 5 0 0 0
## z23sb_vs_uninf 177 550 295 401
## z22sb_vs_uninf 235 393 216 321
## sb_vs_uninf 191 352 0 0
## extra_z2322 0 0 0 0
## extra_drugnodrug 0 0 0 0

hs_macr_lesssig <- extract_significant_genes(
hs_macr_table, lfc = 0.6,
excel = glue("analyses/macrophage_de/sig_tables/hs_macr_drug_zymo_sig_lfc0.6-v{ver}.xlsx"))
## There is no deseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no deseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no ebseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no ebseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no basic_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no basic_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 0.6 adj P cutoff: 0.05
## limma_up limma_down edger_up edger_down deseq_up deseq_down
## z23nosb_vs_uninf 701 587 856 594 865 587
## z22nosb_vs_uninf 378 128 464 21 505 22
## z23nosb_vs_z22nosb 867 786 746 964 728 981
## z23sb_vs_z22sb 670 587 649 645 655 641
## z23sb_vs_z23nosb 1237 1395 1297 1536 1279 1545
## z22sb_vs_z22nosb 1492 1542 1287 1692 1211 1747
## z23sb_vs_sb 622 643 761 610 772 614
## z22sb_vs_sb 2 0 33 0 34 0
## z23sb_vs_uninf 1516 1656 1595 1671 1557 1700
## z22sb_vs_uninf 1127 1297 1246 1293 1222 1340
## sb_vs_uninf 1037 1148 1055 1262 1042 1291
## extra_z2322 381 288 482 210 0 0
## extra_drugnodrug 381 288 482 210 0 0
## ebseq_up ebseq_down basic_up basic_down
## z23nosb_vs_uninf 141 196 0 0
## z22nosb_vs_uninf 186 4 0 0
## z23nosb_vs_z22nosb 463 602 593 580
## z23sb_vs_z22sb 144 237 193 144
## z23sb_vs_z23nosb 774 1166 1016 1047
## z22sb_vs_z22nosb 1044 1349 1228 1264
## z23sb_vs_sb 39 115 0 0
## z22sb_vs_sb 30 0 0 0
## z23sb_vs_uninf 458 1259 665 812
## z22sb_vs_uninf 746 907 535 686
## sb_vs_uninf 495 788 0 0
## extra_z2322 0 0 0 0
## extra_drugnodrug 0 0 0 0

gene group upset
2.3 vs 2.2 up and
down vs. uninfected
This is my version of the Venn diagram which includes the text:
“Differentially expressed genes in macrophages infected with
subpopulations 2.2 or 2.3. Volcano plots contrast of: A. Venn diagram
for upregulated and downregulated genes by infection with 2.3 and 2.2
strains. B. infected cells with 2.3 strains and uninfected cells; C.
infected cells with 2.2 strains and uninfected cells; D. infected cells
with 2.3 strains and infected cells with 2.2 strains”
The following upset plot is currently Figure 2E.
nodrug_upset <- upsetr_combined_de(hs_macr_table,
desired_contrasts = c("z22nosb_vs_uninf", "z23nosb_vs_uninf"))
pp(file = "images/nodrug_upset.svg")
nodrug_upset[["plot"]]
dev.off()
## png
## 2
## Plot describing unique/shared genes in a differential expression table.

A point of
interest while Olga visits Umd
Najib and Olga asked about pulling the 9 gene IDs which are in the
peculiar situation of increased expression in z2.2/uninf and decreased
in z2.3/uninf. In the previous upset plot, these are visible in the 6th
bar. I can access these via the attr() function, which I should admit I
can never remember how to use, so I am going to use the code under the
‘Compare(no)Sb z2.3/z2.2 treatment’ heading to remember how to extract
these genes.
all_groups <- nodrug_upset[["groups"]]
wanted_group <- "z23nosb_vs_uninf_down:z22nosb_vs_uninf_up"
gene_idx <- all_groups[[wanted_group]]
wanted_genes <- attr(all_groups, "elements")[gene_idx]
wanted_genes
## [1] "ENSG00000004846" "ENSG00000111783" "ENSG00000118298" "ENSG00000120738"
## [5] "ENSG00000126217" "ENSG00000163687" "ENSG00000170345" "ENSG00000244242"
## [9] "ENSG00000277481"
gene_symbol_idx <- rownames(fData(hs_macr)) %in% as.character(wanted_genes)
fData(hs_macr)[gene_symbol_idx, "hgnc_symbol"]
## [1] "ABCB5" "RFX4" "CA14" "EGR1" "MCF2L" "DNASE1L3" "FOS"
## [8] "IFITM10" "PKD1L3"
- ABCB5: ATB Binding Cassette Subfamily B Member #5, wide range of
functions in this diverse paralogous family. Associated with skin
diseases (melanoma and Epidermolysis Bullosa; participate in
ATP-dependent transmembrane transport).
- RFX4: Regulatory Factor X #4: transcription factor.
- CA14: Carbonic anhydrase #14: Zync metalloenzyme catalyzes
reversible hydration of CO2. This gene looks pretty neat, but not really
relevant to anything we are likely to care about.
- EGR1: Early Growth Response Protein #1: Another Tx factor
(zinc-finger) – important for cell survival/proliferation/cell death.
Presumably important for healing?
- MCF2L: MCF.2 Cell Line Derived Transforming Sequence Like? guanine
nucleotide exchange factor interacting with GTP-bound Rac1. Apparently
associated with ostroarthritis; potentially relevant to regulation of
RHOA and CDC42 signalling.
- DNASE1L3: Deoxyribonuclease I family member: not inhibited by actin,
breaks down DNA during apoptosis. Important during necrosis.
- FOS: Proto-Oncogene, AP-1 Transcription Factor: leucine zipper
dimerizes with JUN family proteins, forming tx factor complex AP-1.
Important for cell proliferation, differentiation, and
transformation.
- IFITM10: Interferon-Induced Transmembrane Protein #10
- PKD1L3: Polycystin 1 Like #3, Transient Receptor Potential Channel
Interacting: 11 transmembrane domain protein which might help create
cation channels.
As some comparison points, the Venn in the current figure has:
- 387 up z2.3
- 259 up z2.2
- 83 shared up z2.3 and z2.2
- 247 down z2.3
- 3 down z2.2
- 3 shared down z2.3 and z2.2
2.2 and 2.3 with
SbV vs 2.2 and 2.3 without SbV
This is my version of the Venn with the text:
“Differentially expressed genes in macrophages infected with
subpopulations 2.2 or 2.3, in presence of SbV. Volcano plots contrast
of: A. infected cells with 2.3 strains + SbV and infected cells with 2.3
strains; B. infected cells with 2.2 strains + SbV and infected cells
with 2.2 strains; C. infected cells with 2.3 strains + SbV and infected
cells with 2.2 strains + SbV. D. Venn diagram for upregulated and
downregulated genes by infection with 2.3+SbV and 2.2+SbV strains.”
A query from Olga (20240801): Please include in the upset in figure 3
the contrast of uninfected cells + SbV vs uninfected without SbV.
## I keep mis-interpreting this text, it is z2.3/z2.3SbV and z2.2/z2.2SbV
drugnodrug_upset <- upsetr_combined_de(hs_macr_table,
desired_contrasts = c("z23sb_vs_z23nosb", "z22sb_vs_z22nosb"))
pp(file = "images/drugnodrug_upset.pdf")
drugnodrug_upset[["plot"]]
dev.off()
## png
## 2
## Plot describing unique/shared genes in a differential expression table.

drugnodrug_uninf_contrasts <- c("z23sb_vs_z23nosb", "z22sb_vs_z22nosb", "sb_vs_uninf")
drugnodrug_upset_with_uninf <- upsetr_combined_de(hs_macr_table,
desired_contrasts = drugnodrug_uninf_contrasts)
pp(file = "figures/drugnodrug_with_uninf_upset.svg")
drugnodrug_upset_with_uninf[["plot"]]
dev.off()
## png
## 2
drugnodrug_upset_with_uninf
## Plot describing unique/shared genes in a differential expression table.

For some comparison points, the venn image has:
- 222 up z2.3 SbV
- 134 up z2.2 SbV
- 182 down z2.3 SbV
- 396 down z2.2 SbV
- 605 shared down z2.2 and z2.3 SbV
- 34 shared down z2.2 SbV and up z2.3 SbV
- 363 shared up z2.2 SbV and z2.3 SbV
Compare z2.2SbV vs
SbV and z2.3SbV and SbV
drug_upset <- upsetr_combined_de(hs_macr_table,
desired_contrasts = c("z22sb_vs_sb", "z23sb_vs_sb"))
pp(file = "images/drug_upset.pdf")
drug_upset[["plot"]]
dev.off()
## png
## 2
## Plot describing unique/shared genes in a differential expression table.

Significance barplot
of interest
Olga kindly sent a set of particularly interesting contrasts and
colors for a significance barplot, they include the following:
- z2.3 vs. uninfected.
- z2.2 vs. uninfected.
- z2.3 vs z2.2
- z2.3Sbv vs z2.3
- z2.2Sbv vs z2.2
- z2.3Sbv vs z2.2Sbv
- Sbv vs uninfected.
The existing set of ‘keepers’ exvised to these is taken from the
extant set of ‘tmrc2_human_keepers’ and is as follows:
barplot_keepers <- list(
## z2.3 vs uninfected
"z23nosb_vs_uninf" = c("infz23", "uninfnone"),
## z2.2 vs uninfected
"z22nosb_vs_uninf" = c("infz22", "uninfnone"),
## z2.3 vs z2.2
"z23nosb_vs_z22nosb" = c("infz23", "infz22"),
## z2.3Sbv vs z2.3
"z23sb_vs_z23nosb" = c("infsbz23", "infz23"),
## z2.2Sbv vs z2.2
"z22sb_vs_z22nosb" = c("infsbz22", "infz22"),
## z2.3Sbv vs z2.2Sbv
"z23sb_vs_z22sb" = c("infsbz23", "infsbz22"),
## Sbv vs uninfected.
"sb_vs_uninf" = c("uninfsbnone", "uninfnone"))
barplot_combined <- combine_de_tables(
hs_macr_de, keepers = barplot_keepers,
excel = glue("analyses/macrophage_de/de_tables/hs_macr_drug_zymo_7contrasts-v{ver}.xlsx"))
## The keepers has no elements in the coefficients.
## Here are the keepers: infz23, uninfnone, infz22, uninfnone, infz23, infz22, infsbz23, infz23, infsbz22, infz22, infsbz23, infsbz22, uninfsbnone, uninfnone
## Here are the coefficients: uninf_sb_none, uninf_none, uninf_sb_none, inf_z23, uninf_none, inf_z23, uninf_sb_none, inf_z22, uninf_none, inf_z22, inf_z23, inf_z22, uninf_sb_none, inf_sb_z23, uninf_none, inf_sb_z23, inf_z23, inf_sb_z23, inf_z22, inf_sb_z23, uninf_sb_none, inf_sb_z22, uninf_none, inf_sb_z22, inf_z23, inf_sb_z22, inf_z22, inf_sb_z22, inf_sb_z23, inf_sb_z22
## Error in extract_keepers(extracted, keepers, table_names, all_coefficients, : Unable to find the set of contrasts to keep, fix this and try again.
Now let us use the colors suggested by Olga to make a barplot of
these…
color_list <- c( "#de8bf9", "#ad07e3","#410257", "#ffa0a0", "#f94040", "#a00000")
barplot_sig <- extract_significant_genes(
barplot_combined, color_list = color_list, according_to = "deseq",
excel = glue("analyses/macrophage_de/sig_tables/hs_macr_drug_zymo_7contrasts_sig-v{ver}.xlsx"))
## Error: object 'barplot_combined' not found
## Error: object 'barplot_sig' not found
LS0tCnRpdGxlOiAiVE1SQzIgYHIgU3lzLmdldGVudignVkVSU0lPTicpYDogTWFjcm9waGFnZSBEaWZmZXJlbnRpYWwgRXhwcmVzc2lvbi4iCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICB0aGVtZTogcmVhZGFibGUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KYm9keSAubWFpbi1jb250YWluZXIgewogIG1heC13aWR0aDogMTYwMHB4Owp9CmJvZHksIHRkIHsKICBmb250LXNpemU6IDE2cHg7Cn0KY29kZS5yewogIGZvbnQtc2l6ZTogMTZweDsKfQpwcmUgewogIGZvbnQtc2l6ZTogMTZweAp9Cjwvc3R5bGU+CgpgYGB7ciBvcHRpb25zLCBpbmNsdWRlID0gRkFMU0V9CmxpYnJhcnkoZ2dicmVhaykKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdsdWUpCmxpYnJhcnkoSGVhdHBsdXMpCmxpYnJhcnkoaHBnbHRvb2xzKQpsaWJyYXJ5KFVwU2V0UikKbGlicmFyeSh0aWJibGUpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZW5yaWNocGxvdCkKbGlicmFyeShnZ3N0YXRzcGxvdCkKCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHByb2dyZXNzID0gVFJVRSwgdmVyYm9zZSA9IFRSVUUsIHdpZHRoID0gOTAsIGVjaG8gPSBUUlVFKQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZXJyb3IgPSBUUlVFLCBmaWcud2lkdGggPSA4LCBmaWcuaGVpZ2h0ID0gOCwgZmlnLnJldGluYSA9IDIsCiAgb3V0LndpZHRoID0gIjEwMCUiLCBkZXYgPSAicG5nIiwKICBkZXYuYXJncyA9IGxpc3QocG5nID0gbGlzdCh0eXBlID0gImNhaXJvLXBuZyIpKSkKb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHMgPSA0LCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbCA9ICJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMikpCnZlciA8LSBTeXMuZ2V0ZW52KCJWRVJTSU9OIikKcHJldmlvdXNfZmlsZSA8LSAiIgpydW5kYXRlIDwtIGZvcm1hdChTeXMuRGF0ZSgpLCBmb3JtYXQgPSAiJVklbSVkIikKCiMjIHRtcCA8LSB0cnkoc20obG9hZG1lKGZpbGVuYW1lID0gZ3N1YihwYXR0ZXJuID0gIlxcLlJtZCIsIHJlcGxhY2UgPSAiXFwucmRhXFwueHoiLCB4ID0gcHJldmlvdXNfZmlsZSkpKSkKcm1kX2ZpbGUgPC0gIjAzZGlmZmVyZW50aWFsX2V4cHJlc3Npb24uUm1kIgpsb2FkZWQgPC0gbG9hZChmaWxlID0gZ2x1ZSgicmRhL3RtcmMyX2RhdGFfc3RydWN0dXJlcy12e3Zlcn0ucmRhIikpCnNhdmVmaWxlIDwtIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLCByZXBsYWNlID0gIlxcLnJkYVxcLnh6IiwgeCA9IHJtZF9maWxlKQpjcmVhdGVkIDwtIGRpci5jcmVhdGUoImFuYWx5c2VzIikKYGBgCgojIENoYW5nZWxvZwoKKiAyMDI0MDEtMjAyNDA1OiBDbGVhbnVwcywgZm9ybWF0dGluZywgZW5zdXJpbmcgdGhhdCBldmVyeXRoaW5nIHdvcmtzIGluIHRoZSBjb250YWluZXIuCiogMjAyMzEwOiBDbGVhbmluZyB1cCB0byBtYWtlIGV2ZXJ5dGhpbmcgcGFzcyB3aXRoaW4gYSBjb250YWluZXJpemVkIGVudmlyb25tZW50LgoqIDIwMjMxMDogUmVjZWl2ZWQgYSBzZXQgb2YgY29sb3JzIGFuZCBjb250cmFzdHMgb2YgaW50ZXJlc3QgZm9yIGEgYmFycGxvdCBvZiBzaWduaWZpY2FuY2UuCiogMjAyMzA0MTA6IE1ha2luZyBzb21lIGNoYW5nZXMgdG8gaW1wcm92ZSB0aGUgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24KICBwbG90cyBhcyB3ZWxsIGFzIHByZXBhcmUgZm9yIHNvbWUgZGlmZmVyZW50IHBhdGh3YXkvR1NFQS9HU1ZBCiAgYW5hbHlzZXMgb24gdGhlIGRhdGEuCgojIEludHJvZHVjdGlvbgoKSGF2aW5nIGVzdGFibGlzaGVkIHRoYXQgdGhlIFRNUkMyIG1hY3JvcGhhZ2UgZGF0YSBsb29rcyByb2J1c3QgYW5kCmlsbHVzdHJhdGl2ZSBvZiBhIGNvdXBsZSBvZiBpbnRlcmVzdGluZyBxdWVzdGlvbnMsIGxldCB1cyBwZXJmb3JtIGEKY291cGxlIG9mIGRpZmZlcmVudGlhbCBhbmFseXNlcyBvZiBpdC4KCkFsc28gbm90ZSB0aGF0IGFzIG9mIDIwMjIxMiwgd2UgcmVjZWl2ZWQgYSBuZXcgc2V0IG9mIHNhbXBsZXMgd2hpY2gKbm93IGluY2x1ZGUgc29tZSB3aGljaCBhcmUgYSBjb21wbGV0ZWx5IGRpZmZlcmVudCBjZWxsIHR5cGUsClU5MzcuICBBcyB0aGVpciBBVENDIHBhZ2Ugc3RhdGVzLCB0aGV5IGFyZSBtYWxpZ25hbnQgY2VsbHMgdGFrZW4gZnJvbQp0aGUgcGxldXJhbCBlZmZ1c2lvbiBvZiBhIDM3IHllYXIgb2xkIHdoaXRlIG1hbGUgd2l0aCBoaXN0aW9jeXRpYwpseW1waG9tYSBhbmQgd2hpY2ggZXhoaWJpdCB0aGUgbW9ycGhvbG9neSBvZiBtb25vY3l0ZXMuICBUaHVzLCB0aGlzCmRvY3VtZW50IG5vdyBpbmNsdWRlcyBzb21lIGNvbXBhcmlzb25zIG9mIHRoZSBjZWxsIHR5cGVzIGFzIHdlbGwgYXMKdGhlIHZhcmlvdXMgbWFjcm9waGFnZSBkb25vcnMgKGdpdmVuIHRoYXQgdGhlcmUgYXJlIG5vdyBtb3JlIGRvbm9ycwp0b28pLgoKIyMgSHVtYW4gZGF0YQoKSSBhbSBtb3ZpbmcgdGhlIGRhdGFzZXQgbWFuaXB1bGF0aW9ucyBoZXJlIHNvIHRoYXQgSSBjYW4gbG9vayBhdCB0aGVtCmFsbCB0b2dldGhlciBiZWZvcmUgcnVubmluZyB0aGUgdmFyaW91cyBERSBhbmFseXNlcy4KCiMjIENyZWF0ZSBzZXRzIGZvY3VzZWQgb24gZHJ1ZywgY2VsbHR5cGUsIHN0cmFpbiwgYW5kIGNvbWJpbmF0aW9ucwoKTGV0IHVzIHN0YXJ0IGJ5IHBsYXlpbmcgd2l0aCB0aGUgbWV0YWRhdGEgYSBsaXR0bGUgYW5kIGNyZWF0ZSBzZXRzCndpdGggdGhlIGNvbmRpdGlvbiBzZXQgdG86CgoqIERydWcgdHJlYXRtZW50CiogQ2VsbCB0eXBlIChtYWNyb3BoYWdlIG9yIFU5MzcpCiogRG9ub3IKKiBJbmZlY3Rpb24gU3RyYWluCiogU29tZSB1c2VmdWwgY29tYmluYXRpb25zIHRoZXJlb2YKCkluIGFkZGl0aW9uLCBrZWVwIG1lbnRhbCB0cmFjayBvZiB3aGljaCBkYXRhc2V0cyBhcmUgY29tcHJpc2VkIG9mIGFsbApzYW1wbGVzIHZzLiB0aG9zZSB3aGljaCBhcmUgb25seSBtYWNyb3BoYWdlIHZzLiB0aG9zZSB3aGljaCBhcmUgb25seQpVOTM3LiAgKFRodXMsIHRoZSB1c2FnZSBvZiBhbGxfaHVtYW4gdnMuIGhzX21hY3IgdnMuIHU5MzcgYXMgcHJlZml4ZXMKZm9yIHRoZSBkYXRhIHN0cnVjdHVyZXMuKQoKSWRlYWxseSwgdGhlc2UgcmVjcmVhdGlvbnMgb2YgdGhlIGRhdGEgc2hvdWxkIHBlcmhhcHMgYmUgaW4gdGhlCmRhdGFzdHJ1Y3R1cmVzIHdvcmtzaGVldC4KCmBgYHtyfQphbGxfaHVtYW4gPC0gc2FuaXRpemVfbWV0YWRhdGEoaHNfbWFjcm9waGFnZSwgY29sdW1ucyA9ICJkcnVnIikgJT4lCiAgc2V0X2NvbmRpdGlvbnMoZmFjdCA9ICJkcnVnIiwgY29sb3JzID0gY29sb3JfY2hvaWNlc1tbImRydWciXV0pICU+JQogIHNldF9iYXRjaGVzKGZhY3QgPSAidHlwZW9mY2VsbHMiKQoKIyMgVGhlIGZvbGxvd2luZyAzIGxpbmVzIHdlcmUgY29weS9wYXN0ZWQgdG8gZGF0YXN0cnVjdHVyZXMgYW5kIHNob3VsZCBiZSByZW1vdmVkIHNvb24uCm5vX3N0cmFpbl9pZHggPC0gY29sRGF0YShhbGxfaHVtYW4pW1sic3RyYWluaWQiXV0gPT0gIm5vbmUiCiMjcERhdGEoYWxsX2h1bWFuKVtbInN0cmFpbmlkIl1dIDwtIHBhc3RlMCgicyIsIHBEYXRhKGFsbF9odW1hbilbWyJzdHJhaW5pZCJdXSwKIyMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJfIiwgcERhdGEoYWxsX2h1bWFuKVtbIm1hY3JvcGhhZ2V6eW1vZGVtZSJdXSkKY29sRGF0YShhbGxfaHVtYW4pW25vX3N0cmFpbl9pZHgsICJzdHJhaW5pZCJdIDwtICJub25lIgp0YWJsZShjb2xEYXRhKGFsbF9odW1hbilbWyJzdHJhaW5pZCJdXSkKCmFsbF9odW1hbl90eXBlcyA8LSBzZXRfY29uZGl0aW9ucyhhbGxfaHVtYW4sIGZhY3QgPSAidHlwZW9mY2VsbHMiKSAlPiUKICBzZXRfYmF0Y2hlcyhmYWN0ID0gImRydWciKQoKdHlwZV96eW1vX2ZhY3QgPC0gcGFzdGUwKGNvbERhdGEoYWxsX2h1bWFuX3R5cGVzKVtbImNvbmRpdGlvbiJdXSwgIl8iLAogICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YShhbGxfaHVtYW5fdHlwZXMpW1sibWFjcm9waGFnZXp5bW9kZW1lIl1dKQp0eXBlX3p5bW8gPC0gc2V0X2NvbmRpdGlvbnMoYWxsX2h1bWFuX3R5cGVzLCBmYWN0ID0gdHlwZV96eW1vX2ZhY3QpCgp0eXBlX2RydWdfZmFjdCA8LSBwYXN0ZTAoY29sRGF0YShhbGxfaHVtYW5fdHlwZXMpW1siY29uZGl0aW9uIl1dLCAiXyIsCiAgICAgICAgICAgICAgICAgICAgICAgICBjb2xEYXRhKGFsbF9odW1hbl90eXBlcylbWyJkcnVnIl1dKQp0eXBlX2RydWcgPC0gc2V0X2NvbmRpdGlvbnMoYWxsX2h1bWFuX3R5cGVzLCBmYWN0ID0gdHlwZV9kcnVnX2ZhY3QpCgpzdHJhaW5fZmFjdCA8LSBjb2xEYXRhKGFsbF9odW1hbl90eXBlcylbWyJzdHJhaW5pZCJdXQp0YWJsZShzdHJhaW5fZmFjdCkKCm5ld19jb25kaXRpb25zIDwtIHBhc3RlMChjb2xEYXRhKGhzX21hY3JvcGhhZ2UpW1sibWFjcm9waGFnZXRyZWF0bWVudCJdXSwgIl8iLAogICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YShoc19tYWNyb3BoYWdlKVtbIm1hY3JvcGhhZ2V6eW1vZGVtZSJdXSkKIyMgTm90ZSB0aGUgc2FuaXRpemUoKSBjYWxsIGlzIHJlZHVuZGFudCB3aXRoIHRoZSBhZGRpdGlvbiBvZiBzYW5pdGl6ZSgpIGluIHRoZQojIyBkYXRhc3RydWN0dXJlcyBmaWxlLCBidXQgSSBkb24ndCB3YW50IHRvIHdhaXQgdG8gcmVydW4gdGhhdC4KaHNfbWFjciA8LSBzZXRfY29uZGl0aW9ucyhoc19tYWNyb3BoYWdlLCBmYWN0ID0gbmV3X2NvbmRpdGlvbnMpICU+JQogIHNhbml0aXplX21ldGFkYXRhKGNvbHVtbiA9ICJkcnVnIikgJT4lCiAgc3Vic2V0X3NlKHN1YnNldCA9ICJ0eXBlb2ZjZWxscyE9J1U5MzcnIikgJT4lCiAgc2V0X3NlX2NvbG9ycyhjb2xvcl9jaG9pY2VzW1sidHJlYXRtZW50X3p5bW8iXV0pCmBgYAoKIyMjIFNlcGFyYXRlIE1hY3JvcGhhZ2Ugc2FtcGxlcwoKT25jZSBhZ2Fpbiwgd2Ugc2hvdWxkIHJlY29uc2lkZXIgd2hlcmUgdGhlIGZvbGxvd2luZyBibG9jayBpcyBwbGFjZWQsCmJ1dCB0aGVzZSBkYXRhc3RydWN0dXJlcyBhcmUgbGlrZWx5IHRvIGJlIHVzZWQgaW4gbWFueSBvZiB0aGUKZm9sbG93aW5nIGFuYWx5c2VzLgoKYGBge3J9CmhzX21hY3JfZHJ1Z19zZSA8LSBzZXRfY29uZGl0aW9ucyhoc19tYWNyLCBmYWN0ID0gImRydWciLCBjb2xvcnMgPSBjb2xvcl9jaG9pY2VzW1siZHJ1ZyJdXSkKCmhzX21hY3Jfc3RyYWluX3NlIDwtIHNldF9jb25kaXRpb25zKGhzX21hY3IsIGZhY3QgPSAibWFjcm9waGFnZXp5bW9kZW1lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcnMgPSBjb2xvcl9jaG9pY2VzW1sienltbyJdXSkgJT4lCiAgc3Vic2V0X3NlKHN1YnNldCA9ICJtYWNyb3BoYWdlenltb2RlbWUgIT0gJ25vbmUnIikKCnRhYmxlKGNvbERhdGEoaHNfbWFjcilbWyJzdHJhaW5pZCJdXSkKYGBgCgojIyMgUmVmYWN0b3IgVTkzNyBzYW1wbGVzCgpUaGUgVTkzNyBzYW1wbGVzIHdlcmUgc2VwYXJhdGVkIGluIHRoZSBkYXRhc3RydWN0dXJlcyBmaWxlLCBidXQgd2UKd2FudCB0byB1c2UgdGhlIGNvbWJpbmF0aW9uIG9mIGRydWcvenltb2RlbWUgd2l0aCB0aGVtIHByZXR0eSBtdWNoCmV4Y2x1c2l2ZWx5LgoKYGBge3J9Cm5ld19jb25kaXRpb25zIDwtIHBhc3RlMChjb2xEYXRhKGhzX3U5MzcpW1sibWFjcm9waGFnZXRyZWF0bWVudCJdXSwgIl8iLAogICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YShoc191OTM3KVtbIm1hY3JvcGhhZ2V6eW1vZGVtZSJdXSkKdTkzN19zZSA8LSBzZXRfY29uZGl0aW9ucyhoc191OTM3LCBmYWN0ID0gbmV3X2NvbmRpdGlvbnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcnMgPSBjb2xvcl9jaG9pY2VzW1sidHJlYXRtZW50X3p5bW8iXV0pCmBgYAoKIyMgQ29udHJhc3RzIHVzZWQgaW4gdGhpcyBkb2N1bWVudAoKR2l2ZW4gdGhlIHZhcmlvdXMgd2F5cyB3ZSBoYXZlIGNob3BwZWQgdXAgdGhpcyBkYXRhc2V0LCB0aGVyZSBhcmUgYQpmZXcgZ2VuZXJhbCB0eXBlcyBvZiBjb250cmFzdHMgd2Ugd2lsbCBwZXJmb3JtLCB3aGljaCB3aWxsIHRoZW4gYmUKY29tYmluZWQgaW50byBncmVhdGVyIGNvbXBsZXhpdHk6CgoqIGRydWcgdHJlYXRtZW50OiBBbnRpbW9uYWwgdHJlYXRlZCBvciBub3QuCiogc3RyYWlucyB1c2VkOiBVbmluZmVjdGVkLCB6Mi4zLCBhbmQgejIuMi4KKiBjZWxsbHR5cGVzOiBVOTM3IG9yIG1hY3JvcGhhZ2UuCiogZG9ub3JzOiBUaGUgcGVyc29uIGZyb20gd2hvbSB0aGUgbWFjcm9waGFnZXMgd2VyZSB0YWtlbi4KCkluIHRoZSBlbmQsIG91ciBhY3R1YWwgZ29hbCBpcyB0byBjb25zaWRlciB0aGUgdmFyaWFibGUgZWZmZWN0cyBvZgpkcnVnK3N0cmFpbiBhbmQgc2VlIGlmIHdlIGNhbiBkaXNjZXJuIHBhdHRlcm5zIHdoaWNoIGxlYWQgdG8gYmV0dGVyIG9yCndvcnNlIGRydWcgdHJlYXRtZW50IG91dGNvbWUuCgpUaGVyZSBpcyBhIHNldCBvZiBjb250cmFzdHMgaW4gd2hpY2ggd2UgYXJlIHByaW1hcmlseSBpbnRlcmVzdGVkIGluCnRoaXMgZGF0YSwgdGhlc2UgZm9sbG93LiAgSSBjcmVhdGVkIG9uZSByYXRpbyBvZiByYXRpb3MgY29udHJhc3Qgd2hpY2gKSSB0aGluayBoYXMgdGhlIHBvdGVudGlhbCB0byBhc2sgb3VyIGJpZ2dlc3QgcXVlc3Rpb24uCgpgYGB7cn0KIyMgRWFjaCBvZiB0aGUgZm9sbG93aW5nIGxpc3RzIGhhcyB0aGUgbmFtZSBvZiB0aGUgY29udHJhc3QgYXMgdGhlIGtleQojIyBmb2xsb3dlZCBieSBhIHR3byBlbGVtZW50IHZlY3RvciBjb21wcmlzZWQgb2YgdGhlIG51bWVyYXRvciBhbmQKIyMgZGVub21pbmF0b3IgYXMgdGhlIHZhbHVlLiAgSW4gdGhlIGNhc2Ugb2YgdGhpcyBmaXJzdCBjb250cmFzdCwgdGhhdAojIyBpcyBjb21wcmlzZWQgb2YgYSBzdHJpbmcgd2hpY2ggbWFudWFsbHkgZGVmaW5lcyBhIHNlcmllcyBvZiBtb3JlCiMjIGNvbXBsZXggY29udHJhc3RzIHRoYW4gdGhlIHVzdWFsL3NpbXBsZSBwYWlyd2lzZS4KdG1yYzJfaHVtYW5fZXh0cmEgPC0gInoyM2RydWdub2RydWdfdnNfejIyZHJ1Z25vZHJ1ZyA9IChjb25kaXRpb25pbmZfc2JfejIzIC0gY29uZGl0aW9uaW5mX3oyMykgLSAoY29uZGl0aW9uaW5mX3NiX3oyMiAtIGNvbmRpdGlvbmluZl96MjIpLCB6MjN6MjJkcnVnX3ZzX3oyM3oyMm5vZHJ1ZyA9IChjb25kaXRpb25pbmZfc2JfejIzIC0gY29uZGl0aW9uaW5mX3NiX3oyMikgLSAoY29uZGl0aW9uaW5mX3oyMyAtIGNvbmRpdGlvbmluZl96MjIpIgp0bXJjMl9odW1hbl9rZWVwZXJzIDwtIGxpc3QoCiAgInoyM25vc2JfdnNfdW5pbmYiID0gYygiaW5mX3oyMyIsICJ1bmluZl9ub25lIiksCiAgInoyMm5vc2JfdnNfdW5pbmYiID0gYygiaW5mX3oyMiIsICJ1bmluZl9ub25lIiksCiAgInoyM25vc2JfdnNfejIybm9zYiIgPSBjKCJpbmZfejIzIiwgImluZl96MjIiKSwKICAiejIzc2JfdnNfejIyc2IiID0gYygiaW5mX3NiX3oyMyIsICJpbmZfc2JfejIyIiksCiAgInoyM3NiX3ZzX3oyM25vc2IiID0gYygiaW5mX3NiX3oyMyIsICJpbmZfejIzIiksCiAgInoyMnNiX3ZzX3oyMm5vc2IiID0gYygiaW5mX3NiX3oyMiIsICJpbmZfejIyIiksCiAgInoyM3NiX3ZzX3NiIiA9IGMoImluZl9zYl96MjMiLCAidW5pbmZfc2Jfbm9uZSIpLAogICJ6MjJzYl92c19zYiIgPSBjKCJpbmZfc2JfejIyIiwgInVuaW5mX3NiX25vbmUiKSwKICAiejIzc2JfdnNfdW5pbmYiID0gYygiaW5mX3NiX3oyMyIsICJ1bmluZl9ub25lIiksCiAgInoyMnNiX3ZzX3VuaW5mIiA9IGMoImluZl9zYl96MjIiLCAidW5pbmZfbm9uZSIpLAogICJzYl92c191bmluZiIgPSBjKCJ1bmluZl9zYl9ub25lIiwgInVuaW5mX25vbmUiKSwKICAiZXh0cmFfejIzMjIiID0gYygiejIzZHJ1Z25vZHJ1ZyIsICJ6MjJkcnVnbm9kcnVnIiksCiAgImV4dHJhX2RydWdub2RydWciID0gYygiejIzejIyZHJ1ZyIsICJ6MjN6MjJub2RydWciKSkKc2luZ2xlX3RtcmMyX2tlZXBlciA8LSBsaXN0KAogICJ6MjJzYl92c19zYiIgPSBjKCJpbmZfc2JfejIyIiwgInVuaW5mX3NiX25vbmUiKSkKdG1yYzJfZHJ1Z19rZWVwZXJzIDwtIGxpc3QoCiAgImRydWciID0gYygiYW50aW1vbnkiLCAibm9uZSIpKQp0bXJjMl90eXBlX2tlZXBlcnMgPC0gbGlzdCgKICAidHlwZSIgPSBjKCJVOTM3IiwgIk1hY3JvcGhhZ2VzIikpCnRtcmMyX3N0cmFpbl9rZWVwZXJzIDwtIGxpc3QoCiAgInN0cmFpbiIgPSBjKCJ6MjMiLCAiejIyIikpCnR5cGVfenltb19leHRyYSA8LSAienltb3NfdnNfdHlwZXMgPSAoY29uZGl0aW9uVTkzN196MjMgLSBjb25kaXRpb25VOTM3X3oyMikgLSAoY29uZGl0aW9uTWFjcm9waGFnZXNfejIzIC0gY29uZGl0aW9uTWFjcm9waGFnZXNfejIyKSIKdG1yYzJfdHlwZXp5bW9fa2VlcGVycyA8LSBsaXN0KAogICJ1OTM3X21hY3IiID0gYygiTWFjcm9waGFnZXNfbm9uZSIsICJVOTM3X25vbmUiKSwKICAienltb19tYWNyIiA9IGMoIk1hY3JvcGhhZ2VzX3oyMyIsICJNYWNyb3BoYWdlc196MjIiKSwKICAienltb191OTM3IiA9IGMoIlU5MzdfejIzIiwgIlU5MzdfejIyIiksCiAgInoyM190eXBlcyIgPSBjKCJVOTM3X3oyMyIsICJNYWNyb3BoYWdlc196MjMiKSwKICAiejIyX3R5cGVzIiA9IGMoIlU5MzdfejIyIiwgIk1hY3JvcGhhZ2VzX3oyMiIpLAogICJ6eW1vc190eXBlcyIgPSBjKCJ6eW1vc192c190eXBlcyIpKQp0bXJjMl90eXBlZHJ1Z19rZWVwZXJzIDwtIGxpc3QoCiAgInR5cGVfbm9kcnVnIiA9IGMoIlU5Mzdfbm9uZSIsICJNYWNyb3BoYWdlc19ub25lIiksCiAgInR5cGVfZHJ1ZyIgPSBjKCJVOTM3X2FudGltb255IiwgIk1hY3JvcGhhZ2VzX2FudGltb255IiksCiAgIm1hY3JfZHJ1Z3MiID0gYygiTWFjcm9waGFnZXNfYW50aW1vbnkiLCAiTWFjcm9waGFnZXNfbm9uZSIpLAogICJ1OTM3X2RydWdzIiA9IGMoIlU5MzdfYW50aW1vbnkiLCAiVTkzN19ub25lIikpCnU5Mzdfa2VlcGVycyA8LSBsaXN0KAogICJ6MjNub3NiX3ZzX3VuaW5mIiA9IGMoImluZl96MjMiLCAidW5pbmZfbm9uZSIpLAogICJ6MjJub3NiX3ZzX3VuaW5mIiA9IGMoImluZl96MjIiLCAidW5pbmZfbm9uZSIpLAogICJ6MjNub3NiX3ZzX3oyMm5vc2IiID0gYygiaW5mX3oyMyIsICJpbmZfejIyIiksCiAgInoyM3NiX3ZzX3oyMnNiIiA9IGMoImluZl9zYl96MjMiLCAiaW5mX3NiX3oyMiIpLAogICJ6MjNzYl92c196MjNub3NiIiA9IGMoImluZl9zYl96MjMiLCAiaW5mX3oyMyIpLAogICJ6MjJzYl92c196MjJub3NiIiA9IGMoImluZl9zYl96MjIiLCAiaW5mX3oyMiIpLAogICJ6MjNzYl92c19zYiIgPSBjKCJpbmZfc2JfejIzIiwgInVuaW5mX3NiX25vbmUiKSwKICAiejIyc2JfdnNfc2IiID0gYygiaW5mX3NiX3oyMiIsICJ1bmluZl9zYl9ub25lIiksCiAgInoyM3NiX3ZzX3VuaW5mIiA9IGMoImluZl9zYl96MjMiLCAidW5pbmZfbm9uZSIpLAogICJ6MjJzYl92c191bmluZiIgPSBjKCJpbmZfc2JfejIyIiwgInVuaW5mX25vbmUiKSwKICAic2JfdnNfdW5pbmYiID0gYygidW5pbmZfc2Jfbm9uZSIsICJ1bmluZl9ub25lIikpCiMjIElmIHNvbWUgY2FzZXMsIHdoZW4gdGhlIHNldCBvZiBzaWduaWZpY2FudCBnZW5lcyB3YXMgY2hvc2VuLCBhbgojIyBhZGRpdGlvbmFsIGZpbHRlciB3YXMgYWRkZWQgdG8gZXhjbHVkZSBnZW5lcyB3aXRoIGV4cHJlc3Npb24gdmFsdWVzCiMjIGxlc3MgdGhhbiAnaGlnaF9leHByZXNzaW9uJyBhY2NvcmRpbmcgdG8gdGhlCiMjICdoaWdoX2V4cHJlc3Npb25fY29sdW1uJyBpbiB0aGUgdGFibGUuCmhpZ2hfZXhwcmVzc2lvbiA8LSAxMjgKaGlnaF9leHByZXNzaW9uX2NvbHVtbiA8LSAiZGVzZXFfYmFzZW1lYW4iCgpjb21iaW5lZF90b190c3YgPC0gZnVuY3Rpb24oY29tYmluZWQsIGNlbGx0eXBlID0gImFsbCIpIHsKICBrZWVwZXJzIDwtIGNvbWJpbmVkW1sia2VlcGVycyJdXQogIGZvciAoayBpbiBzZXFfbGVuKGxlbmd0aChrZWVwZXJzKSkpIHsKICAgIGtuYW1lIDwtIG5hbWVzKGtlZXBlcnMpW2tdCiAgICBudW1lcmF0b3IgPC0ga2VlcGVyc1tba11dWzFdCiAgICBkZW5vbWluYXRvciA8LSBrZWVwZXJzW1trXV1bMl0KICAgIGZpbGVuYW1lIDwtIGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvdHN2X3RhYmxlcy90bXJjMl97Y2VsbHR5cGV9X3trbmFtZX1fbntudW1lcmF0b3J9X2R7ZGVub21pbmF0b3J9LXZ7dmVyfS54bHN4IikKICAgIGtkYXRhIDwtIGNvbWJpbmVkW1siZGF0YSJdXVtba25hbWVdXQogICAgaWYgKGlzLm51bGwoa2RhdGFbWyJiYXNpY19udW0iXV0pKSB7CiAgICAgIG5leHQKICAgIH0KICAgIHdhbnRlZCA8LSBjKCJoZ25jX3N5bWJvbCIsICJkZXNlcV9sb2dmYyIsICJkZXNlcV9hZGpwIiwKICAgICAgICAgICAgICAgICJkZXNlcV9iYXNlbWVhbiIsICJkZXNlcV9udW0iLCAiZGVzZXFfZGVuIikKICAgIHdhbnRlZF9kYXRhIDwtIGtkYXRhWywgd2FudGVkXQogICAgY29sbmFtZXMod2FudGVkX2RhdGEpIDwtIGMoImhnbmNfc3ltYm9sIiwgImRlc2VxX2xvZ2ZjIiwgImRlc2VxX2FkanAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImRlc2VxX21lYW4iLCAiZGVzZXFfbnVtZXJhdG9yIiwgImRlc2VxX2Rlbm9taW5hdG9yIikKICAgIHdyaXRlX3hsc3goZGF0YSA9IHdhbnRlZF9kYXRhLCBleGNlbCA9IGZpbGVuYW1lKQogIH0KfQoKd3JpdGVfYWxsX2dwIDwtIGZ1bmN0aW9uKGFsbF9ncCwgc3VmZml4ID0gTlVMTCkgewogIGFsbF93cml0dGVuIDwtIGxpc3QoKQogIGZvciAoZyBpbiBzZXFfbGVuKGxlbmd0aChhbGxfZ3ApKSkgewogICAgbmFtZSA8LSBuYW1lcyhhbGxfZ3ApW2ddCiAgICBkYXR1bSA8LSBhbGxfZ3BbW25hbWVdXQogICAgZmlsZW5hbWUgPC0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9ncHJvZmlsZXIve25hbWV9X2dwcm9maWxlci12e3Zlcn0ueGxzeCIpCiAgICBpZiAoIWlzLm51bGwoc3VmZml4KSkgewogICAgICBmaWxlbmFtZSA8LSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2dwcm9maWxlci97bmFtZX1fZ3Byb2ZpbGVye3N1ZmZpeH0tdnt2ZXJ9Lnhsc3giKQogICAgfQogICAgd3JpdHRlbiA8LSBzbSh3cml0ZV9ncHJvZmlsZXJfZGF0YShkYXR1bSwgZXhjZWwgPSBmaWxlbmFtZSkpCiAgICBhbGxfd3JpdHRlbltbZ11dIDwtIHdyaXR0ZW4KICB9CiAgcmV0dXJuKGFsbF93cml0dGVuKQp9CmBgYAoKIyMgUHJpbWFyeSBxdWVyaWVzCgpUaGVyZSBpcyBhIHNlcmllcyBvZiBpbml0aWFsIHF1ZXN0aW9ucyB3aGljaCBtYWtlIHNvbWUgc2Vuc2UKdG8gbWUsIGJ1dCB0aGVzZSBkbyBub3QgbmVjZXNzYXJpbHkgbWF0Y2ggdGhlIHNldCBvZiBxdWVzdGlvbnMgd2hpY2gKYXJlIG1vc3QgcHJlc3NpbmcuICBJIGFtIGhvcGluZyB0byBwdWxsIGJvdGggb2YgdGhlc2Ugc2V0cyBvZgpxdWVyaWVzIGluIG9uZS4KCkJlZm9yZSBleHRyYWN0aW5nIHRoZXNlIGdyb3VwcyBvZiBxdWVyaWVzLCBsZXQgdXMgaW52b2tlIHRoZQphbGxfcGFpcndpc2UoKSBmdW5jdGlvbiBhbmQgZ2V0IGFsbCBvZiB0aGUgbGlrZWx5IGNvbnRyYXN0cyBhbG9uZyB3aXRoCm9uZSBvciBtb3JlIGV4dHJhcyB0aGF0IG1pZ2h0IHByb3ZlIHVzZWZ1bCAodGhlICdleHRyYScgYXJndW1lbnQpLgoKVGhlIHN0cnVjdHVyZSBvZiB0aGVzZSBibG9ja3Mgd2lsbCBhbGwgYmFzaWNhbGx5IGJlIGlkZW50aWNhbDoKCiogUGVyZm9ybSBhIHNldCBvZiBwYWlyd2lzZSBjb250cmFzdHMgb2YgYWxsIHRoZSBjb25kaXRpb25zIGFnYWluc3QKICBlYWNoIG90aGVyLiAgT3B0aW9uYWxseSB1c2Ugc3ZhLgoqIEdpdmVuIHRoYXQgcmVzdWx0LCBkdW1wIGl0IGluIGl0cyBlbnRpcmV0eSB0byBhbiB4bHN4IGZpbGUgaW4gdGhlCiAgYW5hbHlzZXMvIGRpcmVjdG9yeS4KKiBHaXZlbiB0aG9zZSBjb21iaW5lZCB0YWJsZXMsIGV4dHJhY3QgZnJvbSB0aGVtIHRoZSBzZXQgZGVlbWVkCiAgJ3NpZ25pZmljYW50JyBieSB3aGF0ZXZlciBjcml0ZXJpYSB3ZSB3YW50IHRvIHRyeS4gKFVzdWFsbHkgfGxmY3wgPj0KICAxLjAsIGFkanVzdGVkIHAgPD0gMC4wNTsgYnV0IHBvdGVudGlhbGx5IGFsc28gZXhwcmVzc2lvbiA+PSB4IGFuZAogIHNvbWV0aW1lcyBhIHNldCBvZiBsZXNzIHN0cmluZ2VudCB2YWx1ZXMgKHxsZmN8ID49IDAuNikpCiogR2l2ZW4gb25lIG9yIG1vcmUgZ2VuZSBzZXRzIGRlZW1lZCAnc2lnbmlmaWNhbnQnIHBhc3MgdGhlbSB0bwogIGdQcm9maWxlcjIgYW5kIHNlZSB3aGF0IHBvcHMgb3V0LgoKIyMjIENvbWJpbmVkIFU5MzcgYW5kIE1hY3JvcGhhZ2VzOiBDb21wYXJlIGRydWcgZWZmZWN0cwoKV2hlbiB3ZSBoYXZlIHRoZSB1OTM3IGNlbGxzIGluIHRoZSBzYW1lIGRhdGFzZXQgYXMgdGhlIG1hY3JvcGhhZ2VzLAp0aGF0IHByb3ZpZGVzIGFuIGludGVyZXN0aW5nIG9wcG9ydHVuaXR5IHRvIHNlZSBpZiB3ZSBjYW4gb2JzZXJ2ZQpkcnVnLWRlcGVuZGFudCBlZmZlY3RzIHdoaWNoIGFyZSBzaGFyZWQgYWNyb3NzIGJvdGggY2VsbCB0eXBlcy4KCk5vdGUgdG8gc2VsZjogZ2l2ZW4gdGhlIGNoYW5nZXMgdG8gaHBnbHRvb2xzIEkgbWF5IG5lZWQgdG8gc3BlY2lmeSB0aGUKc3RhdGlzdGljYWwgbW9kZWwgc3RyaW5nIHdoZW4gSSBhbSB1c2luZyBzdmFzZXEgZm9yIHNvbWUvbWFueS9hbGwgb2YKdGhlc2UgY29tcGFyaXNvbnMuCgpgYGB7cn0KZHJ1Z19kZSA8LSBhbGxfcGFpcndpc2UoYWxsX2h1bWFuLCBmaWx0ZXIgPSBUUlVFLCBtb2RlbF9zdnMgPSAic3Zhc2VxIiwKICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfZnN0cmluZyA9ICJ+IDAgKyBjb25kaXRpb24iKQpkcnVnX2RlCgpkcnVnX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGRydWdfZGUsIGtlZXBlcnMgPSB0bXJjMl9kcnVnX2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9tYWNyb3BoYWdlX2RydWdfY29tcGFyaXNvbi12e3Zlcn0ueGxzeCIpKQpkcnVnX3RhYmxlCmNvbWJpbmVkX3RvX3RzdihkcnVnX3RhYmxlLCBjZWxsdHlwZSA9ICJhbGwiKQoKZHJ1Z19zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBkcnVnX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL21hY3JvcGhhZ2VfZHJ1Z19zaWctdnt2ZXJ9Lnhsc3giKSkKZHJ1Z19zaWcKZHJ1Z19oaWdoc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgZHJ1Z190YWJsZSwgbWluX21lYW5fZXhwcnMgPSBoaWdoX2V4cHJlc3Npb24sIGV4cHJzX2NvbHVtbiA9IGhpZ2hfZXhwcmVzc2lvbl9jb2x1bW4sCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZV9kcnVnX2hpZ2hzaWctdnt2ZXJ9Lnhsc3giKSkKZHJ1Z19oaWdoc2lnCmRydWdfbGVzc3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGRydWdfdGFibGUsIGxmYyA9IDAuNiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlX2RydWdfbGVzc3NpZy12e3Zlcn0ueGxzeCIpKQpkcnVnX2xlc3NzaWcKYGBgCgojIyMjIGdQcm9maWxlcjIgcmVzdWx0cyBvZiB0aGUgc2lnbmlmaWNhbnQgZHJ1ZyBnZW5lcwoKYGBge3J9CmFsbF9kcnVnX2dwIDwtIGFsbF9ncHJvZmlsZXIoZHJ1Z19zaWcsIGVucmljaF9pZF9jb2x1bW4gPSAiaGduY19zeW1ib2wiKQphbGxfZHJ1Z19ncAp3cml0dGVuIDwtIHdyaXRlX2FsbF9ncChhbGxfZHJ1Z19ncCkKCmFsbF9kcnVnX2xlc3NzaWcgPC0gYWxsX2dwcm9maWxlcihkcnVnX2xlc3NzaWcsIGVucmljaF9pZF9jb2x1bW4gPSAiaGduY19zeW1ib2wiKQp3cml0dGVuIDwtIHdyaXRlX2FsbF9ncChhbGxfZHJ1Z19sZXNzc2lnLCBzdWZmaXggPSAiX2xmYzAuNl8iKQpgYGAKCiMjIyBDb21iaW5lZCBVOTM3IGFuZCBNYWNyb3BoYWdlczogY29tcGFyZSBjZWxsIHR5cGVzCgpUaGVyZSBhcmUgYSBjb3VwbGUgb2Ygd2F5cyBvbmUgbWlnaHQgd2FudCB0byBkaXJlY3RseSBjb21wYXJlIHRoZSB0d28KY2VsbCB0eXBlcy4KCiogR2l2ZW4gdGhhdCB0aGUgdmFyaWFuY2UgYmV0d2VlbiB0aGUgdHdvIGNlbGx0eXBlcyBpcyBzbyBodWdlLCBqdXN0CmNvbXBhcmUgYWxsIHNhbXBsZXMuCiogT25lIG1pZ2h0IHdhbnQgdG8gY29tcGFyZSB0aGVtIHdpdGggdGhlIGludGVyYWN0aW9uIGVmZmVjdHMgb2YgZHJ1Zy96eW1vZGVtZS4KCmBgYHtyfQp0eXBlX2RlIDwtIGFsbF9wYWlyd2lzZShhbGxfaHVtYW5fdHlwZXMsIGZpbHRlciA9IFRSVUUsIG1vZGVsX2ZzdHJpbmcgPSAifiAwICsgY29uZGl0aW9uIiwKICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfc3ZzID0gInN2YXNlcSIpCnR5cGVfZGUKCnR5cGVfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgdHlwZV9kZSwga2VlcGVycyA9IHRtcmMyX3R5cGVfa2VlcGVycywKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL21hY3JvcGhhZ2VfdHlwZV9jb21wYXJpc29uLXZ7dmVyfS54bHN4IikpCnR5cGVfdGFibGUKY29tYmluZWRfdG9fdHN2KHR5cGVfdGFibGUsIGNlbGx0eXBlID0gImFsbCIpCgp0eXBlX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHR5cGVfdGFibGUsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZV90eXBlX3NpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX3NpZwp0eXBlX2hpZ2hzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB0eXBlX3RhYmxlLCBtaW5fbWVhbl9leHBycyA9IGhpZ2hfZXhwcmVzc2lvbiwgZXhwcnNfY29sdW1uID0gaGlnaF9leHByZXNzaW9uX2NvbHVtbiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlX3R5cGVfaGlnaHNpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX2hpZ2hzaWcKCnR5cGVfbGVzc3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHR5cGVfdGFibGUsIGxmYyA9IDAuNiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlX3R5cGVfbGVzc3NpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX3NpZwpgYGAKCiMjIyMgQ29tYmluZWQgZmFjdG9ycyBvZiBpbnRlcmVzdDogY2VsbHR5cGUrenltb2RlbWUKCkdpdmVuIHRoZSBhYm92ZSBleHBsaWNpdCBjb21wYXJpc29uIG9mIGFsbCBzYW1wbGVzIGNvbXByaXNpbmcgdGhlIHR3bwpjZWxsIHR5cGVzLCBub3cgbGV0IHVzIGxvb2sgYXQgdGhlIGRydWcgdHJlYXRtZW50K3p5bW9kZW1lIHN0YXR1cyB3aXRoCmFsbCBzYW1wbGVzLCBtYWNyb3BoYWdlcyBhbmQgVTkzNy4KCmBgYHtyfQp0eXBlX3p5bW9fZGUgPC0gYWxsX3BhaXJ3aXNlKHR5cGVfenltbywgZmlsdGVyID0gVFJVRSwgbW9kZWxfc3ZzID0gInN2YXNlcSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfZnN0cmluZyA9ICJ+IDAgKyBjb25kaXRpb24iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4dHJhX2NvbnRyYXN0cyA9IHR5cGVfenltb19leHRyYSkKdHlwZV96eW1vX2RlCgp0eXBlX3p5bW9fdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgdHlwZV96eW1vX2RlLCBrZWVwZXJzID0gdG1yYzJfdHlwZXp5bW9fa2VlcGVycywKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL21hY3JvcGhhZ2VfdHlwZV96eW1vX2NvbXBhcmlzb24tdnt2ZXJ9Lnhsc3giKSkKI2NvbWJpbmVkX3RvX3Rzdih0eXBlX3p5bW9fdGFibGUsIGNlbGx0eXBlID0gImFsbCIpCgp0eXBlX3p5bW9fc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgdHlwZV96eW1vX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL21hY3JvcGhhZ2VfdHlwZV96eW1vX3NpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX3p5bW9fc2lnCnR5cGVfenltb19oaWdoc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgdHlwZV96eW1vX3RhYmxlLCBtaW5fbWVhbl9leHBycyA9IGhpZ2hfZXhwcmVzc2lvbiwgZXhwcnNfY29sdW1uID0gaGlnaF9leHByZXNzaW9uX2NvbHVtbiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlX3R5cGVfenltb19oaWdoc2lnLXZ7dmVyfS54bHN4IikpCnR5cGVfenltb19sZXNzc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgdHlwZV96eW1vX3RhYmxlLCBsZmMgPSAwLjYsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZV90eXBlX3p5bW9fbGVzc3NpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX3p5bW9fbGVzc3NpZwpgYGAKCiMjIyMgQ29tYmluZWQgZmFjdG9ycyBvZiBpbnRlcmVzdDogY2VsbHR5cGUrZHJ1ZwoKVGhlICd0eXBlX2RydWcnIGRhdGFzdHJ1Y3R1cmUgaXMgdGhlIHNhbWUgYXMgYWJvdmUsIGJ1dCB0aGUgY29uZGl0aW9uCmlzIGNyZWF0ZWQgZnJvbSB0aGUgY29uY2F0ZW5hdGlvbiBvZiB0aGUgY2VsbCB0eXBlIGFuZCBkcnVnIHRyZWF0bWVudC4KCmBgYHtyfQp0eXBlX2RydWdfZGUgPC0gYWxsX3BhaXJ3aXNlKHR5cGVfZHJ1ZywgZmlsdGVyID0gVFJVRSwgbW9kZWxfc3ZzID0gInN2YXNlcSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfZnN0cmluZyA9ICJ+IDAgKyBjb25kaXRpb24iKQp0eXBlX2RydWdfZGUKdHlwZV9kcnVnX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIHR5cGVfZHJ1Z19kZSwga2VlcGVycyA9IHRtcmMyX3R5cGVkcnVnX2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9tYWNyb3BoYWdlX3R5cGVfZHJ1Z19jb21wYXJpc29uLXZ7dmVyfS54bHN4IikpCnR5cGVfZHJ1Z190YWJsZQoKI2NvbWJpbmVkX3RvX3Rzdih0eXBlX2RydWdfdGFibGUsIGNlbGx0eXBlID0gImFsbCIpCgp0eXBlX2RydWdfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgdHlwZV9kcnVnX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL21hY3JvcGhhZ2VfdHlwZV9kcnVnX3NpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX2RydWdfc2lnCgp0eXBlX2RydWdfaGlnaHNpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHR5cGVfZHJ1Z190YWJsZSwgbWluX21lYW5fZXhwcnMgPSBoaWdoX2V4cHJlc3Npb24sIGV4cHJzX2NvbHVtbiA9IGhpZ2hfZXhwcmVzc2lvbl9jb2x1bW4sCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZV90eXBlX2RydWdfaGlnaHNpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX2RydWdfaGlnaHNpZwoKdHlwZV9kcnVnX2xlc3NzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB0eXBlX2RydWdfdGFibGUsIGxmYyA9IDAuNiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlX3R5cGVfZHJ1Z19sZXNzc2lnLXZ7dmVyfS54bHN4IikpCnR5cGVfZHJ1Z19sZXNzc2lnCmBgYAoKIyBJbmRpdmlkdWFsIGNlbGwgdHlwZXMKCkF0IHRoaXMgcG9pbnQsIEkgdGhpbmsgaXQgaXMgZmFpciB0byBzYXkgdGhhdCB0aGUgdHdvIGNlbGwgdHlwZXMgYXJlCnN1ZmZpY2llbnRseSBkaWZmZXJlbnQgdGhhdCB0aGV5IGRvIG5vdCByZWFsbHkgYmVsb25nIHRvZ2V0aGVyIGluIGEKc2luZ2xlIGFuYWx5c2lzLgoKIyMgZHJ1ZyBvciBzdHJhaW4gZWZmZWN0cywgc2luZ2xlIGNlbGwgdHlwZQoKT25lIG9mIHRoZSBxdWVyaWVzIE5hamliIGFza2VkIHdoaWNoIEkgdGhpbmsgSSBtaXNpbnRlcnByZXRlZCB3YXMgdG8KbG9vayBhdCBkcnVnIGFuZC9vciBzdHJhaW4gZWZmZWN0cy4gIE15IGludGVycHJldGF0aW9uIGlzIHNvbWV3aGVyZQpiZWxvdyBhbmQgd2FzIG5vdCB3aGF0IGhlIHdhcyBsb29raW5nIGZvci4gIEluc3RlYWQsIGhlIHdhcyBsb29raW5nIHRvCnNlZSBhbGwobWFjcm9waGFnZSkgZHJ1Zy9ub2RydWcgYW5kIGFsbChtYWNyb3BoYWdlKSB6MjMvejIyIGFuZApjb21wYXJlIHRoZW0gdG8gZWFjaCBvdGhlci4gIEl0IG1heSBiZSB0aGF0IHRoaXMgaXMgc3RpbGwgYSB3cm9uZwppbnRlcnByZXRhdGlvbiwgaWYgc28gdGhlIG1vc3QgbGlrZWx5IGNvbXBhcmlzb24gaXMgZWl0aGVyOgoKKiAgKHoyM2RydWcvejIyZHJ1ZykgLyAoejIzbm9kcnVnL3oyMm5vZHJ1ZyksIG9yIHBlcmhhcHMKKiAgKHoyM2RydWcvejIzbm9kcnVnKSAvICh6MjJkcnVnL3oyMm5vZHJ1ZyksCgpJIGFtIG5vdCBzdXJlIHRob3NlIGNvbmZ1c2UgbWUsIGFuZCBhdCBsZWFzdCBvbmUgb2YgdGhlbSBpcyBiZWxvdwoKIyMgTWFjcm9waGFnZXMKCkluIHRoZXNlIGJsb2NrcyB3ZSB3aWxsIGV4cGxpY2l0bHkgcXVlcnkgb25seSBvbmUgZmFjdG9yIGF0IGEgdGltZSwKZHJ1ZyBhbmQgc3RyYWluLiAgVGhlIGV2ZW50dWFsIGdvYWwgaXMgdG8gbG9vayBmb3IgZWZmZWN0cyBvZgpkcnVnIHRyZWF0bWVudCBhbmQvb3Igc3RyYWluIHRyZWF0bWVudCB3aGljaCBhcmUgc2hhcmVkPwoKIyMjIE1hY3JvcGhhZ2UgRHJ1ZyBvbmx5CgpUaHVzIHdlIHdpbGwgc3RhcnQgd2l0aCB0aGUgcHVyZSBkcnVnIHF1ZXJ5LiAgSW4gdGhpcyBibG9jayB3ZSB3aWxsCmxvb2sgb25seSBhdCB0aGUgZHJ1Zy9ub2RydWcgZWZmZWN0LgoKYGBge3J9CmhzX21hY3JfZHJ1Z19kZSA8LSBhbGxfcGFpcndpc2UoaHNfbWFjcl9kcnVnX3NlLCBmaWx0ZXIgPSBUUlVFLCBtb2RlbF9zdnMgPSAic3Zhc2VxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9mc3RyaW5nID0gIn4gMCArIGNvbmRpdGlvbiIpCmhzX21hY3JfZHJ1Z19kZQoKaHNfbWFjcl9kcnVnX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGhzX21hY3JfZHJ1Z19kZSwga2VlcGVycyA9IHRtcmMyX2RydWdfa2VlcGVycywKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL21hY3JvcGhhZ2Vfb25seWRydWdfdGFibGUtdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9kcnVnX3RhYmxlCgojY29tYmluZWRfdG9fdHN2KGhzX21hY3JfZHJ1Z190YWJsZSwgY2VsbHR5cGUgPSAibWFjcm9waGFnZSIpCgpoc19tYWNyX2RydWdfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgaHNfbWFjcl9kcnVnX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL21hY3JvcGhhZ2Vvbmx5X2RydWdfc2lnLXZ7dmVyfS54bHN4IikpCmhzX21hY3JfZHJ1Z19zaWcKCmhzX21hY3JfZHJ1Z19oaWdoc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgaHNfbWFjcl9kcnVnX3RhYmxlLCBtaW5fbWVhbl9leHBycyA9IGhpZ2hfZXhwcmVzc2lvbiwgZXhwcnNfY29sdW1uID0gaGlnaF9leHByZXNzaW9uX2NvbHVtbiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlb25seV9kcnVnX2hpZ2hzaWctdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9kcnVnX2hpZ2hzaWcKCiMjIENyZWF0aW5nIHRoZSBmb2xsb3dpbmcgdG8gc2VlIGhvdyBpdCBhZmZlY3RzIGdQcm9maWxlci4KaHNfbWFjcl9kcnVnX2xlc3NzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBoc19tYWNyX2RydWdfdGFibGUsIGxmYyA9IDAuNiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlb25seV9kcnVnX3NpZ19sZmMwLjYtdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIyMgTWFjcm9waGFnZSBTdHJhaW4gb25seQoKSW4gYSBzaW1pbGFyIGZhc2hpb24sIGxldCB1cyBsb29rIGZvciBlZmZlY3RzIHdoaWNoIGFyZSBvYnNlcnZlZCB3aGVuCndlIGNvbnNpZGVyIG9ubHkgdGhlIHN0cmFpbiB1c2VkIGR1cmluZyBpbmZlY3Rpb24uCgpgYGB7cn0KaHNfbWFjcl9zdHJhaW5fZGUgPC0gYWxsX3BhaXJ3aXNlKGhzX21hY3Jfc3RyYWluX3NlLCBmaWx0ZXIgPSBUUlVFLCBtb2RlbF9zdnMgPSAic3Zhc2VxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsX2ZzdHJpbmcgPSAifiAwICsgY29uZGl0aW9uIikKaHNfbWFjcl9zdHJhaW5fZGUKCmhzX21hY3Jfc3RyYWluX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGhzX21hY3Jfc3RyYWluX2RlLCBrZWVwZXJzID0gdG1yYzJfc3RyYWluX2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9tYWNyb3BoYWdlX29ubHlzdHJhaW5fdGFibGUtdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9zdHJhaW5fdGFibGUKY29tYmluZWRfdG9fdHN2KGhzX21hY3Jfc3RyYWluX3RhYmxlLCBjZWxsdHlwZSA9ICJtYWNyb3BoYWdlIikKCmhzX21hY3Jfc3RyYWluX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX21hY3Jfc3RyYWluX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL21hY3JvcGhhZ2Vvbmx5X29ubHlzdHJhaW5fc2lnLXZ7dmVyfS54bHN4IikpCmhzX21hY3Jfc3RyYWluX3NpZwoKaHNfbWFjcl9zdHJhaW5faGlnaHNpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX21hY3Jfc3RyYWluX3RhYmxlLCBtaW5fbWVhbl9leHBycyA9IGhpZ2hfZXhwcmVzc2lvbiwgZXhwcnNfY29sdW1uID0gaGlnaF9leHByZXNzaW9uX2NvbHVtbiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlb25seV9vbmx5c3RyYWluX2hpZ2hzaWctdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9zdHJhaW5faGlnaHNpZwoKaHNfbWFjcl9zdHJhaW5fbGVzc3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX21hY3Jfc3RyYWluX3RhYmxlLCBsZmMgPSAwLjYsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZW9ubHlfb25seXN0cmFpbl9sZXNzc2lnLXZ7dmVyfS54bHN4IikpCmhzX21hY3Jfc3RyYWluX2xlc3NzaWcKYGBgCgojIyMgQ29tcGFyZSBEcnVnIGFuZCBTdHJhaW4gRWZmZWN0cwoKTm93IGxldCB1cyBjb25zaWRlciB0aGUgYWJvdmUgdHdvIGNvbXBhcmlzb25zIHRvZ2V0aGVyLiAgRmlyc3QsIEkgd2lsbApwbG90IHRoZSBsb2dGQyB2YWx1ZXMgb2YgdGhlbSBhZ2FpbnN0IGVhY2ggb3RoZXIgKGRydWcgb24geC1heGlzIGFuZApzdHJhaW4gb24gdGhlIHktYXhpcykuICBUaGVuIHdlIGNhbiBleHRyYWN0IHRoZSBzaWduaWZpY2FudCBnZW5lcyBpbiBhCmZldyBjb21iaW5lZCBjYXRlZ29yaWVzIG9mIGludGVyZXN0LiAgSSBhc3N1bWUgdGhlc2Ugd2lsbCBmb2N1cwpleGNsdXNpdmVseSBvbiB0aGUgY2F0ZWdvcmllcyB3aGljaCBpbmNsdWRlIHRoZSBpbnRyb2R1Y3Rpb24gb2YgdGhlCmRydWcuCgpgYGB7cn0KZHJ1Z19zdHJhaW5fY29tcF9kZiA8LSBtZXJnZShoc19tYWNyX2RydWdfdGFibGVbWyJkYXRhIl1dW1siZHJ1ZyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoc19tYWNyX3N0cmFpbl90YWJsZVtbImRhdGEiXV1bWyJzdHJhaW4iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAicm93Lm5hbWVzIikKZHJ1Z19zdHJhaW5fY29tcF9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoCiAgZHJ1Z19zdHJhaW5fY29tcF9kZlssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKIyMgQ29udHJhc3RzOiBhbnRpbW9ueS9ub25lLCB6MjMvejIyOyB4LWF4aXM6IGRydWcsIHktYXhpczogc3RyYWluCiMjIHRvcCBsZWZ0OiBoaWdoZXIgbm8gZHJ1ZywgejIzOyB0b3AgcmlnaHQ6IGhpZ2hlciBkcnVnIHoyMwojIyBib3R0b20gbGVmdDogaGlnaGVyIG5vIGRydWcsIHoyMjsgYm90dG9tIHJpZ2h0OiBoaWdoZXIgZHJ1ZyB6MjIKZHJ1Z19zdHJhaW5fY29tcF9wbG90W1sic2NhdHRlciJdXQpgYGAKCkFzIEkgbm90ZWQgaW4gdGhlIGNvbW1lbnRzIGFib3ZlLCBzb21lIHF1YWRyYW50cyBvZiB0aGUgc2NhdHRlciBwbG90CmFyZSBsaWtlbHkgdG8gYmUgb2YgZ3JlYXRlciBpbnRlcmVzdCB0byB1cyB0aGFuIG90aGVycyAodGhlIHJpZ2h0CnNpZGUpLiAgQmVjYXVzZSBJIGdldCBjb25mdXNlZCBzb21ldGltZXMsIHRoZSBmb2xsb3dpbmcgYmxvY2sgd2lsbApleHBsaWNpdGx5IG5hbWUgdGhlIGNhdGVnb3JpZXMgb2YgbGlrZWx5IGludGVyZXN0LCB0aGVuIGFzayB3aGljaApnZW5lcyBhcmUgc2hhcmVkIGFtb25nIHRoZW0sIGFuZCBmaW5hbGx5IHVzZSBVcFNldFIgdG8gZXh0cmFjdCB0aGUKdmFyaW91cyBnZW5lIGludGVyc2VjdGlvbi91bmlvbiBjYXRlZ29yaWVzLgoKYGBge3J9CmhpZ2hlcl9kcnVnIDwtIGhzX21hY3JfZHJ1Z19zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1sxXV0KaGlnaGVyX25vZHJ1ZyA8LSBoc19tYWNyX2RydWdfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWzFdXQpoaWdoZXJfejIzIDwtIGhzX21hY3Jfc3RyYWluX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1sxXV0KaGlnaGVyX3oyMiA8LSBoc19tYWNyX3N0cmFpbl9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1sxXV0Kc3VtKHJvd25hbWVzKGhpZ2hlcl9kcnVnKSAlaW4lIHJvd25hbWVzKGhpZ2hlcl96MjMpKQpzdW0ocm93bmFtZXMoaGlnaGVyX2RydWcpICVpbiUgcm93bmFtZXMoaGlnaGVyX3oyMikpCnN1bShyb3duYW1lcyhoaWdoZXJfbm9kcnVnKSAlaW4lIHJvd25hbWVzKGhpZ2hlcl96MjMpKQpzdW0ocm93bmFtZXMoaGlnaGVyX25vZHJ1ZykgJWluJSByb3duYW1lcyhoaWdoZXJfejIyKSkKCmRydWdfejIzX2xzdCA8LSBsaXN0KCJkcnVnIiA9IHJvd25hbWVzKGhpZ2hlcl9kcnVnKSwKICAgICAgICAgICAgICAgICAgICAgInoyMyIgPSByb3duYW1lcyhoaWdoZXJfejIzKSkKdXBzZXRfaW5wdXQgPC0gVXBTZXRSOjpmcm9tTGlzdChkcnVnX3oyM19sc3QpCmhpZ2hlcl9kcnVnX3oyMyA8LSB1cHNldCh1cHNldF9pbnB1dCwgdGV4dC5zY2FsZSA9IDIpCmhpZ2hlcl9kcnVnX3oyMwoKZHJ1Z196MjNfc2hhcmVkX2dlbmVzIDwtIG92ZXJsYXBfZ3JvdXBzKGRydWdfejIzX2xzdCkKc2hhcmVkX2dlbmVzX2RydWdfejIzIDwtIG92ZXJsYXBfZ2VuZWlkcyhkcnVnX3oyM19zaGFyZWRfZ2VuZXMsICJkcnVnOnoyMyIpCnNoYXJlZF9nZW5lc19kcnVnX3oyMyA8LSBhdHRyKGRydWdfejIzX3NoYXJlZF9nZW5lcywgImVsZW1lbnRzIilbZHJ1Z196MjNfc2hhcmVkX2dlbmVzW1siZHJ1Zzp6MjMiXV1dCgpkcnVnX3oyMl9sc3QgPC0gbGlzdCgiZHJ1ZyIgPSByb3duYW1lcyhoaWdoZXJfZHJ1ZyksCiAgICAgICAgICAgICAgICAgICAgICJ6MjIiID0gcm93bmFtZXMoaGlnaGVyX3oyMikpCmhpZ2hlcl9kcnVnX3oyMiA8LSB1cHNldChVcFNldFI6OmZyb21MaXN0KGRydWdfejIyX2xzdCksIHRleHQuc2NhbGUgPSAyKQpoaWdoZXJfZHJ1Z196MjIKCmRydWdfejIyX3NoYXJlZF9nZW5lcyA8LSBvdmVybGFwX2dyb3VwcyhkcnVnX3oyMl9sc3QpCnNoYXJlZF9nZW5lc19kcnVnX3oyMiA8LSBvdmVybGFwX2dlbmVpZHMoZHJ1Z196MjJfc2hhcmVkX2dlbmVzLCAiZHJ1Zzp6MjIiKQpzaGFyZWRfZ2VuZXNfZHJ1Z196MjIgPC0gYXR0cihkcnVnX3oyMl9zaGFyZWRfZ2VuZXMsICJlbGVtZW50cyIpW2RydWdfejIyX3NoYXJlZF9nZW5lc1tbImRydWc6ejIyIl1dXQpgYGAKCiMjIyBQZXJmb3JtIGdQcm9maWxlciBvbiBkcnVnL3N0cmFpbiBlZmZlY3Qgc2hhcmVkIGdlbmVzCgpOb3cgdGhhdCB3ZSBoYXZlIHNvbWUgcG9wdWxhdGlvbnMgb2YgZ2VuZXMgd2hpY2ggYXJlIHNoYXJlZCBhY3Jvc3MgdGhlCmRydWcvc3RyYWluIGVmZmVjdHMsIGxldCB1cyBwYXNzIHRoZW0gdG8gc29tZSBHU0VBIGFuYWx5c2VzIGFuZCBzZWUKd2hhdCBwb3BzIG91dC4KCmBgYHtyfQp3YW50ZWQgPC0gZHJ1Z196MjNfc2hhcmVkX2dlbmVzW1siZHJ1Zzp6MjMiXV0Kc2hhcmVkX2dlbmVzX2RydWdfejIzIDwtIGF0dHIoZHJ1Z196MjNfc2hhcmVkX2dlbmVzLCAiZWxlbWVudHMiKVt3YW50ZWRdCnNoYXJlZF9kcnVnX3oyM19ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNoYXJlZF9nZW5lc19kcnVnX3oyMykKc2hhcmVkX2RydWdfejIzX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0Kc2hhcmVkX2RydWdfejIzX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siQlAiXV0Kc2hhcmVkX2RydWdfejIzX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQoKd2FudGVkIDwtIGRydWdfejIyX3NoYXJlZF9nZW5lc1tbImRydWc6ejIyIl1dCnNoYXJlZF9nZW5lc19kcnVnX3oyMiA8LSBhdHRyKGRydWdfejIyX3NoYXJlZF9nZW5lcywgImVsZW1lbnRzIilbd2FudGVkXQpzaGFyZWRfZHJ1Z196MjJfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihzaGFyZWRfZ2VuZXNfZHJ1Z196MjIpCnNoYXJlZF9kcnVnX3oyMl9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCmBgYAoKIyBPdXIgbWFpbiBxdWVzdGlvbiBvZiBpbnRlcmVzdAoKVGhlIGRhdGEgc3RydWN0dXJlIGhzX21hY3IgY29udGFpbnMgb3VyIHByaW1hcnkgbWFjcm9waGFnZXMsIHdoaWNoCmFyZSwgYXMgc2hvd24gYWJvdmUsIHRoZSBkYXRhIHdlIGNhbiByZWFsbHkgc2luayBvdXIgdGVldGggaW50by4KCk5vdGUsIHdlIGV4cGVjdCBzb21lIGVycm9ycyB3aGVuIHJ1bm5pbmcgdGhlIGNvbWJpbmVfZGVfdGFibGVzKCkKYmVjYXVzZSBub3QgYWxsIG1ldGhvZHMgSSB1c2UgYXJlIGNvbWZvcnRhYmxlIHVzaW5nIHRoZSByYXRpbyBvcgpyYXRpb3MgY29udHJhc3RzIHdlIGFkZGVkIGluIHRoZSAnZXh0cmFzJyBhcmd1bWVudC4gIEFzIGEgcmVzdWx0LCB3aGVuCndlIGNvbWJpbmUgdGhlbSBpbnRvIHRoZSBsYXJnZXIgb3V0cHV0IHRhYmxlcywgdGhvc2UgcGVjdWxpYXIKY29udHJhc3RzIGZhaWwuICBUaGlzIGRvZXMgbm90IHN0b3AgaXQgZnJvbSB3cml0aW5nIHRoZSByZXN0IG9mIHRoZQpyZXN1bHRzLCBob3dldmVyLgoKYGBge3J9CiN0ZXN0ID0gZGVzZXFfcGFpcndpc2Uobm9ybWFsaXplX3NlKGhzX21hY3IsIGZpbHRlcj1UUlVFKSwKIyAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9zdnMgPSAic3Zhc2VxIiwgZmlsdGVyID0gVFJVRSwKIyAgICAgICAgICAgICAgICAgICAgICBleHRyYV9jb250cmFzdHMgPSB0bXJjMl9odW1hbl9leHRyYSkKCmhzX21hY3JfZGVfbm9leHRyYSA8LSBhbGxfcGFpcndpc2UoaHNfbWFjciwgbW9kZWxfc3ZzID0gInN2YXNlcSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfZnN0cmluZyA9ICJ+IDAgKyBjb25kaXRpb24iLCBmaWx0ZXIgPSBUUlVFKQoKaHNfbWFjcl9kZSA8LSBhbGxfcGFpcndpc2UoaHNfbWFjciwgbW9kZWxfc3ZzID0gInN2YXNlcSIsIG1vZGVsX2ZzdHJpbmcgPSAifiAwICsgY29uZGl0aW9uIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyID0gVFJVRSwgZXh0cmFfY29udHJhc3RzID0gdG1yYzJfaHVtYW5fZXh0cmEpCmhzX21hY3JfZGUKCmhzX3NpbmdsZV90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBoc19tYWNyX2RlLCBrZWVwZXJzID0gc2luZ2xlX3RtcmMyX2tlZXBlciwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL2hzX21hY3JfZHJ1Z196eW1vX3oyMnNiX3NiLXZ7dmVyfS54bHN4IikpCmhzX3NpbmdsZV90YWJsZQpoc19tYWNyX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGhzX21hY3JfZGUsIGtlZXBlcnMgPSB0bXJjMl9odW1hbl9rZWVwZXJzLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9kZV90YWJsZXMvaHNfbWFjcl9kcnVnX3p5bW9fdGFibGVfbWFjcl9vbmx5LXZ7dmVyfS54bHN4IikpCmhzX21hY3JfdGFibGUKI2NvbWJpbmVkX3RvX3Rzdihoc19tYWNyX3RhYmxlLCAibWFjcm9waGFnZSIpCgpoc19tYWNyX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX21hY3JfdGFibGUsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvaHNfbWFjcl9kcnVnX3p5bW9fc2lnLXZ7dmVyfS54bHN4IikpCmhzX21hY3Jfc2lnCmhzX21hY3JfaGlnaHNpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX21hY3JfdGFibGUsIG1pbl9tZWFuX2V4cHJzID0gaGlnaF9leHByZXNzaW9uLCBleHByc19jb2x1bW4gPSBoaWdoX2V4cHJlc3Npb25fY29sdW1uLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL2hzX21hY3JfZHJ1Z196eW1vX2hpZ2hzaWctdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9oaWdoc2lnCmhzX21hY3JfbGVzc3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX21hY3JfdGFibGUsIGxmYyA9IDAuNiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9oc19tYWNyX2RydWdfenltb19zaWdfbGZjMC42LXZ7dmVyfS54bHN4IikpCmhzX21hY3JfbGVzc3NpZwpgYGAKCiMjIGdlbmUgZ3JvdXAgdXBzZXQKCiMjIyAyLjMgdnMgMi4yIHVwIGFuZCBkb3duIHZzLiB1bmluZmVjdGVkCgpUaGlzIGlzIG15IHZlcnNpb24gb2YgdGhlIFZlbm4gZGlhZ3JhbSB3aGljaCBpbmNsdWRlcyB0aGUgdGV4dDoKCiJEaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgaW4gbWFjcm9waGFnZXMgaW5mZWN0ZWQgd2l0aApzdWJwb3B1bGF0aW9ucyAyLjIgb3IgMi4zLiAgVm9sY2FubyBwbG90cyBjb250cmFzdCBvZjogQS4gVmVubiBkaWFncmFtCmZvciB1cHJlZ3VsYXRlZCBhbmQgZG93bnJlZ3VsYXRlZCBnZW5lcyBieSBpbmZlY3Rpb24gd2l0aCAyLjMgYW5kIDIuMgpzdHJhaW5zLiBCLiBpbmZlY3RlZCBjZWxscyB3aXRoIDIuMyBzdHJhaW5zIGFuZCB1bmluZmVjdGVkIGNlbGxzOwpDLiBpbmZlY3RlZCBjZWxscyB3aXRoIDIuMiBzdHJhaW5zIGFuZCB1bmluZmVjdGVkIGNlbGxzOyBELiBpbmZlY3RlZApjZWxscyB3aXRoIDIuMyBzdHJhaW5zIGFuZCBpbmZlY3RlZCBjZWxscyB3aXRoIDIuMiBzdHJhaW5zIgoKVGhlIGZvbGxvd2luZyB1cHNldCBwbG90IGlzIGN1cnJlbnRseSBGaWd1cmUgMkUuCgpgYGB7cn0Kbm9kcnVnX3Vwc2V0IDwtIHVwc2V0cl9jb21iaW5lZF9kZShoc19tYWNyX3RhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2lyZWRfY29udHJhc3RzID0gYygiejIybm9zYl92c191bmluZiIsICJ6MjNub3NiX3ZzX3VuaW5mIikpCnBwKGZpbGUgPSAiaW1hZ2VzL25vZHJ1Z191cHNldC5zdmciKQpub2RydWdfdXBzZXRbWyJwbG90Il1dCmRldi5vZmYoKQpub2RydWdfdXBzZXQKYGBgCgojIyMjIEEgcG9pbnQgb2YgaW50ZXJlc3Qgd2hpbGUgT2xnYSB2aXNpdHMgVW1kCgpOYWppYiBhbmQgT2xnYSBhc2tlZCBhYm91dCBwdWxsaW5nIHRoZSA5IGdlbmUgSURzIHdoaWNoIGFyZSBpbiB0aGUKcGVjdWxpYXIgc2l0dWF0aW9uIG9mIGluY3JlYXNlZCBleHByZXNzaW9uIGluIHoyLjIvdW5pbmYgYW5kIGRlY3JlYXNlZAppbiB6Mi4zL3VuaW5mLiAgSW4gdGhlIHByZXZpb3VzIHVwc2V0IHBsb3QsIHRoZXNlIGFyZSB2aXNpYmxlIGluIHRoZQo2dGggYmFyLiAgSSBjYW4gYWNjZXNzIHRoZXNlIHZpYSB0aGUgYXR0cigpIGZ1bmN0aW9uLCB3aGljaCBJIHNob3VsZAphZG1pdCBJIGNhbiBuZXZlciByZW1lbWJlciBob3cgdG8gdXNlLCBzbyBJIGFtIGdvaW5nIHRvIHVzZSB0aGUgY29kZQp1bmRlciB0aGUgJ0NvbXBhcmUobm8pU2IgejIuMy96Mi4yIHRyZWF0bWVudCcgaGVhZGluZyB0byByZW1lbWJlciBob3cKdG8gZXh0cmFjdCB0aGVzZSBnZW5lcy4KCmBgYHtyfQphbGxfZ3JvdXBzIDwtIG5vZHJ1Z191cHNldFtbImdyb3VwcyJdXQp3YW50ZWRfZ3JvdXAgPC0gInoyM25vc2JfdnNfdW5pbmZfZG93bjp6MjJub3NiX3ZzX3VuaW5mX3VwIgpnZW5lX2lkeCA8LSBhbGxfZ3JvdXBzW1t3YW50ZWRfZ3JvdXBdXQp3YW50ZWRfZ2VuZXMgPC0gYXR0cihhbGxfZ3JvdXBzLCAiZWxlbWVudHMiKVtnZW5lX2lkeF0Kd2FudGVkX2dlbmVzCmdlbmVfc3ltYm9sX2lkeCA8LSByb3duYW1lcyhmRGF0YShoc19tYWNyKSkgJWluJSBhcy5jaGFyYWN0ZXIod2FudGVkX2dlbmVzKQpmRGF0YShoc19tYWNyKVtnZW5lX3N5bWJvbF9pZHgsICJoZ25jX3N5bWJvbCJdCmBgYAoKKiBBQkNCNTogQVRCIEJpbmRpbmcgQ2Fzc2V0dGUgU3ViZmFtaWx5IEIgTWVtYmVyICM1LCB3aWRlIHJhbmdlIG9mCiAgZnVuY3Rpb25zIGluIHRoaXMgZGl2ZXJzZSBwYXJhbG9nb3VzIGZhbWlseS4gIEFzc29jaWF0ZWQgd2l0aCBza2luCiAgZGlzZWFzZXMgKG1lbGFub21hIGFuZCBFcGlkZXJtb2x5c2lzIEJ1bGxvc2E7IHBhcnRpY2lwYXRlIGluCiAgQVRQLWRlcGVuZGVudCB0cmFuc21lbWJyYW5lIHRyYW5zcG9ydCkuCiogUkZYNDogUmVndWxhdG9yeSBGYWN0b3IgWCAjNDogdHJhbnNjcmlwdGlvbiBmYWN0b3IuCiogQ0ExNDogQ2FyYm9uaWMgYW5oeWRyYXNlICMxNDogWnluYyBtZXRhbGxvZW56eW1lIGNhdGFseXplcwogIHJldmVyc2libGUgaHlkcmF0aW9uIG9mIENPMi4gIFRoaXMgZ2VuZSBsb29rcyBwcmV0dHkgbmVhdCwgYnV0IG5vdAogIHJlYWxseSByZWxldmFudCB0byBhbnl0aGluZyB3ZSBhcmUgbGlrZWx5IHRvIGNhcmUgYWJvdXQuCiogRUdSMTogRWFybHkgR3Jvd3RoIFJlc3BvbnNlIFByb3RlaW4gIzE6IEFub3RoZXIgVHggZmFjdG9yCiAgKHppbmMtZmluZ2VyKSAtLSBpbXBvcnRhbnQgZm9yIGNlbGwgc3Vydml2YWwvcHJvbGlmZXJhdGlvbi9jZWxsCiAgZGVhdGguICBQcmVzdW1hYmx5IGltcG9ydGFudCBmb3IgaGVhbGluZz8KKiBNQ0YyTDogTUNGLjIgQ2VsbCBMaW5lIERlcml2ZWQgVHJhbnNmb3JtaW5nIFNlcXVlbmNlIExpa2U/ICBndWFuaW5lCiAgbnVjbGVvdGlkZSBleGNoYW5nZSBmYWN0b3IgaW50ZXJhY3Rpbmcgd2l0aCBHVFAtYm91bmQgUmFjMS4KICBBcHBhcmVudGx5IGFzc29jaWF0ZWQgd2l0aCBvc3Ryb2FydGhyaXRpczsgcG90ZW50aWFsbHkgcmVsZXZhbnQgdG8KICByZWd1bGF0aW9uIG9mIFJIT0EgYW5kIENEQzQyIHNpZ25hbGxpbmcuCiogRE5BU0UxTDM6IERlb3h5cmlib251Y2xlYXNlIEkgZmFtaWx5IG1lbWJlcjogbm90IGluaGliaXRlZCBieSBhY3RpbiwKICBicmVha3MgZG93biBETkEgZHVyaW5nIGFwb3B0b3Npcy4gIEltcG9ydGFudCBkdXJpbmcgbmVjcm9zaXMuCiogRk9TOiBQcm90by1PbmNvZ2VuZSwgQVAtMSBUcmFuc2NyaXB0aW9uIEZhY3RvcjogbGV1Y2luZSB6aXBwZXIKICBkaW1lcml6ZXMgd2l0aCBKVU4gZmFtaWx5IHByb3RlaW5zLCBmb3JtaW5nIHR4IGZhY3RvciBjb21wbGV4IEFQLTEuCiAgSW1wb3J0YW50IGZvciBjZWxsIHByb2xpZmVyYXRpb24sIGRpZmZlcmVudGlhdGlvbiwgYW5kCiAgdHJhbnNmb3JtYXRpb24uCiogSUZJVE0xMDogSW50ZXJmZXJvbi1JbmR1Y2VkIFRyYW5zbWVtYnJhbmUgUHJvdGVpbiAjMTAKKiBQS0QxTDM6IFBvbHljeXN0aW4gMSBMaWtlICMzLCBUcmFuc2llbnQgUmVjZXB0b3IgUG90ZW50aWFsIENoYW5uZWwKICBJbnRlcmFjdGluZzogMTEgdHJhbnNtZW1icmFuZSBkb21haW4gcHJvdGVpbiB3aGljaCBtaWdodCBoZWxwIGNyZWF0ZQogIGNhdGlvbiBjaGFubmVscy4KCkFzIHNvbWUgY29tcGFyaXNvbiBwb2ludHMsIHRoZSBWZW5uIGluIHRoZSBjdXJyZW50IGZpZ3VyZSBoYXM6CgoqIDM4NyB1cCB6Mi4zCiogMjU5IHVwIHoyLjIKKiA4MyBzaGFyZWQgdXAgejIuMyBhbmQgejIuMgoqIDI0NyBkb3duIHoyLjMKKiAzIGRvd24gejIuMgoqIDMgc2hhcmVkIGRvd24gejIuMyBhbmQgejIuMgoKIyMjIDIuMiBhbmQgMi4zIHdpdGggU2JWIHZzIDIuMiBhbmQgMi4zIHdpdGhvdXQgU2JWCgpUaGlzIGlzIG15IHZlcnNpb24gb2YgdGhlIFZlbm4gd2l0aCB0aGUgdGV4dDoKCiJEaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgaW4gbWFjcm9waGFnZXMgaW5mZWN0ZWQgd2l0aApzdWJwb3B1bGF0aW9ucyAyLjIgb3IgMi4zLCBpbiBwcmVzZW5jZSBvZiBTYlYuIFZvbGNhbm8gcGxvdHMgY29udHJhc3QKb2Y6IEEuIGluZmVjdGVkIGNlbGxzIHdpdGggMi4zIHN0cmFpbnMgKyBTYlYgYW5kIGluZmVjdGVkIGNlbGxzIHdpdGgKMi4zIHN0cmFpbnM7IEIuIGluZmVjdGVkIGNlbGxzIHdpdGggMi4yIHN0cmFpbnMgKyBTYlYgYW5kIGluZmVjdGVkCmNlbGxzIHdpdGggMi4yIHN0cmFpbnM7IEMuIGluZmVjdGVkIGNlbGxzIHdpdGggMi4zIHN0cmFpbnMgKyBTYlYgYW5kCmluZmVjdGVkIGNlbGxzIHdpdGggMi4yIHN0cmFpbnMgKyBTYlYuIEQuIFZlbm4gZGlhZ3JhbSBmb3IgdXByZWd1bGF0ZWQKYW5kIGRvd25yZWd1bGF0ZWQgZ2VuZXMgYnkgaW5mZWN0aW9uIHdpdGggMi4zK1NiViBhbmQgMi4yK1NiVgpzdHJhaW5zLiIKCkEgcXVlcnkgZnJvbSBPbGdhICgyMDI0MDgwMSk6IFBsZWFzZSBpbmNsdWRlIGluIHRoZSB1cHNldCBpbiBmaWd1cmUgMwp0aGUgY29udHJhc3Qgb2YgdW5pbmZlY3RlZCBjZWxscyArIFNiViB2cyB1bmluZmVjdGVkIHdpdGhvdXQgU2JWLgoKYGBge3J9CiMjIEkga2VlcCBtaXMtaW50ZXJwcmV0aW5nIHRoaXMgdGV4dCwgaXQgaXMgejIuMy96Mi4zU2JWIGFuZCB6Mi4yL3oyLjJTYlYKZHJ1Z25vZHJ1Z191cHNldCA8LSB1cHNldHJfY29tYmluZWRfZGUoaHNfbWFjcl90YWJsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaXJlZF9jb250cmFzdHMgPSBjKCJ6MjNzYl92c196MjNub3NiIiwgInoyMnNiX3ZzX3oyMm5vc2IiKSkKcHAoZmlsZSA9ICJpbWFnZXMvZHJ1Z25vZHJ1Z191cHNldC5wZGYiKQpkcnVnbm9kcnVnX3Vwc2V0W1sicGxvdCJdXQpkZXYub2ZmKCkKZHJ1Z25vZHJ1Z191cHNldAoKZHJ1Z25vZHJ1Z191bmluZl9jb250cmFzdHMgPC0gYygiejIzc2JfdnNfejIzbm9zYiIsICJ6MjJzYl92c196MjJub3NiIiwgInNiX3ZzX3VuaW5mIikKZHJ1Z25vZHJ1Z191cHNldF93aXRoX3VuaW5mIDwtIHVwc2V0cl9jb21iaW5lZF9kZShoc19tYWNyX3RhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpcmVkX2NvbnRyYXN0cyA9IGRydWdub2RydWdfdW5pbmZfY29udHJhc3RzKQpwcChmaWxlID0gImZpZ3VyZXMvZHJ1Z25vZHJ1Z193aXRoX3VuaW5mX3Vwc2V0LnN2ZyIpCmRydWdub2RydWdfdXBzZXRfd2l0aF91bmluZltbInBsb3QiXV0KZGV2Lm9mZigpCmRydWdub2RydWdfdXBzZXRfd2l0aF91bmluZgpgYGAKCkZvciBzb21lIGNvbXBhcmlzb24gcG9pbnRzLCB0aGUgdmVubiBpbWFnZSBoYXM6CgoqIDIyMiB1cCB6Mi4zIFNiVgoqIDEzNCB1cCB6Mi4yIFNiVgoqIDE4MiBkb3duIHoyLjMgU2JWCiogMzk2IGRvd24gejIuMiBTYlYKKiA2MDUgc2hhcmVkIGRvd24gejIuMiBhbmQgejIuMyBTYlYKKiAzNCBzaGFyZWQgZG93biB6Mi4yIFNiViBhbmQgdXAgejIuMyBTYlYKKiAzNjMgc2hhcmVkIHVwIHoyLjIgU2JWIGFuZCB6Mi4zIFNiVgoKIyMjIENvbXBhcmUgejIuMlNiViB2cyBTYlYgYW5kIHoyLjNTYlYgYW5kIFNiVgoKYGBge3J9CmRydWdfdXBzZXQgPC0gdXBzZXRyX2NvbWJpbmVkX2RlKGhzX21hY3JfdGFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2lyZWRfY29udHJhc3RzID0gYygiejIyc2JfdnNfc2IiLCAiejIzc2JfdnNfc2IiKSkKcHAoZmlsZSA9ICJpbWFnZXMvZHJ1Z191cHNldC5wZGYiKQpkcnVnX3Vwc2V0W1sicGxvdCJdXQpkZXYub2ZmKCkKZHJ1Z191cHNldApgYGAKCiMjIFNpZ25pZmljYW5jZSBiYXJwbG90IG9mIGludGVyZXN0CgpPbGdhIGtpbmRseSBzZW50IGEgc2V0IG9mIHBhcnRpY3VsYXJseSBpbnRlcmVzdGluZyBjb250cmFzdHMgYW5kCmNvbG9ycyBmb3IgYSBzaWduaWZpY2FuY2UgYmFycGxvdCwgdGhleSBpbmNsdWRlIHRoZSBmb2xsb3dpbmc6CgoqIHoyLjMgdnMuIHVuaW5mZWN0ZWQuCiogejIuMiB2cy4gdW5pbmZlY3RlZC4KKiB6Mi4zIHZzIHoyLjIKKiB6Mi4zU2J2IHZzIHoyLjMKKiB6Mi4yU2J2IHZzIHoyLjIKKiB6Mi4zU2J2IHZzIHoyLjJTYnYKKiBTYnYgdnMgdW5pbmZlY3RlZC4KClRoZSBleGlzdGluZyBzZXQgb2YgJ2tlZXBlcnMnIGV4dmlzZWQgdG8gdGhlc2UgaXMgdGFrZW4gZnJvbSB0aGUKZXh0YW50IHNldCBvZiAndG1yYzJfaHVtYW5fa2VlcGVycycgYW5kIGlzIGFzIGZvbGxvd3M6CgoKYGBge3J9CmJhcnBsb3Rfa2VlcGVycyA8LSBsaXN0KAogICMjIHoyLjMgdnMgdW5pbmZlY3RlZAogICJ6MjNub3NiX3ZzX3VuaW5mIiA9IGMoImluZnoyMyIsICJ1bmluZm5vbmUiKSwKICAjIyB6Mi4yIHZzIHVuaW5mZWN0ZWQKICAiejIybm9zYl92c191bmluZiIgPSBjKCJpbmZ6MjIiLCAidW5pbmZub25lIiksCiAgIyMgejIuMyB2cyB6Mi4yCiAgInoyM25vc2JfdnNfejIybm9zYiIgPSBjKCJpbmZ6MjMiLCAiaW5mejIyIiksCiAgIyMgejIuM1NidiB2cyB6Mi4zCiAgInoyM3NiX3ZzX3oyM25vc2IiID0gYygiaW5mc2J6MjMiLCAiaW5mejIzIiksCiAgIyMgejIuMlNidiB2cyB6Mi4yCiAgInoyMnNiX3ZzX3oyMm5vc2IiID0gYygiaW5mc2J6MjIiLCAiaW5mejIyIiksCiAgIyMgejIuM1NidiB2cyB6Mi4yU2J2CiAgInoyM3NiX3ZzX3oyMnNiIiA9IGMoImluZnNiejIzIiwgImluZnNiejIyIiksCiAgIyMgU2J2IHZzIHVuaW5mZWN0ZWQuCiAgInNiX3ZzX3VuaW5mIiA9IGMoInVuaW5mc2Jub25lIiwgInVuaW5mbm9uZSIpKQpiYXJwbG90X2NvbWJpbmVkIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGhzX21hY3JfZGUsIGtlZXBlcnMgPSBiYXJwbG90X2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9oc19tYWNyX2RydWdfenltb183Y29udHJhc3RzLXZ7dmVyfS54bHN4IikpCmBgYAoKTm93IGxldCB1cyB1c2UgdGhlIGNvbG9ycyBzdWdnZXN0ZWQgYnkgT2xnYSB0byBtYWtlIGEgYmFycGxvdCBvZgp0aGVzZS4uLgoKYGBge3J9CmNvbG9yX2xpc3QgPC0gIGMoICIjZGU4YmY5IiwgIiNhZDA3ZTMiLCIjNDEwMjU3IiwgIiNmZmEwYTAiLCAiI2Y5NDA0MCIsICIjYTAwMDAwIikKYmFycGxvdF9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBiYXJwbG90X2NvbWJpbmVkLCBjb2xvcl9saXN0ID0gY29sb3JfbGlzdCwgYWNjb3JkaW5nX3RvID0gImRlc2VxIiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9oc19tYWNyX2RydWdfenltb183Y29udHJhc3RzX3NpZy12e3Zlcn0ueGxzeCIpKQpiYXJwbG90X3NpZwpgYGAKCiMgUFJPUEVSCgpJbiBvdXIgbGFzdCBtZWV0aW5nIHRoZXJlIHdlcmUgc29tZSBxdWVzdGlvbnMgYWJvdXQgdGhlIHN0YXRpc3RpY2FsCnBvd2VyIG9mIGRpZmZlcmVudCBmdXR1cmUgZXhwZXJpbWVudGFsIGRlc2lnbnMuICBPbmUgdGhpbmcgSSBjYW4gZG8gaXMKdG8gdXNlIFBST1BFUiB0byBlc3RpbWF0ZSB0aGUgcG93ZXIgb2YgYW4gZXh0YW50IGRhdGFzZXQgYW5kIGluZmVyCmZyb20gdGhhdCB0aGUgbGlrZWx5IHBvd2VyIG9mIG90aGVyIGRlc2lnbnMuCgpJbiBvcmRlciB0byB1c2UgcHJvcGVyLCBvbmUgbXVzdCBmZWVkIGl0IG9uZSBvciBtb3JlIERFIHRhYmxlcy4KCmBgYHtyfQpwb3dlcl9lc3RpbWF0ZSA8LSBzaW1wbGVfcHJvcGVyKGhzX3NpbmdsZV90YWJsZSkKCnBvd2VyX2VzdGltYXRlW1sxXV1bWyJwb3dlcl9wbG90Il1dCnBvd2VyX2VzdGltYXRlW1sxXV1bWyJwb3dlcnRkX3Bsb3QiXV0KcG93ZXJfZXN0aW1hdGVbWzFdXVtbInBvd2VyZmRfcGxvdCJdXQpgYGAKCiMgT3VyIG1haW4gcXVlc3Rpb25zIGluIFU5MzcKCkxldCB1cyBkbyB0aGUgc2FtZSBjb21wYXJpc29ucyBpbiB0aGUgVTkzNyBzYW1wbGVzLCB0aG91Z2ggSSB3aWxsIG5vdApkbyB0aGUgZXh0cmEgY29udHJhc3RzLCBwcmltYXJpbHkgYmVjYXVzZSBJIHRoaW5rIHRoZSBkYXRhc2V0IGlzIGxlc3MKbGlrZWx5IHRvIHN1cHBvcnQgdGhlbS4KCmBgYHtyfQp1OTM3X2RlIDwtIGFsbF9wYWlyd2lzZSh1OTM3X3NlLCBtb2RlbF9zdnMgPSAic3Zhc2VxIiwKICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyID0gVFJVRSwgbW9kZWxfZnN0cmluZyA9ICJ+IDAgKyBjb25kaXRpb24iKQp1OTM3X2RlCnU5MzdfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgdTkzN19kZSwga2VlcGVycyA9IHU5Mzdfa2VlcGVycywKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL3U5MzdfZHJ1Z196eW1vX3RhYmxlLXZ7dmVyfS54bHN4IikpCnU5MzdfdGFibGUKY29tYmluZWRfdG9fdHN2KHU5MzdfdGFibGUsIGNlbGx0eXBlID0gInU5MzciKQoKdTkzN19zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB1OTM3X3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL3U5MzdfZHJ1Z196eW1vX3NpZy12e3Zlcn0ueGxzeCIpKQp1OTM3X3NpZwp1OTM3X2hpZ2hzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB1OTM3X3RhYmxlLCBtaW5fbWVhbl9leHBycyA9IGhpZ2hfZXhwcmVzc2lvbiwgZXhwcnNfY29sdW1uID0gaGlnaF9leHByZXNzaW9uX2NvbHVtbiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy91OTM3X2RydWdfenltb19oaWdoc2lnLXZ7dmVyfS54bHN4IikpCnU5MzdfaGlnaHNpZwp1OTM3X2xlc3NzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB1OTM3X3RhYmxlLCBsZmMgPSAwLjYsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvdTkzN19kcnVnX3p5bW9fbGVzc3NpZy12e3Zlcn0ueGxzeCIpKQp1OTM3X2xlc3NzaWcKYGBgCgojIENvbXBhcmUgKG5vKVNiIHoyLjMvejIuMiB0cmVhdG1lbnRzIGFtb25nIG1hY3JvcGhhZ2VzCgpJbiB0aGUgZm9sbG93aW5nIGJsb2NrLCBJIHdpbGwganVtcCBiYWNrIHRvIHRoZSBtYWNyb3BoYWdlIHNhbXBsZXMgYW5kCmxvb2sgZm9yIGdlbmVzIHdoaWNoIGFyZSBzaGFyZWQvdW5pcXVlIHdoZW4gY29tcGFyaW5nIHoyLjMvejIuMgpmb3IgdGhlIGRydWcgdHJlYXRlZCBzYW1wbGVzIGFuZCB0aGUgdW50cmVhdGVkIHNhbXBsZXMuCgpgYGB7cn0KdXBzZXRfcGxvdHNfaHNfbWFjciA8LSB1cHNldHJfc2lnKAogIGhzX21hY3Jfc2lnLCBib3RoID0gVFJVRSwKICBjb250cmFzdHMgPSBjKCJ6MjNzYl92c196MjJzYiIsICJ6MjNub3NiX3ZzX3oyMm5vc2IiKSkKdXBzZXRfcGxvdHNfaHNfbWFjcltbImJvdGgiXV0KZ3JvdXBzIDwtIHVwc2V0X3Bsb3RzX2hzX21hY3JbWyJib3RoX2dyb3VwcyJdXQpzaGFyZWRfZ2VuZXMgPC0gYXR0cihncm91cHMsICJlbGVtZW50cyIpW2dyb3Vwc1tbMl1dXSAlPiUKICBnc3ViKHBhdHRlcm4gPSAiXmdlbmU6IiwgcmVwbGFjZW1lbnQgPSAiIikKbGVuZ3RoKHNoYXJlZF9nZW5lcykKCnNoYXJlZF9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNoYXJlZF9nZW5lcykKc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0Kc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siQlAiXV0Kc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQoKZHJ1Z19nZW5lcyA8LSBhdHRyKGdyb3VwcywgImVsZW1lbnRzIilbZ3JvdXBzW1siejIzc2JfdnNfejIyc2IiXV1dICU+JQogIGdzdWIocGF0dGVybiA9ICJeZ2VuZToiLCByZXBsYWNlbWVudCA9ICIiKQpkcnVnb25seV9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKGRydWdfZ2VuZXMpCmRydWdvbmx5X2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siQlAiXV0KYGBgCgpJIHdhbnQgdG8gdHJ5IHNvbWV0aGluZywgZGlyZWN0bHkgaW5jbHVkZSB0aGUgdTkzNyBkYXRhIGluIHRoaXMuClRodXMsIGluIHRoZSBmb2xsb3dpbmcgYmxvY2sgSSB3aWxsIHJlcGVhdCBidXQgY29tcGFyZSBhbGwgc2FtcGxlcyBhbmQKdGhlIFU5MzcgdXNpbmcgdGhlIHNhbWUgbG9naWMuCgpgYGB7cn0KYm90aF9zaWcgPC0gaHNfbWFjcl9zaWcKbmFtZXMoYm90aF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXSkgPC0gcGFzdGUwKCJtYWNyXyIsIG5hbWVzKGJvdGhfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV0pKQpuYW1lcyhib3RoX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV0pIDwtIHBhc3RlMCgibWFjcl8iLCBuYW1lcyhib3RoX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV0pKQp1OTM3X2Rlc2VxIDwtIHU5Mzdfc2lnW1siZGVzZXEiXV0KbmFtZXModTkzN19kZXNlcVtbInVwcyJdXSkgPC0gcGFzdGUwKCJ1OTM3XyIsIG5hbWVzKHU5MzdfZGVzZXFbWyJ1cHMiXV0pKQpuYW1lcyh1OTM3X2Rlc2VxW1siZG93bnMiXV0pIDwtIHBhc3RlMCgidTkzN18iLCBuYW1lcyh1OTM3X2Rlc2VxW1siZG93bnMiXV0pKQpib3RoX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dIDwtIGMoYm90aF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXSwgdTkzN19kZXNlcVtbInVwcyJdXSkKYm90aF9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dIDwtIGMoYm90aF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXSwgdTkzN19kZXNlcVtbImRvd25zIl1dKQpzdW1tYXJ5KGJvdGhfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV0pCgp1cHNldF9wbG90c19ib3RoIDwtIHVwc2V0cl9zaWcoCiAgYm90aF9zaWcsIGJvdGggPSBUUlVFLAogIGNvbnRyYXN0cyA9IGMoIm1hY3JfejIzc2JfdnNfejIyc2IiLCAibWFjcl96MjNub3NiX3ZzX3oyMm5vc2IiLAogICAgICAgICAgICAgICAgInU5MzdfejIzc2JfdnNfejIyc2IiLCAidTkzN196MjNub3NiX3ZzX3oyMm5vc2IiKSkKdXBzZXRfcGxvdHNfYm90aFtbImJvdGgiXV0KYGBgCgojIyBDb21wYXJlIERFIHJlc3VsdHMgZnJvbSBtYWNyb3BoYWdlcyBhbmQgVTkzNyBzYW1wbGVzCgpMb29raW5nIGEgYml0IG1vcmUgY2xvc2VseSBhdCB0aGVzZSwgSSB0aGluayB0aGUgdTkzNyBkYXRhIGlzIHRvbwpzcGFyc2UgdG8gZWZmZWN0aXZlbHkgY29tcGFyZS4KCmBgYHtyfQptYWNyX3U5MzdfY29tcGFyaXNvbiA8LSBjb21wYXJlX2RlX3Jlc3VsdHMoaHNfbWFjcl90YWJsZSwgdTkzN190YWJsZSkKbWFjcl91OTM3X2NvbXBhcmlzb25bWyJsZmNfaGVhdCJdXQoKbWFjcl91OTM3X3Zlbm5zIDwtIGNvbXBhcmVfc2lnbmlmaWNhbnRfY29udHJhc3RzKGhzX21hY3Jfc2lnLCBzZWNvbmRfc2lnX3RhYmxlcyA9IHU5Mzdfc2lnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJhc3RzID0gInoyM3NiX3ZzX3oyM25vc2IiKQptYWNyX3U5MzdfdmVubnNbWyJ1cF9wbG90Il1dCm1hY3JfdTkzN192ZW5uc1tbImRvd25fcGxvdCJdXQoKbWFjcl91OTM3X3Zlbm5zX3YyIDwtIGNvbXBhcmVfc2lnbmlmaWNhbnRfY29udHJhc3RzKAogIGhzX21hY3Jfc2lnLCBzZWNvbmRfc2lnX3RhYmxlcyA9IHU5Mzdfc2lnLCBjb250cmFzdHMgPSAiejIyc2JfdnNfejIybm9zYiIpCm1hY3JfdTkzN192ZW5uc192MltbInVwX3Bsb3QiXV0KbWFjcl91OTM3X3Zlbm5zX3YyW1siZG93bl9wbG90Il1dCgptYWNyX3U5MzdfdmVubnNfdjMgPC0gY29tcGFyZV9zaWduaWZpY2FudF9jb250cmFzdHMoCiAgaHNfbWFjcl9zaWcsIHNlY29uZF9zaWdfdGFibGVzID0gdTkzN19zaWcsIGNvbnRyYXN0cyA9ICJzYl92c191bmluZiIpCm1hY3JfdTkzN192ZW5uc192M1tbInVwX3Bsb3QiXV0KbWFjcl91OTM3X3Zlbm5zX3YzW1siZG93bl9wbG90Il1dCmBgYAoKIyMgQ29tcGFyZSBtYWNyb3BoYWdlL3U5Mzcgd2l0aCByZXNwZWN0IHRvIHoyLjMvejIuMgoKYGBge3J9CmNvbXBhcmlzb25fZGYgPC0gbWVyZ2UoaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNzYl92c196MjJzYiJdXSwKICAgICAgICAgICAgICAgICAgICAgICB1OTM3X3RhYmxlW1siZGF0YSJdXVtbInoyM3NiX3ZzX3oyMnNiIl1dLAogICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInJvdy5uYW1lcyIpCm1hY3J1OTM3X3oyM3oyMl9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoY29tcGFyaXNvbl9kZlssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKbWFjcnU5MzdfejIzejIyX3Bsb3RbWyJzY2F0dGVyIl1dCgpjb21wYXJpc29uX2RmIDwtIG1lcmdlKGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dLAogICAgICAgICAgICAgICAgICAgICAgIHU5MzdfdGFibGVbWyJkYXRhIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dLAogICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInJvdy5uYW1lcyIpCm1hY3J1OTM3X3oyM3oyMl9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoY29tcGFyaXNvbl9kZlssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKbWFjcnU5MzdfejIzejIyX3Bsb3RbWyJzY2F0dGVyIl1dCmBgYAoKIyBBZGQgZG9ub3IgdG8gdGhlIGNvbnRyYXN0cywgbm8gc3ZhCgpJbiB0aGUgZm9sbG93aW5nIGJsb2NrLCBJIHdpbGwgY2hhbmdlIHRoZSBzYW1wbGUgY29uZGl0aW9uIHRvIGluY2x1ZGUKdGhlIGRvbm9yLgoKYGBge3J9Cm5vX3Bvd2VyX2ZhY3QgPC0gcGFzdGUwKHBEYXRhKGhzX21hY3IpW1siZG9ub3IiXV0sICJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgcERhdGEoaHNfbWFjcilbWyJjb25kaXRpb24iXV0pCnRhYmxlKHBEYXRhKGhzX21hY3IpW1siZG9ub3IiXV0pCnRhYmxlKG5vX3Bvd2VyX2ZhY3QpCmhzX25vcG93ZXIgPC0gc2V0X3NlX2NvbmRpdGlvbnMoaHNfbWFjciwgZmFjdCA9IG5vX3Bvd2VyX2ZhY3QpCmhzX25vcG93ZXIgPC0gc3Vic2V0X3NlKGhzX25vcG93ZXIsIHN1YnNldCA9ICJtYWNyb3BoYWdlenltb2RlbWUhPSdub25lJyIpCmhzX25vcG93ZXJfbm9zdmFfZGUgPC0gYWxsX3BhaXJ3aXNlKGhzX25vcG93ZXIsIG1vZGVsX3N2cyA9IEZBTFNFLCBmaWx0ZXIgPSBUUlVFKQpub3Bvd2VyX2tlZXBlcnMgPC0gbGlzdCgKICAiZDAxX3p5bW8iID0gYygiZDAxaW5mejIzIiwgImQwMWluZnoyMiIpLAogICJkMDFfc2J6eW1vIiA9IGMoImQwMWluZnNiejIzIiwgImQwMWluZnNiejIyIiksCiAgImQwMl96eW1vIiA9IGMoImQwMmluZnoyMyIsICJkMDJpbmZ6MjIiKSwKICAiZDAyX3NienltbyIgPSBjKCJkMDJpbmZzYnoyMyIsICJkMDJpbmZzYnoyMiIpLAogICJkMDlfenltbyIgPSBjKCJkMDlpbmZ6MjMiLCAiZDA5aW5mejIyIiksCiAgImQwOV9zYnp5bW8iID0gYygiZDA5aW5mc2J6MjMiLCAiZDA5aW5mc2J6MjIiKSwKICAiZDgxX3p5bW8iID0gYygiZDgxaW5mejIzIiwgImQ4MWluZnoyMiIpLAogICJkODFfc2J6eW1vIiA9IGMoImQ4MWluZnNiejIzIiwgImQ4MWluZnNiejIyIikpCmhzX25vcG93ZXJfbm9zdmFfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgaHNfbm9wb3dlcl9ub3N2YV9kZSwga2VlcGVycyA9IG5vcG93ZXJfa2VlcGVycywKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL2hzX25vcG93ZXJfdGFibGUtdnt2ZXJ9Lnhsc3giKSkKIyMgZXh0cmFfY29udHJhc3RzID0gZXh0cmEpCmhzX25vcG93ZXJfbm9zdmFfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgaHNfbm9wb3dlcl9ub3N2YV90YWJsZSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9oc19ub3Bvd2VyX25vc3ZhX3NpZy12e3Zlcn0ueGxzeCIpKQoKZDAxZDAyX3p5bW9fbm9zdmFfY29tcCA8LSBtZXJnZShoc19ub3Bvd2VyX25vc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwMV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhzX25vcG93ZXJfbm9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDAyX3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAicm93Lm5hbWVzIikKZDAxMDJfenltb19ub3N2YV9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoZDAxZDAyX3p5bW9fbm9zdmFfY29tcFssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKZDAxMDJfenltb19ub3N2YV9wbG90W1sic2NhdHRlciJdXQpkMDEwMl96eW1vX25vc3ZhX3Bsb3RbWyJjb3JyZWxhdGlvbiJdXQpkMDEwMl96eW1vX25vc3ZhX3Bsb3RbWyJsbV9yc3EiXV0KCmQwOWQ4MV96eW1vX25vc3ZhX2NvbXAgPC0gbWVyZ2UoaHNfbm9wb3dlcl9ub3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDlfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoc19ub3Bvd2VyX25vc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQ4MV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInJvdy5uYW1lcyIpCmQwOTgxX3p5bW9fbm9zdmFfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGQwOWQ4MV96eW1vX25vc3ZhX2NvbXBbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCmQwOTgxX3p5bW9fbm9zdmFfcGxvdFtbInNjYXR0ZXIiXV0KZDA5ODFfenltb19ub3N2YV9wbG90W1siY29ycmVsYXRpb24iXV0KZDA5ODFfenltb19ub3N2YV9wbG90W1sibG1fcnNxIl1dCgpkMDFkODFfenltb19ub3N2YV9jb21wIDwtIG1lcmdlKGhzX25vcG93ZXJfbm9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDAxX3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHNfbm9wb3dlcl9ub3N2YV90YWJsZVtbImRhdGEiXV1bWyJkODFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJyb3cubmFtZXMiKQpkMDE4MV96eW1vX25vc3ZhX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihkMDFkODFfenltb19ub3N2YV9jb21wWywgYygiZGVzZXFfbG9nZmMueCIsICJkZXNlcV9sb2dmYy55IildKQpkMDE4MV96eW1vX25vc3ZhX3Bsb3RbWyJzY2F0dGVyIl1dCmQwMTgxX3p5bW9fbm9zdmFfcGxvdFtbImNvcnJlbGF0aW9uIl1dCmQwMTgxX3p5bW9fbm9zdmFfcGxvdFtbImxtX3JzcSJdXQoKdXBzZXRfcGxvdHNfbm9zdmEgPC0gdXBzZXRyX3NpZyhoc19ub3Bvd2VyX25vc3ZhX3NpZywgYm90aCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJhc3RzID0gYygiZDAxX3p5bW8iLCAiZDAyX3p5bW8iLCAiZDA5X3p5bW8iLCAiZDgxX3p5bW8iKSkKdXBzZXRfcGxvdHNfbm9zdmFbWyJ1cCJdXQp1cHNldF9wbG90c19ub3N2YVtbImRvd24iXV0KdXBzZXRfcGxvdHNfbm9zdmFbWyJib3RoIl1dCiMjIFRoZSA3dGggZWxlbWVudCBpbiB0aGUgYm90aCBncm91cHMgbGlzdCBpcyB0aGUgc2V0IHNoYXJlZCBhbW9uZyBhbGwgZG9ub3JzLgojIyBJIGRvbid0IGZlZWwgbGlrZSB3cml0aW5nIG91dCB4Onk6ejphCmdyb3VwcyA8LSB1cHNldF9wbG90c19ub3N2YVtbImJvdGhfZ3JvdXBzIl1dCnNoYXJlZF9nZW5lcyA8LSBhdHRyKGdyb3VwcywgImVsZW1lbnRzIilbZ3JvdXBzW1s3XV1dICU+JQogIGdzdWIocGF0dGVybiA9ICJeZ2VuZToiLCByZXBsYWNlbWVudCA9ICIiKQpzaGFyZWRfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihzaGFyZWRfZ2VuZXMpCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0Kc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KYGBgCgojIEFkZCBkb25vciB0byB0aGUgY29udHJhc3RzLCBzdmEKClNhbWUgZGVhbCBhcyB0aGUgbGFzdCBibG9jaywgYnV0IHRoaXMgdGltZSBhZGQgU1ZBIGludG8gdGhlIG1peCEKCmBgYHtyfQpoc19ub3Bvd2VyX3N2YV9kZSA8LSBhbGxfcGFpcndpc2UoaHNfbm9wb3dlciwgbW9kZWxfc3ZzID0gInN2YXNlcSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9mc3RyaW5nID0gIn4gMCArIGNvbmRpdGlvbiIsIGZpbHRlciA9IFRSVUUpCm5vcG93ZXJfa2VlcGVycyA8LSBsaXN0KAogICJkMDFfenltbyIgPSBjKCJkMDFpbmZ6MjMiLCAiZDAxaW5mejIyIiksCiAgImQwMV9zYnp5bW8iID0gYygiZDAxaW5mc2J6MjMiLCAiZDAxaW5mc2J6MjIiKSwKICAiZDAyX3p5bW8iID0gYygiZDAyaW5mejIzIiwgImQwMmluZnoyMiIpLAogICJkMDJfc2J6eW1vIiA9IGMoImQwMmluZnNiejIzIiwgImQwMmluZnNiejIyIiksCiAgImQwOV96eW1vIiA9IGMoImQwOWluZnoyMyIsICJkMDlpbmZ6MjIiKSwKICAiZDA5X3NienltbyIgPSBjKCJkMDlpbmZzYnoyMyIsICJkMDlpbmZzYnoyMiIpLAogICJkODFfenltbyIgPSBjKCJkODFpbmZ6MjMiLCAiZDgxaW5mejIyIiksCiAgImQ4MV9zYnp5bW8iID0gYygiZDgxaW5mc2J6MjMiLCAiZDgxaW5mc2J6MjIiKSkKaHNfbm9wb3dlcl9zdmFfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgaHNfbm9wb3dlcl9zdmFfZGUsIGtlZXBlcnMgPSBub3Bvd2VyX2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9oc19ub3Bvd2VyX3RhYmxlLXZ7dmVyfS54bHN4IikpCiMjIGV4dHJhX2NvbnRyYXN0cyA9IGV4dHJhKQpoc19ub3Bvd2VyX3N2YV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBoc19ub3Bvd2VyX3N2YV90YWJsZSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9oc19ub3Bvd2VyX3N2YV9zaWctdnt2ZXJ9Lnhsc3giKSkKCmQwMWQwMl96eW1vX3N2YV9jb21wIDwtIG1lcmdlKGhzX25vcG93ZXJfc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwMV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoc19ub3Bvd2VyX3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDJfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAicm93Lm5hbWVzIikKZDAxMDJfenltb19zdmFfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGQwMWQwMl96eW1vX3N2YV9jb21wWywgYygiZGVzZXFfbG9nZmMueCIsICJkZXNlcV9sb2dmYy55IildKQpkMDEwMl96eW1vX3N2YV9wbG90W1sic2NhdHRlciJdXQpkMDEwMl96eW1vX3N2YV9wbG90W1siY29ycmVsYXRpb24iXV0KZDAxMDJfenltb19zdmFfcGxvdFtbImxtX3JzcSJdXQoKZDA5ZDgxX3p5bW9fc3ZhX2NvbXAgPC0gbWVyZ2UoaHNfbm9wb3dlcl9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDA5X3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhzX25vcG93ZXJfc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQ4MV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJyb3cubmFtZXMiKQpkMDk4MV96eW1vX3N2YV9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoZDA5ZDgxX3p5bW9fc3ZhX2NvbXBbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCmQwOTgxX3p5bW9fc3ZhX3Bsb3RbWyJzY2F0dGVyIl1dCmQwOTgxX3p5bW9fc3ZhX3Bsb3RbWyJjb3JyZWxhdGlvbiJdXQpkMDk4MV96eW1vX3N2YV9wbG90W1sibG1fcnNxIl1dCgpkMDFkODFfenltb19zdmFfY29tcCA8LSBtZXJnZShoc19ub3Bvd2VyX3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHNfbm9wb3dlcl9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDgxX3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInJvdy5uYW1lcyIpCmQwMTgxX3p5bW9fc3ZhX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihkMDFkODFfenltb19zdmFfY29tcFssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKZDAxODFfenltb19zdmFfcGxvdFtbInNjYXR0ZXIiXV0KZDAxODFfenltb19zdmFfcGxvdFtbImNvcnJlbGF0aW9uIl1dCmQwMTgxX3p5bW9fc3ZhX3Bsb3RbWyJsbV9yc3EiXV0KCnVwc2V0X3Bsb3RzX3N2YSA8LSB1cHNldHJfc2lnKGhzX25vcG93ZXJfc3ZhX3NpZywgYm90aCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyYXN0cyA9IGMoImQwMV96eW1vIiwgImQwMl96eW1vIiwgImQwOV96eW1vIiwgImQ4MV96eW1vIikpCnVwc2V0X3Bsb3RzX3N2YVtbInVwIl1dCnVwc2V0X3Bsb3RzX3N2YVtbImRvd24iXV0KdXBzZXRfcGxvdHNfc3ZhW1siYm90aCJdXQojIyBUaGUgN3RoIGVsZW1lbnQgaW4gdGhlIGJvdGggZ3JvdXBzIGxpc3QgaXMgdGhlIHNldCBzaGFyZWQgYW1vbmcgYWxsIGRvbm9ycy4KIyMgSSBkb24ndCBmZWVsIGxpa2Ugd3JpdGluZyBvdXQgeDp5Ono6YQpncm91cHMgPC0gdXBzZXRfcGxvdHNfc3ZhW1siYm90aF9ncm91cHMiXV0Kc2hhcmVkX2dlbmVzIDwtIGF0dHIoZ3JvdXBzLCAiZWxlbWVudHMiKVtncm91cHNbWzddXV0gJT4lCiAgZ3N1YihwYXR0ZXJuID0gIl5nZW5lOiIsIHJlcGxhY2VtZW50ID0gIiIpCnNoYXJlZF9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNoYXJlZF9nZW5lcykKc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0Kc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siQlAiXV0Kc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQpzaGFyZWRfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJXUCJdXQpgYGAKCiMgRG9ub3IgY29tcGFyaXNvbgoKTm93IGNvbXBhcmUgdGhlIGRvbm9ycyB0byBlYWNoIG90aGVyIGRpcmVjdGx5LgoKYGBge3J9CmhzX2Rvbm9ycyA8LSBzZXRfc2VfY29uZGl0aW9ucyhoc19tYWNyLCBmYWN0ID0gImRvbm9yIikKZG9ub3JfZGUgPC0gYWxsX3BhaXJ3aXNlKGhzX2Rvbm9ycywgbW9kZWxfc3ZzID0gInN2YXNlcSIsCiAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9mc3RyaW5nID0gIn4gMCArIGNvbmRpdGlvbiIsIGZpbHRlciA9IFRSVUUpCmRvbm9yX2RlCmRvbm9yX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGRvbm9yX2RlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9kZV90YWJsZXMvZG9ub3JfdGFibGVzLXZ7dmVyfS54bHN4IikpCmRvbm9yX3RhYmxlCmRvbm9yX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGRvbm9yX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL2Rvbm9yX3NpZy12e3Zlcn0ueGxzeCIpKQpkb25vcl9zaWcKYGBgCgojIFByaW1hcnkgcXVlcnkgY29udHJhc3RzCgpUaGUgZmluYWwgY29udHJhc3QgaW4gdGhpcyBsaXN0IGlzIGludGVyZXN0aW5nIGJlY2F1c2UgaXQgZGVwZW5kcyBvbgp0aGUgZXh0cmEgY29udHJhc3RzIGFwcGxpZWQgdG8gdGhlIGFsbF9wYWlyd2lzZSgpIGFib3ZlLiAgSW4gbXkgd2F5IG9mCnRoaW5raW5nLCB0aGUgcHJpbWFyeSBjb21wYXJpc29ucyB0byBjb25zaWRlciBhcmUgZWl0aGVyIGNyb3NzLWRydWcgb3IKY3Jvc3Mtc3RyYWluLCBidXQgbm90IGJvdGguICBIb3dldmVyIEkgdGhpbmsgaW4gYXQgbGVhc3QgYSBmZXcKaW5zdGFuY2VzIE9sZ2EgaXMgaW50ZXJlc3RlZCBpbiBzdHJhaW4rZHJ1ZyAvIHVuaW5mZWN0ZWQrbm9kcnVnLgoKIyMgV3JpdGUgY29udHJhc3QgcmVzdWx0cwoKTm93IGxldCB1cyB3cml0ZSBvdXQgdGhlIHhsc3ggZmlsZSBjb250YWluaW5nIHRoZSBhYm92ZSBjb250cmFzdHMuClRoZSBmaWxlIHdpdGggdGhlIHN1ZmZpeCBfdGFibGUtdmVyc2lvbiB3aWxsIHRoZXJlZm9yZSBjb250YWluIGFsbApnZW5lcyBhbmQgdGhlIGZpbGUgd2l0aCB0aGUgc3VmZml4IF9zaWctdmVyc2lvbiB3aWxsIGNvbnRhaW4gb25seQp0aG9zZSBkZWVtZWQgc2lnbmlmaWNhbnQgdmlhIG91ciBkZWZhdWx0IGNyaXRlcmlhIG9mIERFU2VxMiB8bG9nRkN8ID49IDEuMAphbmQgYWRqdXN0ZWQgcC12YWx1ZSA8PSAwLjA1LgoKIyMgT3ZlciByZXByZXNlbnRhdGlvbiBzZWFyY2hlcwoKSSBkZWNpZGVkIHRvIG1ha2Ugb25lIGluaXRpYWxseSBzbWFsbCwgYnV0IEkgdGhpbmsgcXVpY2tseSBiaWcgY2hhbmdlCnRvIHRoZSBvcmdhbml6YXRpb24gb2YgdGhpcyBkb2N1bWVudDogIEkgYW0gbW92aW5nIHRoZSBHU0VBIHNlYXJjaGVzCnVwIHRvIGltbWVkaWF0ZWx5IGFmdGVyIHRoZSBERS4gIEkgd2lsbCB0aGVuIG1vdmUgdGhlIHBsb3RzIG9mIHRoZQpncHJvZmlsZXIgcmVzdWx0cyB0byBpbW1lZGlhdGVseSBhZnRlciB0aGUgdmFyaW91cyB2b2xjYW5vIHBsb3RzIHNvCnRoYXQgaXQgaXMgZWFzaWVyIHRvIGludGVycHJldCB0aGVtLgoKSSBhbSByZWFzb25hYmx5IGNlcnRhaW4gdGhpcyBpcyB0aGUgcGxhY2UgdG8gY2hlY2sgdGhhdCB6MjNubyBkcnVnIC8KdW5pbmZlY3RlZCBoYXMgdGhlIGV4cGVjdGVkIHNldCBvZiBnZW5lcyBhbmQgdGhhdCB0aGVyZSBpcyBvciBpcyBub3QgYQpyZWFjdG9tZSByZXN1bHQuCgpSZXByb2R1Y2liaWxpdHkgbm90ZTogR2l2ZW4gdGhhdCB0aGlzIGlzIGVudGlyZWx5IGRlcGVuZGVudCBvbiBhbgpvbmxpbmUgc2VydmljZSwgSSBtdXN0IGFzc3VtZSB0aGF0IHRoZSByZXN1bHRzIHdpbGwgY2hhbmdlIG92ZXIgdGltZTsKaW4gYWRkaXRpb24gdGhlaXIgd2ViIHNlcnZlcnMgdW5kZXJnbyBtYWludGVuYW5jZSByZWd1bGFybHksIHdoaWNoIG1heQpyZXN1bHQgaW4gc3lzdGVtYXRpYyBmYWlsdXJlIG9mIHRoZXNlIGFuYWx5c2VzLiAgSSBsaWtlIGdQcm9maWxlcgpxdWl0ZSBhIGxvdCBmb3IgdGhpcyB0eXBlIG9mIHN0dWZmLCBidXQgdGhpcyBpcyBhbiBpbXBvcnRhbnQgY2F2ZWF0LgoKQ29udmVyc2VseSwgdGhlIGNsdXN0ZXJQcm9maWxlciByZXN1bHRzIGxhdGVyIGRlcGVuZCBvbiBhIGNvbnNpc3RlbnQKb3JnZGIgYW5ub3RhdGlvbiBzZXQgKG9yIHJlYWN0b21lIG9yIHdoYXRldmVyKTsgdGhvc2UgdmVyc2lvbnMgYXJlCmZpeGVkIGJ5IHRoZSBjb250YWluZXIgaW5zdGFsbGF0aW9uLgoKYGBge3J9CmFsbF9ncCA8LSBhbGxfZ3Byb2ZpbGVyKGhzX21hY3Jfc2lnLCBlbnJpY2hfaWRfY29sdW1uID0gImhnbmNfc3ltYm9sIikKZm9yIChnIGluIHNlcV9sZW4obGVuZ3RoKGFsbF9ncCkpKSB7CiAgbmFtZSA8LSBuYW1lcyhhbGxfZ3ApW2ddCiAgZGF0dW0gPC0gYWxsX2dwW1tuYW1lXV0KICBmaWxlbmFtZSA8LSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2dwcm9maWxlci97bmFtZX1fZ3Byb2ZpbGVyLXZ7dmVyfS54bHN4IikKICB3cml0dGVuIDwtIHNtKHdyaXRlX2dwcm9maWxlcl9kYXRhKGRhdHVtLCBleGNlbCA9IGZpbGVuYW1lKSkKfQpgYGAKCiMjIEV4cGxpY2l0IEdTRUEgc2VhcmNoIHZpcyBjbHVzdGVyUHJvZmlsZXIKCmBgYHtyfQphbGxfY3AgPC0gYWxsX2Nwcm9maWxlcihoc19tYWNyX3NpZywgaHNfbWFjcl90YWJsZSkKYGBgCgojIyBTcGVjaWZpYyBkZXNpcmVzIGluIFJlYWN0b21lIHJlc3VsdHMKCkluIHByZXZpb3VzIGFuYWx5c2VzIChJIHRoaW5rIGJ5IERyLiBDb2xtZW5hcmVzKSwgYSBzcGVjaWZpYwpUcnlwdG9waGFuIGJpb3N5bnRoZXNpcyBwYXRod2F5IHdhcyBvYnNlcnZlZC4gIFBhcnRjaXVsYXJseSBpbiB0aGUKMi4zL3VuaW5mZWN0ZWQgY29tcGFyaXNvbi4gIEkgdGhpbmsgbXkgZ3Byb2ZpbGVyIGFuYWx5c2lzIGlzIHRvbwpzdHJpbmdlbnQgYW5kIHRoZXJlZm9yZSBub3Qgb2JzZXJ2aW5nIHRoaXMuICBPbGdhIGFza2VkIGlmIEkgY291bGQKbG9vayBhdCB0aGF0IGFuZCBzZWUgaWYgdGhlcmUgYXJlIHRyaXZpYWwgc2V0dGluZ3MgSSBjYW4gY2hhbmdlIHRvCmhpZ2hsaWdodCB0aGlzIHBhdGh3YXkuICBUaGUgdHdvIG1vc3QgbGlrZWx5IHRoaW5ncyBJIGNhbiBjaGFuZ2UgYXJlCnRoZSBzdHJpbmdlbmNpZXMgb2YgdGhlIERFIGFuYWx5c2lzIGFuZC9vciBnUHJvZmlsZXIuCgpgYGB7cn0KdGVzdF96MjNfdW5pbmZfdXAgPC0gaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM25vc2JfdnNfdW5pbmYiXV0KbnJvdyh0ZXN0X3oyM191bmluZl91cCkKdGVzdF96MjNfdW5pbmZfZG93biA8LSBoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJ6MjNub3NiX3ZzX3VuaW5mIl1dCm5yb3codGVzdF96MjNfdW5pbmZfZG93bikKCnRlc3RfZ3BfdXAgPC0gc2ltcGxlX2dwcm9maWxlcih0ZXN0X3oyM191bmluZl91cCwgZW5yaWNoX2lkX2NvbHVtbiA9ICJoZ25jX3N5bWJvbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJlc2hvbGQgPSAxLjApCnRlc3RfZ3BfdXAKd3JpdHRlbl91cCA8LSB3cml0ZV9ncHJvZmlsZXJfZGF0YSh0ZXN0X2dwX3VwLCBleGNlbCA9ICJleGNlbC96MjNfdW5pbmZfZ3BfdXBfYWxsLnhsc3giKQoKdGVzdF9ncF9kb3duIDwtIHNpbXBsZV9ncHJvZmlsZXIodGVzdF96MjNfdW5pbmZfZG93biwgZW5yaWNoX2lkX2NvbHVtbiA9ICJoZ25jX3N5bWJvbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocmVzaG9sZCA9IDEuMCkKdGVzdF9ncF9kb3duCndyaXR0ZW5fZG93biA8LSB3cml0ZV9ncHJvZmlsZXJfZGF0YSh0ZXN0X2dwX2Rvd24sIGV4Y2VsID0gImV4Y2VsL3oyM191bmluZl9ncF9kb3duX2FsbC54bHN4IikKYGBgCgojIyBQbG90IGNvbnRyYXN0cyBvZiBpbnRlcmVzdAoKT25lIHN1Z2dlc3Rpb24gSSByZWNlaXZlZCByZWNlbnRseSB3YXMgdG8gc2V0IHRoZSBheGVzIGZvciB0aGVzZQp2b2xjYW5vIHBsb3RzIHRvIGJlIHN0YXRpYyByYXRoZXIgdGhhbiBsZXQgZ2dwbG90IGNob29zZSBpdHMgb3duLiAgSQphbSBhc3N1bWluZyB0aGlzIGlzIG9ubHkgcmVsZXZhbnQgZm9yIHBhaXJzIG9mIGNvbnRyYXN0cywgYnV0IHRoYXQKbWlnaHQgbm90IGJlIHRydWUuCgojIyBJbmRpdmlkdWFsIHp5bW9kZW1lcyB2cy4gdW5pbmZlY3RlZAoKVGhlIGZvbGxvd2luZyBibG9ja3Mgd2lsbCBiZSBhIGxvdCBvZiByZXBldGl0aW9uLiAgSW4gZWFjaCBjYXNlIEkgYW0KeWFua2luZyBvdXQgdGhlIHZvbGNhbm8gcGxvdCBmb3IgYSBzcGVjaWZpYyBjb250cmFzdCBhbmQgc2hvd2luZyB0aGUKb3JpZ2luYWwgZm9sbG93ZWQgYnkgYSB2ZXJzaW9uIHdpdGggZGlmZmVyZW50IGNvbG9ycy9sYWJlbGxpbmcuCgojIyMgSW5mZWN0ZWQgd2l0aCB6Mi4zIG5vIEFudGltb25pYWwgdnMuIFVuaW5mZWN0ZWQKCmBgYHtyfQpwbG90X2NvbG9ycyA8LSBnZXRfc2VfY29sb3JzKGhzX21hY3JfdGFibGVbWyJpbnB1dCJdXVtbImlucHV0Il1dKQoKIyMgVGhlIG9yaWdpbmFsIHBsb3QgZnJvbSBteSB4bHN4IGZpbGUKaHNfbWFjcl90YWJsZVtbInBsb3RzIl1dW1siejIzbm9zYl92c191bmluZiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQoKejIzbm9zYl92c191bmluZl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaW5wdXQgPSBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyM25vc2JfdnNfdW5pbmYiXV0sCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNfc3ltYm9sIiwKICBjb2xvcl9sb3cgPSBwbG90X2NvbG9yc1tbInVuaW5mbm9uZSJdXSwgY29sb3JfaGlnaCA9IHBsb3RfY29sb3JzW1siaW5mejIzIl1dKQoKbGFiZWxlZCA8LSB6MjNub3NiX3ZzX3VuaW5mX3ZvbGNhbm9bWyJwbG90Il1dICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtNiwgMjEpLCBicmVha3MgPSBjKC02LCAtNCwgLTIsIDAsIDIsIDQsIDYsIDgsIDEwLCAyMCkpICsKICBnZ2JyZWFrOjpzY2FsZV94X2JyZWFrKGMoMTAsIDE5KSwgc2NhbGVzID0gMC4yLCBzcGFjZSA9IDAuMDIpCnBwKGZpbGUgPSAiZmlndXJlcy9maWcyYV9sYWJlbGVkX3dpdGhfYnJlYWsuc3ZnIikKbGFiZWxlZApkZXYub2ZmKCkKbGFiZWxlZAoKcGxvdGx5OjpnZ3Bsb3RseSh6MjNub3NiX3ZzX3VuaW5mX3ZvbGNhbm9bWyJwbG90Il1dKQpgYGAKClRoZSBmb2xsb3dpbmcgcHJvdmlkZXMgc29tZSBvZiB0aGUgb3Zlci1yZXByZXNlbnRhdGlvbiBwbG90cyBmcm9tIGdQcm9maWxlcjIuCgpgYGB7cn0KYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siS0VHRyJdXQojIyBLRUdHLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KIyNhbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KIyMgV2lraVBhdGh3YXlzLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbImludGVyYWN0aXZlX3Bsb3RzIl1dW1siV1AiXV0KCm1lc3NhZ2UoIk9sZ2EgcmVjZWl2ZWQgYSBxdWVyeSBhYm91dCB0aGUgZm9sbG93aW5nIHJlc3VsdCwgSSB0aGluayBpdCBpcyBudWxsLiIpCmFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KbWVzc2FnZSgiSXMgdGhlIHByZXZpb3VzIHBsb3QgbnVsbD8iKQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgpgYGAKCldlIGhhdmUgc29tZSBvdGhlciBjYXRlZ29yaWNhbCBlbnJpY2htZW50IHBsb3RzIGF2YWlsYWJsZSB2aWEKZW5yaWNocGxvdCwgbGV0IHVzIHRyeSBhIGZldyBvdXQgZm9yIGNvbnRyYXN0cyBvZiBpbnRlcmVzdCBhbmQgc2VlIGlmCmFueSBvZiB0aGVtIHByb3ZlIGhlbHBmdWwuCgpGaXJzdCwgYXMgYSByZW1pbmRlciwgaGVyZSBhcmUgdGhlIGNvbnRyYXN0cyB3aGljaCBhcmUgYXZhaWxhYmxlIHRvCmV4YW1pbmUsIGluIGVhY2ggY2FzZSB0aGVyZSBpcyBhbiBfdXAgYW5kIF9kb3duIGVucmljaG1lbnQgb2JqZWN0IGluCnRoZSBkYXRhLiAgVGh1cyBpbiB0aGUgZm9sbG93aW5nIGxpc3QgSSBhbSBnb2luZyB0byBhcmJpdHJhcmlseSBwcmludApvdXQgc29tZSBpbnZvY2F0aW9ucyB3aGljaCBleHRyYWN0IHB1dGF0aXZlbHkgaW50ZXJlc3RpbmcgYml0cyBvZiBkYXRhLgoKKiB6MjNub3NiX3ZzX3VuaW5mOiBhbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX3VwIl1dW1siQlBfZW5yaWNoIl1dCiogejIybm9zYl92c191bmluZi4KKiB6MjNub3NiX3ZzX3oyMm5vc2IuCiogejIzc2JfdnNfejIyc2IuCiogejIzc2JfdnNfejIzbm9zYi4KKiB6MjJzYl92c196MjJub3NiLgoqIHoyM3NiX3ZzX3NiLgoqIHoyMnNiX3ZzX3NiLgoqIHoyM3NiX3ZzX3VuaW5mLgoqIHoyMnNiX3ZzX3VuaW5mLgoqIHNiX3ZzX3VuaW5mLgoqIGV4dHJhX3oyMzIyLgoqIGV4dHJhX2RydWdub2RydWcuCgpgYGB7cn0KejIzbm9zYl91bmluZl91cF9nbyA8LSBhbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX3VwIl1dW1siQlBfZW5yaWNoIl1dCnoyM25vc2JfdW5pbmZfdXBfZ29fcGFpciA8LSBwYWlyd2lzZV90ZXJtc2ltKHoyM25vc2JfdW5pbmZfdXBfZ28pCmRvdHBsb3QoejIzbm9zYl91bmluZl91cF9nbykKZW1hcHBsb3QoejIzbm9zYl91bmluZl91cF9nb19wYWlyKQojI3NzcGxvdCh6MjNub3NiX3VuaW5mX3VwX2dvX3BhaXIpCnRyZWVwbG90KHoyM25vc2JfdW5pbmZfdXBfZ29fcGFpcikKdXBzZXRwbG90KHoyM25vc2JfdW5pbmZfdXBfZ28pCmNuZXRwbG90KHoyM25vc2JfdW5pbmZfdXBfZ28pCmBgYAoKIyMjIFJlcGVhdCwgYnV0IHVzaW5nIGEgbGVzcyBzdHJpY3Qgc2V0IG9mICdzaWduaWZpY2FudCBnZW5lcycKCkkgYW0gbm90IGVudGlyZWx5IGNlcnRhaW4gaWYgdGhlIFJlYWN0b21lIHJlc3VsdHMgT2xnYSBzaG93ZWQgbWUKaW5jbHVkZWQgYm90aCB1cCBhbmQgZG93biBnZW5lcz8gIEkgYW0gZ29pbmcgdG8gYXNzdW1lIGZvciB0aGUgbW9tZW50CnRoYXQgaXQgd2FzIGp1c3QgdXAvZG93biwgYnV0IGlmIHRoYXQgcHJvdmVzIGludHJhY3RhYmxlIEkgd2lsbCBnbwpiYWNrIHRvIHRoZSBtYW51c2NyaXB0IGFuZCByZWFkIG1vcmUgY2FyZWZ1bGx5IChlLmcuIEkganVzdCByZW1lbWJlcmVkCndoZXJlIHRoZSBwaWN0dXJlIGNhbWUgZnJvbSEpCgojIyMjIEFkZCBhIGxpdHRsZSB0b3BnbwoKSW4gdGhlIHByb2Nlc3Mgb2YgZXhwbG9yaW5nIHRoZSB2YXJpb3VzIHBhcmFtZXRlcnMgdXNlZCB3aXRoCmdQcm9maWxlcjIsIEkgZm91bmQgbXlzZWxmIHRoaW5raW5nIHRoYXQgaXQgd291bGQgYmUgbmljZSB0byBoYXZlIHNvbWUKdG9wZ28gcmVzdWx0cyB0byBjb21wYXJlIGFnYWluc3QuICBUaGUgZm9sbG93aW5nIGJsb2NrIGlzIHRoZSByZXN1bHQKb2YgdGhhdCB0aG91Z2h0LgoKYGBge3J9CnRlc3RfZ2VuZXNfdXAgPC0gaHNfbWFjcl9sZXNzc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjNub3NiX3ZzX3VuaW5mIl1dCnRlc3RfcXVlcnlfdXAgPC0gc2ltcGxlX2dwcm9maWxlcih0ZXN0X2dlbmVzX3VwLCB0aHJlc2hvbGQgPSAwLjEpCnRlc3RfcXVlcnlfdXBbWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCnBkZihmaWxlID0gImltYWdlcy90ZXN0X3F1ZXJ5X2Jpb2xvZ2ljYWxfcHJvY2Vzc196MjNfdnNfdW5pbmZfdXAucGRmIiwgaGVpZ2h0ID0gMTIsIHdpZHRoID0gOSkKdGVzdF9xdWVyeV91cFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCmRldi5vZmYoKQplbnJpY2hwbG90Ojpkb3RwbG90KHRlc3RfcXVlcnlfdXBbWyJCUF9lbnJpY2giXV0pCnRlc3RfZ2VuZXNfZG93biA8LSBoc19tYWNyX2xlc3NzaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1siejIzbm9zYl92c191bmluZiJdXQp0ZXN0X3F1ZXJ5X2Rvd24gPC0gc2ltcGxlX2dwcm9maWxlcih0ZXN0X2dlbmVzX2Rvd24pCnRlc3RfcXVlcnlfZG93bltbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KCiMjIEkga2VlcCBnZXR0aW5nIGFsbCBzb3J0cyBvZiBhbm5veWluZyBiaW9tYXJ0IGVycm9ycy4KaHNfZ28gPC0gdHJ5KGxvYWRfYmlvbWFydF9nbyhhcmNoaXZlID0gRkFMU0UsIG92ZXJ3cml0ZSA9IFRSVUUpKQppZiAoInRyeS1lcnJvciIgJWluJSBjbGFzcyhoc19nbykpIHsKICBoc19nbyA8LSBsb2FkX2Jpb21hcnRfZ28oYXJjaGl2ZSA9IFRSVUUsIG1vbnRoID0gIjA0IiwgeWVhciA9ICIyMDIwIiwgb3ZlcndyaXRlID0gVFJVRSkKfQp0ZXN0X3RvcGdvX3VwIDwtIHNpbXBsZV90b3Bnbyh0ZXN0X2dlbmVzX3VwLCBnb19kYiA9IGhzX2dvW1siZ28iXV0sIHBhcmFsbGVsID0gRkFMU0UpCndyaXR0ZW5fdG9wZ28gPC0gd3JpdGVfdG9wZ29fZGF0YSgKICB0ZXN0X3RvcGdvX3VwLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9vbnRvbG9neV90b3Bnby90b3Bnb196MjNfdW5pbmZfbGVzc19zdHJpY3QueGxzeCIpKQpgYGAKCiMjIyBJbmZlY3RlZCB3aXRoIHoyLjIgbm8gQW50aW1vbmlhbCB2cy4gVW5pbmZlY3RlZAoKSGVyZSBpcyB3aGVyZSB0aGluZ3Mgd2lsbCBnZXQgbW9zdCByZXBldGl0aXZlLiAgSW4gZWFjaCBpbnN0YW5jZSBJIGFtCmNyZWF0aW5nIGEgY291cGxlIG9mIHZvbGNhbm8gcGxvdHMgZm9sbG93ZWQgYnkgcHJpbnRpbmcgc29tZSBvZiB0aGUKZ1Byb2ZpbGVyMiByZXN1bHRzICh3aGVuIEkgZ2V0IHRoZSBpdGNoKS4KClRoZSBmb2xsb3dpbmcgc2hvdWxkIGJlIGEgc2xpZ2h0bHkgaW1wcm92ZWQgdmVyc2lvbiBvZiBvdXIgZXh0YW50CmZpZ3VyZSAyQi4KCmBgYHtyfQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlW1sicGxvdHMiXV1bWyJ6MjJub3NiX3ZzX3VuaW5mIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dCgp6MjJub3NiX3ZzX3VuaW5mX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2NvbmRpdGlvbl9kZSgKICBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyMm5vc2JfdnNfdW5pbmYiXV0sICJ6MjJub3NiX3ZzX3VuaW5mIiwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY19zeW1ib2wiLAogIGNvbG9yX2xvdyA9IHBsb3RfY29sb3JzW1sidW5pbmZub25lIl1dLCBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJpbmZ6MjIiXV0pCgpsYWJlbGVkIDwtIHoyMm5vc2JfdnNfdW5pbmZfdm9sY2Fub1tbInBsb3QiXV0gKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0yLCAyMSksIGJyZWFrcyA9IGMoLTIsIDAsIDIsIDQsIDYsIDgsIDEwLCAyMSwgMjIpKSArCiAgZ2dicmVhazo6c2NhbGVfeF9icmVhayhjKDExLCAyMCksIHNjYWxlcyA9IDAuMiwgc3BhY2UgPSAwLjAyKQpwcChmaWxlID0gImZpZ3VyZXMvZmlnMmJfbGFiZWxlZF93aXRoX2JyZWFrLnN2ZyIpCmxhYmVsZWQKZGV2Lm9mZigpCmxhYmVsZWQKCnBsb3RseTo6Z2dwbG90bHkoejIybm9zYl92c191bmluZl92b2xjYW5vW1sicGxvdCJdXSkKYGBgCgpBZGQgc29tZSBwdmFsdWUgYmFycGxvdHMgZnJvbSBnUHJvZmlsZXIgZm9yIHRoaXMgY29udHJhc3QuCgpgYGB7cn0KYWxsX2dwW1siejIybm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4yIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjJub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4yIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjJub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4yIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjJub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KIyMgV2lraVBhdGh3YXlzLCB6eW1vZGVtZTIuMiB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KCmFsbF9ncFtbInoyMm5vc2JfdnNfdW5pbmZfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4yIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyMm5vc2JfdnNfdW5pbmZfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMiB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjJub3NiX3ZzX3VuaW5mX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYGBgCgojIyMgSW5mZWN0ZWQgd2l0aCB6Mi4zIHRyZWF0ZWQgdnMuIFVuaW5mZWN0ZWQgdHJlYXRlZAoKSSBkbyBub3QgdGhpbmsgdGhpcyBwbG90IGlzIHVzZWQgYXQgdGhpcyB0aW1lLgoKYGBge3J9CiMjIFRoZSBvcmlnaW5hbCBwbG90CmhzX21hY3JfdGFibGVbWyJwbG90cyJdXVtbInoyM3NiX3ZzX3NiIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dCgp6MjNzYl92c191bmluZnNiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2NvbmRpdGlvbl9kZSgKICBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyM3NiX3ZzX3NiIl1dLCAiejIzc2JfdnNfc2IiLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jX3N5bWJvbCIsCiAgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJpbmZzYnoyMyJdXSwgY29sb3JfaGlnaCA9IHBsb3RfY29sb3JzW1sidW5pbmZzYm5vbmUiXV0pCnoyM3NiX3ZzX3VuaW5mc2Jfdm9sY2Fub1tbInBsb3QiXV0KCnBsb3RseTo6Z2dwbG90bHkoejIzc2JfdnNfdW5pbmZzYl92b2xjYW5vW1sicGxvdCJdXSkKYGBgCgojIyMgSW5mZWN0ZWQgd2l0aCB6Mi4zIHVudHJlYXRlZCB2cy4gejIuMiB1bnRyZWF0ZWQKClRoaXMgaXMgZmlndXJlIDJDIGF0IHRoaXMgdGltZS4KCmBgYHtyfQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlW1sicGxvdHMiXV1bWyJ6MjNub3NiX3ZzX3oyMm5vc2IiXV1bWyJkZXNlcV92b2xfcGxvdHMiXV0KCnoyM25vc2JfdnNfejIybm9zYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNub3NiX3ZzX3oyMm5vc2IiXV0sICJ6MjNub3NiX3ZzX3oyMm5vc2IiLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jX3N5bWJvbCIsCiAgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJpbmZ6MjMiXV0sIGNvbG9yX2hpZ2ggPSBwbG90X2NvbG9yc1tbImluZnoyMiJdXSkKCmxhYmVsZWQgPC0gejIzbm9zYl92c196MjJub3NiX3ZvbGNhbm9bWyJwbG90Il1dICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygtMTAsIC04LCAtNiwgLTQsIC0yLCAwLCAyLCA0LCA2KSkKCnBwKGZpbGUgPSAiZmlndXJlcy9maWcyY19sYWJlbGVkLnN2ZyIpCmxhYmVsZWQKZGV2Lm9mZigpCmxhYmVsZWQKYGBgCgojIyMgSW5mZWN0ZWQgd2l0aCB6Mi4zIHRyZWF0ZWQgdnMuIHoyLjIgdHJlYXRlZAoKVGhpcyBpcyBjdXJyZW50bHkgZmlndXJlIDNDLgoKRklYTUU6IFRoZSBheGlzIGxhYmVsIGlzbid0IHF1aXRlIHJpZ2h0IGZvciB0aGUgZ2dicmVhay4KCmBgYHtyfQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlW1sicGxvdHMiXV1bWyJ6MjNzYl92c196MjJzYiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQoKejIzc2JfdnNfejIyc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfejIyc2IiXV0sICJ6MjNzYl92c196MjJzYiIsCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNfc3ltYm9sIiwKICBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJpbmZzYnoyMyJdXSwgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJpbmZzYnoyMiJdXSkKCmxhYmVsZWQgPC0gejIzc2JfdnNfejIyc2Jfdm9sY2Fub1tbInBsb3QiXV0gKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKC0yMywgLTYsIC00LCAtMiwgMCwgMiwgNCwgNikpICsKICBnZ2JyZWFrOjpzY2FsZV94X2JyZWFrKGMoLTUsIC0yMi41KSwgc2NhbGVzID0gMTAsIHNwYWNlID0gMC4wMikKcHAoZmlsZSA9ICJmaWd1cmVzL2ZpZzNjX2xhYmVsZWRfYnJlYWtzLnN2ZyIpCmxhYmVsZWQKZGV2Lm9mZigpCmxhYmVsZWQKYGBgCgojIyMgSW5mZWN0ZWQgd2l0aCB6Mi4zIFNCIHRyZWF0ZWQgdnMuIHoyLjMgdW50cmVhdGVkCgpJIHRoaW5rIHRoaXMgaXMgY3VycmVudGx5IGZpZ3VyZSAzQS4KCkZJWE1FOiBUaGUgYXhpcyBsYWJlbCBmb3IgdGhlIGdnYnJlYWsgaXNuJ3QgcXVpdGUgcmlnaHQuCgpgYGB7cn0KIyMgVGhlIG9yaWdpbmFsIHBsb3QKaHNfbWFjcl90YWJsZVtbInBsb3RzIl1dW1siejIzc2JfdnNfejIzbm9zYiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQoKejIzc2JfdnNfejIzbm9zYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNzYl92c196MjNub3NiIl1dLCAiejIzc2JfdnNfejIzbm9zYiIsCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNfc3ltYm9sIiwKICBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJpbmZzYnoyMyJdXSwgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJpbmZ6MjMiXV0pCgpsYWJlbGVkIDwtIHoyM3NiX3ZzX3oyM25vc2Jfdm9sY2Fub1tbInBsb3QiXV0gKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xOSwgNiksCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoLTIwLCAtMTgsIC0xNiwgLTE0LCAtMTIsIC0xMCwgLTYsIC00LCAtMiwgMCwgMiwgNCwgNikpICsKICBnZ2JyZWFrOjpzY2FsZV94X2JyZWFrKGMoLTE3LCAtOCksIHNjYWxlcyA9IDE3LCBzcGFjZSA9IDAuMDIpCnBwKGZpbGUgPSAiZmlndXJlcy9maWczYV9sYWJlbGVkX3dpdGhfYnJlYWsuc3ZnIikKbGFiZWxlZApkZXYub2ZmKCkKbGFiZWxlZApgYGAKCiMjIyBJbmZlY3RlZCB3aXRoIHoyLjMgU0IgdHJlYXRlZCB2cy4gejIuMyB1bnRyZWF0ZWQKCmBgYHtyfQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlW1sicGxvdHMiXV1bWyJ6MjJzYl92c196MjJub3NiIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dCgp6MjJzYl92c196MjJub3NiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2NvbmRpdGlvbl9kZSgKICBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyMnNiX3ZzX3oyMm5vc2IiXV0sICJ6MjJzYl92c196MjJub3NiIiwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY19zeW1ib2wiLAogIGNvbG9yX2hpZ2ggPSBwbG90X2NvbG9yc1tbImluZnNiejIyIl1dLCBjb2xvcl9sb3cgPSBwbG90X2NvbG9yc1tbImluZnoyMiJdXSkKCmxhYmVsZWQgPC0gejIyc2JfdnNfejIybm9zYl92b2xjYW5vW1sicGxvdCJdXSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoLTYsIC00LCAtMiwgMCwgMiwgNCwgNikpCgpwcChmaWxlID0gImZpZ3VyZXMvZmlnM2JfbGFiZWxlZC5zdmciKQpsYWJlbGVkCmRldi5vZmYoKQpsYWJlbGVkCmBgYAoKIyMjIEluZmVjdGVkIHdpdGggejIuMyBTQiB0cmVhdGVkIHZzLiB1bmluZmVjdGVkIHRyZWF0ZWQKCmBgYHtyfQp4X2xpbWl0cyA8LSBjKC02LCA2KQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlW1sicGxvdHMiXV1bWyJ6MjNzYl92c19zYiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQoKejIzc2JfdnNfc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfc2IiXV0sICJ6MjNzYl92c19zYiIsCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNfc3ltYm9sIiwgaW52ZXJ0ID0gVFJVRSwKICBjb2xvcl9sb3cgPSBwbG90X2NvbG9yc1tbImluZnNiejIzIl1dLCBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJ1bmluZnNibm9uZSJdXSkKejIzc2JfdnNfc2Jfdm9sY2Fub1tbInBsb3QiXV0KYGBgCgojIyMgSW5mZWN0ZWQgd2l0aCB6Mi4yIFNCIHRyZWF0ZWQgdnMuIHVuaW5mZWN0ZWQgdHJlYXRlZAoKYGBge3J9CiMjIFRoZSBvcmlnaW5hbCBwbG90CmhzX21hY3JfdGFibGVbWyJwbG90cyJdXVtbInoyMnNiX3ZzX3NiIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dCgp6MjJzYl92c19zYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjJzYl92c19zYiJdXSwgInoyMnNiX3ZzX3NiIiwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY19zeW1ib2wiLCBpbnZlcnQgPSBUUlVFLAogIGNvbG9yX2xvdyA9IHBsb3RfY29sb3JzW1siaW5mc2J6MjIiXV0sIGNvbG9yX2hpZ2ggPSBwbG90X2NvbG9yc1tbInVuaW5mc2Jub25lIl1dKQp6MjJzYl92c19zYl92b2xjYW5vW1sicGxvdCJdXQpgYGAKCiMjIyBVbmluZmVjdGVkK1NiViB2cy4gVW5pbmZlY3RlZC1TYlYKClRoaXMgaXMgY3VycmVudGx5IGZpZ3VyZSAzRC4KCkZJWE1FOiBUaGlzIG5lZWRzIHRoZSBCT0xBMkIgZ2dicmVhay4KCmBgYHtyfQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlW1sicGxvdHMiXV1bWyJzYl92c191bmluZiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQoKc2JfdnNfdW5pbmZfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1sic2JfdnNfdW5pbmYiXV0sICJzYl92c191bmluZiIsCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNfc3ltYm9sIiwKICBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJ1bmluZnNibm9uZSJdXSwgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJ1bmluZm5vbmUiXV0pCgpsYWJlbGVkIDwtIHNiX3ZzX3VuaW5mX3ZvbGNhbm9bWyJwbG90Il1dICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygtMjMsIC02LCAtNCwgLTIsIDAsIDIsIDQsIDYpKSArCiAgZ2dicmVhazo6c2NhbGVfeF9icmVhayhjKC01LCAtMjIuNSksIHNjYWxlcyA9IDEwLCBzcGFjZSA9IDAuMDIpCnBwKGZpbGUgPSAiZmlndXJlcy9maWczZF9sYWJlbGVkX2JyZWFrcy5zdmciKQpsYWJlbGVkCmRldi5vZmYoKQpsYWJlbGVkCmBgYAoKIyMgRG91YmxlLWNoZWNrIHRoYXQgZ2VuZSBjb3VudHMgbWF0Y2ggbXkgcGVyY2VwdGlvbnMKCkNoZWNrIHRoYXQgbXkgcGVyY2VwdGlvbiBvZiB0aGUgbnVtYmVyIG9mIHNpZ25pZmljYW50IHVwL2Rvd24gZ2VuZXMKbWF0Y2hlcyB3aGF0IHRoZSB0YWJsZS92ZW5uIHNheXMuICBJbiB0aGUgZm9sbG93aW5nIGJsb2NrIEkgYW0KcGVyZm9ybWluZyBzb21lIHZlbm4vdXBzZXQgYW5hbHlzZXMgdG8gc2VlIGlmIHRoZSBudW1iZXJzIG9mIGdlbmVzCm1hdGNoIHdoYXQgd2UgaGF2ZSBpbiB0aGUgY3VycmVudCB2ZXJzaW9uIG9mIHRoZSBtYW51c2NyaXB0IChwbHVzIG9yCm1pbnVzIGEgZ2VuZSkgYW5kIHRodXMgaWYgbXkgaW50ZXJwcmV0YXRpb24gb2YgdGhlIGZpZ3VyZS9sZWdlbmQgdGV4dAptYXRjaGVzIHdoYXQgSSB0aGluayBpdCBtZWFucy4KCmBgYHtyfQpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KAogICJkcnVnIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjNzYl92c191bmluZiJdXSksCiAgIm5vZHJ1ZyIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIzbm9zYl92c191bmluZiJdXSkpKQpwcChmaWxlID0gImltYWdlcy96MjNfdnNfdW5pbmZfdmVubl91cC5wbmciKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKZGV2Lm9mZigpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQojIyBJIHNlZSA5MTAgejIzc2IvdW5pbmYgYW5kIDY3MCBubyB6MjNub3NiL3VuaW5mIGdlbmVzIGluIHRoZSB2ZW5uIGRpYWdyYW0uCmxlbmd0aChzaGFyZWRASW50ZXJzZWN0aW9uU2V0c1tbIjEwIl1dKSArIGxlbmd0aChzaGFyZWRASW50ZXJzZWN0aW9uU2V0c1tbIjExIl1dKQpkaW0oaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM3NiX3ZzX3VuaW5mIl1dKQoKc2hhcmVkIDwtIFZlbm5lcmFibGU6OlZlbm4obGlzdCgKICAiZHJ1ZyIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIyc2JfdnNfdW5pbmYiXV0pLAogICJub2RydWciID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyMm5vc2JfdnNfdW5pbmYiXV0pKSkKcHAoZmlsZSA9ICJpbWFnZXMvejIyX3ZzX3VuaW5mX3Zlbm5fdXAucG5nIikKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmRldi5vZmYoKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKCmxlbmd0aChzaGFyZWRASW50ZXJzZWN0aW9uU2V0c1tbIjEwIl1dKSArIGxlbmd0aChzaGFyZWRASW50ZXJzZWN0aW9uU2V0c1tbIjExIl1dKQpkaW0oaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyMnNiX3ZzX3VuaW5mIl1dKQpgYGAKCipOb3RlIHRvIHNlbGYqOiBUaGVyZSBpcyBhbiBlcnJvciBpbiBteSB2b2xjYW5vIHBsb3QgY29kZSB3aGljaCB0YWtlcwplZmZlY3Qgd2hlbiB0aGUgbnVtZXJhdG9yIGFuZCBkZW5vbWluYXRvciBvZiB0aGUgYWxsX3BhaXJ3aXNlCmNvbnRyYXN0cyBhcmUgZGlmZmVyZW50IHRoYW4gdGhvc2UgaW4gY29tYmluZV9kZV90YWJsZXMuICBJdCBpcwpwdXR0aW5nIHRoZSB1cHMvZG93bnMgb24gdGhlIGNvcnJlY3Qgc2lkZXMgb2YgdGhlIHBsb3QsIGJ1dCBjYWxsaW5nCnRoZSBkb3duIGdlbmVzICd1cCcgYW5kIHZpY2UtdmVyc2EuICBUaGUgcmVhc29uIGZvciB0aGlzIGlzIHRoYXQgSSBkaWQKYSBjaGVjayBmb3IgdGhpcyBoYXBwZW5pbmcsIGJ1dCB1c2VkIHRoZSB3cm9uZyBhcmd1bWVudCB0byBoYW5kbGUgaXQuCgpBIGxpa2VseSBiaXQgb2YgdGV4dCBmb3IgdGhlc2Ugdm9sY2FubyBwbG90czoKClRoZSBzZXQgb2YgZ2VuZXMgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGJldHdlZW4gdGhlIHp5bW9kZW1lIDIuMwphbmQgdW5pbmZlY3RlZCBzYW1wbGVzIHdpdGhvdXQgZHJ1Z2UgdHJlYXRtZW50IHdhcyBxdWFudGlmaWVkIHdpdGgKREVTZXEyIGFuZCBpbmNsdWRlZCBzdXJyb2dhdGUgZXN0aW1hdGVzIGZyb20gU1ZBLiAgR2l2ZW4gdGhlIGNyaXRlcmlhCm9mIHNpZ25pZmljYW5jZSBvZiBhIGFicyhsb2dGQykgPj0gMS4wIGFuZCBmYWxzZSBkaXNjb3ZlcnkgcmF0ZQphZGp1c3RlZCBwLXZhbHVlIDw9IDAuMDUsIDY3MCBnZW5lcyB3ZXJlIG9ic2VydmVkIGFzIHNpZ25pZmljYW50bHkKaW5jcmVhc2VkIGJldHdlZW4gdGhlIGluZmVjdGVkIGFuZCB1bmluZmVjdGVkIHNhbXBsZXMgYW5kIDM4NiB3ZXJlCm9ic2VydmVkIGFzIGRlY3JlYXNlZC4gVGhlIG1vc3QgaW5jcmVhc2VkIGdlbmVzIGZyb20gdGhlIHVuaW5mZWN0ZWQKc2FtcGxlcyBpbmNsdWRlIHNvbWUgd2hpY2ggYXJlIHBvdGVudGlhbGx5IGluZGljYXRpdmUgb2YgYSBzdHJvbmcKaW5uYXRlIGltbXVuZSByZXNwb25zZSBhbmQgdGhlIGluZmxhbW1hdG9yeSByZXNwb25zZS4KCkluIGNvbnRyYXN0LCB3aGVuIHRoZSBzZXQgb2YgZ2VuZXMgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGJldHdlZW4KdGhlIHp5bW9kZW1lIDIuMiBhbmQgdW5pbmZlY3RlZCBzYW1wbGVzIHdhcyB2aXN1YWxpemVkLCBvbmx5IDcgZ2VuZXMKd2VyZSBvYnNlcnZlZCBhcyBkZWNyZWFzZWQgYW5kIDQzNSBpbmNyZWFzZWQuICBUaGUgaW5mbGFtbWF0b3J5CnJlc3BvbnNlIHdhcyBzaWduaWZpY2FudGx5IGxlc3MgYXBwYXJlbnQgaW4gdGhpcyBzZXQsIGJ1dCBpbnN0ZWFkCmluY2x1ZGVkIGdlbmVzIHJlbGF0ZWQgdG8gdHJhbnNwb3J0ZXIgYWN0aXZpdHkgYW5kIG94aWRvcmVkdWN0YXNlcy4KCiMjIERpcmVjdCB6eW1vZGVtZSBjb21wYXJpc29ucwoKQW4gb3J0aG9nb25hbCBjb21wYXJpc29uIHRvIHRoYXQgcGVyZm9ybWVkIGFib3ZlIGlzIHRvIGRpcmVjdGx5CmNvbXBhcmUgdGhlIHp5bW9kZW1lIDIuMyBhbmQgMi4yIHNhbXBsZXMgd2l0aCBhbmQgd2l0aG91dCBhbnRpbW9uaWFsCnRyZWF0bWVudC4KCiMjIyBaMi4zIC8gejIuMiB3aXRob3V0IGRydWcKCmBgYHtyfQp6MjNub3NiX3ZzX3oyMm5vc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fZGUoCiAgdGFibGUgPSBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXSwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBzaGFwZXNfYnlfc3RhdGUgPSBGQUxTRSwgY29sb3JfYnkgPSAiZmMiLCAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNfc3ltYm9sIikKcGxvdGx5OjpnZ3Bsb3RseSh6MjNub3NiX3ZzX3oyMm5vc2Jfdm9sY2Fub1tbInBsb3QiXV0pCgp6MjNzYl92c196MjJzYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19kZSgKICB0YWJsZSA9IGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfejIyc2IiXV0sCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgc2hhcGVzX2J5X3N0YXRlID0gRkFMU0UsIGNvbG9yX2J5ID0gImZjIiwgIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jX3N5bWJvbCIpCnBsb3RseTo6Z2dwbG90bHkoejIzc2JfdnNfejIyc2Jfdm9sY2Fub1tbInBsb3QiXV0pCmBgYAoKYGBge3J9CnoyM25vc2JfdnNfejIybm9zYl92b2xjYW5vW1sicGxvdCJdXSArCiAgeGxpbSgtMTAsIDEwKSArCiAgeWxpbSgwLCA2MCkKCnBwKGZpbGUgPSAiaW1hZ2VzL3oyM25vc2JfdnNfejIybm9zYl9yZWFjdG9tZV91cC5zdmciLAogICBpbWFnZSA9IGFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0sCiAgIGhlaWdodCA9IDEyLCB3aWR0aCA9IDkpCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJLRUdHIl1dCiMjIEtFR0csIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KIyMgV2lraVBhdGh3YXlzLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX3VwIl1dW1siaW50ZXJhY3RpdmVfcGxvdHMiXV1bWyJXUCJdXQoKcHAoZmlsZSA9ICJpbWFnZXMvejIzbm9zYl92c196MjJub3NiX3JlYWN0b21lX2Rvd24uc3ZnIiwKICAgaW1hZ2UgPSBhbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0sCiAgIGhlaWdodCA9IDEyLCB3aWR0aCA9IDkpCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYGBgCgojIyMgejIuMyAvIHoyLjIgd2l0aCBkcnVnCgpgYGB7cn0KejIzc2JfdnNfejIyc2Jfdm9sY2Fub1tbInBsb3QiXV0gKwogIHhsaW0oLTEwLCAxMCkgKwogIHlsaW0oMCwgNjApCgpwcCgKICBmaWxlID0gImltYWdlcy96MjNzYl92c196MjJzYl9yZWFjdG9tZV91cC5wbmciLAogIGltYWdlID0gYWxsX2dwW1siejIzc2JfdnNfejIyc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dLAogIGhlaWdodCA9IDEyLCB3aWR0aCA9IDkpCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siS0VHRyJdXQojIyBLRUdHLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIyc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIldQIl1dCiMjIFdpa2lQYXRod2F5cywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1siaW50ZXJhY3RpdmVfcGxvdHMiXV1bWyJXUCJdXQoKYWxsX2dwW1siejIzc2JfdnNfejIyc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzc2JfdnNfejIyc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgpgYGAKCiMjIyBWZW5uIHRvIHNlZSBzaGFyZWQvdW5pcXVlIGdlbmVzCgpPbmNlIGFnYWluIEkgd2lzaCB0byBwdWxsIG91dCB0aGUgc2lnbmlmaWNhbnQgZ2VuZXMgYW5kIHNlZSBob3cgbXkKbnVtYmVycyBtYXRjaCBhZ2FpbnN0IHRoZSB0ZXh0LgoKYGBge3J9CnNoYXJlZCA8LSBWZW5uZXJhYmxlOjpWZW5uKGxpc3QoCiAgImRydWciID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM3NiX3ZzX3oyMnNiIl1dKSwKICAibm9kcnVnIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjNub3NiX3ZzX3oyMm5vc2IiXV0pKSkKcHAoZmlsZSA9ICJpbWFnZXMvZHJ1Z19ub2RydWdfdmVubl91cC5wbmciKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKZGV2Lm9mZigpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQoKc2hhcmVkIDwtIFZlbm5lcmFibGU6OlZlbm4oCiAgbGlzdCgiZHJ1ZyIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJ6MjNzYl92c196MjJzYiJdXSksCiAgICAgICAibm9kcnVnIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXSkpKQpwcChmaWxlID0gImltYWdlcy9kcnVnX25vZHJ1Z192ZW5uX2Rvd24ucG5nIikKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmRldi5vZmYoKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKYGBgCgpBIHNsaWdodGx5IGRpZmZlcmVudCB3YXkgb2YgbG9va2luZyBhdCB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgdHdvCnp5bW9kZW1lIGluZmVjdGlvbnMgaXMgdG8gZGlyZWN0bHkgY29tcGFyZSB0aGUgaW5mZWN0ZWQgc2FtcGxlcyB3aXRoCmFuZCB3aXRob3V0IGRydWcuICBUaHVzLCB3aGVuIGEgdm9sY2FubyBwbG90IHNob3dpbmcgdGhlIGNvbXBhcmlzb24gb2YKdGhlIHp5bW9kZW1lIDIuMyB2cy4gMi4yIHNhbXBsZXMgd2FzIHBsb3R0ZWQsIDQ4NCBnZW5lcyB3ZXJlIG9ic2VydmVkCmFzIGluY3JlYXNlZCBhbmQgNDIyIGRlY3JlYXNlZDsgdGhlc2UgZ3JvdXBzIGluY2x1ZGUgbWFueSBvZiB0aGUgc2FtZQppbmZsYW1tYXRvcnkgKHVwKSBhbmQgbWVtYnJhbmUgKGRvd24pIGdlbmVzLgoKU2ltaWxhciBwYXR0ZXJucyB3ZXJlIG9ic2VydmVkIHdoZW4gdGhlIGFudGltb25pYWwgd2FzIGluY2x1ZGVkLgpUaHVzLCB3aGVuIGEgVmVubiBkaWFncmFtIG9mIHRoZSB0d28gc2V0cyBvZiBpbmNyZWFzZWQgZ2VuZXMgd2FzCnBsb3R0ZWQsIGEgc2lnbmlmaWNhbnQgbnVtYmVyIG9mIHRoZSBnZW5lcyB3YXMgb2JzZXJ2ZWQgYXMgaW5jcmVhc2VkCigzMTMpIGFuZCBkZWNyZWFzZWQgKDI0NCkgaW4gYm90aCB0aGUgdW50cmVhdGVkIGFuZCBhbnRpbW9uaWFsIHRyZWF0ZWQKc2FtcGxlcy4KCiMjIERydWcgZWZmZWN0cyBvbiBlYWNoIHp5bW9kZW1lIGluZmVjdGlvbgoKQW5vdGhlciBsaWtlbHkgcXVlc3Rpb24gaXMgdG8gZGlyZWN0bHkgY29tcGFyZSB0aGUgdHJlYXRlZCB2cwp1bnRyZWF0ZWQgc2FtcGxlcyBmb3IgZWFjaCB6eW1vZGVtZSBpbmZlY3Rpb24gaW4gb3JkZXIgdG8gdmlzdWFsaXplCnRoZSBlZmZlY3RzIG9mIGFudGltb25pYWwuCgojIyMgejIuMyB3aXRoIGFuZCB3aXRob3V0IGRydWcKCmBgYHtyfQp6MjNzYl92c196MjNub3NiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2RlKAogIHRhYmxlID0gaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNzYl92c196MjNub3NiIl1dLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY19zeW1ib2wiKQpwbG90bHk6OmdncGxvdGx5KHoyM3NiX3ZzX3oyM25vc2Jfdm9sY2Fub1tbInBsb3QiXV0pCnoyMnNiX3ZzX3oyMm5vc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fZGUoCiAgdGFibGUgPSBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyMnNiX3ZzX3oyMm5vc2IiXV0sCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgc2hhcGVzX2J5X3N0YXRlID0gRkFMU0UsIGNvbG9yX2J5ID0gImZjIiwgIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jX3N5bWJvbCIpCnBsb3RseTo6Z2dwbG90bHkoejIyc2JfdnNfejIybm9zYl92b2xjYW5vW1sicGxvdCJdXSkKYGBgCgpgYGB7cn0KejIzc2JfdnNfejIzbm9zYl92b2xjYW5vW1sicGxvdCJdXSArCiAgeGxpbSgtOCwgOCkgKwogIHlsaW0oMCwgMjEwKQoKcHAoZmlsZSA9ICJpbWFnZXMvejIzc2JfdnNfejIzbm9zYl9yZWFjdG9tZV91cC5wbmciLAogICBpbWFnZSA9IGFsbF9ncFtbInoyM3NiX3ZzX3oyM25vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dLAogICBoZWlnaHQgPSAxMiwgd2lkdGggPSA5KQphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyM25vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJLRUdHIl1dCiMjIEtFR0csIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KIyMgV2lraVBhdGh3YXlzLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbImludGVyYWN0aXZlX3Bsb3RzIl1dW1siV1AiXV0KCmFsbF9ncFtbInoyM3NiX3ZzX3oyM25vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyM3NiX3ZzX3oyM25vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYGBgCgojIyMgejIuMiB3aXRoIGFuZCB3aXRob3V0IGRydWcKCmBgYHtyfQp6MjJzYl92c196MjJub3NiX3ZvbGNhbm9bWyJwbG90Il1dICsKICB4bGltKC04LCA4KSArCiAgeWxpbSgwLCAyMTApCgpwcChmaWxlID0gImltYWdlcy96MjJzYl92c196MjJub3NiX3JlYWN0b21lX3VwLnBuZyIsCiAgIGltYWdlID0gYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0sCiAgIGhlaWdodCA9IDEyLCB3aWR0aCA9IDkpCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIktFR0ciXV0KIyMgS0VHRywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJXUCJdXQojIyBXaWtpUGF0aHdheXMsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1siaW50ZXJhY3RpdmVfcGxvdHMiXV1bWyJXUCJdXQoKYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgpgYGAKCiMjIyBTaGFyZWQgYW5kIHVuaXF1ZSBnZW5lcyBhZnRlci9iZWZvcmUgZHJ1ZwoKYGBge3J9CnNoYXJlZCA8LSBWZW5uZXJhYmxlOjpWZW5uKGxpc3QoCiAgInoyMyIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIzc2JfdnNfejIzbm9zYiJdXSksCiAgInoyMiIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIyc2JfdnNfejIybm9zYiJdXSkpKQpwcChmaWxlID0gImltYWdlcy96MjNfejIyX2RydWdfdmVubl91cC5wbmciKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKZGV2Lm9mZigpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQoKc2hhcmVkIDwtIFZlbm5lcmFibGU6OlZlbm4obGlzdCgKICAiejIzIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyM3NiX3ZzX3oyM25vc2IiXV0pLAogICJ6MjIiID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1siejIyc2JfdnNfejIybm9zYiJdXSkpKQpwcChmaWxlID0gImltYWdlcy96MjNfejIyX2RydWdfdmVubl9kb3duLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmBgYAoKTm90ZTogSSBhbSBzZXR0aWcgdGhlIHggYW5kIHktYXhpcyBib3VuZGFyaWVzIGJ5IGFsbG93aW5nIHRoZSBwbG90dGVyCnRvIHBpY2sgaXRzIG93biBheGlzIHRoZSBmaXJzdCB0aW1lLCB3cml0aW5nIGRvd24gdGhlIHJhbmdlcyBJCm9ic2VydmUsIGFuZCB0aGVuIHNldHRpbmcgdGhlbSB0byB0aGUgbGFyZ2VzdCBvZiB0aGUgcGFpci4gIEl0IGlzCnRoZXJlZm9yZSBwb3NzaWJsZSB0aGF0IEkgbWlzc2VkIG9uZSBvciBtb3JlIGdlbmVzIHdoaWNoIGxpZXMgb3V0c2lkZQp0aGF0IHJhbmdlLgoKVGhlIHByZXZpb3VzIHBsb3R0ZWQgY29udHJhc3RzIHNvdWdodCB0byBzaG93IGNoYW5nZXMgYmV0d2VlbiB0aGUgdHdvCnN0cmFpbnMgejIuMyBhbmQgejIuMi4gIENvbnZlcnNlbHksIHRoZSBwcmV2aW91cyB2b2xjYW5vIHBsb3RzIHNlZWsgdG8KZGlyZWN0bHkgY29tcGFyZSBlYWNoIHN0cmFpbiBiZWZvcmUvYWZ0ZXIgZHJ1ZyB0cmVhdG1lbnQuCgojIExSVCBvZiB0aGUgSHVtYW4gTWFjcm9waGFnZQoKQSBzbGlnaHRseSBkaWZmZXJlbnQgdGFjayB0byBleGFtaW5lIHRoZSBkYXRhIGlzIHRvIHBlcmZvcm0gYQpsaWtlbGlob29kIHJhdGlvIHRlc3QgaW4gb3JkZXIgdG8gbG9vayBmb3IgdHJlbmRzIHdoaWNoIGFyZSBzaGFyZWQKYW1vbmcgZ2VuZXMgd2hlbiBleGFtaW5pbmcgZGlmZmVyZW50IGNvbmRpdGlvbnMgaW4gdGhlIGRhdGEuCgpgYGB7cn0KdG1yYzJfbHJ0X3N0cmFpbl9kcnVnIDwtIGRlc2VxX2xydChoc19tYWNyLCBpbnRlcmFjdG9yX2NvbHVtbiA9ICJkcnVnIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcmVzdF9jb2x1bW4gPSAibWFjcm9waGFnZXp5bW9kZW1lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWN0b3JzID0gYygiZHJ1ZyIsICJtYWNyb3BoYWdlenltb2RlbWUiKSkKdG1yYzJfbHJ0X3N0cmFpbl9kcnVnW1siY2x1c3Rlcl9kYXRhIl1dW1sicGxvdCJdXQpgYGAKCiMgUGFyYXNpdGUKCkxldCB1cyBjb25zaWRlciBmb3IgYSBtb21lbnQgZGlmZmVyZW5jZXMgYW1vbmcgdGhlIHBhcmFzaXRlCnRyYW5zY3JpcHRvbWVzIGZvciB0aGUgc2FtcGxlcyB3aGljaCB3ZXJlIG5vdCBkcnVnIHRyZWF0ZWQuCgpPbmUgdGhpbmcgSSBkaWQgaW4gdGhlIGluaXRpYWwgaW1wbGVtZW50YXRpb24gb2YgdGhpcyBkb2N1bWVudCB3YXMgdG8KcmVwZWF0IHRoZSB2YXJpYWJsZSAndXBfZ2VuZXMnIGZvciBlYWNoIGNvbXBhcmlzb247IEkgdGhpbmsgdGhpcyB0aW1lCkkgd2lsbCBtYWtlIGEgZGlmZmVyZW50IHZhcmlhYmxlIGZvciBlYWNoIGNvbXBhcmlzb24gc28gSSBjYW4gcGxheQp3aXRoIHRoZW0gYSBsaXR0bGUgZnVydGhlci4KCmBgYHtyfQpjb21wYXJpc29uIDwtICJ6MjNfdnNfejIyIgpscF9tYWNyb3BoYWdlX2RlIDwtIGFsbF9wYWlyd2lzZShscF9tYWNyb3BoYWdlX25vc2IsIG1vZGVsX3N2cyA9ICJzdmFzZXEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9mc3RyaW5nID0gIn4gMCArIGNvbmRpdGlvbiIsIGZpbHRlciA9IFRSVUUpCnRtcmMyX3BhcmFzaXRlX2tlZXBlcnMgPC0gbGlzdCgKICAiejIzX3ZzX3oyMiIgPSBjKCJ6MjMiLCAiejIyIikpCmxwX21hY3JvcGhhZ2VfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgbHBfbWFjcm9waGFnZV9kZSwga2VlcGVycyA9IHRtcmMyX3BhcmFzaXRlX2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9wYXJhc2l0ZV9pbmZlY3Rpb25fZGUtdnt2ZXJ9Lnhsc3giKSkKbHBfbWFjcm9waGFnZV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBscF9tYWNyb3BoYWdlX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL3BhcmFzaXRlX3NpZy12e3Zlcn0ueGxzeCIpKQoKbHBfbWFjcm9waGFnZV90YWJsZVtbInBsb3RzIl1dW1tjb21wYXJpc29uXV1bWyJkZXNlcV92b2xfcGxvdHMiXV0KbHBfbWFjcm9waGFnZV90YWJsZVtbInBsb3RzIl1dW1tjb21wYXJpc29uXV1bWyJkZXNlcV9tYV9wbG90cyJdXQoKdXBfZ2VuZXNfejIzejIyIDwtIGxwX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bW2NvbXBhcmlzb25dXQpkaW0odXBfZ2VuZXNfejIzejIyKQpkb3duX2dlbmVzX3oyM3oyMiA8LSBscF9tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bW2NvbXBhcmlzb25dXQpkaW0oZG93bl9nZW5lc196MjN6MjIpCmBgYAoKYGBge3IgcGFyYXNpdGVfdm9sY2Fub30KbHBfejIzc2JfdnNfejIyc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fZGUoCiAgdGFibGUgPSBscF9tYWNyb3BoYWdlX3RhYmxlW1siZGF0YSJdXVtbInoyM192c196MjIiXV0sCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgc2hhcGVzX2J5X3N0YXRlID0gRkFMU0UsIGNvbG9yX2J5ID0gImZjIiwgIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jX3N5bWJvbCIpCnBsb3RseTo6Z2dwbG90bHkobHBfejIzc2JfdnNfejIyc2Jfdm9sY2Fub1tbInBsb3QiXV0pCmxwX3oyM3NiX3ZzX3oyMnNiX3ZvbGNhbm9bWyJwbG90Il1dCmBgYAoKIyMgT250b2xvZ3kgc2VhcmNoCgpBbiBpbXBvcnRhbnQgbm90ZSwgSSByZWNlbnRseSBhZGRlZCBhIG1pbmltdW0gY3Jvc3NyZWZlcmVuY2UgYXJndW1lbnQKKGRlZmF1bHRpbmcgdG8gNDAgZ2VuZXMpLCB3aGljaCBjYXVzZXMgbG90cyBvZiBjb21wYXJpc29ucyB0byBmYWlsIGZvcgpwb29ybHkgYW5ub3RhdGVkIGdlbm9tZXMgKGxpa2UgcGFuYW1lbnNpcy4pICBUaHVzLCBJIGFtIHJlbGF4aW5nIHRoYXQKY29uc3RyYWludCBmb3IgdGhlc2Ugc2VhcmNoZXMuCgpgYGB7cn0KbHBfbGVuZ3RocyA8LSBhbGxfbHBfYW5ub3RbLCBjKCJnaWQiLCAiYW5ub3RfY2RzX2xlbmd0aCIpXQpjb2xuYW1lcyhscF9sZW5ndGhzKSAgPC0gYygiSUQiLCAibGVuZ3RoIikKCnVwX2dvc2VxIDwtIHNpbXBsZV9nb3NlcSh1cF9nZW5lc196MjN6MjIsIGdvX2RiID0gbHBfZ28sCiAgICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGhfZGIgPSBscF9sZW5ndGhzLCBtaW5feHJlZiA9IDE1KQojIyBWaWV3IGNhdGVnb3JpZXMgb3ZlciByZXByZXNlbnRlZCBpbiB0aGUgMi4zIHNhbXBsZXMKdXBfZ29zZXFbWyJwdmFsdWVfcGxvdHMiXV1bWyJicHBfcGxvdF9vdmVyIl1dCmRvd25fZ29zZXEgPC0gc2ltcGxlX2dvc2VxKGRvd25fZ2VuZXNfejIzejIyLCBnb19kYiA9IGxwX2dvLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGhfZGIgPSBscF9sZW5ndGhzLCBtaW5feHJlZiA9IDE1KQojIyBWaWV3IGNhdGVnb3JpZXMgb3ZlciByZXByZXNlbnRlZCBpbiB0aGUgMi4yIHNhbXBsZXMKZG93bl9nb3NlcVtbInB2YWx1ZV9wbG90cyJdXVtbImJwcF9wbG90X292ZXIiXV0KCmNyZWF0ZWQgPC0gZGlyLmNyZWF0ZShnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2dvc2VxX3BhcmFzaXRlIikpCndyaXR0ZW5fZ29zZXEgPC0gd3JpdGVfZ29zZXFfZGF0YSgKICB1cF9nb3NlcSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZ29zZXFfcGFyYXNpdGUvbHBfbWFjcm9waGFnZV9pbmNyZWFzZWRfejIuM19nb3NlcS12e3Zlcn0ueGxzeCIpKQp3cml0dGVuX2dvc2VxIDwtIHdyaXRlX2dvc2VxX2RhdGEoCiAgZG93bl9nb3NlcSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZ29zZXFfcGFyYXNpdGUvbHBfbWFjcm9waGFnZV9pbmNyZWFzZWRfejIuMl9nb3NlcS12e3Zlcn0ueGxzeCIpKQpgYGAKCiMgR1NWQQoKTm90ZTogVGhlIGZvbGxvd2luZyBibG9jayBhc3N1bWVzIG9uZSBpcyBhYmxlIHRvIGRvd25sb2FkIGEgZnJlc2ggY29weQpvZiBtc2lnREIsIHdoaWNoIEkgYW0gbm90IHN1cmUgaXMgcG9zc2libGUgd2l0aGluIHRoZSBjb25zdHJhaW50cyBvZiBhCmNvbnRhaW5lciAoSSBtZWFuIGl0IGlzIHRyaXZpYWwgdG8gZG8sIGJ1dCBJIGFtIG5vdCBzdXJlIGlmIGl0IGlzIG9rCmR1ZSB0byBsaWNlbnNpbmcpLiAgSG93ZXZlciwgQnJvYWQgcHJvdmlkZXMgYSBkYXRhIHBhY2thZ2Ugb2YgYSBtc2lnZGIKcmVsZWFzZS4gIEFzIGEgcmVzdWx0LCB0aGUgZm9sbG93aW5nIGJsb2NrIHdpbGwgYmUgcmVwZWF0ZWQgdXNpbmcgdGhhdC4KCmBgYHtyLCBldmFsPUZBTFNFfQpoc19pbmZlY3RlZCA8LSBzdWJzZXRfc2UoaHNfbWFjcm9waGFnZSwgc3Vic2V0ID0gIm1hY3JvcGhhZ2V0cmVhdG1lbnQhPSd1bmluZiciKSAlPiUKICBzdWJzZXRfc2Uoc3Vic2V0ID0gIm1hY3JvcGhhZ2V0cmVhdG1lbnQhPSd1bmluZl9zYiciKQpoc19nc3ZhX2MyIDwtIHNpbXBsZV9nc3ZhKGhzX2luZmVjdGVkKQpoc19nc3ZhX2MyX21ldGEgPC0gZ2V0X21zaWdkYl9tZXRhZGF0YShoc19nc3ZhX2MyLCBtc2lnX3htbCA9ICJyZWZlcmVuY2UvbXNpZ2RiX3Y3LjIueG1sIikKaHNfZ3N2YV9jMl9zaWcgPC0gZ2V0X3NpZ19nc3ZhX2NhdGVnb3JpZXMoCiAgaHNfZ3N2YV9jMl9tZXRhLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9nc3ZhL2hzX21hY3JvcGhhZ2VfZ3N2YV9jMl9zaWcueGxzeCIpKQpoc19nc3ZhX2MyX3NpZ1tbInJhd19wbG90Il1dCgpoc19nc3ZhX2M3IDwtIHNpbXBsZV9nc3ZhKGhzX2luZmVjdGVkLCBzaWduYXR1cmVfY2F0ZWdvcnkgPSAiYzciKQpoc19nc3ZhX2M3X21ldGEgPC0gZ2V0X21zaWdkYl9tZXRhZGF0YShoc19nc3ZhX2M3LCBtc2lnX3htbCA9ICJyZWZlcmVuY2UvbXNpZ2RiX3Y3LjIueG1sIikKaHNfZ3N2YV9jN19zaWcgPC0gZ2V0X3NpZ19nc3ZhX2NhdGVnb3JpZXMoCiAgaHNfZ3N2YV9jNywKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZ3N2YS9oc19tYWNyb3BoYWdlX2dzdmFfYzdfc2lnLnhsc3giKSkKaHNfZ3N2YV9jN19zaWdbWyJyYXdfcGxvdCJdXQpgYGAKCiMjIFJlcGVhdCB1c2luZyB0aGUgR1NWQWRhdGEgcGFja2FnZS4KCmBgYHtyfQpoc19pbmZlY3RlZCA8LSBzdWJzZXRfc2UoaHNfbWFjcm9waGFnZSwgc3Vic2V0ID0gIm1hY3JvcGhhZ2V0cmVhdG1lbnQhPSd1bmluZiciKSAlPiUKICBzdWJzZXRfc2Uoc3Vic2V0ID0gIm1hY3JvcGhhZ2V0cmVhdG1lbnQhPSd1bmluZl9zYiciKQpoc19nc3ZhX2MyIDwtIHNpbXBsZV9nc3ZhKGhzX2luZmVjdGVkKQojI2hzX2dzdmFfYzJfbWV0YSA8LSBnZXRfbXNpZ2RiX21ldGFkYXRhKGhzX2dzdmFfYzIsIG1zaWdfeG1sPSJyZWZlcmVuY2UvbXNpZ2RiX3Y3LjIueG1sIikKaHNfZ3N2YV9jMl9zaWcgPC0gZ2V0X3NpZ19nc3ZhX2NhdGVnb3JpZXMoCiAgaHNfZ3N2YV9jMiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZ3N2YS9oc19tYWNyb3BoYWdlX2dzdmFfYzJfc2lnLnhsc3giKSkKaHNfZ3N2YV9jMl9zaWdbWyJyYXdfcGxvdCJdXQoKaHNfZ3N2YV9jNyA8LSBzaW1wbGVfZ3N2YShoc19pbmZlY3RlZCwgc2lnbmF0dXJlX2NhdGVnb3J5ID0gImM3IikKIyNoc19nc3ZhX2M3X21ldGEgPC0gZ2V0X21zaWdkYl9tZXRhZGF0YShoc19nc3ZhX2M3LCBtc2lnX3htbD0icmVmZXJlbmNlL21zaWdkYl92Ny4yLnhtbCIpCmhzX2dzdmFfYzdfc2lnIDwtIGdldF9zaWdfZ3N2YV9jYXRlZ29yaWVzKAogIGhzX2dzdmFfYzcsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2dzdmEvaHNfbWFjcm9waGFnZV9nc3ZhX2M3X3NpZy54bHN4IikpCmhzX2dzdmFfYzdfc2lnW1sicmF3X3Bsb3QiXV0KYGBgCgojIFRyeSBvdXQgYSBuZXcgdG9vbAoKVHdvIHJlYXNvbnM6IE5hamliIGxvdmVzIGhpbSBzb21lIFBDQSwgdGhpcyB1c2VzIHdpa2lwYXRod2F5cywgd2hpY2ggaXMgc29tZXRoaW5nIEkgdGhpbmsgaXMgbmVhdC4KCk9rLCBJIHNwZW50IHNvbWUgdGltZSBsb29raW5nIHRocm91Z2ggdGhlIGNvZGUgYW5kIEkgaGF2ZSBzb21lCnByb2JsZW1zIHdpdGggc29tZSBvZiB0aGUgZGVzaWduIGRlY2lzaW9ucy4KCk1vc3QgaW1wb3J0YW50bHksIGl0IHJlcXVpcmVzIGEgZGF0YS5mcmFtZSgpIHdoaWNoIGhhcyB0aGUgZm9sbG93aW5nIGZvcm1hdDoKCjEuICBObyByb3duYW1lcywgaW5zdGVhZCBjb2x1bW4gIzEgaXMgdGhlIHNhbXBsZSBJRC4KMi4gIENvbHVtbnMgMi1tIGFyZSB0aGUgY2F0ZWdvcmljYWwvc3Vydml2YWwvZXRjIG1ldHJpY3MuCjMuICBDb2x1bW5zIG0tbiBhcmUgMSBnZW5lLXBlci1jb2x1bW4gd2l0aCBsb2cyIHZhbHVlcy4KCkJ1dCB3aGVuIEkgdGhpbmsgYWJvdXQgaXQgSSB0aGluayBJIGdldCB0aGUgaWRlYSwgdGhleSB3YW50IHRvIGJlIGFibGUgdG8gZG8gbW9kZWxsaW5nIHN0dWZmCm1vcmUgZWFzaWx5IHdpdGggcmVzcG9uc2UgZmFjdG9ycy4KCmBgYHtyfQpsaWJyYXJ5KHBhdGh3YXlQQ0EpCmxpYnJhcnkocldpa2lQYXRod2F5cykKCmRvd25sb2FkZWQgPC0gZG93bmxvYWRQYXRod2F5QXJjaGl2ZShvcmdhbmlzbSA9ICJIb21vIHNhcGllbnMiLCBmb3JtYXQgPSAiZ210IikKZGF0YV9wYXRoIDwtIHN5c3RlbS5maWxlKCJleHRkYXRhIiwgcGFja2FnZSA9ICJwYXRod2F5UENBIikKd2lraXBhdGh3YXlzIDwtIHJlYWRfZ210KHBhc3RlMChkYXRhX3BhdGgsICIvd2lraXBhdGh3YXlzX2h1bWFuX3N5bWJvbC5nbXQiKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uID0gVFJVRSkKCmV4cHQgPC0gc3Vic2V0X3NlKGhzX21hY3JvcGhhZ2UsIHN1YnNldCA9ICJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmYnIikgJT4lCiAgc3Vic2V0X3NlKHN1YnNldCA9ICJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmZfc2InIikKZXhwdCA8LSBzZXRfc2VfY29uZGl0aW9ucyhleHB0LCBmYWN0ID0gIm1hY3JvcGhhZ2V6eW1vZGVtZSIpCnN5bWJvbF9jb2x1bW4gPC0gImhnbmNfc3ltYm9sIgpzeW1ib2xfdmVjdG9yIDwtIGZEYXRhKGV4cHQpW1tzeW1ib2xfY29sdW1uXV0KbmFtZXMoc3ltYm9sX3ZlY3RvcikgPC0gcm93bmFtZXMoZkRhdGEoZXhwdCkpCnN5bWJvbF9kZiA8LSBhcy5kYXRhLmZyYW1lKHN5bWJvbF92ZWN0b3IpCgphc3NheV9kZiA8LSBtZXJnZShzeW1ib2xfZGYsIGFzLmRhdGEuZnJhbWUoZXhwcnMoZXhwdCkpLCBieSA9ICJyb3cubmFtZXMiKQphc3NheV9kZltbIlJvdy5uYW1lcyJdXSA8LSBOVUxMCnJvd25hbWVzKGFzc2F5X2RmKSA8LSBtYWtlLm5hbWVzKGFzc2F5X2RmW1sic3ltYm9sX3ZlY3RvciJdXSwgdW5pcXVlID0gVFJVRSkKYXNzYXlfZGZbWyJzeW1ib2xfdmVjdG9yIl1dIDwtIE5VTEwKYXNzYXlfZGYgPC0gYXMuZGF0YS5mcmFtZSh0KGFzc2F5X2RmKSkKYXNzYXlfZGZbWyJTYW1wbGVJRCJdXSA8LSByb3duYW1lcyhhc3NheV9kZikKYXNzYXlfZGYgPC0gZHBseXI6OnNlbGVjdChhc3NheV9kZiwgIlNhbXBsZUlEIiwgZXZlcnl0aGluZygpKQoKZmFjdG9yX2RmIDwtIGFzLmRhdGEuZnJhbWUocERhdGEoZXhwdCkpCmZhY3Rvcl9kZltbIlNhbXBsZUlEIl1dIDwtIHJvd25hbWVzKGZhY3Rvcl9kZikKZmFjdG9yX2RmIDwtIGRwbHlyOjpzZWxlY3QoZmFjdG9yX2RmLCAiU2FtcGxlSUQiLCBldmVyeXRoaW5nKCkpCmZhY3Rvcl9kZiA8LSBmYWN0b3JfZGZbLCBjKCJTYW1wbGVJRCIsIGZhY3RvcnMpXQoKdHQgPC0gQ3JlYXRlT21pY3MoCiAgYXNzYXlEYXRhX2RmID0gYXNzYXlfZGYsCiAgcGF0aHdheUNvbGxlY3Rpb25fbHMgPSB3aWtpcGF0aHdheXMsCiAgcmVzcG9uc2UgPSBmYWN0b3JfZGYsCiAgcmVzcFR5cGUgPSAiY2F0ZWdvcmljYWwiLAogIG1pblBhdGhTaXplID0gNSkKCnN1cGVyIDwtIEFFU1BDQV9wVmFscygKICBvYmplY3QgPSB0dCwKICBudW1QQ3MgPSAyLAogIHBhcmFsbGVsID0gRkFMU0UsCiAgbnVtQ29yZXMgPSA4LAogIG51bVJlcHMgPSAyLAogIGFkanVzdG1lbnQgPSAiQkgiKQpgYGAKCiMgRXZhbHVhdGluZyBhIGxvZzJGQyBiYXJwbG90CgpGaWd1cmUgMkUgaXMgbm93IGNvbXByaXNlZCBvZiBhIHBsb3Qgd2hpY2ggc2hvd3MgbG9nMkZDIHZhbHVlcyB3aXRoCmVycm9yIGJhcnMgZm9yIHNlbGVjdGVkIGdlbmVzIGFuZCBzZWVrcyB0byBzaG93IGRpZmZlcmVuY2VzIGJldHdlZW4KMi4zL3VuaW5mZWN0ZWQgYW5kIDIuMi91bmluZmVjdGVkLgoKSGVyZSBpcyB0aGUgdGFibGUgT2xnYSB1c2VkIHRvIGdlbmVyYXRlIGl0OgoKSSB3ZW50IGxvb2tpbmcgaW4gdGhlIHhsc3ggZmlsZXMgcHJvZHVjZWQgaW4gMjAyNDA1IGFuZCBmb3VuZCB0aGF0CnRoZXNlIGFyZSB0aGUgbG9nMkZDIHZhbHVlcyBhbmQgc3RhbmRhcmQgZXJyb3JzIHByb2R1Y2VkIGJ5IERFU2VxMi4KCkl0IHNob3VsZCBiZSBub3RlZCB0aGF0IGluIG15IG1vc3QgcmVjZW50IHZlcnNpb24gb2YgdGhlc2UgYW5hbHlzZXMsCnRoZXNlIG51bWJlcnMgZGlkIHNoaWZ0IHNsaWdodGx5LiAgSSBhbSBsb29raW5nIGludG8gdGhhdCBub3cuCgoqIERhdGEgd2l0b3V0IGRydWcKCioqIDIuMyB2cyBVbmluZmVjdGVkIE3DmCAgICAgICAgICAgIDIuMiB2cyBVbmluZmVjdGVkIE3DmAoKfCBHZW5lIHwgTWVhbiAgIHwgU0VNICAgICAgfCBuIHwgTWVhbiAgfCBTRU0gICAgIHxuIHwKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQp8SUZJMjcgfCAgNy4yMjQgfCAgMC41NjYyICB8NiAgfCAyLjcwMiB8ICAwLjU2NjkgfCA2fAp8UlNBRDIgfCAgNi4yOSAgfCAgMC43MzEyICB8NiAgfCAxLjYyMyB8ICAwLjczMDMgfCA2fAp8Q0NMOCAgfCAgNi4yMjUgfCAgMC45MjggICB8NiAgfCAtMC4zMTR8ICAwLjk0MSAgfCA2fAp8SUZJNDRMfCAgNS44OTUgfCAgMC42MTIgICB8NiAgfCAyLjA2ICB8ICAwLjYxMSAgfCA2fAp8T0FTTCAgfCAgNC43MjYgfCAgMC40OTc0ICB8NiAgfCAxLjM5MiB8ICAwLjQ5NzMgfCA2fAp8VVNQMTggfCAgMy42NDQgfCAgMC40ODMgICB8NiAgfCAwLjk5OSB8ICAwLjQ4MjYgfCA2fAp8SURPMSAgfCAgNy4xNDUgfCAgMS4xMDcgICB8NiAgfCAxLjI1NyB8ICAxLjE0MSAgfCA2fAp8SURPMiAgfCAgMy45MzUgfCAgMS4zICAgICB8NiAgfCAyLjU1NyB8ICAxLjM0MSAgfCA2fAp8S1lOVSAgfCAgMS4wNyAgfCAgMC4yMTg2ICB8NiAgfCAwLjAyMDd8ICAwLjIxODQgfCA2fAp8QUhSICAgfCAwLjkzODIgfCAwLjIyMzYgICB8NiAgfCAwLjUwMzJ8ICAwLjIyMzkgfCA2fAp8SUw0STEgfCAgMi41OTMgfCAgMC40NjIzICB8NiAgfCAwLjAzOSB8ICAwLjQ2MTggfCA2fAp8U09EMiAgfCAgMi43NiAgfCAgMC4zNDkgICB8NiAgfCAwLjQyNDF8ICAwLjM1MjggfCA2fAp8Tk9UQ0gxfCAgMC43NTcyfCAgMC4yNzUgICB8NiAgfCAxLjQ5NSB8ICAwLjI3NDQgfCA2fAp8RExMMSAgfCAgMC44MjY4fCAgMC41Mjg1ICB8NiAgfCAzLjQ1NSB8ICAwLjUyMjggfCA2fAp8RExMNCAgfCAgMS4xMTYgfCAgMC43MzcgICB8NiAgfCA0LjI0MyB8ICAwLjcxICAgfCA2fAp8SEVTMSAgfCAtMC4wMTgzfCAwLjg1OTkgICB8NiAgfCA2LjUzNiB8ICAwLjc5NzMgfCA2fAp8SEVZMSAgfCAgMC41NTMzfCAwLjU3ODkgICB8NiAgfCA0LjE4MSB8ICAwLjYyNzMgfCA2fAoKT2ssIEkgdGhpbmsgSSBmb3VuZCBhIHByb2JsZW06IFRoZSBOT1RDSDEgdmFsdWUgaXMgYWN0dWFsbHkgdGhlCmFkanVzdGVkIHAtdmFsdWUuCgoqIFRyYW5zcG9ydGVycyB3aXRob3V0IGRydWcKCioqIDIuMyB2cyBVbmluZmVjdGVkIE3DmCAgICAgICAgICAgIDIuMiB2cyBVbmluZmVjdGVkIE3DmAoKfCBHZW5lIHwgTWVhbiAgICB8ICAgU0VNICB8IG58ICBNZWFuICAgfCBTRU0gICB8IG58Ci0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KfEFCQ0IxIHwgIC0yLjM1NCB8IDAuNDQyICB8IDZ8ICAgLTAuNDA2fCAgMC40MzF8IDZ8CnxBQkNHNCB8ICAtMy43MTUgfCAwLjY0OCAgfCA2fCAgIC0wLjY1M3wgIDAuNjMwfCA2fAp8QUJDQjUgfCAgLTEuMTkyIHwgMC4zODAgIHwgNnwgICAxLjM1MSB8ICAwLjM2M3wgNnwKfEFCQ0E5IHwgIDEuODgwICB8IDAuNjQ4ICB8IDZ8ICAgMy40NDQgfCAgMC42Mzd8IDZ8CnxBQkNDMiB8ICAwLjQ1NCAgfCAwLjMyMSAgfCA2fCAgIDEuODE4IHwgIDAuMzE0fCA2fAp8QVFQMiAgfCAgLTEuMTkxIHwgMC41MjkgIHwgNnwgICAwLjc0NSB8ICAwLjUxNHwgNnwKfEFRUDMgIHwgIC0wLjk0MCB8IDAuNDAyICB8IDZ8ICAgMC40MzEgfCAgMC4zOTV8IDZ8CgoqIFRyYW5zcG9ydGVycyB3aXRoIGRydWcKCioqIDIuMyB2cyBVbmluZmVjdGVkIE3DmCAgICAgICAgICAgIDIuMiB2cyBVbmluZmVjdGVkIE3DmAoKfEdlbmUgIHwgTWVhbiAgIHwgICAgU0VNIHwgbnwgTWVhbiAgfCAgU0VNICAgfCBuIHwKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCnxBQkNCMSB8ICAtMC42OTd8ICAwLjM0OSB8IDZ8IC0xLjI1NXwgIDAuMzM3IHwgIDZ8CnxBQkNHNCB8ICAxLjIzMSB8ICAwLjUwMyB8IDZ8IDAuNTQ3IHwgIDAuNDg0IHwgIDZ8CnxBUVAyICB8ICAwLjgxNiB8ICAwLjM5OSB8IDZ8IDAuMDQzIHwgIDAuMzg3IHwgIDZ8CnxBUVAzICB8ICAtMS4yODZ8ICAwLjMyMCB8IDZ8IC0xLjYxM3wgIDAuMzA5IHwgIDZ8CnxBUVA4ICB8ICAwLjYzNCB8ICAwLjM3MCB8IDZ8IDAuOTQzIHwgIDAuMzY1IHwgIDZ8CgpMZXQgdXMgbm93IHNlZSBpZiBJIGNhbiByZWNhcGl0dWxhdGUgdGhlIHBsb3QuLi4KCmBgYHtyfQpub2RydWdfY29udHJhc3RzIDwtIGMoInoyM25vc2JfdnNfdW5pbmYiLCAiejIybm9zYl92c191bmluZiIpCmdlbmVzX25vX2RydWcgPC0gYygiSUZJMjciLCAiUlNBRDIiLCAiQ0NMOCIsICJJRkk0NEwiLCAiT0FTTCIsICJVU1AxOCIsICJJRE8xIiwgIklETzIiLCAiS1lOVSIsICJBSFIiLCAiSUw0STEiLCAiU09EMiIsICJOT1RDSDEiLCAiRExMMSIsICJETEw0IiwgIkhFUzEiLCAiSEVZMSIpCnRyYW5zcG9ydGVyc19ub19kcnVnIDwtIGMoIkFCQ0IxIiwgIkFCQ0c0IiwgIkFCQ0I1IiwgIkFCQ0E5IiwgIkFCQ0MyIiwgIkFRUDIiLCAiQVFQMyIpCmRydWdfY29udHJhc3RzIDwtIGMoInoyM3NiX3ZzX3NiIiwgInoyMnNiX3ZzX3NiIikKdHJhbnNwb3J0ZXJzX2RydWcgPC0gYygiQUJDQjEiLCAiQUJDRzQiLCAiQVFQMiIsICJBUVAzIiwgIkFRUDgiKQpgYGAKClRoZXNlIHZhbHVlcyBjYW1lIG91dCBvZiB0aGUgZGF0YSBzdHJ1Y3R1cmUgY2FsbGVkICdoc19tYWNyX3RhYmxlJwoKYGBge3J9CnoyM25vc2JfdW5pbmZfdmFsdWVzIDwtIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzbm9zYl92c191bmluZiJdXQpnZW5lX2lkeCA8LSB6MjNub3NiX3VuaW5mX3ZhbHVlc1tbImhnbmNfc3ltYm9sIl1dICVpbiUgZ2VuZXNfbm9fZHJ1Zwpub2RydWdfcm93cyA8LSAgejIzbm9zYl91bmluZl92YWx1ZXNbZ2VuZV9pZHgsIF0Kcm93bmFtZXMobm9kcnVnX3Jvd3MpIDwtIG5vZHJ1Z19yb3dzW1siaGduY19zeW1ib2wiXV0KejIzX25vZHJ1Z192YWx1ZXMgPC0gbm9kcnVnX3Jvd3NbLCBjKCJkZXNlcV9sb2dmYyIsICJkZXNlcV9sZmNzZSIpXQp6MjNfbm9kcnVnX3ZhbHVlcwoKejIybm9zYl91bmluZl92YWx1ZXMgPC0gaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjJub3NiX3ZzX3VuaW5mIl1dCmdlbmVfaWR4IDwtIHoyMm5vc2JfdW5pbmZfdmFsdWVzW1siaGduY19zeW1ib2wiXV0gJWluJSBnZW5lc19ub19kcnVnCm5vZHJ1Z19yb3dzIDwtICB6MjJub3NiX3VuaW5mX3ZhbHVlc1tnZW5lX2lkeCwgXQpyb3duYW1lcyhub2RydWdfcm93cykgPC0gbm9kcnVnX3Jvd3NbWyJoZ25jX3N5bWJvbCJdXQp6MjJfbm9kcnVnX3ZhbHVlcyA8LSBub2RydWdfcm93c1ssIGMoImRlc2VxX2xvZ2ZjIiwgImRlc2VxX2xmY3NlIildCnoyMl9ub2RydWdfdmFsdWVzCgp6MjNfbm9kcnVnX3ZhbHVlc1tbInN0YXRlIl1dIDwtICJ6MjNfdnNfdW5pbmZlY3RlZCIKejIyX25vZHJ1Z192YWx1ZXNbWyJzdGF0ZSJdXSA8LSAiejIyX3ZzX3VuaW5mZWN0ZWQiCnBsb3RfZGYgPC0gcmJpbmQuZGF0YS5mcmFtZShhcy5kYXRhLmZyYW1lKHoyM19ub2RydWdfdmFsdWVzKSwgYXMuZGF0YS5mcmFtZSh6MjJfbm9kcnVnX3ZhbHVlcykpCnBsb3RfZGZbWyJnZW5lIl1dIDwtIHJvd25hbWVzKHBsb3RfZGYpCgojIyBJIGp1c3QgcmVhbGl6ZWQgdGhhdCB0aGlzIGlzIGFjdHVhbGx5IGp1c3QgYSBjb21wYXJpc29uIG9mIHoyMy96MjIKIyMgd2Ugc2hvdWxkIGp1c3QgdGFrZSB0aGUgYWRqdXN0ZWQgcC12YWx1ZXMgZnJvbSB0aGF0IGNvbnRyYXN0IGZvciB0aGlzLgp6MjNfejIyX2NvbXBhcmlzb24gPC0gaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNub3NiX3ZzX3oyMm5vc2IiXV0Kbm9kcnVnX3Jvd3MgPC0gejIzX3oyMl9jb21wYXJpc29uW2dlbmVfaWR4LCBdCm5vZHJ1Z19wdmFsdWVzIDwtIG5vZHJ1Z19yb3dzWywgYygiZGVzZXFfcCIsICJkZXNlcV9hZGpwIildCnJvd25hbWVzKG5vZHJ1Z19wdmFsdWVzKSA8LSBub2RydWdfcm93c1tbImhnbmNfc3ltYm9sIl1dCm5vZHJ1Z19wdmFsdWVzCgpnZ3Bsb3QocGxvdF9kZiwgYWVzKHggPSBnZW5lLCB5ID0gZGVzZXFfbG9nZmMsIGZpbGwgPSBzdGF0ZSkpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKCksIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IGRlc2VxX2xvZ2ZjIC0gZGVzZXFfbGZjc2UsCiAgICAgICAgICAgICAgICAgICAgeW1heCA9IGRlc2VxX2xvZ2ZjICsgZGVzZXFfbGZjc2UpLAogICAgICAgICAgICAgICAgd2lkdGggPSAwLjIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC45KSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMxQjlFNzciLCAiIzc1NzBCMyIpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUpKQoKY29tcGFyaXNvbiA8LSBjKCJ6MjNfdnNfdW5pbmZlY3RlZCIsICJ6MjJfdnNfdW5pbmZlY3RlZCIpCmNvbXBhcmlzb25zIDwtIHJlcChsaXN0KGNvbXBhcmlzb24pLCBucm93KHBsb3RfZGYpIC8gMikKZ2dwbG90KHBsb3RfZGYsIGFlcyh4ID0gZ2VuZSwgeSA9IGRlc2VxX2xvZ2ZjLCBmaWxsID0gc3RhdGUsIGFkZCA9IGRlc2VxX2xmY3NlLCBmYWNldC5ieSA9ICJzdGF0ZSIpKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgpLCBzdGF0ID0gImlkZW50aXR5IikgKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBkZXNlcV9sb2dmYyAtIGRlc2VxX2xmY3NlLAogICAgICAgICAgICAgICAgICAgIHltYXggPSBkZXNlcV9sb2dmYyArIGRlc2VxX2xmY3NlKSwKICAgICAgICAgICAgICAgIHdpZHRoID0gMC4yLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuOSkpICsKICBzdGF0X2NvbXBhcmVfbWVhbnMoKSArCiAgc3RhdF9jb21wYXJlX21lYW5zKGNvbXBhcmlzb25zID0gY29tcGFyaXNvbnMsIGxhYmVsLnkgPSByb3duYW1lcyh6MjNfbm9kcnVnX3ZhbHVlcykpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMUI5RTc3IiwgIiM3NTcwQjMiKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41KSkKCmBgYAoKRXhjZWxsZW50LCB0aGUgdmFsdWVzIG5vdyBtYXRjaCB1cC4gIE5vdyBJIHVzdCBuZWVkIHRvIGZpZ3VyZSBvdXQgd2h5CnRoZSBzdHVwaWQgaGduYyBJRHMgZ290IGxvc3QuLi4gIEkgY2FuIHNlZSB0aGVtIGluIHRoZSBoc19hbm5vdCBkYXRhCnN0cnVjdHVyZSwgc28gSSBtdXN0IGhhdmUgbWVzc2VkIHVwIHdoZW4gSSByZWdlbmVyZWQgdGhlIGlucHV0IHRvIHRoZQpkZS4gIE9rLCBJIGdvdCB0byB0aGUgc2FtZSBzdGFydGluZyBwb2ludCBub3cgd2l0aCBpZGVudGljYWwgdmFsdWVzLgpBcyBzb29uIGFzIEkgZGlkIHRoYXQsIEkgbG9va2VkIGF0IHRoZSByZXN1bHRpbmcgcGxvdCBhbmQgcmVhbGl6ZWQKdGhhdCB3ZSBhcmUgYWN0dWFsbHkganVzdCBjb21wYXJpbmcgejIzIC8gejIyLgoKSGVyZSBpcyB3aHk6IHRoZSBwbG90IGFzIGl0IHN0YW5kcyBpcyBhIGNvbXBhcmlzb24gb2YgdGhlIGxvZzJGQwp2YWx1ZXMgb2YgdGhlIGZvbGxvd2luZyB0d28gY29udHJhc3RzOiB6MjMvdW5pbmZlY3RlZCBhbmQKejIyL3VuaW5mZWN0ZWQ7IHN0YXRlZCBkaWZmZXJlbnRseSwgdGhpcyBpcyAoejIzL3VuaW5mKS8oejIyL3VuaW5mKQp3aGljaCBvZiBjb3Vyc2UgY2FuY2VscyBvdXQgdG8ganVzdCB6MjMvejIyLgoKVGhlcmVmb3JlIGl0IGlzIG11Y2ggbW9yZSBwYXJzaW1vbmlvdXMgdG8ganVzdCB1c2UgdGhlIHZhbHVlcyBmcm9tCnoyMy96MjIuICBJIHN3ZWFyIEkgaGF2ZSBnb25lIHRocm91Z2ggdGhpcyBleGFjdCBleGVyY2lzZSBvbiBzbyBzbwptYW55IG9jY2FzaW9ucyBpbiB0aGUgcGFzdCBpdCBpcyB0ZXJyaWJsZS4KCmBgYHtyfQp3YW50ZWRfZ2VuZXMgPC0gYygiSUZJMjciLCAiUlNBRDIiLCAiQ0NMOCIsICJJRkk0NEwiLCAiT0FTTCIsCiAgICAgICAgICAgICAgICAgICJVU1AxOCIsICJJRE8xIiwgIklETzIiLCAiS1lOVSIsICJBSFIiLCAiSUw0STEiLAogICAgICAgICAgICAgICAgICAiU09EMiIsICJOT1RDSDEiLCAiRExMMSIsICJETEw0IiwgIkhFUzEiLCAiSEVZMSIpCmdnc2lnbmlmX3Bsb3QgPC0gZ2dzaWduaWZfcGFpcmVkX2dlbmVzKAogIGhzX21hY3IsIGNvbmRpdGlvbnMgPSBjKCJpbmZfejIzIiwgImluZl96MjIiKSwgZ2VuZXMgPSB3YW50ZWRfZ2VuZXMpCmdnc2lnbmlmX3Bsb3QKYGBgCgpgYGB7cn0KcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSkKbWVzc2FnZSgiVGhpcyBpcyBocGdsdG9vbHMgY29tbWl0OiAiLCBnZXRfZ2l0X2NvbW1pdCgpKQp0bXAgPC0gc2F2ZW1lKGZpbGVuYW1lID0gc2F2ZWZpbGUpCmBgYAoKYGBge3IgbG9hZG1lX2FmdGVyLCBldmFsPUZBTFNFfQp0bXAgPC0gbG9hZG1lKGZpbGVuYW1lID0gc2F2ZWZpbGUpCmBgYApkZXZ0b29sczo6bG9hZF9hbGwoJ34vaHBnbHRvb2xzJykK