Packages
@@ -477,7 +477,7 @@
Loading the data
We can read in a file from a path on our computer on on the web and use this as the value. Note that we need to put quotes (“”) around file paths.
Assignment operator shortcut
-In RStudio, typing Alt + - (push Alt at the same time as the - key) will write <-
in a single keystroke in a PC, while typing > Option + - (push Option at the same time as the - key) does the same in a Mac.
+In RStudio, typing Alt + - (push Alt at the same time as the - key) will write <-
in a single keystroke in Windows, while typing > Option + - (push Option at the same time as the - key) does the same in a Mac.
@@ -556,8 +556,9 @@
Getting to know the data
colnames(sampleinfo)
-
-
[1] "X1" "characteristics" "immunophenotype" "developmental stage"
+
+
[1] "X1" "characteristics" "immunophenotype"
+[4] "developmental stage"
@@ -567,9 +568,10 @@
Getting to know the data
sampleinfo$X1
-
-
[1] "GSM1480291" "GSM1480292" "GSM1480293" "GSM1480294" "GSM1480295" "GSM1480296" "GSM1480297"
- [8] "GSM1480298" "GSM1480299" "GSM1480300" "GSM1480301" "GSM1480302"
+
+
[1] "GSM1480291" "GSM1480292" "GSM1480293" "GSM1480294" "GSM1480295"
+ [6] "GSM1480296" "GSM1480297" "GSM1480298" "GSM1480299" "GSM1480300"
+[11] "GSM1480301" "GSM1480302"
@@ -613,35 +615,42 @@
Getting to know the data
summary(counts)
-
-
X1 gene_symbol GSM1480291 GSM1480292 GSM1480293
- Length:23735 Length:23735 Min. : 0.000 Min. : 0.000 Min. : 0.00
- Class :character Class :character 1st Qu.: 0.000 1st Qu.: 0.000 1st Qu.: 0.00
- Mode :character Mode :character Median : 1.745 Median : 1.891 Median : 0.92
- Mean : 42.132 Mean : 42.132 Mean : 42.13
- 3rd Qu.: 29.840 3rd Qu.: 29.604 3rd Qu.: 21.91
- Max. :12525.066 Max. :12416.211 Max. :49191.15
- GSM1480294 GSM1480295 GSM1480296 GSM1480297
- Min. : 0.00 Min. : 0.00 Min. : 0.00 Min. : 0.000
- 1st Qu.: 0.00 1st Qu.: 0.00 1st Qu.: 0.00 1st Qu.: 0.000
- Median : 0.89 Median : 0.58 Median : 0.54 Median : 2.158
- Mean : 42.13 Mean : 42.13 Mean : 42.13 Mean : 42.132
- 3rd Qu.: 19.92 3rd Qu.: 12.27 3rd Qu.: 12.28 3rd Qu.: 27.414
- Max. :55692.09 Max. :111850.87 Max. :108726.08 Max. :10489.311
- GSM1480298 GSM1480299 GSM1480300 GSM1480301
- Min. : 0.000 Min. : 0.000 Min. : 0.000 Min. : 0.000
- 1st Qu.: 0.000 1st Qu.: 0.000 1st Qu.: 0.000 1st Qu.: 0.000
- Median : 2.254 Median : 1.854 Median : 1.816 Median : 1.629
- Mean : 42.132 Mean : 42.132 Mean : 42.132 Mean : 42.132
- 3rd Qu.: 26.450 3rd Qu.: 24.860 3rd Qu.: 23.443 3rd Qu.: 23.443
- Max. :10662.486 Max. :15194.048 Max. :17434.935 Max. :19152.728
- GSM1480302
- Min. : 0.000
- 1st Qu.: 0.000
- Median : 1.749
- Mean : 42.132
- 3rd Qu.: 24.818
- Max. :15997.193
+
+
X1 gene_symbol GSM1480291
+ Length:23735 Length:23735 Min. : 0.000
+ Class :character Class :character 1st Qu.: 0.000
+ Mode :character Mode :character Median : 1.745
+ Mean : 42.132
+ 3rd Qu.: 29.840
+ Max. :12525.066
+ GSM1480292 GSM1480293 GSM1480294
+ Min. : 0.000 Min. : 0.00 Min. : 0.00
+ 1st Qu.: 0.000 1st Qu.: 0.00 1st Qu.: 0.00
+ Median : 1.891 Median : 0.92 Median : 0.89
+ Mean : 42.132 Mean : 42.13 Mean : 42.13
+ 3rd Qu.: 29.604 3rd Qu.: 21.91 3rd Qu.: 19.92
+ Max. :12416.211 Max. :49191.15 Max. :55692.09
+ GSM1480295 GSM1480296 GSM1480297
+ Min. : 0.00 Min. : 0.00 Min. : 0.000
+ 1st Qu.: 0.00 1st Qu.: 0.00 1st Qu.: 0.000
+ Median : 0.58 Median : 0.54 Median : 2.158
+ Mean : 42.13 Mean : 42.13 Mean : 42.132
+ 3rd Qu.: 12.27 3rd Qu.: 12.28 3rd Qu.: 27.414
+ Max. :111850.87 Max. :108726.08 Max. :10489.311
+ GSM1480298 GSM1480299 GSM1480300
+ Min. : 0.000 Min. : 0.000 Min. : 0.000
+ 1st Qu.: 0.000 1st Qu.: 0.000 1st Qu.: 0.000
+ Median : 2.254 Median : 1.854 Median : 1.816
+ Mean : 42.132 Mean : 42.132 Mean : 42.132
+ 3rd Qu.: 26.450 3rd Qu.: 24.860 3rd Qu.: 23.443
+ Max. :10662.486 Max. :15194.048 Max. :17434.935
+ GSM1480301 GSM1480302
+ Min. : 0.000 Min. : 0.000
+ 1st Qu.: 0.000 1st Qu.: 0.000
+ Median : 1.629 Median : 1.749
+ Mean : 42.132 Mean : 42.132
+ 3rd Qu.: 23.443 3rd Qu.: 24.818
+ Max. :19152.728 Max. :15997.193
@@ -748,8 +757,8 @@
Plotting with ggplot2
ggplot(data = allinfo, mapping = aes(x = Sample, y = Count)) +
geom_boxplot()
-
-
+
+
@@ -761,8 +770,8 @@
Plotting with ggplot2
ggplot(data = allinfo, mapping = aes(x = Sample, y = log2(Count))) +
geom_boxplot()
-
-
+
+
@@ -773,15 +782,15 @@
Plotting with ggplot2
ggplot(data = allinfo, mapping = aes(x = Sample, y = log2(Count + 1))) +
geom_boxplot()
-
-
+
+
The box plots show that the distributions of the samples are not identical but they are not very different.
Box plots are useful summaries, but hide the shape of the distribution. For example, if the distribution is bimodal, we would not see it in a boxplot. An alternative to the boxplot is the violin plot, where the shape (of the density of points) is drawn. See here for an example of how differences in distribution may be hidden in box plots but revealed with violin plots. We could also make jitter plots. A jitter plot is similar to a scatter plot. It adds a small amount of random variation to the location of each point so they don’t overlap. There are too many points in this case for the jitter plots to be useful but this is just to demonstrate, as jitter with and without boxplot is a commonly used ggplot type. We will also make use of jitter plots later.
-
-
Exercise
+
+
Exercises
You can easily make different types of plots with ggplot by using different geoms. Using the same data (same x and y values), try editing the code above to make the plots listed in 1. 2. and 3.
- Make a violin plot (geom_violin)
@@ -796,8 +805,8 @@ Exercise
ggplot(data = allinfo, mapping = aes(x = Sample, y = log2(Count + 1), colour = Sample)) +
geom_boxplot()
-
-
+
+
@@ -808,16 +817,16 @@ Exercise
ggplot(data = allinfo, mapping = aes(x = Sample, y = log2(Count + 1), fill = Sample)) +
geom_boxplot()
-
-
+
+
That looks better. fill =
is used to fill in areas in ggplot2 plots, whereas colour =
is used to colour lines and points.
A really nice feature about ggplot is that we can easily colour by another variable by simply changing the column we give to fill =
.
-
-
Exercise
+
+
Exercises
Modify the plot above. Colour by other variables (columns) in the metadata file:
- characteristics
@@ -870,7 +879,7 @@ Make subplots for each gene
Note on specifying genes
This example is to demonstrate how we could specify any genes in the data to plot. The genes used here were the 8 genes with the highest counts summed across all samples. The command for how to get the gene symbols for these 8 genes is shown below.
-allinfo %>%
+mygenes <- allinfo %>%
group_by(gene_symbol) %>%
summarise(Total_count = sum(Count)) %>%
arrange(desc(Total_count)) %>%
@@ -893,8 +902,8 @@
Note on specifying genes
geom_boxplot() +
facet_wrap(~ gene_symbol)
-
-
+
+
@@ -906,8 +915,8 @@ Note on specifying genes
geom_point() +
facet_wrap(~ gene_symbol)
-
-
+
+
@@ -919,8 +928,8 @@ Note on specifying genes
geom_jitter() +
facet_wrap(~ gene_symbol)
-
-
+
+
@@ -932,8 +941,8 @@ Note on specifying genes
geom_jitter() +
facet_wrap(~ gene_symbol)
-
-
+
+
@@ -959,8 +968,8 @@ Specifying colours
facet_wrap(~ gene_symbol) +
scale_colour_manual(values = mycolours)
-
-
+
+
@@ -973,13 +982,13 @@ Specifying colours
facet_wrap(~ gene_symbol) +
scale_colour_brewer(palette = "Dark2")
-
-
+
+
-
-
Exercise
+
+
Exercises
Make a colourblind friendly plot. Hint there are colourblind friendly palettes here
@@ -994,8 +1003,8 @@ Axis labels and Title
facet_wrap(~ gene_symbol) +
labs(x = "Cell type and stage", y = "Count", title = "Mammary gland RNA-seq data")
-
-
+
+
@@ -1012,8 +1021,8 @@ Themes
labs(x = "Cell type and stage", y = "Count", title = "Mammary gland RNA-seq data") +
theme(axis.text.x = element_text(angle = 90))
-
-
+
+
@@ -1029,8 +1038,8 @@ Themes
theme_bw() +
theme(axis.text.x = element_text(angle = 90))
-
-
+
+
@@ -1044,8 +1053,8 @@ Themes
theme_minimal() +
theme(axis.text.x = element_text(angle = 90))
-
-
+
+
@@ -1063,8 +1072,8 @@ Themes
panel.grid.major = element_blank(),
panel.grid.minor = element_blank())
-
-
+
+
@@ -1089,16 +1098,16 @@ Order of groups
-Take a look at the data.
+Take a look at the data. As the table is quite wide we can use select()
to select just the columns we want to view.
-
-mygenes_counts
+
+mygenes_counts %>% select(X1, Group, Group_f)
-
+
@@ -1149,8 +1158,8 @@ Order of groups
panel.grid.major = element_blank(),
panel.grid.minor = element_blank())
-
-
+
+
@@ -1159,7 +1168,7 @@ Order of groups
Saving plots
-
We can save plots interactively by clicking Export in the Plots window. Or we can output plots to pdf using pdf()
followed by dev.off()
. We put our plot code after the call to pdf()
and before closing the plot device with dev.off()
.
+
We can save plots interactively by clicking Export in the Plots window and saving as e.g. “myplot.pdf”. Or we can output plots to pdf using pdf()
followed by dev.off()
. We put our plot code after the call to pdf()
and before closing the plot device with dev.off()
.
Let’s save our last plot.
@@ -1177,9 +1186,8 @@
Saving plots
-
-
-
Exercises
+
+
Exercises
- Download the raw counts for this dataset
@@ -1191,6 +1199,7 @@
Exercises
Download the normalised counts for the GSE63310 dataset from GREIN. Make boxplots colouring the samples using different columns in the metadata file.
+
Key Points
@@ -1209,7 +1218,7 @@ Further Reading
-
LS0tCnRpdGxlOiAiSW50cm9kdWN0aW9uIHRvIFIgZm9yIEJpb2xvZ2lzdHMiCmF1dGhvcjogIk1hcmlhIERveWxlLCBKZXNzaWNhIENodW5nLCBWaWNreSBQZXJyZWF1IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDMKICAgIHRvY19mbG9hdDogeWVzCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkICVCICVZJylgIgotLS0KCiMgUiBmb3IgQmlvbG9naXN0cyBjb3Vyc2UKClIgdGFrZXMgdGltZSB0byBsZWFybiwgbGlrZSBhIHNwb2tlbiBsYW5ndWFnZS4gTm8gb25lIGNhbiBleHBlY3QgdG8gYmUgYW4gUiBleHBlcnQgYWZ0ZXIgbGVhcm5pbmcgUiBmb3IgYSBmZXcgaG91cnMuIFRoaXMgY291cnNlIGhhcyBiZWVuIGRlc2lnbmVkIHRvIGludHJvZHVjZSBiaW9sb2dpc3RzIHRvIFIsIHNob3dpbmcgc29tZSBiYXNpY3MgYW5kIHNvbWUgcG93ZXJmdWwgdGhpbmdzIFIgY2FuIGRvLiBUaGUgYWltIGlzIHRvIGdpdmUgYmVnaW5uZXJzIHRoZSBjb25maWRlbmNlIHRvIGNvbnRpbnVlIGxlYXJuaW5nIFIsIHNvIHRoZSBmb2N1cyBoZXJlIGlzIG9uIHRpZHl2ZXJzZSBhbmQgdmlzdWFsaXNhdGlvbiBvZiBiaW9sb2dpY2FsIGRhdGEsIGFzIHdlIGJlbGlldmUgdGhpcyBpcyBhIHByb2R1Y3RpdmUgYW5kIGVuZ2FnaW5nIHdheSB0byBzdGFydCBsZWFybmluZyBSLgoKIyBJbnRybyB0byBSIGFuZCBSU3R1ZGlvCgpSU3R1ZGlvIGlzIGFuIGludGVyZmFjZSB0aGF0IG1ha2VzIGl0IGVhc2llciB0byB1c2UgUi4gVGhlcmUgYXJlIGZvdXIgd2luZG93cyBpbiBSU3R1ZGlvLiBUaGUgc2NyZWVuc2hvdCBiZWxvdyBzaG93cyBhbiBbYW5hbG9neSBsaW5raW5nIHRoZSBkaWZmZXJlbnQgUlN0dWRpbyB3aW5kb3dzIHRvIGNvb2tpbmddKGh0dHBzOi8vdHdpdHRlci5jb20vUkxhZGllc05DTC9zdGF0dXMvMTEzODgxMjgyNjkxNzcyNDE2MCkuCgohW10oaW1hZ2VzL3JzdHVkaW9fY29va2luZy5qcGcpCgpcICAKXCAgClwgIAoKIyMgUiBzY3JpcHQgdnMgY29uc29sZQoKVGhlcmUgYXJlIHR3byB3YXlzIHRvIHdvcmsgaW4gUlN0dWRpbyBpbiB0aGUgY29uc29sZSBvciBpbiBhIHNjcmlwdC4gV2UgY2FuIHR5cGUgYSBjb21tYW5kIGluIHRoZSBjb25zb2xlIGFuZCBwcmVzcyBgRW50ZXJgIHRvIHJ1biBpdC4gVHJ5IHJ1bm5pbmcgdGhlIGNvbW1hbmQgYmVsb3cgaW4gdGhlIGNvbnNvbGUuCgpgYGB7cn0KMSArIDEKYGBgCgpPciB3ZSBjYW4gdXNlIGFuIFIgc2NyaXB0LiBUbyBjcmVhdGUgYSBzY3JpcHQsIGZyb20gdGhlIHRvcCBtZW51IGluIFJTdHVkaW86IGBGaWxlID4gTmV3IEZpbGUgPiBSIFNjcmlwdGAuIE5vdyB0eXBlIHRoZSBjb21tYW5kIGJlbG93IGluIHRoZSBzY3JpcHQuIFRoaXMgdGltZSwgdG8gcnVuIHRoZSBjb21tYW5kLCB5b3UgdXNlIGBDdHJsYCArIGBFbnRlcmAgZm9yIFdpbmRvd3MvTGludXggb3IgYENtZGAgKyBgRW50ZXJgIGZvciBNYWNPUy4gVGhpcyBzZW5kcyB0aGUgY29tbWFuZCB3aGVyZSB0aGUgY3Vyc29yIGlzIGZyb20gdGhlIHNjcmlwdCB0byB0aGUgY29uc29sZS4gWW91IGNhbiBoaWdobGlnaHQgbXVsdGlwbGUgY29tbWFuZHMgYW5kIHRoZW4gcHJlc3MgYENtZC9DdHJsYCArIGBFbnRlcmAgdG8gcnVuIHRoZW0gb25lIGFmdGVyIHRoZSBvdGhlci4KCmBgYHtyfQoyICsgMgpgYGAKCkFzIHRoZSBSU3R1ZGlvIHNjcmVlbnNob3QgYWJvdmUgZXhwbGFpbnMsIGlmIHdlIHdvcmsgaW4gdGhlIGNvbnNvbGUgd2UgZG9uJ3QgaGF2ZSBhIGdvb2QgcmVjb3JkIChyZWNpcGUpIG9mIHdoYXQgd2UndmUgZG9uZS4gV2UgY2FuIHNlZSBjb21tYW5kcyB3ZSd2ZSBydW4gaW4gdGhlIEhpc3RvcnkgcGFuZWwgKHRvcCByaWdodCB3aW5kb3cpLCBhbmQgd2UgY2FuIGdvIGJhY2t3YXJkcyBhbmQgZm9yd2FyZHMgdGhyb3VnaCBvdXIgaGlzdG9yeSBpbiB0aGUgY29uc29sZSB1c2luZyB0aGUgdXAgYXJyb3cgYW5kIGRvd24gYXJyb3cuIEJ1dCB0aGUgaGlzdG9yeSBpbmNsdWRlcyBldmVyeXRoaW5nIHdlJ3ZlIHRyaWVkIHRvIHJ1biwgaW5jbHVkaW5nIG91ciBtaXN0YWtlcyBzbyBpdCBpcyBnb29kIHByYWN0aWNlIHRvIHVzZSBhbiBSIHNjcmlwdC4KCldlIGNhbiBhbHNvIGFkZCBjb21tZW50cyB0byBhIHNjcmlwdC4gVGhlc2UgYXJlIG5vdGVzIHRvIG91cnNlbGYgb3Igb3RoZXJzIGFib3V0IHRoZSBjb21tYW5kcyBpbiB0aGUgc2NyaXB0LiBDb21tZW50cyBzdGFydCB3aXRoIGEgYCNgIHdoaWNoIHRlbGxzIFIgbm90IHRvIHJ1biB0aGVtIGFzIGNvbW1hbmRzLgoKYGBge3J9CiMgdGVzdGluZyBSCjIgKyAyCmBgYAoKS2VlcGluZyBhbiBhY2N1cmF0ZSByZWNvcmQgb2YgaG93IHlvdSd2ZSBtYW5pcHVsYXRlZCB5b3VyIGRhdGEgaXMgaW1wb3J0YW50IGZvciBbcmVwcm9kdWNpYmxlIHJlc2VhcmNoXShodHRwczovL3JvcGVuc2NpLmdpdGh1Yi5pby9yZXByb2R1Y2liaWxpdHktZ3VpZGUvc2VjdGlvbnMvaW50cm9kdWN0aW9uLykuIFdyaXRpbmcgZGV0YWlsZWQgY29tbWVudHMgYW5kIGRvY3VtZW50aW5nIHlvdXIgd29yayBhcmUgdXNlZnVsIHJlbWluZGVycyB0byB5b3VyIGZ1dHVyZSBzZWxmIChhbmQgYW55b25lIGVsc2UgcmVhZGluZyB5b3VyIHNjcmlwdHMpIG9uIHdoYXQgeW91ciBjb2RlIGRvZXMuCgojIyBXb3JraW5nIGRpcmVjdG9yeQoKT3BlbmluZyBhbiBSU3R1ZGlvIHNlc3Npb24gbGF1bmNoZXMgaXQgZnJvbSBhIHNwZWNpZmljIGxvY2F0aW9uLiBUaGlzIGlzIHRoZSDigJh3b3JraW5nIGRpcmVjdG9yeeKAmS4gKipSIGxvb2tzIGluIHRoZSB3b3JraW5nIGRpcmVjdG9yeSBieSBkZWZhdWx0IHRvIHJlYWQgaW4gZGF0YSBhbmQgc2F2ZSBmaWxlcy4qKiBZb3UgY2FuIGZpbmQgb3V0IHdoYXQgdGhlIHdvcmtpbmcgZGlyZWN0b3J5IGlzIGJ5IHVzaW5nIHRoZSBjb21tYW5kIGBnZXR3ZCgpYC4gVGhpcyBzaG93cyB5b3UgdGhlIHBhdGggdG8geW91ciB3b3JraW5nIGRpcmVjdG9yeSBpbiB0aGUgY29uc29sZS4gSW4gTWFjIHRoaXMgaXMgaW4gdGhlIGZvcm1hdCBgL3BhdGgvdG8vd29ya2luZy9kaXJlY3RvcnlgIGFuZCBpbiBXaW5kb3dzIGBDOlxwYXRoXHRvXHdvcmtpbmdcZGlyZWN0b3J5YC4gSXQgaXMgb2Z0ZW4gdXNlZnVsIHRvIGhhdmUgeW91ciBkYXRhIGFuZCBSIHNjcmlwdHMgaW4gdGhlIHNhbWUgZGlyZWN0b3J5IGFuZCBzZXQgdGhpcyBhcyB5b3VyIHdvcmtpbmcgZGlyZWN0b3J5LiBXZSB3aWxsIGRvIHRoaXMgbm93LiAKCk1ha2UgYSBmb2xkZXIgZm9yIHRoaXMgY291cnNlIHNvbWV3aGVyZSBvbiB5b3VyIGNvbXB1dGVyIHRoYXQgeW91IHdpbGwgYmUgYWJsZSB0byBlYXNpbHkgZmluZC4gTmFtZSB0aGUgZm9sZGVyIGZvciBleGFtcGxlLCBgSW50cm9fUl9jb3Vyc2VgLiBUaGVuLCB0byBzZXQgdGhpcyBmb2xkZXIgYXMgeW91ciB3b3JraW5nIGRpcmVjdG9yeToKCkluIFJTdHVkaW8gY2xpY2sgb24gdGhlIOKAmEZpbGVz4oCZIHRhYiBhbmQgdGhlbiBjbGljayBvbiB0aGUgdGhyZWUgZG90cywgYXMgc2hvd24gYmVsb3cuCgohW10oaW1hZ2VzL3RocmVlX2RvdHMucG5nKQoKSW4gdGhlIHdpbmRvdyB0aGF0IGFwcGVhcnMsIGZpbmQgdGhlIGZvbGRlciB5b3UgY3JlYXRlZCAoZS5nLiBgSW50cm9fUl9jb3Vyc2VgKSwgY2xpY2sgb24gaXQsIHRoZW4gY2xpY2sg4oCYT3BlbuKAmS4gVGhlIGZpbGVzIHRhYiB3aWxsIG5vdyBzaG93IHRoZSBjb250ZW50cyBvZiB5b3VyIG5ldyBmb2xkZXIuIENsaWNrIG9uIGBNb3JlID4gU2V0IEFzIFdvcmtpbmcgRGlyZWN0b3J5YCwgYXMgc2hvd24gYmVsb3cuCgohW10oaW1hZ2VzL3dvcmtpbmdfZGlyZWN0b3J5LnBuZykKClNhdmUgdGhlIHNjcmlwdCB5b3UgY3JlYXRlZCBpbiB0aGUgcHJldmlvdXMgc2VjdGlvbiBhcyBgaW50cm8uUmAgaW4gdGhpcyBkaXJlY3RvcnkuIFlvdSBjYW4gZG8gdGhpcyBieSBjbGlrY2luZyBvbiBgRmlsZSA+IFNhdmVgIGFuZCB0aGUgZGVmYXVsdCBsb2NhdGlvbiBzaG91bGQgYmUgdGhlIGN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnkgKGUuZy4gYEludHJvX1JfY291cnNlYCkuCgojIyBQYWNrYWdlcwoKSWYgaXQncyBub3QgYWxyZWFkeSBpbnN0YWxsZWQgb24geW91ciBjb21wdXRlciwgeW91IGNhbiB1c2UgdGhlIGBpbnN0YWxsLnBhY2thZ2VzYCAqKmZ1bmN0aW9uKiogdG8gaW5zdGFsbCBhICoqcGFja2FnZSoqLiBBIHBhY2thZ2UgaXMgYSBjb2xsZWN0aW9uIG9mIGZ1bmN0aW9ucyBhbG9uZyB3aXRoIGRvY3VtZW50YXRpb24sIGNvZGUsIHRlc3RzIGFuZCBleGFtcGxlIGRhdGEuCgpgYGB7ciwgZXZhbD1GQUxTRX0KaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikKYGBgCgpXZSB3aWxsIHNlZSBtYW55IGZ1bmN0aW9ucyBpbiB0aGlzIHR1dG9yaWFsLiBGdW5jdGlvbnMgYXJlICJjYW5uZWQgc2NyaXB0cyIgdGhhdCBhdXRvbWF0ZSBtb3JlIGNvbXBsaWNhdGVkIHNldHMgb2YgY29tbWFuZHMuIE1hbnkgZnVuY3Rpb25zIGFyZSBwcmVkZWZpbmVkLCBvciBjYW4gYmUgbWFkZSBhdmFpbGFibGUgYnkgaW1wb3J0aW5nIFIgcGFja2FnZXMuIEEgZnVuY3Rpb24gdXN1YWxseSB0YWtlcyBvbmUgb3IgbW9yZSBpbnB1dHMgY2FsbGVkICphcmd1bWVudHMqLiBIZXJlIHRpZHl2ZXJzZSBpcyB0aGUgYXJndW1lbnQgdG8gdGhlIGBpbnN0YWxsLnBhY2thZ2VzKClgIGZ1bmN0aW9uLiAqKk5vdGUgdGhhdCBmdW5jdGlvbnMgcmVxdWlyZSBwYXJlbnRoZXNlcyBhZnRlciB0aGUgZnVuY3Rpb24gbmFtZS4qKgoKIyMgR2V0dGluZyBoZWxwCgpUbyBzZWUgd2hhdCBhbnkgZnVuY3Rpb24gaW4gUiBkb2VzLCB0eXBlIGEgYD9gIGJlZm9yZSB0aGUgbmFtZSBhbmQgaGVscCBpbmZvcm1hdGlvbiB3aWxsIGFwcGVhciBpbiB0aGUgSGVscCBwYW5lbCBvbiB0aGUgcmlnaHQgaW4gUlN0dWRpby4gT3IgeW91IGNhbiBzZWFyY2ggdGhlIGZ1bmN0aW9uIG5hbWUgaW4gdGhlIEhlbHAgcGFuZWwgc2VhcmNoIGJveC4gR29vZ2xlIGFuZCBbU3RhY2sgT3ZlcmZsb3ddKGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vKSBhcmUgYWxzbyB1c2VmdWwgcmVzb3VyY2VzIGZvciBnZXR0aW5nIGhlbHAuCgpgYGB7ciwgZXZhbD1GQUxTRX0KP2luc3RhbGwucGFja2FnZXMKYGBgCgo+ICMjIyMgVGFiIGNvbXBsZXRpb24KPiBBIHZlcnkgdXNlZnVsIGZlYXR1cmUgaXMgVGFiIGNvbXBsZXRpb24uIFlvdSBjYW4gc3RhcnQgdHlwaW5nIGFuZCB1c2UgPGtiZD5UYWI8L2tiZD4gdG8gYXV0b2NvbXBsZXRlIGNvZGUsIGZvciBleGFtcGxlLCBhIGZ1bmN0aW9uIG5hbWUuIAoKIyMgQ29tbW9uIFIgZXJyb3JzCgpSIGVycm9yIG1lc3NhZ2VzIGFyZSBjb21tb24gYW5kIGNhbiBzb21ldGltZXMgYmUgY3J5cHRpYy4gWW91IG1vc3QgbGlrZWx5IHdpbGwgZW5jb3VudGVyIGF0IGxlYXN0IG9uZSBlcnJvciBtZXNzYWdlIGR1cmluZyB0aGlzIHR1dG9yaWFsLiBTb21lIGNvbW1vbiByZWFzb25zIGZvciBlcnJvcnMgYXJlOgoKLSBDYXNlIHNlbnNpdGl2aXR5LiBJbiBSLCBhcyBpbiBvdGhlciBwcm9ncmFtbWluZyBsYW5ndWFnZXMsIGNhc2Ugc2Vuc2l0aXZpdHkgaXMgaW1wb3J0YW50LiA/aW5zdGFsbC5wYWNrYWdlcyBpcyBkaWZmZXJlbnQgdG8gP0luc3RhbGwucGFja2FnZXMuCi0gTWlzc2luZyBjb21tYXMKLSBNaXNtYXRjaGVkIHBhcmVudGhlc2VzIG9yIGJyYWNrZXRzCi0gTm90IHF1b3RpbmcgZmlsZSBwYXRocwotIE5vdCBmaW5pc2hpbmcgYSBjb21tYW5kIHNvIHNlZWluZyAiKyIgaW4gdGhlIGNvbnNvbGUuIElmIHlvdSBuZWVkIHRvLCB5b3UgY2FuIHByZXNzIEVTQyB0byBjYW5jZWwgdGhlIGNvbW1hbmQuCgpUbyBzZWUgZXhhbXBsZXMgb2Ygc29tZSBSIGVycm9yIG1lc3NhZ2VzIHdpdGggZXhwbGFuYXRpb25zIHNlZSBbaGVyZV0oIGh0dHBzOi8vZ2l0aHViLmNvbS9ub2Ftcm9zcy96ZXJvLWRlcGVuZGVuY3ktcHJvYmxlbXMvaXNzdWVzLzcpCgoKIyBHZXR0aW5nIHN0YXJ0ZWQgd2l0aCBkYXRhCgoKIyMgRGF0YSBmaWxlcwpUaGUgZGF0YSBmaWxlcyByZXF1aXJlZCBmb3IgdGhpcyB3b3Jrc2hvcCBhcmUgYXZhaWxhYmxlIG9uIFtHaXRIdWJdKGh0dHBzOi8vZ2l0aHViLmNvbS9tYmx1ZTkvci1pbnRyby1iaW9sb2dpc3RzL2Jsb2IvbWFzdGVyL2RhdGEuemlwKS4gVG8gZG93bmxvYWQgdGhlIGRhdGEuemlwIGZpbGUsIHlvdSBjYW4gY2xpY2sgW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9tYmx1ZTkvci1pbnRyby1iaW9sb2dpc3RzL3Jhdy9tYXN0ZXIvZGF0YS56aXApLiBVbnppcCB0aGUgZmlsZSBhbmQgc3RvcmUgdGhpcyBgZGF0YWAgZm9sZGVyIGluIHlvdXIgd29ya2luZyBkaXJlY3RvcnkuCgoKIyMgR1JFSU4gKEdFTyBSTkEtc2VxIEV4cGVyaW1lbnRzIEludGVyYWN0aXZlIE5hdmlnYXRvcikgCkluIHRoaXMgdHV0b3JpYWwsIHdlIHdpbGwgbGVhcm4gc29tZSBSIHRocm91Z2ggY3JlYXRpbmcgcGxvdHMgdG8gdmlzdWFsaXNlIGRhdGEgZnJvbSBhbiBSTkEtc2VxIGV4cGVyaW1lbnQuIFJOQS1zZXEgY291bnRzIGZpbGUgY2FuIGJlIG9idGFpbmVkIGZyb20gdGhlIFtHUkVJTiBwbGF0Zm9ybV0oaHR0cHM6Ly93d3cubmF0dXJlLmNvbS9hcnRpY2xlcy9zNDE1OTgtMDE5LTQzOTM1LTgpLiBHUkVJTiBwcm92aWRlcyA+Niw1MDAgcHVibGlzaGVkIGRhdGFzZXRzIGZyb20gR0VPIHRoYXQgaGF2ZSBiZWVuIHVuaWZvcm1seSBwcm9jZXNzZWQuIEl0IGlzIGF2YWlsYWJsZSBhdCBodHRwOi8vd3d3LmlsaW5jcy5vcmcvYXBwcy9ncmVpbi8uIFlvdSBjYW4gc2VhcmNoIGZvciBhIGRhdGFzZXQgb2YgaW50ZXJlc3QgdXNpbmcgdGhlIEdFTyBjb2RlLiBXZSBvYnRhaW5lZCB0aGUgZGF0YXNldCB1c2VkIGhlcmUgdXNpbmcgdGhlIGNvZGUgR1NFNjA0NTAuIEdSRUlOIHByb3ZpZGUgUUMgbWV0cmljcyBmb3IgdGhlIFJOQS1zZXEgZGF0YXNldHMgYW5kIGJvdGggcmF3IGFuZCBub3JtYWxpemVkIGNvdW50cy4gV2Ugd2lsbCB1c2UgdGhlIG5vcm1hbGl6ZWQgY291bnRzIGhlcmUuIFRoZXNlIGFyZSB0aGUgY291bnRzIG9mIHJlYWRzIGZvciBlYWNoIGdlbmUgZm9yIGVhY2ggc2FtcGxlIG5vcm1hbGl6ZWQgZm9yIGRpZmZlcmVuY2VzIGluIHNlcXVlbmNpbmcgZGVwdGggYW5kIGNvbXBvc2l0aW9uIGJpYXMuIEdlbmVyYWxseSwgdGhlIGhpZ2hlciB0aGUgbnVtYmVyIG9mIGNvdW50cyB0aGUgbW9yZSB0aGUgZ2VuZSBpcyBleHByZXNzZWQuClwgIApcIAoKIyMgUk5BLXNlcSBkYXRhc2V0CkhlcmUgd2Ugd2lsbCBjcmVhdGUgc29tZSBwbG90cyB1c2luZyBSTkEtc2VxIGRhdGEgZnJvbSB0aGUgcGFwZXIgYnkgW0Z1IGV0IGFsLiAyMDE1XShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC8yNTczMDQ3MiksIEdFTyBjb2RlIEdTRTYwNDUwLiBUaGlzIHN0dWR5IGV4YW1pbmVkIGV4cHJlc3Npb24gaW4gYmFzYWwgYW5kIGx1bWluYWwgY2VsbHMgZnJvbSBtaWNlIGF0IGRpZmZlcmVudCBzdGFnZXMgKHZpcmdpbiwgcHJlZ25hbnQgYW5kIGxhY3RhdGluZykuIFRoZXJlIGFyZSAyIHNhbXBsZXMgcGVyIGdyb3VwIGFuZCA2IGdyb3VwcywgMTIgc2FtcGxlcyBpbiB0b3RhbC4KCiFbXShpbWFnZXMvbW91c2VfZXhwLnBuZykKCiMjIFRpZHl2ZXJzZQoKIVt3d3cudGlkeXZlcnNlLm9yZ10oaW1hZ2VzL3RpZHl2ZXJzZS5wbmcpe3dpZHRoPTEwMCUgfQoKSW4gdGhpcyBjb3Vyc2Ugd2Ugd2lsbCB1c2UgdGhlICoqdGlkeXZlcnNlKiouIFRoZSB0aWR5dmVyc2UgaXMgYSBjb2xsZWN0aW9uIG9mIFIgcGFja2FnZXMgdGhhdCBpbmNsdWRlcyB0aGUgZXh0cmVtZWx5IHdpZGVseSB1c2VkICoqYGdncGxvdDJgKiogcGFja2FnZS4KClwgIApcICAKXCAgCgohW1RpZHl2ZXJzZSBwYWNrYWdlc10oaW1hZ2VzL3RpZHl2ZXJzZV9wYWNrYWdlcy5qcGVnKXt3aWR0aD01MCUgfQoKXCAgClwgIApcIAoKKipUaGUgW3RpZHl2ZXJzZV0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8pIG1ha2VzIGRhdGEgc2NpZW5jZSBmYXN0ZXIsIGVhc2llciBhbmQgbW9yZSBmdW4uKioKClwgIApcICAKXCAgCgoKIyMgTG9hZGluZyB0aGUgZGF0YQoKV2UgdXNlIGBsaWJyYXJ5KClgIHRvIGxvYWQgaW4gdGhlIHBhY2thZ2VzIHRoYXQgd2UgbmVlZC4gQXMgZGVzY3JpYmVkIGluIHRoZSBjb29raW5nIGFuYWxvZ3kgaW4gdGhlIGZpcnN0IHNjcmVlbnNob3QsIGBpbnN0YWxsLnBhY2thZ2VzKClgIGlzIGxpa2UgYnV5aW5nIGEgc2F1Y2VwYW4sIGBsaWJyYXJ5KClgIGlzIHRha2luZyBpdCBvdXQgb2YgdGhlIGN1cGJvYXJkIHRvIHVzZSBpdC4KCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgpUaGUgZmlsZXMgd2Ugd2lsbCB1c2UgYXJlIGNzdiBjb21tYS1zZXBhcmF0ZWQsIHNvIHdlIHdpbGwgdXNlIHRoZSBgcmVhZF9jc3YoKWAgZnVuY3Rpb24gZnJvbSB0aGUgdGlkeXZlcnNlLiBUaGVyZSBpcyBhbHNvIGEgYHJlYWRfdHN2KClgIGZ1bmN0aW9uIGZvciB0YWItc2VwYXJhdGVkIHZhbHVlcy4KCldlIHdpbGwgdXNlIHRoZSBjb3VudHMgZmlsZSBjYWxsZWQgYEdTRTYwNDUwX0dlbmVMZXZlbF9Ob3JtYWxpemVkKENQTS5hbmQuVE1NKV9kYXRhLmNzdmAgdGhhdCdzIGluIGEgZm9sZGVyIGNhbGxlZCBgZGF0YWAgaS5lLiB0aGUgcGF0aCB0byB0aGUgZmlsZSBzaG91bGQgYmUgYGRhdGEvR1NFNjA0NTBfR2VuZUxldmVsX05vcm1hbGl6ZWQoQ1BNLmFuZC5UTU0pX2RhdGEuY3N2YC4KCldlIGNhbiByZWFkIHRoZSBjb3VudHMgZmlsZSBpbnRvIFIgd2l0aCB0aGUgY29tbWFuZCBiZWxvdy4gV2UnbGwgc3RvcmUgdGhlIGNvbnRlbnRzIG9mIHRoZSBjb3VudHMgZmlsZSBpbiBhbiAqKm9iamVjdCoqIGNhbGxlZCBgY291bnRzYC4gVGhpcyBzdG9yZXMgdGhlIGZpbGUgY29udGVudHMgaW4gUidzIG1lbW9yeSBtYWtpbmcgaXQgZWFzaWVyIHRvIHVzZS4KCmBgYHtyfQojIHJlYWQgaW4gY291bnRzIGZpbGUKY291bnRzIDwtIHJlYWRfY3N2KCJkYXRhL0dTRTYwNDUwX0dlbmVMZXZlbF9Ob3JtYWxpemVkKENQTS5hbmQuVE1NKV9kYXRhLmNzdiIpCgojIHJlYWQgaW4gbWV0YWRhdGEKc2FtcGxlaW5mbyA8LSByZWFkX2NzdigiZGF0YS9HU0U2MDQ1MF9maWx0ZXJlZF9tZXRhZGF0YS5jc3YiKQpgYGAKClRoZXJlIGlzIHNvbWUgaW5mb3JtYXRpb24gb3V0cHV0IGJ5IHJlYWRfY3N2IG9uICJjb2x1bW4gc3BlY2lmaWNhdGlvbiIuIEl0IHRlbGxzIHVzIHRoYXQgdGhlcmUgaXMgYSBtaXNzaW5nIGhlYWRlciBhbmQgaXQgaGFzIGJlZW4gZmlsbGVkIHdpdGggdGhlIG5hbWUgIlgxIi4gSXQgYWxzbyB0ZWxscyB1cyB3aGF0IGRhdGEgdHlwZXMgcmVhZF9jc3YgaXMgZGV0ZWN0aW5nIGluIGVhY2ggY29sdW1uLiBDb2x1bW5zIHdpdGggdGV4dCBjaGFyYWN0ZXJzaGF2ZSBiZWVuIGRldGVjdGVkIChjb2xfY2hhcmFjdGVyKSBhbmQgYWxzbyBjb2x1bW5zIHdpdGggbnVtYmVycyAoY29sX2RvdWJsZSkuIFdlIHdvbid0IGdldCBpbnRvIHRoZSBkZXRhaWxzIG9mIFIgZGF0YSB0eXBlcyBpbiB0aGlzIHR1dG9yaWFsIGJ1dCB0aGV5IGFyZSBpbXBvcnRhbnQgdG8ga25vdyBhbmQgeW91IGNhbiByZWFkIG1vcmUgYWJvdXQgdGhlbSBpbiB0aGUgW1IgZm9yIERhdGEgU2NpZW5jZSBib29rXShodHRwczovL3I0ZHMuaGFkLmNvLm56L3ZlY3RvcnMuaHRtbCNpbXBvcnRhbnQtdHlwZXMtb2YtYXRvbWljLXZlY3RvcikuCgpJbiBSIHdlIHVzZSBgPC1gIHRvIGFzc2lnbiB2YWx1ZXMgdG8gb2JqZWN0cy4gYDwtYCBpcyB0aGUgKiphc3NpZ25tZW50IG9wZXJhdG9yKiouICBJdCBhc3NpZ25zIHZhbHVlcyBvbiB0aGUgcmlnaHQgdG8gb2JqZWN0cyBvbiB0aGUgbGVmdC4gU28gdG8gY3JlYXRlIGFuIG9iamVjdCwgd2UgbmVlZCB0byBnaXZlIGl0IGEgbmFtZSAoZS5nLiBgY291bnRzYCksIGZvbGxvd2VkIGJ5IHRoZSBhc3NpZ25tZW50IG9wZXJhdG9yIGA8LWAsIGFuZCB0aGUgdmFsdWUgd2Ugd2FudCB0byBnaXZlIGl0LiBXZSBjYW4gZ2l2ZSBhbiBvYmplY3QgYWxtb3N0IGFueSBuYW1lIHdlIHdhbnQgYnV0IHRoZXJlIGFyZSBzb21lIHJ1bGVzIGFuZCBjb252ZW50aW9ucyBhcyBkZXNjcmliZWQgaW4gdGhlIFt0aWR5dmVyc2UgUiBzdHlsZSBndWlkZV0oaHR0cHM6Ly9zdHlsZS50aWR5dmVyc2Uub3JnL3N5bnRheC5odG1sI29iamVjdC1uYW1lcykKCldlIGNhbiByZWFkIGluIGEgZmlsZSBmcm9tIGEgcGF0aCBvbiBvdXIgY29tcHV0ZXIgb24gb24gdGhlIHdlYiBhbmQgdXNlIHRoaXMgYXMgdGhlIHZhbHVlLiBOb3RlIHRoYXQgd2UgbmVlZCB0byBwdXQgcXVvdGVzICgiIikgYXJvdW5kIGZpbGUgcGF0aHMuCgo+ICMjIyMgQXNzaWdubWVudCBvcGVyYXRvciBzaG9ydGN1dAo+IEluIFJTdHVkaW8sIHR5cGluZyA8a2JkPkFsdDwva2JkPiArIDxrYmQ+LTwva2JkPiAocHVzaCA8a2JkPkFsdDwva2JkPiBhdCB0aGUKPiBzYW1lIHRpbWUgYXMgdGhlIDxrYmQ+LTwva2JkPiBrZXkpIHdpbGwgd3JpdGUgYCA8LSBgIGluIGEgc2luZ2xlIGtleXN0cm9rZSBpbiBhIFBDLCB3aGlsZSB0eXBpbmcgPiA8a2JkPk9wdGlvbjwva2JkPiArIDxrYmQ+LTwva2JkPiAocHVzaCA8a2JkPk9wdGlvbjwva2JkPiBhdCB0aGUKPiBzYW1lIHRpbWUgYXMgdGhlIDxrYmQ+LTwva2JkPiBrZXkpIGRvZXMgdGhlIHNhbWUgaW4gYSBNYWMuIAoKCiMjIEdldHRpbmcgdG8ga25vdyB0aGUgZGF0YQoKV2hlbiBhc3NpZ25pbmcgYSB2YWx1ZSB0byBhbiBvYmplY3QsIFIgZG9lcyBub3QgcHJpbnQgdGhlIHZhbHVlLiBGb3IgZXhhbXBsZSwgaGVyZSB3ZSBkb24ndCBzZWUgd2hhdCdzIGluIHRoZSBjb3VudHMgb3Igc2FtcGxlaW5mbyBmaWxlcy4gQnV0IHRoZXJlIGFyZSB3YXlzIHdlIGNhbiBsb29rIGF0IHRoZSBkYXRhLiBXZSB3aWxsIGRlbW9uc3RyYXRlIHVzaW5nIHRoZSBgc2FtcGxlaW5mb2Agb2JqZWN0LgoKV2UgY2FuIHR5cGUgdGhlIG5hbWUgb2YgdGhlIG9iamVjdCBhbmQgdGhpcyB3aWxsIHByaW50IHRoZSBmaXJzdCBmZXcgbGluZXMgYW5kIHNvbWUgaW5mb3JtYXRpb24sIHN1Y2ggYXMgbnVtYmVyIG9mIHJvd3MuIAoKYGBge3J9CnNhbXBsZWluZm8KYGBgCgpXZSBjYW4gYWxzbyB1c2UgYGRpbSgpYCB0byBzZWUgdGhlIGRpbWVuc2lvbnMgb2YgYW4gb2JqZWN0LCB0aGUgbnVtYmVyIG9mIHJvd3MgYW5kIGNvbHVtbnMuCgpgYGB7cn0KZGltKHNhbXBsZWluZm8pCmBgYAoKVGhpcyBzaG93IHVzIHRoZXJlIGFyZSAxMiByb3dzIGFuZCA0IGNvbHVtbnMuCgpJbiB0aGUgRW52aXJvbm1lbnQgVGFiIGluIHRoZSB0b3AgcmlnaHQgcGFuZWwgaW4gUlN0dWRpbyB3ZSBjYW4gYWxzbyBzZWUgdGhlIG51bWJlciBvZiByb3dzIGFuZCBjb2x1bW5zIGluIHRoZSBvYmplY3RzIHdlIGhhdmUgaW4gb3VyIHNlc3Npb24uCgpXZSBjYW4gYWxzbyB0YWtlIGEgbG9vayB0aGUgZmlyc3QgZmV3IGxpbmVzIHdpdGggYGhlYWQoKWAuIFRoaXMgc2hvd3MgdXMgdGhlIGZpcnN0IDYgbGluZXMuCgpgYGB7cn0KaGVhZChzYW1wbGVpbmZvKQpgYGAKCldlIGNhbiBsb29rIGF0IHRoZSBsYXN0IGZldyBsaW5lcyB3aXRoIGB0YWlsKClgLiBUaGlzIHNob3dzIHVzIHRoZSBsYXN0IDYgbGluZXMuIFRoaXMgY2FuIGJlIHVzZWZ1bCB0byBjaGVjayB0aGUgYm90dG9tIG9mIHRoZSBmaWxlLCB0aGF0IGl0IGxvb2tzIG9rLgpgYGB7cn0KdGFpbChzYW1wbGVpbmZvKQpgYGAKCk9yIHdlIGNhbiBzZWUgdGhlIHdob2xlIGZpbGUgd2l0aCBgVmlldygpYC4KCmBgYHtyIGV2YWw9RkFMU0V9ClZpZXcoc2FtcGxlaW5mbykKYGBgCgpJbiB0aGUgRW52aXJvbm1lbnQgdGFiIHdlIGNhbiBzZWUgaG93IG1hbnkgcm93cyBhbmQgY29sdW1ucyB0aGUgb2JqZWN0IGNvbnRhaW5zIGFuZCB3ZSBjYW4gY2xpY2sgb24gdGhlIGljb24gdG8gdmlldyBhbGwgdGhlIGNvbnRlbnRzIGluIGEgdGFiLiBUaGlzIHJ1bnMgdGhlIGNvbW1hbmQgVmlldygpIGZvciB1cy4KCldlIGNhbiBzZWUgYWxsIHRoZSBjb2x1bW4gbmFtZXMgd2l0aCBgY29sbmFtZXMoKWAuCmBgYHtyfQpjb2xuYW1lcyhzYW1wbGVpbmZvKQpgYGAKCldlIGNhbiBhY2Nlc3MgaW5kaXZpZHVhbCBjb2x1bW5zIGJ5IG5hbWUgdXNpbmcgdGhlIGAkYCBzeW1ib2wuIEZvciBleGFtcGxlIHdlIGNhbiBzZWUgd2hhdCdzIGNvbnRhaW5lZCBpbiBjb2x1bW4gWDEuCgpgYGB7cn0Kc2FtcGxlaW5mbyRYMQpgYGAKCklmIHdlIGp1c3Qgd2FudGVkIHRvIHNlZSB0aGUgZmlyc3QgMyB2YWx1ZXMgaW4gdGhlIGNvbHVtbiB3ZSBjYW4gc3BlY2lmeSB0aGlzIHVzaW5nIHNxdWFyZSBicmFja2V0cy4KCmBgYHtyfQpzYW1wbGVpbmZvJFgxWzE6M10KYGBgCgpPdGhlciB1c2VmdWwgY29tbWFuZHMgZm9yIGNoZWNraW5nIGRhdGEgYXJlIGBzdHIoKWAgYW5kIGBzdW1tYXJ5KClgLgoKYHN0cigpYCBzaG93cyB1cyB0aGUgc3RydWN0dXJlIG9mIG91ciBkYXRhLiBJdCBzaG93cyB1cyB3aGF0IGNvbHVtbnMgdGhlcmUgYXJlLCB0aGUgZmlyc3QgZmV3IGVudHJpZXMsIGFuZCB3aGF0IGRhdGEgdHlwZSB0aGV5IGFyZSBlLmcuIGNoYXJhY3RlciBvciBudW1iZXJzIChkb3VibGUgb3IgaW50ZWdlcikuCgpgYGB7cn0Kc3RyKHNhbXBsZWluZm8pCmBgYAoKYHN1bW1hcnkoKWAgZ2VuZXJhdGVzIHN1bW1hcnkgc3RhdGlzdGljcyBvZiBvdXIgZGF0YS4gRm9yIG51bWVyaWMgY29sdW1ucyAoY29sdW1ucyBvZiB0eXBlIGRvdWJsZSBvciBpbnRlZ2VyKSBpdCBvdXRwdXRzIHN0YXRpc3RpY3Mgc3VjaCBhcyB0aGUgbWluLCBtYXgsIG1lYW4gYW5kIG1lZGlhbi4gV2Ugd2lsbCBkZW1vbnN0cmF0ZSB0aGlzIHdpdGggdGhlIGNvdW50cyBmaWxlIGFzIGl0IGNvbnRhaW5zIG51bWVyaWMgZGF0YS4gRm9yIGNoYXJhY3RlciBjb2x1bW5zIGl0IHNob3dzIHVzIHRoZSBsZW5ndGggKGhvdyBtYW55IHJvd3MpLgoKYGBge3J9CnN1bW1hcnkoY291bnRzKQpgYGAKCgojIEZvcm1hdHRpbmcgdGhlIGRhdGEKCldlIHdpbGwgZmlyc3QgY29udmVydCB0aGUgZGF0YSBmcm9tIHdpZGUgZm9ybWF0IGludG8gbG9uZyBmb3JtYXQgdG8gbWFrZSBpdCBlYXNpZXIgdG8gd29yayB3aXRoIGFuZCBwbG90IHdpdGggZ2dwbG90LiBXZSB3YW50IGp1c3Qgb25lIGNvbHVtbiBjb250YWluaW5nIGFsbCB0aGUgZXhwcmVzc2lvbiB2YWx1ZXMgaW5zdGVhZCBvZiBtdWx0aXBsZSBjb2x1bW5zIHdpdGggY291bnRzIGZvciBlYWNoIHNhbXBsZSwgYXMgc2hvd24gaW4gdGhlIGltYWdlIGJlbG93LgoKIVtdKGltYWdlcy9yZXNoYXBlX2RhdGEucG5nKQoKV2UgY2FuIHVzZSBgZ2F0aGVyKClgIHRvIGVhc2lseSBjaGFuZ2UgdGhlIGZvcm1hdCBpbnRvIGxvbmcgZm9ybWF0LgoKYGBge3J9CnNlcWRhdGEgPC0gZ2F0aGVyKGNvdW50cywga2V5ID0gU2FtcGxlLCB2YWx1ZSA9IENvdW50LCBzdGFydHNfd2l0aCgiR1NNIikpCmBgYAoKV2UgdXNlIGBzdGFydHNfd2l0aCgiR1NNIilgIHRvIHRlbGwgZ2F0aGVyIHdlIHdhbnQgdG8gcmVmb3JtYXQgdGhlIGNvbHVtbnMgd2hvc2UgbmFtZXMgc3RhcnQgd2l0aCBHU00uIGBnYXRoZXIoKWAgd2lsbCB0aGVuIHJlZm9ybWF0IHRoZSBzcGVjaWZpZWQgY29sdW1ucyBpbnRvIHR3byBuZXcgY29sdW1ucywg4oCca2V54oCdIGFuZCDigJx2YWx1ZeKAnS4gVGhlIOKAnGtleeKAnSBjb2x1bW4gd2lsbCBjb250YWluIHRoZSBjb2x1bW4gbmFtZXMsIGFuZCB0aGUg4oCcdmFsdWXigJ0gY29sdW1uIHdpbGwgY29udGFpbiB0aGUgY29sdW1uIHZhbHVlcy4gV2UgaGF2ZSB0byB0ZWxsIGdhdGhlciB3aGF0IHdlIHdhbnQgdGhlIG5ldyBrZXkgYW5kIHZhbHVlIGNvbHVtbnMgdG8gYmUgY2FsbGVkLiBXZSB3aWxsIGdpdmUgdGhlIGtleSBjb2x1bW4gdGhlIG5hbWUgIlNhbXBsZSIgYW5kIHRoZSB2YWx1ZSBjb2x1bW4gdGhlIG5hbWUgIkNvdW50Ii4KCldlIGNvdWxkIGFsc28gc3BlY2lmeSBhIGNvbHVtbiByYW5nZSB0byByZWZvcm1hdC4gVGhlIGNvbW1hbmQgYmVsb3cgd291bGQgZ2l2ZSB1cyB0aGUgc2FtZSByZXN1bHQgYXMgdGhlIHByZXZpb3VzIGNvbW1hbmQuCmBgYHtyfQpzZXFkYXRhIDwtIGdhdGhlcihjb3VudHMsIGtleSA9IFNhbXBsZSwgdmFsdWUgPSBDb3VudCwgR1NNMTQ4MDI5MTpHU00xNDgwMzAyKQpgYGAKCkFsdGVybmF0aXZlbHksIHdlIGNvdWxkIHNwZWNpZnkgdGhlIGNvbHVtbnMgd2UgKmRvbid0KiB3YW50IHRvIHJlZm9ybWF0IGFuZCBnYXRoZXIgd2lsbCByZWZvcm1hdCBhbGwgdGhlIG90aGVyIGNvbHVtbnMuIFRvIGRvIHRoYXQgd2UgcHV0IGEgaHlwaGVuICItIiBpbiBmcm9udCBvZiB0aGUgY29sdW1uIG5hbWVzIHRoYXQgd2UgZG9uJ3Qgd2FudCB0byByZWZvcm1hdC4gVGhpcyBpcyBhIHByZXR0eSBjb21tb24gd2F5IHRvIHVzZSBgZ2F0aGVyKClgIGFzIHNvbWV0aW1lcyBpdCBpcyBlYXNpZXIgdG8gZG8gdGhhdC4gVGhlIGNvbW1hbmQgYmVsb3cgd291bGQgZ2l2ZSB1cyB0aGUgc2FtZSByZXN1bHQgYXMgdGhlIHByZXZpb3VzIGNvbW1hbmQuCgpgYGB7cn0Kc2VxZGF0YSA8LSBnYXRoZXIoY291bnRzLCBrZXkgPSBTYW1wbGUsIHZhbHVlID0gQ291bnQsIC1YMSwgLWdlbmVfc3ltYm9sKQpgYGAKCkxldCdzIGhhdmUgYSBsb29rIGF0IHRoZSBkYXRhLgpgYGB7cn0Kc2VxZGF0YQpgYGAKCk5vdyB0aGF0IHdlJ3ZlIGdvdCBqdXN0IG9uZSBjb2x1bW4gY29udGFpbmluZyBzYW1wbGUgaWRzIGluIGJvdGggb3VyIGNvdW50cyBmaWxlIGFuZCBvdXIgbWV0YWRhdGEgZmlsZXMgd2UgY2FuIGpvaW4gdGhlbSB0b2dldGhlciB1c2luZyB0aGUgc2FtcGxlIGlkcy4KCiFbXShpbWFnZXMvam9pbl9kYXRhLnBuZykKCldlIHdpbGwgdXNlIHRoZSBmdW5jdGlvbiBgZnVsbF9qb2luKClgIGFuZCBnaXZlIGl0IHRoZSB0d28gdGFibGVzIHdlIHdhbnQgdG8gam9pbi4gV2UgYWRkIGBieSA9IGMoIlNhbXBsZSIgPSAiWDEiKWAgdG8gc2F5IHdlIHdhbnQgdG8gam9pbiBvbiB0aGUgY29sdW1uIGNhbGxlZCAiU2FtcGxlIiIgaW4gdGhlIGZpcnN0IHRhYmxlIChgc2VxZGF0YWApIGFuZCB0aGUgY29sdW1uIGNhbGxlZCAiWDEiIGluIHRoZSBzZWNvbmQgdGFibGUgKGBzYW1wbGVpbmZvYCkKCmBgYHtyfQphbGxpbmZvIDwtIGZ1bGxfam9pbihzZXFkYXRhLCBzYW1wbGVpbmZvLCBieSA9IGMoIlNhbXBsZSIgPSAiWDEiKSkKYGBgCgpIZXJlIHdlIHNlZSB0aGUgZnVuY3Rpb24gYGMoKWAgZm9yIHRoZSBmaXJzdCB0aW1lLiBXZSB1c2UgdGhpcyBmdW5jdGlvbiBleHRyZW1lbHkgb2Z0ZW4gaW4gUiB3aGVuIHdlIGhhdmUgbXVsdGlwbGUgaXRlbXMgdGhhdCB3ZSBhcmUgKmNvbWJpbmluZyouIFdlIHdpbGwgc2VlIGl0IGFnYWluIGluIHRoaXMgdHV0b3JpYWwuCgpMZXQncyBoYXZlIGEgbG9vayBhdCB0aGUgZGF0YS4KYGBge3J9CmFsbGluZm8KYGBgCgpUaGUgdHdvIHRhYmxlcyBoYXZlIGJlZW4gam9pbmVkLgoKIyBQbG90dGluZyB3aXRoICoqYGdncGxvdDJgKioKCioqYGdncGxvdDJgKiogaXMgYSBwbG90dGluZyBwYWNrYWdlIHRoYXQgbWFrZXMgaXQgc2ltcGxlIHRvIGNyZWF0ZSBjb21wbGV4IHBsb3RzLiBPbmUgcmVhbGx5IGdyZWF0IGJlbmVmaXQgb2YgZ2dwbG90MiB2ZXJzdXMgdGhlIG9sZGVyIGJhc2UgUiBwbG90dGluZyBpcyB0aGF0IHdlIG9ubHkgbmVlZCB0byBtYWtlIG1pbmltYWwgY2hhbmdlcyBpZiB0aGUgdW5kZXJseWluZyBkYXRhIGNoYW5nZSBvciBpZiB3ZSBkZWNpZGUgdG8gY2hhbmdlIG91ciBwbG90IHR5cGUsIGZvciBleGFtcGxlLCBmcm9tIGEgYm94IHBsb3QgdG8gYSB2aW9saW4gcGxvdC4gVGhpcyBoZWxwcyBpbiBjcmVhdGluZyBwdWJsaWNhdGlvbiBxdWFsaXR5IHBsb3RzIHdpdGggbWluaW1hbCBhbW91bnRzIG9mIGFkanVzdG1lbnRzIGFuZCB0d2Vha2luZy4KCioqYGdncGxvdDJgKiogbGlrZXMgZGF0YSBpbiB0aGUgJ2xvbmcnIGZvcm1hdCwgaS5lLiwgYSBjb2x1bW4gZm9yIGV2ZXJ5IHZhcmlhYmxlLCBhbmQgYSByb3cgZm9yIGV2ZXJ5IG9ic2VydmF0aW9uLCBzaW1pbGFyIHRvIHdoYXQgd2UgY3JlYXRlZCB3aXRoIGBnYXRoZXIoKWAuIFdlbGwtc3RydWN0dXJlZCBkYXRhIHdpbGwgc2F2ZSB5b3UgbG90cyBvZiB0aW1lIHdoZW4gbWFraW5nIGZpZ3VyZXMgd2l0aCAqKmBnZ3Bsb3QyYCoqLgoKQXMgd2Ugc2hhbGwgc2VlLCBnZ3Bsb3QgZ3JhcGhpY3MgYXJlIGJ1aWx0IHN0ZXAgYnkgc3RlcCBieSBhZGRpbmcgbmV3IGVsZW1lbnRzIHVzaW5nIHRoZSBgK2AuIEFkZGluZyBsYXllcnMgaW4gdGhpcyBmYXNoaW9uIGFsbG93cyBmb3IgZXh0ZW5zaXZlIGZsZXhpYmlsaXR5IGFuZCBjdXN0b21pemF0aW9uIG9mIHBsb3RzLgoKVG8gYnVpbGQgYSBnZ3Bsb3QsIHdlIHVzZSB0aGUgZm9sbG93aW5nIGJhc2ljIHRlbXBsYXRlIHRoYXQgY2FuIGJlIHVzZWQgZm9yIGRpZmZlcmVudCB0eXBlcyBvZiBwbG90cy4gVGhyZWUgdGhpbmdzIGFyZSByZXF1aXJlZCBmb3IgYSBnZ3Bsb3Q6CgohW10oaW1hZ2VzL2dncGxvdF90ZW1wbGF0ZS5wbmcpCgoxLiBUaGUgZGF0YQoyLiBUaGUgY29sdW1ucyBpbiB0aGUgZGF0YSB3ZSB3YW50IHRvIG1hcCB0byB2aXN1YWwgcHJvcGVydGllcyAoY2FsbGVkIGFlc3RoZXRpY3Mgb3IgYWVzIGluIGdncGxvdDIpIGUuZy4gdGhlIGNvbHVtbnMgZm9yIHggdmFsdWVzLCB5IHZhbHVlcyBhbmQgY29sb3VycwozLiBUaGUgdHlwZSBvZiBwbG90ICh0aGUgZ2VvbV8pCgpUaGVyZSBhcmUgZGlmZmVyZW50IGdlb21zIHdlIGNhbiB1c2UgdG8gY3JlYXRlIGRpZmZlcmVudCB0eXBlcyBvZiBwbG90IGUuZy4gYGdlb21fbGluZSgpYCBgZ2VvbV9wb2ludCgpYCwgYGdlb21fYm94cGxvdCgpYC4gVG8gc2VlIHRoZSBnZW9tcyBhdmFpbGFibGUgdGFrZSBhIGxvb2sgYXQgdGhlIGdncGxvdDIgaGVscCBvciB0aGUgaGFuZHkgW2dncGxvdDIgY2hlYXRzaGVldF0oaHR0cHM6Ly9naXRodWIuY29tL3JzdHVkaW8vY2hlYXRzaGVldHMvcmF3L21hc3Rlci9kYXRhLXZpc3VhbGl6YXRpb24tMi4xLnBkZikuIE9yIGlmIHlvdSB0eXBlICJnZW9tIiBpbiBSU3R1ZGlvLCBSU3R1ZGlvIHdpbGwgc2hvdyB5b3UgdGhlIGRpZmZlcmVudCB0eXBlcyBvZiBnZW9tcyB5b3UgY2FuIHVzZS4KCldlIGNhbiBtYWtlIGJveHBsb3RzIHRvIHZpc3VhbGlzZSB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBjb3VudHMgZm9yIGVhY2ggc2FtcGxlLiBUaGlzIGhlbHBzIHVzIHRvIGNvbXBhcmUgdGhlIHNhbXBsZXMgYW5kIGNoZWNrIGlmIGFueSBsb29rIHVudXN1YWwuICoqTm90ZSB0aGF0IHdpdGggZ2dwbG90IHRoZSAiKyIgbXVzdCBnbyBhdCB0aGUgZW5kIG9mIHRoZSBsaW5lLCBpdCBjYW4ndCBnbyBhdCB0aGUgYmVnaW5uaW5nLioqCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGxpbmZvLCBtYXBwaW5nID0gYWVzKHggPSBTYW1wbGUsIHkgPSBDb3VudCkpICsgCiAgZ2VvbV9ib3hwbG90KCkKYGBgCgpXZSBoYXZlIGdlbmVyYXRlZCBvdXIgZmlyc3QgcGxvdCEKCkJ1dCBpdCBsb29rcyBhIGJpdCB3ZWlyZC4gSXQncyBiZWNhdXNlIHdlIGhhdmUgc29tZSBnZW5lcyB3aXRoIGV4dHJlbWVseSBoaWdoIGNvdW50cy4gVG8gbWFrZSBpdCBlYXNpZXIgdG8gdmlzdWFsaXNlIHRoZSBkaXN0cmlidXRpb25zIHdlIHVzdWFsbHkgcGxvdCB0aGUgbG9nYXJpdGhtIG9mIFJOQS1zZXEgY291bnRzLiBXZSdsbCBwbG90IHRoZSBTYW1wbGUgb24gdGhlIFggYXhpcyBhbmQgbG9nfiAyfiAgQ291bnRzIG9uIHRoZSB5IGF4aXMuIFdlIGNhbiBsb2cgdGhlIENvdW50cyB3aXRoaW4gdGhlIGBhZXMoKWAuIFRoZSBzYW1wbGUgbGFiZWxzIGFyZSBhbHNvIG92ZXJsYXBwaW5nIGVhY2ggb3RoZXIsIHdlIHdpbGwgc2hvdyBob3cgdG8gZml4IHRoaXMgbGF0ZXIuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGxpbmZvLCBtYXBwaW5nID0gYWVzKHggPSBTYW1wbGUsIHkgPSBsb2cyKENvdW50KSkpICsgCiAgZ2VvbV9ib3hwbG90KCkKYGBgCgpOb3RlIHRoYXQgd2UgZ2V0IGEgd2FybmluZyBoZXJlIGFib3V0IHJvd3MgY29udGFpbmluZyBub24tZmluaXRlIHZhbHVlcyBiZWluZyByZW1vdmVkLiBUaGlzIGlzIGJlY2F1c2Ugc29tZSBvZiB0aGUgZ2VuZXMgaGF2ZSBhIGNvdW50IG9mIHplcm8gaW4gdGhlIHNhbXBsZXMgYW5kIGEgbG9nIG9mIHplcm8gaXMgdW5kZWZpbmVkLiBXZSBjYW4gYWRkIGEgc21hbGwgbnVtYmVyIHRvIGV2ZXJ5IGNvdW50IHRvIGF2b2lkIHRoZSB6ZXJvcyBiZWluZyBkcm9wcGVkLgoKYGBge3J9CmdncGxvdChkYXRhID0gYWxsaW5mbywgbWFwcGluZyA9IGFlcyh4ID0gU2FtcGxlLCB5ID0gbG9nMihDb3VudCArIDEpKSkgKyAKICBnZW9tX2JveHBsb3QoKQpgYGAKClRoZSBib3ggcGxvdHMgc2hvdyB0aGF0IHRoZSBkaXN0cmlidXRpb25zIG9mIHRoZSBzYW1wbGVzIGFyZSBub3QgaWRlbnRpY2FsIGJ1dCB0aGV5IGFyZSBub3QgdmVyeSBkaWZmZXJlbnQuCgpCb3ggcGxvdHMgYXJlIHVzZWZ1bCBzdW1tYXJpZXMsIGJ1dCBoaWRlIHRoZSBzaGFwZSBvZiB0aGUgZGlzdHJpYnV0aW9uLiBGb3IgZXhhbXBsZSwgaWYgdGhlIGRpc3RyaWJ1dGlvbiBpcyBiaW1vZGFsLCB3ZSB3b3VsZCBub3Qgc2VlIGl0IGluIGEgYm94cGxvdC4gQW4gYWx0ZXJuYXRpdmUgdG8gdGhlIGJveHBsb3QgaXMgdGhlICoqdmlvbGluIHBsb3QqKiwgd2hlcmUgdGhlIHNoYXBlIChvZiB0aGUgZGVuc2l0eSBvZiBwb2ludHMpIGlzIGRyYXduLiBTZWUgW2hlcmVdKGh0dHBzOi8vYmxvZy5iaW90dXJpbmcuY29tLzIwMTgvMDUvMTYvNS1yZWFzb25zLXlvdS1zaG91bGQtdXNlLWEtdmlvbGluLWdyYXBoLykgZm9yIGFuIGV4YW1wbGUgb2YgaG93IGRpZmZlcmVuY2VzIGluIGRpc3RyaWJ1dGlvbiBtYXkgYmUgaGlkZGVuIGluIGJveCBwbG90cyBidXQgcmV2ZWFsZWQgd2l0aCB2aW9saW4gcGxvdHMuIFdlIGNvdWxkIGFsc28gbWFrZSBqaXR0ZXIgcGxvdHMuIEEgKipqaXR0ZXIgcGxvdCoqIGlzIHNpbWlsYXIgdG8gYSBzY2F0dGVyIHBsb3QuIEl0IGFkZHMgYSBzbWFsbCBhbW91bnQgb2YgcmFuZG9tIHZhcmlhdGlvbiB0byB0aGUgbG9jYXRpb24gb2YgZWFjaCBwb2ludCBzbyB0aGV5IGRvbuKAmXQgb3ZlcmxhcC4gVGhlcmUgYXJlIHRvbyBtYW55IHBvaW50cyBpbiB0aGlzIGNhc2UgZm9yIHRoZSBqaXR0ZXIgcGxvdHMgdG8gYmUgdXNlZnVsIGJ1dCB0aGlzIGlzIGp1c3QgdG8gZGVtb25zdHJhdGUsIGFzIFtqaXR0ZXIgd2l0aCBhbmQgd2l0aG91dCBib3hwbG90XShodHRwczovL3NpbXBseXN0YXRpc3RpY3Mub3JnLzIwMTkvMDIvMjEvZHluYW1pdGUtcGxvdHMtbXVzdC1kaWUvKSBpcyBhIGNvbW1vbmx5IHVzZWQgZ2dwbG90IHR5cGUuIFdlIHdpbGwgYWxzbyBtYWtlIHVzZSBvZiBqaXR0ZXIgcGxvdHMgbGF0ZXIuCgojIyMjIEV4ZXJjaXNlIApZb3UgY2FuIGVhc2lseSBtYWtlIGRpZmZlcmVudCB0eXBlcyBvZiBwbG90cyB3aXRoIGdncGxvdCBieSB1c2luZyBkaWZmZXJlbnQgZ2VvbXMuIFVzaW5nIHRoZSBzYW1lIGRhdGEgKHNhbWUgeCBhbmQgeSB2YWx1ZXMpLCB0cnkgZWRpdGluZyB0aGUgY29kZSBhYm92ZSB0byBtYWtlIHRoZSBwbG90cyBsaXN0ZWQgaW4gMS4gMi4gYW5kIDMuCgoxLiBNYWtlIGEgdmlvbGluIHBsb3QgKGdlb21fdmlvbGluKQoyLiBNYWtlIGEgaml0dGVyIHBsb3QgKGdlb21faml0dGVyKQozLiBNYWtlIGEgYm94cGxvdCB3aXRoIGEgaml0dGVyIHBsb3Qgb3ZlcmxhaWQgKEhpbnQ6IHlvdSBjYW4gYWRkIG11bHRpcGxlIGdlb21zIHdpdGggKyApCgpXaGF0IGlmIHdlIHdvdWxkIGxpa2UgdG8gYWRkIHNvbWUgY29sb3VyIHRvIHRoZSBwbG90LCBmb3IgZXhhbXBsZSwgYSBkaWZmZXJlbnQgY29sb3VyIGZvciBlYWNoIHNhbXBsZS4gCgpJZiB3ZSBsb29rIGF0IHRoZSBgZ2VvbV9ib3hwbG90YCBoZWxwIHdlIGNhbiBzZWUgdW5kZXIgdGhlIGhlYWRpbmcgY2FsbGVkICJBZXN0aGV0aWNzIiB0aGF0IHRoZXJlJ3MgYW4gb3B0aW9uIGZvciBjb2xvdXIuIExldCdzIHRyeSBhZGRpbmcgdGhhdCB0byBvdXIgcGxvdC4gV2UnbGwgc3BlY2lmeSB3ZSB3YW50IHRvIG1hcCB0aGUgU2FtcGxlIGNvbHVtbiB0byBgY29sb3VyID0gYC4gQXMgd2UgYXJlIG1hcHBpbmcgY29sb3VyIHRvIGEgY29sdW1uIGluIG91ciBkYXRhIHdlIG5lZWQgdG8gcHV0IHRoaXMgaW5zaWRlIHRoZSBgYWVzKClgLgoKYGBge3J9CmdncGxvdChkYXRhID0gYWxsaW5mbywgbWFwcGluZyA9IGFlcyh4ID0gU2FtcGxlLCB5ID0gbG9nMihDb3VudCArIDEpLCBjb2xvdXIgPSBTYW1wbGUpKSArIAogIGdlb21fYm94cGxvdCgpCmBgYAoKQ29sb3VyaW5nIHRoZSBlZGdlcyB3YXNu4oCZdCBxdWl0ZSB3aGF0IHdlIGhhZCBpbiBtaW5kLiBMb29rIGF0IHRoZSBoZWxwIGZvciBgZ2VvbV9ib3hwbG90YCB0byBzZWUgd2hhdCBvdGhlciBhZXN0aGV0aWMgd2UgY291bGQgdXNlLiBMZXQncyB0cnkgYGZpbGwgPSBgIGluc3RlYWQuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGxpbmZvLCBtYXBwaW5nID0gYWVzKHggPSBTYW1wbGUsIHkgPSBsb2cyKENvdW50ICsgMSksIGZpbGwgPSBTYW1wbGUpKSArIAogIGdlb21fYm94cGxvdCgpCmBgYAoKVGhhdCBsb29rcyBiZXR0ZXIuIGBmaWxsID0gYCBpcyB1c2VkIHRvICoqZmlsbCoqIGluIGFyZWFzIGluIGdncGxvdDIgcGxvdHMsIHdoZXJlYXMgYGNvbG91ciA9IGAgaXMgdXNlZCB0byBjb2xvdXIgbGluZXMgYW5kIHBvaW50cy4KCkEgcmVhbGx5IG5pY2UgZmVhdHVyZSBhYm91dCBnZ3Bsb3QgaXMgdGhhdCB3ZSBjYW4gZWFzaWx5IGNvbG91ciBieSBhbm90aGVyIHZhcmlhYmxlIGJ5IHNpbXBseSBjaGFuZ2luZyB0aGUgY29sdW1uIHdlIGdpdmUgdG8gYGZpbGwgPSBgLgoKIyMjIyBFeGVyY2lzZSAKTW9kaWZ5IHRoZSBwbG90IGFib3ZlLiBDb2xvdXIgYnkgb3RoZXIgdmFyaWFibGVzIChjb2x1bW5zKSBpbiB0aGUgbWV0YWRhdGEgZmlsZToKCjEuIGNoYXJhY3RlcmlzdGljcwoyLiBpbW11bm9waGVub3R5cGUKMy4gXGBkZXZlbG9wbWVudGFsIHN0YWdlXGAgKEFzIHRoZXJlIGlzIGEgc3BhY2UgaW4gdGhlIGNvbHVtbiBuYW1lIHdlIG5lZWQgdG8gdXNlIGJhY2t0aWNrcyBhcm91bmQgdGhlIG5hbWUgKFxgXGApLiBOb3RlIHRoYXQgYmFja3RpY2tzIGFyZSBub3Qgc2luZ2xlIHF1b3RlcyAoXCdcJykuIFRoZSBiYWNrdGljayBidXR0b24gaXMgdXN1YWxseSBhdCB0aGUgdG9wIGxlZnQgY29ybmVyIG9mIGEgbGFwdG9wIGtleWJvYXJkIHVuZGVyIHRoZSBFU0MgYnV0dG9uLiBDaGVjayB3aGF0IGhhcHBlbnMgaWYgeW91IGRvbid0IHVzZSBiYWNrdGlja3MuKQoKCiMgTWFrZSBzdWJwbG90cyBmb3IgZWFjaCBnZW5lCgpXaXRoIGdncGxvdCB3ZSBjYW4gZWFzaWx5IG1ha2Ugc3VicGxvdHMgdXNpbmcgKmZhY2V0aW5nKi4gRm9yIGV4YW1wbGUgd2UgY2FuIG1ha2Ugc3RyaXBjaGFydHMsIHBsb3R0aW5nIGV4cHJlc3Npb24gYnkgdGhlIGdyb3VwcyAoYmFzYWwgdmlyZ2luLCBiYXNhbCBwcmVnbmFudCwgYmFzYWwgbGFjdGF0aW5nLCBsdW1pbmFsIHZpcmdpbiwgbHVtaW5hbCBwcmVnbmFudCwgbHVtaW5hbCBsYWN0YXRpbmcpIGZvciBlYWNoIGdlbmUuIAoKRmlyc3Qgd2UnbGwgdXNlIGBtdXRhdGUoKWAgdG8gYWRkIGEgY29sdW1uIHdpdGggc2hvcnRlciBncm91cCBuYW1lcyB0byB1c2UgaW4gdGhlIHBsb3QsIGFzIHRoZSBncm91cCBuYW1lcyBpbiB0aGUgY2hhcmFjdGVyaXN0aWNzIGNvbHVtbiBhcmUgcXVpdGUgbG9uZy4KCmBgYHtyfQogYWxsaW5mbyA8LSBtdXRhdGUoYWxsaW5mbywgR3JvdXAgPSBjYXNlX3doZW4oICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgIHN0cl9kZXRlY3QoY2hhcmFjdGVyaXN0aWNzLCAiYmFzYWwuKnZpcmdpbiIpIH4gICJidmlyZyIsCiAgICAgICAgc3RyX2RldGVjdChjaGFyYWN0ZXJpc3RpY3MsICJiYXNhbC4qcHJlZyIpICB+ICAiYnByZWciLAogICAgICAgIHN0cl9kZXRlY3QoY2hhcmFjdGVyaXN0aWNzLCAiYmFzYWwuKmxhY3QiKSAgfiAgImJsYWN0IiwKICAgICAgICBzdHJfZGV0ZWN0KGNoYXJhY3RlcmlzdGljcywgImx1bWluYWwuKnZpcmdpbiIpICB+ICAibHZpcmciLAogICAgICAgIHN0cl9kZXRlY3QoY2hhcmFjdGVyaXN0aWNzLCAibHVtaW5hbC4qcHJlZyIpICB+ICAibHByZWciLAogICAgICAgIHN0cl9kZXRlY3QoY2hhcmFjdGVyaXN0aWNzLCAibHVtaW5hbC4qbGFjdCIpICB+ICAibGxhY3QiCiAgICAgICApKQpgYGAKCkhhdmUgYSBsb29rIGF0IHRoaXMgZGF0YSB1c2luZyBgaGVhZCgpYC4gWW91IHNob3VsZCBzZWUgYSBuZXcgY29sdW1uIGNhbGxlZCBgR3JvdXBgIGhhcyBiZWVuIGFkZGVkIHRvIHRoZSBlbmQuCgpgYGB7cn0KaGVhZChhbGxpbmZvKQpgYGAKCldlIGNhbiBtYWtlIHBsb3RzIGZvciBhIHNldCBvZiBnZW5lcy4KCmBgYHtyfQpteWdlbmVzIDwtIGMoIkNzbjFzMmEiLCAiQ3NuMXMxIiwgIkNzbjIiLCAiR2x5Y2FtMSIsICJDT1gxIiwgIlRyZiIsICJXYXAiLCAiRWVmMWExIikKYGBgCgo+ICMjIyMgTm90ZSBvbiBzcGVjaWZ5aW5nIGdlbmVzCj4gVGhpcyBleGFtcGxlIGlzIHRvIGRlbW9uc3RyYXRlIGhvdyB3ZSBjb3VsZCBzcGVjaWZ5IGFueSBnZW5lcyBpbiB0aGUgZGF0YSB0byBwbG90LiBUaGUgZ2VuZXMgdXNlZCBoZXJlIHdlcmUgdGhlIDggZ2VuZXMgd2l0aCB0aGUgaGlnaGVzdCBjb3VudHMgc3VtbWVkIGFjcm9zcyBhbGwgc2FtcGxlcy4gVGhlIGNvbW1hbmQgZm9yIGhvdyB0byBnZXQgdGhlIGdlbmUgc3ltYm9scyBmb3IgdGhlc2UgOCBnZW5lcyBpcyBzaG93biBiZWxvdy4gIAo+YWxsaW5mbyAlPiUgIAo+ICBncm91cF9ieShnZW5lX3N5bWJvbCkgJT4lICAKPiAgc3VtbWFyaXNlKFRvdGFsX2NvdW50ID0gc3VtKENvdW50KSkgJT4lICAKPiAgYXJyYW5nZShkZXNjKFRvdGFsX2NvdW50KSkgJT4lICAKPiAgaGVhZChuID0gOCkgJT4lICAKPiAgcHVsbChnZW5lX3N5bWJvbCkgCgpXZSBmaWx0ZXIgb3VyIGRhdGEgZm9yIGp1c3QgdGhlc2UgZ2VuZXMgb2YgaW50ZXJlc3QuIFdlIHVzZSAlaW4lIHRvIGNoZWNrIGlmIGEgdmFsdWUgaXMgaW4gYSBzZXQgb2YgdmFsdWVzLgoKYGBge3J9Cm15Z2VuZXNfY291bnRzIDwtIGZpbHRlcihhbGxpbmZvLCBnZW5lX3N5bWJvbCAlaW4lIG15Z2VuZXMpCmBgYAoKV2UgY2FuIG1ha2UgYm94cGxvdHMgZm9yIGp1c3QgdGhlc2UgZ2VuZXMuIFdlICpmYWNldCogb24gdGhlIGBnZW5lX3N5bWJvbGAgY29sdW1uIHVzaW5nIGBmYWNldF93cmFwKClgLiBXZSBhZGQgdGhlIHRpbGRlIHN5bWJvbCBgfiBgIGluIGZyb250IG9mIHRoZSBjb2x1bW4gd2Ugd2FudCB0byBmYWNldCBvbi4gCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBteWdlbmVzX2NvdW50cywgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXAsIHkgPSBsb2cyKENvdW50ICsgMSksIGZpbGwgPSBHcm91cCkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgZmFjZXRfd3JhcCh+IGdlbmVfc3ltYm9sKQpgYGAKClRoZSBib3hwbG90cyBkb24ndCBsb29rIGdvb2QgYXMgd2Ugb25seSBoYXZlIHR3byB2YWx1ZXMgcGVyIGdyb3VwLiBXZSBjb3VsZCBqdXN0IHBsb3QgdGhlIGluZGl2aWR1YWwgcG9pbnRzIGluc3RlYWQuIFdlIGNvdWxkIHVzZSAKYGdlb21fcG9pbnQoKWAgdG8gbWFrZSBhIHNjYXR0ZXJwbG90LgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBteWdlbmVzX2NvdW50cywgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXAsIHkgPSBsb2cyKENvdW50ICsgMSkpKSArCiAgZ2VvbV9wb2ludCgpICsKICBmYWNldF93cmFwKH4gZ2VuZV9zeW1ib2wpCmBgYAoKVGhlIHBvaW50cyBhcmUgb3ZlcmxhcHBpbmcgc28gd2Ugd2lsbCB1c2UgYGdlb21faml0dGVyKClgIHdoaWNoIGFkZHMgYSBzbWFsbCBhbW91bnQgb2YgcmFuZG9tIHZhcmlhdGlvbiB0byB0aGUgcG9pbnRzLgoKYGBge3J9CmdncGxvdChkYXRhID0gbXlnZW5lc19jb3VudHMsIG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLCB5ID0gbG9nMihDb3VudCArIDEpKSkgKwogIGdlb21faml0dGVyKCkgKwogIGZhY2V0X3dyYXAofiBnZW5lX3N5bWJvbCkKYGBgCgpXZSBjYW4gY29sb3VyIHRoZSBncm91cHMgc2ltaWxhciB0byBiZWZvcmUgdXNpbmcgYGNvbG91ciA9IGAuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBteWdlbmVzX2NvdW50cywgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXAsIHkgPSBsb2cyKENvdW50ICsgMSksIGNvbG91ciA9IEdyb3VwKSkgKwogIGdlb21faml0dGVyKCkgKwogIGZhY2V0X3dyYXAofiBnZW5lX3N5bWJvbCkgCmBgYAoKIyBDdXN0b21pc2luZyB0aGUgcGxvdAoKIyMjIFNwZWNpZnlpbmcgY29sb3VycwoKV2UgbWlnaHQgd2FudCB0byBjaGFuZ2UgdGhlIGNvbG91cnMuIFRvIHNlZSB3aGF0IGNvbG91ciBuYW1lcyBhcmUgYXZhaWxhYmxlIHlvdSBjYW4gdHlwZSBgY29sb3VycygpYC4gVGhlcmUgaXMgYWxzbyBhbiBbUiBjb2xvdXJzIGNoZWF0c2hlZXRdKGh0dHBzOi8vd3d3Lm5jZWFzLnVjc2IuZWR1L34gZnJhemllci9SU3BhdGlhbEd1aWRlcy9jb2xvclBhbGV0dGVDaGVhdHNoZWV0LnBkZikgdGhhdCBzaG93cyB3aGF0IHRoZSBjb2xvdXJzIGxvb2sgbGlrZS4KYGBge3J9Cm15Y29sb3VycyA8LSBjKCJ0dXJxdW9pc2UiLCAicGx1bSIsICJ0b21hdG8iLCAidmlvbGV0IiwgInN0ZWVsYmx1ZSIsICJjaG9jb2xhdGUiKQpgYGAKClRoZW4gd2UgdGhlbiBhZGQgdGhlc2UgY29sb3VycyB0byB0aGUgcGxvdCB1c2luZyBhIGArYCBhbmQgYHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gbXljb2xvdXJzKWAuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBteWdlbmVzX2NvdW50cywgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXAsIHkgPSBsb2cyKENvdW50ICsgMSksIGNvbG91ciA9IEdyb3VwKSkgKwogIGdlb21faml0dGVyKCkgKwogIGZhY2V0X3dyYXAofiBnZW5lX3N5bWJvbCkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gbXljb2xvdXJzKQpgYGAKClRoZXJlIGFyZSBidWlsdC1pbiBjb2xvdXIgcGFsZXR0ZXMgdGhhdCBjYW4gYmUgaGFuZHkgdG8gdXNlLCB3aGVyZSB0aGUgc2V0cyBvZiBjb2xvdXJzIGFyZSBwcmVkZWZpbmVkLiBgc2NhbGVfY29sb3VyX2JyZXdlcigpYCBpcyBhIHBvcHVsYXIgb25lICh0aGVyZSBpcyBhbHNvIGBzY2FsZV9maWxsX2JyZXdlcigpYCkuIFlvdSBjYW4gdGFrZSBhIGxvb2sgYXQgdGhlIGhlbHAgZm9yIGBzY2FsZV9jb2xvdXJfYnJld2VyKClgIHRvIHNlZSB3aGF0IHBhbGV0dGVzIGFyZSBhdmFpbGFibGUuIFRoZSBbUiBjb2xvdXJzIGNoZWF0c2hlZXRdKGh0dHBzOi8vd3d3Lm5jZWFzLnVjc2IuZWR1L34gZnJhemllci9SU3BhdGlhbEd1aWRlcy9jb2xvclBhbGV0dGVDaGVhdHNoZWV0LnBkZikgYWxzbyBzaG93cyB3aGF0IHRoZSBjb2xvdXJzIG9mIHRoZSBwYWxldHRlcyBsb29rIGxpa2UuIFRoZXJlJ3Mgb25lIGNhbGxlZCAiRGFyazIiLCBsZXQncyBoYXZlIGEgbG9vayBhdCB0aGF0LiAKCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IG15Z2VuZXNfY291bnRzLCBtYXBwaW5nID0gYWVzKHggPSBHcm91cCwgeSA9IGxvZzIoQ291bnQgKyAxKSwgY29sb3VyID0gR3JvdXApKSArCiAgZ2VvbV9qaXR0ZXIoKSArCiAgZmFjZXRfd3JhcCh+IGdlbmVfc3ltYm9sKSArCiAgc2NhbGVfY29sb3VyX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikKYGBgCgoKIyMjIyBFeGVyY2lzZQpNYWtlIGEgY29sb3VyYmxpbmQgZnJpZW5kbHkgcGxvdC4gSGludCB0aGVyZSBhcmUgY29sb3VyYmxpbmQgZnJpZW5kbHkgcGFsZXR0ZXMgW2hlcmVdKGh0dHA6Ly93d3cuY29va2Jvb2stci5jb20vR3JhcGhzL0NvbG9yc18oZ2dwbG90MikvI2EtY29sb3JibGluZC1mcmllbmRseS1wYWxldHRlKQoKIyMjIEF4aXMgbGFiZWxzIGFuZCBUaXRsZQoKV2UgY2FuIGNoYW5nZSB0aGUgYXhpcyBsYWJlbHMgYW5kIGFkZCBhIHRpdGxlIHdpdGggYGxhYnMoKWAuIFRvIGNoYW5nZSB0aGUgeCBheGlzIGxhYmVsIHdlIHVzZSBgbGFicyh4ID0gIk5ldyBuYW1lIilgLiBUbyBjaGFuZ2UgdGhlIHkgYXhpcyBsYWJlbCB3ZSB1c2UgYGxhYnMoeSA9ICJOZXcgbmFtZSIpYCBvciB3ZSBjYW4gY2hhbmdlIHRoZW0gYWxsIGF0IHRoZSBzYW1lIHRpbWUuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBteWdlbmVzX2NvdW50cywgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXAsIHkgPSBsb2cyKENvdW50ICsgMSksIGNvbG91ciA9IEdyb3VwKSkgKwogIGdlb21faml0dGVyKCkgKwogIGZhY2V0X3dyYXAofiBnZW5lX3N5bWJvbCkgKyAKICBsYWJzKHggPSAiQ2VsbCB0eXBlIGFuZCBzdGFnZSIsIHkgPSAiQ291bnQiLCB0aXRsZSA9ICJNYW1tYXJ5IGdsYW5kIFJOQS1zZXEgZGF0YSIpCmBgYAoKIyMjIFRoZW1lcwoKV2UgY2FuIGFkanVzdCB0aGUgdGV4dCBvbiB0aGUgeCBheGlzICh0aGUgZ3JvdXAgbGFiZWxzKSBieSB0dXJuaW5nIHRoZW0gOTAgZGVncmVlcyBzbyB3ZSBjYW4gcmVhZCB0aGUgbGFiZWxzIGJldHRlci4gVG8gZG8gdGhpcyB3ZSBtb2RpZnkgdGhlIGdncGxvdCB0aGVtZS4gVGhlbWVzIGFyZSB0aGUgbm9uLWRhdGEgcGFydHMgb2YgdGhlIHBsb3QuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBteWdlbmVzX2NvdW50cywgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXAsIHkgPSBsb2cyKENvdW50ICsgMSksIGNvbG91ciA9IEdyb3VwKSkgKwogIGdlb21faml0dGVyKCkgKwogIGZhY2V0X3dyYXAofiBnZW5lX3N5bWJvbCkgKyAKICBsYWJzKHggPSAiQ2VsbCB0eXBlIGFuZCBzdGFnZSIsIHkgPSAiQ291bnQiLCB0aXRsZSA9ICJNYW1tYXJ5IGdsYW5kIFJOQS1zZXEgZGF0YSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKYGBgCgpXZSBjYW4gcmVtb3ZlIHRoZSBncmV5IGJhY2tncm91bmQgYW5kIGdyaWQgbGluZXMuCgpUaGVyZSBhcmUgYWxzbyBhIGxvdCBvZiBidWlsdC1pbiB0aGVtZXMuIExldCdzIGhhdmUgYSBsb29rIGF0IGEgY291cGxlIG9mIHRoZSBtb3JlIHdpZGVseSB1c2VkIHRoZW1lcy4gVGhlIGRlZmF1bHQgZ2dwbG90IHRoZW1lIGlzIGB0aGVtZV9ncmV5KCkuYAoKYGBge3J9CmdncGxvdChkYXRhID0gbXlnZW5lc19jb3VudHMsIG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLCB5ID0gbG9nMihDb3VudCArIDEpLCBjb2xvdXIgPSBHcm91cCkpICsKICBnZW9tX2ppdHRlcigpICsKICBmYWNldF93cmFwKH4gZ2VuZV9zeW1ib2wpICsgCiAgbGFicyh4ID0gIkNlbGwgdHlwZSBhbmQgc3RhZ2UiLCB5ID0gIkNvdW50IiwgdGl0bGUgPSAiTWFtbWFyeSBnbGFuZCBSTkEtc2VxIGRhdGEiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCmBgYAoKYGBge3J9CmdncGxvdChkYXRhID0gbXlnZW5lc19jb3VudHMsIG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLCB5ID0gbG9nMihDb3VudCArIDEpLCBjb2xvdXIgPSBHcm91cCkpICsKICBnZW9tX2ppdHRlcigpICsKICBmYWNldF93cmFwKH4gZ2VuZV9zeW1ib2wpICsgCiAgbGFicyh4ID0gIkNlbGwgdHlwZSBhbmQgc3RhZ2UiLCB5ID0gIkNvdW50IiwgdGl0bGUgPSAiTWFtbWFyeSBnbGFuZCBSTkEtc2VxIGRhdGEiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKYGBgCgpUaGVyZSBhcmUgbWFueSB0aGVtZXMgYXZhaWxhYmxlLCB5b3UgY2FuIHNlZSBzb21lIGluIHRoZSBbUiBncmFwaCBnYWxsZXJ5XShodHRwczovL3d3dy5yLWdyYXBoLWdhbGxlcnkuY29tLzE5Mi1nZ3Bsb3QtdGhlbWVzLykuCgpXZSBjYW4gYWxzbyBtb2RpZnkgcGFydHMgb2YgdGhlIHRoZW1lIGluZGl2aWR1YWxseS4gV2UgY2FuIHJlbW92ZSB0aGUgZ3JleSBiYWNrZ3JvdW5kIGFuZCBncmlkIGxpbmVzIHdpdGggdGhlIGNvZGUgYmVsb3cuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBteWdlbmVzX2NvdW50cywgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXAsIHkgPSBsb2cyKENvdW50ICsgMSksIGNvbG91ciA9IEdyb3VwKSkgKwogIGdlb21faml0dGVyKCkgKwogIGZhY2V0X3dyYXAofiBnZW5lX3N5bWJvbCkgKyAKICBsYWJzKHggPSAiQ2VsbCB0eXBlIGFuZCBzdGFnZSIsIHkgPSAiQ291bnQiLCB0aXRsZSA9ICJNYW1tYXJ5IGdsYW5kIFJOQS1zZXEgZGF0YSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkgKyAKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCiMjIyBPcmRlciBvZiBncm91cHMKClRoZSBncm91cHMgaGF2ZSBiZWVuIHBsb3R0ZWQgaW4gYWxwaGFiZXRpY2FsIG9yZGVyIG9uIHRoZSB4IGF4aXMgYW5kIGluIHRoZSBsZWdlbmQgKHRoYXQgaXMgdGhlIGRlZmF1bHQgb3JkZXIpLCBob3dldmVyLCB3ZSBtYXkgd2FudCB0byBjaGFuZ2UgdGhlIG9yZGVyLiBXZSBtYXkgcHJlZmVyIHRvIHBsb3QgdGhlIGdyb3VwcyBpbiBvcmRlciBvZiBzdGFnZSwgZm9yIGV4YW1wbGUsIGJhc2FsIHZpcmdpbiwgYmFzYWwgcHJlZ25hbnQsIGJhc2FsIGxhY3RhdGUsIGx1bWluYWwgdmlyZ2luLCBsdW1pbmFsIHByZWduYW50LCBsdW1pbmFsIGxhY3RhdGUuCgpGaXJzdCBsZXQncyBtYWtlIGFuIG9iamVjdCB3aXRoIHRoZSBncm91cCBvcmRlciB0aGF0IHdlIHdhbnQuCmBgYHtyfQpncm91cF9vcmRlciA8LSBjKCJidmlyZyIsICJicHJlZyIsICJibGFjdCIsICJsdmlyZyIsICJscHJlZyIsICJsbGFjdCIpCmBgYAoKTmV4dCB3ZSBuZWVkIHRvIG1ha2UgYSBjb2x1bW4gd2l0aCB0aGUgZ3JvdXBzIGludG8gYW4gUiBkYXRhIHR5cGUgY2FsbGVkIGEgKipmYWN0b3IqKi4gRmFjdG9ycyBpbiBSIGFyZSBhIHNwZWNpYWwgZGF0YSB0eXBlIHVzZWQgdG8gc3BlY2lmeSBjYXRlZ29yaWVzLCB5b3UgY2FuIHJlYWQgbW9yZSBhYm91dCB0aGVtIGluIHRoZSBbUiBmb3IgRGF0YSBTY2llbmNlIGJvb2tdKGh0dHBzOi8vcjRkcy5oYWQuY28ubnovdmVjdG9ycy5odG1sI2F1Z21lbnRlZC12ZWN0b3JzKS4gVGhlIG5hbWVzIG9mIHRoZSBjYXRlZ29yaWVzIGFyZSBjYWxsZWQgdGhlIGZhY3RvciAqKmxldmVscyoqLiAKCldlJ2xsIGFkZCBhbm90aGVyIGNvbHVtbiBjYWxsZWQgIkdyb3VwX2YiIHdoZXJlIHdlJ2xsIG1ha2UgdGhlIEdyb3VwIGNvbHVtbiBpbnRvIGEgZmFjdG9yIGFuZCBzcGVjaWZ5IHdoYXQgb3JkZXIgd2Ugd2FudCB0aGUgbGV2ZWxzIG9mIHRoZSBmYWN0b3IuCgpgYGB7cn0KbXlnZW5lc19jb3VudHMgPC0gbXV0YXRlKG15Z2VuZXNfY291bnRzLCBHcm91cF9mID0gZmFjdG9yKEdyb3VwLCBsZXZlbHMgPSBncm91cF9vcmRlcikpCmBgYAoKVGFrZSBhIGxvb2sgYXQgdGhlIGRhdGEuCgpgYGB7cn0KbXlnZW5lc19jb3VudHMKYGBgCgpOb3RpY2UgdGhhdCB0aGUgR3JvdXAgY29sdW1uIGhhcyBgPGNocj5gIHVuZGVyIHRoZSBoZWFkaW5nLCB0aGF0IGluZGljYXRlcyBpcyBhIGNoYXJhY3RlciBkYXRhIHR5cGUsIHdoaWxlIHRoZSBHcm91cF9mIGNvbHVtbiBoYXMgYDxmY3Q+YCB1bmRlciB0aGUgaGVhZGluZywgaW5kaWNhdGluZyBpdCBpcyBhIGZhY3RvciBkYXRhIHR5cGUuIFRoZSBgc3RyKClgIGNvbW1hbmQgdGhhdCB3ZSBzYXcgcHJldmlvdXNseSBpcyB1c2VmdWwgdG8gY2hlY2sgdGhlIGRhdGEgdHlwZXMgaW4gb2JqZWN0cy4KCmBgYHtyfQpzdHIobXlnZW5lc19jb3VudHMpCmBgYAoKYHN0cigpYCBzaG93cyB1cyBHcm91cF9mIGNvbHVtbiBpcyBhIEZhY3RvciB3aXRoIDYgbGV2ZWxzIChjYXRlZ29yaWVzKS4KCldlIGNhbiBjaGVjayB0aGUgZmFjdG9yIGxldmVscyBvZiBhIGNvbHVtbiBhcyBiZWxvdy4KCmBgYHtyfQpsZXZlbHMobXlnZW5lc19jb3VudHMkR3JvdXBfZikKYGBgCgpUaGUgbGV2ZWxzIGFyZSBpbiB0aGUgb3JkZXIgdGhhdCB3ZSB3YW50LCBzbyB3ZSBjYW4gbm93IGNoYW5nZSBvdXIgcGxvdCB0byB1c2UgdGhlICJHcm91cF9mIiBjb2x1bW4gaW5zdGVhZCBvZiBHcm91cCBjb2x1bW4gKGNoYW5nZSBgeCA9IGAgYW5kIGBjb2xvdXIgPSBgKS4KCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IG15Z2VuZXNfY291bnRzLCBtYXBwaW5nID0gYWVzKHggPSBHcm91cF9mLCB5ID0gbG9nMihDb3VudCArIDEpLCBjb2xvdXIgPSBHcm91cF9mKSkgKwogIGdlb21faml0dGVyKCkgKwogIGZhY2V0X3dyYXAofiBnZW5lX3N5bWJvbCkgKyAKICBsYWJzKHggPSAiQ2VsbCB0eXBlIGFuZCBzdGFnZSIsIHkgPSAiQ291bnQiLCB0aXRsZSA9ICJNYW1tYXJ5IGdsYW5kIFJOQS1zZXEgZGF0YSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkgKyAKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKQpgYGAKV2UgY291bGQgZG8gc2ltaWxhciBpZiB3ZSB3YW50ZWQgdG8gaGF2ZSB0aGUgZ2VuZXMgaW4gdGhlIGZhY2V0cyBpbiBhIGRpZmZlcmVudCBvcmRlci4gRm9yIGV4YW1wbGUsIHdlIGNvdWxkIGFkZCBhbm90aGVyIGNvbHVtbiBjYWxsZWQgImdlbmVfc3ltYm9sX2YiIHdoZXJlIHdlIG1ha2UgdGhlIGdlbmVfc3ltYm9sIGNvbHVtbiBpbnRvIGEgZmFjdG9yLCBzcGVjaWZ5aW5nIHRoZSBvcmRlciBvZiB0aGUgbGV2ZWxzLgoKIyBTYXZpbmcgcGxvdHMKV2UgY2FuIHNhdmUgcGxvdHMgaW50ZXJhY3RpdmVseSBieSBjbGlja2luZyBFeHBvcnQgaW4gdGhlIFBsb3RzIHdpbmRvdy4gT3Igd2UgY2FuIG91dHB1dCBwbG90cyB0byBwZGYgdXNpbmcgYHBkZigpYCBmb2xsb3dlZCBieSBgZGV2Lm9mZigpYC4gV2UgcHV0IG91ciBwbG90IGNvZGUgYWZ0ZXIgdGhlIGNhbGwgdG8gYHBkZigpYCBhbmQgYmVmb3JlIGNsb3NpbmcgdGhlIHBsb3QgZGV2aWNlIHdpdGggYGRldi5vZmYoKWAuCgpMZXQncyBzYXZlIG91ciBsYXN0IHBsb3QuCgpgYGB7ciwgZXZhbD1GQUxTRX0KcGRmKCJteXBsb3QucGRmIikKZ2dwbG90KGRhdGEgPSBteWdlbmVzX2NvdW50cywgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXBfZiwgeSA9IGxvZzIoQ291bnQgKyAxKSwgY29sb3VyID0gR3JvdXBfZikpICsKICBnZW9tX2ppdHRlcigpICsKICBmYWNldF93cmFwKH4gZ2VuZV9zeW1ib2wpICsgCiAgbGFicyh4ID0gIkNlbGwgdHlwZSBhbmQgc3RhZ2UiLCB5ID0gIkNvdW50IiwgdGl0bGUgPSAiTWFtbWFyeSBnbGFuZCBSTkEtc2VxIGRhdGEiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpICsgCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSkKZGV2Lm9mZigpCmBgYAoKCiMgRXhlcmNpc2VzCjEuIERvd25sb2FkIHRoZSByYXcgY291bnRzIGZvciB0aGlzIGRhdGFzZXQKICBhLiBNYWtlIGEgYm94cGxvdC4gRG8gdGhlIHNhbXBsZXMgbG9vayBhbnkgZGlmZmVyZW50IHRvIHRoZSBub3JtYWxpc2VkIGNvdW50cz8KICBiLiBNYWtlIHN1YnBsb3RzIGZvciB0aGUgc2FtZSBzZXQgb2YgOCBnZW5lcy4gRG8gdGhleSBsb29rIGFueSBkaWZmZXJlbnQgdG8gdGhlIG5vcm1hbGlzZWQgY291bnRzPwoyLiBEb3dubG9hZCB0aGUgbm9ybWFsaXNlZCBjb3VudHMgZm9yIHRoZSBHU0U2MzMxMCBkYXRhc2V0IGZyb20gR1JFSU4uIE1ha2UgYm94cGxvdHMgY29sb3VyaW5nIHRoZSBzYW1wbGVzIHVzaW5nIGRpZmZlcmVudCBjb2x1bW5zIGluIHRoZSBtZXRhZGF0YSBmaWxlLgoKCiMgS2V5IFBvaW50cwotIFRhYnVsYXIgZGF0YSBjYW4gYmUgbG9hZGVkIGludG8gUiB3aXRoIHRoZSB0aWR5dmVyc2UgZnVuY3Rpb25zIGByZWFkX2NzdigpYCBhbmQgYHJlYWRfdHN2KClgCi0gVGlkeXZlcnNlIGZ1bmN0aW9ucyBzdWNoIGFzIGBmdWxsX2pvaW4oKWAsIGBnYXRoZXIoKWAsIGBtdXRhdGUoKWAsIGBmaWx0ZXIoKWAgY2FuIGJlIHVzZWQgdG8gbWFuaXB1bGF0ZSBkYXRhCi0gQSBnZ3Bsb3QgaGFzIDMgY29tcG9uZW50czogZGF0YSAoZGF0YXNldCksIG1hcHBpbmcgKGNvbHVtbnMgdG8gcGxvdCkgYW5kIGdlb20gKHR5cGUgb2YgcGxvdCkuIERpZmZlcmVudCB0eXBlcyBvZiBwbG90cyBpbmNsdWRlIGBnZW9tX3BvaW50KClgLCBgZ2VvbV9qaXR0ZXIoKWAsIGBnZW9tX2xpbmUoKWAsIGBnZW9tX2JveHBsb3QoKWAsIGBnZW9tX3Zpb2xpbigpYC4KLSBgZmFjZXRfd3JhcCgpYCBjYW4gYmUgdXNlZCB0byBtYWtlIHN1YnBsb3RzIG9mIHRoZSBkYXRhCi0gVGhlIGFlc3RoZXRpY3Mgb2YgYSBnZ3Bsb3QgY2FuIGJlIG1vZGlmaWVkLCBzdWNoIGFzIGNvbG91cmluZyBieSBkaWZmZXJlbnQgY29sdW1ucyBpbiB0aGUgZGF0YXNldCwgYWRkaW5nIGxhYmVscyBvciBjaGFuZ2luZyB0aGUgYmFja2dyb3VuZAoKCiMgRnVydGhlciBSZWFkaW5nCltJbnRybyB0byBSIGFuZCB0aWR5dmVyc2VdKGh0dHBzOi8vcG1hY2Rhc2NpLmdpdGh1Yi5pby9yLWludHJvLXRpZHl2ZXJzZS8pICAKW1RvcCA1MCBHZ3Bsb3QgVmlzdWFsaXNhdGlvbnNdKCBodHRwOi8vci1zdGF0aXN0aWNzLmNvL1RvcDUwLUdncGxvdDItVmlzdWFsaXphdGlvbnMtTWFzdGVyTGlzdC1SLUNvZGUuaHRtbCkgIApbUiBmb3IgRGF0YSBTY2llbmNlXShodHRwczovL3I0ZHMuaGFkLmNvLm56LykK
+
LS0tCnRpdGxlOiAiSW50cm9kdWN0aW9uIHRvIFIgZm9yIEJpb2xvZ2lzdHMiCmF1dGhvcjogIk1hcmlhIERveWxlLCBKZXNzaWNhIENodW5nLCBWaWNreSBQZXJyZWF1IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDMKICAgIHRvY19mbG9hdDogeWVzCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkICVCICVZJylgIgotLS0KCiMgUiBmb3IgQmlvbG9naXN0cyBjb3Vyc2UKClIgdGFrZXMgdGltZSB0byBsZWFybiwgbGlrZSBhIHNwb2tlbiBsYW5ndWFnZS4gTm8gb25lIGNhbiBleHBlY3QgdG8gYmUgYW4gUiBleHBlcnQgYWZ0ZXIgbGVhcm5pbmcgUiBmb3IgYSBmZXcgaG91cnMuIFRoaXMgY291cnNlIGhhcyBiZWVuIGRlc2lnbmVkIHRvIGludHJvZHVjZSBiaW9sb2dpc3RzIHRvIFIsIHNob3dpbmcgc29tZSBiYXNpY3MgYW5kIHNvbWUgcG93ZXJmdWwgdGhpbmdzIFIgY2FuIGRvLiBUaGUgYWltIGlzIHRvIGdpdmUgYmVnaW5uZXJzIHRoZSBjb25maWRlbmNlIHRvIGNvbnRpbnVlIGxlYXJuaW5nIFIsIHNvIHRoZSBmb2N1cyBoZXJlIGlzIG9uIHRpZHl2ZXJzZSBhbmQgdmlzdWFsaXNhdGlvbiBvZiBiaW9sb2dpY2FsIGRhdGEsIGFzIHdlIGJlbGlldmUgdGhpcyBpcyBhIHByb2R1Y3RpdmUgYW5kIGVuZ2FnaW5nIHdheSB0byBzdGFydCBsZWFybmluZyBSLgoKIyBJbnRybyB0byBSIGFuZCBSU3R1ZGlvCgpSU3R1ZGlvIGlzIGFuIGludGVyZmFjZSB0aGF0IG1ha2VzIGl0IGVhc2llciB0byB1c2UgUi4gVGhlcmUgYXJlIGZvdXIgd2luZG93cyBpbiBSU3R1ZGlvLiBUaGUgc2NyZWVuc2hvdCBiZWxvdyBzaG93cyBhbiBbYW5hbG9neSBsaW5raW5nIHRoZSBkaWZmZXJlbnQgUlN0dWRpbyB3aW5kb3dzIHRvIGNvb2tpbmddKGh0dHBzOi8vdHdpdHRlci5jb20vUkxhZGllc05DTC9zdGF0dXMvMTEzODgxMjgyNjkxNzcyNDE2MCkuCgohW10oaW1hZ2VzL3JzdHVkaW9fY29va2luZy5qcGcpCgpcICAKXCAgClwgIAoKIyMgUiBzY3JpcHQgdnMgY29uc29sZQoKVGhlcmUgYXJlIHR3byB3YXlzIHRvIHdvcmsgaW4gUlN0dWRpbyBpbiB0aGUgY29uc29sZSBvciBpbiBhIHNjcmlwdC4gV2UgY2FuIHR5cGUgYSBjb21tYW5kIGluIHRoZSBjb25zb2xlIGFuZCBwcmVzcyBgRW50ZXJgIHRvIHJ1biBpdC4gVHJ5IHJ1bm5pbmcgdGhlIGNvbW1hbmQgYmVsb3cgaW4gdGhlIGNvbnNvbGUuCgpgYGB7cn0KMSArIDEKYGBgCgpPciB3ZSBjYW4gdXNlIGFuIFIgc2NyaXB0LiBUbyBjcmVhdGUgYSBzY3JpcHQsIGZyb20gdGhlIHRvcCBtZW51IGluIFJTdHVkaW86IGBGaWxlID4gTmV3IEZpbGUgPiBSIFNjcmlwdGAuIE5vdyB0eXBlIHRoZSBjb21tYW5kIGJlbG93IGluIHRoZSBzY3JpcHQuIFRoaXMgdGltZSwgdG8gcnVuIHRoZSBjb21tYW5kLCB5b3UgdXNlIGBDdHJsYCArIGBFbnRlcmAgZm9yIFdpbmRvd3MvTGludXggb3IgYENtZGAgKyBgRW50ZXJgIGZvciBNYWNPUy4gVGhpcyBzZW5kcyB0aGUgY29tbWFuZCB3aGVyZSB0aGUgY3Vyc29yIGlzIGZyb20gdGhlIHNjcmlwdCB0byB0aGUgY29uc29sZS4gWW91IGNhbiBoaWdobGlnaHQgbXVsdGlwbGUgY29tbWFuZHMgYW5kIHRoZW4gcHJlc3MgYENtZC9DdHJsYCArIGBFbnRlcmAgdG8gcnVuIHRoZW0gb25lIGFmdGVyIHRoZSBvdGhlci4KCmBgYHtyfQoyICsgMgpgYGAKCkFzIHRoZSBSU3R1ZGlvIHNjcmVlbnNob3QgYWJvdmUgZXhwbGFpbnMsIGlmIHdlIHdvcmsgaW4gdGhlIGNvbnNvbGUgd2UgZG9uJ3QgaGF2ZSBhIGdvb2QgcmVjb3JkIChyZWNpcGUpIG9mIHdoYXQgd2UndmUgZG9uZS4gV2UgY2FuIHNlZSBjb21tYW5kcyB3ZSd2ZSBydW4gaW4gdGhlIEhpc3RvcnkgcGFuZWwgKHRvcCByaWdodCB3aW5kb3cpLCBhbmQgd2UgY2FuIGdvIGJhY2t3YXJkcyBhbmQgZm9yd2FyZHMgdGhyb3VnaCBvdXIgaGlzdG9yeSBpbiB0aGUgY29uc29sZSB1c2luZyB0aGUgdXAgYXJyb3cgYW5kIGRvd24gYXJyb3cuIEJ1dCB0aGUgaGlzdG9yeSBpbmNsdWRlcyBldmVyeXRoaW5nIHdlJ3ZlIHRyaWVkIHRvIHJ1biwgaW5jbHVkaW5nIG91ciBtaXN0YWtlcyBzbyBpdCBpcyBnb29kIHByYWN0aWNlIHRvIHVzZSBhbiBSIHNjcmlwdC4KCldlIGNhbiBhbHNvIGFkZCBjb21tZW50cyB0byBhIHNjcmlwdC4gVGhlc2UgYXJlIG5vdGVzIHRvIG91cnNlbGYgb3Igb3RoZXJzIGFib3V0IHRoZSBjb21tYW5kcyBpbiB0aGUgc2NyaXB0LiBDb21tZW50cyBzdGFydCB3aXRoIGEgYCNgIHdoaWNoIHRlbGxzIFIgbm90IHRvIHJ1biB0aGVtIGFzIGNvbW1hbmRzLgoKYGBge3J9CiMgdGVzdGluZyBSCjIgKyAyCmBgYAoKS2VlcGluZyBhbiBhY2N1cmF0ZSByZWNvcmQgb2YgaG93IHlvdSd2ZSBtYW5pcHVsYXRlZCB5b3VyIGRhdGEgaXMgaW1wb3J0YW50IGZvciBbcmVwcm9kdWNpYmxlIHJlc2VhcmNoXShodHRwczovL3JvcGVuc2NpLmdpdGh1Yi5pby9yZXByb2R1Y2liaWxpdHktZ3VpZGUvc2VjdGlvbnMvaW50cm9kdWN0aW9uLykuIFdyaXRpbmcgZGV0YWlsZWQgY29tbWVudHMgYW5kIGRvY3VtZW50aW5nIHlvdXIgd29yayBhcmUgdXNlZnVsIHJlbWluZGVycyB0byB5b3VyIGZ1dHVyZSBzZWxmIChhbmQgYW55b25lIGVsc2UgcmVhZGluZyB5b3VyIHNjcmlwdHMpIG9uIHdoYXQgeW91ciBjb2RlIGRvZXMuCgojIyBXb3JraW5nIGRpcmVjdG9yeQoKT3BlbmluZyBhbiBSU3R1ZGlvIHNlc3Npb24gbGF1bmNoZXMgaXQgZnJvbSBhIHNwZWNpZmljIGxvY2F0aW9uLiBUaGlzIGlzIHRoZSDigJh3b3JraW5nIGRpcmVjdG9yeeKAmS4gKipSIGxvb2tzIGluIHRoZSB3b3JraW5nIGRpcmVjdG9yeSBieSBkZWZhdWx0IHRvIHJlYWQgaW4gZGF0YSBhbmQgc2F2ZSBmaWxlcy4qKiBZb3UgY2FuIGZpbmQgb3V0IHdoYXQgdGhlIHdvcmtpbmcgZGlyZWN0b3J5IGlzIGJ5IHVzaW5nIHRoZSBjb21tYW5kIGBnZXR3ZCgpYC4gVGhpcyBzaG93cyB5b3UgdGhlIHBhdGggdG8geW91ciB3b3JraW5nIGRpcmVjdG9yeSBpbiB0aGUgY29uc29sZS4gSW4gTWFjIHRoaXMgaXMgaW4gdGhlIGZvcm1hdCBgL3BhdGgvdG8vd29ya2luZy9kaXJlY3RvcnlgIGFuZCBpbiBXaW5kb3dzIGBDOlxwYXRoXHRvXHdvcmtpbmdcZGlyZWN0b3J5YC4gSXQgaXMgb2Z0ZW4gdXNlZnVsIHRvIGhhdmUgeW91ciBkYXRhIGFuZCBSIHNjcmlwdHMgaW4gdGhlIHNhbWUgZGlyZWN0b3J5IGFuZCBzZXQgdGhpcyBhcyB5b3VyIHdvcmtpbmcgZGlyZWN0b3J5LiBXZSB3aWxsIGRvIHRoaXMgbm93LiAKCk1ha2UgYSBmb2xkZXIgZm9yIHRoaXMgY291cnNlIHNvbWV3aGVyZSBvbiB5b3VyIGNvbXB1dGVyIHRoYXQgeW91IHdpbGwgYmUgYWJsZSB0byBlYXNpbHkgZmluZC4gTmFtZSB0aGUgZm9sZGVyIGZvciBleGFtcGxlLCBgSW50cm9fUl9jb3Vyc2VgLiBUaGVuLCB0byBzZXQgdGhpcyBmb2xkZXIgYXMgeW91ciB3b3JraW5nIGRpcmVjdG9yeToKCkluIFJTdHVkaW8gY2xpY2sgb24gdGhlIOKAmEZpbGVz4oCZIHRhYiBhbmQgdGhlbiBjbGljayBvbiB0aGUgdGhyZWUgZG90cywgYXMgc2hvd24gYmVsb3cuCgohW10oaW1hZ2VzL3RocmVlX2RvdHMucG5nKQoKSW4gdGhlIHdpbmRvdyB0aGF0IGFwcGVhcnMsIGZpbmQgdGhlIGZvbGRlciB5b3UgY3JlYXRlZCAoZS5nLiBgSW50cm9fUl9jb3Vyc2VgKSwgY2xpY2sgb24gaXQsIHRoZW4gY2xpY2sg4oCYT3BlbuKAmS4gVGhlIGZpbGVzIHRhYiB3aWxsIG5vdyBzaG93IHRoZSBjb250ZW50cyBvZiB5b3VyIG5ldyBmb2xkZXIuIENsaWNrIG9uIGBNb3JlID4gU2V0IEFzIFdvcmtpbmcgRGlyZWN0b3J5YCwgYXMgc2hvd24gYmVsb3cuCgohW10oaW1hZ2VzL3dvcmtpbmdfZGlyZWN0b3J5LnBuZykKClNhdmUgdGhlIHNjcmlwdCB5b3UgY3JlYXRlZCBpbiB0aGUgcHJldmlvdXMgc2VjdGlvbiBhcyBgaW50cm8uUmAgaW4gdGhpcyBkaXJlY3RvcnkuIFlvdSBjYW4gZG8gdGhpcyBieSBjbGlja2luZyBvbiBgRmlsZSA+IFNhdmVgIGFuZCB0aGUgZGVmYXVsdCBsb2NhdGlvbiBzaG91bGQgYmUgdGhlIGN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnkgKGUuZy4gYEludHJvX1JfY291cnNlYCkuCgojIyBQYWNrYWdlcwoKSWYgaXQncyBub3QgYWxyZWFkeSBpbnN0YWxsZWQgb24geW91ciBjb21wdXRlciwgeW91IGNhbiB1c2UgdGhlIGBpbnN0YWxsLnBhY2thZ2VzYCAqKmZ1bmN0aW9uKiogdG8gaW5zdGFsbCBhICoqcGFja2FnZSoqLiBBIHBhY2thZ2UgaXMgYSBjb2xsZWN0aW9uIG9mIGZ1bmN0aW9ucyBhbG9uZyB3aXRoIGRvY3VtZW50YXRpb24sIGNvZGUsIHRlc3RzIGFuZCBleGFtcGxlIGRhdGEuCgpgYGB7ciwgZXZhbD1GQUxTRX0KaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikKYGBgCgpXZSB3aWxsIHNlZSBtYW55IGZ1bmN0aW9ucyBpbiB0aGlzIHR1dG9yaWFsLiBGdW5jdGlvbnMgYXJlICJjYW5uZWQgc2NyaXB0cyIgdGhhdCBhdXRvbWF0ZSBtb3JlIGNvbXBsaWNhdGVkIHNldHMgb2YgY29tbWFuZHMuIE1hbnkgZnVuY3Rpb25zIGFyZSBwcmVkZWZpbmVkLCBvciBjYW4gYmUgbWFkZSBhdmFpbGFibGUgYnkgaW1wb3J0aW5nIFIgcGFja2FnZXMuIEEgZnVuY3Rpb24gdXN1YWxseSB0YWtlcyBvbmUgb3IgbW9yZSBpbnB1dHMgY2FsbGVkICphcmd1bWVudHMqLiBIZXJlIHRpZHl2ZXJzZSBpcyB0aGUgYXJndW1lbnQgdG8gdGhlIGBpbnN0YWxsLnBhY2thZ2VzKClgIGZ1bmN0aW9uLiAqKk5vdGUgdGhhdCBmdW5jdGlvbnMgcmVxdWlyZSBwYXJlbnRoZXNlcyBhZnRlciB0aGUgZnVuY3Rpb24gbmFtZS4qKgoKIyMgR2V0dGluZyBoZWxwCgpUbyBzZWUgd2hhdCBhbnkgZnVuY3Rpb24gaW4gUiBkb2VzLCB0eXBlIGEgYD9gIGJlZm9yZSB0aGUgbmFtZSBhbmQgaGVscCBpbmZvcm1hdGlvbiB3aWxsIGFwcGVhciBpbiB0aGUgSGVscCBwYW5lbCBvbiB0aGUgcmlnaHQgaW4gUlN0dWRpby4gT3IgeW91IGNhbiBzZWFyY2ggdGhlIGZ1bmN0aW9uIG5hbWUgaW4gdGhlIEhlbHAgcGFuZWwgc2VhcmNoIGJveC4gR29vZ2xlIGFuZCBbU3RhY2sgT3ZlcmZsb3ddKGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vKSBhcmUgYWxzbyB1c2VmdWwgcmVzb3VyY2VzIGZvciBnZXR0aW5nIGhlbHAuCgpgYGB7ciwgZXZhbD1GQUxTRX0KP2luc3RhbGwucGFja2FnZXMKYGBgCgo+ICMjIyMgVGFiIGNvbXBsZXRpb24KPiBBIHZlcnkgdXNlZnVsIGZlYXR1cmUgaXMgVGFiIGNvbXBsZXRpb24uIFlvdSBjYW4gc3RhcnQgdHlwaW5nIGFuZCB1c2UgPGtiZD5UYWI8L2tiZD4gdG8gYXV0b2NvbXBsZXRlIGNvZGUsIGZvciBleGFtcGxlLCBhIGZ1bmN0aW9uIG5hbWUuIAoKIyMgQ29tbW9uIFIgZXJyb3JzCgpSIGVycm9yIG1lc3NhZ2VzIGFyZSBjb21tb24gYW5kIGNhbiBzb21ldGltZXMgYmUgY3J5cHRpYy4gWW91IG1vc3QgbGlrZWx5IHdpbGwgZW5jb3VudGVyIGF0IGxlYXN0IG9uZSBlcnJvciBtZXNzYWdlIGR1cmluZyB0aGlzIHR1dG9yaWFsLiBTb21lIGNvbW1vbiByZWFzb25zIGZvciBlcnJvcnMgYXJlOgoKLSBDYXNlIHNlbnNpdGl2aXR5LiBJbiBSLCBhcyBpbiBvdGhlciBwcm9ncmFtbWluZyBsYW5ndWFnZXMsIGNhc2Ugc2Vuc2l0aXZpdHkgaXMgaW1wb3J0YW50LiA/aW5zdGFsbC5wYWNrYWdlcyBpcyBkaWZmZXJlbnQgdG8gP0luc3RhbGwucGFja2FnZXMuCi0gTWlzc2luZyBjb21tYXMKLSBNaXNtYXRjaGVkIHBhcmVudGhlc2VzIG9yIGJyYWNrZXRzCi0gTm90IHF1b3RpbmcgZmlsZSBwYXRocwotIE5vdCBmaW5pc2hpbmcgYSBjb21tYW5kIHNvIHNlZWluZyAiKyIgaW4gdGhlIGNvbnNvbGUuIElmIHlvdSBuZWVkIHRvLCB5b3UgY2FuIHByZXNzIEVTQyB0byBjYW5jZWwgdGhlIGNvbW1hbmQuCgpUbyBzZWUgZXhhbXBsZXMgb2Ygc29tZSBSIGVycm9yIG1lc3NhZ2VzIHdpdGggZXhwbGFuYXRpb25zIHNlZSBbaGVyZV0oIGh0dHBzOi8vZ2l0aHViLmNvbS9ub2Ftcm9zcy96ZXJvLWRlcGVuZGVuY3ktcHJvYmxlbXMvaXNzdWVzLzcpCgoKIyBHZXR0aW5nIHN0YXJ0ZWQgd2l0aCBkYXRhCgoKIyMgRGF0YSBmaWxlcwpUaGUgZGF0YSBmaWxlcyByZXF1aXJlZCBmb3IgdGhpcyB3b3Jrc2hvcCBhcmUgYXZhaWxhYmxlIG9uIFtHaXRIdWJdKGh0dHBzOi8vZ2l0aHViLmNvbS9tYmx1ZTkvci1pbnRyby1iaW9sb2dpc3RzL2Jsb2IvbWFzdGVyL2RhdGEuemlwKS4gVG8gZG93bmxvYWQgdGhlIGRhdGEuemlwIGZpbGUsIHlvdSBjYW4gY2xpY2sgW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9tYmx1ZTkvci1pbnRyby1iaW9sb2dpc3RzL3Jhdy9tYXN0ZXIvZGF0YS56aXApLiBVbnppcCB0aGUgZmlsZSBhbmQgc3RvcmUgdGhpcyBgZGF0YWAgZm9sZGVyIGluIHlvdXIgd29ya2luZyBkaXJlY3RvcnkuCgoKIyMgR1JFSU4gKEdFTyBSTkEtc2VxIEV4cGVyaW1lbnRzIEludGVyYWN0aXZlIE5hdmlnYXRvcikgCkluIHRoaXMgdHV0b3JpYWwsIHdlIHdpbGwgbGVhcm4gc29tZSBSIHRocm91Z2ggY3JlYXRpbmcgcGxvdHMgdG8gdmlzdWFsaXNlIGRhdGEgZnJvbSBhbiBSTkEtc2VxIGV4cGVyaW1lbnQuIFJOQS1zZXEgY291bnRzIGZpbGUgY2FuIGJlIG9idGFpbmVkIGZyb20gdGhlIFtHUkVJTiBwbGF0Zm9ybV0oaHR0cHM6Ly93d3cubmF0dXJlLmNvbS9hcnRpY2xlcy9zNDE1OTgtMDE5LTQzOTM1LTgpLiBHUkVJTiBwcm92aWRlcyA+Niw1MDAgcHVibGlzaGVkIGRhdGFzZXRzIGZyb20gR0VPIHRoYXQgaGF2ZSBiZWVuIHVuaWZvcm1seSBwcm9jZXNzZWQuIEl0IGlzIGF2YWlsYWJsZSBhdCBodHRwOi8vd3d3LmlsaW5jcy5vcmcvYXBwcy9ncmVpbi8uIFlvdSBjYW4gc2VhcmNoIGZvciBhIGRhdGFzZXQgb2YgaW50ZXJlc3QgdXNpbmcgdGhlIEdFTyBjb2RlLiBXZSBvYnRhaW5lZCB0aGUgZGF0YXNldCB1c2VkIGhlcmUgdXNpbmcgdGhlIGNvZGUgR1NFNjA0NTAuIEdSRUlOIHByb3ZpZGUgUUMgbWV0cmljcyBmb3IgdGhlIFJOQS1zZXEgZGF0YXNldHMgYW5kIGJvdGggcmF3IGFuZCBub3JtYWxpemVkIGNvdW50cy4gV2Ugd2lsbCB1c2UgdGhlIG5vcm1hbGl6ZWQgY291bnRzIGhlcmUuIFRoZXNlIGFyZSB0aGUgY291bnRzIG9mIHJlYWRzIGZvciBlYWNoIGdlbmUgZm9yIGVhY2ggc2FtcGxlIG5vcm1hbGl6ZWQgZm9yIGRpZmZlcmVuY2VzIGluIHNlcXVlbmNpbmcgZGVwdGggYW5kIGNvbXBvc2l0aW9uIGJpYXMuIEdlbmVyYWxseSwgdGhlIGhpZ2hlciB0aGUgbnVtYmVyIG9mIGNvdW50cyB0aGUgbW9yZSB0aGUgZ2VuZSBpcyBleHByZXNzZWQuClwgIApcIAoKIyMgUk5BLXNlcSBkYXRhc2V0CkhlcmUgd2Ugd2lsbCBjcmVhdGUgc29tZSBwbG90cyB1c2luZyBSTkEtc2VxIGRhdGEgZnJvbSB0aGUgcGFwZXIgYnkgW0Z1IGV0IGFsLiAyMDE1XShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC8yNTczMDQ3MiksIEdFTyBjb2RlIEdTRTYwNDUwLiBUaGlzIHN0dWR5IGV4YW1pbmVkIGV4cHJlc3Npb24gaW4gYmFzYWwgYW5kIGx1bWluYWwgY2VsbHMgZnJvbSBtaWNlIGF0IGRpZmZlcmVudCBzdGFnZXMgKHZpcmdpbiwgcHJlZ25hbnQgYW5kIGxhY3RhdGluZykuIFRoZXJlIGFyZSAyIHNhbXBsZXMgcGVyIGdyb3VwIGFuZCA2IGdyb3VwcywgMTIgc2FtcGxlcyBpbiB0b3RhbC4KCiFbXShpbWFnZXMvbW91c2VfZXhwLnBuZykKCiMjIFRpZHl2ZXJzZQoKIVt3d3cudGlkeXZlcnNlLm9yZ10oaW1hZ2VzL3RpZHl2ZXJzZS5wbmcpe3dpZHRoPTEwMCUgfQoKSW4gdGhpcyBjb3Vyc2Ugd2Ugd2lsbCB1c2UgdGhlICoqdGlkeXZlcnNlKiouIFRoZSB0aWR5dmVyc2UgaXMgYSBjb2xsZWN0aW9uIG9mIFIgcGFja2FnZXMgdGhhdCBpbmNsdWRlcyB0aGUgZXh0cmVtZWx5IHdpZGVseSB1c2VkICoqYGdncGxvdDJgKiogcGFja2FnZS4KClwgIApcICAKXCAgCgohW1RpZHl2ZXJzZSBwYWNrYWdlc10oaW1hZ2VzL3RpZHl2ZXJzZV9wYWNrYWdlcy5qcGVnKXt3aWR0aD01MCUgfQoKXCAgClwgIApcIAoKKipUaGUgW3RpZHl2ZXJzZV0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8pIG1ha2VzIGRhdGEgc2NpZW5jZSBmYXN0ZXIsIGVhc2llciBhbmQgbW9yZSBmdW4uKioKClwgIApcICAKXCAgCgoKIyMgTG9hZGluZyB0aGUgZGF0YQoKV2UgdXNlIGBsaWJyYXJ5KClgIHRvIGxvYWQgaW4gdGhlIHBhY2thZ2VzIHRoYXQgd2UgbmVlZC4gQXMgZGVzY3JpYmVkIGluIHRoZSBjb29raW5nIGFuYWxvZ3kgaW4gdGhlIGZpcnN0IHNjcmVlbnNob3QsIGBpbnN0YWxsLnBhY2thZ2VzKClgIGlzIGxpa2UgYnV5aW5nIGEgc2F1Y2VwYW4sIGBsaWJyYXJ5KClgIGlzIHRha2luZyBpdCBvdXQgb2YgdGhlIGN1cGJvYXJkIHRvIHVzZSBpdC4KCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgpUaGUgZmlsZXMgd2Ugd2lsbCB1c2UgYXJlIGNzdiBjb21tYS1zZXBhcmF0ZWQsIHNvIHdlIHdpbGwgdXNlIHRoZSBgcmVhZF9jc3YoKWAgZnVuY3Rpb24gZnJvbSB0aGUgdGlkeXZlcnNlLiBUaGVyZSBpcyBhbHNvIGEgYHJlYWRfdHN2KClgIGZ1bmN0aW9uIGZvciB0YWItc2VwYXJhdGVkIHZhbHVlcy4KCldlIHdpbGwgdXNlIHRoZSBjb3VudHMgZmlsZSBjYWxsZWQgYEdTRTYwNDUwX0dlbmVMZXZlbF9Ob3JtYWxpemVkKENQTS5hbmQuVE1NKV9kYXRhLmNzdmAgdGhhdCdzIGluIGEgZm9sZGVyIGNhbGxlZCBgZGF0YWAgaS5lLiB0aGUgcGF0aCB0byB0aGUgZmlsZSBzaG91bGQgYmUgYGRhdGEvR1NFNjA0NTBfR2VuZUxldmVsX05vcm1hbGl6ZWQoQ1BNLmFuZC5UTU0pX2RhdGEuY3N2YC4KCldlIGNhbiByZWFkIHRoZSBjb3VudHMgZmlsZSBpbnRvIFIgd2l0aCB0aGUgY29tbWFuZCBiZWxvdy4gV2UnbGwgc3RvcmUgdGhlIGNvbnRlbnRzIG9mIHRoZSBjb3VudHMgZmlsZSBpbiBhbiAqKm9iamVjdCoqIGNhbGxlZCBgY291bnRzYC4gVGhpcyBzdG9yZXMgdGhlIGZpbGUgY29udGVudHMgaW4gUidzIG1lbW9yeSBtYWtpbmcgaXQgZWFzaWVyIHRvIHVzZS4KCmBgYHtyfQojIHJlYWQgaW4gY291bnRzIGZpbGUKY291bnRzIDwtIHJlYWRfY3N2KCJkYXRhL0dTRTYwNDUwX0dlbmVMZXZlbF9Ob3JtYWxpemVkKENQTS5hbmQuVE1NKV9kYXRhLmNzdiIpCgojIHJlYWQgaW4gbWV0YWRhdGEKc2FtcGxlaW5mbyA8LSByZWFkX2NzdigiZGF0YS9HU0U2MDQ1MF9maWx0ZXJlZF9tZXRhZGF0YS5jc3YiKQpgYGAKClRoZXJlIGlzIHNvbWUgaW5mb3JtYXRpb24gb3V0cHV0IGJ5IHJlYWRfY3N2IG9uICJjb2x1bW4gc3BlY2lmaWNhdGlvbiIuIEl0IHRlbGxzIHVzIHRoYXQgdGhlcmUgaXMgYSBtaXNzaW5nIGhlYWRlciBhbmQgaXQgaGFzIGJlZW4gZmlsbGVkIHdpdGggdGhlIG5hbWUgIlgxIi4gSXQgYWxzbyB0ZWxscyB1cyB3aGF0IGRhdGEgdHlwZXMgcmVhZF9jc3YgaXMgZGV0ZWN0aW5nIGluIGVhY2ggY29sdW1uLiBDb2x1bW5zIHdpdGggdGV4dCBjaGFyYWN0ZXJzaGF2ZSBiZWVuIGRldGVjdGVkIChjb2xfY2hhcmFjdGVyKSBhbmQgYWxzbyBjb2x1bW5zIHdpdGggbnVtYmVycyAoY29sX2RvdWJsZSkuIFdlIHdvbid0IGdldCBpbnRvIHRoZSBkZXRhaWxzIG9mIFIgZGF0YSB0eXBlcyBpbiB0aGlzIHR1dG9yaWFsIGJ1dCB0aGV5IGFyZSBpbXBvcnRhbnQgdG8ga25vdyBhbmQgeW91IGNhbiByZWFkIG1vcmUgYWJvdXQgdGhlbSBpbiB0aGUgW1IgZm9yIERhdGEgU2NpZW5jZSBib29rXShodHRwczovL3I0ZHMuaGFkLmNvLm56L3ZlY3RvcnMuaHRtbCNpbXBvcnRhbnQtdHlwZXMtb2YtYXRvbWljLXZlY3RvcikuCgpJbiBSIHdlIHVzZSBgPC1gIHRvIGFzc2lnbiB2YWx1ZXMgdG8gb2JqZWN0cy4gYDwtYCBpcyB0aGUgKiphc3NpZ25tZW50IG9wZXJhdG9yKiouICBJdCBhc3NpZ25zIHZhbHVlcyBvbiB0aGUgcmlnaHQgdG8gb2JqZWN0cyBvbiB0aGUgbGVmdC4gU28gdG8gY3JlYXRlIGFuIG9iamVjdCwgd2UgbmVlZCB0byBnaXZlIGl0IGEgbmFtZSAoZS5nLiBgY291bnRzYCksIGZvbGxvd2VkIGJ5IHRoZSBhc3NpZ25tZW50IG9wZXJhdG9yIGA8LWAsIGFuZCB0aGUgdmFsdWUgd2Ugd2FudCB0byBnaXZlIGl0LiBXZSBjYW4gZ2l2ZSBhbiBvYmplY3QgYWxtb3N0IGFueSBuYW1lIHdlIHdhbnQgYnV0IHRoZXJlIGFyZSBzb21lIHJ1bGVzIGFuZCBjb252ZW50aW9ucyBhcyBkZXNjcmliZWQgaW4gdGhlIFt0aWR5dmVyc2UgUiBzdHlsZSBndWlkZV0oaHR0cHM6Ly9zdHlsZS50aWR5dmVyc2Uub3JnL3N5bnRheC5odG1sI29iamVjdC1uYW1lcykKCldlIGNhbiByZWFkIGluIGEgZmlsZSBmcm9tIGEgcGF0aCBvbiBvdXIgY29tcHV0ZXIgb24gb24gdGhlIHdlYiBhbmQgdXNlIHRoaXMgYXMgdGhlIHZhbHVlLiBOb3RlIHRoYXQgd2UgbmVlZCB0byBwdXQgcXVvdGVzICgiIikgYXJvdW5kIGZpbGUgcGF0aHMuCgo+ICMjIyMgQXNzaWdubWVudCBvcGVyYXRvciBzaG9ydGN1dAo+IEluIFJTdHVkaW8sIHR5cGluZyA8a2JkPkFsdDwva2JkPiArIDxrYmQ+LTwva2JkPiAocHVzaCA8a2JkPkFsdDwva2JkPiBhdCB0aGUKPiBzYW1lIHRpbWUgYXMgdGhlIDxrYmQ+LTwva2JkPiBrZXkpIHdpbGwgd3JpdGUgYCA8LSBgIGluIGEgc2luZ2xlIGtleXN0cm9rZSBpbiBXaW5kb3dzLCB3aGlsZSB0eXBpbmcgPiA8a2JkPk9wdGlvbjwva2JkPiArIDxrYmQ+LTwva2JkPiAocHVzaCA8a2JkPk9wdGlvbjwva2JkPiBhdCB0aGUKPiBzYW1lIHRpbWUgYXMgdGhlIDxrYmQ+LTwva2JkPiBrZXkpIGRvZXMgdGhlIHNhbWUgaW4gYSBNYWMuIAoKCiMjIEdldHRpbmcgdG8ga25vdyB0aGUgZGF0YQoKV2hlbiBhc3NpZ25pbmcgYSB2YWx1ZSB0byBhbiBvYmplY3QsIFIgZG9lcyBub3QgcHJpbnQgdGhlIHZhbHVlLiBGb3IgZXhhbXBsZSwgaGVyZSB3ZSBkb24ndCBzZWUgd2hhdCdzIGluIHRoZSBjb3VudHMgb3Igc2FtcGxlaW5mbyBmaWxlcy4gQnV0IHRoZXJlIGFyZSB3YXlzIHdlIGNhbiBsb29rIGF0IHRoZSBkYXRhLiBXZSB3aWxsIGRlbW9uc3RyYXRlIHVzaW5nIHRoZSBgc2FtcGxlaW5mb2Agb2JqZWN0LgoKV2UgY2FuIHR5cGUgdGhlIG5hbWUgb2YgdGhlIG9iamVjdCBhbmQgdGhpcyB3aWxsIHByaW50IHRoZSBmaXJzdCBmZXcgbGluZXMgYW5kIHNvbWUgaW5mb3JtYXRpb24sIHN1Y2ggYXMgbnVtYmVyIG9mIHJvd3MuIAoKYGBge3J9CnNhbXBsZWluZm8KYGBgCgpXZSBjYW4gYWxzbyB1c2UgYGRpbSgpYCB0byBzZWUgdGhlIGRpbWVuc2lvbnMgb2YgYW4gb2JqZWN0LCB0aGUgbnVtYmVyIG9mIHJvd3MgYW5kIGNvbHVtbnMuCgpgYGB7cn0KZGltKHNhbXBsZWluZm8pCmBgYAoKVGhpcyBzaG93IHVzIHRoZXJlIGFyZSAxMiByb3dzIGFuZCA0IGNvbHVtbnMuCgpJbiB0aGUgRW52aXJvbm1lbnQgVGFiIGluIHRoZSB0b3AgcmlnaHQgcGFuZWwgaW4gUlN0dWRpbyB3ZSBjYW4gYWxzbyBzZWUgdGhlIG51bWJlciBvZiByb3dzIGFuZCBjb2x1bW5zIGluIHRoZSBvYmplY3RzIHdlIGhhdmUgaW4gb3VyIHNlc3Npb24uCgpXZSBjYW4gYWxzbyB0YWtlIGEgbG9vayB0aGUgZmlyc3QgZmV3IGxpbmVzIHdpdGggYGhlYWQoKWAuIFRoaXMgc2hvd3MgdXMgdGhlIGZpcnN0IDYgbGluZXMuCgpgYGB7cn0KaGVhZChzYW1wbGVpbmZvKQpgYGAKCldlIGNhbiBsb29rIGF0IHRoZSBsYXN0IGZldyBsaW5lcyB3aXRoIGB0YWlsKClgLiBUaGlzIHNob3dzIHVzIHRoZSBsYXN0IDYgbGluZXMuIFRoaXMgY2FuIGJlIHVzZWZ1bCB0byBjaGVjayB0aGUgYm90dG9tIG9mIHRoZSBmaWxlLCB0aGF0IGl0IGxvb2tzIG9rLgpgYGB7cn0KdGFpbChzYW1wbGVpbmZvKQpgYGAKCk9yIHdlIGNhbiBzZWUgdGhlIHdob2xlIGZpbGUgd2l0aCBgVmlldygpYC4KCmBgYHtyIGV2YWw9RkFMU0V9ClZpZXcoc2FtcGxlaW5mbykKYGBgCgpJbiB0aGUgRW52aXJvbm1lbnQgdGFiIHdlIGNhbiBzZWUgaG93IG1hbnkgcm93cyBhbmQgY29sdW1ucyB0aGUgb2JqZWN0IGNvbnRhaW5zIGFuZCB3ZSBjYW4gY2xpY2sgb24gdGhlIGljb24gdG8gdmlldyBhbGwgdGhlIGNvbnRlbnRzIGluIGEgdGFiLiBUaGlzIHJ1bnMgdGhlIGNvbW1hbmQgVmlldygpIGZvciB1cy4KCldlIGNhbiBzZWUgYWxsIHRoZSBjb2x1bW4gbmFtZXMgd2l0aCBgY29sbmFtZXMoKWAuCmBgYHtyfQpjb2xuYW1lcyhzYW1wbGVpbmZvKQpgYGAKCldlIGNhbiBhY2Nlc3MgaW5kaXZpZHVhbCBjb2x1bW5zIGJ5IG5hbWUgdXNpbmcgdGhlIGAkYCBzeW1ib2wuIEZvciBleGFtcGxlIHdlIGNhbiBzZWUgd2hhdCdzIGNvbnRhaW5lZCBpbiBjb2x1bW4gWDEuCgpgYGB7cn0Kc2FtcGxlaW5mbyRYMQpgYGAKCklmIHdlIGp1c3Qgd2FudGVkIHRvIHNlZSB0aGUgZmlyc3QgMyB2YWx1ZXMgaW4gdGhlIGNvbHVtbiB3ZSBjYW4gc3BlY2lmeSB0aGlzIHVzaW5nIHNxdWFyZSBicmFja2V0cy4KCmBgYHtyfQpzYW1wbGVpbmZvJFgxWzE6M10KYGBgCgpPdGhlciB1c2VmdWwgY29tbWFuZHMgZm9yIGNoZWNraW5nIGRhdGEgYXJlIGBzdHIoKWAgYW5kIGBzdW1tYXJ5KClgLgoKYHN0cigpYCBzaG93cyB1cyB0aGUgc3RydWN0dXJlIG9mIG91ciBkYXRhLiBJdCBzaG93cyB1cyB3aGF0IGNvbHVtbnMgdGhlcmUgYXJlLCB0aGUgZmlyc3QgZmV3IGVudHJpZXMsIGFuZCB3aGF0IGRhdGEgdHlwZSB0aGV5IGFyZSBlLmcuIGNoYXJhY3RlciBvciBudW1iZXJzIChkb3VibGUgb3IgaW50ZWdlcikuCgpgYGB7cn0Kc3RyKHNhbXBsZWluZm8pCmBgYAoKYHN1bW1hcnkoKWAgZ2VuZXJhdGVzIHN1bW1hcnkgc3RhdGlzdGljcyBvZiBvdXIgZGF0YS4gRm9yIG51bWVyaWMgY29sdW1ucyAoY29sdW1ucyBvZiB0eXBlIGRvdWJsZSBvciBpbnRlZ2VyKSBpdCBvdXRwdXRzIHN0YXRpc3RpY3Mgc3VjaCBhcyB0aGUgbWluLCBtYXgsIG1lYW4gYW5kIG1lZGlhbi4gV2Ugd2lsbCBkZW1vbnN0cmF0ZSB0aGlzIHdpdGggdGhlIGNvdW50cyBmaWxlIGFzIGl0IGNvbnRhaW5zIG51bWVyaWMgZGF0YS4gRm9yIGNoYXJhY3RlciBjb2x1bW5zIGl0IHNob3dzIHVzIHRoZSBsZW5ndGggKGhvdyBtYW55IHJvd3MpLgoKYGBge3J9CnN1bW1hcnkoY291bnRzKQpgYGAKCgojIEZvcm1hdHRpbmcgdGhlIGRhdGEKCldlIHdpbGwgZmlyc3QgY29udmVydCB0aGUgZGF0YSBmcm9tIHdpZGUgZm9ybWF0IGludG8gbG9uZyBmb3JtYXQgdG8gbWFrZSBpdCBlYXNpZXIgdG8gd29yayB3aXRoIGFuZCBwbG90IHdpdGggZ2dwbG90LiBXZSB3YW50IGp1c3Qgb25lIGNvbHVtbiBjb250YWluaW5nIGFsbCB0aGUgZXhwcmVzc2lvbiB2YWx1ZXMgaW5zdGVhZCBvZiBtdWx0aXBsZSBjb2x1bW5zIHdpdGggY291bnRzIGZvciBlYWNoIHNhbXBsZSwgYXMgc2hvd24gaW4gdGhlIGltYWdlIGJlbG93LgoKIVtdKGltYWdlcy9yZXNoYXBlX2RhdGEucG5nKQoKV2UgY2FuIHVzZSBgZ2F0aGVyKClgIHRvIGVhc2lseSBjaGFuZ2UgdGhlIGZvcm1hdCBpbnRvIGxvbmcgZm9ybWF0LgoKYGBge3J9CnNlcWRhdGEgPC0gZ2F0aGVyKGNvdW50cywga2V5ID0gU2FtcGxlLCB2YWx1ZSA9IENvdW50LCBzdGFydHNfd2l0aCgiR1NNIikpCmBgYAoKV2UgdXNlIGBzdGFydHNfd2l0aCgiR1NNIilgIHRvIHRlbGwgZ2F0aGVyIHdlIHdhbnQgdG8gcmVmb3JtYXQgdGhlIGNvbHVtbnMgd2hvc2UgbmFtZXMgc3RhcnQgd2l0aCBHU00uIGBnYXRoZXIoKWAgd2lsbCB0aGVuIHJlZm9ybWF0IHRoZSBzcGVjaWZpZWQgY29sdW1ucyBpbnRvIHR3byBuZXcgY29sdW1ucywg4oCca2V54oCdIGFuZCDigJx2YWx1ZeKAnS4gVGhlIOKAnGtleeKAnSBjb2x1bW4gd2lsbCBjb250YWluIHRoZSBjb2x1bW4gbmFtZXMsIGFuZCB0aGUg4oCcdmFsdWXigJ0gY29sdW1uIHdpbGwgY29udGFpbiB0aGUgY29sdW1uIHZhbHVlcy4gV2UgaGF2ZSB0byB0ZWxsIGdhdGhlciB3aGF0IHdlIHdhbnQgdGhlIG5ldyBrZXkgYW5kIHZhbHVlIGNvbHVtbnMgdG8gYmUgY2FsbGVkLiBXZSB3aWxsIGdpdmUgdGhlIGtleSBjb2x1bW4gdGhlIG5hbWUgIlNhbXBsZSIgYW5kIHRoZSB2YWx1ZSBjb2x1bW4gdGhlIG5hbWUgIkNvdW50Ii4KCldlIGNvdWxkIGFsc28gc3BlY2lmeSBhIGNvbHVtbiByYW5nZSB0byByZWZvcm1hdC4gVGhlIGNvbW1hbmQgYmVsb3cgd291bGQgZ2l2ZSB1cyB0aGUgc2FtZSByZXN1bHQgYXMgdGhlIHByZXZpb3VzIGNvbW1hbmQuCmBgYHtyfQpzZXFkYXRhIDwtIGdhdGhlcihjb3VudHMsIGtleSA9IFNhbXBsZSwgdmFsdWUgPSBDb3VudCwgR1NNMTQ4MDI5MTpHU00xNDgwMzAyKQpgYGAKCkFsdGVybmF0aXZlbHksIHdlIGNvdWxkIHNwZWNpZnkgdGhlIGNvbHVtbnMgd2UgKmRvbid0KiB3YW50IHRvIHJlZm9ybWF0IGFuZCBnYXRoZXIgd2lsbCByZWZvcm1hdCBhbGwgdGhlIG90aGVyIGNvbHVtbnMuIFRvIGRvIHRoYXQgd2UgcHV0IGEgaHlwaGVuICItIiBpbiBmcm9udCBvZiB0aGUgY29sdW1uIG5hbWVzIHRoYXQgd2UgZG9uJ3Qgd2FudCB0byByZWZvcm1hdC4gVGhpcyBpcyBhIHByZXR0eSBjb21tb24gd2F5IHRvIHVzZSBgZ2F0aGVyKClgIGFzIHNvbWV0aW1lcyBpdCBpcyBlYXNpZXIgdG8gZG8gdGhhdC4gVGhlIGNvbW1hbmQgYmVsb3cgd291bGQgZ2l2ZSB1cyB0aGUgc2FtZSByZXN1bHQgYXMgdGhlIHByZXZpb3VzIGNvbW1hbmQuCgpgYGB7cn0Kc2VxZGF0YSA8LSBnYXRoZXIoY291bnRzLCBrZXkgPSBTYW1wbGUsIHZhbHVlID0gQ291bnQsIC1YMSwgLWdlbmVfc3ltYm9sKQpgYGAKCkxldCdzIGhhdmUgYSBsb29rIGF0IHRoZSBkYXRhLgpgYGB7cn0Kc2VxZGF0YQpgYGAKCk5vdyB0aGF0IHdlJ3ZlIGdvdCBqdXN0IG9uZSBjb2x1bW4gY29udGFpbmluZyBzYW1wbGUgaWRzIGluIGJvdGggb3VyIGNvdW50cyBmaWxlIGFuZCBvdXIgbWV0YWRhdGEgZmlsZXMgd2UgY2FuIGpvaW4gdGhlbSB0b2dldGhlciB1c2luZyB0aGUgc2FtcGxlIGlkcy4KCiFbXShpbWFnZXMvam9pbl9kYXRhLnBuZykKCldlIHdpbGwgdXNlIHRoZSBmdW5jdGlvbiBgZnVsbF9qb2luKClgIGFuZCBnaXZlIGl0IHRoZSB0d28gdGFibGVzIHdlIHdhbnQgdG8gam9pbi4gV2UgYWRkIGBieSA9IGMoIlNhbXBsZSIgPSAiWDEiKWAgdG8gc2F5IHdlIHdhbnQgdG8gam9pbiBvbiB0aGUgY29sdW1uIGNhbGxlZCAiU2FtcGxlIiIgaW4gdGhlIGZpcnN0IHRhYmxlIChgc2VxZGF0YWApIGFuZCB0aGUgY29sdW1uIGNhbGxlZCAiWDEiIGluIHRoZSBzZWNvbmQgdGFibGUgKGBzYW1wbGVpbmZvYCkKCmBgYHtyfQphbGxpbmZvIDwtIGZ1bGxfam9pbihzZXFkYXRhLCBzYW1wbGVpbmZvLCBieSA9IGMoIlNhbXBsZSIgPSAiWDEiKSkKYGBgCgpIZXJlIHdlIHNlZSB0aGUgZnVuY3Rpb24gYGMoKWAgZm9yIHRoZSBmaXJzdCB0aW1lLiBXZSB1c2UgdGhpcyBmdW5jdGlvbiBleHRyZW1lbHkgb2Z0ZW4gaW4gUiB3aGVuIHdlIGhhdmUgbXVsdGlwbGUgaXRlbXMgdGhhdCB3ZSBhcmUgKmNvbWJpbmluZyouIFdlIHdpbGwgc2VlIGl0IGFnYWluIGluIHRoaXMgdHV0b3JpYWwuCgpMZXQncyBoYXZlIGEgbG9vayBhdCB0aGUgZGF0YS4KYGBge3J9CmFsbGluZm8KYGBgCgpUaGUgdHdvIHRhYmxlcyBoYXZlIGJlZW4gam9pbmVkLgoKIyBQbG90dGluZyB3aXRoICoqYGdncGxvdDJgKioKCioqYGdncGxvdDJgKiogaXMgYSBwbG90dGluZyBwYWNrYWdlIHRoYXQgbWFrZXMgaXQgc2ltcGxlIHRvIGNyZWF0ZSBjb21wbGV4IHBsb3RzLiBPbmUgcmVhbGx5IGdyZWF0IGJlbmVmaXQgb2YgZ2dwbG90MiB2ZXJzdXMgdGhlIG9sZGVyIGJhc2UgUiBwbG90dGluZyBpcyB0aGF0IHdlIG9ubHkgbmVlZCB0byBtYWtlIG1pbmltYWwgY2hhbmdlcyBpZiB0aGUgdW5kZXJseWluZyBkYXRhIGNoYW5nZSBvciBpZiB3ZSBkZWNpZGUgdG8gY2hhbmdlIG91ciBwbG90IHR5cGUsIGZvciBleGFtcGxlLCBmcm9tIGEgYm94IHBsb3QgdG8gYSB2aW9saW4gcGxvdC4gVGhpcyBoZWxwcyBpbiBjcmVhdGluZyBwdWJsaWNhdGlvbiBxdWFsaXR5IHBsb3RzIHdpdGggbWluaW1hbCBhbW91bnRzIG9mIGFkanVzdG1lbnRzIGFuZCB0d2Vha2luZy4KCioqYGdncGxvdDJgKiogbGlrZXMgZGF0YSBpbiB0aGUgJ2xvbmcnIGZvcm1hdCwgaS5lLiwgYSBjb2x1bW4gZm9yIGV2ZXJ5IHZhcmlhYmxlLCBhbmQgYSByb3cgZm9yIGV2ZXJ5IG9ic2VydmF0aW9uLCBzaW1pbGFyIHRvIHdoYXQgd2UgY3JlYXRlZCB3aXRoIGBnYXRoZXIoKWAuIFdlbGwtc3RydWN0dXJlZCBkYXRhIHdpbGwgc2F2ZSB5b3UgbG90cyBvZiB0aW1lIHdoZW4gbWFraW5nIGZpZ3VyZXMgd2l0aCAqKmBnZ3Bsb3QyYCoqLgoKQXMgd2Ugc2hhbGwgc2VlLCBnZ3Bsb3QgZ3JhcGhpY3MgYXJlIGJ1aWx0IHN0ZXAgYnkgc3RlcCBieSBhZGRpbmcgbmV3IGVsZW1lbnRzIHVzaW5nIHRoZSBgK2AuIEFkZGluZyBsYXllcnMgaW4gdGhpcyBmYXNoaW9uIGFsbG93cyBmb3IgZXh0ZW5zaXZlIGZsZXhpYmlsaXR5IGFuZCBjdXN0b21pemF0aW9uIG9mIHBsb3RzLgoKVG8gYnVpbGQgYSBnZ3Bsb3QsIHdlIHVzZSB0aGUgZm9sbG93aW5nIGJhc2ljIHRlbXBsYXRlIHRoYXQgY2FuIGJlIHVzZWQgZm9yIGRpZmZlcmVudCB0eXBlcyBvZiBwbG90cy4gVGhyZWUgdGhpbmdzIGFyZSByZXF1aXJlZCBmb3IgYSBnZ3Bsb3Q6CgohW10oaW1hZ2VzL2dncGxvdF90ZW1wbGF0ZS5wbmcpCgoxLiBUaGUgZGF0YQoyLiBUaGUgY29sdW1ucyBpbiB0aGUgZGF0YSB3ZSB3YW50IHRvIG1hcCB0byB2aXN1YWwgcHJvcGVydGllcyAoY2FsbGVkIGFlc3RoZXRpY3Mgb3IgYWVzIGluIGdncGxvdDIpIGUuZy4gdGhlIGNvbHVtbnMgZm9yIHggdmFsdWVzLCB5IHZhbHVlcyBhbmQgY29sb3VycwozLiBUaGUgdHlwZSBvZiBwbG90ICh0aGUgZ2VvbV8pCgpUaGVyZSBhcmUgZGlmZmVyZW50IGdlb21zIHdlIGNhbiB1c2UgdG8gY3JlYXRlIGRpZmZlcmVudCB0eXBlcyBvZiBwbG90IGUuZy4gYGdlb21fbGluZSgpYCBgZ2VvbV9wb2ludCgpYCwgYGdlb21fYm94cGxvdCgpYC4gVG8gc2VlIHRoZSBnZW9tcyBhdmFpbGFibGUgdGFrZSBhIGxvb2sgYXQgdGhlIGdncGxvdDIgaGVscCBvciB0aGUgaGFuZHkgW2dncGxvdDIgY2hlYXRzaGVldF0oaHR0cHM6Ly9naXRodWIuY29tL3JzdHVkaW8vY2hlYXRzaGVldHMvcmF3L21hc3Rlci9kYXRhLXZpc3VhbGl6YXRpb24tMi4xLnBkZikuIE9yIGlmIHlvdSB0eXBlICJnZW9tIiBpbiBSU3R1ZGlvLCBSU3R1ZGlvIHdpbGwgc2hvdyB5b3UgdGhlIGRpZmZlcmVudCB0eXBlcyBvZiBnZW9tcyB5b3UgY2FuIHVzZS4KCldlIGNhbiBtYWtlIGJveHBsb3RzIHRvIHZpc3VhbGlzZSB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBjb3VudHMgZm9yIGVhY2ggc2FtcGxlLiBUaGlzIGhlbHBzIHVzIHRvIGNvbXBhcmUgdGhlIHNhbXBsZXMgYW5kIGNoZWNrIGlmIGFueSBsb29rIHVudXN1YWwuICoqTm90ZSB0aGF0IHdpdGggZ2dwbG90IHRoZSAiKyIgbXVzdCBnbyBhdCB0aGUgZW5kIG9mIHRoZSBsaW5lLCBpdCBjYW4ndCBnbyBhdCB0aGUgYmVnaW5uaW5nLioqCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGxpbmZvLCBtYXBwaW5nID0gYWVzKHggPSBTYW1wbGUsIHkgPSBDb3VudCkpICsgCiAgZ2VvbV9ib3hwbG90KCkKYGBgCgpXZSBoYXZlIGdlbmVyYXRlZCBvdXIgZmlyc3QgcGxvdCEKCkJ1dCBpdCBsb29rcyBhIGJpdCB3ZWlyZC4gSXQncyBiZWNhdXNlIHdlIGhhdmUgc29tZSBnZW5lcyB3aXRoIGV4dHJlbWVseSBoaWdoIGNvdW50cy4gVG8gbWFrZSBpdCBlYXNpZXIgdG8gdmlzdWFsaXNlIHRoZSBkaXN0cmlidXRpb25zIHdlIHVzdWFsbHkgcGxvdCB0aGUgbG9nYXJpdGhtIG9mIFJOQS1zZXEgY291bnRzLiBXZSdsbCBwbG90IHRoZSBTYW1wbGUgb24gdGhlIFggYXhpcyBhbmQgbG9nfiAyfiAgQ291bnRzIG9uIHRoZSB5IGF4aXMuIFdlIGNhbiBsb2cgdGhlIENvdW50cyB3aXRoaW4gdGhlIGBhZXMoKWAuIFRoZSBzYW1wbGUgbGFiZWxzIGFyZSBhbHNvIG92ZXJsYXBwaW5nIGVhY2ggb3RoZXIsIHdlIHdpbGwgc2hvdyBob3cgdG8gZml4IHRoaXMgbGF0ZXIuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGxpbmZvLCBtYXBwaW5nID0gYWVzKHggPSBTYW1wbGUsIHkgPSBsb2cyKENvdW50KSkpICsgCiAgZ2VvbV9ib3hwbG90KCkKYGBgCgpOb3RlIHRoYXQgd2UgZ2V0IGEgd2FybmluZyBoZXJlIGFib3V0IHJvd3MgY29udGFpbmluZyBub24tZmluaXRlIHZhbHVlcyBiZWluZyByZW1vdmVkLiBUaGlzIGlzIGJlY2F1c2Ugc29tZSBvZiB0aGUgZ2VuZXMgaGF2ZSBhIGNvdW50IG9mIHplcm8gaW4gdGhlIHNhbXBsZXMgYW5kIGEgbG9nIG9mIHplcm8gaXMgdW5kZWZpbmVkLiBXZSBjYW4gYWRkIGEgc21hbGwgbnVtYmVyIHRvIGV2ZXJ5IGNvdW50IHRvIGF2b2lkIHRoZSB6ZXJvcyBiZWluZyBkcm9wcGVkLgoKYGBge3J9CmdncGxvdChkYXRhID0gYWxsaW5mbywgbWFwcGluZyA9IGFlcyh4ID0gU2FtcGxlLCB5ID0gbG9nMihDb3VudCArIDEpKSkgKyAKICBnZW9tX2JveHBsb3QoKQpgYGAKClRoZSBib3ggcGxvdHMgc2hvdyB0aGF0IHRoZSBkaXN0cmlidXRpb25zIG9mIHRoZSBzYW1wbGVzIGFyZSBub3QgaWRlbnRpY2FsIGJ1dCB0aGV5IGFyZSBub3QgdmVyeSBkaWZmZXJlbnQuCgpCb3ggcGxvdHMgYXJlIHVzZWZ1bCBzdW1tYXJpZXMsIGJ1dCBoaWRlIHRoZSBzaGFwZSBvZiB0aGUgZGlzdHJpYnV0aW9uLiBGb3IgZXhhbXBsZSwgaWYgdGhlIGRpc3RyaWJ1dGlvbiBpcyBiaW1vZGFsLCB3ZSB3b3VsZCBub3Qgc2VlIGl0IGluIGEgYm94cGxvdC4gQW4gYWx0ZXJuYXRpdmUgdG8gdGhlIGJveHBsb3QgaXMgdGhlICoqdmlvbGluIHBsb3QqKiwgd2hlcmUgdGhlIHNoYXBlIChvZiB0aGUgZGVuc2l0eSBvZiBwb2ludHMpIGlzIGRyYXduLiBTZWUgW2hlcmVdKGh0dHBzOi8vYmxvZy5iaW90dXJpbmcuY29tLzIwMTgvMDUvMTYvNS1yZWFzb25zLXlvdS1zaG91bGQtdXNlLWEtdmlvbGluLWdyYXBoLykgZm9yIGFuIGV4YW1wbGUgb2YgaG93IGRpZmZlcmVuY2VzIGluIGRpc3RyaWJ1dGlvbiBtYXkgYmUgaGlkZGVuIGluIGJveCBwbG90cyBidXQgcmV2ZWFsZWQgd2l0aCB2aW9saW4gcGxvdHMuIFdlIGNvdWxkIGFsc28gbWFrZSBqaXR0ZXIgcGxvdHMuIEEgKipqaXR0ZXIgcGxvdCoqIGlzIHNpbWlsYXIgdG8gYSBzY2F0dGVyIHBsb3QuIEl0IGFkZHMgYSBzbWFsbCBhbW91bnQgb2YgcmFuZG9tIHZhcmlhdGlvbiB0byB0aGUgbG9jYXRpb24gb2YgZWFjaCBwb2ludCBzbyB0aGV5IGRvbuKAmXQgb3ZlcmxhcC4gVGhlcmUgYXJlIHRvbyBtYW55IHBvaW50cyBpbiB0aGlzIGNhc2UgZm9yIHRoZSBqaXR0ZXIgcGxvdHMgdG8gYmUgdXNlZnVsIGJ1dCB0aGlzIGlzIGp1c3QgdG8gZGVtb25zdHJhdGUsIGFzIFtqaXR0ZXIgd2l0aCBhbmQgd2l0aG91dCBib3hwbG90XShodHRwczovL3NpbXBseXN0YXRpc3RpY3Mub3JnLzIwMTkvMDIvMjEvZHluYW1pdGUtcGxvdHMtbXVzdC1kaWUvKSBpcyBhIGNvbW1vbmx5IHVzZWQgZ2dwbG90IHR5cGUuIFdlIHdpbGwgYWxzbyBtYWtlIHVzZSBvZiBqaXR0ZXIgcGxvdHMgbGF0ZXIuCgojIyMjIEV4ZXJjaXNlcyAKWW91IGNhbiBlYXNpbHkgbWFrZSBkaWZmZXJlbnQgdHlwZXMgb2YgcGxvdHMgd2l0aCBnZ3Bsb3QgYnkgdXNpbmcgZGlmZmVyZW50IGdlb21zLiBVc2luZyB0aGUgc2FtZSBkYXRhIChzYW1lIHggYW5kIHkgdmFsdWVzKSwgdHJ5IGVkaXRpbmcgdGhlIGNvZGUgYWJvdmUgdG8gbWFrZSB0aGUgcGxvdHMgbGlzdGVkIGluIDEuIDIuIGFuZCAzLgoKMS4gTWFrZSBhIHZpb2xpbiBwbG90IChnZW9tX3Zpb2xpbikKMi4gTWFrZSBhIGppdHRlciBwbG90IChnZW9tX2ppdHRlcikKMy4gTWFrZSBhIGJveHBsb3Qgd2l0aCBhIGppdHRlciBwbG90IG92ZXJsYWlkIChIaW50OiB5b3UgY2FuIGFkZCBtdWx0aXBsZSBnZW9tcyB3aXRoICsgKQoKV2hhdCBpZiB3ZSB3b3VsZCBsaWtlIHRvIGFkZCBzb21lIGNvbG91ciB0byB0aGUgcGxvdCwgZm9yIGV4YW1wbGUsIGEgZGlmZmVyZW50IGNvbG91ciBmb3IgZWFjaCBzYW1wbGUuIAoKSWYgd2UgbG9vayBhdCB0aGUgYGdlb21fYm94cGxvdGAgaGVscCB3ZSBjYW4gc2VlIHVuZGVyIHRoZSBoZWFkaW5nIGNhbGxlZCAiQWVzdGhldGljcyIgdGhhdCB0aGVyZSdzIGFuIG9wdGlvbiBmb3IgY29sb3VyLiBMZXQncyB0cnkgYWRkaW5nIHRoYXQgdG8gb3VyIHBsb3QuIFdlJ2xsIHNwZWNpZnkgd2Ugd2FudCB0byBtYXAgdGhlIFNhbXBsZSBjb2x1bW4gdG8gYGNvbG91ciA9IGAuIEFzIHdlIGFyZSBtYXBwaW5nIGNvbG91ciB0byBhIGNvbHVtbiBpbiBvdXIgZGF0YSB3ZSBuZWVkIHRvIHB1dCB0aGlzIGluc2lkZSB0aGUgYGFlcygpYC4KCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGFsbGluZm8sIG1hcHBpbmcgPSBhZXMoeCA9IFNhbXBsZSwgeSA9IGxvZzIoQ291bnQgKyAxKSwgY29sb3VyID0gU2FtcGxlKSkgKyAKICBnZW9tX2JveHBsb3QoKQpgYGAKCkNvbG91cmluZyB0aGUgZWRnZXMgd2FzbuKAmXQgcXVpdGUgd2hhdCB3ZSBoYWQgaW4gbWluZC4gTG9vayBhdCB0aGUgaGVscCBmb3IgYGdlb21fYm94cGxvdGAgdG8gc2VlIHdoYXQgb3RoZXIgYWVzdGhldGljIHdlIGNvdWxkIHVzZS4gTGV0J3MgdHJ5IGBmaWxsID0gYCBpbnN0ZWFkLgoKYGBge3J9CmdncGxvdChkYXRhID0gYWxsaW5mbywgbWFwcGluZyA9IGFlcyh4ID0gU2FtcGxlLCB5ID0gbG9nMihDb3VudCArIDEpLCBmaWxsID0gU2FtcGxlKSkgKyAKICBnZW9tX2JveHBsb3QoKQpgYGAKClRoYXQgbG9va3MgYmV0dGVyLiBgZmlsbCA9IGAgaXMgdXNlZCB0byAqKmZpbGwqKiBpbiBhcmVhcyBpbiBnZ3Bsb3QyIHBsb3RzLCB3aGVyZWFzIGBjb2xvdXIgPSBgIGlzIHVzZWQgdG8gY29sb3VyIGxpbmVzIGFuZCBwb2ludHMuCgpBIHJlYWxseSBuaWNlIGZlYXR1cmUgYWJvdXQgZ2dwbG90IGlzIHRoYXQgd2UgY2FuIGVhc2lseSBjb2xvdXIgYnkgYW5vdGhlciB2YXJpYWJsZSBieSBzaW1wbHkgY2hhbmdpbmcgdGhlIGNvbHVtbiB3ZSBnaXZlIHRvIGBmaWxsID0gYC4KCiMjIyMgRXhlcmNpc2VzIApNb2RpZnkgdGhlIHBsb3QgYWJvdmUuIENvbG91ciBieSBvdGhlciB2YXJpYWJsZXMgKGNvbHVtbnMpIGluIHRoZSBtZXRhZGF0YSBmaWxlOgoKMS4gY2hhcmFjdGVyaXN0aWNzCjIuIGltbXVub3BoZW5vdHlwZQozLiBcYGRldmVsb3BtZW50YWwgc3RhZ2VcYCAoQXMgdGhlcmUgaXMgYSBzcGFjZSBpbiB0aGUgY29sdW1uIG5hbWUgd2UgbmVlZCB0byB1c2UgYmFja3RpY2tzIGFyb3VuZCB0aGUgbmFtZSAoXGBcYCkuIE5vdGUgdGhhdCBiYWNrdGlja3MgYXJlIG5vdCBzaW5nbGUgcXVvdGVzIChcJ1wnKS4gVGhlIGJhY2t0aWNrIGJ1dHRvbiBpcyB1c3VhbGx5IGF0IHRoZSB0b3AgbGVmdCBjb3JuZXIgb2YgYSBsYXB0b3Aga2V5Ym9hcmQgdW5kZXIgdGhlIEVTQyBidXR0b24uIENoZWNrIHdoYXQgaGFwcGVucyBpZiB5b3UgZG9uJ3QgdXNlIGJhY2t0aWNrcy4pCgoKIyBNYWtlIHN1YnBsb3RzIGZvciBlYWNoIGdlbmUKCldpdGggZ2dwbG90IHdlIGNhbiBlYXNpbHkgbWFrZSBzdWJwbG90cyB1c2luZyAqZmFjZXRpbmcqLiBGb3IgZXhhbXBsZSB3ZSBjYW4gbWFrZSBzdHJpcGNoYXJ0cywgcGxvdHRpbmcgZXhwcmVzc2lvbiBieSB0aGUgZ3JvdXBzIChiYXNhbCB2aXJnaW4sIGJhc2FsIHByZWduYW50LCBiYXNhbCBsYWN0YXRpbmcsIGx1bWluYWwgdmlyZ2luLCBsdW1pbmFsIHByZWduYW50LCBsdW1pbmFsIGxhY3RhdGluZykgZm9yIGVhY2ggZ2VuZS4gCgpGaXJzdCB3ZSdsbCB1c2UgYG11dGF0ZSgpYCB0byBhZGQgYSBjb2x1bW4gd2l0aCBzaG9ydGVyIGdyb3VwIG5hbWVzIHRvIHVzZSBpbiB0aGUgcGxvdCwgYXMgdGhlIGdyb3VwIG5hbWVzIGluIHRoZSBjaGFyYWN0ZXJpc3RpY3MgY29sdW1uIGFyZSBxdWl0ZSBsb25nLgoKYGBge3J9CiBhbGxpbmZvIDwtIG11dGF0ZShhbGxpbmZvLCBHcm91cCA9IGNhc2Vfd2hlbiggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgc3RyX2RldGVjdChjaGFyYWN0ZXJpc3RpY3MsICJiYXNhbC4qdmlyZ2luIikgfiAgImJ2aXJnIiwKICAgICAgICBzdHJfZGV0ZWN0KGNoYXJhY3RlcmlzdGljcywgImJhc2FsLipwcmVnIikgIH4gICJicHJlZyIsCiAgICAgICAgc3RyX2RldGVjdChjaGFyYWN0ZXJpc3RpY3MsICJiYXNhbC4qbGFjdCIpICB+ICAiYmxhY3QiLAogICAgICAgIHN0cl9kZXRlY3QoY2hhcmFjdGVyaXN0aWNzLCAibHVtaW5hbC4qdmlyZ2luIikgIH4gICJsdmlyZyIsCiAgICAgICAgc3RyX2RldGVjdChjaGFyYWN0ZXJpc3RpY3MsICJsdW1pbmFsLipwcmVnIikgIH4gICJscHJlZyIsCiAgICAgICAgc3RyX2RldGVjdChjaGFyYWN0ZXJpc3RpY3MsICJsdW1pbmFsLipsYWN0IikgIH4gICJsbGFjdCIKICAgICAgICkpCmBgYAoKSGF2ZSBhIGxvb2sgYXQgdGhpcyBkYXRhIHVzaW5nIGBoZWFkKClgLiBZb3Ugc2hvdWxkIHNlZSBhIG5ldyBjb2x1bW4gY2FsbGVkIGBHcm91cGAgaGFzIGJlZW4gYWRkZWQgdG8gdGhlIGVuZC4KCmBgYHtyfQpoZWFkKGFsbGluZm8pCmBgYAoKV2UgY2FuIG1ha2UgcGxvdHMgZm9yIGEgc2V0IG9mIGdlbmVzLgoKYGBge3J9Cm15Z2VuZXMgPC0gYygiQ3NuMXMyYSIsICJDc24xczEiLCAiQ3NuMiIsICJHbHljYW0xIiwgIkNPWDEiLCAiVHJmIiwgIldhcCIsICJFZWYxYTEiKQpgYGAKCj4gIyMjIyBOb3RlIG9uIHNwZWNpZnlpbmcgZ2VuZXMKPiBUaGlzIGV4YW1wbGUgaXMgdG8gZGVtb25zdHJhdGUgaG93IHdlIGNvdWxkIHNwZWNpZnkgYW55IGdlbmVzIGluIHRoZSBkYXRhIHRvIHBsb3QuIFRoZSBnZW5lcyB1c2VkIGhlcmUgd2VyZSB0aGUgOCBnZW5lcyB3aXRoIHRoZSBoaWdoZXN0IGNvdW50cyBzdW1tZWQgYWNyb3NzIGFsbCBzYW1wbGVzLiBUaGUgY29tbWFuZCBmb3IgaG93IHRvIGdldCB0aGUgZ2VuZSBzeW1ib2xzIGZvciB0aGVzZSA4IGdlbmVzIGlzIHNob3duIGJlbG93LiAgCj4gbXlnZW5lcyA8LSBhbGxpbmZvICU+JSAgCj4gIGdyb3VwX2J5KGdlbmVfc3ltYm9sKSAlPiUgIAo+ICBzdW1tYXJpc2UoVG90YWxfY291bnQgPSBzdW0oQ291bnQpKSAlPiUgIAo+ICBhcnJhbmdlKGRlc2MoVG90YWxfY291bnQpKSAlPiUgIAo+ICBoZWFkKG4gPSA4KSAlPiUgIAo+ICBwdWxsKGdlbmVfc3ltYm9sKSAKCldlIGZpbHRlciBvdXIgZGF0YSBmb3IganVzdCB0aGVzZSBnZW5lcyBvZiBpbnRlcmVzdC4gV2UgdXNlICVpbiUgdG8gY2hlY2sgaWYgYSB2YWx1ZSBpcyBpbiBhIHNldCBvZiB2YWx1ZXMuCgpgYGB7cn0KbXlnZW5lc19jb3VudHMgPC0gZmlsdGVyKGFsbGluZm8sIGdlbmVfc3ltYm9sICVpbiUgbXlnZW5lcykKYGBgCgpXZSBjYW4gbWFrZSBib3hwbG90cyBmb3IganVzdCB0aGVzZSBnZW5lcy4gV2UgKmZhY2V0KiBvbiB0aGUgYGdlbmVfc3ltYm9sYCBjb2x1bW4gdXNpbmcgYGZhY2V0X3dyYXAoKWAuIFdlIGFkZCB0aGUgdGlsZGUgc3ltYm9sIGB+IGAgaW4gZnJvbnQgb2YgdGhlIGNvbHVtbiB3ZSB3YW50IHRvIGZhY2V0IG9uLiAKCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IG15Z2VuZXNfY291bnRzLCBtYXBwaW5nID0gYWVzKHggPSBHcm91cCwgeSA9IGxvZzIoQ291bnQgKyAxKSwgZmlsbCA9IEdyb3VwKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBmYWNldF93cmFwKH4gZ2VuZV9zeW1ib2wpCmBgYAoKVGhlIGJveHBsb3RzIGRvbid0IGxvb2sgZ29vZCBhcyB3ZSBvbmx5IGhhdmUgdHdvIHZhbHVlcyBwZXIgZ3JvdXAuIFdlIGNvdWxkIGp1c3QgcGxvdCB0aGUgaW5kaXZpZHVhbCBwb2ludHMgaW5zdGVhZC4gV2UgY291bGQgdXNlIApgZ2VvbV9wb2ludCgpYCB0byBtYWtlIGEgc2NhdHRlcnBsb3QuCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IG15Z2VuZXNfY291bnRzLCBtYXBwaW5nID0gYWVzKHggPSBHcm91cCwgeSA9IGxvZzIoQ291bnQgKyAxKSkpICsKICBnZW9tX3BvaW50KCkgKwogIGZhY2V0X3dyYXAofiBnZW5lX3N5bWJvbCkKYGBgCgpUaGUgcG9pbnRzIGFyZSBvdmVybGFwcGluZyBzbyB3ZSB3aWxsIHVzZSBgZ2VvbV9qaXR0ZXIoKWAgd2hpY2ggYWRkcyBhIHNtYWxsIGFtb3VudCBvZiByYW5kb20gdmFyaWF0aW9uIHRvIHRoZSBwb2ludHMuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBteWdlbmVzX2NvdW50cywgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXAsIHkgPSBsb2cyKENvdW50ICsgMSkpKSArCiAgZ2VvbV9qaXR0ZXIoKSArCiAgZmFjZXRfd3JhcCh+IGdlbmVfc3ltYm9sKQpgYGAKCldlIGNhbiBjb2xvdXIgdGhlIGdyb3VwcyBzaW1pbGFyIHRvIGJlZm9yZSB1c2luZyBgY29sb3VyID0gYC4KCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IG15Z2VuZXNfY291bnRzLCBtYXBwaW5nID0gYWVzKHggPSBHcm91cCwgeSA9IGxvZzIoQ291bnQgKyAxKSwgY29sb3VyID0gR3JvdXApKSArCiAgZ2VvbV9qaXR0ZXIoKSArCiAgZmFjZXRfd3JhcCh+IGdlbmVfc3ltYm9sKSAKYGBgCgojIEN1c3RvbWlzaW5nIHRoZSBwbG90CgojIyMgU3BlY2lmeWluZyBjb2xvdXJzCgpXZSBtaWdodCB3YW50IHRvIGNoYW5nZSB0aGUgY29sb3Vycy4gVG8gc2VlIHdoYXQgY29sb3VyIG5hbWVzIGFyZSBhdmFpbGFibGUgeW91IGNhbiB0eXBlIGBjb2xvdXJzKClgLiBUaGVyZSBpcyBhbHNvIGFuIFtSIGNvbG91cnMgY2hlYXRzaGVldF0oaHR0cHM6Ly93d3cubmNlYXMudWNzYi5lZHUvfiBmcmF6aWVyL1JTcGF0aWFsR3VpZGVzL2NvbG9yUGFsZXR0ZUNoZWF0c2hlZXQucGRmKSB0aGF0IHNob3dzIHdoYXQgdGhlIGNvbG91cnMgbG9vayBsaWtlLgpgYGB7cn0KbXljb2xvdXJzIDwtIGMoInR1cnF1b2lzZSIsICJwbHVtIiwgInRvbWF0byIsICJ2aW9sZXQiLCAic3RlZWxibHVlIiwgImNob2NvbGF0ZSIpCmBgYAoKVGhlbiB3ZSB0aGVuIGFkZCB0aGVzZSBjb2xvdXJzIHRvIHRoZSBwbG90IHVzaW5nIGEgYCtgIGFuZCBgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBteWNvbG91cnMpYC4KCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IG15Z2VuZXNfY291bnRzLCBtYXBwaW5nID0gYWVzKHggPSBHcm91cCwgeSA9IGxvZzIoQ291bnQgKyAxKSwgY29sb3VyID0gR3JvdXApKSArCiAgZ2VvbV9qaXR0ZXIoKSArCiAgZmFjZXRfd3JhcCh+IGdlbmVfc3ltYm9sKSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBteWNvbG91cnMpCmBgYAoKVGhlcmUgYXJlIGJ1aWx0LWluIGNvbG91ciBwYWxldHRlcyB0aGF0IGNhbiBiZSBoYW5keSB0byB1c2UsIHdoZXJlIHRoZSBzZXRzIG9mIGNvbG91cnMgYXJlIHByZWRlZmluZWQuIGBzY2FsZV9jb2xvdXJfYnJld2VyKClgIGlzIGEgcG9wdWxhciBvbmUgKHRoZXJlIGlzIGFsc28gYHNjYWxlX2ZpbGxfYnJld2VyKClgKS4gWW91IGNhbiB0YWtlIGEgbG9vayBhdCB0aGUgaGVscCBmb3IgYHNjYWxlX2NvbG91cl9icmV3ZXIoKWAgdG8gc2VlIHdoYXQgcGFsZXR0ZXMgYXJlIGF2YWlsYWJsZS4gVGhlIFtSIGNvbG91cnMgY2hlYXRzaGVldF0oaHR0cHM6Ly93d3cubmNlYXMudWNzYi5lZHUvfiBmcmF6aWVyL1JTcGF0aWFsR3VpZGVzL2NvbG9yUGFsZXR0ZUNoZWF0c2hlZXQucGRmKSBhbHNvIHNob3dzIHdoYXQgdGhlIGNvbG91cnMgb2YgdGhlIHBhbGV0dGVzIGxvb2sgbGlrZS4gVGhlcmUncyBvbmUgY2FsbGVkICJEYXJrMiIsIGxldCdzIGhhdmUgYSBsb29rIGF0IHRoYXQuIAoKYGBge3J9CmdncGxvdChkYXRhID0gbXlnZW5lc19jb3VudHMsIG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLCB5ID0gbG9nMihDb3VudCArIDEpLCBjb2xvdXIgPSBHcm91cCkpICsKICBnZW9tX2ppdHRlcigpICsKICBmYWNldF93cmFwKH4gZ2VuZV9zeW1ib2wpICsKICBzY2FsZV9jb2xvdXJfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKQpgYGAKCgojIyMjIEV4ZXJjaXNlcwpNYWtlIGEgY29sb3VyYmxpbmQgZnJpZW5kbHkgcGxvdC4gSGludCB0aGVyZSBhcmUgY29sb3VyYmxpbmQgZnJpZW5kbHkgcGFsZXR0ZXMgW2hlcmVdKGh0dHA6Ly93d3cuY29va2Jvb2stci5jb20vR3JhcGhzL0NvbG9yc18oZ2dwbG90MikvI2EtY29sb3JibGluZC1mcmllbmRseS1wYWxldHRlKQoKIyMjIEF4aXMgbGFiZWxzIGFuZCBUaXRsZQoKV2UgY2FuIGNoYW5nZSB0aGUgYXhpcyBsYWJlbHMgYW5kIGFkZCBhIHRpdGxlIHdpdGggYGxhYnMoKWAuIFRvIGNoYW5nZSB0aGUgeCBheGlzIGxhYmVsIHdlIHVzZSBgbGFicyh4ID0gIk5ldyBuYW1lIilgLiBUbyBjaGFuZ2UgdGhlIHkgYXhpcyBsYWJlbCB3ZSB1c2UgYGxhYnMoeSA9ICJOZXcgbmFtZSIpYCBvciB3ZSBjYW4gY2hhbmdlIHRoZW0gYWxsIGF0IHRoZSBzYW1lIHRpbWUuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBteWdlbmVzX2NvdW50cywgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXAsIHkgPSBsb2cyKENvdW50ICsgMSksIGNvbG91ciA9IEdyb3VwKSkgKwogIGdlb21faml0dGVyKCkgKwogIGZhY2V0X3dyYXAofiBnZW5lX3N5bWJvbCkgKyAKICBsYWJzKHggPSAiQ2VsbCB0eXBlIGFuZCBzdGFnZSIsIHkgPSAiQ291bnQiLCB0aXRsZSA9ICJNYW1tYXJ5IGdsYW5kIFJOQS1zZXEgZGF0YSIpCmBgYAoKIyMjIFRoZW1lcwoKV2UgY2FuIGFkanVzdCB0aGUgdGV4dCBvbiB0aGUgeCBheGlzICh0aGUgZ3JvdXAgbGFiZWxzKSBieSB0dXJuaW5nIHRoZW0gOTAgZGVncmVlcyBzbyB3ZSBjYW4gcmVhZCB0aGUgbGFiZWxzIGJldHRlci4gVG8gZG8gdGhpcyB3ZSBtb2RpZnkgdGhlIGdncGxvdCB0aGVtZS4gVGhlbWVzIGFyZSB0aGUgbm9uLWRhdGEgcGFydHMgb2YgdGhlIHBsb3QuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBteWdlbmVzX2NvdW50cywgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXAsIHkgPSBsb2cyKENvdW50ICsgMSksIGNvbG91ciA9IEdyb3VwKSkgKwogIGdlb21faml0dGVyKCkgKwogIGZhY2V0X3dyYXAofiBnZW5lX3N5bWJvbCkgKyAKICBsYWJzKHggPSAiQ2VsbCB0eXBlIGFuZCBzdGFnZSIsIHkgPSAiQ291bnQiLCB0aXRsZSA9ICJNYW1tYXJ5IGdsYW5kIFJOQS1zZXEgZGF0YSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKYGBgCgpXZSBjYW4gcmVtb3ZlIHRoZSBncmV5IGJhY2tncm91bmQgYW5kIGdyaWQgbGluZXMuCgpUaGVyZSBhcmUgYWxzbyBhIGxvdCBvZiBidWlsdC1pbiB0aGVtZXMuIExldCdzIGhhdmUgYSBsb29rIGF0IGEgY291cGxlIG9mIHRoZSBtb3JlIHdpZGVseSB1c2VkIHRoZW1lcy4gVGhlIGRlZmF1bHQgZ2dwbG90IHRoZW1lIGlzIGB0aGVtZV9ncmV5KCkuYAoKYGBge3J9CmdncGxvdChkYXRhID0gbXlnZW5lc19jb3VudHMsIG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLCB5ID0gbG9nMihDb3VudCArIDEpLCBjb2xvdXIgPSBHcm91cCkpICsKICBnZW9tX2ppdHRlcigpICsKICBmYWNldF93cmFwKH4gZ2VuZV9zeW1ib2wpICsgCiAgbGFicyh4ID0gIkNlbGwgdHlwZSBhbmQgc3RhZ2UiLCB5ID0gIkNvdW50IiwgdGl0bGUgPSAiTWFtbWFyeSBnbGFuZCBSTkEtc2VxIGRhdGEiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCmBgYAoKYGBge3J9CmdncGxvdChkYXRhID0gbXlnZW5lc19jb3VudHMsIG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLCB5ID0gbG9nMihDb3VudCArIDEpLCBjb2xvdXIgPSBHcm91cCkpICsKICBnZW9tX2ppdHRlcigpICsKICBmYWNldF93cmFwKH4gZ2VuZV9zeW1ib2wpICsgCiAgbGFicyh4ID0gIkNlbGwgdHlwZSBhbmQgc3RhZ2UiLCB5ID0gIkNvdW50IiwgdGl0bGUgPSAiTWFtbWFyeSBnbGFuZCBSTkEtc2VxIGRhdGEiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKYGBgCgpUaGVyZSBhcmUgbWFueSB0aGVtZXMgYXZhaWxhYmxlLCB5b3UgY2FuIHNlZSBzb21lIGluIHRoZSBbUiBncmFwaCBnYWxsZXJ5XShodHRwczovL3d3dy5yLWdyYXBoLWdhbGxlcnkuY29tLzE5Mi1nZ3Bsb3QtdGhlbWVzLykuCgpXZSBjYW4gYWxzbyBtb2RpZnkgcGFydHMgb2YgdGhlIHRoZW1lIGluZGl2aWR1YWxseS4gV2UgY2FuIHJlbW92ZSB0aGUgZ3JleSBiYWNrZ3JvdW5kIGFuZCBncmlkIGxpbmVzIHdpdGggdGhlIGNvZGUgYmVsb3cuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBteWdlbmVzX2NvdW50cywgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXAsIHkgPSBsb2cyKENvdW50ICsgMSksIGNvbG91ciA9IEdyb3VwKSkgKwogIGdlb21faml0dGVyKCkgKwogIGZhY2V0X3dyYXAofiBnZW5lX3N5bWJvbCkgKyAKICBsYWJzKHggPSAiQ2VsbCB0eXBlIGFuZCBzdGFnZSIsIHkgPSAiQ291bnQiLCB0aXRsZSA9ICJNYW1tYXJ5IGdsYW5kIFJOQS1zZXEgZGF0YSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkgKyAKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCiMjIyBPcmRlciBvZiBncm91cHMKClRoZSBncm91cHMgaGF2ZSBiZWVuIHBsb3R0ZWQgaW4gYWxwaGFiZXRpY2FsIG9yZGVyIG9uIHRoZSB4IGF4aXMgYW5kIGluIHRoZSBsZWdlbmQgKHRoYXQgaXMgdGhlIGRlZmF1bHQgb3JkZXIpLCBob3dldmVyLCB3ZSBtYXkgd2FudCB0byBjaGFuZ2UgdGhlIG9yZGVyLiBXZSBtYXkgcHJlZmVyIHRvIHBsb3QgdGhlIGdyb3VwcyBpbiBvcmRlciBvZiBzdGFnZSwgZm9yIGV4YW1wbGUsIGJhc2FsIHZpcmdpbiwgYmFzYWwgcHJlZ25hbnQsIGJhc2FsIGxhY3RhdGUsIGx1bWluYWwgdmlyZ2luLCBsdW1pbmFsIHByZWduYW50LCBsdW1pbmFsIGxhY3RhdGUuCgpGaXJzdCBsZXQncyBtYWtlIGFuIG9iamVjdCB3aXRoIHRoZSBncm91cCBvcmRlciB0aGF0IHdlIHdhbnQuCmBgYHtyfQpncm91cF9vcmRlciA8LSBjKCJidmlyZyIsICJicHJlZyIsICJibGFjdCIsICJsdmlyZyIsICJscHJlZyIsICJsbGFjdCIpCmBgYAoKTmV4dCB3ZSBuZWVkIHRvIG1ha2UgYSBjb2x1bW4gd2l0aCB0aGUgZ3JvdXBzIGludG8gYW4gUiBkYXRhIHR5cGUgY2FsbGVkIGEgKipmYWN0b3IqKi4gRmFjdG9ycyBpbiBSIGFyZSBhIHNwZWNpYWwgZGF0YSB0eXBlIHVzZWQgdG8gc3BlY2lmeSBjYXRlZ29yaWVzLCB5b3UgY2FuIHJlYWQgbW9yZSBhYm91dCB0aGVtIGluIHRoZSBbUiBmb3IgRGF0YSBTY2llbmNlIGJvb2tdKGh0dHBzOi8vcjRkcy5oYWQuY28ubnovdmVjdG9ycy5odG1sI2F1Z21lbnRlZC12ZWN0b3JzKS4gVGhlIG5hbWVzIG9mIHRoZSBjYXRlZ29yaWVzIGFyZSBjYWxsZWQgdGhlIGZhY3RvciAqKmxldmVscyoqLiAKCldlJ2xsIGFkZCBhbm90aGVyIGNvbHVtbiBjYWxsZWQgIkdyb3VwX2YiIHdoZXJlIHdlJ2xsIG1ha2UgdGhlIEdyb3VwIGNvbHVtbiBpbnRvIGEgZmFjdG9yIGFuZCBzcGVjaWZ5IHdoYXQgb3JkZXIgd2Ugd2FudCB0aGUgbGV2ZWxzIG9mIHRoZSBmYWN0b3IuCgpgYGB7cn0KbXlnZW5lc19jb3VudHMgPC0gbXV0YXRlKG15Z2VuZXNfY291bnRzLCBHcm91cF9mID0gZmFjdG9yKEdyb3VwLCBsZXZlbHMgPSBncm91cF9vcmRlcikpCmBgYAoKVGFrZSBhIGxvb2sgYXQgdGhlIGRhdGEuIEFzIHRoZSB0YWJsZSBpcyBxdWl0ZSB3aWRlIHdlIGNhbiB1c2UgYHNlbGVjdCgpYCB0byBzZWxlY3QganVzdCB0aGUgY29sdW1ucyB3ZSB3YW50IHRvIHZpZXcuCgpgYGB7cn0KbXlnZW5lc19jb3VudHMgJT4lIHNlbGVjdChYMSwgR3JvdXAsIEdyb3VwX2YpCmBgYAoKTm90aWNlIHRoYXQgdGhlIEdyb3VwIGNvbHVtbiBoYXMgYDxjaHI+YCB1bmRlciB0aGUgaGVhZGluZywgdGhhdCBpbmRpY2F0ZXMgaXMgYSBjaGFyYWN0ZXIgZGF0YSB0eXBlLCB3aGlsZSB0aGUgR3JvdXBfZiBjb2x1bW4gaGFzIGA8ZmN0PmAgdW5kZXIgdGhlIGhlYWRpbmcsIGluZGljYXRpbmcgaXQgaXMgYSBmYWN0b3IgZGF0YSB0eXBlLiBUaGUgYHN0cigpYCBjb21tYW5kIHRoYXQgd2Ugc2F3IHByZXZpb3VzbHkgaXMgdXNlZnVsIHRvIGNoZWNrIHRoZSBkYXRhIHR5cGVzIGluIG9iamVjdHMuCgpgYGB7cn0Kc3RyKG15Z2VuZXNfY291bnRzKQpgYGAKCmBzdHIoKWAgc2hvd3MgdXMgR3JvdXBfZiBjb2x1bW4gaXMgYSBGYWN0b3Igd2l0aCA2IGxldmVscyAoY2F0ZWdvcmllcykuCgpXZSBjYW4gY2hlY2sgdGhlIGZhY3RvciBsZXZlbHMgb2YgYSBjb2x1bW4gYXMgYmVsb3cuCgpgYGB7cn0KbGV2ZWxzKG15Z2VuZXNfY291bnRzJEdyb3VwX2YpCmBgYAoKVGhlIGxldmVscyBhcmUgaW4gdGhlIG9yZGVyIHRoYXQgd2Ugd2FudCwgc28gd2UgY2FuIG5vdyBjaGFuZ2Ugb3VyIHBsb3QgdG8gdXNlIHRoZSAiR3JvdXBfZiIgY29sdW1uIGluc3RlYWQgb2YgR3JvdXAgY29sdW1uIChjaGFuZ2UgYHggPSBgIGFuZCBgY29sb3VyID0gYCkuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBteWdlbmVzX2NvdW50cywgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXBfZiwgeSA9IGxvZzIoQ291bnQgKyAxKSwgY29sb3VyID0gR3JvdXBfZikpICsKICBnZW9tX2ppdHRlcigpICsKICBmYWNldF93cmFwKH4gZ2VuZV9zeW1ib2wpICsgCiAgbGFicyh4ID0gIkNlbGwgdHlwZSBhbmQgc3RhZ2UiLCB5ID0gIkNvdW50IiwgdGl0bGUgPSAiTWFtbWFyeSBnbGFuZCBSTkEtc2VxIGRhdGEiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpICsgCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSkKYGBgCldlIGNvdWxkIGRvIHNpbWlsYXIgaWYgd2Ugd2FudGVkIHRvIGhhdmUgdGhlIGdlbmVzIGluIHRoZSBmYWNldHMgaW4gYSBkaWZmZXJlbnQgb3JkZXIuIEZvciBleGFtcGxlLCB3ZSBjb3VsZCBhZGQgYW5vdGhlciBjb2x1bW4gY2FsbGVkICJnZW5lX3N5bWJvbF9mIiB3aGVyZSB3ZSBtYWtlIHRoZSBnZW5lX3N5bWJvbCBjb2x1bW4gaW50byBhIGZhY3Rvciwgc3BlY2lmeWluZyB0aGUgb3JkZXIgb2YgdGhlIGxldmVscy4KCiMgU2F2aW5nIHBsb3RzCldlIGNhbiBzYXZlIHBsb3RzIGludGVyYWN0aXZlbHkgYnkgY2xpY2tpbmcgRXhwb3J0IGluIHRoZSBQbG90cyB3aW5kb3cgYW5kIHNhdmluZyBhcyBlLmcuICJteXBsb3QucGRmIi4gT3Igd2UgY2FuIG91dHB1dCBwbG90cyB0byBwZGYgdXNpbmcgYHBkZigpYCBmb2xsb3dlZCBieSBgZGV2Lm9mZigpYC4gV2UgcHV0IG91ciBwbG90IGNvZGUgYWZ0ZXIgdGhlIGNhbGwgdG8gYHBkZigpYCBhbmQgYmVmb3JlIGNsb3NpbmcgdGhlIHBsb3QgZGV2aWNlIHdpdGggYGRldi5vZmYoKWAuCgpMZXQncyBzYXZlIG91ciBsYXN0IHBsb3QuCgpgYGB7ciwgZXZhbD1GQUxTRX0KcGRmKCJteXBsb3QucGRmIikKZ2dwbG90KGRhdGEgPSBteWdlbmVzX2NvdW50cywgbWFwcGluZyA9IGFlcyh4ID0gR3JvdXBfZiwgeSA9IGxvZzIoQ291bnQgKyAxKSwgY29sb3VyID0gR3JvdXBfZikpICsKICBnZW9tX2ppdHRlcigpICsKICBmYWNldF93cmFwKH4gZ2VuZV9zeW1ib2wpICsgCiAgbGFicyh4ID0gIkNlbGwgdHlwZSBhbmQgc3RhZ2UiLCB5ID0gIkNvdW50IiwgdGl0bGUgPSAiTWFtbWFyeSBnbGFuZCBSTkEtc2VxIGRhdGEiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpICsgCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSkKZGV2Lm9mZigpCmBgYAoKCiMjIyMgRXhlcmNpc2VzCjEuIERvd25sb2FkIHRoZSByYXcgY291bnRzIGZvciB0aGlzIGRhdGFzZXQKICBhLiBNYWtlIGEgYm94cGxvdC4gRG8gdGhlIHNhbXBsZXMgbG9vayBhbnkgZGlmZmVyZW50IHRvIHRoZSBub3JtYWxpc2VkIGNvdW50cz8KICBiLiBNYWtlIHN1YnBsb3RzIGZvciB0aGUgc2FtZSBzZXQgb2YgOCBnZW5lcy4gRG8gdGhleSBsb29rIGFueSBkaWZmZXJlbnQgdG8gdGhlIG5vcm1hbGlzZWQgY291bnRzPwoyLiBEb3dubG9hZCB0aGUgbm9ybWFsaXNlZCBjb3VudHMgZm9yIHRoZSBHU0U2MzMxMCBkYXRhc2V0IGZyb20gR1JFSU4uIE1ha2UgYm94cGxvdHMgY29sb3VyaW5nIHRoZSBzYW1wbGVzIHVzaW5nIGRpZmZlcmVudCBjb2x1bW5zIGluIHRoZSBtZXRhZGF0YSBmaWxlLgoKCiMgS2V5IFBvaW50cwotIFRhYnVsYXIgZGF0YSBjYW4gYmUgbG9hZGVkIGludG8gUiB3aXRoIHRoZSB0aWR5dmVyc2UgZnVuY3Rpb25zIGByZWFkX2NzdigpYCBhbmQgYHJlYWRfdHN2KClgCi0gVGlkeXZlcnNlIGZ1bmN0aW9ucyBzdWNoIGFzIGBmdWxsX2pvaW4oKWAsIGBnYXRoZXIoKWAsIGBtdXRhdGUoKWAsIGBmaWx0ZXIoKWAgY2FuIGJlIHVzZWQgdG8gbWFuaXB1bGF0ZSBkYXRhCi0gQSBnZ3Bsb3QgaGFzIDMgY29tcG9uZW50czogZGF0YSAoZGF0YXNldCksIG1hcHBpbmcgKGNvbHVtbnMgdG8gcGxvdCkgYW5kIGdlb20gKHR5cGUgb2YgcGxvdCkuIERpZmZlcmVudCB0eXBlcyBvZiBwbG90cyBpbmNsdWRlIGBnZW9tX3BvaW50KClgLCBgZ2VvbV9qaXR0ZXIoKWAsIGBnZW9tX2xpbmUoKWAsIGBnZW9tX2JveHBsb3QoKWAsIGBnZW9tX3Zpb2xpbigpYC4KLSBgZmFjZXRfd3JhcCgpYCBjYW4gYmUgdXNlZCB0byBtYWtlIHN1YnBsb3RzIG9mIHRoZSBkYXRhCi0gVGhlIGFlc3RoZXRpY3Mgb2YgYSBnZ3Bsb3QgY2FuIGJlIG1vZGlmaWVkLCBzdWNoIGFzIGNvbG91cmluZyBieSBkaWZmZXJlbnQgY29sdW1ucyBpbiB0aGUgZGF0YXNldCwgYWRkaW5nIGxhYmVscyBvciBjaGFuZ2luZyB0aGUgYmFja2dyb3VuZAoKCiMgRnVydGhlciBSZWFkaW5nCltJbnRybyB0byBSIGFuZCB0aWR5dmVyc2VdKGh0dHBzOi8vcG1hY2Rhc2NpLmdpdGh1Yi5pby9yLWludHJvLXRpZHl2ZXJzZS8pICAKW1RvcCA1MCBHZ3Bsb3QgVmlzdWFsaXNhdGlvbnNdKCBodHRwOi8vci1zdGF0aXN0aWNzLmNvL1RvcDUwLUdncGxvdDItVmlzdWFsaXphdGlvbnMtTWFzdGVyTGlzdC1SLUNvZGUuaHRtbCkgIApbUiBmb3IgRGF0YSBTY2llbmNlXShodHRwczovL3I0ZHMuaGFkLmNvLm56LykK