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+IDAgKyBjb25kaXRpb24iKQpkcnVnX2RlCgpkcnVnX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGRydWdfZGUsIGtlZXBlcnMgPSB0bXJjMl9kcnVnX2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9tYWNyb3BoYWdlX2RydWdfY29tcGFyaXNvbi12e3Zlcn0ueGxzeCIpKQpkcnVnX3RhYmxlCiNjb21iaW5lZF90b190c3YoZHJ1Z190YWJsZSwgY2VsbHR5cGUgPSAiYWxsIikKCmRydWdfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgZHJ1Z190YWJsZSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlX2RydWdfc2lnLXZ7dmVyfS54bHN4IikpCmRydWdfc2lnCmRydWdfaGlnaHNpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGRydWdfdGFibGUsIG1pbl9tZWFuX2V4cHJzID0gaGlnaF9leHByZXNzaW9uLCBleHByc19jb2x1bW4gPSBoaWdoX2V4cHJlc3Npb25fY29sdW1uLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL21hY3JvcGhhZ2VfZHJ1Z19oaWdoc2lnLXZ7dmVyfS54bHN4IikpCmRydWdfaGlnaHNpZwpkcnVnX2xlc3NzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBkcnVnX3RhYmxlLCBsZmMgPSAwLjYsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZV9kcnVnX2xlc3NzaWctdnt2ZXJ9Lnhsc3giKSkKZHJ1Z19sZXNzc2lnCmBgYAoKIyMjIyBnUHJvZmlsZXIyIHJlc3VsdHMgb2YgdGhlIHNpZ25pZmljYW50IGRydWcgZ2VuZXMKCmBgYHtyfQphbGxfZHJ1Z19ncCA8LSBhbGxfZ3Byb2ZpbGVyKGRydWdfc2lnLCBlbnJpY2hfaWRfY29sdW1uID0gImhnbmNfc3ltYm9sIikKYWxsX2RydWdfZ3AKd3JpdHRlbiA8LSB3cml0ZV9hbGxfZ3AoYWxsX2RydWdfZ3ApCgphbGxfZHJ1Z19sZXNzc2lnIDwtIGFsbF9ncHJvZmlsZXIoZHJ1Z19sZXNzc2lnLCBlbnJpY2hfaWRfY29sdW1uID0gImhnbmNfc3ltYm9sIikKd3JpdHRlbiA8LSB3cml0ZV9hbGxfZ3AoYWxsX2RydWdfbGVzc3NpZywgc3VmZml4ID0gIl9sZmMwLjZfIikKYGBgCgojIyMgQ29tYmluZWQgVTkzNyBhbmQgTWFjcm9waGFnZXM6IGNvbXBhcmUgY2VsbCB0eXBlcwoKVGhlcmUgYXJlIGEgY291cGxlIG9mIHdheXMgb25lIG1pZ2h0IHdhbnQgdG8gZGlyZWN0bHkgY29tcGFyZSB0aGUgdHdvCmNlbGwgdHlwZXMuCgoqIEdpdmVuIHRoYXQgdGhlIHZhcmlhbmNlIGJldHdlZW4gdGhlIHR3byBjZWxsdHlwZXMgaXMgc28gaHVnZSwganVzdApjb21wYXJlIGFsbCBzYW1wbGVzLgoqIE9uZSBtaWdodCB3YW50IHRvIGNvbXBhcmUgdGhlbSB3aXRoIHRoZSBpbnRlcmFjdGlvbiBlZmZlY3RzIG9mIGRydWcvenltb2RlbWUuCgpgYGB7cn0KdHlwZV9kZSA8LSBhbGxfcGFpcndpc2UoYWxsX2h1bWFuX3R5cGVzLCBmaWx0ZXIgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9zdnMgPSAic3Zhc2VxIiwgZG9fbm9pc2VxID0gRkFMU0UpCnR5cGVfZGUKCnR5cGVfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgdHlwZV9kZSwga2VlcGVycyA9IHRtcmMyX3R5cGVfa2VlcGVycywKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL21hY3JvcGhhZ2VfdHlwZV9jb21wYXJpc29uLXZ7dmVyfS54bHN4IikpCnR5cGVfdGFibGUKI2NvbWJpbmVkX3RvX3Rzdih0eXBlX3RhYmxlLCBjZWxsdHlwZSA9ICJhbGwiKQoKdHlwZV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB0eXBlX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL21hY3JvcGhhZ2VfdHlwZV9zaWctdnt2ZXJ9Lnhsc3giKSkKdHlwZV9zaWcKdHlwZV9oaWdoc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgdHlwZV90YWJsZSwgbWluX21lYW5fZXhwcnMgPSBoaWdoX2V4cHJlc3Npb24sIGV4cHJzX2NvbHVtbiA9IGhpZ2hfZXhwcmVzc2lvbl9jb2x1bW4sCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZV90eXBlX2hpZ2hzaWctdnt2ZXJ9Lnhsc3giKSkKdHlwZV9oaWdoc2lnCgp0eXBlX2xlc3NzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB0eXBlX3RhYmxlLCBsZmMgPSAwLjYsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZV90eXBlX2xlc3NzaWctdnt2ZXJ9Lnhsc3giKSkKdHlwZV9zaWcKYGBgCgojIyMjIENvbWJpbmVkIGZhY3RvcnMgb2YgaW50ZXJlc3Q6IGNlbGx0eXBlK3p5bW9kZW1lCgpHaXZlbiB0aGUgYWJvdmUgZXhwbGljaXQgY29tcGFyaXNvbiBvZiBhbGwgc2FtcGxlcyBjb21wcmlzaW5nIHRoZSB0d28KY2VsbCB0eXBlcywgbm93IGxldCB1cyBsb29rIGF0IHRoZSBkcnVnIHRyZWF0bWVudCt6eW1vZGVtZSBzdGF0dXMgd2l0aAphbGwgc2FtcGxlcywgbWFjcm9waGFnZXMgYW5kIFU5MzcuCgpgYGB7cn0KdHlwZV96eW1vX2RlIDwtIGFsbF9wYWlyd2lzZSh0eXBlX3p5bW8sIGZpbHRlciA9IFRSVUUsIG1vZGVsX3N2cyA9ICJzdmFzZXEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvX25vaXNlcSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4dHJhX2NvbnRyYXN0cyA9IHR5cGVfenltb19leHRyYSkKdHlwZV96eW1vX2RlCgp0eXBlX3p5bW9fdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgdHlwZV96eW1vX2RlLCBrZWVwZXJzID0gdG1yYzJfdHlwZXp5bW9fa2VlcGVycywKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL21hY3JvcGhhZ2VfdHlwZV96eW1vX2NvbXBhcmlzb24tdnt2ZXJ9Lnhsc3giKSkKI2NvbWJpbmVkX3RvX3Rzdih0eXBlX3p5bW9fdGFibGUsIGNlbGx0eXBlID0gImFsbCIpCgp0eXBlX3p5bW9fc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgdHlwZV96eW1vX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL21hY3JvcGhhZ2VfdHlwZV96eW1vX3NpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX3p5bW9fc2lnCnR5cGVfenltb19oaWdoc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgdHlwZV96eW1vX3RhYmxlLCBtaW5fbWVhbl9leHBycyA9IGhpZ2hfZXhwcmVzc2lvbiwgZXhwcnNfY29sdW1uID0gaGlnaF9leHByZXNzaW9uX2NvbHVtbiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlX3R5cGVfenltb19oaWdoc2lnLXZ7dmVyfS54bHN4IikpCnR5cGVfenltb19sZXNzc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgdHlwZV96eW1vX3RhYmxlLCBsZmMgPSAwLjYsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZV90eXBlX3p5bW9fbGVzc3NpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX3p5bW9fbGVzc3NpZwpgYGAKCiMjIyMgQ29tYmluZWQgZmFjdG9ycyBvZiBpbnRlcmVzdDogY2VsbHR5cGUrZHJ1ZwoKVGhlICd0eXBlX2RydWcnIGRhdGFzdHJ1Y3R1cmUgaXMgdGhlIHNhbWUgYXMgYWJvdmUsIGJ1dCB0aGUgY29uZGl0aW9uCmlzIGNyZWF0ZWQgZnJvbSB0aGUgY29uY2F0ZW5hdGlvbiBvZiB0aGUgY2VsbCB0eXBlIGFuZCBkcnVnIHRyZWF0bWVudC4KCmBgYHtyfQp0eXBlX2RydWdfZGUgPC0gYWxsX3BhaXJ3aXNlKHR5cGVfZHJ1ZywgZmlsdGVyID0gVFJVRSwgbW9kZWxfc3ZzID0gInN2YXNlcSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfZnN0cmluZyA9ICJ+IDAgKyBjb25kaXRpb24iKQp0eXBlX2RydWdfZGUKdHlwZV9kcnVnX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIHR5cGVfZHJ1Z19kZSwga2VlcGVycyA9IHRtcmMyX3R5cGVkcnVnX2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9tYWNyb3BoYWdlX3R5cGVfZHJ1Z19jb21wYXJpc29uLXZ7dmVyfS54bHN4IikpCnR5cGVfZHJ1Z190YWJsZQoKI2NvbWJpbmVkX3RvX3Rzdih0eXBlX2RydWdfdGFibGUsIGNlbGx0eXBlID0gImFsbCIpCgp0eXBlX2RydWdfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgdHlwZV9kcnVnX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL21hY3JvcGhhZ2VfdHlwZV9kcnVnX3NpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX2RydWdfc2lnCgp0eXBlX2RydWdfaGlnaHNpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHR5cGVfZHJ1Z190YWJsZSwgbWluX21lYW5fZXhwcnMgPSBoaWdoX2V4cHJlc3Npb24sIGV4cHJzX2NvbHVtbiA9IGhpZ2hfZXhwcmVzc2lvbl9jb2x1bW4sCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZV90eXBlX2RydWdfaGlnaHNpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX2RydWdfaGlnaHNpZwoKdHlwZV9kcnVnX2xlc3NzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB0eXBlX2RydWdfdGFibGUsIGxmYyA9IDAuNiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlX3R5cGVfZHJ1Z19sZXNzc2lnLXZ7dmVyfS54bHN4IikpCnR5cGVfZHJ1Z19sZXNzc2lnCmBgYAoKIyBJbmRpdmlkdWFsIGNlbGwgdHlwZXMKCkF0IHRoaXMgcG9pbnQsIEkgdGhpbmsgaXQgaXMgZmFpciB0byBzYXkgdGhhdCB0aGUgdHdvIGNlbGwgdHlwZXMgYXJlCnN1ZmZpY2llbnRseSBkaWZmZXJlbnQgdGhhdCB0aGV5IGRvIG5vdCByZWFsbHkgYmVsb25nIHRvZ2V0aGVyIGluIGEKc2luZ2xlIGFuYWx5c2lzLgoKIyMgZHJ1ZyBvciBzdHJhaW4gZWZmZWN0cywgc2luZ2xlIGNlbGwgdHlwZQoKT25lIG9mIHRoZSBxdWVyaWVzIE5hamliIGFza2VkIHdoaWNoIEkgdGhpbmsgSSBtaXNpbnRlcnByZXRlZCB3YXMgdG8KbG9vayBhdCBkcnVnIGFuZC9vciBzdHJhaW4gZWZmZWN0cy4gIE15IGludGVycHJldGF0aW9uIGlzIHNvbWV3aGVyZQpiZWxvdyBhbmQgd2FzIG5vdCB3aGF0IGhlIHdhcyBsb29raW5nIGZvci4gIEluc3RlYWQsIGhlIHdhcyBsb29raW5nIHRvCnNlZSBhbGwobWFjcm9waGFnZSkgZHJ1Zy9ub2RydWcgYW5kIGFsbChtYWNyb3BoYWdlKSB6MjMvejIyIGFuZApjb21wYXJlIHRoZW0gdG8gZWFjaCBvdGhlci4gIEl0IG1heSBiZSB0aGF0IHRoaXMgaXMgc3RpbGwgYSB3cm9uZwppbnRlcnByZXRhdGlvbiwgaWYgc28gdGhlIG1vc3QgbGlrZWx5IGNvbXBhcmlzb24gaXMgZWl0aGVyOgoKKiAgKHoyM2RydWcvejIyZHJ1ZykgLyAoejIzbm9kcnVnL3oyMm5vZHJ1ZyksIG9yIHBlcmhhcHMKKiAgKHoyM2RydWcvejIzbm9kcnVnKSAvICh6MjJkcnVnL3oyMm5vZHJ1ZyksCgpJIGFtIG5vdCBzdXJlIHRob3NlIGNvbmZ1c2UgbWUsIGFuZCBhdCBsZWFzdCBvbmUgb2YgdGhlbSBpcyBiZWxvdwoKIyMgTWFjcm9waGFnZXMKCkluIHRoZXNlIGJsb2NrcyB3ZSB3aWxsIGV4cGxpY2l0bHkgcXVlcnkgb25seSBvbmUgZmFjdG9yIGF0IGEgdGltZSwKZHJ1ZyBhbmQgc3RyYWluLiAgVGhlIGV2ZW50dWFsIGdvYWwgaXMgdG8gbG9vayBmb3IgZWZmZWN0cyBvZgpkcnVnIHRyZWF0bWVudCBhbmQvb3Igc3RyYWluIHRyZWF0bWVudCB3aGljaCBhcmUgc2hhcmVkPwoKIyMjIE1hY3JvcGhhZ2UgRHJ1ZyBvbmx5CgpUaHVzIHdlIHdpbGwgc3RhcnQgd2l0aCB0aGUgcHVyZSBkcnVnIHF1ZXJ5LiAgSW4gdGhpcyBibG9jayB3ZSB3aWxsCmxvb2sgb25seSBhdCB0aGUgZHJ1Zy9ub2RydWcgZWZmZWN0LgoKYGBge3J9CmhzX21hY3JfZHJ1Z19kZSA8LSBhbGxfcGFpcndpc2UoaHNfbWFjcl9kcnVnX3NlLCBmaWx0ZXIgPSBUUlVFLCBtb2RlbF9zdnMgPSAic3Zhc2VxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9mc3RyaW5nID0gIn4gMCArIGNvbmRpdGlvbiIpCmhzX21hY3JfZHJ1Z19kZQoKaHNfbWFjcl9kcnVnX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGhzX21hY3JfZHJ1Z19kZSwga2VlcGVycyA9IHRtcmMyX2RydWdfa2VlcGVycywKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL21hY3JvcGhhZ2Vfb25seWRydWdfdGFibGUtdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9kcnVnX3RhYmxlCgojY29tYmluZWRfdG9fdHN2KGhzX21hY3JfZHJ1Z190YWJsZSwgY2VsbHR5cGUgPSAibWFjcm9waGFnZSIpCgpoc19tYWNyX2RydWdfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgaHNfbWFjcl9kcnVnX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL21hY3JvcGhhZ2Vvbmx5X2RydWdfc2lnLXZ7dmVyfS54bHN4IikpCmhzX21hY3JfZHJ1Z19zaWcKCmhzX21hY3JfZHJ1Z19oaWdoc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgaHNfbWFjcl9kcnVnX3RhYmxlLCBtaW5fbWVhbl9leHBycyA9IGhpZ2hfZXhwcmVzc2lvbiwgZXhwcnNfY29sdW1uID0gaGlnaF9leHByZXNzaW9uX2NvbHVtbiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlb25seV9kcnVnX2hpZ2hzaWctdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9kcnVnX2hpZ2hzaWcKCiMjIENyZWF0aW5nIHRoZSBmb2xsb3dpbmcgdG8gc2VlIGhvdyBpdCBhZmZlY3RzIGdQcm9maWxlci4KaHNfbWFjcl9kcnVnX2xlc3NzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBoc19tYWNyX2RydWdfdGFibGUsIGxmYyA9IDAuNiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlb25seV9kcnVnX3NpZ19sZmMwLjYtdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIyMgTWFjcm9waGFnZSBTdHJhaW4gb25seQoKSW4gYSBzaW1pbGFyIGZhc2hpb24sIGxldCB1cyBsb29rIGZvciBlZmZlY3RzIHdoaWNoIGFyZSBvYnNlcnZlZCB3aGVuCndlIGNvbnNpZGVyIG9ubHkgdGhlIHN0cmFpbiB1c2VkIGR1cmluZyBpbmZlY3Rpb24uCgpgYGB7cn0KaHNfbWFjcl9zdHJhaW5fZGUgPC0gYWxsX3BhaXJ3aXNlKGhzX21hY3Jfc3RyYWluX3NlLCBmaWx0ZXIgPSBUUlVFLCBtb2RlbF9zdnMgPSAic3Zhc2VxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsX2ZzdHJpbmcgPSAifiAwICsgY29uZGl0aW9uIikKaHNfbWFjcl9zdHJhaW5fZGUKCmhzX21hY3Jfc3RyYWluX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGhzX21hY3Jfc3RyYWluX2RlLCBrZWVwZXJzID0gdG1yYzJfc3RyYWluX2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9tYWNyb3BoYWdlX29ubHlzdHJhaW5fdGFibGUtdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9zdHJhaW5fdGFibGUKY29tYmluZWRfdG9fdHN2KGhzX21hY3Jfc3RyYWluX3RhYmxlLCBjZWxsdHlwZSA9ICJtYWNyb3BoYWdlIikKCmhzX21hY3Jfc3RyYWluX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX21hY3Jfc3RyYWluX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL21hY3JvcGhhZ2Vvbmx5X29ubHlzdHJhaW5fc2lnLXZ7dmVyfS54bHN4IikpCmhzX21hY3Jfc3RyYWluX3NpZwoKaHNfbWFjcl9zdHJhaW5faGlnaHNpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX21hY3Jfc3RyYWluX3RhYmxlLCBtaW5fbWVhbl9leHBycyA9IGhpZ2hfZXhwcmVzc2lvbiwgZXhwcnNfY29sdW1uID0gaGlnaF9leHByZXNzaW9uX2NvbHVtbiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlb25seV9vbmx5c3RyYWluX2hpZ2hzaWctdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9zdHJhaW5faGlnaHNpZwoKaHNfbWFjcl9zdHJhaW5fbGVzc3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX21hY3Jfc3RyYWluX3RhYmxlLCBsZmMgPSAwLjYsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZW9ubHlfb25seXN0cmFpbl9sZXNzc2lnLXZ7dmVyfS54bHN4IikpCmhzX21hY3Jfc3RyYWluX2xlc3NzaWcKYGBgCgojIyMgQ29tcGFyZSBEcnVnIGFuZCBTdHJhaW4gRWZmZWN0cwoKTm93IGxldCB1cyBjb25zaWRlciB0aGUgYWJvdmUgdHdvIGNvbXBhcmlzb25zIHRvZ2V0aGVyLiAgRmlyc3QsIEkgd2lsbApwbG90IHRoZSBsb2dGQyB2YWx1ZXMgb2YgdGhlbSBhZ2FpbnN0IGVhY2ggb3RoZXIgKGRydWcgb24geC1heGlzIGFuZApzdHJhaW4gb24gdGhlIHktYXhpcykuICBUaGVuIHdlIGNhbiBleHRyYWN0IHRoZSBzaWduaWZpY2FudCBnZW5lcyBpbiBhCmZldyBjb21iaW5lZCBjYXRlZ29yaWVzIG9mIGludGVyZXN0LiAgSSBhc3N1bWUgdGhlc2Ugd2lsbCBmb2N1cwpleGNsdXNpdmVseSBvbiB0aGUgY2F0ZWdvcmllcyB3aGljaCBpbmNsdWRlIHRoZSBpbnRyb2R1Y3Rpb24gb2YgdGhlCmRydWcuCgpgYGB7cn0KZHJ1Z19zdHJhaW5fY29tcF9kZiA8LSBtZXJnZShoc19tYWNyX2RydWdfdGFibGVbWyJkYXRhIl1dW1siZHJ1ZyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoc19tYWNyX3N0cmFpbl90YWJsZVtbImRhdGEiXV1bWyJzdHJhaW4iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAicm93Lm5hbWVzIikKZHJ1Z19zdHJhaW5fY29tcF9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoCiAgZHJ1Z19zdHJhaW5fY29tcF9kZlssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKIyMgQ29udHJhc3RzOiBhbnRpbW9ueS9ub25lLCB6MjMvejIyOyB4LWF4aXM6IGRydWcsIHktYXhpczogc3RyYWluCiMjIHRvcCBsZWZ0OiBoaWdoZXIgbm8gZHJ1ZywgejIzOyB0b3AgcmlnaHQ6IGhpZ2hlciBkcnVnIHoyMwojIyBib3R0b20gbGVmdDogaGlnaGVyIG5vIGRydWcsIHoyMjsgYm90dG9tIHJpZ2h0OiBoaWdoZXIgZHJ1ZyB6MjIKZHJ1Z19zdHJhaW5fY29tcF9wbG90W1sic2NhdHRlciJdXQpgYGAKCkFzIEkgbm90ZWQgaW4gdGhlIGNvbW1lbnRzIGFib3ZlLCBzb21lIHF1YWRyYW50cyBvZiB0aGUgc2NhdHRlciBwbG90CmFyZSBsaWtlbHkgdG8gYmUgb2YgZ3JlYXRlciBpbnRlcmVzdCB0byB1cyB0aGFuIG90aGVycyAodGhlIHJpZ2h0CnNpZGUpLiAgQmVjYXVzZSBJIGdldCBjb25mdXNlZCBzb21ldGltZXMsIHRoZSBmb2xsb3dpbmcgYmxvY2sgd2lsbApleHBsaWNpdGx5IG5hbWUgdGhlIGNhdGVnb3JpZXMgb2YgbGlrZWx5IGludGVyZXN0LCB0aGVuIGFzayB3aGljaApnZW5lcyBhcmUgc2hhcmVkIGFtb25nIHRoZW0sIGFuZCBmaW5hbGx5IHVzZSBVcFNldFIgdG8gZXh0cmFjdCB0aGUKdmFyaW91cyBnZW5lIGludGVyc2VjdGlvbi91bmlvbiBjYXRlZ29yaWVzLgoKYGBge3J9CmhpZ2hlcl9kcnVnIDwtIGhzX21hY3JfZHJ1Z19zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1sxXV0KaGlnaGVyX25vZHJ1ZyA8LSBoc19tYWNyX2RydWdfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWzFdXQpoaWdoZXJfejIzIDwtIGhzX21hY3Jfc3RyYWluX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1sxXV0KaGlnaGVyX3oyMiA8LSBoc19tYWNyX3N0cmFpbl9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1sxXV0Kc3VtKHJvd25hbWVzKGhpZ2hlcl9kcnVnKSAlaW4lIHJvd25hbWVzKGhpZ2hlcl96MjMpKQpzdW0ocm93bmFtZXMoaGlnaGVyX2RydWcpICVpbiUgcm93bmFtZXMoaGlnaGVyX3oyMikpCnN1bShyb3duYW1lcyhoaWdoZXJfbm9kcnVnKSAlaW4lIHJvd25hbWVzKGhpZ2hlcl96MjMpKQpzdW0ocm93bmFtZXMoaGlnaGVyX25vZHJ1ZykgJWluJSByb3duYW1lcyhoaWdoZXJfejIyKSkKCmRydWdfejIzX2xzdCA8LSBsaXN0KCJkcnVnIiA9IHJvd25hbWVzKGhpZ2hlcl9kcnVnKSwKICAgICAgICAgICAgICAgICAgICAgInoyMyIgPSByb3duYW1lcyhoaWdoZXJfejIzKSkKdXBzZXRfaW5wdXQgPC0gVXBTZXRSOjpmcm9tTGlzdChkcnVnX3oyM19sc3QpCmhpZ2hlcl9kcnVnX3oyMyA8LSB1cHNldCh1cHNldF9pbnB1dCwgdGV4dC5zY2FsZSA9IDIpCmhpZ2hlcl9kcnVnX3oyMwoKZHJ1Z196MjNfc2hhcmVkX2dlbmVzIDwtIG92ZXJsYXBfZ3JvdXBzKGRydWdfejIzX2xzdCkKc2hhcmVkX2dlbmVzX2RydWdfejIzIDwtIG92ZXJsYXBfZ2VuZWlkcyhkcnVnX3oyM19zaGFyZWRfZ2VuZXMsICJkcnVnOnoyMyIpCnNoYXJlZF9nZW5lc19kcnVnX3oyMyA8LSBhdHRyKGRydWdfejIzX3NoYXJlZF9nZW5lcywgImVsZW1lbnRzIilbZHJ1Z196MjNfc2hhcmVkX2dlbmVzW1siZHJ1Zzp6MjMiXV1dCgpkcnVnX3oyMl9sc3QgPC0gbGlzdCgiZHJ1ZyIgPSByb3duYW1lcyhoaWdoZXJfZHJ1ZyksCiAgICAgICAgICAgICAgICAgICAgICJ6MjIiID0gcm93bmFtZXMoaGlnaGVyX3oyMikpCmhpZ2hlcl9kcnVnX3oyMiA8LSB1cHNldChVcFNldFI6OmZyb21MaXN0KGRydWdfejIyX2xzdCksIHRleHQuc2NhbGUgPSAyKQpoaWdoZXJfZHJ1Z196MjIKCmRydWdfejIyX3NoYXJlZF9nZW5lcyA8LSBvdmVybGFwX2dyb3VwcyhkcnVnX3oyMl9sc3QpCnNoYXJlZF9nZW5lc19kcnVnX3oyMiA8LSBvdmVybGFwX2dlbmVpZHMoZHJ1Z196MjJfc2hhcmVkX2dlbmVzLCAiZHJ1Zzp6MjIiKQpzaGFyZWRfZ2VuZXNfZHJ1Z196MjIgPC0gYXR0cihkcnVnX3oyMl9zaGFyZWRfZ2VuZXMsICJlbGVtZW50cyIpW2RydWdfejIyX3NoYXJlZF9nZW5lc1tbImRydWc6ejIyIl1dXQpgYGAKCiMjIyBQZXJmb3JtIGdQcm9maWxlciBvbiBkcnVnL3N0cmFpbiBlZmZlY3Qgc2hhcmVkIGdlbmVzCgpOb3cgdGhhdCB3ZSBoYXZlIHNvbWUgcG9wdWxhdGlvbnMgb2YgZ2VuZXMgd2hpY2ggYXJlIHNoYXJlZCBhY3Jvc3MgdGhlCmRydWcvc3RyYWluIGVmZmVjdHMsIGxldCB1cyBwYXNzIHRoZW0gdG8gc29tZSBHU0VBIGFuYWx5c2VzIGFuZCBzZWUKd2hhdCBwb3BzIG91dC4KCmBgYHtyfQp3YW50ZWQgPC0gZHJ1Z196MjNfc2hhcmVkX2dlbmVzW1siZHJ1Zzp6MjMiXV0Kc2hhcmVkX2dlbmVzX2RydWdfejIzIDwtIGF0dHIoZHJ1Z196MjNfc2hhcmVkX2dlbmVzLCAiZWxlbWVudHMiKVt3YW50ZWRdCnNoYXJlZF9kcnVnX3oyM19ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNoYXJlZF9nZW5lc19kcnVnX3oyMykKc2hhcmVkX2RydWdfejIzX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0Kc2hhcmVkX2RydWdfejIzX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siQlAiXV0Kc2hhcmVkX2RydWdfejIzX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQoKd2FudGVkIDwtIGRydWdfejIyX3NoYXJlZF9nZW5lc1tbImRydWc6ejIyIl1dCnNoYXJlZF9nZW5lc19kcnVnX3oyMiA8LSBhdHRyKGRydWdfejIyX3NoYXJlZF9nZW5lcywgImVsZW1lbnRzIilbd2FudGVkXQpzaGFyZWRfZHJ1Z196MjJfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihzaGFyZWRfZ2VuZXNfZHJ1Z196MjIpCnNoYXJlZF9kcnVnX3oyMl9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCmBgYAoKIyBPdXIgbWFpbiBxdWVzdGlvbiBvZiBpbnRlcmVzdAoKVGhlIGRhdGEgc3RydWN0dXJlIGhzX21hY3IgY29udGFpbnMgb3VyIHByaW1hcnkgbWFjcm9waGFnZXMsIHdoaWNoCmFyZSwgYXMgc2hvd24gYWJvdmUsIHRoZSBkYXRhIHdlIGNhbiByZWFsbHkgc2luayBvdXIgdGVldGggaW50by4KCk5vdGUsIHdlIGV4cGVjdCBzb21lIGVycm9ycyB3aGVuIHJ1bm5pbmcgdGhlIGNvbWJpbmVfZGVfdGFibGVzKCkKYmVjYXVzZSBub3QgYWxsIG1ldGhvZHMgSSB1c2UgYXJlIGNvbWZvcnRhYmxlIHVzaW5nIHRoZSByYXRpbyBvcgpyYXRpb3MgY29udHJhc3RzIHdlIGFkZGVkIGluIHRoZSAnZXh0cmFzJyBhcmd1bWVudC4gIEFzIGEgcmVzdWx0LCB3aGVuCndlIGNvbWJpbmUgdGhlbSBpbnRvIHRoZSBsYXJnZXIgb3V0cHV0IHRhYmxlcywgdGhvc2UgcGVjdWxpYXIKY29udHJhc3RzIGZhaWwuICBUaGlzIGRvZXMgbm90IHN0b3AgaXQgZnJvbSB3cml0aW5nIHRoZSByZXN0IG9mIHRoZQpyZXN1bHRzLCBob3dldmVyLgoKYGBge3J9CiN0ZXN0ID0gZGVzZXFfcGFpcndpc2Uobm9ybWFsaXplX3NlKGhzX21hY3IsIGZpbHRlcj1UUlVFKSwKIyAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9zdnMgPSAic3Zhc2VxIiwgZmlsdGVyID0gVFJVRSwKIyAgICAgICAgICAgICAgICAgICAgICBleHRyYV9jb250cmFzdHMgPSB0bXJjMl9odW1hbl9leHRyYSkKCmhzX21hY3JfZGVfbm9leHRyYSA8LSBhbGxfcGFpcndpc2UoaHNfbWFjciwgbW9kZWxfc3ZzID0gInN2YXNlcSIsIG1vZGVsX2ZzdHJpbmcgPSAifiAwICsgY29uZGl0aW9uIiwgZmlsdGVyID0gVFJVRSkKCmhzX21hY3JfZGUgPC0gYWxsX3BhaXJ3aXNlKGhzX21hY3IsIG1vZGVsX3N2cyA9ICJzdmFzZXEiLCBtb2RlbF9mc3RyaW5nID0gIn4gMCArIGNvbmRpdGlvbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlciA9IFRSVUUsIGV4dHJhX2NvbnRyYXN0cyA9IHRtcmMyX2h1bWFuX2V4dHJhKQpoc19tYWNyX2RlCgpoc19zaW5nbGVfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgaHNfbWFjcl9kZSwga2VlcGVycyA9IHNpbmdsZV90bXJjMl9rZWVwZXIsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9oc19tYWNyX2RydWdfenltb196MjJzYl9zYi12e3Zlcn0ueGxzeCIpKQpoc19zaW5nbGVfdGFibGUKaHNfbWFjcl90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBoc19tYWNyX2RlLCBrZWVwZXJzID0gdG1yYzJfaHVtYW5fa2VlcGVycywKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL2hzX21hY3JfZHJ1Z196eW1vX3RhYmxlX21hY3Jfb25seS12e3Zlcn0ueGxzeCIpKQpoc19tYWNyX3RhYmxlCiNjb21iaW5lZF90b190c3YoaHNfbWFjcl90YWJsZSwgIm1hY3JvcGhhZ2UiKQoKaHNfbWFjcl9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBoc19tYWNyX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL2hzX21hY3JfZHJ1Z196eW1vX3NpZy12e3Zlcn0ueGxzeCIpKQpoc19tYWNyX3NpZwpoc19tYWNyX2hpZ2hzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBoc19tYWNyX3RhYmxlLCBtaW5fbWVhbl9leHBycyA9IGhpZ2hfZXhwcmVzc2lvbiwgZXhwcnNfY29sdW1uID0gaGlnaF9leHByZXNzaW9uX2NvbHVtbiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9oc19tYWNyX2RydWdfenltb19oaWdoc2lnLXZ7dmVyfS54bHN4IikpCmhzX21hY3JfaGlnaHNpZwpoc19tYWNyX2xlc3NzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBoc19tYWNyX3RhYmxlLCBsZmMgPSAwLjYsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvaHNfbWFjcl9kcnVnX3p5bW9fc2lnX2xmYzAuNi12e3Zlcn0ueGxzeCIpKQpoc19tYWNyX2xlc3NzaWcKYGBgCgojIyBnZW5lIGdyb3VwIHVwc2V0CgojIyMgMi4zIHZzIDIuMiB1cCBhbmQgZG93biB2cy4gdW5pbmZlY3RlZAoKVGhpcyBpcyBteSB2ZXJzaW9uIG9mIHRoZSBWZW5uIGRpYWdyYW0gd2hpY2ggaW5jbHVkZXMgdGhlIHRleHQ6CgoiRGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGluIG1hY3JvcGhhZ2VzIGluZmVjdGVkIHdpdGgKc3VicG9wdWxhdGlvbnMgMi4yIG9yIDIuMy4gIFZvbGNhbm8gcGxvdHMgY29udHJhc3Qgb2Y6IEEuIFZlbm4gZGlhZ3JhbQpmb3IgdXByZWd1bGF0ZWQgYW5kIGRvd25yZWd1bGF0ZWQgZ2VuZXMgYnkgaW5mZWN0aW9uIHdpdGggMi4zIGFuZCAyLjIKc3RyYWlucy4gQi4gaW5mZWN0ZWQgY2VsbHMgd2l0aCAyLjMgc3RyYWlucyBhbmQgdW5pbmZlY3RlZCBjZWxsczsKQy4gaW5mZWN0ZWQgY2VsbHMgd2l0aCAyLjIgc3RyYWlucyBhbmQgdW5pbmZlY3RlZCBjZWxsczsgRC4gaW5mZWN0ZWQKY2VsbHMgd2l0aCAyLjMgc3RyYWlucyBhbmQgaW5mZWN0ZWQgY2VsbHMgd2l0aCAyLjIgc3RyYWlucyIKClRoZSBmb2xsb3dpbmcgdXBzZXQgcGxvdCBpcyBjdXJyZW50bHkgRmlndXJlIDJFLgoKYGBge3J9Cm5vZHJ1Z191cHNldCA8LSB1cHNldHJfY29tYmluZWRfZGUoaHNfbWFjcl90YWJsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpcmVkX2NvbnRyYXN0cyA9IGMoInoyMm5vc2JfdnNfdW5pbmYiLCAiejIzbm9zYl92c191bmluZiIpKQpwcChmaWxlID0gImltYWdlcy9ub2RydWdfdXBzZXQuc3ZnIikKbm9kcnVnX3Vwc2V0W1sicGxvdCJdXQpkZXYub2ZmKCkKbm9kcnVnX3Vwc2V0CmBgYAoKIyMjIyBBIHBvaW50IG9mIGludGVyZXN0IHdoaWxlIE9sZ2EgdmlzaXRzIFVtZAoKTmFqaWIgYW5kIE9sZ2EgYXNrZWQgYWJvdXQgcHVsbGluZyB0aGUgOSBnZW5lIElEcyB3aGljaCBhcmUgaW4gdGhlCnBlY3VsaWFyIHNpdHVhdGlvbiBvZiBpbmNyZWFzZWQgZXhwcmVzc2lvbiBpbiB6Mi4yL3VuaW5mIGFuZCBkZWNyZWFzZWQKaW4gejIuMy91bmluZi4gIEluIHRoZSBwcmV2aW91cyB1cHNldCBwbG90LCB0aGVzZSBhcmUgdmlzaWJsZSBpbiB0aGUKNnRoIGJhci4gIEkgY2FuIGFjY2VzcyB0aGVzZSB2aWEgdGhlIGF0dHIoKSBmdW5jdGlvbiwgd2hpY2ggSSBzaG91bGQKYWRtaXQgSSBjYW4gbmV2ZXIgcmVtZW1iZXIgaG93IHRvIHVzZSwgc28gSSBhbSBnb2luZyB0byB1c2UgdGhlIGNvZGUKdW5kZXIgdGhlICdDb21wYXJlKG5vKVNiIHoyLjMvejIuMiB0cmVhdG1lbnQnIGhlYWRpbmcgdG8gcmVtZW1iZXIgaG93CnRvIGV4dHJhY3QgdGhlc2UgZ2VuZXMuCgpgYGB7cn0KYWxsX2dyb3VwcyA8LSBub2RydWdfdXBzZXRbWyJncm91cHMiXV0Kd2FudGVkX2dyb3VwIDwtICJ6MjNub3NiX3ZzX3VuaW5mX2Rvd246ejIybm9zYl92c191bmluZl91cCIKZ2VuZV9pZHggPC0gYWxsX2dyb3Vwc1tbd2FudGVkX2dyb3VwXV0Kd2FudGVkX2dlbmVzIDwtIGF0dHIoYWxsX2dyb3VwcywgImVsZW1lbnRzIilbZ2VuZV9pZHhdCndhbnRlZF9nZW5lcwpnZW5lX3N5bWJvbF9pZHggPC0gcm93bmFtZXMoZkRhdGEoaHNfbWFjcikpICVpbiUgYXMuY2hhcmFjdGVyKHdhbnRlZF9nZW5lcykKZkRhdGEoaHNfbWFjcilbZ2VuZV9zeW1ib2xfaWR4LCAiaGduY19zeW1ib2wiXQpgYGAKCiogQUJDQjU6IEFUQiBCaW5kaW5nIENhc3NldHRlIFN1YmZhbWlseSBCIE1lbWJlciAjNSwgd2lkZSByYW5nZSBvZgogIGZ1bmN0aW9ucyBpbiB0aGlzIGRpdmVyc2UgcGFyYWxvZ291cyBmYW1pbHkuICBBc3NvY2lhdGVkIHdpdGggc2tpbgogIGRpc2Vhc2VzIChtZWxhbm9tYSBhbmQgRXBpZGVybW9seXNpcyBCdWxsb3NhOyBwYXJ0aWNpcGF0ZSBpbgogIEFUUC1kZXBlbmRlbnQgdHJhbnNtZW1icmFuZSB0cmFuc3BvcnQpLgoqIFJGWDQ6IFJlZ3VsYXRvcnkgRmFjdG9yIFggIzQ6IHRyYW5zY3JpcHRpb24gZmFjdG9yLgoqIENBMTQ6IENhcmJvbmljIGFuaHlkcmFzZSAjMTQ6IFp5bmMgbWV0YWxsb2VuenltZSBjYXRhbHl6ZXMKICByZXZlcnNpYmxlIGh5ZHJhdGlvbiBvZiBDTzIuICBUaGlzIGdlbmUgbG9va3MgcHJldHR5IG5lYXQsIGJ1dCBub3QKICByZWFsbHkgcmVsZXZhbnQgdG8gYW55dGhpbmcgd2UgYXJlIGxpa2VseSB0byBjYXJlIGFib3V0LgoqIEVHUjE6IEVhcmx5IEdyb3d0aCBSZXNwb25zZSBQcm90ZWluICMxOiBBbm90aGVyIFR4IGZhY3RvcgogICh6aW5jLWZpbmdlcikgLS0gaW1wb3J0YW50IGZvciBjZWxsIHN1cnZpdmFsL3Byb2xpZmVyYXRpb24vY2VsbAogIGRlYXRoLiAgUHJlc3VtYWJseSBpbXBvcnRhbnQgZm9yIGhlYWxpbmc/CiogTUNGMkw6IE1DRi4yIENlbGwgTGluZSBEZXJpdmVkIFRyYW5zZm9ybWluZyBTZXF1ZW5jZSBMaWtlPyAgZ3VhbmluZQogIG51Y2xlb3RpZGUgZXhjaGFuZ2UgZmFjdG9yIGludGVyYWN0aW5nIHdpdGggR1RQLWJvdW5kIFJhYzEuCiAgQXBwYXJlbnRseSBhc3NvY2lhdGVkIHdpdGggb3N0cm9hcnRocml0aXM7IHBvdGVudGlhbGx5IHJlbGV2YW50IHRvCiAgcmVndWxhdGlvbiBvZiBSSE9BIGFuZCBDREM0MiBzaWduYWxsaW5nLgoqIEROQVNFMUwzOiBEZW94eXJpYm9udWNsZWFzZSBJIGZhbWlseSBtZW1iZXI6IG5vdCBpbmhpYml0ZWQgYnkgYWN0aW4sCiAgYnJlYWtzIGRvd24gRE5BIGR1cmluZyBhcG9wdG9zaXMuICBJbXBvcnRhbnQgZHVyaW5nIG5lY3Jvc2lzLgoqIEZPUzogUHJvdG8tT25jb2dlbmUsIEFQLTEgVHJhbnNjcmlwdGlvbiBGYWN0b3I6IGxldWNpbmUgemlwcGVyCiAgZGltZXJpemVzIHdpdGggSlVOIGZhbWlseSBwcm90ZWlucywgZm9ybWluZyB0eCBmYWN0b3IgY29tcGxleCBBUC0xLgogIEltcG9ydGFudCBmb3IgY2VsbCBwcm9saWZlcmF0aW9uLCBkaWZmZXJlbnRpYXRpb24sIGFuZAogIHRyYW5zZm9ybWF0aW9uLgoqIElGSVRNMTA6IEludGVyZmVyb24tSW5kdWNlZCBUcmFuc21lbWJyYW5lIFByb3RlaW4gIzEwCiogUEtEMUwzOiBQb2x5Y3lzdGluIDEgTGlrZSAjMywgVHJhbnNpZW50IFJlY2VwdG9yIFBvdGVudGlhbCBDaGFubmVsCiAgSW50ZXJhY3Rpbmc6IDExIHRyYW5zbWVtYnJhbmUgZG9tYWluIHByb3RlaW4gd2hpY2ggbWlnaHQgaGVscCBjcmVhdGUKICBjYXRpb24gY2hhbm5lbHMuCgpBcyBzb21lIGNvbXBhcmlzb24gcG9pbnRzLCB0aGUgVmVubiBpbiB0aGUgY3VycmVudCBmaWd1cmUgaGFzOgoKKiAzODcgdXAgejIuMwoqIDI1OSB1cCB6Mi4yCiogODMgc2hhcmVkIHVwIHoyLjMgYW5kIHoyLjIKKiAyNDcgZG93biB6Mi4zCiogMyBkb3duIHoyLjIKKiAzIHNoYXJlZCBkb3duIHoyLjMgYW5kIHoyLjIKCiMjIyAyLjIgYW5kIDIuMyB3aXRoIFNiViB2cyAyLjIgYW5kIDIuMyB3aXRob3V0IFNiVgoKVGhpcyBpcyBteSB2ZXJzaW9uIG9mIHRoZSBWZW5uIHdpdGggdGhlIHRleHQ6CgoiRGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGluIG1hY3JvcGhhZ2VzIGluZmVjdGVkIHdpdGgKc3VicG9wdWxhdGlvbnMgMi4yIG9yIDIuMywgaW4gcHJlc2VuY2Ugb2YgU2JWLiBWb2xjYW5vIHBsb3RzIGNvbnRyYXN0Cm9mOiBBLiBpbmZlY3RlZCBjZWxscyB3aXRoIDIuMyBzdHJhaW5zICsgU2JWIGFuZCBpbmZlY3RlZCBjZWxscyB3aXRoCjIuMyBzdHJhaW5zOyBCLiBpbmZlY3RlZCBjZWxscyB3aXRoIDIuMiBzdHJhaW5zICsgU2JWIGFuZCBpbmZlY3RlZApjZWxscyB3aXRoIDIuMiBzdHJhaW5zOyBDLiBpbmZlY3RlZCBjZWxscyB3aXRoIDIuMyBzdHJhaW5zICsgU2JWIGFuZAppbmZlY3RlZCBjZWxscyB3aXRoIDIuMiBzdHJhaW5zICsgU2JWLiBELiBWZW5uIGRpYWdyYW0gZm9yIHVwcmVndWxhdGVkCmFuZCBkb3ducmVndWxhdGVkIGdlbmVzIGJ5IGluZmVjdGlvbiB3aXRoIDIuMytTYlYgYW5kIDIuMitTYlYKc3RyYWlucy4iCgpBIHF1ZXJ5IGZyb20gT2xnYSAoMjAyNDA4MDEpOiBQbGVhc2UgaW5jbHVkZSBpbiB0aGUgdXBzZXQgaW4gZmlndXJlIDMKdGhlIGNvbnRyYXN0IG9mIHVuaW5mZWN0ZWQgY2VsbHMgKyBTYlYgdnMgdW5pbmZlY3RlZCB3aXRob3V0IFNiVi4KCmBgYHtyfQojIyBJIGtlZXAgbWlzLWludGVycHJldGluZyB0aGlzIHRleHQsIGl0IGlzIHoyLjMvejIuM1NiViBhbmQgejIuMi96Mi4yU2JWCmRydWdub2RydWdfdXBzZXQgPC0gdXBzZXRyX2NvbWJpbmVkX2RlKGhzX21hY3JfdGFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2lyZWRfY29udHJhc3RzID0gYygiejIzc2JfdnNfejIzbm9zYiIsICJ6MjJzYl92c196MjJub3NiIikpCnBwKGZpbGUgPSAiaW1hZ2VzL2RydWdub2RydWdfdXBzZXQucGRmIikKZHJ1Z25vZHJ1Z191cHNldFtbInBsb3QiXV0KZGV2Lm9mZigpCmRydWdub2RydWdfdXBzZXQKCmRydWdub2RydWdfdW5pbmZfY29udHJhc3RzIDwtIGMoInoyM3NiX3ZzX3oyM25vc2IiLCAiejIyc2JfdnNfejIybm9zYiIsICJzYl92c191bmluZiIpCmRydWdub2RydWdfdXBzZXRfd2l0aF91bmluZiA8LSB1cHNldHJfY29tYmluZWRfZGUoaHNfbWFjcl90YWJsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaXJlZF9jb250cmFzdHMgPSBkcnVnbm9kcnVnX3VuaW5mX2NvbnRyYXN0cykKcHAoZmlsZSA9ICJmaWd1cmVzL2RydWdub2RydWdfd2l0aF91bmluZl91cHNldC5zdmciKQpkcnVnbm9kcnVnX3Vwc2V0X3dpdGhfdW5pbmZbWyJwbG90Il1dCmRldi5vZmYoKQpkcnVnbm9kcnVnX3Vwc2V0X3dpdGhfdW5pbmYKYGBgCgpGb3Igc29tZSBjb21wYXJpc29uIHBvaW50cywgdGhlIHZlbm4gaW1hZ2UgaGFzOgoKKiAyMjIgdXAgejIuMyBTYlYKKiAxMzQgdXAgejIuMiBTYlYKKiAxODIgZG93biB6Mi4zIFNiVgoqIDM5NiBkb3duIHoyLjIgU2JWCiogNjA1IHNoYXJlZCBkb3duIHoyLjIgYW5kIHoyLjMgU2JWCiogMzQgc2hhcmVkIGRvd24gejIuMiBTYlYgYW5kIHVwIHoyLjMgU2JWCiogMzYzIHNoYXJlZCB1cCB6Mi4yIFNiViBhbmQgejIuMyBTYlYKCiMjIyBDb21wYXJlIHoyLjJTYlYgdnMgU2JWIGFuZCB6Mi4zU2JWIGFuZCBTYlYKCmBgYHtyfQpkcnVnX3Vwc2V0IDwtIHVwc2V0cl9jb21iaW5lZF9kZShoc19tYWNyX3RhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpcmVkX2NvbnRyYXN0cyA9IGMoInoyMnNiX3ZzX3NiIiwgInoyM3NiX3ZzX3NiIikpCnBwKGZpbGUgPSAiaW1hZ2VzL2RydWdfdXBzZXQucGRmIikKZHJ1Z191cHNldFtbInBsb3QiXV0KZGV2Lm9mZigpCmRydWdfdXBzZXQKYGBgCgojIyBTaWduaWZpY2FuY2UgYmFycGxvdCBvZiBpbnRlcmVzdAoKT2xnYSBraW5kbHkgc2VudCBhIHNldCBvZiBwYXJ0aWN1bGFybHkgaW50ZXJlc3RpbmcgY29udHJhc3RzIGFuZApjb2xvcnMgZm9yIGEgc2lnbmlmaWNhbmNlIGJhcnBsb3QsIHRoZXkgaW5jbHVkZSB0aGUgZm9sbG93aW5nOgoKKiB6Mi4zIHZzLiB1bmluZmVjdGVkLgoqIHoyLjIgdnMuIHVuaW5mZWN0ZWQuCiogejIuMyB2cyB6Mi4yCiogejIuM1NidiB2cyB6Mi4zCiogejIuMlNidiB2cyB6Mi4yCiogejIuM1NidiB2cyB6Mi4yU2J2CiogU2J2IHZzIHVuaW5mZWN0ZWQuCgpUaGUgZXhpc3Rpbmcgc2V0IG9mICdrZWVwZXJzJyBleHZpc2VkIHRvIHRoZXNlIGlzIHRha2VuIGZyb20gdGhlCmV4dGFudCBzZXQgb2YgJ3RtcmMyX2h1bWFuX2tlZXBlcnMnIGFuZCBpcyBhcyBmb2xsb3dzOgoKCmBgYHtyfQpiYXJwbG90X2tlZXBlcnMgPC0gbGlzdCgKICAjIyB6Mi4zIHZzIHVuaW5mZWN0ZWQKICAiejIzbm9zYl92c191bmluZiIgPSBjKCJpbmZ6MjMiLCAidW5pbmZub25lIiksCiAgIyMgejIuMiB2cyB1bmluZmVjdGVkCiAgInoyMm5vc2JfdnNfdW5pbmYiID0gYygiaW5mejIyIiwgInVuaW5mbm9uZSIpLAogICMjIHoyLjMgdnMgejIuMgogICJ6MjNub3NiX3ZzX3oyMm5vc2IiID0gYygiaW5mejIzIiwgImluZnoyMiIpLAogICMjIHoyLjNTYnYgdnMgejIuMwogICJ6MjNzYl92c196MjNub3NiIiA9IGMoImluZnNiejIzIiwgImluZnoyMyIpLAogICMjIHoyLjJTYnYgdnMgejIuMgogICJ6MjJzYl92c196MjJub3NiIiA9IGMoImluZnNiejIyIiwgImluZnoyMiIpLAogICMjIHoyLjNTYnYgdnMgejIuMlNidgogICJ6MjNzYl92c196MjJzYiIgPSBjKCJpbmZzYnoyMyIsICJpbmZzYnoyMiIpLAogICMjIFNidiB2cyB1bmluZmVjdGVkLgogICJzYl92c191bmluZiIgPSBjKCJ1bmluZnNibm9uZSIsICJ1bmluZm5vbmUiKSkKYmFycGxvdF9jb21iaW5lZCA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBoc19tYWNyX2RlLCBrZWVwZXJzID0gYmFycGxvdF9rZWVwZXJzLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9kZV90YWJsZXMvaHNfbWFjcl9kcnVnX3p5bW9fN2NvbnRyYXN0cy12e3Zlcn0ueGxzeCIpKQpgYGAKCk5vdyBsZXQgdXMgdXNlIHRoZSBjb2xvcnMgc3VnZ2VzdGVkIGJ5IE9sZ2EgdG8gbWFrZSBhIGJhcnBsb3Qgb2YKdGhlc2UuLi4KCmBgYHtyfQpjb2xvcl9saXN0IDwtICBjKCAiI2RlOGJmOSIsICIjYWQwN2UzIiwiIzQxMDI1NyIsICIjZmZhMGEwIiwgIiNmOTQwNDAiLCAiI2EwMDAwMCIpCmJhcnBsb3Rfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgYmFycGxvdF9jb21iaW5lZCwgY29sb3JfbGlzdCA9IGNvbG9yX2xpc3QsIGFjY29yZGluZ190byA9ICJkZXNlcSIsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvaHNfbWFjcl9kcnVnX3p5bW9fN2NvbnRyYXN0c19zaWctdnt2ZXJ9Lnhsc3giKSkKYmFycGxvdF9zaWcKYGBgCgojIFBST1BFUgoKSW4gb3VyIGxhc3QgbWVldGluZyB0aGVyZSB3ZXJlIHNvbWUgcXVlc3Rpb25zIGFib3V0IHRoZSBzdGF0aXN0aWNhbApwb3dlciBvZiBkaWZmZXJlbnQgZnV0dXJlIGV4cGVyaW1lbnRhbCBkZXNpZ25zLiAgT25lIHRoaW5nIEkgY2FuIGRvIGlzCnRvIHVzZSBQUk9QRVIgdG8gZXN0aW1hdGUgdGhlIHBvd2VyIG9mIGFuIGV4dGFudCBkYXRhc2V0IGFuZCBpbmZlcgpmcm9tIHRoYXQgdGhlIGxpa2VseSBwb3dlciBvZiBvdGhlciBkZXNpZ25zLgoKSW4gb3JkZXIgdG8gdXNlIHByb3Blciwgb25lIG11c3QgZmVlZCBpdCBvbmUgb3IgbW9yZSBERSB0YWJsZXMuCgpgYGB7cn0KcG93ZXJfZXN0aW1hdGUgPC0gc2ltcGxlX3Byb3Blcihoc19zaW5nbGVfdGFibGUpCgpwb3dlcl9lc3RpbWF0ZVtbMV1dW1sicG93ZXJfcGxvdCJdXQpwb3dlcl9lc3RpbWF0ZVtbMV1dW1sicG93ZXJ0ZF9wbG90Il1dCnBvd2VyX2VzdGltYXRlW1sxXV1bWyJwb3dlcmZkX3Bsb3QiXV0KYGBgCgojIE91ciBtYWluIHF1ZXN0aW9ucyBpbiBVOTM3CgpMZXQgdXMgZG8gdGhlIHNhbWUgY29tcGFyaXNvbnMgaW4gdGhlIFU5Mzcgc2FtcGxlcywgdGhvdWdoIEkgd2lsbCBub3QKZG8gdGhlIGV4dHJhIGNvbnRyYXN0cywgcHJpbWFyaWx5IGJlY2F1c2UgSSB0aGluayB0aGUgZGF0YXNldCBpcyBsZXNzCmxpa2VseSB0byBzdXBwb3J0IHRoZW0uCgpgYGB7cn0KdTkzN19kZSA8LSBhbGxfcGFpcndpc2UodTkzN19zZSwgbW9kZWxfc3ZzID0gInN2YXNlcSIsCiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlciA9IFRSVUUsIGRvX25vaXNlcSA9IEZBTFNFKQp1OTM3X2RlCnU5MzdfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgdTkzN19kZSwga2VlcGVycyA9IHU5Mzdfa2VlcGVycywKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL3U5MzdfZHJ1Z196eW1vX3RhYmxlLXZ7dmVyfS54bHN4IikpCnU5MzdfdGFibGUKY29tYmluZWRfdG9fdHN2KHU5MzdfdGFibGUsIGNlbGx0eXBlID0gInU5MzciKQoKdTkzN19zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB1OTM3X3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL3U5MzdfZHJ1Z196eW1vX3NpZy12e3Zlcn0ueGxzeCIpKQp1OTM3X3NpZwp1OTM3X2hpZ2hzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB1OTM3X3RhYmxlLCBtaW5fbWVhbl9leHBycyA9IGhpZ2hfZXhwcmVzc2lvbiwgZXhwcnNfY29sdW1uID0gaGlnaF9leHByZXNzaW9uX2NvbHVtbiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy91OTM3X2RydWdfenltb19oaWdoc2lnLXZ7dmVyfS54bHN4IikpCnU5MzdfaGlnaHNpZwp1OTM3X2xlc3NzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB1OTM3X3RhYmxlLCBsZmMgPSAwLjYsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvdTkzN19kcnVnX3p5bW9fbGVzc3NpZy12e3Zlcn0ueGxzeCIpKQp1OTM3X2xlc3NzaWcKYGBgCgojIENvbXBhcmUgKG5vKVNiIHoyLjMvejIuMiB0cmVhdG1lbnRzIGFtb25nIG1hY3JvcGhhZ2VzCgpJbiB0aGUgZm9sbG93aW5nIGJsb2NrLCBJIHdpbGwganVtcCBiYWNrIHRvIHRoZSBtYWNyb3BoYWdlIHNhbXBsZXMgYW5kCmxvb2sgZm9yIGdlbmVzIHdoaWNoIGFyZSBzaGFyZWQvdW5pcXVlIHdoZW4gY29tcGFyaW5nIHoyLjMvejIuMgpmb3IgdGhlIGRydWcgdHJlYXRlZCBzYW1wbGVzIGFuZCB0aGUgdW50cmVhdGVkIHNhbXBsZXMuCgpgYGB7cn0KdXBzZXRfcGxvdHNfaHNfbWFjciA8LSB1cHNldHJfc2lnKAogIGhzX21hY3Jfc2lnLCBib3RoID0gVFJVRSwKICBjb250cmFzdHMgPSBjKCJ6MjNzYl92c196MjJzYiIsICJ6MjNub3NiX3ZzX3oyMm5vc2IiKSkKdXBzZXRfcGxvdHNfaHNfbWFjcltbImJvdGgiXV0KZ3JvdXBzIDwtIHVwc2V0X3Bsb3RzX2hzX21hY3JbWyJib3RoX2dyb3VwcyJdXQpzaGFyZWRfZ2VuZXMgPC0gYXR0cihncm91cHMsICJlbGVtZW50cyIpW2dyb3Vwc1tbMl1dXSAlPiUKICBnc3ViKHBhdHRlcm4gPSAiXmdlbmU6IiwgcmVwbGFjZW1lbnQgPSAiIikKbGVuZ3RoKHNoYXJlZF9nZW5lcykKCnNoYXJlZF9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNoYXJlZF9nZW5lcykKc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0Kc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siQlAiXV0Kc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQoKZHJ1Z19nZW5lcyA8LSBhdHRyKGdyb3VwcywgImVsZW1lbnRzIilbZ3JvdXBzW1siejIzc2JfdnNfejIyc2IiXV1dICU+JQogIGdzdWIocGF0dGVybiA9ICJeZ2VuZToiLCByZXBsYWNlbWVudCA9ICIiKQpkcnVnb25seV9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKGRydWdfZ2VuZXMpCmRydWdvbmx5X2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siQlAiXV0KYGBgCgpJIHdhbnQgdG8gdHJ5IHNvbWV0aGluZywgZGlyZWN0bHkgaW5jbHVkZSB0aGUgdTkzNyBkYXRhIGluIHRoaXMuClRodXMsIGluIHRoZSBmb2xsb3dpbmcgYmxvY2sgSSB3aWxsIHJlcGVhdCBidXQgY29tcGFyZSBhbGwgc2FtcGxlcyBhbmQKdGhlIFU5MzcgdXNpbmcgdGhlIHNhbWUgbG9naWMuCgpgYGB7cn0KYm90aF9zaWcgPC0gaHNfbWFjcl9zaWcKbmFtZXMoYm90aF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXSkgPC0gcGFzdGUwKCJtYWNyXyIsIG5hbWVzKGJvdGhfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV0pKQpuYW1lcyhib3RoX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV0pIDwtIHBhc3RlMCgibWFjcl8iLCBuYW1lcyhib3RoX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV0pKQp1OTM3X2Rlc2VxIDwtIHU5Mzdfc2lnW1siZGVzZXEiXV0KbmFtZXModTkzN19kZXNlcVtbInVwcyJdXSkgPC0gcGFzdGUwKCJ1OTM3XyIsIG5hbWVzKHU5MzdfZGVzZXFbWyJ1cHMiXV0pKQpuYW1lcyh1OTM3X2Rlc2VxW1siZG93bnMiXV0pIDwtIHBhc3RlMCgidTkzN18iLCBuYW1lcyh1OTM3X2Rlc2VxW1siZG93bnMiXV0pKQpib3RoX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dIDwtIGMoYm90aF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXSwgdTkzN19kZXNlcVtbInVwcyJdXSkKYm90aF9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dIDwtIGMoYm90aF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXSwgdTkzN19kZXNlcVtbImRvd25zIl1dKQpzdW1tYXJ5KGJvdGhfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV0pCgp1cHNldF9wbG90c19ib3RoIDwtIHVwc2V0cl9zaWcoCiAgYm90aF9zaWcsIGJvdGggPSBUUlVFLAogIGNvbnRyYXN0cyA9IGMoIm1hY3JfejIzc2JfdnNfejIyc2IiLCAibWFjcl96MjNub3NiX3ZzX3oyMm5vc2IiLAogICAgICAgICAgICAgICAgInU5MzdfejIzc2JfdnNfejIyc2IiLCAidTkzN196MjNub3NiX3ZzX3oyMm5vc2IiKSkKdXBzZXRfcGxvdHNfYm90aFtbImJvdGgiXV0KYGBgCgojIyBDb21wYXJlIERFIHJlc3VsdHMgZnJvbSBtYWNyb3BoYWdlcyBhbmQgVTkzNyBzYW1wbGVzCgpMb29raW5nIGEgYml0IG1vcmUgY2xvc2VseSBhdCB0aGVzZSwgSSB0aGluayB0aGUgdTkzNyBkYXRhIGlzIHRvbwpzcGFyc2UgdG8gZWZmZWN0aXZlbHkgY29tcGFyZS4KCmBgYHtyfQptYWNyX3U5MzdfY29tcGFyaXNvbiA8LSBjb21wYXJlX2RlX3Jlc3VsdHMoaHNfbWFjcl90YWJsZSwgdTkzN190YWJsZSkKbWFjcl91OTM3X2NvbXBhcmlzb25bWyJsZmNfaGVhdCJdXQoKbWFjcl91OTM3X3Zlbm5zIDwtIGNvbXBhcmVfc2lnbmlmaWNhbnRfY29udHJhc3RzKGhzX21hY3Jfc2lnLCBzZWNvbmRfc2lnX3RhYmxlcyA9IHU5Mzdfc2lnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJhc3RzID0gInoyM3NiX3ZzX3oyM25vc2IiKQptYWNyX3U5MzdfdmVubnNbWyJ1cF9wbG90Il1dCm1hY3JfdTkzN192ZW5uc1tbImRvd25fcGxvdCJdXQoKbWFjcl91OTM3X3Zlbm5zX3YyIDwtIGNvbXBhcmVfc2lnbmlmaWNhbnRfY29udHJhc3RzKAogIGhzX21hY3Jfc2lnLCBzZWNvbmRfc2lnX3RhYmxlcyA9IHU5Mzdfc2lnLCBjb250cmFzdHMgPSAiejIyc2JfdnNfejIybm9zYiIpCm1hY3JfdTkzN192ZW5uc192MltbInVwX3Bsb3QiXV0KbWFjcl91OTM3X3Zlbm5zX3YyW1siZG93bl9wbG90Il1dCgptYWNyX3U5MzdfdmVubnNfdjMgPC0gY29tcGFyZV9zaWduaWZpY2FudF9jb250cmFzdHMoCiAgaHNfbWFjcl9zaWcsIHNlY29uZF9zaWdfdGFibGVzID0gdTkzN19zaWcsIGNvbnRyYXN0cyA9ICJzYl92c191bmluZiIpCm1hY3JfdTkzN192ZW5uc192M1tbInVwX3Bsb3QiXV0KbWFjcl91OTM3X3Zlbm5zX3YzW1siZG93bl9wbG90Il1dCmBgYAoKIyMgQ29tcGFyZSBtYWNyb3BoYWdlL3U5Mzcgd2l0aCByZXNwZWN0IHRvIHoyLjMvejIuMgoKYGBge3J9CmNvbXBhcmlzb25fZGYgPC0gbWVyZ2UoaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNzYl92c196MjJzYiJdXSwKICAgICAgICAgICAgICAgICAgICAgICB1OTM3X3RhYmxlW1siZGF0YSJdXVtbInoyM3NiX3ZzX3oyMnNiIl1dLAogICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInJvdy5uYW1lcyIpCm1hY3J1OTM3X3oyM3oyMl9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoY29tcGFyaXNvbl9kZlssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKbWFjcnU5MzdfejIzejIyX3Bsb3RbWyJzY2F0dGVyIl1dCgpjb21wYXJpc29uX2RmIDwtIG1lcmdlKGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dLAogICAgICAgICAgICAgICAgICAgICAgIHU5MzdfdGFibGVbWyJkYXRhIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dLAogICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInJvdy5uYW1lcyIpCm1hY3J1OTM3X3oyM3oyMl9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoY29tcGFyaXNvbl9kZlssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKbWFjcnU5MzdfejIzejIyX3Bsb3RbWyJzY2F0dGVyIl1dCmBgYAoKIyBBZGQgZG9ub3IgdG8gdGhlIGNvbnRyYXN0cywgbm8gc3ZhCgpJbiB0aGUgZm9sbG93aW5nIGJsb2NrLCBJIHdpbGwgY2hhbmdlIHRoZSBzYW1wbGUgY29uZGl0aW9uIHRvIGluY2x1ZGUKdGhlIGRvbm9yLgoKYGBge3J9Cm5vX3Bvd2VyX2ZhY3QgPC0gcGFzdGUwKHBEYXRhKGhzX21hY3IpW1siZG9ub3IiXV0sICJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgcERhdGEoaHNfbWFjcilbWyJjb25kaXRpb24iXV0pCnRhYmxlKHBEYXRhKGhzX21hY3IpW1siZG9ub3IiXV0pCnRhYmxlKG5vX3Bvd2VyX2ZhY3QpCmhzX25vcG93ZXIgPC0gc2V0X3NlX2NvbmRpdGlvbnMoaHNfbWFjciwgZmFjdCA9IG5vX3Bvd2VyX2ZhY3QpCmhzX25vcG93ZXIgPC0gc3Vic2V0X3NlKGhzX25vcG93ZXIsIHN1YnNldCA9ICJtYWNyb3BoYWdlenltb2RlbWUhPSdub25lJyIpCmhzX25vcG93ZXJfbm9zdmFfZGUgPC0gYWxsX3BhaXJ3aXNlKGhzX25vcG93ZXIsIG1vZGVsX3N2cyA9IEZBTFNFLCBmaWx0ZXIgPSBUUlVFKQpub3Bvd2VyX2tlZXBlcnMgPC0gbGlzdCgKICAiZDAxX3p5bW8iID0gYygiZDAxaW5mejIzIiwgImQwMWluZnoyMiIpLAogICJkMDFfc2J6eW1vIiA9IGMoImQwMWluZnNiejIzIiwgImQwMWluZnNiejIyIiksCiAgImQwMl96eW1vIiA9IGMoImQwMmluZnoyMyIsICJkMDJpbmZ6MjIiKSwKICAiZDAyX3NienltbyIgPSBjKCJkMDJpbmZzYnoyMyIsICJkMDJpbmZzYnoyMiIpLAogICJkMDlfenltbyIgPSBjKCJkMDlpbmZ6MjMiLCAiZDA5aW5mejIyIiksCiAgImQwOV9zYnp5bW8iID0gYygiZDA5aW5mc2J6MjMiLCAiZDA5aW5mc2J6MjIiKSwKICAiZDgxX3p5bW8iID0gYygiZDgxaW5mejIzIiwgImQ4MWluZnoyMiIpLAogICJkODFfc2J6eW1vIiA9IGMoImQ4MWluZnNiejIzIiwgImQ4MWluZnNiejIyIikpCmhzX25vcG93ZXJfbm9zdmFfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgaHNfbm9wb3dlcl9ub3N2YV9kZSwga2VlcGVycyA9IG5vcG93ZXJfa2VlcGVycywKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL2hzX25vcG93ZXJfdGFibGUtdnt2ZXJ9Lnhsc3giKSkKIyMgZXh0cmFfY29udHJhc3RzID0gZXh0cmEpCmhzX25vcG93ZXJfbm9zdmFfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgaHNfbm9wb3dlcl9ub3N2YV90YWJsZSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9oc19ub3Bvd2VyX25vc3ZhX3NpZy12e3Zlcn0ueGxzeCIpKQoKZDAxZDAyX3p5bW9fbm9zdmFfY29tcCA8LSBtZXJnZShoc19ub3Bvd2VyX25vc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwMV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhzX25vcG93ZXJfbm9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDAyX3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAicm93Lm5hbWVzIikKZDAxMDJfenltb19ub3N2YV9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoZDAxZDAyX3p5bW9fbm9zdmFfY29tcFssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKZDAxMDJfenltb19ub3N2YV9wbG90W1sic2NhdHRlciJdXQpkMDEwMl96eW1vX25vc3ZhX3Bsb3RbWyJjb3JyZWxhdGlvbiJdXQpkMDEwMl96eW1vX25vc3ZhX3Bsb3RbWyJsbV9yc3EiXV0KCmQwOWQ4MV96eW1vX25vc3ZhX2NvbXAgPC0gbWVyZ2UoaHNfbm9wb3dlcl9ub3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDlfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoc19ub3Bvd2VyX25vc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQ4MV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInJvdy5uYW1lcyIpCmQwOTgxX3p5bW9fbm9zdmFfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGQwOWQ4MV96eW1vX25vc3ZhX2NvbXBbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCmQwOTgxX3p5bW9fbm9zdmFfcGxvdFtbInNjYXR0ZXIiXV0KZDA5ODFfenltb19ub3N2YV9wbG90W1siY29ycmVsYXRpb24iXV0KZDA5ODFfenltb19ub3N2YV9wbG90W1sibG1fcnNxIl1dCgpkMDFkODFfenltb19ub3N2YV9jb21wIDwtIG1lcmdlKGhzX25vcG93ZXJfbm9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDAxX3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHNfbm9wb3dlcl9ub3N2YV90YWJsZVtbImRhdGEiXV1bWyJkODFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJyb3cubmFtZXMiKQpkMDE4MV96eW1vX25vc3ZhX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihkMDFkODFfenltb19ub3N2YV9jb21wWywgYygiZGVzZXFfbG9nZmMueCIsICJkZXNlcV9sb2dmYy55IildKQpkMDE4MV96eW1vX25vc3ZhX3Bsb3RbWyJzY2F0dGVyIl1dCmQwMTgxX3p5bW9fbm9zdmFfcGxvdFtbImNvcnJlbGF0aW9uIl1dCmQwMTgxX3p5bW9fbm9zdmFfcGxvdFtbImxtX3JzcSJdXQoKdXBzZXRfcGxvdHNfbm9zdmEgPC0gdXBzZXRyX3NpZyhoc19ub3Bvd2VyX25vc3ZhX3NpZywgYm90aCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJhc3RzID0gYygiZDAxX3p5bW8iLCAiZDAyX3p5bW8iLCAiZDA5X3p5bW8iLCAiZDgxX3p5bW8iKSkKdXBzZXRfcGxvdHNfbm9zdmFbWyJ1cCJdXQp1cHNldF9wbG90c19ub3N2YVtbImRvd24iXV0KdXBzZXRfcGxvdHNfbm9zdmFbWyJib3RoIl1dCiMjIFRoZSA3dGggZWxlbWVudCBpbiB0aGUgYm90aCBncm91cHMgbGlzdCBpcyB0aGUgc2V0IHNoYXJlZCBhbW9uZyBhbGwgZG9ub3JzLgojIyBJIGRvbid0IGZlZWwgbGlrZSB3cml0aW5nIG91dCB4Onk6ejphCmdyb3VwcyA8LSB1cHNldF9wbG90c19ub3N2YVtbImJvdGhfZ3JvdXBzIl1dCnNoYXJlZF9nZW5lcyA8LSBhdHRyKGdyb3VwcywgImVsZW1lbnRzIilbZ3JvdXBzW1s3XV1dICU+JQogIGdzdWIocGF0dGVybiA9ICJeZ2VuZToiLCByZXBsYWNlbWVudCA9ICIiKQpzaGFyZWRfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihzaGFyZWRfZ2VuZXMpCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0Kc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KYGBgCgojIEFkZCBkb25vciB0byB0aGUgY29udHJhc3RzLCBzdmEKClNhbWUgZGVhbCBhcyB0aGUgbGFzdCBibG9jaywgYnV0IHRoaXMgdGltZSBhZGQgU1ZBIGludG8gdGhlIG1peCEKCmBgYHtyfQpoc19ub3Bvd2VyX3N2YV9kZSA8LSBhbGxfcGFpcndpc2UoaHNfbm9wb3dlciwgbW9kZWxfc3ZzID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpCm5vcG93ZXJfa2VlcGVycyA8LSBsaXN0KAogICJkMDFfenltbyIgPSBjKCJkMDFpbmZ6MjMiLCAiZDAxaW5mejIyIiksCiAgImQwMV9zYnp5bW8iID0gYygiZDAxaW5mc2J6MjMiLCAiZDAxaW5mc2J6MjIiKSwKICAiZDAyX3p5bW8iID0gYygiZDAyaW5mejIzIiwgImQwMmluZnoyMiIpLAogICJkMDJfc2J6eW1vIiA9IGMoImQwMmluZnNiejIzIiwgImQwMmluZnNiejIyIiksCiAgImQwOV96eW1vIiA9IGMoImQwOWluZnoyMyIsICJkMDlpbmZ6MjIiKSwKICAiZDA5X3NienltbyIgPSBjKCJkMDlpbmZzYnoyMyIsICJkMDlpbmZzYnoyMiIpLAogICJkODFfenltbyIgPSBjKCJkODFpbmZ6MjMiLCAiZDgxaW5mejIyIiksCiAgImQ4MV9zYnp5bW8iID0gYygiZDgxaW5mc2J6MjMiLCAiZDgxaW5mc2J6MjIiKSkKaHNfbm9wb3dlcl9zdmFfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgaHNfbm9wb3dlcl9zdmFfZGUsIGtlZXBlcnMgPSBub3Bvd2VyX2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9oc19ub3Bvd2VyX3RhYmxlLXZ7dmVyfS54bHN4IikpCiMjIGV4dHJhX2NvbnRyYXN0cyA9IGV4dHJhKQpoc19ub3Bvd2VyX3N2YV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBoc19ub3Bvd2VyX3N2YV90YWJsZSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9oc19ub3Bvd2VyX3N2YV9zaWctdnt2ZXJ9Lnhsc3giKSkKCmQwMWQwMl96eW1vX3N2YV9jb21wIDwtIG1lcmdlKGhzX25vcG93ZXJfc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwMV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoc19ub3Bvd2VyX3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDJfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAicm93Lm5hbWVzIikKZDAxMDJfenltb19zdmFfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGQwMWQwMl96eW1vX3N2YV9jb21wWywgYygiZGVzZXFfbG9nZmMueCIsICJkZXNlcV9sb2dmYy55IildKQpkMDEwMl96eW1vX3N2YV9wbG90W1sic2NhdHRlciJdXQpkMDEwMl96eW1vX3N2YV9wbG90W1siY29ycmVsYXRpb24iXV0KZDAxMDJfenltb19zdmFfcGxvdFtbImxtX3JzcSJdXQoKZDA5ZDgxX3p5bW9fc3ZhX2NvbXAgPC0gbWVyZ2UoaHNfbm9wb3dlcl9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDA5X3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhzX25vcG93ZXJfc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQ4MV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJyb3cubmFtZXMiKQpkMDk4MV96eW1vX3N2YV9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoZDA5ZDgxX3p5bW9fc3ZhX2NvbXBbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCmQwOTgxX3p5bW9fc3ZhX3Bsb3RbWyJzY2F0dGVyIl1dCmQwOTgxX3p5bW9fc3ZhX3Bsb3RbWyJjb3JyZWxhdGlvbiJdXQpkMDk4MV96eW1vX3N2YV9wbG90W1sibG1fcnNxIl1dCgpkMDFkODFfenltb19zdmFfY29tcCA8LSBtZXJnZShoc19ub3Bvd2VyX3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHNfbm9wb3dlcl9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDgxX3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInJvdy5uYW1lcyIpCmQwMTgxX3p5bW9fc3ZhX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihkMDFkODFfenltb19zdmFfY29tcFssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKZDAxODFfenltb19zdmFfcGxvdFtbInNjYXR0ZXIiXV0KZDAxODFfenltb19zdmFfcGxvdFtbImNvcnJlbGF0aW9uIl1dCmQwMTgxX3p5bW9fc3ZhX3Bsb3RbWyJsbV9yc3EiXV0KCnVwc2V0X3Bsb3RzX3N2YSA8LSB1cHNldHJfc2lnKGhzX25vcG93ZXJfc3ZhX3NpZywgYm90aCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyYXN0cyA9IGMoImQwMV96eW1vIiwgImQwMl96eW1vIiwgImQwOV96eW1vIiwgImQ4MV96eW1vIikpCnVwc2V0X3Bsb3RzX3N2YVtbInVwIl1dCnVwc2V0X3Bsb3RzX3N2YVtbImRvd24iXV0KdXBzZXRfcGxvdHNfc3ZhW1siYm90aCJdXQojIyBUaGUgN3RoIGVsZW1lbnQgaW4gdGhlIGJvdGggZ3JvdXBzIGxpc3QgaXMgdGhlIHNldCBzaGFyZWQgYW1vbmcgYWxsIGRvbm9ycy4KIyMgSSBkb24ndCBmZWVsIGxpa2Ugd3JpdGluZyBvdXQgeDp5Ono6YQpncm91cHMgPC0gdXBzZXRfcGxvdHNfc3ZhW1siYm90aF9ncm91cHMiXV0Kc2hhcmVkX2dlbmVzIDwtIGF0dHIoZ3JvdXBzLCAiZWxlbWVudHMiKVtncm91cHNbWzddXV0gJT4lCiAgZ3N1YihwYXR0ZXJuID0gIl5nZW5lOiIsIHJlcGxhY2VtZW50ID0gIiIpCnNoYXJlZF9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNoYXJlZF9nZW5lcykKc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0Kc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siQlAiXV0Kc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQpzaGFyZWRfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJXUCJdXQpgYGAKCiMgRG9ub3IgY29tcGFyaXNvbgoKTm93IGNvbXBhcmUgdGhlIGRvbm9ycyB0byBlYWNoIG90aGVyIGRpcmVjdGx5LgoKYGBge3J9CmhzX2Rvbm9ycyA8LSBzZXRfc2VfY29uZGl0aW9ucyhoc19tYWNyLCBmYWN0ID0gImRvbm9yIikKZG9ub3JfZGUgPC0gYWxsX3BhaXJ3aXNlKGhzX2Rvbm9ycywgbW9kZWxfc3ZzID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpCmRvbm9yX2RlCmRvbm9yX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGRvbm9yX2RlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9kZV90YWJsZXMvZG9ub3JfdGFibGVzLXZ7dmVyfS54bHN4IikpCmRvbm9yX3RhYmxlCmRvbm9yX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGRvbm9yX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL2Rvbm9yX3NpZy12e3Zlcn0ueGxzeCIpKQpkb25vcl9zaWcKYGBgCgojIFByaW1hcnkgcXVlcnkgY29udHJhc3RzCgpUaGUgZmluYWwgY29udHJhc3QgaW4gdGhpcyBsaXN0IGlzIGludGVyZXN0aW5nIGJlY2F1c2UgaXQgZGVwZW5kcyBvbgp0aGUgZXh0cmEgY29udHJhc3RzIGFwcGxpZWQgdG8gdGhlIGFsbF9wYWlyd2lzZSgpIGFib3ZlLiAgSW4gbXkgd2F5IG9mCnRoaW5raW5nLCB0aGUgcHJpbWFyeSBjb21wYXJpc29ucyB0byBjb25zaWRlciBhcmUgZWl0aGVyIGNyb3NzLWRydWcgb3IKY3Jvc3Mtc3RyYWluLCBidXQgbm90IGJvdGguICBIb3dldmVyIEkgdGhpbmsgaW4gYXQgbGVhc3QgYSBmZXcKaW5zdGFuY2VzIE9sZ2EgaXMgaW50ZXJlc3RlZCBpbiBzdHJhaW4rZHJ1ZyAvIHVuaW5mZWN0ZWQrbm9kcnVnLgoKIyMgV3JpdGUgY29udHJhc3QgcmVzdWx0cwoKTm93IGxldCB1cyB3cml0ZSBvdXQgdGhlIHhsc3ggZmlsZSBjb250YWluaW5nIHRoZSBhYm92ZSBjb250cmFzdHMuClRoZSBmaWxlIHdpdGggdGhlIHN1ZmZpeCBfdGFibGUtdmVyc2lvbiB3aWxsIHRoZXJlZm9yZSBjb250YWluIGFsbApnZW5lcyBhbmQgdGhlIGZpbGUgd2l0aCB0aGUgc3VmZml4IF9zaWctdmVyc2lvbiB3aWxsIGNvbnRhaW4gb25seQp0aG9zZSBkZWVtZWQgc2lnbmlmaWNhbnQgdmlhIG91ciBkZWZhdWx0IGNyaXRlcmlhIG9mIERFU2VxMiB8bG9nRkN8ID49IDEuMAphbmQgYWRqdXN0ZWQgcC12YWx1ZSA8PSAwLjA1LgoKIyMgT3ZlciByZXByZXNlbnRhdGlvbiBzZWFyY2hlcwoKSSBkZWNpZGVkIHRvIG1ha2Ugb25lIGluaXRpYWxseSBzbWFsbCwgYnV0IEkgdGhpbmsgcXVpY2tseSBiaWcgY2hhbmdlCnRvIHRoZSBvcmdhbml6YXRpb24gb2YgdGhpcyBkb2N1bWVudDogIEkgYW0gbW92aW5nIHRoZSBHU0VBIHNlYXJjaGVzCnVwIHRvIGltbWVkaWF0ZWx5IGFmdGVyIHRoZSBERS4gIEkgd2lsbCB0aGVuIG1vdmUgdGhlIHBsb3RzIG9mIHRoZQpncHJvZmlsZXIgcmVzdWx0cyB0byBpbW1lZGlhdGVseSBhZnRlciB0aGUgdmFyaW91cyB2b2xjYW5vIHBsb3RzIHNvCnRoYXQgaXQgaXMgZWFzaWVyIHRvIGludGVycHJldCB0aGVtLgoKSSBhbSByZWFzb25hYmx5IGNlcnRhaW4gdGhpcyBpcyB0aGUgcGxhY2UgdG8gY2hlY2sgdGhhdCB6MjNubyBkcnVnIC8KdW5pbmZlY3RlZCBoYXMgdGhlIGV4cGVjdGVkIHNldCBvZiBnZW5lcyBhbmQgdGhhdCB0aGVyZSBpcyBvciBpcyBub3QgYQpyZWFjdG9tZSByZXN1bHQuCgpSZXByb2R1Y2liaWxpdHkgbm90ZTogR2l2ZW4gdGhhdCB0aGlzIGlzIGVudGlyZWx5IGRlcGVuZGVudCBvbiBhbgpvbmxpbmUgc2VydmljZSwgSSBtdXN0IGFzc3VtZSB0aGF0IHRoZSByZXN1bHRzIHdpbGwgY2hhbmdlIG92ZXIgdGltZTsKaW4gYWRkaXRpb24gdGhlaXIgd2ViIHNlcnZlcnMgdW5kZXJnbyBtYWludGVuYW5jZSByZWd1bGFybHksIHdoaWNoIG1heQpyZXN1bHQgaW4gc3lzdGVtYXRpYyBmYWlsdXJlIG9mIHRoZXNlIGFuYWx5c2VzLiAgSSBsaWtlIGdQcm9maWxlcgpxdWl0ZSBhIGxvdCBmb3IgdGhpcyB0eXBlIG9mIHN0dWZmLCBidXQgdGhpcyBpcyBhbiBpbXBvcnRhbnQgY2F2ZWF0LgoKQ29udmVyc2VseSwgdGhlIGNsdXN0ZXJQcm9maWxlciByZXN1bHRzIGxhdGVyIGRlcGVuZCBvbiBhIGNvbnNpc3RlbnQKb3JnZGIgYW5ub3RhdGlvbiBzZXQgKG9yIHJlYWN0b21lIG9yIHdoYXRldmVyKTsgdGhvc2UgdmVyc2lvbnMgYXJlCmZpeGVkIGJ5IHRoZSBjb250YWluZXIgaW5zdGFsbGF0aW9uLgoKYGBge3J9CmFsbF9ncCA8LSBhbGxfZ3Byb2ZpbGVyKGhzX21hY3Jfc2lnLCBlbnJpY2hfaWRfY29sdW1uID0gImhnbmNzeW1ib2wiKQpmb3IgKGcgaW4gc2VxX2xlbihsZW5ndGgoYWxsX2dwKSkpIHsKICBuYW1lIDwtIG5hbWVzKGFsbF9ncClbZ10KICBkYXR1bSA8LSBhbGxfZ3BbW25hbWVdXQogIGZpbGVuYW1lIDwtIGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZ3Byb2ZpbGVyL3tuYW1lfV9ncHJvZmlsZXItdnt2ZXJ9Lnhsc3giKQogIHdyaXR0ZW4gPC0gc20od3JpdGVfZ3Byb2ZpbGVyX2RhdGEoZGF0dW0sIGV4Y2VsID0gZmlsZW5hbWUpKQp9CmBgYAoKIyMgRXhwbGljaXQgR1NFQSBzZWFyY2ggdmlzIGNsdXN0ZXJQcm9maWxlcgoKYGBge3J9CmFsbF9jcCA8LSBhbGxfY3Byb2ZpbGVyKGhzX21hY3Jfc2lnLCBoc19tYWNyX3RhYmxlKQpgYGAKCiMjIFNwZWNpZmljIGRlc2lyZXMgaW4gUmVhY3RvbWUgcmVzdWx0cwoKSW4gcHJldmlvdXMgYW5hbHlzZXMgKEkgdGhpbmsgYnkgRHIuIENvbG1lbmFyZXMpLCBhIHNwZWNpZmljClRyeXB0b3BoYW4gYmlvc3ludGhlc2lzIHBhdGh3YXkgd2FzIG9ic2VydmVkLiAgUGFydGNpdWxhcmx5IGluIHRoZQoyLjMvdW5pbmZlY3RlZCBjb21wYXJpc29uLiAgSSB0aGluayBteSBncHJvZmlsZXIgYW5hbHlzaXMgaXMgdG9vCnN0cmluZ2VudCBhbmQgdGhlcmVmb3JlIG5vdCBvYnNlcnZpbmcgdGhpcy4gIE9sZ2EgYXNrZWQgaWYgSSBjb3VsZApsb29rIGF0IHRoYXQgYW5kIHNlZSBpZiB0aGVyZSBhcmUgdHJpdmlhbCBzZXR0aW5ncyBJIGNhbiBjaGFuZ2UgdG8KaGlnaGxpZ2h0IHRoaXMgcGF0aHdheS4gIFRoZSB0d28gbW9zdCBsaWtlbHkgdGhpbmdzIEkgY2FuIGNoYW5nZSBhcmUKdGhlIHN0cmluZ2VuY2llcyBvZiB0aGUgREUgYW5hbHlzaXMgYW5kL29yIGdQcm9maWxlci4KCmBgYHtyfQp0ZXN0X3oyM191bmluZl91cCA8LSBoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIzbm9zYl92c191bmluZiJdXQpucm93KHRlc3RfejIzX3VuaW5mX3VwKQp0ZXN0X3oyM191bmluZl9kb3duIDwtIGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyM25vc2JfdnNfdW5pbmYiXV0KbnJvdyh0ZXN0X3oyM191bmluZl9kb3duKQoKdGVzdF9ncF91cCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHRlc3RfejIzX3VuaW5mX3VwLCBlbnJpY2hfaWRfY29sdW1uID0gImhnbmNzeW1ib2wiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyZXNob2xkID0gMS4wKQp0ZXN0X2dwX3VwCndyaXR0ZW5fdXAgPC0gd3JpdGVfZ3Byb2ZpbGVyX2RhdGEodGVzdF9ncF91cCwgZXhjZWwgPSAiZXhjZWwvejIzX3VuaW5mX2dwX3VwX2FsbC54bHN4IikKCnRlc3RfZ3BfZG93biA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHRlc3RfejIzX3VuaW5mX2Rvd24sIGVucmljaF9pZF9jb2x1bW4gPSAiaGduY3N5bWJvbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocmVzaG9sZCA9IDEuMCkKdGVzdF9ncF9kb3duCndyaXR0ZW5fZG93biA8LSB3cml0ZV9ncHJvZmlsZXJfZGF0YSh0ZXN0X2dwX2Rvd24sIGV4Y2VsID0gImV4Y2VsL3oyM191bmluZl9ncF9kb3duX2FsbC54bHN4IikKYGBgCgojIyBQbG90IGNvbnRyYXN0cyBvZiBpbnRlcmVzdAoKT25lIHN1Z2dlc3Rpb24gSSByZWNlaXZlZCByZWNlbnRseSB3YXMgdG8gc2V0IHRoZSBheGVzIGZvciB0aGVzZQp2b2xjYW5vIHBsb3RzIHRvIGJlIHN0YXRpYyByYXRoZXIgdGhhbiBsZXQgZ2dwbG90IGNob29zZSBpdHMgb3duLiAgSQphbSBhc3N1bWluZyB0aGlzIGlzIG9ubHkgcmVsZXZhbnQgZm9yIHBhaXJzIG9mIGNvbnRyYXN0cywgYnV0IHRoYXQKbWlnaHQgbm90IGJlIHRydWUuCgojIyBJbmRpdmlkdWFsIHp5bW9kZW1lcyB2cy4gdW5pbmZlY3RlZAoKVGhlIGZvbGxvd2luZyBibG9ja3Mgd2lsbCBiZSBhIGxvdCBvZiByZXBldGl0aW9uLiAgSW4gZWFjaCBjYXNlIEkgYW0KeWFua2luZyBvdXQgdGhlIHZvbGNhbm8gcGxvdCBmb3IgYSBzcGVjaWZpYyBjb250cmFzdCBhbmQgc2hvd2luZyB0aGUKb3JpZ2luYWwgZm9sbG93ZWQgYnkgYSB2ZXJzaW9uIHdpdGggZGlmZmVyZW50IGNvbG9ycy9sYWJlbGxpbmcuCgojIyMgSW5mZWN0ZWQgd2l0aCB6Mi4zIG5vIEFudGltb25pYWwgdnMuIFVuaW5mZWN0ZWQKCmBgYHtyfQpwbG90X2NvbG9ycyA8LSBnZXRfc2VfY29sb3JzKGhzX21hY3JfdGFibGVbWyJpbnB1dCJdXVtbImlucHV0Il1dKQoKIyMgVGhlIG9yaWdpbmFsIHBsb3QgZnJvbSBteSB4bHN4IGZpbGUKaHNfbWFjcl90YWJsZVtbInBsb3RzIl1dW1siejIzbm9zYl92c191bmluZiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQoKejIzbm9zYl92c191bmluZl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaW5wdXQgPSBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyM25vc2JfdnNfdW5pbmYiXV0sCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiLAogIGNvbG9yX2xvdyA9IHBsb3RfY29sb3JzW1sidW5pbmZub25lIl1dLCBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJpbmZ6MjMiXV0pCgpsYWJlbGVkIDwtIHoyM25vc2JfdnNfdW5pbmZfdm9sY2Fub1tbInBsb3QiXV0gKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC02LCAyMSksIGJyZWFrcyA9IGMoLTYsIC00LCAtMiwgMCwgMiwgNCwgNiwgOCwgMTAsIDIwKSkgKwogIGdnYnJlYWs6OnNjYWxlX3hfYnJlYWsoYygxMCwgMTkpLCBzY2FsZXMgPSAwLjIsIHNwYWNlID0gMC4wMikKcHAoZmlsZSA9ICJmaWd1cmVzL2ZpZzJhX2xhYmVsZWRfd2l0aF9icmVhay5zdmciKQpsYWJlbGVkCmRldi5vZmYoKQpsYWJlbGVkCgpwbG90bHk6OmdncGxvdGx5KHoyM25vc2JfdnNfdW5pbmZfdm9sY2Fub1tbInBsb3QiXV0pCmBgYAoKVGhlIGZvbGxvd2luZyBwcm92aWRlcyBzb21lIG9mIHRoZSBvdmVyLXJlcHJlc2VudGF0aW9uIHBsb3RzIGZyb20gZ1Byb2ZpbGVyMi4KCmBgYHtyfQphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJLRUdHIl1dCiMjIEtFR0csIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgojI2FsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJXUCJdXQojIyBXaWtpUGF0aHdheXMsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX3VwIl1dW1siaW50ZXJhY3RpdmVfcGxvdHMiXV1bWyJXUCJdXQoKbWVzc2FnZSgiT2xnYSByZWNlaXZlZCBhIHF1ZXJ5IGFib3V0IHRoZSBmb2xsb3dpbmcgcmVzdWx0LCBJIHRoaW5rIGl0IGlzIG51bGwuIikKYWxsX2dwW1siejIzbm9zYl92c191bmluZl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQptZXNzYWdlKCJJcyB0aGUgcHJldmlvdXMgcGxvdCBudWxsPyIpCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmBgYAoKV2UgaGF2ZSBzb21lIG90aGVyIGNhdGVnb3JpY2FsIGVucmljaG1lbnQgcGxvdHMgYXZhaWxhYmxlIHZpYQplbnJpY2hwbG90LCBsZXQgdXMgdHJ5IGEgZmV3IG91dCBmb3IgY29udHJhc3RzIG9mIGludGVyZXN0IGFuZCBzZWUgaWYKYW55IG9mIHRoZW0gcHJvdmUgaGVscGZ1bC4KCkZpcnN0LCBhcyBhIHJlbWluZGVyLCBoZXJlIGFyZSB0aGUgY29udHJhc3RzIHdoaWNoIGFyZSBhdmFpbGFibGUgdG8KZXhhbWluZSwgaW4gZWFjaCBjYXNlIHRoZXJlIGlzIGFuIF91cCBhbmQgX2Rvd24gZW5yaWNobWVudCBvYmplY3QgaW4KdGhlIGRhdGEuICBUaHVzIGluIHRoZSBmb2xsb3dpbmcgbGlzdCBJIGFtIGdvaW5nIHRvIGFyYml0cmFyaWx5IHByaW50Cm91dCBzb21lIGludm9jYXRpb25zIHdoaWNoIGV4dHJhY3QgcHV0YXRpdmVseSBpbnRlcmVzdGluZyBiaXRzIG9mIGRhdGEuCgoqIHoyM25vc2JfdnNfdW5pbmY6IGFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfdXAiXV1bWyJCUF9lbnJpY2giXV0KKiB6MjJub3NiX3ZzX3VuaW5mLgoqIHoyM25vc2JfdnNfejIybm9zYi4KKiB6MjNzYl92c196MjJzYi4KKiB6MjNzYl92c196MjNub3NiLgoqIHoyMnNiX3ZzX3oyMm5vc2IuCiogejIzc2JfdnNfc2IuCiogejIyc2JfdnNfc2IuCiogejIzc2JfdnNfdW5pbmYuCiogejIyc2JfdnNfdW5pbmYuCiogc2JfdnNfdW5pbmYuCiogZXh0cmFfejIzMjIuCiogZXh0cmFfZHJ1Z25vZHJ1Zy4KCmBgYHtyfQp6MjNub3NiX3VuaW5mX3VwX2dvIDwtIGFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfdXAiXV1bWyJCUF9lbnJpY2giXV0KejIzbm9zYl91bmluZl91cF9nb19wYWlyIDwtIHBhaXJ3aXNlX3Rlcm1zaW0oejIzbm9zYl91bmluZl91cF9nbykKZG90cGxvdCh6MjNub3NiX3VuaW5mX3VwX2dvKQplbWFwcGxvdCh6MjNub3NiX3VuaW5mX3VwX2dvX3BhaXIpCiMjc3NwbG90KHoyM25vc2JfdW5pbmZfdXBfZ29fcGFpcikKdHJlZXBsb3QoejIzbm9zYl91bmluZl91cF9nb19wYWlyKQp1cHNldHBsb3QoejIzbm9zYl91bmluZl91cF9nbykKY25ldHBsb3QoejIzbm9zYl91bmluZl91cF9nbykKYGBgCgojIyMgUmVwZWF0LCBidXQgdXNpbmcgYSBsZXNzIHN0cmljdCBzZXQgb2YgJ3NpZ25pZmljYW50IGdlbmVzJwoKSSBhbSBub3QgZW50aXJlbHkgY2VydGFpbiBpZiB0aGUgUmVhY3RvbWUgcmVzdWx0cyBPbGdhIHNob3dlZCBtZQppbmNsdWRlZCBib3RoIHVwIGFuZCBkb3duIGdlbmVzPyAgSSBhbSBnb2luZyB0byBhc3N1bWUgZm9yIHRoZSBtb21lbnQKdGhhdCBpdCB3YXMganVzdCB1cC9kb3duLCBidXQgaWYgdGhhdCBwcm92ZXMgaW50cmFjdGFibGUgSSB3aWxsIGdvCmJhY2sgdG8gdGhlIG1hbnVzY3JpcHQgYW5kIHJlYWQgbW9yZSBjYXJlZnVsbHkgKGUuZy4gSSBqdXN0IHJlbWVtYmVyZWQKd2hlcmUgdGhlIHBpY3R1cmUgY2FtZSBmcm9tISkKCiMjIyMgQWRkIGEgbGl0dGxlIHRvcGdvCgpJbiB0aGUgcHJvY2VzcyBvZiBleHBsb3JpbmcgdGhlIHZhcmlvdXMgcGFyYW1ldGVycyB1c2VkIHdpdGgKZ1Byb2ZpbGVyMiwgSSBmb3VuZCBteXNlbGYgdGhpbmtpbmcgdGhhdCBpdCB3b3VsZCBiZSBuaWNlIHRvIGhhdmUgc29tZQp0b3BnbyByZXN1bHRzIHRvIGNvbXBhcmUgYWdhaW5zdC4gIFRoZSBmb2xsb3dpbmcgYmxvY2sgaXMgdGhlIHJlc3VsdApvZiB0aGF0IHRob3VnaHQuCgpgYGB7cn0KdGVzdF9nZW5lc191cCA8LSBoc19tYWNyX2xlc3NzaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM25vc2JfdnNfdW5pbmYiXV0KdGVzdF9xdWVyeV91cCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHRlc3RfZ2VuZXNfdXAsIHRocmVzaG9sZCA9IDAuMSkKdGVzdF9xdWVyeV91cFtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KcGRmKGZpbGUgPSAiaW1hZ2VzL3Rlc3RfcXVlcnlfYmlvbG9naWNhbF9wcm9jZXNzX3oyM192c191bmluZl91cC5wZGYiLCBoZWlnaHQgPSAxMiwgd2lkdGggPSA5KQp0ZXN0X3F1ZXJ5X3VwW1sicHZhbHVlX3Bsb3RzIl1dW1siQlAiXV0KZGV2Lm9mZigpCmVucmljaHBsb3Q6OmRvdHBsb3QodGVzdF9xdWVyeV91cFtbIkJQX2VucmljaCJdXSkKdGVzdF9nZW5lc19kb3duIDwtIGhzX21hY3JfbGVzc3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJ6MjNub3NiX3ZzX3VuaW5mIl1dCnRlc3RfcXVlcnlfZG93biA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHRlc3RfZ2VuZXNfZG93bikKdGVzdF9xdWVyeV9kb3duW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQoKIyMgSSBrZWVwIGdldHRpbmcgYWxsIHNvcnRzIG9mIGFubm95aW5nIGJpb21hcnQgZXJyb3JzLgpoc19nbyA8LSB0cnkobG9hZF9iaW9tYXJ0X2dvKGFyY2hpdmUgPSBGQUxTRSwgb3ZlcndyaXRlID0gVFJVRSkpCmlmICgidHJ5LWVycm9yIiAlaW4lIGNsYXNzKGhzX2dvKSkgewogIGhzX2dvIDwtIGxvYWRfYmlvbWFydF9nbyhhcmNoaXZlID0gVFJVRSwgbW9udGggPSAiMDQiLCB5ZWFyID0gIjIwMjAiLCBvdmVyd3JpdGUgPSBUUlVFKQp9CnRlc3RfdG9wZ29fdXAgPC0gc2ltcGxlX3RvcGdvKHRlc3RfZ2VuZXNfdXAsIGdvX2RiID0gaHNfZ29bWyJnbyJdXSwgcGFyYWxsZWwgPSBGQUxTRSkKd3JpdHRlbl90b3BnbyA8LSB3cml0ZV90b3Bnb19kYXRhKAogIHRlc3RfdG9wZ29fdXAsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL29udG9sb2d5X3RvcGdvL3RvcGdvX3oyM191bmluZl9sZXNzX3N0cmljdC54bHN4IikpCmBgYAoKIyMjIEluZmVjdGVkIHdpdGggejIuMiBubyBBbnRpbW9uaWFsIHZzLiBVbmluZmVjdGVkCgpIZXJlIGlzIHdoZXJlIHRoaW5ncyB3aWxsIGdldCBtb3N0IHJlcGV0aXRpdmUuICBJbiBlYWNoIGluc3RhbmNlIEkgYW0KY3JlYXRpbmcgYSBjb3VwbGUgb2Ygdm9sY2FubyBwbG90cyBmb2xsb3dlZCBieSBwcmludGluZyBzb21lIG9mIHRoZQpnUHJvZmlsZXIyIHJlc3VsdHMgKHdoZW4gSSBnZXQgdGhlIGl0Y2gpLgoKVGhlIGZvbGxvd2luZyBzaG91bGQgYmUgYSBzbGlnaHRseSBpbXByb3ZlZCB2ZXJzaW9uIG9mIG91ciBleHRhbnQKZmlndXJlIDJCLgoKYGBge3J9CiMjIFRoZSBvcmlnaW5hbCBwbG90CmhzX21hY3JfdGFibGVbWyJwbG90cyJdXVtbInoyMm5vc2JfdnNfdW5pbmYiXV1bWyJkZXNlcV92b2xfcGxvdHMiXV0KCnoyMm5vc2JfdnNfdW5pbmZfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIybm9zYl92c191bmluZiJdXSwgInoyMm5vc2JfdnNfdW5pbmYiLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jc3ltYm9sIiwKICBjb2xvcl9sb3cgPSBwbG90X2NvbG9yc1tbInVuaW5mbm9uZSJdXSwgY29sb3JfaGlnaCA9IHBsb3RfY29sb3JzW1siaW5mejIyIl1dKQoKbGFiZWxlZCA8LSB6MjJub3NiX3ZzX3VuaW5mX3ZvbGNhbm9bWyJwbG90Il1dICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMiwgMjEpLCBicmVha3MgPSBjKC0yLCAwLCAyLCA0LCA2LCA4LCAxMCwgMjEsIDIyKSkgKwogIGdnYnJlYWs6OnNjYWxlX3hfYnJlYWsoYygxMSwgMjApLCBzY2FsZXMgPSAwLjIsIHNwYWNlID0gMC4wMikKcHAoZmlsZSA9ICJmaWd1cmVzL2ZpZzJiX2xhYmVsZWRfd2l0aF9icmVhay5zdmciKQpsYWJlbGVkCmRldi5vZmYoKQpsYWJlbGVkCgpwbG90bHk6OmdncGxvdGx5KHoyMm5vc2JfdnNfdW5pbmZfdm9sY2Fub1tbInBsb3QiXV0pCmBgYAoKQWRkIHNvbWUgcHZhbHVlIGJhcnBsb3RzIGZyb20gZ1Byb2ZpbGVyIGZvciB0aGlzIGNvbnRyYXN0LgoKYGBge3J9CmFsbF9ncFtbInoyMm5vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMiB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIybm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMiB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIybm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMiB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIybm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIldQIl1dCiMjIFdpa2lQYXRod2F5cywgenltb2RlbWUyLjIgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCgphbGxfZ3BbWyJ6MjJub3NiX3ZzX3VuaW5mX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMiB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjJub3NiX3ZzX3VuaW5mX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjIgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIybm9zYl92c191bmluZl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmBgYAoKIyMjIEluZmVjdGVkIHdpdGggejIuMyB0cmVhdGVkIHZzLiBVbmluZmVjdGVkIHRyZWF0ZWQKCkkgZG8gbm90IHRoaW5rIHRoaXMgcGxvdCBpcyB1c2VkIGF0IHRoaXMgdGltZS4KCmBgYHtyfQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlW1sicGxvdHMiXV1bWyJ6MjNzYl92c19zYiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQoKejIzc2JfdnNfdW5pbmZzYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNzYl92c19zYiJdXSwgInoyM3NiX3ZzX3NiIiwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIsCiAgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJpbmZzYnoyMyJdXSwgY29sb3JfaGlnaCA9IHBsb3RfY29sb3JzW1sidW5pbmZzYm5vbmUiXV0pCnoyM3NiX3ZzX3VuaW5mc2Jfdm9sY2Fub1tbInBsb3QiXV0KCnBsb3RseTo6Z2dwbG90bHkoejIzc2JfdnNfdW5pbmZzYl92b2xjYW5vW1sicGxvdCJdXSkKYGBgCgojIyMgSW5mZWN0ZWQgd2l0aCB6Mi4zIHVudHJlYXRlZCB2cy4gejIuMiB1bnRyZWF0ZWQKClRoaXMgaXMgZmlndXJlIDJDIGF0IHRoaXMgdGltZS4KCmBgYHtyfQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlW1sicGxvdHMiXV1bWyJ6MjNub3NiX3ZzX3oyMm5vc2IiXV1bWyJkZXNlcV92b2xfcGxvdHMiXV0KCnoyM25vc2JfdnNfejIybm9zYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNub3NiX3ZzX3oyMm5vc2IiXV0sICJ6MjNub3NiX3ZzX3oyMm5vc2IiLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jc3ltYm9sIiwKICBjb2xvcl9sb3cgPSBwbG90X2NvbG9yc1tbImluZnoyMyJdXSwgY29sb3JfaGlnaCA9IHBsb3RfY29sb3JzW1siaW5mejIyIl1dKQoKbGFiZWxlZCA8LSB6MjNub3NiX3ZzX3oyMm5vc2Jfdm9sY2Fub1tbInBsb3QiXV0gKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKC0xMCwgLTgsIC02LCAtNCwgLTIsIDAsIDIsIDQsIDYpKQoKcHAoZmlsZSA9ICJmaWd1cmVzL2ZpZzJjX2xhYmVsZWQuc3ZnIikKbGFiZWxlZApkZXYub2ZmKCkKbGFiZWxlZApgYGAKCiMjIyBJbmZlY3RlZCB3aXRoIHoyLjMgdHJlYXRlZCB2cy4gejIuMiB0cmVhdGVkCgpUaGlzIGlzIGN1cnJlbnRseSBmaWd1cmUgM0MuCgpGSVhNRTogVGhlIGF4aXMgbGFiZWwgaXNuJ3QgcXVpdGUgcmlnaHQgZm9yIHRoZSBnZ2JyZWFrLgoKYGBge3J9CiMjIFRoZSBvcmlnaW5hbCBwbG90CmhzX21hY3JfdGFibGVbWyJwbG90cyJdXVtbInoyM3NiX3ZzX3oyMnNiIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dCgp6MjNzYl92c196MjJzYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNzYl92c196MjJzYiJdXSwgInoyM3NiX3ZzX3oyMnNiIiwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIsCiAgY29sb3JfaGlnaCA9IHBsb3RfY29sb3JzW1siaW5mc2J6MjMiXV0sIGNvbG9yX2xvdyA9IHBsb3RfY29sb3JzW1siaW5mc2J6MjIiXV0pCgpsYWJlbGVkIDwtIHoyM3NiX3ZzX3oyMnNiX3ZvbGNhbm9bWyJwbG90Il1dICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygtMjMsIC02LCAtNCwgLTIsIDAsIDIsIDQsIDYpKSArCiAgZ2dicmVhazo6c2NhbGVfeF9icmVhayhjKC01LCAtMjIuNSksIHNjYWxlcyA9IDEwLCBzcGFjZSA9IDAuMDIpCnBwKGZpbGUgPSAiZmlndXJlcy9maWczY19sYWJlbGVkX2JyZWFrcy5zdmciKQpsYWJlbGVkCmRldi5vZmYoKQpsYWJlbGVkCmBgYAoKIyMjIEluZmVjdGVkIHdpdGggejIuMyBTQiB0cmVhdGVkIHZzLiB6Mi4zIHVudHJlYXRlZAoKSSB0aGluayB0aGlzIGlzIGN1cnJlbnRseSBmaWd1cmUgM0EuCgpGSVhNRTogVGhlIGF4aXMgbGFiZWwgZm9yIHRoZSBnZ2JyZWFrIGlzbid0IHF1aXRlIHJpZ2h0LgoKYGBge3J9CiMjIFRoZSBvcmlnaW5hbCBwbG90CmhzX21hY3JfdGFibGVbWyJwbG90cyJdXVtbInoyM3NiX3ZzX3oyM25vc2IiXV1bWyJkZXNlcV92b2xfcGxvdHMiXV0KCnoyM3NiX3ZzX3oyM25vc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfejIzbm9zYiJdXSwgInoyM3NiX3ZzX3oyM25vc2IiLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jc3ltYm9sIiwKICBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJpbmZzYnoyMyJdXSwgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJpbmZ6MjMiXV0pCgpsYWJlbGVkIDwtIHoyM3NiX3ZzX3oyM25vc2Jfdm9sY2Fub1tbInBsb3QiXV0gKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xOSwgNiksCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoLTIwLCAtMTgsIC0xNiwgLTE0LCAtMTIsIC0xMCwgLTYsIC00LCAtMiwgMCwgMiwgNCwgNikpICsKICBnZ2JyZWFrOjpzY2FsZV94X2JyZWFrKGMoLTE3LCAtOCksIHNjYWxlcyA9IDE3LCBzcGFjZSA9IDAuMDIpCnBwKGZpbGUgPSAiZmlndXJlcy9maWczYV9sYWJlbGVkX3dpdGhfYnJlYWsuc3ZnIikKbGFiZWxlZApkZXYub2ZmKCkKbGFiZWxlZApgYGAKCiMjIyBJbmZlY3RlZCB3aXRoIHoyLjMgU0IgdHJlYXRlZCB2cy4gejIuMyB1bnRyZWF0ZWQKCmBgYHtyfQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlW1sicGxvdHMiXV1bWyJ6MjJzYl92c196MjJub3NiIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dCgp6MjJzYl92c196MjJub3NiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2NvbmRpdGlvbl9kZSgKICBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyMnNiX3ZzX3oyMm5vc2IiXV0sICJ6MjJzYl92c196MjJub3NiIiwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIsCiAgY29sb3JfaGlnaCA9IHBsb3RfY29sb3JzW1siaW5mc2J6MjIiXV0sIGNvbG9yX2xvdyA9IHBsb3RfY29sb3JzW1siaW5mejIyIl1dKQoKbGFiZWxlZCA8LSB6MjJzYl92c196MjJub3NiX3ZvbGNhbm9bWyJwbG90Il1dICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygtNiwgLTQsIC0yLCAwLCAyLCA0LCA2KSkKCnBwKGZpbGUgPSAiZmlndXJlcy9maWczYl9sYWJlbGVkLnN2ZyIpCmxhYmVsZWQKZGV2Lm9mZigpCmxhYmVsZWQKYGBgCgojIyMgSW5mZWN0ZWQgd2l0aCB6Mi4zIFNCIHRyZWF0ZWQgdnMuIHVuaW5mZWN0ZWQgdHJlYXRlZAoKYGBge3J9CnhfbGltaXRzIDwtIGMoLTYsIDYpCiMjIFRoZSBvcmlnaW5hbCBwbG90CmhzX21hY3JfdGFibGVbWyJwbG90cyJdXVtbInoyM3NiX3ZzX3NiIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dCgp6MjNzYl92c19zYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNzYl92c19zYiJdXSwgInoyM3NiX3ZzX3NiIiwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIsIGludmVydCA9IFRSVUUsCiAgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJpbmZzYnoyMyJdXSwgY29sb3JfaGlnaCA9IHBsb3RfY29sb3JzW1sidW5pbmZzYm5vbmUiXV0pCnoyM3NiX3ZzX3NiX3ZvbGNhbm9bWyJwbG90Il1dCmBgYAoKIyMjIEluZmVjdGVkIHdpdGggejIuMiBTQiB0cmVhdGVkIHZzLiB1bmluZmVjdGVkIHRyZWF0ZWQKCmBgYHtyfQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlW1sicGxvdHMiXV1bWyJ6MjJzYl92c19zYiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQoKejIyc2JfdnNfc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIyc2JfdnNfc2IiXV0sICJ6MjJzYl92c19zYiIsCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiLCBpbnZlcnQgPSBUUlVFLAogIGNvbG9yX2xvdyA9IHBsb3RfY29sb3JzW1siaW5mc2J6MjIiXV0sIGNvbG9yX2hpZ2ggPSBwbG90X2NvbG9yc1tbInVuaW5mc2Jub25lIl1dKQp6MjJzYl92c19zYl92b2xjYW5vW1sicGxvdCJdXQpgYGAKCiMjIyBVbmluZmVjdGVkK1NiViB2cy4gVW5pbmZlY3RlZC1TYlYKClRoaXMgaXMgY3VycmVudGx5IGZpZ3VyZSAzRC4KCkZJWE1FOiBUaGlzIG5lZWRzIHRoZSBCT0xBMkIgZ2dicmVhay4KCmBgYHtyfQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlW1sicGxvdHMiXV1bWyJzYl92c191bmluZiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQoKc2JfdnNfdW5pbmZfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1sic2JfdnNfdW5pbmYiXV0sICJzYl92c191bmluZiIsCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiLAogIGNvbG9yX2hpZ2ggPSBwbG90X2NvbG9yc1tbInVuaW5mc2Jub25lIl1dLCBjb2xvcl9sb3cgPSBwbG90X2NvbG9yc1tbInVuaW5mbm9uZSJdXSkKCmxhYmVsZWQgPC0gc2JfdnNfdW5pbmZfdm9sY2Fub1tbInBsb3QiXV0gKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKC0yMywgLTYsIC00LCAtMiwgMCwgMiwgNCwgNikpICsKICBnZ2JyZWFrOjpzY2FsZV94X2JyZWFrKGMoLTUsIC0yMi41KSwgc2NhbGVzID0gMTAsIHNwYWNlID0gMC4wMikKcHAoZmlsZSA9ICJmaWd1cmVzL2ZpZzNkX2xhYmVsZWRfYnJlYWtzLnN2ZyIpCmxhYmVsZWQKZGV2Lm9mZigpCmxhYmVsZWQKYGBgCgojIyBEb3VibGUtY2hlY2sgdGhhdCBnZW5lIGNvdW50cyBtYXRjaCBteSBwZXJjZXB0aW9ucwoKQ2hlY2sgdGhhdCBteSBwZXJjZXB0aW9uIG9mIHRoZSBudW1iZXIgb2Ygc2lnbmlmaWNhbnQgdXAvZG93biBnZW5lcwptYXRjaGVzIHdoYXQgdGhlIHRhYmxlL3Zlbm4gc2F5cy4gIEluIHRoZSBmb2xsb3dpbmcgYmxvY2sgSSBhbQpwZXJmb3JtaW5nIHNvbWUgdmVubi91cHNldCBhbmFseXNlcyB0byBzZWUgaWYgdGhlIG51bWJlcnMgb2YgZ2VuZXMKbWF0Y2ggd2hhdCB3ZSBoYXZlIGluIHRoZSBjdXJyZW50IHZlcnNpb24gb2YgdGhlIG1hbnVzY3JpcHQgKHBsdXMgb3IKbWludXMgYSBnZW5lKSBhbmQgdGh1cyBpZiBteSBpbnRlcnByZXRhdGlvbiBvZiB0aGUgZmlndXJlL2xlZ2VuZCB0ZXh0Cm1hdGNoZXMgd2hhdCBJIHRoaW5rIGl0IG1lYW5zLgoKYGBge3J9CnNoYXJlZCA8LSBWZW5uZXJhYmxlOjpWZW5uKGxpc3QoCiAgImRydWciID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM3NiX3ZzX3VuaW5mIl1dKSwKICAibm9kcnVnIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjNub3NiX3ZzX3VuaW5mIl1dKSkpCnBwKGZpbGUgPSAiaW1hZ2VzL3oyM192c191bmluZl92ZW5uX3VwLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCiMjIEkgc2VlIDkxMCB6MjNzYi91bmluZiBhbmQgNjcwIG5vIHoyM25vc2IvdW5pbmYgZ2VuZXMgaW4gdGhlIHZlbm4gZGlhZ3JhbS4KbGVuZ3RoKHNoYXJlZEBJbnRlcnNlY3Rpb25TZXRzW1siMTAiXV0pICsgbGVuZ3RoKHNoYXJlZEBJbnRlcnNlY3Rpb25TZXRzW1siMTEiXV0pCmRpbShoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIzc2JfdnNfdW5pbmYiXV0pCgpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KAogICJkcnVnIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjJzYl92c191bmluZiJdXSksCiAgIm5vZHJ1ZyIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIybm9zYl92c191bmluZiJdXSkpKQpwcChmaWxlID0gImltYWdlcy96MjJfdnNfdW5pbmZfdmVubl91cC5wbmciKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKZGV2Lm9mZigpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQoKbGVuZ3RoKHNoYXJlZEBJbnRlcnNlY3Rpb25TZXRzW1siMTAiXV0pICsgbGVuZ3RoKHNoYXJlZEBJbnRlcnNlY3Rpb25TZXRzW1siMTEiXV0pCmRpbShoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIyc2JfdnNfdW5pbmYiXV0pCmBgYAoKKk5vdGUgdG8gc2VsZio6IFRoZXJlIGlzIGFuIGVycm9yIGluIG15IHZvbGNhbm8gcGxvdCBjb2RlIHdoaWNoIHRha2VzCmVmZmVjdCB3aGVuIHRoZSBudW1lcmF0b3IgYW5kIGRlbm9taW5hdG9yIG9mIHRoZSBhbGxfcGFpcndpc2UKY29udHJhc3RzIGFyZSBkaWZmZXJlbnQgdGhhbiB0aG9zZSBpbiBjb21iaW5lX2RlX3RhYmxlcy4gIEl0IGlzCnB1dHRpbmcgdGhlIHVwcy9kb3ducyBvbiB0aGUgY29ycmVjdCBzaWRlcyBvZiB0aGUgcGxvdCwgYnV0IGNhbGxpbmcKdGhlIGRvd24gZ2VuZXMgJ3VwJyBhbmQgdmljZS12ZXJzYS4gIFRoZSByZWFzb24gZm9yIHRoaXMgaXMgdGhhdCBJIGRpZAphIGNoZWNrIGZvciB0aGlzIGhhcHBlbmluZywgYnV0IHVzZWQgdGhlIHdyb25nIGFyZ3VtZW50IHRvIGhhbmRsZSBpdC4KCkEgbGlrZWx5IGJpdCBvZiB0ZXh0IGZvciB0aGVzZSB2b2xjYW5vIHBsb3RzOgoKVGhlIHNldCBvZiBnZW5lcyBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYmV0d2VlbiB0aGUgenltb2RlbWUgMi4zCmFuZCB1bmluZmVjdGVkIHNhbXBsZXMgd2l0aG91dCBkcnVnZSB0cmVhdG1lbnQgd2FzIHF1YW50aWZpZWQgd2l0aApERVNlcTIgYW5kIGluY2x1ZGVkIHN1cnJvZ2F0ZSBlc3RpbWF0ZXMgZnJvbSBTVkEuICBHaXZlbiB0aGUgY3JpdGVyaWEKb2Ygc2lnbmlmaWNhbmNlIG9mIGEgYWJzKGxvZ0ZDKSA+PSAxLjAgYW5kIGZhbHNlIGRpc2NvdmVyeSByYXRlCmFkanVzdGVkIHAtdmFsdWUgPD0gMC4wNSwgNjcwIGdlbmVzIHdlcmUgb2JzZXJ2ZWQgYXMgc2lnbmlmaWNhbnRseQppbmNyZWFzZWQgYmV0d2VlbiB0aGUgaW5mZWN0ZWQgYW5kIHVuaW5mZWN0ZWQgc2FtcGxlcyBhbmQgMzg2IHdlcmUKb2JzZXJ2ZWQgYXMgZGVjcmVhc2VkLiBUaGUgbW9zdCBpbmNyZWFzZWQgZ2VuZXMgZnJvbSB0aGUgdW5pbmZlY3RlZApzYW1wbGVzIGluY2x1ZGUgc29tZSB3aGljaCBhcmUgcG90ZW50aWFsbHkgaW5kaWNhdGl2ZSBvZiBhIHN0cm9uZwppbm5hdGUgaW1tdW5lIHJlc3BvbnNlIGFuZCB0aGUgaW5mbGFtbWF0b3J5IHJlc3BvbnNlLgoKSW4gY29udHJhc3QsIHdoZW4gdGhlIHNldCBvZiBnZW5lcyBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYmV0d2Vlbgp0aGUgenltb2RlbWUgMi4yIGFuZCB1bmluZmVjdGVkIHNhbXBsZXMgd2FzIHZpc3VhbGl6ZWQsIG9ubHkgNyBnZW5lcwp3ZXJlIG9ic2VydmVkIGFzIGRlY3JlYXNlZCBhbmQgNDM1IGluY3JlYXNlZC4gIFRoZSBpbmZsYW1tYXRvcnkKcmVzcG9uc2Ugd2FzIHNpZ25pZmljYW50bHkgbGVzcyBhcHBhcmVudCBpbiB0aGlzIHNldCwgYnV0IGluc3RlYWQKaW5jbHVkZWQgZ2VuZXMgcmVsYXRlZCB0byB0cmFuc3BvcnRlciBhY3Rpdml0eSBhbmQgb3hpZG9yZWR1Y3Rhc2VzLgoKIyMgRGlyZWN0IHp5bW9kZW1lIGNvbXBhcmlzb25zCgpBbiBvcnRob2dvbmFsIGNvbXBhcmlzb24gdG8gdGhhdCBwZXJmb3JtZWQgYWJvdmUgaXMgdG8gZGlyZWN0bHkKY29tcGFyZSB0aGUgenltb2RlbWUgMi4zIGFuZCAyLjIgc2FtcGxlcyB3aXRoIGFuZCB3aXRob3V0IGFudGltb25pYWwKdHJlYXRtZW50LgoKIyMjIFoyLjMgLyB6Mi4yIHdpdGhvdXQgZHJ1ZwoKYGBge3J9CnoyM25vc2JfdnNfejIybm9zYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19kZSgKICB0YWJsZSA9IGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIpCnBsb3RseTo6Z2dwbG90bHkoejIzbm9zYl92c196MjJub3NiX3ZvbGNhbm9bWyJwbG90Il1dKQoKejIzc2JfdnNfejIyc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fZGUoCiAgdGFibGUgPSBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyM3NiX3ZzX3oyMnNiIl1dLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIpCnBsb3RseTo6Z2dwbG90bHkoejIzc2JfdnNfejIyc2Jfdm9sY2Fub1tbInBsb3QiXV0pCmBgYAoKYGBge3J9CnoyM25vc2JfdnNfejIybm9zYl92b2xjYW5vW1sicGxvdCJdXSArCiAgeGxpbSgtMTAsIDEwKSArCiAgeWxpbSgwLCA2MCkKCnBwKGZpbGUgPSAiaW1hZ2VzL3oyM25vc2JfdnNfejIybm9zYl9yZWFjdG9tZV91cC5zdmciLAogICBpbWFnZSA9IGFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0sCiAgIGhlaWdodCA9IDEyLCB3aWR0aCA9IDkpCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJLRUdHIl1dCiMjIEtFR0csIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KIyMgV2lraVBhdGh3YXlzLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX3VwIl1dW1siaW50ZXJhY3RpdmVfcGxvdHMiXV1bWyJXUCJdXQoKcHAoZmlsZSA9ICJpbWFnZXMvejIzbm9zYl92c196MjJub3NiX3JlYWN0b21lX2Rvd24uc3ZnIiwKICAgaW1hZ2UgPSBhbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0sCiAgIGhlaWdodCA9IDEyLCB3aWR0aCA9IDkpCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYGBgCgojIyMgejIuMyAvIHoyLjIgd2l0aCBkcnVnCgpgYGB7cn0KejIzc2JfdnNfejIyc2Jfdm9sY2Fub1tbInBsb3QiXV0gKwogIHhsaW0oLTEwLCAxMCkgKwogIHlsaW0oMCwgNjApCgpwcCgKICBmaWxlID0gImltYWdlcy96MjNzYl92c196MjJzYl9yZWFjdG9tZV91cC5wbmciLAogIGltYWdlID0gYWxsX2dwW1siejIzc2JfdnNfejIyc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dLAogIGhlaWdodCA9IDEyLCB3aWR0aCA9IDkpCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siS0VHRyJdXQojIyBLRUdHLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIyc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIldQIl1dCiMjIFdpa2lQYXRod2F5cywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1siaW50ZXJhY3RpdmVfcGxvdHMiXV1bWyJXUCJdXQoKYWxsX2dwW1siejIzc2JfdnNfejIyc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzc2JfdnNfejIyc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgpgYGAKCiMjIyBWZW5uIHRvIHNlZSBzaGFyZWQvdW5pcXVlIGdlbmVzCgpPbmNlIGFnYWluIEkgd2lzaCB0byBwdWxsIG91dCB0aGUgc2lnbmlmaWNhbnQgZ2VuZXMgYW5kIHNlZSBob3cgbXkKbnVtYmVycyBtYXRjaCBhZ2FpbnN0IHRoZSB0ZXh0LgoKYGBge3J9CnNoYXJlZCA8LSBWZW5uZXJhYmxlOjpWZW5uKGxpc3QoCiAgImRydWciID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM3NiX3ZzX3oyMnNiIl1dKSwKICAibm9kcnVnIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjNub3NiX3ZzX3oyMm5vc2IiXV0pKSkKcHAoZmlsZSA9ICJpbWFnZXMvZHJ1Z19ub2RydWdfdmVubl91cC5wbmciKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKZGV2Lm9mZigpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQoKc2hhcmVkIDwtIFZlbm5lcmFibGU6OlZlbm4oCiAgbGlzdCgiZHJ1ZyIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJ6MjNzYl92c196MjJzYiJdXSksCiAgICAgICAibm9kcnVnIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXSkpKQpwcChmaWxlID0gImltYWdlcy9kcnVnX25vZHJ1Z192ZW5uX2Rvd24ucG5nIikKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmRldi5vZmYoKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKYGBgCgpBIHNsaWdodGx5IGRpZmZlcmVudCB3YXkgb2YgbG9va2luZyBhdCB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgdHdvCnp5bW9kZW1lIGluZmVjdGlvbnMgaXMgdG8gZGlyZWN0bHkgY29tcGFyZSB0aGUgaW5mZWN0ZWQgc2FtcGxlcyB3aXRoCmFuZCB3aXRob3V0IGRydWcuICBUaHVzLCB3aGVuIGEgdm9sY2FubyBwbG90IHNob3dpbmcgdGhlIGNvbXBhcmlzb24gb2YKdGhlIHp5bW9kZW1lIDIuMyB2cy4gMi4yIHNhbXBsZXMgd2FzIHBsb3R0ZWQsIDQ4NCBnZW5lcyB3ZXJlIG9ic2VydmVkCmFzIGluY3JlYXNlZCBhbmQgNDIyIGRlY3JlYXNlZDsgdGhlc2UgZ3JvdXBzIGluY2x1ZGUgbWFueSBvZiB0aGUgc2FtZQppbmZsYW1tYXRvcnkgKHVwKSBhbmQgbWVtYnJhbmUgKGRvd24pIGdlbmVzLgoKU2ltaWxhciBwYXR0ZXJucyB3ZXJlIG9ic2VydmVkIHdoZW4gdGhlIGFudGltb25pYWwgd2FzIGluY2x1ZGVkLgpUaHVzLCB3aGVuIGEgVmVubiBkaWFncmFtIG9mIHRoZSB0d28gc2V0cyBvZiBpbmNyZWFzZWQgZ2VuZXMgd2FzCnBsb3R0ZWQsIGEgc2lnbmlmaWNhbnQgbnVtYmVyIG9mIHRoZSBnZW5lcyB3YXMgb2JzZXJ2ZWQgYXMgaW5jcmVhc2VkCigzMTMpIGFuZCBkZWNyZWFzZWQgKDI0NCkgaW4gYm90aCB0aGUgdW50cmVhdGVkIGFuZCBhbnRpbW9uaWFsIHRyZWF0ZWQKc2FtcGxlcy4KCiMjIERydWcgZWZmZWN0cyBvbiBlYWNoIHp5bW9kZW1lIGluZmVjdGlvbgoKQW5vdGhlciBsaWtlbHkgcXVlc3Rpb24gaXMgdG8gZGlyZWN0bHkgY29tcGFyZSB0aGUgdHJlYXRlZCB2cwp1bnRyZWF0ZWQgc2FtcGxlcyBmb3IgZWFjaCB6eW1vZGVtZSBpbmZlY3Rpb24gaW4gb3JkZXIgdG8gdmlzdWFsaXplCnRoZSBlZmZlY3RzIG9mIGFudGltb25pYWwuCgojIyMgejIuMyB3aXRoIGFuZCB3aXRob3V0IGRydWcKCmBgYHtyfQp6MjNzYl92c196MjNub3NiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2RlKAogIHRhYmxlID0gaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNzYl92c196MjNub3NiIl1dLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIpCnBsb3RseTo6Z2dwbG90bHkoejIzc2JfdnNfejIzbm9zYl92b2xjYW5vW1sicGxvdCJdXSkKejIyc2JfdnNfejIybm9zYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19kZSgKICB0YWJsZSA9IGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIyc2JfdnNfejIybm9zYiJdXSwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBzaGFwZXNfYnlfc3RhdGUgPSBGQUxTRSwgY29sb3JfYnkgPSAiZmMiLCAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiKQpwbG90bHk6OmdncGxvdGx5KHoyMnNiX3ZzX3oyMm5vc2Jfdm9sY2Fub1tbInBsb3QiXV0pCmBgYAoKYGBge3J9CnoyM3NiX3ZzX3oyM25vc2Jfdm9sY2Fub1tbInBsb3QiXV0gKwogIHhsaW0oLTgsIDgpICsKICB5bGltKDAsIDIxMCkKCnBwKGZpbGUgPSAiaW1hZ2VzL3oyM3NiX3ZzX3oyM25vc2JfcmVhY3RvbWVfdXAucG5nIiwKICAgaW1hZ2UgPSBhbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXSwKICAgaGVpZ2h0ID0gMTIsIHdpZHRoID0gOSkKYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siS0VHRyJdXQojIyBLRUdHLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIldQIl1dCiMjIFdpa2lQYXRod2F5cywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyM25vc2JfdXAiXV1bWyJpbnRlcmFjdGl2ZV9wbG90cyJdXVtbIldQIl1dCgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmBgYAoKIyMjIHoyLjIgd2l0aCBhbmQgd2l0aG91dCBkcnVnCgpgYGB7cn0KejIyc2JfdnNfejIybm9zYl92b2xjYW5vW1sicGxvdCJdXSArCiAgeGxpbSgtOCwgOCkgKwogIHlsaW0oMCwgMjEwKQoKcHAoZmlsZSA9ICJpbWFnZXMvejIyc2JfdnNfejIybm9zYl9yZWFjdG9tZV91cC5wbmciLAogICBpbWFnZSA9IGFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dLAogICBoZWlnaHQgPSAxMiwgd2lkdGggPSA5KQphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJLRUdHIl1dCiMjIEtFR0csIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KIyMgV2lraVBhdGh3YXlzLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl91cCJdXVtbImludGVyYWN0aXZlX3Bsb3RzIl1dW1siV1AiXV0KCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYGBgCgojIyMgU2hhcmVkIGFuZCB1bmlxdWUgZ2VuZXMgYWZ0ZXIvYmVmb3JlIGRydWcKCmBgYHtyfQpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KAogICJ6MjMiID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM3NiX3ZzX3oyM25vc2IiXV0pLAogICJ6MjIiID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyMnNiX3ZzX3oyMm5vc2IiXV0pKSkKcHAoZmlsZSA9ICJpbWFnZXMvejIzX3oyMl9kcnVnX3Zlbm5fdXAucG5nIikKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmRldi5vZmYoKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKCnNoYXJlZCA8LSBWZW5uZXJhYmxlOjpWZW5uKGxpc3QoCiAgInoyMyIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJ6MjNzYl92c196MjNub3NiIl1dKSwKICAiejIyIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyMnNiX3ZzX3oyMm5vc2IiXV0pKSkKcHAoZmlsZSA9ICJpbWFnZXMvejIzX3oyMl9kcnVnX3Zlbm5fZG93bi5wbmciKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKZGV2Lm9mZigpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpgYGAKCk5vdGU6IEkgYW0gc2V0dGlnIHRoZSB4IGFuZCB5LWF4aXMgYm91bmRhcmllcyBieSBhbGxvd2luZyB0aGUgcGxvdHRlcgp0byBwaWNrIGl0cyBvd24gYXhpcyB0aGUgZmlyc3QgdGltZSwgd3JpdGluZyBkb3duIHRoZSByYW5nZXMgSQpvYnNlcnZlLCBhbmQgdGhlbiBzZXR0aW5nIHRoZW0gdG8gdGhlIGxhcmdlc3Qgb2YgdGhlIHBhaXIuICBJdCBpcwp0aGVyZWZvcmUgcG9zc2libGUgdGhhdCBJIG1pc3NlZCBvbmUgb3IgbW9yZSBnZW5lcyB3aGljaCBsaWVzIG91dHNpZGUKdGhhdCByYW5nZS4KClRoZSBwcmV2aW91cyBwbG90dGVkIGNvbnRyYXN0cyBzb3VnaHQgdG8gc2hvdyBjaGFuZ2VzIGJldHdlZW4gdGhlIHR3bwpzdHJhaW5zIHoyLjMgYW5kIHoyLjIuICBDb252ZXJzZWx5LCB0aGUgcHJldmlvdXMgdm9sY2FubyBwbG90cyBzZWVrIHRvCmRpcmVjdGx5IGNvbXBhcmUgZWFjaCBzdHJhaW4gYmVmb3JlL2FmdGVyIGRydWcgdHJlYXRtZW50LgoKIyBMUlQgb2YgdGhlIEh1bWFuIE1hY3JvcGhhZ2UKCkEgc2xpZ2h0bHkgZGlmZmVyZW50IHRhY2sgdG8gZXhhbWluZSB0aGUgZGF0YSBpcyB0byBwZXJmb3JtIGEKbGlrZWxpaG9vZCByYXRpbyB0ZXN0IGluIG9yZGVyIHRvIGxvb2sgZm9yIHRyZW5kcyB3aGljaCBhcmUgc2hhcmVkCmFtb25nIGdlbmVzIHdoZW4gZXhhbWluaW5nIGRpZmZlcmVudCBjb25kaXRpb25zIGluIHRoZSBkYXRhLgoKYGBge3J9CnRtcmMyX2xydF9zdHJhaW5fZHJ1ZyA8LSBkZXNlcV9scnQoaHNfbWFjciwgaW50ZXJhY3Rvcl9jb2x1bW4gPSAiZHJ1ZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJlc3RfY29sdW1uID0gIm1hY3JvcGhhZ2V6eW1vZGVtZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjdG9ycyA9IGMoImRydWciLCAibWFjcm9waGFnZXp5bW9kZW1lIikpCnRtcmMyX2xydF9zdHJhaW5fZHJ1Z1tbImNsdXN0ZXJfZGF0YSJdXVtbInBsb3QiXV0KYGBgCgojIFBhcmFzaXRlCgpMZXQgdXMgY29uc2lkZXIgZm9yIGEgbW9tZW50IGRpZmZlcmVuY2VzIGFtb25nIHRoZSBwYXJhc2l0ZQp0cmFuc2NyaXB0b21lcyBmb3IgdGhlIHNhbXBsZXMgd2hpY2ggd2VyZSBub3QgZHJ1ZyB0cmVhdGVkLgoKT25lIHRoaW5nIEkgZGlkIGluIHRoZSBpbml0aWFsIGltcGxlbWVudGF0aW9uIG9mIHRoaXMgZG9jdW1lbnQgd2FzIHRvCnJlcGVhdCB0aGUgdmFyaWFibGUgJ3VwX2dlbmVzJyBmb3IgZWFjaCBjb21wYXJpc29uOyBJIHRoaW5rIHRoaXMgdGltZQpJIHdpbGwgbWFrZSBhIGRpZmZlcmVudCB2YXJpYWJsZSBmb3IgZWFjaCBjb21wYXJpc29uIHNvIEkgY2FuIHBsYXkKd2l0aCB0aGVtIGEgbGl0dGxlIGZ1cnRoZXIuCgpgYGB7cn0KY29tcGFyaXNvbiA8LSAiejIzX3ZzX3oyMiIKbHBfbWFjcm9waGFnZV9kZSA8LSBhbGxfcGFpcndpc2UobHBfbWFjcm9waGFnZV9ub3NiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9zdnMgPSAic3Zhc2VxIiwgZmlsdGVyID0gVFJVRSkKdG1yYzJfcGFyYXNpdGVfa2VlcGVycyA8LSBsaXN0KAogICJ6MjNfdnNfejIyIiA9IGMoInoyMyIsICJ6MjIiKSkKbHBfbWFjcm9waGFnZV90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBscF9tYWNyb3BoYWdlX2RlLCBrZWVwZXJzID0gdG1yYzJfcGFyYXNpdGVfa2VlcGVycywKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL3BhcmFzaXRlX2luZmVjdGlvbl9kZS12e3Zlcn0ueGxzeCIpKQpscF9tYWNyb3BoYWdlX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGxwX21hY3JvcGhhZ2VfdGFibGUsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvcGFyYXNpdGVfc2lnLXZ7dmVyfS54bHN4IikpCgpscF9tYWNyb3BoYWdlX3RhYmxlW1sicGxvdHMiXV1bW2NvbXBhcmlzb25dXVtbImRlc2VxX3ZvbF9wbG90cyJdXQpscF9tYWNyb3BoYWdlX3RhYmxlW1sicGxvdHMiXV1bW2NvbXBhcmlzb25dXVtbImRlc2VxX21hX3Bsb3RzIl1dCgp1cF9nZW5lc196MjN6MjIgPC0gbHBfbWFjcm9waGFnZV9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbY29tcGFyaXNvbl1dCmRpbSh1cF9nZW5lc196MjN6MjIpCmRvd25fZ2VuZXNfejIzejIyIDwtIGxwX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbY29tcGFyaXNvbl1dCmRpbShkb3duX2dlbmVzX3oyM3oyMikKYGBgCgpgYGB7ciBwYXJhc2l0ZV92b2xjYW5vfQpscF96MjNzYl92c196MjJzYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19kZSgKICB0YWJsZSA9IGxwX21hY3JvcGhhZ2VfdGFibGVbWyJkYXRhIl1dW1siejIzX3ZzX3oyMiJdXSwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBzaGFwZXNfYnlfc3RhdGUgPSBGQUxTRSwgY29sb3JfYnkgPSAiZmMiLCAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiKQpwbG90bHk6OmdncGxvdGx5KGxwX3oyM3NiX3ZzX3oyMnNiX3ZvbGNhbm9bWyJwbG90Il1dKQpscF96MjNzYl92c196MjJzYl92b2xjYW5vW1sicGxvdCJdXQpgYGAKCiMjIE9udG9sb2d5IHNlYXJjaAoKQW4gaW1wb3J0YW50IG5vdGUsIEkgcmVjZW50bHkgYWRkZWQgYSBtaW5pbXVtIGNyb3NzcmVmZXJlbmNlIGFyZ3VtZW50CihkZWZhdWx0aW5nIHRvIDQwIGdlbmVzKSwgd2hpY2ggY2F1c2VzIGxvdHMgb2YgY29tcGFyaXNvbnMgdG8gZmFpbCBmb3IKcG9vcmx5IGFubm90YXRlZCBnZW5vbWVzIChsaWtlIHBhbmFtZW5zaXMuKSAgVGh1cywgSSBhbSByZWxheGluZyB0aGF0CmNvbnN0cmFpbnQgZm9yIHRoZXNlIHNlYXJjaGVzLgoKYGBge3J9CmxwX2xlbmd0aHMgPC0gYWxsX2xwX2Fubm90WywgYygiZ2lkIiwgImFubm90X2Nkc19sZW5ndGgiKV0KY29sbmFtZXMobHBfbGVuZ3RocykgIDwtIGMoIklEIiwgImxlbmd0aCIpCgp1cF9nb3NlcSA8LSBzaW1wbGVfZ29zZXEodXBfZ2VuZXNfejIzejIyLCBnb19kYiA9IGxwX2dvLAogICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoX2RiID0gbHBfbGVuZ3RocywgbWluX3hyZWYgPSAxNSkKIyMgVmlldyBjYXRlZ29yaWVzIG92ZXIgcmVwcmVzZW50ZWQgaW4gdGhlIDIuMyBzYW1wbGVzCnVwX2dvc2VxW1sicHZhbHVlX3Bsb3RzIl1dW1siYnBwX3Bsb3Rfb3ZlciJdXQpkb3duX2dvc2VxIDwtIHNpbXBsZV9nb3NlcShkb3duX2dlbmVzX3oyM3oyMiwgZ29fZGIgPSBscF9nbywKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoX2RiID0gbHBfbGVuZ3RocywgbWluX3hyZWYgPSAxNSkKIyMgVmlldyBjYXRlZ29yaWVzIG92ZXIgcmVwcmVzZW50ZWQgaW4gdGhlIDIuMiBzYW1wbGVzCmRvd25fZ29zZXFbWyJwdmFsdWVfcGxvdHMiXV1bWyJicHBfcGxvdF9vdmVyIl1dCgpjcmVhdGVkIDwtIGRpci5jcmVhdGUoZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9nb3NlcV9wYXJhc2l0ZSIpKQp3cml0dGVuX2dvc2VxIDwtIHdyaXRlX2dvc2VxX2RhdGEoCiAgdXBfZ29zZXEsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2dvc2VxX3BhcmFzaXRlL2xwX21hY3JvcGhhZ2VfaW5jcmVhc2VkX3oyLjNfZ29zZXEtdnt2ZXJ9Lnhsc3giKSkKd3JpdHRlbl9nb3NlcSA8LSB3cml0ZV9nb3NlcV9kYXRhKAogIGRvd25fZ29zZXEsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2dvc2VxX3BhcmFzaXRlL2xwX21hY3JvcGhhZ2VfaW5jcmVhc2VkX3oyLjJfZ29zZXEtdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIEdTVkEKCk5vdGU6IFRoZSBmb2xsb3dpbmcgYmxvY2sgYXNzdW1lcyBvbmUgaXMgYWJsZSB0byBkb3dubG9hZCBhIGZyZXNoIGNvcHkKb2YgbXNpZ0RCLCB3aGljaCBJIGFtIG5vdCBzdXJlIGlzIHBvc3NpYmxlIHdpdGhpbiB0aGUgY29uc3RyYWludHMgb2YgYQpjb250YWluZXIgKEkgbWVhbiBpdCBpcyB0cml2aWFsIHRvIGRvLCBidXQgSSBhbSBub3Qgc3VyZSBpZiBpdCBpcyBvawpkdWUgdG8gbGljZW5zaW5nKS4gIEhvd2V2ZXIsIEJyb2FkIHByb3ZpZGVzIGEgZGF0YSBwYWNrYWdlIG9mIGEgbXNpZ2RiCnJlbGVhc2UuICBBcyBhIHJlc3VsdCwgdGhlIGZvbGxvd2luZyBibG9jayB3aWxsIGJlIHJlcGVhdGVkIHVzaW5nIHRoYXQuCgpgYGB7ciwgZXZhbD1GQUxTRX0KaHNfaW5mZWN0ZWQgPC0gc3Vic2V0X3NlKGhzX21hY3JvcGhhZ2UsIHN1YnNldCA9ICJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmYnIikgJT4lCiAgc3Vic2V0X3NlKHN1YnNldCA9ICJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmZfc2InIikKaHNfZ3N2YV9jMiA8LSBzaW1wbGVfZ3N2YShoc19pbmZlY3RlZCkKaHNfZ3N2YV9jMl9tZXRhIDwtIGdldF9tc2lnZGJfbWV0YWRhdGEoaHNfZ3N2YV9jMiwgbXNpZ194bWwgPSAicmVmZXJlbmNlL21zaWdkYl92Ny4yLnhtbCIpCmhzX2dzdmFfYzJfc2lnIDwtIGdldF9zaWdfZ3N2YV9jYXRlZ29yaWVzKAogIGhzX2dzdmFfYzJfbWV0YSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZ3N2YS9oc19tYWNyb3BoYWdlX2dzdmFfYzJfc2lnLnhsc3giKSkKaHNfZ3N2YV9jMl9zaWdbWyJyYXdfcGxvdCJdXQoKaHNfZ3N2YV9jNyA8LSBzaW1wbGVfZ3N2YShoc19pbmZlY3RlZCwgc2lnbmF0dXJlX2NhdGVnb3J5ID0gImM3IikKaHNfZ3N2YV9jN19tZXRhIDwtIGdldF9tc2lnZGJfbWV0YWRhdGEoaHNfZ3N2YV9jNywgbXNpZ194bWwgPSAicmVmZXJlbmNlL21zaWdkYl92Ny4yLnhtbCIpCmhzX2dzdmFfYzdfc2lnIDwtIGdldF9zaWdfZ3N2YV9jYXRlZ29yaWVzKAogIGhzX2dzdmFfYzcsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2dzdmEvaHNfbWFjcm9waGFnZV9nc3ZhX2M3X3NpZy54bHN4IikpCmhzX2dzdmFfYzdfc2lnW1sicmF3X3Bsb3QiXV0KYGBgCgojIyBSZXBlYXQgdXNpbmcgdGhlIEdTVkFkYXRhIHBhY2thZ2UuCgpgYGB7cn0KaHNfaW5mZWN0ZWQgPC0gc3Vic2V0X3NlKGhzX21hY3JvcGhhZ2UsIHN1YnNldCA9ICJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmYnIikgJT4lCiAgc3Vic2V0X3NlKHN1YnNldCA9ICJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmZfc2InIikKaHNfZ3N2YV9jMiA8LSBzaW1wbGVfZ3N2YShoc19pbmZlY3RlZCkKIyNoc19nc3ZhX2MyX21ldGEgPC0gZ2V0X21zaWdkYl9tZXRhZGF0YShoc19nc3ZhX2MyLCBtc2lnX3htbD0icmVmZXJlbmNlL21zaWdkYl92Ny4yLnhtbCIpCmhzX2dzdmFfYzJfc2lnIDwtIGdldF9zaWdfZ3N2YV9jYXRlZ29yaWVzKAogIGhzX2dzdmFfYzIsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2dzdmEvaHNfbWFjcm9waGFnZV9nc3ZhX2MyX3NpZy54bHN4IikpCmhzX2dzdmFfYzJfc2lnW1sicmF3X3Bsb3QiXV0KCmhzX2dzdmFfYzcgPC0gc2ltcGxlX2dzdmEoaHNfaW5mZWN0ZWQsIHNpZ25hdHVyZV9jYXRlZ29yeSA9ICJjNyIpCiMjaHNfZ3N2YV9jN19tZXRhIDwtIGdldF9tc2lnZGJfbWV0YWRhdGEoaHNfZ3N2YV9jNywgbXNpZ194bWw9InJlZmVyZW5jZS9tc2lnZGJfdjcuMi54bWwiKQpoc19nc3ZhX2M3X3NpZyA8LSBnZXRfc2lnX2dzdmFfY2F0ZWdvcmllcygKICBoc19nc3ZhX2M3LAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9nc3ZhL2hzX21hY3JvcGhhZ2VfZ3N2YV9jN19zaWcueGxzeCIpKQpoc19nc3ZhX2M3X3NpZ1tbInJhd19wbG90Il1dCmBgYAoKIyBUcnkgb3V0IGEgbmV3IHRvb2wKClR3byByZWFzb25zOiBOYWppYiBsb3ZlcyBoaW0gc29tZSBQQ0EsIHRoaXMgdXNlcyB3aWtpcGF0aHdheXMsIHdoaWNoIGlzIHNvbWV0aGluZyBJIHRoaW5rIGlzIG5lYXQuCgpPaywgSSBzcGVudCBzb21lIHRpbWUgbG9va2luZyB0aHJvdWdoIHRoZSBjb2RlIGFuZCBJIGhhdmUgc29tZQpwcm9ibGVtcyB3aXRoIHNvbWUgb2YgdGhlIGRlc2lnbiBkZWNpc2lvbnMuCgpNb3N0IGltcG9ydGFudGx5LCBpdCByZXF1aXJlcyBhIGRhdGEuZnJhbWUoKSB3aGljaCBoYXMgdGhlIGZvbGxvd2luZyBmb3JtYXQ6CgoxLiAgTm8gcm93bmFtZXMsIGluc3RlYWQgY29sdW1uICMxIGlzIHRoZSBzYW1wbGUgSUQuCjIuICBDb2x1bW5zIDItbSBhcmUgdGhlIGNhdGVnb3JpY2FsL3N1cnZpdmFsL2V0YyBtZXRyaWNzLgozLiAgQ29sdW1ucyBtLW4gYXJlIDEgZ2VuZS1wZXItY29sdW1uIHdpdGggbG9nMiB2YWx1ZXMuCgpCdXQgd2hlbiBJIHRoaW5rIGFib3V0IGl0IEkgdGhpbmsgSSBnZXQgdGhlIGlkZWEsIHRoZXkgd2FudCB0byBiZSBhYmxlIHRvIGRvIG1vZGVsbGluZyBzdHVmZgptb3JlIGVhc2lseSB3aXRoIHJlc3BvbnNlIGZhY3RvcnMuCgpgYGB7cn0KbGlicmFyeShwYXRod2F5UENBKQpsaWJyYXJ5KHJXaWtpUGF0aHdheXMpCgpkb3dubG9hZGVkIDwtIGRvd25sb2FkUGF0aHdheUFyY2hpdmUob3JnYW5pc20gPSAiSG9tbyBzYXBpZW5zIiwgZm9ybWF0ID0gImdtdCIpCmRhdGFfcGF0aCA8LSBzeXN0ZW0uZmlsZSgiZXh0ZGF0YSIsIHBhY2thZ2UgPSAicGF0aHdheVBDQSIpCndpa2lwYXRod2F5cyA8LSByZWFkX2dtdChwYXN0ZTAoZGF0YV9wYXRoLCAiL3dpa2lwYXRod2F5c19odW1hbl9zeW1ib2wuZ210IiksCiAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiA9IFRSVUUpCgpleHB0IDwtIHN1YnNldF9zZShoc19tYWNyb3BoYWdlLCBzdWJzZXQgPSAibWFjcm9waGFnZXRyZWF0bWVudCE9J3VuaW5mJyIpICU+JQogIHN1YnNldF9zZShzdWJzZXQgPSAibWFjcm9waGFnZXRyZWF0bWVudCE9J3VuaW5mX3NiJyIpCmV4cHQgPC0gc2V0X3NlX2NvbmRpdGlvbnMoZXhwdCwgZmFjdCA9ICJtYWNyb3BoYWdlenltb2RlbWUiKQpzeW1ib2xfY29sdW1uIDwtICJoZ25jX3N5bWJvbCIKc3ltYm9sX3ZlY3RvciA8LSBmRGF0YShleHB0KVtbc3ltYm9sX2NvbHVtbl1dCm5hbWVzKHN5bWJvbF92ZWN0b3IpIDwtIHJvd25hbWVzKGZEYXRhKGV4cHQpKQpzeW1ib2xfZGYgPC0gYXMuZGF0YS5mcmFtZShzeW1ib2xfdmVjdG9yKQoKYXNzYXlfZGYgPC0gbWVyZ2Uoc3ltYm9sX2RmLCBhcy5kYXRhLmZyYW1lKGV4cHJzKGV4cHQpKSwgYnkgPSAicm93Lm5hbWVzIikKYXNzYXlfZGZbWyJSb3cubmFtZXMiXV0gPC0gTlVMTApyb3duYW1lcyhhc3NheV9kZikgPC0gbWFrZS5uYW1lcyhhc3NheV9kZltbInN5bWJvbF92ZWN0b3IiXV0sIHVuaXF1ZSA9IFRSVUUpCmFzc2F5X2RmW1sic3ltYm9sX3ZlY3RvciJdXSA8LSBOVUxMCmFzc2F5X2RmIDwtIGFzLmRhdGEuZnJhbWUodChhc3NheV9kZikpCmFzc2F5X2RmW1siU2FtcGxlSUQiXV0gPC0gcm93bmFtZXMoYXNzYXlfZGYpCmFzc2F5X2RmIDwtIGRwbHlyOjpzZWxlY3QoYXNzYXlfZGYsICJTYW1wbGVJRCIsIGV2ZXJ5dGhpbmcoKSkKCmZhY3Rvcl9kZiA8LSBhcy5kYXRhLmZyYW1lKHBEYXRhKGV4cHQpKQpmYWN0b3JfZGZbWyJTYW1wbGVJRCJdXSA8LSByb3duYW1lcyhmYWN0b3JfZGYpCmZhY3Rvcl9kZiA8LSBkcGx5cjo6c2VsZWN0KGZhY3Rvcl9kZiwgIlNhbXBsZUlEIiwgZXZlcnl0aGluZygpKQpmYWN0b3JfZGYgPC0gZmFjdG9yX2RmWywgYygiU2FtcGxlSUQiLCBmYWN0b3JzKV0KCnR0IDwtIENyZWF0ZU9taWNzKAogIGFzc2F5RGF0YV9kZiA9IGFzc2F5X2RmLAogIHBhdGh3YXlDb2xsZWN0aW9uX2xzID0gd2lraXBhdGh3YXlzLAogIHJlc3BvbnNlID0gZmFjdG9yX2RmLAogIHJlc3BUeXBlID0gImNhdGVnb3JpY2FsIiwKICBtaW5QYXRoU2l6ZSA9IDUpCgpzdXBlciA8LSBBRVNQQ0FfcFZhbHMoCiAgb2JqZWN0ID0gdHQsCiAgbnVtUENzID0gMiwKICBwYXJhbGxlbCA9IEZBTFNFLAogIG51bUNvcmVzID0gOCwKICBudW1SZXBzID0gMiwKICBhZGp1c3RtZW50ID0gIkJIIikKYGBgCgojIEV2YWx1YXRpbmcgYSBsb2cyRkMgYmFycGxvdAoKRmlndXJlIDJFIGlzIG5vdyBjb21wcmlzZWQgb2YgYSBwbG90IHdoaWNoIHNob3dzIGxvZzJGQyB2YWx1ZXMgd2l0aAplcnJvciBiYXJzIGZvciBzZWxlY3RlZCBnZW5lcyBhbmQgc2Vla3MgdG8gc2hvdyBkaWZmZXJlbmNlcyBiZXR3ZWVuCjIuMy91bmluZmVjdGVkIGFuZCAyLjIvdW5pbmZlY3RlZC4KCkhlcmUgaXMgdGhlIHRhYmxlIE9sZ2EgdXNlZCB0byBnZW5lcmF0ZSBpdDoKCkkgd2VudCBsb29raW5nIGluIHRoZSB4bHN4IGZpbGVzIHByb2R1Y2VkIGluIDIwMjQwNSBhbmQgZm91bmQgdGhhdAp0aGVzZSBhcmUgdGhlIGxvZzJGQyB2YWx1ZXMgYW5kIHN0YW5kYXJkIGVycm9ycyBwcm9kdWNlZCBieSBERVNlcTIuCgpJdCBzaG91bGQgYmUgbm90ZWQgdGhhdCBpbiBteSBtb3N0IHJlY2VudCB2ZXJzaW9uIG9mIHRoZXNlIGFuYWx5c2VzLAp0aGVzZSBudW1iZXJzIGRpZCBzaGlmdCBzbGlnaHRseS4gIEkgYW0gbG9va2luZyBpbnRvIHRoYXQgbm93LgoKKiBEYXRhIHdpdG91dCBkcnVnCgoqKiAyLjMgdnMgVW5pbmZlY3RlZCBNw5ggICAgICAgICAgICAyLjIgdnMgVW5pbmZlY3RlZCBNw5gKCnwgR2VuZSB8IE1lYW4gICB8IFNFTSAgICAgIHwgbiB8IE1lYW4gIHwgU0VNICAgICB8biB8Ci0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KfElGSTI3IHwgIDcuMjI0IHwgIDAuNTY2MiAgfDYgIHwgMi43MDIgfCAgMC41NjY5IHwgNnwKfFJTQUQyIHwgIDYuMjkgIHwgIDAuNzMxMiAgfDYgIHwgMS42MjMgfCAgMC43MzAzIHwgNnwKfENDTDggIHwgIDYuMjI1IHwgIDAuOTI4ICAgfDYgIHwgLTAuMzE0fCAgMC45NDEgIHwgNnwKfElGSTQ0THwgIDUuODk1IHwgIDAuNjEyICAgfDYgIHwgMi4wNiAgfCAgMC42MTEgIHwgNnwKfE9BU0wgIHwgIDQuNzI2IHwgIDAuNDk3NCAgfDYgIHwgMS4zOTIgfCAgMC40OTczIHwgNnwKfFVTUDE4IHwgIDMuNjQ0IHwgIDAuNDgzICAgfDYgIHwgMC45OTkgfCAgMC40ODI2IHwgNnwKfElETzEgIHwgIDcuMTQ1IHwgIDEuMTA3ICAgfDYgIHwgMS4yNTcgfCAgMS4xNDEgIHwgNnwKfElETzIgIHwgIDMuOTM1IHwgIDEuMyAgICAgfDYgIHwgMi41NTcgfCAgMS4zNDEgIHwgNnwKfEtZTlUgIHwgIDEuMDcgIHwgIDAuMjE4NiAgfDYgIHwgMC4wMjA3fCAgMC4yMTg0IHwgNnwKfEFIUiAgIHwgMC45MzgyIHwgMC4yMjM2ICAgfDYgIHwgMC41MDMyfCAgMC4yMjM5IHwgNnwKfElMNEkxIHwgIDIuNTkzIHwgIDAuNDYyMyAgfDYgIHwgMC4wMzkgfCAgMC40NjE4IHwgNnwKfFNPRDIgIHwgIDIuNzYgIHwgIDAuMzQ5ICAgfDYgIHwgMC40MjQxfCAgMC4zNTI4IHwgNnwKfE5PVENIMXwgIDAuNzU3MnwgIDAuMjc1ICAgfDYgIHwgMS40OTUgfCAgMC4yNzQ0IHwgNnwKfERMTDEgIHwgIDAuODI2OHwgIDAuNTI4NSAgfDYgIHwgMy40NTUgfCAgMC41MjI4IHwgNnwKfERMTDQgIHwgIDEuMTE2IHwgIDAuNzM3ICAgfDYgIHwgNC4yNDMgfCAgMC43MSAgIHwgNnwKfEhFUzEgIHwgLTAuMDE4M3wgMC44NTk5ICAgfDYgIHwgNi41MzYgfCAgMC43OTczIHwgNnwKfEhFWTEgIHwgIDAuNTUzM3wgMC41Nzg5ICAgfDYgIHwgNC4xODEgfCAgMC42MjczIHwgNnwKCk9rLCBJIHRoaW5rIEkgZm91bmQgYSBwcm9ibGVtOiBUaGUgTk9UQ0gxIHZhbHVlIGlzIGFjdHVhbGx5IHRoZQphZGp1c3RlZCBwLXZhbHVlLgoKKiBUcmFuc3BvcnRlcnMgd2l0aG91dCBkcnVnCgoqKiAyLjMgdnMgVW5pbmZlY3RlZCBNw5ggICAgICAgICAgICAyLjIgdnMgVW5pbmZlY3RlZCBNw5gKCnwgR2VuZSB8IE1lYW4gICAgfCAgIFNFTSAgfCBufCAgTWVhbiAgIHwgU0VNICAgfCBufAotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCnxBQkNCMSB8ICAtMi4zNTQgfCAwLjQ0MiAgfCA2fCAgIC0wLjQwNnwgIDAuNDMxfCA2fAp8QUJDRzQgfCAgLTMuNzE1IHwgMC42NDggIHwgNnwgICAtMC42NTN8ICAwLjYzMHwgNnwKfEFCQ0I1IHwgIC0xLjE5MiB8IDAuMzgwICB8IDZ8ICAgMS4zNTEgfCAgMC4zNjN8IDZ8CnxBQkNBOSB8ICAxLjg4MCAgfCAwLjY0OCAgfCA2fCAgIDMuNDQ0IHwgIDAuNjM3fCA2fAp8QUJDQzIgfCAgMC40NTQgIHwgMC4zMjEgIHwgNnwgICAxLjgxOCB8ICAwLjMxNHwgNnwKfEFRUDIgIHwgIC0xLjE5MSB8IDAuNTI5ICB8IDZ8ICAgMC43NDUgfCAgMC41MTR8IDZ8CnxBUVAzICB8ICAtMC45NDAgfCAwLjQwMiAgfCA2fCAgIDAuNDMxIHwgIDAuMzk1fCA2fAoKKiBUcmFuc3BvcnRlcnMgd2l0aCBkcnVnCgoqKiAyLjMgdnMgVW5pbmZlY3RlZCBNw5ggICAgICAgICAgICAyLjIgdnMgVW5pbmZlY3RlZCBNw5gKCnxHZW5lICB8IE1lYW4gICB8ICAgIFNFTSB8IG58IE1lYW4gIHwgIFNFTSAgIHwgbiB8Ci0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQp8QUJDQjEgfCAgLTAuNjk3fCAgMC4zNDkgfCA2fCAtMS4yNTV8ICAwLjMzNyB8ICA2fAp8QUJDRzQgfCAgMS4yMzEgfCAgMC41MDMgfCA2fCAwLjU0NyB8ICAwLjQ4NCB8ICA2fAp8QVFQMiAgfCAgMC44MTYgfCAgMC4zOTkgfCA2fCAwLjA0MyB8ICAwLjM4NyB8ICA2fAp8QVFQMyAgfCAgLTEuMjg2fCAgMC4zMjAgfCA2fCAtMS42MTN8ICAwLjMwOSB8ICA2fAp8QVFQOCAgfCAgMC42MzQgfCAgMC4zNzAgfCA2fCAwLjk0MyB8ICAwLjM2NSB8ICA2fAoKTGV0IHVzIG5vdyBzZWUgaWYgSSBjYW4gcmVjYXBpdHVsYXRlIHRoZSBwbG90Li4uCgpgYGB7cn0Kbm9kcnVnX2NvbnRyYXN0cyA8LSBjKCJ6MjNub3NiX3ZzX3VuaW5mIiwgInoyMm5vc2JfdnNfdW5pbmYiKQpnZW5lc19ub19kcnVnIDwtIGMoIklGSTI3IiwgIlJTQUQyIiwgIkNDTDgiLCAiSUZJNDRMIiwgIk9BU0wiLCAiVVNQMTgiLCAiSURPMSIsICJJRE8yIiwgIktZTlUiLCAiQUhSIiwgIklMNEkxIiwgIlNPRDIiLCAiTk9UQ0gxIiwgIkRMTDEiLCAiRExMNCIsICJIRVMxIiwgIkhFWTEiKQp0cmFuc3BvcnRlcnNfbm9fZHJ1ZyA8LSBjKCJBQkNCMSIsICJBQkNHNCIsICJBQkNCNSIsICJBQkNBOSIsICJBQkNDMiIsICJBUVAyIiwgIkFRUDMiKQpkcnVnX2NvbnRyYXN0cyA8LSBjKCJ6MjNzYl92c19zYiIsICJ6MjJzYl92c19zYiIpCnRyYW5zcG9ydGVyc19kcnVnIDwtIGMoIkFCQ0IxIiwgIkFCQ0c0IiwgIkFRUDIiLCAiQVFQMyIsICJBUVA4IikKYGBgCgpUaGVzZSB2YWx1ZXMgY2FtZSBvdXQgb2YgdGhlIGRhdGEgc3RydWN0dXJlIGNhbGxlZCAnaHNfbWFjcl90YWJsZScKCmBgYHtyfQp6MjNub3NiX3VuaW5mX3ZhbHVlcyA8LSBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyM25vc2JfdnNfdW5pbmYiXV0KZ2VuZV9pZHggPC0gejIzbm9zYl91bmluZl92YWx1ZXNbWyJoZ25jX3N5bWJvbCJdXSAlaW4lIGdlbmVzX25vX2RydWcKbm9kcnVnX3Jvd3MgPC0gIHoyM25vc2JfdW5pbmZfdmFsdWVzW2dlbmVfaWR4LCBdCnJvd25hbWVzKG5vZHJ1Z19yb3dzKSA8LSBub2RydWdfcm93c1tbImhnbmNfc3ltYm9sIl1dCnoyM19ub2RydWdfdmFsdWVzIDwtIG5vZHJ1Z19yb3dzWywgYygiZGVzZXFfbG9nZmMiLCAiZGVzZXFfbGZjc2UiKV0KejIzX25vZHJ1Z192YWx1ZXMKCnoyMm5vc2JfdW5pbmZfdmFsdWVzIDwtIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIybm9zYl92c191bmluZiJdXQpnZW5lX2lkeCA8LSB6MjJub3NiX3VuaW5mX3ZhbHVlc1tbImhnbmNfc3ltYm9sIl1dICVpbiUgZ2VuZXNfbm9fZHJ1Zwpub2RydWdfcm93cyA8LSAgejIybm9zYl91bmluZl92YWx1ZXNbZ2VuZV9pZHgsIF0Kcm93bmFtZXMobm9kcnVnX3Jvd3MpIDwtIG5vZHJ1Z19yb3dzW1siaGduY19zeW1ib2wiXV0KejIyX25vZHJ1Z192YWx1ZXMgPC0gbm9kcnVnX3Jvd3NbLCBjKCJkZXNlcV9sb2dmYyIsICJkZXNlcV9sZmNzZSIpXQp6MjJfbm9kcnVnX3ZhbHVlcwoKejIzX25vZHJ1Z192YWx1ZXNbWyJzdGF0ZSJdXSA8LSAiejIzX3ZzX3VuaW5mZWN0ZWQiCnoyMl9ub2RydWdfdmFsdWVzW1sic3RhdGUiXV0gPC0gInoyMl92c191bmluZmVjdGVkIgpwbG90X2RmIDwtIHJiaW5kLmRhdGEuZnJhbWUoYXMuZGF0YS5mcmFtZSh6MjNfbm9kcnVnX3ZhbHVlcyksIGFzLmRhdGEuZnJhbWUoejIyX25vZHJ1Z192YWx1ZXMpKQpwbG90X2RmW1siZ2VuZSJdXSA8LSByb3duYW1lcyhwbG90X2RmKQoKIyMgSSBqdXN0IHJlYWxpemVkIHRoYXQgdGhpcyBpcyBhY3R1YWxseSBqdXN0IGEgY29tcGFyaXNvbiBvZiB6MjMvejIyCiMjIHdlIHNob3VsZCBqdXN0IHRha2UgdGhlIGFkanVzdGVkIHAtdmFsdWVzIGZyb20gdGhhdCBjb250cmFzdCBmb3IgdGhpcy4KejIzX3oyMl9jb21wYXJpc29uIDwtIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dCm5vZHJ1Z19yb3dzIDwtIHoyM196MjJfY29tcGFyaXNvbltnZW5lX2lkeCwgXQpub2RydWdfcHZhbHVlcyA8LSBub2RydWdfcm93c1ssIGMoImRlc2VxX3AiLCAiZGVzZXFfYWRqcCIpXQpyb3duYW1lcyhub2RydWdfcHZhbHVlcykgPC0gbm9kcnVnX3Jvd3NbWyJoZ25jX3N5bWJvbCJdXQpub2RydWdfcHZhbHVlcwoKZ2dwbG90KHBsb3RfZGYsIGFlcyh4ID0gZ2VuZSwgeSA9IGRlc2VxX2xvZ2ZjLCBmaWxsID0gc3RhdGUpKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgpLCBzdGF0ID0gImlkZW50aXR5IikgKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBkZXNlcV9sb2dmYyAtIGRlc2VxX2xmY3NlLAogICAgICAgICAgICAgICAgICAgIHltYXggPSBkZXNlcV9sb2dmYyArIGRlc2VxX2xmY3NlKSwKICAgICAgICAgICAgICAgIHdpZHRoID0gMC4yLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuOSkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMUI5RTc3IiwgIiM3NTcwQjMiKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41KSkKCmNvbXBhcmlzb24gPC0gYygiejIzX3ZzX3VuaW5mZWN0ZWQiLCAiejIyX3ZzX3VuaW5mZWN0ZWQiKQpjb21wYXJpc29ucyA8LSByZXAobGlzdChjb21wYXJpc29uKSwgbnJvdyhwbG90X2RmKSAvIDIpCmdncGxvdChwbG90X2RmLCBhZXMoeCA9IGdlbmUsIHkgPSBkZXNlcV9sb2dmYywgZmlsbCA9IHN0YXRlLCBhZGQgPSBkZXNlcV9sZmNzZSwgZmFjZXQuYnkgPSAic3RhdGUiKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoKSwgc3RhdCA9ICJpZGVudGl0eSIpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gZGVzZXFfbG9nZmMgLSBkZXNlcV9sZmNzZSwKICAgICAgICAgICAgICAgICAgICB5bWF4ID0gZGVzZXFfbG9nZmMgKyBkZXNlcV9sZmNzZSksCiAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpKSArCiAgc3RhdF9jb21wYXJlX21lYW5zKCkgKwogIHN0YXRfY29tcGFyZV9tZWFucyhjb21wYXJpc29ucyA9IGNvbXBhcmlzb25zLCBsYWJlbC55ID0gcm93bmFtZXMoejIzX25vZHJ1Z192YWx1ZXMpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzFCOUU3NyIsICIjNzU3MEIzIikpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSkpCgpgYGAKCkV4Y2VsbGVudCwgdGhlIHZhbHVlcyBub3cgbWF0Y2ggdXAuICBOb3cgSSB1c3QgbmVlZCB0byBmaWd1cmUgb3V0IHdoeQp0aGUgc3R1cGlkIGhnbmMgSURzIGdvdCBsb3N0Li4uICBJIGNhbiBzZWUgdGhlbSBpbiB0aGUgaHNfYW5ub3QgZGF0YQpzdHJ1Y3R1cmUsIHNvIEkgbXVzdCBoYXZlIG1lc3NlZCB1cCB3aGVuIEkgcmVnZW5lcmVkIHRoZSBpbnB1dCB0byB0aGUKZGUuICBPaywgSSBnb3QgdG8gdGhlIHNhbWUgc3RhcnRpbmcgcG9pbnQgbm93IHdpdGggaWRlbnRpY2FsIHZhbHVlcy4KQXMgc29vbiBhcyBJIGRpZCB0aGF0LCBJIGxvb2tlZCBhdCB0aGUgcmVzdWx0aW5nIHBsb3QgYW5kIHJlYWxpemVkCnRoYXQgd2UgYXJlIGFjdHVhbGx5IGp1c3QgY29tcGFyaW5nIHoyMyAvIHoyMi4KCkhlcmUgaXMgd2h5OiB0aGUgcGxvdCBhcyBpdCBzdGFuZHMgaXMgYSBjb21wYXJpc29uIG9mIHRoZSBsb2cyRkMKdmFsdWVzIG9mIHRoZSBmb2xsb3dpbmcgdHdvIGNvbnRyYXN0czogejIzL3VuaW5mZWN0ZWQgYW5kCnoyMi91bmluZmVjdGVkOyBzdGF0ZWQgZGlmZmVyZW50bHksIHRoaXMgaXMgKHoyMy91bmluZikvKHoyMi91bmluZikKd2hpY2ggb2YgY291cnNlIGNhbmNlbHMgb3V0IHRvIGp1c3QgejIzL3oyMi4KClRoZXJlZm9yZSBpdCBpcyBtdWNoIG1vcmUgcGFyc2ltb25pb3VzIHRvIGp1c3QgdXNlIHRoZSB2YWx1ZXMgZnJvbQp6MjMvejIyLiAgSSBzd2VhciBJIGhhdmUgZ29uZSB0aHJvdWdoIHRoaXMgZXhhY3QgZXhlcmNpc2Ugb24gc28gc28KbWFueSBvY2Nhc2lvbnMgaW4gdGhlIHBhc3QgaXQgaXMgdGVycmlibGUuCgpgYGB7cn0Kd2FudGVkX2dlbmVzIDwtIGMoIklGSTI3IiwgIlJTQUQyIiwgIkNDTDgiLCAiSUZJNDRMIiwgIk9BU0wiLAogICAgICAgICAgICAgICAgICAiVVNQMTgiLCAiSURPMSIsICJJRE8yIiwgIktZTlUiLCAiQUhSIiwgIklMNEkxIiwKICAgICAgICAgICAgICAgICAgIlNPRDIiLCAiTk9UQ0gxIiwgIkRMTDEiLCAiRExMNCIsICJIRVMxIiwgIkhFWTEiKQpnZ3NpZ25pZl9wbG90IDwtIGdnc2lnbmlmX3BhaXJlZF9nZW5lcygKICBoc19tYWNyLCBjb25kaXRpb25zID0gYygiaW5mX3oyMyIsICJpbmZfejIyIiksIGdlbmVzID0gd2FudGVkX2dlbmVzKQpnZ3NpZ25pZl9wbG90CmBgYAoKYGBge3J9CnBhbmRlcjo6cGFuZGVyKHNlc3Npb25JbmZvKCkpCm1lc3NhZ2UoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkKdG1wIDwtIHNhdmVtZShmaWxlbmFtZSA9IHNhdmVmaWxlKQpgYGAKCmBgYHtyIGxvYWRtZV9hZnRlciwgZXZhbD1GQUxTRX0KdG1wIDwtIGxvYWRtZShmaWxlbmFtZSA9IHNhdmVmaWxlKQpgYGAKZGV2dG9vbHM6OmxvYWRfYWxsKCd+L2hwZ2x0b29scycpCg==