Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

DOI

1 How to cite this R Notebook

Please cite this R Notebook as follows (in Unified Style Sheet for Linguistics):

Rajeg, Gede Primahadi Wijaya, Karlina Denistia & Simon Musgrave. 2019. R Markdown Notebook for Vector space model and the usage patterns of Indonesian denominal verbs. figshare. https://doi.org10.6084/m9.figshare.9970205. https://figshare.com/articles/R_Markdown_Notebook_for_i_Vector_space_model_and_the_usage_patterns_of_Indonesian_denominal_verbs_i_/9970205.

2 Preface

This is an R Markdown Notebook (Rajeg, Denistia & Musgrave 2019a) for the statistical analyses accompanying our paper (Rajeg, Denistia & Musgrave 2019b) on vector space models and Indonesian denominal verbs (published in NUSA’s special issue titled Linguistic studies using large annotated corpora, edited by Hiroki Nomoto and David Moeljadi) (Nomoto & Moeljadi 2019). The Notebook, however, does not provide detailed exposition and discussion for each points, including English glossing of the Indonesian words in the tables. Readers are referred to our paper for details. Check the README page here for the tutorial to download this Notebook and the data (Rajeg, Denistia & Musgrave 2019c) for the paper.

The following R packages have to be installed and loaded to run all codes in this Notebook:

  • cluster (Maechler et al. 2018)
  • tidyverse (Wickham & Grolemund 2017)
  • dendextend (Galili 2015)
  • wordVectors (Schmidt & Li 2017)
  • Rling (Levshina 2015)

Click the Code button to hide/reveal the R codes.

3 Illustration for generating Vector Space Models (VSM)

For illustration, we used six deverbal nouns with the suffix -an. They are bacaan ‘reading’ (from the root baca ‘to read’), tulisan ‘writing’ (from tulis ‘to write’), lukisan ‘painting’ (from lukis ‘to paint/draw’), masakan ‘cooking’ (from masak ‘to cook’), makanan ‘food’ (from makan ‘to eat’), and minuman ‘beverages’ (from minum ‘to drink’). We retrieved collocates within three-word window to the either sides (left and right) of each noun. We used one of the Indonesian Leipzig Corpora files, namely ind_mixed_2012_1M-sentences.txt (see Biemann et al. 2007; Quasthoff & Goldhahn 2013).

3.1 Creating the co-occurrence frequency table

The following codes process the retrieved collocates into co-occurrence frequency table and print a subset of this table. The collocates data is available in the "vsm_creation_data.rds" file. This .rds file contains a List data-structure; the table version is available as tab-delimited .csv and .txt files (vsm_creation_data_tb.txt & vsm_creation_data_tb.csv).

alkitab dituangkan halal keras mengandung penutup
bacaan 31 0 0 0 0 0
lukisan 0 0 0 1 0 0
makanan 0 0 19 12 55 7
masakan 0 0 0 0 1 0
minuman 0 0 0 150 14 0
tulisan 16 6 0 2 2 0

3.2 Performing the Positive Pointwise Mutual Information

Current approach in VSM adopts a more principled method of weighting the initial raw-frequency vectors into statistical measures of collocation strength before computing (dis)similarity measure between the target words. The goal of the weighting is “to give a higher weight to context words that co-occur significantly more often than expected by chance” (Heylen et al. 2015:156; cf. Clark 2015:503–504; Perek 2016:12). These significantly associatied context words are assumed to be more informative for the semantics of the target words (Heylen et al. 2015:156). The popular weighting measure used in VSM is the Pointwise Mutual Information (PMI) (see Levshina 2015:327–328 for computing PMI in R):

\[\text{PMI } (x, y) = log_{2} \frac {O_{xy}} {E_{xy}}\]

where \(O_{xy}\) represents the observed co-occurrence frequency between x and y, while \(E_{xy}\) is their expected co-occurrence frequency, which is the frequency expected under the chance distribution between x and y given the overall distribution of x and y in the corpus. Negative PMI values is normally replaced with zero, resulting in the Positive PMI (PPMI) (Levshina 2015; Hilpert & Perek 2015).

alkitab dituangkan halal keras mengandung penutup
bacaan 3.62 0.00 0.00 0.00 0.00 0.00
lukisan 0.00 0.00 0.00 0.00 0.00 0.00
makanan 0.00 0.00 1.05 0.00 0.67 1.05
masakan 0.00 0.00 0.00 0.00 0.00 0.00
minuman 0.00 0.00 0.00 3.07 0.85 0.00
tulisan 0.31 1.87 0.00 0.00 0.00 0.00

Further analysis can be performed. The most common one is determining the semantic (dis)similarity between the target words (i.e., which word is more similar and different among each other). The following section briefly discusses the Cosine Similarity and Hierarchical Agglomerative Cluster (HAC) analyses as the exploratory tools (Levshina 2014; Levshina 2015).

3.3 Exploring VSM with Cosine Similarity and Hierarchical Agglomerative Cluster (HAC) analysis

In VSM, cosine similarity is the popular measure for computing pairwise (dis)similarity between the target words. Cosine similarity computes the cosine of angles between the words’ vectors to capture their (dis)similarity. The cosine value between a pair of word is close to 1 when they are semantically more similar, and close to 0 when otherwise (see @ref(tab:vsm-xmpl-cossim)) (Levshina 2015, Ch. 16).

The following codes perform cosine similarity using the cossim() function from the Rling package (Levshina 2015:329).

bacaan lukisan makanan masakan minuman tulisan
bacaan 1.00 0.04 0.02 0.03 0.02 0.06
lukisan 0.04 1.00 0.01 0.03 0.04 0.04
makanan 0.02 0.01 1.00 0.03 0.03 0.00
masakan 0.03 0.03 0.03 1.00 0.04 0.02
minuman 0.02 0.04 0.03 0.04 1.00 0.02
tulisan 0.06 0.04 0.00 0.02 0.02 1.00

For the cluster analysis, such as HAC (Levshina 2014; see also Gries 2013:336; Levshina 2015, Ch. 15; and Desagulier 2017:276 for R implementations on HAC), the similarity matrix/table as above needs to be converted into distance matrix as input for the cluster analysis (see the codes below adapted from Levshina 2015:330).

The output of HAC can be visualised into a dendrogram tree (see Figure @ref(fig:vsm-xmpl-dendrogram)). To determine the optimal number of cluster solution for grouping the nouns, we used the Average Silhouette Width (ASW) scores and tested two up to five-cluster solutions. The two-cluster solution produces the highest ASW score. See the codes below.

The following codes produce the plot visualising the number of cluster-solutions tested and their corresponding ASW scores.

4 Methodology

4.1 Data source

The paper uses thirteen corpus files from the Indonesian Leipzig Corpora to be trained into a vector space models. The following codes show how to load the data for the information of corpus size (i.e. "wordcount_leipzig_allcorpus.RData") and to print them.

Corpus files Size (in word-tokens)
1 ind_mixed_2012_1M-sentences.txt 15,052,159
2 ind_news_2008_300K-sentences.txt 5,875,376
3 ind_news_2009_300K-sentences.txt 5,868,276
4 ind_news_2010_300K-sentences.txt 5,874,158
5 ind_news_2011_300K-sentences.txt 5,852,211
6 ind_news_2012_300K-sentences.txt 5,873,523
7 ind_newscrawl_2011_1M-sentences.txt 16,376,426
8 ind_newscrawl_2012_1M-sentences.txt 16,916,778
9 ind_web_2011_300K-sentences.txt 4,472,885
10 ind_web_2012_1M-sentences.txt 15,844,629
11 ind_wikipedia_2016_1M-sentences.txt 16,506,714
12 ind-id_web_2013_1M-sentences.txt 16,406,671
13 ind-id_web_2015_3M-sentences.txt 49,849,398

In total, the thirteen corpus files amount to 180,769,204 million word-tokens.

4.2 The studied denominal verbs

The database for the studied verbs is available in the .rds, .csv, and .txt tab-delimited files named "me_parsed_nountaggedbase". The verbs have been parsed and tagged using MorphInd (Larasati, Kuboň & Zeman 2011). We limited the study on the verbs with noun-tagged roots that occur over 20 tokens. For each root, all the verb forms must occur in the three morphological schemas, namely meN-, meN-/-kan, and meN-/-i. For instance, we take mendasar ‘to be basic’, mendasari ‘to underlie sth.’, and mendasarkan ‘to base sth. on’ that are all derived from the nominal root dasar ‘base; foundation’.

The following codes show the filtering processes to retrieve the relevant verbs and Table @ref(tab:studied-verbs-retrieval) shows the snippet of the database.

word token_freq base base_pos morphind affix
mendasar 4571 dasar n meN+dasar<n>_VSA me
mendasari 1365 dasar n meN+dasar<n>+i_VSA me.i
mendasarkan 781 dasar n meN+dasar<n>+kan_VSA me.kan

In total, we analysed 51 denominal verbs based on 17 root types occurring in three morphological schemas.

We mention in the paper about checking the existence of the studied verbs with MALINDO Morph, a morphological dictionary for Indonesian and Malay (Nomoto et al. 2018). We checked it with the latest version of MALINDO Morph from the file named "malindo_dic_20181125.tsv" that has been saved as "malindo_dbase.rds" (an R type of data) and tab-delimited .csv file ("malindo_dbase.csv"). The following codes document the checking processes. The printed verbs are those absent from MALINDO Morph but available in our corpus occurring over 20 tokens overall.

[1] "mengakhir"  "membuah"    "mengantung" "mewakil"   
[5] "mewaris"   

As MALINDO Morph is also based on the Leipzig Corpora, it only takes into account words occurring over ten tokens in all the 300K-sentences version of the corpus (Nomoto et al. 2018). Our frequency check of these absent verbs confirms that they all occur less than ten tokens in the 300K-sentence files that we use. The following codes show these information.

corpus word n
1 ind_news_2008_300K membuah 5
2 ind_news_2009_300K membuah 3
3 ind_news_2010_300K membuah 1
4 ind_news_2011_300K membuah 2
5 ind_news_2012_300K membuah 5
6 ind_web_2011_300K membuah 1
7 ind_news_2008_300K mengakhir 2
8 ind_news_2009_300K mengakhir 5
9 ind_news_2010_300K mengakhir 3
10 ind_news_2011_300K mengakhir 6
11 ind_news_2011_300K mengantung 1
12 ind_news_2012_300K mengantung 1
13 ind_news_2009_300K mewakil 2
14 ind_news_2010_300K mewakil 2
15 ind_news_2011_300K mewakil 4
16 ind_web_2011_300K mewaris 1

4.3 Load the vector space models for the Indonesian Leipzig Corpora

Detailed information concerning the training parameters is available in our paper. In short, we trained the Leipzig Corpora on the MonARCH HPC using the skip-gram learning algorithm from the word2vec model (Mikolov, Chen, et al. 2013; Mikolov, Sutskever, et al. 2013; Mikolov, Yih & Zweig 2013) via the wordVectors R package (Schmidt & Li 2017). The output model is available as .bin file named "leipzig_w2v_vector_full.bin". The following codes show how the model is loaded into R using read.binary.vectors() from wordVectors package.

To retrieve the vector space model (VSM) of the target denominal verbs, use the following codes.

A VectorSpaceModel object of  51  words and  100  vectors
                    [,1]        [,2]        [,3]        [,4]
mengatakan   -0.15838896  0.05143370  0.02442524  0.24287735
menggunakan  -0.10439277  0.07838520  0.18227956  0.38019755
mewakili     -0.25855595 -0.09868021  0.05797758  0.19394790
menempatkan   0.01809703 -0.01772323  0.24649994  0.12339904
menempati    -0.17115426 -0.10566988  0.16301627  0.17471313
mengakhiri    0.24585645  0.12317820 -0.12496730  0.18348111
melangkah     0.14984114  0.02910020  0.04853236 -0.34504056
mencontohkan -0.24159168  0.01203183  0.07734830  0.13243185
mendasar     -0.45044890 -0.07471947  0.37076223 -0.02369694
menandai      0.01873370  0.19389461  0.17055722  0.15514162
                     [,5]         [,6]
mengatakan   -0.037270460 -0.128047243
menggunakan  -0.012107351 -0.019670846
mewakili     -0.219191238 -0.049940147
menempatkan   0.090888657 -0.063201532
menempati    -0.105571389 -0.090712421
mengakhiri   -0.032905310 -0.200849608
melangkah    -0.339647442 -0.008438474
mencontohkan  0.002526026  0.068748802
mendasar      0.357669443  0.234728336
menandai      0.026616529 -0.258213133
attr(,".cache")
<environment: 0x7fbe56512620>

5 Results and discussion

The following codes run the Hierarchical Agglomerative Analysis (HAC) on the target verbs vector space model as well as the Average Silhouette Width (ASW) statistics.

The following codes generate the plot for the ASW scores in the paper.

The dendrogram tree is generated using the following codes:

5.1 Semantic cluster

The subcluster of the motion verbs is extracted using the following codes:

In this section, we present three tables for n-grams data of verbs with the root tapak ‘sole of the foot’. The data can be loaded as follows:

The following codes generate the ten most frequent right-side 3-gram for menapak.

ngrams n
1 menapak_masa_depan 10
2 menapak_ke_babak 6
3 menapak_di_jalan 4
4 menapak_di_lantai 4
5 menapak_karir_di 4
6 menapak_di_atas 3
7 menapak_tilas_jejak 3
8 menapak_di_bumi 2
9 menapak_di_jalanan 2
10 menapak_di_permukaan 2

Menapak can be used as transitive (item 1, 5, and 7) and intransitive verbs (the remaining items in Table @ref(tab:tapak-gram-table)). Its transitive usage shares similar right-side collocation patterns with the MeN-/-i form menapaki, especially their direct object with masa depan ‘future’ and karir ‘career’ (Table@ref(tab:tapaki-gram-table) below).

ngrams n
1 menapaki_anak_tangga 11
2 menapaki_jalan_menuju 11
3 menapaki_masa_depan 11
4 menapaki_jalan_yang 9
5 menapaki_karir_di 9
6 menapaki_karier_sebagai 7
7 menapaki_karier_di 6
8 menapaki_babak_baru 5
9 menapaki_dunia_kerja 5
10 menapaki_karir_sebagai 5

This is different from the transitive usage with MeN-/-kan schema (Table @ref(tab:tapakkan-gram-table) below), which predominantly has kaki ‘foot’ as its direct object, followed by either locational/directional prepositional phrses or motion verb complements (e.g., memasuki ‘to enter’ [item 5] and maju ‘to move forward’ [item 8]).

ngrams n
1 menapakkan_kakinya_di 24
2 menapakkan_kaki_di 14
3 menapakkan_kaki_ke 3
4 menapakkan_dirinya_di 2
5 menapakkan_kaki_memasuki 2
6 menapakkan_kaki_saat 2
7 menapakkan_kakinya_ke 2
8 menapakkan_kakinya_maju 2
9 menapakkan_bisnis_toko 1
10 menapakkan_citra_donnie 1

Codes for extracting the subset of the mixture of communication and psych verbs are as follows.

The above dendrogram is from the top cluster in Figure @ref(fig:hca-plot), consisting of (i) menyesal ‘to be regretful’ (N = 2,556), (ii) menyesali ‘regret sth.’ (N = 956), and (iii) membayangkan ‘imagine; visualise’ (N = 2,719). The other subset of communication and psych verbs (i.e., mengatakan ‘to say sth.’ (N = 265,381), mencontohkan ‘to exemplify’ (N = 4,799), and menyesalkan ‘regret sth.’ (N = 1,976)) is extracted as follows.

What interesting between verbs in these last two clusters is that the MeN-/-i (i.e. mengatai) and MeN-/-kan verbs (i.e. mengatakan) with the root kata ‘word’ are way apart in the dendrogram. Similar case is apparent between menyesalkan separated with menyesal and menyesali, where the latter two verbs cluster together and are merged first in Figure @ref(fig:subcluster-psychs-1) (see §@ref(cluster-split) for further discussion on this split).

5.2 Root-based clustering

This cluster type captures denominal verbs of a given root with the three different morphological schemas that cluster together (Figure @ref(fig:subcluster-root-based)). We have seen few examples of these in the motion cluster with the root tapak ‘sole of the foot’ and jejak ‘footprint’, the derived forms of which fall into one cluster but differ in terms of their within-cluster branching (Figure @ref(fig:subclust-motion)). The other examples are based on the following roots:

  1. susu ‘milk’ -> menyusu ‘(of a baby/young animal) to suckle’ (N = 458); menyusui ‘to breast-feed sb.’ (N = 2,538); menyusukan ‘to let sb. suckle; to breast-feed sb.’ (N = 35)
  2. dasar ‘base’ -> mendasar ‘basic; foundational’ (N = 4,571); mendasari ‘to underlie sth.’ (N = 1,365); mendasarkan ‘to base X (on Y)’ (N = 781)
  3. tempat ‘place; location’ -> menempat ‘to place/position (sth.) at’ (N = 27); menempati ‘to occupy; to site at’ (N = 11,150); menempatkan ‘to put/place/position X at Y’ (N = 11,513)
  4. wakil ‘vice; representative; deputy’ -> mewakil ‘to (be a) represent(ative of) X’ (N = 39); mewakili ‘to (be a) represent(ative of) X’ (N = 12,389); mewakilkan ‘to assign sb. as a representative’ (N = 220)

The cluster subsets of these verbs are extracted from Figure @ref(fig:hca-plot) into Figure @ref(fig:subcluster-root-based) with the codes below.

In the paper, we present n-grams data contrasting mewakili and mewakilkan in terms of their ride-side collocates in their 3-grams data. First, the codes for generating n-grams for mewakili ‘to (be a) represent(ative of) X’ are shown below.

ngrams n
1 mewakili_kebijakan_editorial 174
2 mewakili_indonesia_di 142
3 mewakili_indonesia_dalam 129
4 mewakili_indonesia_pada 69
5 mewakili_lebih_dari 38
6 mewakili_iklan_anda 36
7 mewakili_kepala_dinas 35
8 mewakili_indonesia_untuk 32
9 mewakili_indonesia_ke 26
10 mewakili_kepala_badan 23

Then, the codes for 3-grams of mewakilkan ‘to make X as the representative (of Y)’.

ngrams n
1 mewakilkan_sebuah_film 6
2 mewakilkan_kepada_orang 5
3 mewakilkan_orang_lain 4
4 mewakilkan_benua_asia 3
5 mewakilkan_kehadirannya_kepada 3
6 mewakilkan_kepada_unais 3
7 mewakilkan_kepada_wakil 3
8 mewakilkan_6_perwakilan 2
9 mewakilkan_bisa_dengan 2
10 mewakilkan_dirinya_lewat 2

5.3 Clustering-split between morphological schemas for a given root

This sub-section addresses in more details split cases between morphological schemas for a given root. The split, especially between MeN-/-kan and MeN-/-i verbs, reflects Sneddon et al’s (2010:100–101) hypothesis concerning clear semantic difference between some of a pair of MeN-/-kan and MeN-/-i verbs with the same root. Our VSM-based approach allows us to visualise such split through the dendrogram based on large-scale usage data. The sub-section also demonstrates further enrichment in charactersing the difference between morphologically related verb pairs using the technique of nearest neighbours based on the VSM data.

In §@ref(semclust), we have mentioned the clear split between the transitive melangkahkan ‘to move the foot forward’ and melangkahi ‘to step over’. Looking at the 2-gram data for each verb shows that they have different semantic orientation. The following codes generate the 2-gram data for melangkahi.

ngrams n
1 melangkahi_kewenangan 7
2 melangkahi_aturan 6
3 melangkahi_batas-batas 4
4 melangkahi_apa 3
5 melangkahi_beberapa 3
6 melangkahi_mekanisme 3
7 melangkahi_pundak 3
8 melangkahi_tlundak 3
9 melangkahi_batasan 2
10 melangkahi_dasar-dasar 2

Melangkahi predominantly conveys metaphorical sense related to disobeying/disregarding certain (i) rules/protocols (i.e., aturan, batas-batas/batasan ‘limits; restriction’, mekanisme ‘mechanism’), (ii) foundation (dasar-dasar), or (iii) authority (kewenangan).

In contrast, melangkahkan predominantly collocates with kaki ‘foot’ as its direct object collocates, which can be used in the literal, translational motion and metaphorical motion (see our paper for the example sentences).

ngrams n
1 melangkahkan_kaki 162
2 melangkahkan_kakinya 123
3 melangkahkan_kakiku 13
4 melangkahkan_kedua 3
5 melangkahkan_satu 3
6 melangkahkan_kakimu 2
7 melangkahkan_bakti 1
8 melangkahkan_bidak 1
9 melangkahkan_gambaran 1
10 melangkahkan_jalan 1

Observation on the n-gram can be enriched using information from the VSM of words. Given that the skip-gram algorithm of word2vec learns to predict the contextual environments given a target word (cf. Mikolov, Chen, et al. 2013), one can retrieve from the VSM a set of words that have similar contextual-vector distribution to a given target verb on the basis their cosine similarities; these words can be metaphorically referred to as the verb’s nearest neighbours. Table @ref(tab:nearest-to-melangkahi) illustrates the idea for melangkahi ‘to step over’.

word similarity to “melangkahi
1 mengangkangi 0.5508479
2 berkeras 0.5435145
3 memperhitungkannya 0.5337096
4 mengacuhkan 0.5174865
5 memagari 0.5163426
6 memegang 0.5040103
7 membelakangi 0.5036757
8 mematuhi 0.4959915
9 bersikeras 0.4949589
10 berbenturan 0.4929108

The closest words may not necessarily similar in meaning (e.g., near-synonyms), but may exhibit different kind of relationships, such as antonyms. Words in Table @ref(tab:nearest-to-melangkahi) conveying more or less antonymous sense to melangkahi ‘to step over; to disregard’ include mengacuhkan ‘to care about/heed sth.’, mematuhi ‘to obey’, and (to a degree) memperhitungkannya ‘to take sth. into account’. Mengangkangi ‘to straddle sth.’ is the closest in meaning with melangkahi as it can be extended into ‘disregarding’ sense from its physical, posture sense: the 2-gram data for mengangkangi across the whole corpus (Table @ref(tab:kangkangi-gr)) reveals that it does co-occur with rules-related direct objects, such as hukum ‘law’ (3 tokens), peraturan ‘regulation’ (3), kebenaran ‘the truth’ (2), prinsip ‘principles’ (2), undang-undang ‘constitution’ (2), aturan ‘rules’ (1), inter alia.

ngrams n
1 mengangkangi_tubuh 4
2 mengangkangi_dunia 3
3 mengangkangi_hukum 3
4 mengangkangi_peraturan 3
5 mengangkangi_seluruh 3
6 mengangkangi_bagian 2
7 mengangkangi_hak 2
8 mengangkangi_jembatan 2
9 mengangkangi_kebenaran 2
10 mengangkangi_mu 2
11 mengangkangi_prinsip 2
12 mengangkangi_sebuah 2
13 mengangkangi_tanah 2
14 mengangkangi_undang-undang 2

The following codes retrieve words nearest to melangkahkan.

word similarity to “melangkahkan
1 menjejakkan 0.7487976
2 melangkah 0.7351338
3 dilangkahkan 0.7294263
4 berlari 0.7258124
5 kakiku 0.7195594
6 menghunjamkan 0.7150664
7 menapakkan 0.7126413
8 berjingkat 0.7079603
9 kakinya 0.7068803
10 langkahkan 0.7066612

The codes to retrieve the nearest words of mengatai ‘to rebuke; speake of one’s badness’.

word similarity to “mengatai
1 memaki 0.7476359
2 marah-marah 0.6818458
3 cerewet 0.6806308
4 mengejek 0.6795740
5 memaki-maki 0.6713904
6 jengkel 0.6675079
7 diejek 0.6645705
8 diolok-olok 0.6641099
9 meledek 0.6628723
10 berbohong 0.6597248

In contrast, mengatakan mostly appears as communication verb with similar distribution with other reported speech verbs.

word similarity to “mengatakan
1 menegaskan 0.8376837
2 menyatakan 0.8318030
3 mengungkapkan 0.8079668
4 mengemukakan 0.7967164
5 menuturkan 0.7925858
6 menjelaskan 0.7808896
7 menyebutkan 0.7640667
8 menerangkan 0.7568715
9 mengakui 0.7495804
10 mengatkan 0.7467988

Nearest words to membuahi ‘to breed sth.’ are retrieved as follows.

word similarity to “membuahi
1 dibuahi 0.8372309
2 ovum 0.8330801
3 sperma 0.7965994
4 gamet 0.7326975
5 pembuahan 0.7300101
6 terbuahi 0.7016097
7 spermatozoid 0.6901719
8 spermatozoa 0.6794663
9 parthenogenesis 0.6775866
10 zigot 0.6712285

Codes for extracting closest words to membuahkan ‘to bear a fruit; to result in sth.’.

word similarity to “membuahkan
1 berbuah 0.6716316
2 mem-buahkan 0.6296921
3 tercipta 0.6214626
4 membuah 0.5991543
5 menuai 0.5729809
6 tendangannya 0.5533927
7 ditepis 0.5530693
8 kerasnya 0.5528045
9 pinalti 0.5482891
10 dimentahkan 0.5478375

Notes on the usage sentences for membuah are below. But first load the sentence citations for membuah into R and print them into the console. After that the notes are manually created by manually inspecting all the usage sentences. The sentence data is available as .rds file of list (sentence_membuah.rds) and .txt file as plain text of sentences (sentence_membuah.txt).

[1] "ind_mixed_2012_1M__314113__Dan , entah sudah berapa kali pejabat di Dinas Tata Kota dan Permukiman ( DTKP ) Pemkot telah berganti , tetapi persoalan bangunan mangkrak itu tak juga  <m>membuah</m>  solusi cepat ."
[2] "ind_mixed_2012_1M__635047__Pertemuan dengan ibu saudaranya  <m>membuah</m>  seribu kegembiraan ."                                                                                                                   
[3] "ind_mixed_2012_1M__912835__Peluang Irak lewat tendangan Younis Khalef di dalam kotak penalti juga masih belum  <m>membuah</m>  hasil ."                                                                             
[4] "ind_mixed_2012_1M__912841__Namun penyerbuan ke al-Karak , 1183-84 tidak  <m>membuah</m>  hasil yang memuaskan ."                                                                                                    

The sentence format is corpus-file-name_sentence-id-number_sentence-citation. The <m>...</m> tag indicates the corresponding match/word/verb.

  • membuah (56 citations; Summary: analogy to membuahkan = 24 citations; split with -kan = 1; mispell for membuat = 25; mispell for membuang = 5; unclear = 1)

    • ind_mixed_2012_1M: 4 citations (all FULL FORM)
    • ind_news_2008_300K: 5 citations (2 mispell for membuat [id 53666 & 155569]; 3 FULL FORM analogy to membuahkan)
    • ind_news_2009_300K: 3 citations (1 mispell for membuat [id 200027] 2 FULL FORM analogy to membuahkan)
    • ind_news_2010_300K: 1 citation (all mispell for membuat)
    • ind_news_2011_300K: 2 citations (1 mispell for membuat [id 266814]; 1 FULL FORM analogy to membuahkan)
    • ind_news_2012_300K: 5 citations (4 mispell for membuat [id 200952, 206980, 268407, 269898]; 1 FULL FORM analogy to membuahkan)
    • ind_newscrawl_2011_1M: 6 citations (3 FULL FORM analogy to membuahkan; 3 mispell for membuat [id 118419, 151095, 205239])
    • ind_newscrawl_2012_1M: 3 citations (1 mispell for membuat [id 201217]; 1 mispell for membuang [id 401158]; 1 got split with -kan [id 595662])
    • ind_web_2011_300K: 1 citation (mispell for membuat)
    • ind_web_2012_1M: 4 citations (1 mispell for membuat [id 602274]; 1 unclear for mispell for membuat [id 365510]; 2 FULL FORM analogy to membuahkan)
    • ind_wikipedia_2016_1M: 5 citations (2 mispell for membuat [id 320981, 596205]; 3 FULL FORM analogy to membuahkan)
    • ind-id_web_2013_1M: 5 citations (1 mispell for membuang [id 886076]; 4 FULL FORM as membuahkan)
    • ind-id_web_2015_3M: 12 citations (1 FULL FORM as membuahkan [id 1396285]; 3 mispell for membuang [id 1362223, 1549653, 1564536], the remaining 8 mispell for membuat)

The following codes retrieve the nearest words to mengakhiri (N = 8,512).

word similarity to “mengakhiri
1 mengakhir 0.7149269
2 menyudahi 0.6486199
3 mengahiri 0.6346930
4 akhiri 0.6329971
5 berakhir 0.6263411
6 mengakhirinya 0.6060989
7 mengakiri 0.5811454
8 memimpin 0.5763634
9 memperpanjang 0.5681369
10 memupus 0.5669336

If reader wishes to check all usage sentences for mengakhir to confirm that it occurs as a full word-form and has similar usage patterns with meN-/-i form mengakhiri (i.e. in transitive constructions), use the following code. It will print all sentences for mengakhir into R console.

Next, the nearest words to mengakhirkan (N = 116) are shown below.

word similarity to “mengakhirkan
1 shalat 0.8595279
2 menjamak 0.8582150
3 shubuh 0.8510190
4 dijamak 0.8504550
5 zhuhur 0.8434480
6 qashar 0.8383760
7 isya 0.8300283
8 disunnahkan 0.8250431
9 menjama 0.8227094
10 qabliyah 0.8215906

5.4 Issues and challenges

Codes to extract the nearest words to mengantung ‘to hang’ (N = 28), which is a misspelling of menggantung ‘to hang’ (with double g) (N = 1,100). Nearest words output shows that mengantung is indeed the closest word to menggantung in their usage co-occurrence.

word similarity to “mengantung
1 menggantung 0.6580294
2 blandar 0.6541215
3 memaku 0.6125143
4 ditelungkupkan 0.5888941
5 dibaringkan 0.5863362
6 loso 0.5808274
7 digergaji 0.5766285
8 tertelungkup 0.5721740
9 tersekap 0.5694923
10 ditindih 0.5677198

The codes below extract the nearest words for mengantungkan (N = 44), a misspelling for menggantungkan ‘to hang sth. (onto sth.)’ (N = 1,264).

word similarity to “mengantungkan
1 menggantungkan 0.7764547
2 penghidupannya 0.6517582
3 peladang 0.5890552
4 matapencaharian 0.5649209
5 mengentaskannya 0.5516661
6 bersawah 0.5515007
7 petani-petani 0.5469401
8 pengais 0.5458413
9 bertani 0.5404030
10 upahan 0.5370267

Then, the nearest words for mengantungi (N = 327) which is closest to the common spelling with mengantongi (N = 3,574) based on the root kantong ‘pocket’.

word similarity to “mengantungi
1 mengantongi 0.7021752
2 mengoleksi 0.6954547
3 memuncaki 0.6904767
4 raihan 0.6513341
5 terpaut 0.6435489
6 mengungguli 0.6411234
7 torehan 0.6217388
8 pemuncak 0.6164198
9 mengemas 0.6040049
10 diposisi 0.6004999

Finally, the case where part of the complex word is split. The paper illustrates this with menanda which is part of menandatangani ‘to give signature; to sign’ but is written separately with whitespace, thus, menanda tangani, where the whitespace got tokenised.

word similarity to “menanda
1 ditanda 0.7982222
2 menandatangani 0.6721747
3 menanda-tangani 0.6597414
4 menandatangai 0.6295324
5 menandatangi 0.6148956
6 tanganinya 0.6112830
7 ditandatangani 0.6063122
8 ditanda-tangani 0.6057313
9 ditandatanganinya 0.5950392
10 meneken 0.5891363
  • menanda (N = 121; Summary: split = 113; intransitive usage = 5; transitive usage analogy = 2; ambiguous = 1)

    • ind_mixed_2012_1M (22 citations: 18 split from menandatangani; 4 citations as intransitive with pada (138307, 278193, 542191, 754529))
    • ind_news_2008_300K (1 citation: 1 split from menandatangani)
    • ind_news_2009_300K (2 citations: 2 split from menandatangani)
    • ind_news_2010_300K (2 citations: 2 split from menandatangani)
    • ind_news_2011_300K (3 citations: 3 split from menandatangani)
    • ind_newscrawl_2011_1M (10 citations: 10 split from menandatangani)
    • ind_newscrawl_2012_1M (9 citations: 9 split from menandatangani)
    • ind_web_2011_300K (4 citations: 4 split from menandatangani)
    • ind_web_2012_1M (18 citations):
      • 14 citations split from menandatangani
      • 1 citation of transitive usage in analogy to menandai (44043): “II . mangarus rupa , menerka , mencoba <m>menanda</m> siapa orang ini .”
      • 1 citation of transitive usage in analogy to menandakan ‘to mark/signal (the existence of) sth.’ (368004): “Majlis tamat , hadir berduyun sekumpulan penari dengan meriahnya , <m>menanda</m> temasya kecil kampung bakal bermula , sedikit demi sedikit sahutan penduduk kampung menggila sepenuh nafsu menari sekali bersama penari .” (Malaysian Malay?)
      • 1 citation of intransitive usage (544395): “Bagi aku , kalau tidak sempat <m>menanda</m> di sekolah ( memang tak cukup masa ) , terpaksalah bawa di rumah .”
      • 1 citation of ambiguous usage (981384): “Nama dan No Kad Pengenalan disebut , dan mereka <m>menanda</m> .”
    • ind_wikipedia_2016_1M (16 citations: 16 split from menandatangan(i))
    • ind-id_web_2013_1M (16 citations: 16 split from menandatangan(i))
    • ind-id_web_2015_3M (18 citations: 18 split from menandatangan(i))

Session Info

─ Session info ─────────────────────────────────────────────────

─ Packages ─────────────────────────────────────────────────────
 package     * version date       lib
 assertthat    0.2.1   2019-03-21 [1]
 backports     1.1.5   2019-10-02 [1]
 broom         0.5.5   2020-02-29 [1]
 callr         3.2.0   2019-03-15 [1]
 cellranger    1.1.0   2016-07-27 [1]
 cli           2.0.2   2020-02-28 [1]
 cluster     * 2.1.0   2019-06-19 [2]
 colorspace    1.4-1   2019-03-18 [1]
 crayon        1.3.4   2017-09-16 [1]
 DBI           1.0.0   2018-05-02 [1]
 dbplyr        1.4.2   2019-06-17 [1]
 dendextend  * 1.13.2  2019-12-02 [1]
 desc          1.2.0   2018-05-01 [1]
 devtools      2.2.1   2019-09-24 [1]
 digest        0.6.25  2020-02-23 [1]
 dplyr       * 0.8.5   2020-03-07 [1]
 ellipsis      0.3.0   2019-09-20 [1]
 evaluate      0.14    2019-05-28 [1]
 fansi         0.4.1   2020-01-08 [1]
 farver        2.0.1   2019-11-13 [1]
 forcats     * 0.5.0   2020-03-01 [1]
 fs            1.3.1   2019-05-06 [1]
 generics      0.0.2   2018-11-29 [1]
 ggplot2     * 3.3.0   2020-03-05 [1]
 glue          1.3.2   2020-03-12 [1]
 gridExtra     2.3     2017-09-09 [1]
 gtable        0.3.0   2019-03-25 [1]
 haven         2.2.0   2019-11-08 [1]
 highr         0.8     2019-03-20 [1]
 hms           0.5.3   2020-01-08 [1]
 htmltools     0.3.6   2017-04-28 [1]
 httr          1.4.1   2019-08-05 [1]
 jsonlite      1.6     2018-12-07 [1]
 knitr         1.28    2020-02-06 [1]
 labeling      0.3     2014-08-23 [1]
 lattice       0.20-38 2018-11-04 [2]
 lifecycle     0.2.0   2020-03-06 [1]
 lubridate     1.7.4   2018-04-11 [1]
 magrittr      1.5     2014-11-22 [1]
 memoise       1.1.0   2017-04-21 [1]
 modelr        0.1.5   2019-08-08 [1]
 munsell       0.5.0   2018-06-12 [1]
 nlme          3.1-144 2020-02-06 [2]
 pillar        1.4.3   2019-12-20 [1]
 pkgbuild      1.0.3   2019-03-20 [1]
 pkgconfig     2.0.3   2019-09-22 [1]
 pkgload       1.0.2   2018-10-29 [1]
 prettyunits   1.0.2   2015-07-13 [1]
 processx      3.3.1   2019-05-08 [1]
 ps            1.3.0   2018-12-21 [1]
 purrr       * 0.3.3   2019-10-18 [1]
 R6            2.4.1   2019-11-12 [1]
 Rcpp          1.0.4   2020-03-17 [1]
 readr       * 1.3.1   2018-12-21 [1]
 readxl        1.3.1   2019-03-13 [1]
 remotes       2.1.0   2019-06-24 [1]
 reprex        0.3.0   2019-05-16 [1]
 rlang         0.4.5   2020-03-01 [1]
 Rling       * 1.0     2019-09-12 [1]
 rmarkdown     2.1     2020-01-20 [1]
 rprojroot     1.3-2   2018-01-03 [1]
 rstudioapi    0.10    2019-03-19 [1]
 rvest         0.3.5   2019-11-08 [1]
 scales        1.1.0   2019-11-18 [1]
 sessioninfo   1.1.1   2018-11-05 [1]
 stringi       1.4.6   2020-02-17 [1]
 stringr     * 1.4.0   2019-02-10 [1]
 testthat      2.3.1   2019-12-01 [1]
 tibble      * 2.1.3   2019-06-06 [1]
 tidyr       * 1.0.2   2020-01-24 [1]
 tidyselect    1.0.0   2020-01-27 [1]
 tidyverse   * 1.3.0   2019-11-21 [1]
 usethis       1.5.1   2019-07-04 [1]
 vctrs         0.2.4   2020-03-10 [1]
 viridis       0.5.1   2018-03-29 [1]
 viridisLite   0.3.0   2018-02-01 [1]
 withr         2.1.2   2018-03-15 [1]
 wordVectors * 2.0     2019-06-01 [1]
 xfun          0.12    2020-01-13 [1]
 xml2          1.2.2   2019-08-09 [1]
 source                                
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.3)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.3)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.3)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 local                                 
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        
 Github (bmschmidt/wordVectors@7f1914c)
 CRAN (R 3.6.0)                        
 CRAN (R 3.6.0)                        

[1] /Users/Primahadi/Rlibs
[2] /Library/Frameworks/R.framework/Versions/3.6/Resources/library

References

Biemann, Chris, Gerhard Heyer, Uwe Quasthoff & Matthias Richter. 2007. The Leipzig Corpora Collection: Monolingual corpora of standard size. In Matthew Davies, Paul Rayson, Susan Hunston & Pernilla Danielsson (eds.), Proceedings of the Corpus Linguistics Conference. University of Birmingham, UK. http://ucrel.lancs.ac.uk/publications/CL2007/paper/190_Paper.pdf (5 March, 2014).

Clark, Stephen. 2015. Vector space models of lexical meaning. In Shalom Lappin & Chris Fox (eds.), The Handbook of Contemporary semantic theory, 493–522. Second Edition. Hoboken: John Wiley & Sons.

Desagulier, Guillaume. 2017. Corpus Linguistics and Statistics with R. Cham: Springer International Publishing. doi:10.1007/978-3-319-64572-8.

Galili, Tal. 2015. Dendextend: An R package for visualizing, adjusting, and comparing trees of hierarchical clustering. Bioinformatics. doi:10.1093/bioinformatics/btv428.

Gries, Stefan Th. 2013. Statistics for linguistics with R: A practical introduction. 2nd ed. Berlin: Mouton de Gruyter.

Heylen, Kris, Thomas Wielfaert, Dirk Speelman & Dirk Geeraerts. 2015. Monitoring polysemy: Word space models as a tool for large-scale lexical semantic analysis. Lingua 157. (Polysemy: Current Perspectives and Approaches). 153–172. doi:10.1016/j.lingua.2014.12.001.

Hilpert, Martin & Florent Perek. 2015. Meaning change in a petri dish: Constructions, semantic vector spaces, and motion charts. Linguistics Vanguard 1(1). doi:10.1515/lingvan-2015-0013.

Larasati, Septina Dian, Vladislav Kuboň & Daniel Zeman. 2011. Indonesian Morphology Tool (MorphInd): Towards an Indonesian Corpus. In, Systems and Frameworks for Computational Morphology, 119–129. Springer, Berlin, Heidelberg. doi:10.1007/978-3-642-23138-4_8.

Levshina, Natalia. 2014. Geographic variation of Quite + ADJ in twenty national varieties of English: A pilot study. Yearbook of the German Cognitive Linguistics Association 2(1). 109–126. doi:10.1515/gcla-2014-0008.

Levshina, Natalia. 2015. How to do Linguistics with R: Data exploration and statistical analysis. John Benjamins Publishing Company.

Maechler, Martin, Peter Rousseeuw, Anja Struyf, Mia Hubert & Kurt Hornik. 2018. Cluster: Cluster Analysis Basics and Extensions.

Mikolov, Tomas, Kai Chen, Greg Corrado & Jeffrey Dean. 2013. Efficient Estimation of Word Representations in Vector Space. http://arxiv.org/abs/1301.3781 (14 December, 2018).

Mikolov, Tomas, Ilya Sutskever, Kai Chen, Greg Corrado & Jeffrey Dean. 2013. Distributed Representations of Words and Phrases and their Compositionality. http://arxiv.org/abs/1310.4546 (14 December, 2018).

Mikolov, Tomas, Wen-tau Yih & Geoffrey Zweig. 2013. Linguistic Regularities in Continuous Space Word Representations. In, Proceedings of the 2013 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies, 746–751. Atlanta, Georgia: Association for Computational Linguistics. http://www.aclweb.org/anthology/N13-1090 (14 December, 2018).

Nomoto, Hiroki, Hannah Choi, David Moeljadi & Francis Bond. 2018. MALINDO Morph: Morphological dictionary and analyser for Malay/Indonesian. In, Proceedings of the LREC 2018 Workshop "The 13th Workshop on Asian Language Resources", 36–43. http://lrec-conf.org/workshops/lrec2018/W29/pdf/8_W29.pdf.

Nomoto, Hiroki & David Moeljadi. 2019. Linguistic studies using large annotated corpora: Introduction. (Ed.) Hiroki Nomoto & David Moeljadi. NUSA 67. (Linguistic Studies Using Large Annotated Corpora). 1–6. http://repository.tufs.ac.jp/handle/10108/94450 (1 April, 2020).

Perek, Florent. 2016. Recent change in the productivity and schematicity of the Way-construction: A distributional semantic analysis. Corpus Linguistics and Linguistic Theory. doi:10.1515/cllt-2016-0014.

Quasthoff, Uwe & Dirk Goldhahn. 2013. Indonesian corpora. (Technical Report Series on Corpus Building). Leipzig, Germany: Abteilung Automatische Sprachverarbeitung, Institut für Informatik, Universität Leipzig. http://asvdoku.informatik.uni-leipzig.de/corpora/data/uploads/corpus-building-vol7-ind.pdf (26 July, 2015).

Rajeg, Gede Primahadi Wijaya, Karlina Denistia & Simon Musgrave. 2019a. R markdown notebook for vector space model and the usage patterns of indonesian denominal verbs. figshare. doi:10.6084/m9.figshare.9970205. https://figshare.com/articles/R_Markdown_Notebook_for_i_Vector_space_model_and_the_usage_patterns_of_Indonesian_denominal_verbs_i_/9970205.

Rajeg, Gede Primahadi Wijaya, Karlina Denistia & Simon Musgrave. 2019b. Vector space models and the usage patterns of indonesian denominal verbs: A case study of verbs with meN-, meN-/-kan, and meN-/-i affixes. (Ed.) Hiroki Nomoto & David Moeljadi. NUSA 67. (Linguistic Studies Using Large Annotated Corpora). 35–76. http://repository.tufs.ac.jp/handle/10108/94452 (1 April, 2020).

Rajeg, Gede Primahadi Wijaya, Karlina Denistia & Simon Musgrave. 2019c. Dataset for vector space model and the usage patterns of indonesian denominal verbs. figshare. doi:10.6084/m9.figshare.8187155. https://figshare.com/articles/Dataset_for_i_Vector_space_model_and_the_usage_patterns_of_Indonesian_denominal_verbs_i_/8187155.

Schmidt, Ben & Jian Li. 2017. wordVectors: Tools for creating and analyzing vector-space models of texts. http://github.com/bmschmidt/wordVectors.

Sneddon, James Neil, Alexander Adelaar, Dwi Noverini Djenar & Michael C. Ewing. 2010. Indonesian reference grammar. 2nd ed. Crows Nest, New South Wales, Australia: Allen & Unwin.

Wickham, Hadley & Garrett Grolemund. 2017. R for Data Science. Canada: O’Reilly. http://r4ds.had.co.nz/ (7 March, 2017).

LS0tCnRpdGxlOiBSIE1hcmtkb3duIE5vdGVib29rIGZvciAqVmVjdG9yIFNwYWNlIE1vZGVscyBhbmQgdGhlIHVzYWdlIHBhdHRlcm5zIG9mIEluZG9uZXNpYW4KICBkZW5vbWluYWwgdmVyYnMqCmF1dGhvcjogJ1tHZWRlIFByaW1haGFkaSBXaWpheWEgUmFqZWddKGh0dHBzOi8vZmlnc2hhcmUuY29tL2F1dGhvcnMvR2VkZV9QcmltYWhhZGlfV2lqYXlhX1JhamVnLzEyMzQ3NDkpIDxhIGl0ZW1wcm9wPSJzYW1lQXMiIGNvbnRlbnQ9Imh0dHBzOi8vb3JjaWQub3JnLzAwMDAtMDAwMi0yMDQ3LTg2MjEiIGhyZWY9Imh0dHBzOi8vb3JjaWQub3JnLzAwMDAtMDAwMi0yMDQ3LTg2MjEiIHRhcmdldD0ib3JjaWQud2lkZ2V0IiByZWw9Im5vb3BlbmVyIG5vcmVmZXJyZXIiIHN0eWxlPSJ2ZXJ0aWNhbC1hbGlnbjp0b3A7Ij48aW1nIHNyYz0iaHR0cHM6Ly9vcmNpZC5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9pbWFnZXMvb3JjaWRfMTZ4MTYucG5nIiBzdHlsZT0id2lkdGg6MWVtO21hcmdpbi1yaWdodDouNWVtOyIgYWx0PSJPUkNJRCBpRCBpY29uIj48L2E+LCBbS2FybGluYSBEZW5pc3RpYV0oaHR0cDovL3VuaS10dWViaW5nZW4uYWNhZGVtaWEuZWR1L2thcmxpbmFkZW5pc3RpYSkgPGEgaXRlbXByb3A9InNhbWVBcyIgY29udGVudD0iaHR0cDovL29yY2lkLm9yZy8wMDAwLTAwMDItMTA2MC0zNTQ4IiBocmVmPSJodHRwOi8vb3JjaWQub3JnLzAwMDAtMDAwMi0xMDYwLTM1NDgiIHRhcmdldD0ib3JjaWQud2lkZ2V0IiByZWw9Im5vb3BlbmVyIG5vcmVmZXJyZXIiIHN0eWxlPSJ2ZXJ0aWNhbC1hbGlnbjp0b3A7Ij48aW1nIHNyYz0iaHR0cHM6Ly9vcmNpZC5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9pbWFnZXMvb3JjaWRfMTZ4MTYucG5nIiBzdHlsZT0id2lkdGg6MWVtO21hcmdpbi1yaWdodDouNWVtOyIgYWx0PSJPUkNJRCBpRCBpY29uIj48L2E+LCBbU2ltb24gTXVzZ3JhdmVdKGh0dHA6Ly9wcm9maWxlcy5hcnRzLm1vbmFzaC5lZHUuYXUvc2ltb24tbXVzZ3JhdmUvKSA8YSBpdGVtcHJvcD0ic2FtZUFzIiBjb250ZW50PSJodHRwczovL29yY2lkLm9yZy8wMDAwLTAwMDMtMzIzNy05OTQzIiBocmVmPSJodHRwczovL29yY2lkLm9yZy8wMDAwLTAwMDMtMzIzNy05OTQzIiB0YXJnZXQ9Im9yY2lkLndpZGdldCIgcmVsPSJub29wZW5lciBub3JlZmVycmVyIiBzdHlsZT0idmVydGljYWwtYWxpZ246dG9wOyI+PGltZyBzcmM9Imh0dHBzOi8vb3JjaWQub3JnL3NpdGVzL2RlZmF1bHQvZmlsZXMvaW1hZ2VzL29yY2lkXzE2eDE2LnBuZyIgc3R5bGU9IndpZHRoOjFlbTttYXJnaW4tcmlnaHQ6LjVlbTsiIGFsdD0iT1JDSUQgaUQgaWNvbiI+PC9hPicKZGF0ZTogIkNyZWF0ZWQgMjYgSmFudWFyeSwgMjAxOTsgTGFzdCBVcGRhdGUgYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgZmlnX2NhcHRpb246IHllcwogICAgZmlnX3dpZHRoOiA2CiAgICB0aGVtZTogInVuaXRlZCIKICAgIGhpZ2hsaWdodDogInB5Z21lbnRzIgogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjoKICAgIHRvYzogVFJVRQogICAgdG9jX2Zsb2F0OiBUUlVFCiAgICB0aGVtZTogInVuaXRlZCIKICAgIGhpZ2hsaWdodDogInB5Z21lbnRzIgogICAgZmlnX2NhcHRpb246IHllcwogICAgZmlnX3dpZHRoOiA2CiAgICBudW1iZXJfc2VjdGlvbnM6IFRSVUUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAga2VlcF9tZDogRkFMU0UKbGluay1jaXRhdGlvbnM6IHllcwpjc2w6IHVuaWZpZWRfc3R5bGVzaGVldF9saW5ndWlzdGljcy5jc2wKYmlibGlvZ3JhcGh5OiBpbmRleF9yZWYuYmliCi0tLQoKPGEgcmVsPSJsaWNlbnNlIiBocmVmPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy1zYS80LjAvIj48aW1nIGFsdD0iQ3JlYXRpdmUgQ29tbW9ucyBMaWNlbnNlIiBzdHlsZT0iYm9yZGVyLXdpZHRoOjAiIHNyYz0iaHR0cHM6Ly9pLmNyZWF0aXZlY29tbW9ucy5vcmcvbC9ieS1uYy1zYS80LjAvODh4MzEucG5nIiAvPjwvYT48YnIgLz5UaGlzIHdvcmsgaXMgbGljZW5zZWQgdW5kZXIgYSA8YSByZWw9ImxpY2Vuc2UiIGhyZWY9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLXNhLzQuMC8iPkNyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbC1TaGFyZUFsaWtlIDQuMCBJbnRlcm5hdGlvbmFsIExpY2Vuc2U8L2E+LgoKWyFbRE9JXShodHRwczovL2ltZy5zaGllbGRzLmlvL2JhZGdlL2RvaS0xMC42MDg0L205LmZpZ3NoYXJlLjk5NzAyMDUtYmx1ZS5zdmc/c3R5bGU9ZmxhdCZsYWJlbENvbG9yPXdoaXRlc21va2UmbG9nbz1kYXRhJTNBaW1hZ2UlMkZwbmclM0JiYXNlNjQlMkNpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQjhBQUFBZkNBWUFBQUFmcmhZNUFBQUpza2xFUVZSNDJxV1hkMURUYVJySGYlMkJpQjJIZHQ1emhyQVVLejRJS0VZdTlJR2lHRkZKSlEwZ2tKQ0FLaVdGRFdCUmRGaENRVUYzVVZkZVZjUlFFQnhVSTN5WTlpRW5RSGIzYmRXMWZQdWJueXolMkYxMU03bHZFSGZPUWVlMlpPWXpQeUR2JTJCM3lmOSUyRms5NVlYNGZ4JTJCbHRmVXQwOEdjRkV1UFI0VTloRERaJTJGVm5nSWxoYiUyRlNpSTZJbmtUZ0x6Z0RjZ2Z2dG5vdmhINEJ6b1ZscmJ3cjU1UW5oQ3RCVzRRSFhuRnJaYlBCYVFvQmg0JTJGU1lIMkVucEJFdHFjRE1WekI5M3dBJTJGOEFGd2EyM1hGR2NjOENrVDNteHolMkJmWFd0cTlUOUlRbExJWFlFdUhvanVkYiUyQkNNN0hnZHE4eWRpJTJGQUhpQlh5WSUyQkxqd0ZsQUVuUzZKbmFyJTJGdm5RVmh2ZHphc2FkMGVLdldaS2U4aHZEQjJvZkxaJTJGWkVjV3NoJTJCaHlJdXlPNUJ4czJpWklFNG5SdjdOV0FiMEVPOEFDJTJGV1B4allBV3VPRVgyTVNYWlZnUHh6bVJMM3hLejNTY0dweDZwNlFuT3g0bURJRnFPMHc2UTRmRWhPNUl6d3hsU3d5RDJGWUh6d0FXJTJCQVo0ZkVzZjc0Z0N1bXlrd05Ic2tMTTd0YVF4TFlqakl5eThNVXRyYUdoVFdka2Zoa0ZKcXR2dVZsJTJGOWwyWnF1RGZFeXJIOEIwVzA2bm5wSDNKdEl5UkdwSDFpSjZTZnhESUhqUlhISm1kUWpMcGZIZU41NGduZkZ4NFc5UVJub3Z4JTJGTjIwYVhaZVREMko4NGhuMyUyQnFvRjJUcXIxNFZxVFBVQ0ljUCUyQjUlMkZseTRxQyUyQlVMM3NZeFN2TmoxTndzVllQc1dkTVVmb21zZGtZbTNUajBuYlYwTjF3Ukt3RmUxTWdLQUNESUJkTUFoUEUlMkZ3aWN3Tld4bGw4QWc0MHclMkJGZmhpYkprR0htdXRqWWVROGdWbGFOJTJCak81MW5EeXNhOVR3TlVGTXFhR2JLZFJKWkZmT0pTcDZta1JLc3YwclJJcEVWV2pBdnlGa3hOT0Vwd3ZjQVZQZkVlJTJCbDhvamVOVHgzblhMQmNXUnJZR3hTUmpERWswVmxweFlyYmUxWm1hUTV4dVQwdTNyJTJCMnFlNWowSjV1eXRpWlBHc1JMMkptMzJBbGRweFBVTkozam1tc040eDYyejFjWHJiZWRYQlFmMnl2SUZDZVpydHlpY1paRzJVMm5yckJKellvckkyRVhMcnZUZkNTQjQzczQxUEtFdmJaREVmUWJ5Nkw0SlRqJTJGZkl3YW0lMkI0JTJCd3VjQnUlMkJEZ05LMDVObGUxclN0OUh2UiUyRktQQzRVNkxUZnZVSWFpcDFtaklhOGZQenlraWkyM2gyZWFuVDU3elE3ZnN5WUg1UWp5d3dsb29BVWNBZE9oNVF1bWdUSHg2YUFPNyUyRkw1MmVhUU5FU2hyeGZoTDZhbGJFRG1maEdmbHJzVDR0cHM4Z1RITk9KYmVEZUJsdDBXSldESFNneHM2Y1c2bFFxeWcxRnBENVpWRGZobjFIWUZGMXk0RWlhcWExOHBRZjN6ellNQmhjYW5sQmpZZmdXTmF5QWYlMkZBU09na2x1OGJtZ0Q3aEFEcms0Y1JsT0w3TlNPZXdFY2JxU21haXZUMzNRdUZkSFhqNXNkdmpsTjV5TURyQUVDbWRnRFdHMkw4UCUyQkFLTHM5WkxaN2RKZGElMkJCNFhsODR0N1F2bktmdnBYSnY5b2J6MktnSzhkWHlxSVN5VjBzWEdaMFU0N2hPQSUyRkFpaWdiRU1FQ0p4Qzlhb0twODZyZTVPNXByeE9sSGtja3N1dFNRSnp4WlJsUFptck9LaHNRQkY1ekVaS3liVUMwdlZqRzhQcU9uaE9xNDZxeURURG5qNWdaQnJpV0NrNER2WHJ1ZFFuWFFtblhibGViaEFDMmNDQjZ6SWJNNFBZZ0dsMGVsUFNnSWYzaUZFQTIxYUxkSFlMSFVRdVZrcGdpMDJTeEZkckc4NjJZOHltWUdNdlhEelVtaVg4RFM1dktaeVpsR21zU2dRcWZMdWI1UnlMTlM0emZEaVpjOUVkemglMkZ0Q0UlMkJYOGo5ayUyRnFXQjA3MXJjWnlNSW1uZTFTTGtMNEdSdzRVUEhNVjNqandFWXBQRzV1VzVmQUVvdDBhVFNKbnNHQXdISmkybnZGMVk1T0lxV3ppVkNRZDVOVDd0NlE4Z3VPU3BnUyUyRmExZFNSbjhKR0dhQ0QzQlBYRHlRUkc0QnFodThYcmdBcDB5eThETVN2dnlWWERnSmNKVGNyMXdRMkJ2RktmNjVqcWh2bXhYVXVEcEdCbFJ2VjM2WHZHalF6TGk4S0FLVDJsWU9ubXhRUEdvclVSU1YwTmh5VEl1SXlxT21LVE1oUSUyQmllRXNnT2dwYzRLQmJmRE00QjNTSWdGbGp2ZkhGNmNlZjdxcHlMQlhBaVFjWHZnNWwzSXVucCUyRld2NGRINnFGemlPJTJCTDlQYnJpbVE5Ulk2TVFwaEVmR1VwT21tYTdLa0d6dVM4c1BVRm5DdElZY0tDYUk5RVhvNEhsUUxnR3JCamJpSzVFcU1qMkFLV3Q5UVdjSUZNdG5WdlFWRFFWOWxYSkpxZFBWdFVRcGJoNmdDSTJPdjFudlp0czd5WWRzbnZSZ3hpV0ZPdE5KY09NVkxuMXZncHRWaTZxck5pRk9mRWpIQ0RCM0olMkJIRExxVUI3N1lnUUd3WCUyRmIxZVluYTNoR0tkbHFKS0l5aUU0blNiVjhWRmd4bXhSNGI1bVZra2VVaE1nczVZVGk0amEyWFowMDl4SlJIZGtmd01pJTJCZm9jYWFuY3VPN2glMkZNbGNMT2EwViUyRlN3NkRxNDdDdW1SUUFLaGdiT1A4dCUyQk1UanV4akpHaFhDWTZYcG1EREZxV2xWWWJRMWFESjVDcHRkdzRvTGJmM0NrJTJCZFdrVlAwTHBIN3M5WExQWEklMkZRWDh3cyUyQmoySW42M0ljUnZPT28lMkJUVGppTiUyQmxzc2ZSc2FuVyUyQjNSRVZLb2F2Qk9BUFRYQUJXNEFMN2U0TnlnSGRwQUtCc2NtbERoOUp5c3A0d3hiblVObmEzTDN4QnZ5RTFqeXJHSWtVSGFxUU11eGhIRWxWNm9qMXBpY3ZnTDFRRXVTNVB5WlRFYWl2cWg1dlVDS0pxT3VJZ1BGR0VTbnM4a3lGazclMkZEeHlpbWEzY1l4aSUyRllPUUNqJTJGJTJCOU1zMkxsJTJCaG40Rm1Lbmw3SmtHWFFHREtEQXo5clVHTDFUSWxCcHVKcjlCZTJKaks2cVB6eURnNDk1VXhYWUY3SlkxcUtpbXc5aldqRjBpVjZEUklxRSUyQiUyRmVXRzBKMm9mbVpUazBtTFlWZDRHTGlGQ09vS1IwQ2c3Mjd0V3E5ODFJbll5bnZDdUtXNDNhWGdFam9mVmJ4SXFybTBWTDc2emxIM2dReldQM1IzQnY5b1h4Y2xybE83VlZ0Z0JScFNQNGhNRldKOEJyVVNCQ0pYQzA3bDQwWDRqV3V2dGM0Mm9mTkN4dGxYMkpINmJkZW9qWGdUaDVUeE9CS0V5WTV3dkJFJTJCQUNoOEJ0T1BOUGtBcGpveGk1aCUyQiUyRkZNUVFOcFd2WmFNSDdNS0Z1NUF4OEhvQ1FkbUdrSnJ0bk9pTEh3RDN1UzV5OCUyRjJ4VFNEckUlMkY0UFQxeXF0dDZ2R2U4bGRNQlZNRVBkNkt3cWlZRUNIRGxmYnZ6cGhjV1AlMkJKaVp1TDVzd29XUVlsUyUyQnI3WXU1bU5VaUdEMnJldHhCaTlmbDZSREduNFRpOUIxb3lZeSUyQk1QNUc4N0QlMkZDcFJsdmRudXkwUFk2UkM4QnpUQTQwTlhxY2tROVRhT1VEeXdrWXN1ZHhKelBneURvQVduJTJCQjZuRUZiYVZ4eEM2VVhqSml1RGtXOVRXcTd1UkJPSm9ja3k5aU1mVWhHcHYlMkZkUXVWVkl1R2pZcUFDYlhmOGFhJTJCUGVZTklIWnNNN2w0czVnQVF1VUF6UlVvVDUxaG5IM0VXb2ZYZjJ2a0Q1SEpKMzN2d0UlMkZhRVdwMzZHSHI2R3BNYUg0QUFQdXFNNWVhYkglMkZoZkc5emNDejRuTjZjUGludUF3NklId3R2eUIlMkZkTzF0b1pjaUJhUGgyNVUwZHVjUjJQSTNabDdtb2t5TFdLa1NuRURPZzF4NWZDc0pFOUVLaEg3SHdGTmhXTUdNUzclMkJxeHlZc2JISFJVRFVINEklMkZBaGVRWTd3dWpKTm5GVUg0S2RDanU4M3JpdVFlSFU5V0VxTnpqc0pGdUYlMkZkVERBWiUyRks3JTJGMVdhQVUlMkJBV3ltVDU5cFZNVDRnMkF4Y3dOYTBYRUJEZEJEcEFQdmdESUg3M1IyNXRlZXVBRjVpbWUyVWwwT1VJaUc0R3BTQUVKZVlXOXdEVGY0M3dmd0hnSExLSm9Qem5rd0FBQUFCSlJVNUVya0pnZ2clM0QlM0QpXShodHRwOi8vZHguZG9pLm9yZy8xMC42MDg0L205LmZpZ3NoYXJlLjk5NzAyMDUpCgojIEhvdyB0byBjaXRlIHRoaXMgUiBOb3RlYm9vawoKUGxlYXNlIGNpdGUgdGhpcyBSIE5vdGVib29rIGFzIGZvbGxvd3MgKGluIFVuaWZpZWQgU3R5bGUgU2hlZXQgZm9yIExpbmd1aXN0aWNzKToKCj4gUmFqZWcsIEdlZGUgUHJpbWFoYWRpIFdpamF5YSwgS2FybGluYSBEZW5pc3RpYSAmIFNpbW9uIE11c2dyYXZlLiAyMDE5LiBSIE1hcmtkb3duIE5vdGVib29rIGZvciAqVmVjdG9yIHNwYWNlIG1vZGVsIGFuZCB0aGUgdXNhZ2UgcGF0dGVybnMgb2YgSW5kb25lc2lhbiBkZW5vbWluYWwgdmVyYnMqLiBmaWdzaGFyZS4gaHR0cHM6Ly9kb2kub3JnMTAuNjA4NC9tOS5maWdzaGFyZS45OTcwMjA1LiBodHRwczovL2ZpZ3NoYXJlLmNvbS9hcnRpY2xlcy9SX01hcmtkb3duX05vdGVib29rX2Zvcl9pX1ZlY3Rvcl9zcGFjZV9tb2RlbF9hbmRfdGhlX3VzYWdlX3BhdHRlcm5zX29mX0luZG9uZXNpYW5fZGVub21pbmFsX3ZlcmJzX2lfLzk5NzAyMDUuCgojIFByZWZhY2UKCmBgYHtyIHNldHVwLCBtZXNzYWdlID0gRkFMU0V9CiMgZ2xvYmFsIG9wdGlvbiBjaHVuY2sKa25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy53aWR0aCA9IDcsIAogICAgICAgICAgICAgICAgICAgICAgZmlnLmFzcCA9IDAuNjE4LAogICAgICAgICAgICAgICAgICAgICAgZHBpID0gMzAwLAogICAgICAgICAgICAgICAgICAgICAgZGV2ID0gInBkZiIsCiAgICAgICAgICAgICAgICAgICAgICBlY2hvID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5wYXRoID0gImZpZ3VyZXMvIikKYGBgCgoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgW05vdGVib29rXShodHRwczovL2Jvb2tkb3duLm9yZy95aWh1aS9ybWFya2Rvd24vbm90ZWJvb2suaHRtbCkgW0ByYWplZ19yXzIwMTldIGZvciB0aGUgc3RhdGlzdGljYWwgYW5hbHlzZXMgYWNjb21wYW55aW5nIG91ciBbcGFwZXJdKGh0dHA6Ly9yZXBvc2l0b3J5LnR1ZnMuYWMuanAvaGFuZGxlLzEwMTA4Lzk0NDUyKSBbQHJhamVnX3ZlY3Rvcl8yMDE5XSBvbiB2ZWN0b3Igc3BhY2UgbW9kZWxzIGFuZCBJbmRvbmVzaWFuIGRlbm9taW5hbCB2ZXJicyAocHVibGlzaGVkIGluIFsqTlVTQSpdKGh0dHA6Ly93d3cuYWEudHVmcy5hYy5qcC9lbi9wdWJsaWNhdGlvbnMvbnVzYSkncyBzcGVjaWFsIGlzc3VlIHRpdGxlZCBbKkxpbmd1aXN0aWMgc3R1ZGllcyB1c2luZyBsYXJnZSBhbm5vdGF0ZWQgY29ycG9yYSpdKGh0dHA6Ly9yZXBvc2l0b3J5LnR1ZnMuYWMuanAvaGFuZGxlLzEwMTA4Lzk0NDUwKSwgZWRpdGVkIGJ5IFtIaXJva2kgTm9tb3RvXShodHRwOi8vd3d3LnR1ZnMuYWMuanAvdHMvcGVyc29uYWwvbm9tb3RvLykgYW5kIFtEYXZpZCBNb2VsamFkaV0oaHR0cDovL2NvbXBsaW5nLmhzcy5udHUuZWR1LnNnL3doby9kYXZpZC8pKSBbQG5vbW90b19saW5ndWlzdGljXzIwMTldLiBUaGUgTm90ZWJvb2ssIGhvd2V2ZXIsIGRvZXMgbm90IHByb3ZpZGUgZGV0YWlsZWQgZXhwb3NpdGlvbiBhbmQgZGlzY3Vzc2lvbiBmb3IgZWFjaCBwb2ludHMsIGluY2x1ZGluZyBFbmdsaXNoIGdsb3NzaW5nIG9mIHRoZSBJbmRvbmVzaWFuIHdvcmRzIGluIHRoZSB0YWJsZXMuIFJlYWRlcnMgYXJlIHJlZmVycmVkIHRvIG91ciBbcGFwZXJdKGh0dHA6Ly9yZXBvc2l0b3J5LnR1ZnMuYWMuanAvaGFuZGxlLzEwMTA4Lzk0NDUyKSBmb3IgZGV0YWlscy4gQ2hlY2sgdGhlIFJFQURNRSBwYWdlIFtoZXJlXShodHRwczovL2dpdGh1Yi5jb20vZ2VkZXJhamVnL3ZlY3Rvcl9zcGFjZV9tb2RlbF9pbmRvbmVzaWFuKSBmb3IgdGhlIHR1dG9yaWFsIHRvIGRvd25sb2FkIHRoaXMgTm90ZWJvb2sgYW5kIHRoZSBkYXRhIFtAcmFqZWdfZGF0YXNldF8yMDE5XSBmb3IgdGhlIHBhcGVyLgoKVGhlIGZvbGxvd2luZyBSIHBhY2thZ2VzIGhhdmUgdG8gYmUgaW5zdGFsbGVkIGFuZCBsb2FkZWQgdG8gcnVuIGFsbCBjb2RlcyBpbiB0aGlzIE5vdGVib29rOgoKLSBjbHVzdGVyIFtAbWFlY2hsZXJfY2x1c3Rlcl8yMDE4XQotIHRpZHl2ZXJzZSBbQHdpY2toYW1fcl8yMDE3XQotIGRlbmRleHRlbmQgW0BnYWxpbGlfZGVuZGV4dGVuZF8yMDE1XQotIHdvcmRWZWN0b3JzIFtAc2NobWlkdF93b3JkdmVjdG9yc18yMDE3XQotIFJsaW5nIFtAbGV2c2hpbmFfaG93XzIwMTVdCgpDbGljayB0aGUgYENvZGVgIGJ1dHRvbiB0byBoaWRlL3JldmVhbCB0aGUgUiBjb2Rlcy4KCmBgYHtyIHV0aWxpc2VkLXBhY2thZ2VzLCBlY2hvID0gVFJVRX0KIyBsb2FkIHRoZSByZXF1aXJlZCBwYWNrYWdlcwojIyBtYWtlIHN1cmUgYWxsIHBhY2thZ2VzIGFyZSBpbnN0YWxsZWQhCmxpYnJhcnkoY2x1c3RlcikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZGVuZGV4dGVuZCkKbGlicmFyeSh3b3JkVmVjdG9ycykgIyBzaG91bGQgYmUgaW5zdGFsbGVkIGZyb20gQmVuIFNjaG1pZHQncyBHaXRIdWIKbGlicmFyeShSbGluZykgIyA8LSBgUmxpbmdgIHBhY2thZ2UgZnJvbSBOYXRhbGlhIExldnNoaW5hJ3MgKDIwMTUpIGJvb2sgJ0hvdyB0byBkbyBsaW5ndWlzdGljcyB3aXRoIFInIHB1Ymxpc2hlZCBieSBKb2huIEJlbmphbWlucy4KYGBgCgoKIyBJbGx1c3RyYXRpb24gZm9yIGdlbmVyYXRpbmcgVmVjdG9yIFNwYWNlIE1vZGVscyAoVlNNKQoKRm9yIGlsbHVzdHJhdGlvbiwgd2UgdXNlZCBzaXggZGV2ZXJiYWwgbm91bnMgd2l0aCB0aGUgc3VmZml4IC0qYW4qLiBUaGV5IGFyZSAqYmFjYWFuKiAncmVhZGluZycgKGZyb20gdGhlIHJvb3QgKmJhY2EqICd0byByZWFkJyksICp0dWxpc2FuKiAnd3JpdGluZycgKGZyb20gKnR1bGlzKiAndG8gd3JpdGUnKSwgKmx1a2lzYW4qICdwYWludGluZycgKGZyb20gKmx1a2lzKiAndG8gcGFpbnQvZHJhdycpLCAqbWFzYWthbiogJ2Nvb2tpbmcnIChmcm9tICptYXNhayogJ3RvIGNvb2snKSwgKm1ha2FuYW4qICdmb29kJyAoZnJvbSAqbWFrYW4qICd0byBlYXQnKSwgYW5kICptaW51bWFuKiAnYmV2ZXJhZ2VzJyAoZnJvbSAqbWludW0qICd0byBkcmluaycpLiBXZSByZXRyaWV2ZWQgY29sbG9jYXRlcyB3aXRoaW4gdGhyZWUtd29yZCB3aW5kb3cgdG8gdGhlIGVpdGhlciBzaWRlcyAobGVmdCBhbmQgcmlnaHQpIG9mIGVhY2ggbm91bi4gV2UgdXNlZCBvbmUgb2YgdGhlIF9JbmRvbmVzaWFuXyBbX0xlaXB6aWcgQ29ycG9yYV9dKGh0dHA6Ly9jb3Jwb3JhMi5pbmZvcm1hdGlrLnVuaS1sZWlwemlnLmRlL2Rvd25sb2FkLmh0bWwpIGZpbGVzLCBuYW1lbHkgKmluZF9taXhlZF8yMDEyXzFNLXNlbnRlbmNlcy50eHQqIFtzZWUgQGJpZW1hbm5fbGVpcHppZ18yMDA3OyBAcXVhc3Rob2ZmX2luZG9uZXNpYW5fMjAxM10uCgojIyBDcmVhdGluZyB0aGUgY28tb2NjdXJyZW5jZSBmcmVxdWVuY3kgdGFibGUKClRoZSBmb2xsb3dpbmcgY29kZXMgcHJvY2VzcyB0aGUgcmV0cmlldmVkIGNvbGxvY2F0ZXMgaW50byBjby1vY2N1cnJlbmNlIGZyZXF1ZW5jeSB0YWJsZSBhbmQgcHJpbnQgYSBzdWJzZXQgb2YgdGhpcyB0YWJsZS4gVGhlIGNvbGxvY2F0ZXMgZGF0YSBpcyBhdmFpbGFibGUgaW4gdGhlIGAidnNtX2NyZWF0aW9uX2RhdGEucmRzImAgZmlsZS4gVGhpcyBgLnJkc2AgZmlsZSBjb250YWlucyBhIGBMaXN0YCBkYXRhLXN0cnVjdHVyZTsgdGhlIHRhYmxlIHZlcnNpb24gaXMgYXZhaWxhYmxlIGFzIHRhYi1kZWxpbWl0ZWQgYC5jc3ZgIGFuZCBgLnR4dGAgZmlsZXMgKGB2c21fY3JlYXRpb25fZGF0YV90Yi50eHRgICYgYHZzbV9jcmVhdGlvbl9kYXRhX3RiLmNzdmApLgoKYGBge3IgdnNtLXhtcGwtY29sbGZyZXF9CmRmX2xpc3QgPC0gcmVhZFJEUyhmaWxlID0gImRhdGEvdnNtX2NyZWF0aW9uX2RhdGEucmRzIikKZGZfZXggPC0gcHVycnI6Om1hcF9kZihkZl9saXN0LCBkcGx5cjo6YmluZF9yb3dzKTsgcm0oZGZfbGlzdCkKZGZfZXgxIDwtIGRwbHlyOjpmaWx0ZXIoZGZfZXgsIAogICAgICAgICAgICAgICAgICAgICAgICAhaXMubmEodyksICMgcmVtb3ZlIE5BcwogICAgICAgICAgICAgICAgICAgICAgICBuY2hhcih3KSA+IDEsICMgcmVtb3ZlIG9uZS1jaGFyYWN0ZXIgdG9rZW5zCiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3I6OnN0cl9kZXRlY3QodywgIl5bYS16LV0rJCIpLAogICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgIyByZW1vdmUgaW5jb21wbGV0ZSB3b3JkcwogICAgICAgICAgICAgICAgICAgICAgICAhc3RyaW5ncjo6c3RyX2RldGVjdCh3LCAiXlthLXpdKy0kIiksIAogICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgIyByZW1vdmUgaW5jb21wbGV0ZSB3b3JkcwogICAgICAgICAgICAgICAgICAgICAgICAhc3RyaW5ncjo6c3RyX2RldGVjdCh3LCAiXi1bYS16XSskIikpIAoKZGZfZXgxX2NvdW50IDwtIGRwbHlyOjpjb3VudChkZl9leDEsIG5vZGUsIHcsIHNvcnQgPSBUUlVFKQpkZl9leDFfY291bnRfc3ByZWFkIDwtIHRpZHlyOjpzcHJlYWQoZGZfZXgxX2NvdW50LCB3LCBuLCBmaWxsID0gMCkKZGZfZXgxX2NvdW50X3NwcmVhZCA8LSBhcy5kYXRhLmZyYW1lKGRmX2V4MV9jb3VudF9zcHJlYWQpCmRmX2V4MV9jb3VudF9zcHJlYWQgPC0gZGZfZXgxX2NvdW50X3NwcmVhZFssIGNvbFN1bXMoZGZfZXgxX2NvdW50X3NwcmVhZFssIC0xXSkgPiAwXQpyb3duYW1lcyhkZl9leDFfY291bnRfc3ByZWFkKSA8LSBkZl9leDFfY291bnRfc3ByZWFkJG5vZGUKZGZfZXgxX2NvdW50X3NwcmVhZCA8LSBkZl9leDFfY291bnRfc3ByZWFkWywgLTFdCgpzZWxlY3RlZF9jb2x1bW4gPC0gYygiYWxraXRhYiIsIAogICAgICAgICAgICAgICAgICAgICAiZGl0dWFuZ2thbiIsICJoYWxhbCIsICJrZXJhcyIsIAogICAgICAgICAgICAgICAgICAgICAibWVuZ2FuZHVuZyIsICJwZW51dHVwIikKZGZfZXgxX3ByaW50IDwtIGRmX2V4MV9jb3VudF9zcHJlYWRbLCBzZWxlY3RlZF9jb2x1bW5dCnJvd25hbWVzKGRmX2V4MV9wcmludCkgPC0gcGFzdGUoIioiLCByb3duYW1lcyhkZl9leDFfcHJpbnQpLCAiKiIsIHNlcCA9ICIiKQpjb2xuYW1lcyhkZl9leDFfcHJpbnQpIDwtIHBhc3RlKCIqIiwgY29sbmFtZXMoZGZfZXgxX3ByaW50KSwgIioiLCBzZXAgPSAiIikKZGZfZXgxX3ByaW50JGAuLi5gIDwtIHJlcCgiLi4uIiwgbnJvdyhkZl9leDFfcHJpbnQpKQprbml0cjo6a2FibGUoZGZfZXgxX3ByaW50LCBjYXB0aW9uID0gIlJhdyBjby1vY2N1cnJlbmNlIGZyZXF1ZW5jeSBmb3IgdGhlIHRhcmdldCB3b3JkcyB3aXRoIHRoZSBjb250ZXh0IHdvcmRzIikKYGBgCgoKIyMgUGVyZm9ybWluZyB0aGUgKlBvc2l0aXZlIFBvaW50d2lzZSBNdXR1YWwgSW5mb3JtYXRpb24qCgpDdXJyZW50IGFwcHJvYWNoIGluIFZTTSBhZG9wdHMgYSBtb3JlIHByaW5jaXBsZWQgbWV0aG9kIG9mIHdlaWdodGluZyB0aGUgaW5pdGlhbCByYXctZnJlcXVlbmN5IHZlY3RvcnMgaW50byBzdGF0aXN0aWNhbCBtZWFzdXJlcyBvZiBjb2xsb2NhdGlvbiBzdHJlbmd0aCBiZWZvcmUgY29tcHV0aW5nIChkaXMpc2ltaWxhcml0eSBtZWFzdXJlIGJldHdlZW4gdGhlIHRhcmdldCB3b3Jkcy4gVGhlIGdvYWwgb2YgdGhlIHdlaWdodGluZyBpcyAidG8gZ2l2ZSBhIGhpZ2hlciB3ZWlnaHQgdG8gY29udGV4dCB3b3JkcyB0aGF0IGNvLW9jY3VyIHNpZ25pZmljYW50bHkgbW9yZSBvZnRlbiB0aGFuIGV4cGVjdGVkIGJ5IGNoYW5jZSIgW0BoZXlsZW5fbW9uaXRvcmluZ18yMDE1LCAxNTY7IGNmLiBAbGFwcGluX3ZlY3Rvcl8yMDE1LCA1MDMtNTA0OyBAcGVyZWtfcmVjZW50XzIwMTYsIDEyXS4gVGhlc2Ugc2lnbmlmaWNhbnRseSBhc3NvY2lhdGllZCBjb250ZXh0IHdvcmRzIGFyZSBhc3N1bWVkIHRvIGJlIG1vcmUgaW5mb3JtYXRpdmUgZm9yIHRoZSBzZW1hbnRpY3Mgb2YgdGhlIHRhcmdldCB3b3JkcyBbQGhleWxlbl9tb25pdG9yaW5nXzIwMTUsIDE1Nl0uIFRoZSBwb3B1bGFyIHdlaWdodGluZyBtZWFzdXJlIHVzZWQgaW4gVlNNIGlzIHRoZSAqUG9pbnR3aXNlIE11dHVhbCBJbmZvcm1hdGlvbiogKFBNSSkgW3NlZSBAbGV2c2hpbmFfaG93XzIwMTUsIDMyNy0zMjggZm9yIGNvbXB1dGluZyBQTUkgaW4gUl06CgokJFx0ZXh0e1BNSSB9ICh4LCB5KSA9IGxvZ197Mn0gXGZyYWMge09fe3h5fX0ge0Vfe3h5fX0kJAoKd2hlcmUgJE9fe3h5fSQgcmVwcmVzZW50cyB0aGUgb2JzZXJ2ZWQgY28tb2NjdXJyZW5jZSBmcmVxdWVuY3kgYmV0d2VlbiAqeCogYW5kICp5Kiwgd2hpbGUgJEVfe3h5fSQgaXMgdGhlaXIgZXhwZWN0ZWQgY28tb2NjdXJyZW5jZSBmcmVxdWVuY3ksIHdoaWNoIGlzIHRoZSBmcmVxdWVuY3kgZXhwZWN0ZWQgdW5kZXIgdGhlIGNoYW5jZSBkaXN0cmlidXRpb24gYmV0d2VlbiAqeCogYW5kICp5KiBnaXZlbiB0aGUgb3ZlcmFsbCBkaXN0cmlidXRpb24gb2YgKngqIGFuZCAqeSogaW4gdGhlIGNvcnB1cy4gTmVnYXRpdmUgUE1JIHZhbHVlcyBpcyBub3JtYWxseSByZXBsYWNlZCB3aXRoIHplcm8sIHJlc3VsdGluZyBpbiB0aGUgKlBvc2l0aXZlIFBNSSogKFBQTUkpIFtAbGV2c2hpbmFfaG93XzIwMTU7IEBoaWxwZXJ0X21lYW5pbmdfMjAxNV0uCgpgYGB7ciB2c20teG1wbC1wcG1pLCB3YXJuaW5nID0gRkFMU0V9Cm10eCA8LSBhcy5tYXRyaXgoZGZfZXgxX2NvdW50X3NwcmVhZCkKbXR4X2V4cCA8LSBjaGlzcS50ZXN0KG10eCkkZXhwZWN0ZWQKbXR4X3BtaSA8LSBsb2cyKG10eC9tdHhfZXhwKTsgcm0obXR4KQptdHhfcHBtaSA8LSBpZmVsc2UobXR4X3BtaSA8IDAsIDAsIG10eF9wbWkpOyBybShtdHhfZXhwKQpwcG1pcHJpbnQgPC0gYXMuZGF0YS5mcmFtZShyb3VuZChtdHhfcHBtaSwgZGlnaXRzID0gMikpOyBybShtdHhfcG1pKQpwcG1pcHJpbnQgPC0gcHBtaXByaW50Wywgc2VsZWN0ZWRfY29sdW1uXQpyb3duYW1lcyhwcG1pcHJpbnQpIDwtIHBhc3RlKCIqIiwgcm93bmFtZXMocHBtaXByaW50KSwgIioiLCBzZXAgPSAiIikKY29sbmFtZXMocHBtaXByaW50KSA8LSBwYXN0ZSgiKiIsIGNvbG5hbWVzKHBwbWlwcmludCksICIqIiwgc2VwID0gIiIpCnBwbWlwcmludCRgLi4uYCA8LSByZXAoIi4uLiIsIG5yb3coZGZfZXgxX2NvdW50X3NwcmVhZCkpCmtuaXRyOjprYWJsZShwcG1pcHJpbnQsIGNhcHRpb24gPSAiV2VpZ2h0ZWQgY28tb2NjdXJyZW5jZSBmcmVxdWVuY3kgd2l0aCAqUG9zaXRpdmUgUG9pbnR3aXNlIE11dHVhbCBJbmZvcm1hdGlvbioiKQpgYGAKCkZ1cnRoZXIgYW5hbHlzaXMgY2FuIGJlIHBlcmZvcm1lZC4gVGhlIG1vc3QgY29tbW9uIG9uZSBpcyBkZXRlcm1pbmluZyB0aGUgc2VtYW50aWMgKGRpcylzaW1pbGFyaXR5IGJldHdlZW4gdGhlIHRhcmdldCB3b3JkcyAoaS5lLiwgd2hpY2ggd29yZCBpcyBtb3JlIHNpbWlsYXIgYW5kIGRpZmZlcmVudCBhbW9uZyBlYWNoIG90aGVyKS4gVGhlIGZvbGxvd2luZyBzZWN0aW9uIGJyaWVmbHkgZGlzY3Vzc2VzIHRoZSAqQ29zaW5lIFNpbWlsYXJpdHkqIGFuZCAqSGllcmFyY2hpY2FsIEFnZ2xvbWVyYXRpdmUgQ2x1c3RlciogKEhBQykgYW5hbHlzZXMgYXMgdGhlIGV4cGxvcmF0b3J5IHRvb2xzIFtAbGV2c2hpbmFfZ2VvZ3JhcGhpY18yMDE0OyBAbGV2c2hpbmFfaG93XzIwMTVdLgoKIyMgRXhwbG9yaW5nIFZTTSB3aXRoICpDb3NpbmUgU2ltaWxhcml0eSogYW5kICpIaWVyYXJjaGljYWwgQWdnbG9tZXJhdGl2ZSBDbHVzdGVyKiAoSEFDKSBhbmFseXNpcwoKSW4gVlNNLCAqY29zaW5lIHNpbWlsYXJpdHkqIGlzIHRoZSBwb3B1bGFyIG1lYXN1cmUgZm9yIGNvbXB1dGluZyBwYWlyd2lzZSAoZGlzKXNpbWlsYXJpdHkgYmV0d2VlbiB0aGUgdGFyZ2V0IHdvcmRzLiBDb3NpbmUgc2ltaWxhcml0eSBjb21wdXRlcyB0aGUgY29zaW5lIG9mIGFuZ2xlcyBiZXR3ZWVuIHRoZSB3b3JkcycgdmVjdG9ycyB0byBjYXB0dXJlIHRoZWlyIChkaXMpc2ltaWxhcml0eS4gVGhlIGNvc2luZSB2YWx1ZSBiZXR3ZWVuIGEgcGFpciBvZiB3b3JkIGlzIGNsb3NlIHRvIDEgd2hlbiB0aGV5IGFyZSBzZW1hbnRpY2FsbHkgbW9yZSBzaW1pbGFyLCBhbmQgY2xvc2UgdG8gMCB3aGVuIG90aGVyd2lzZSAoc2VlIFtcQHJlZih0YWI6dnNtLXhtcGwtY29zc2ltKV0oI3ZzbS14bXBsLWNvc3NpbSkpIFtAbGV2c2hpbmFfaG93XzIwMTUsIENoLiAxNl0uIAoKVGhlIGZvbGxvd2luZyBjb2RlcyBwZXJmb3JtIGNvc2luZSBzaW1pbGFyaXR5IHVzaW5nIHRoZSBgY29zc2ltKClgIGZ1bmN0aW9uIGZyb20gdGhlIFJsaW5nIHBhY2thZ2UgW0BsZXZzaGluYV9ob3dfMjAxNSwgMzI5XS4KCmBgYHtyIHZzbS14bXBsLWNvc3NpbX0KIyBDb3NpbmUgU2ltaWxhcml0eQptdHhfY29zc2ltIDwtIFJsaW5nOjpjb3NzaW0obXR4X3BwbWkpOyBybShtdHhfcHBtaSkKCiMgR2VuZXJhdGUgQ29zU2ltIHRhYmxlIG91dHB1dAphdHRyKG10eF9jb3NzaW0sICJkaW1uYW1lcyIpW1sxXV0gPC0gcGFzdGUoIioiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dHIobXR4X2Nvc3NpbSwgImRpbW5hbWVzIilbWzFdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIqIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICIiKQphdHRyKG10eF9jb3NzaW0sICJkaW1uYW1lcyIpW1syXV0gPC0gcGFzdGUoIioiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dHIobXR4X2Nvc3NpbSwgImRpbW5hbWVzIilbWzJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIqIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICIiKQprbml0cjo6a2FibGUocm91bmQobXR4X2Nvc3NpbSwgZGlnaXRzID0gMiksIAogICAgICAgICAgICAgY2FwdGlvbiA9ICJDb3NpbmUgc2ltaWxhcml0eSBtYXRyaXggYmV0d2VlbiB0aGUgZGV2ZXJiYWwgbm91bnMiKQpgYGAKCkZvciB0aGUgY2x1c3RlciBhbmFseXNpcywgc3VjaCBhcyBIQUMgW0BsZXZzaGluYV9nZW9ncmFwaGljXzIwMTQ7IHNlZSBhbHNvIEBncmllc19zdGF0aXN0aWNzXzIwMTMsIDMzNjsgQGxldnNoaW5hX2hvd18yMDE1LCBDaC4gMTU7IGFuZCBAZGVzYWd1bGllcl9jb3JwdXNfMjAxNywgMjc2IGZvciBSIGltcGxlbWVudGF0aW9ucyBvbiBIQUNdLCB0aGUgc2ltaWxhcml0eSBtYXRyaXgvdGFibGUgYXMgYWJvdmUgbmVlZHMgdG8gYmUgY29udmVydGVkIGludG8gZGlzdGFuY2UgbWF0cml4IGFzIGlucHV0IGZvciB0aGUgY2x1c3RlciBhbmFseXNpcyBbc2VlIHRoZSBjb2RlcyBiZWxvdyBhZGFwdGVkIGZyb20gQGxldnNoaW5hX2hvd18yMDE1LCAzMzBdLgoKYGBge3IgdnNtLXhtcGwtaGFjfQojIERpc3RhbmNlIG1hdHJpeCBjb21wdXRhdGlvbgptdHhfZGlzdCA8LSAxIC0gKG10eF9jb3NzaW0vbWF4KG10eF9jb3NzaW1bbXR4X2Nvc3NpbSAhPSAxXSkpCm10eF9kaXN0IDwtIGFzLmRpc3QobXR4X2Rpc3QpCgojIENsdXN0ZXIgYW5hbHlzaXMKbXR4X2hjbCA8LSBoY2x1c3QobXR4X2Rpc3QsIG1ldGhvZCA9ICJ3YXJkLkQyIikKYGBgCgpUaGUgb3V0cHV0IG9mIEhBQyBjYW4gYmUgdmlzdWFsaXNlZCBpbnRvIGEgZGVuZHJvZ3JhbSB0cmVlIChzZWUgW0ZpZ3VyZSBcQHJlZihmaWc6dnNtLXhtcGwtZGVuZHJvZ3JhbSldKCN2c20teG1wbC1kZW5kcm9ncmFtKSkuIFRvIGRldGVybWluZSB0aGUgb3B0aW1hbCBudW1iZXIgb2YgY2x1c3RlciBzb2x1dGlvbiBmb3IgZ3JvdXBpbmcgdGhlIG5vdW5zLCB3ZSB1c2VkIHRoZSAqQXZlcmFnZSBTaWxob3VldHRlIFdpZHRoKiAoQVNXKSBzY29yZXMgYW5kIHRlc3RlZCB0d28gdXAgdG8gZml2ZS1jbHVzdGVyIHNvbHV0aW9ucy4gVGhlIHR3by1jbHVzdGVyIHNvbHV0aW9uIHByb2R1Y2VzIHRoZSBoaWdoZXN0IEFTVyBzY29yZS4gU2VlIHRoZSBjb2RlcyBiZWxvdy4gCgpgYGB7ciB2c20teG1wbC1kZW5kcm9ncmFtLCBmaWcuYXNwID0gMC43NSwgZmlnLmNhcCA9ICJWU00tYmFzZWQgY2x1c3RlciBkZW5kcm9ncmFtIGZvciB0aGUgdGFyZ2V0IHdvcmRzIn0KIyBBU1cgY2FsY3VsYXRpb24KbXR4X2FzdyA8LSBzYXBwbHkoMjoobnJvdyhtdHhfY29zc2ltKSAtIDEpLCBmdW5jdGlvbih4KSBzdW1tYXJ5KGNsdXN0ZXI6OnNpbGhvdWV0dGUoc3RhdHM6OmN1dHJlZShtdHhfaGNsLCBrID0geCksIG10eF9kaXN0KSkkYXZnLndpZHRoKQoKIyBuYW1lcyB0aGUgQVNXIHNjb3JlcyByZXByZXNlbnRpbmcgdGhlIHRlc3RlZCBjbHVzdGVyLXNvbHV0aW9ucyAKbmFtZXMobXR4X2FzdykgPC0gMjoobnJvdyhtdHhfY29zc2ltKSAtIDEpCgojIGlkZW50aWZ5IHRoZSBtYXhpbXVtIEFTVyBzY29yZQptYXhfYXN3IDwtIGFzLm51bWVyaWMobmFtZXMobXR4X2Fzd1ttdHhfYXN3ID09IG1heChtdHhfYXN3KV0pKQoKIyBwbG90dGluZyBkZW5kcm9ncmFtCm10eF9oY2wkbGFiZWxzIDwtIGdzdWIoJ1xcKicsICcnLCBtdHhfaGNsJGxhYmVscykKcGxvdChtdHhfaGNsLCBoYW5nID0gLTEpCnJlY3QuaGNsdXN0KG10eF9oY2wsIGsgPSBtYXhfYXN3KQoKIyBnZW5lcmF0ZSB0ZXh0cyBhbm5vdGF0aW9uIHdpdGhpbiB0aGUgcGxvdAphZGRlZF9pbmZvIDwtIHBhc3RlKCJUaGUgIiwgbWF4X2FzdywgIi1jbHVzdGVyIHNvbHV0aW9uIGlzIGJhc2VkIG9uIHRoZSBoaWdoZXN0IEF2ZXJhZ2UgU2lsaG91ZXR0ZSBXaWR0aCAoQVNXKSBzY29yZSBvZiAiLCByb3VuZChtYXgobXR4X2FzdyksIDMpLCAiLlxuKEFTVyByYW5nZXMgZnJvbSAwIHRvIDE7IG1pbi4gQVNXIHNjb3JlIGZvciBhc3N1bWluZyBzdWJzdGFudGlhbCBjbHVzdGVyIGlzIDAuMikiLCBzZXAgPSAiIikKbXRleHQoYWRkZWRfaW5mbywgc2lkZSA9IDEsIGxpbmUgPSAxLjc1LCBjZXggPSAuOCkKYGBgCgpUaGUgZm9sbG93aW5nIGNvZGVzIHByb2R1Y2UgdGhlIHBsb3QgdmlzdWFsaXNpbmcgdGhlIG51bWJlciBvZiBjbHVzdGVyLXNvbHV0aW9ucyB0ZXN0ZWQgYW5kIHRoZWlyIGNvcnJlc3BvbmRpbmcgQVNXIHNjb3Jlcy4KCmBgYHtyIHZzbS14bXBsLWFzdy1wbG90LCBmaWcuYXNwID0gLjc1LCBmaWcuY2FwID0gIkF2ZXJhZ2UgU2lsaG91ZXR0ZSBXaWR0aHMgZm9yIHRoZSB0ZXN0ZWQgY2x1c3RlciBzb2x1dGlvbnMifQpwbG90KHggPSAyOjUsIHkgPSBtdHhfYXN3LCAKICAgICB0eXBlID0gImIiLCB4YXh0ID0gIm4iLCAKICAgICB5bGFiID0gIkF2ZXJhZ2UgU2lsaG91ZXR0ZSBXaWR0aHMgKEFTVykiLCAKICAgICB5bGltID0gYygwLCAxKSwKICAgICB4bGFiID0gIk51bWJlciBvZiB0ZXN0ZWQgY2x1c3RlciBzb2x1dGlvbnMiKQpheGlzKHNpZGUgPSAxLCBhdCA9IDI6NSkKdGV4dCgyOjUsIAogICAgIG10eF9hc3csIAogICAgIGxhYmVscyA9IHJvdW5kKG10eF9hc3csIGRpZ2l0cyA9IDMpLCAKICAgICBwb3MgPSAzLCAKICAgICBjZXggPSAuOCkKdGV4dCh4ID0gMy4yNSwKICAgICB5ID0gMC4yLCAKICAgICBsYWJlbHMgPSAiVGhlIDItY2x1c3RlciBzb2x1dGlvbiBwcm9kdWNlcyB0aGUgaGlnaGVzdCBBU1cgc2NvcmUiKQpgYGAKCgojIE1ldGhvZG9sb2d5CgojIyBEYXRhIHNvdXJjZQoKVGhlIHBhcGVyIHVzZXMgdGhpcnRlZW4gY29ycHVzIGZpbGVzIGZyb20gdGhlIEluZG9uZXNpYW4gTGVpcHppZyBDb3Jwb3JhIHRvIGJlIHRyYWluZWQgaW50byBhIHZlY3RvciBzcGFjZSBtb2RlbHMuIFRoZSBmb2xsb3dpbmcgY29kZXMgc2hvdyBob3cgdG8gbG9hZCB0aGUgZGF0YSBmb3IgdGhlIGluZm9ybWF0aW9uIG9mIGNvcnB1cyBzaXplIChpLmUuIGAid29yZGNvdW50X2xlaXB6aWdfYWxsY29ycHVzLlJEYXRhImApIGFuZCB0byBwcmludCB0aGVtLgoKYGBge3IgbGVpcHppZy1jb3JwdXMtc2l6ZX0KIyBsb2FkIHRoZSBjb3JwdXMgc2l6ZSBkYXRhCmxvYWQoImRhdGEvd29yZGNvdW50X2xlaXB6aWdfYWxsY29ycHVzLlJEYXRhIikKCiMgcHJpbnQgdGhlIHRhYmxlCmxlaXB6aWcud29yZC5jb3VudCAlPiUKICBzZWxlY3QoLVNpemUpICU+JQogIHJlbmFtZShgU2l6ZSAoaW4gd29yZC10b2tlbnMpYD0gU2l6ZV9wcmludCwKICAgICAgICAgYENvcnB1cyBmaWxlc2AgPSBDb3JwdXMpICU+JQogIGFzLmRhdGEuZnJhbWUoKSAlPiUKICBrbml0cjo6a2FibGUocm93Lm5hbWVzID0gVFJVRSwgY2FwdGlvbiA9ICJJbmRvbmVzaWFuIExlaXB6aWcgQ29ycG9yYSBhbmQgdGhlaXIgc2l6ZXMiKQpgYGAKCkluIHRvdGFsLCB0aGUgdGhpcnRlZW4gY29ycHVzIGZpbGVzIGFtb3VudCB0byBgciBwcmV0dHlOdW0oc3VtKGxlaXB6aWcud29yZC5jb3VudCRTaXplKSwgYmlnLm1hcmsgPSAiLCIpYCBtaWxsaW9uIHdvcmQtdG9rZW5zLgoKIyMgVGhlIHN0dWRpZWQgZGVub21pbmFsIHZlcmJzCgpUaGUgZGF0YWJhc2UgZm9yIHRoZSBzdHVkaWVkIHZlcmJzIGlzIGF2YWlsYWJsZSBpbiB0aGUgYC5yZHNgLCBgLmNzdmAsIGFuZCBgLnR4dGAgdGFiLWRlbGltaXRlZCBmaWxlcyBuYW1lZCBgIm1lX3BhcnNlZF9ub3VudGFnZ2VkYmFzZSJgLiBUaGUgdmVyYnMgaGF2ZSBiZWVuIHBhcnNlZCBhbmQgdGFnZ2VkIHVzaW5nICpNb3JwaEluZCogW0BsYXJhc2F0aV9pbmRvbmVzaWFuXzIwMTFdLiBXZSBsaW1pdGVkIHRoZSBzdHVkeSBvbiB0aGUgdmVyYnMgd2l0aCBub3VuLXRhZ2dlZCByb290cyB0aGF0IG9jY3VyIG92ZXIgMjAgdG9rZW5zLiBGb3IgZWFjaCByb290LCBhbGwgdGhlIHZlcmIgZm9ybXMgbXVzdCBvY2N1ciBpbiB0aGUgdGhyZWUgbW9ycGhvbG9naWNhbCBzY2hlbWFzLCBuYW1lbHkgKm1lTiotLCAqbWVOKi0vLSprYW4qLCBhbmQgKm1lTiotLy0qaSouIEZvciBpbnN0YW5jZSwgd2UgdGFrZSBfKiptZW4qKmRhc2FyXyAndG8gYmUgYmFzaWMnLCBfKiptZW4qKmRhc2FyKippKipfICd0byB1bmRlcmxpZSBzdGguJywgYW5kIF8qKm1lbioqZGFzYXIqKmthbioqXyAndG8gYmFzZSBzdGguIG9uJyB0aGF0IGFyZSBhbGwgZGVyaXZlZCBmcm9tIHRoZSBub21pbmFsIHJvb3QgKmRhc2FyKiAnYmFzZTsgZm91bmRhdGlvbicuIAoKVGhlIGZvbGxvd2luZyBjb2RlcyBzaG93IHRoZSBmaWx0ZXJpbmcgcHJvY2Vzc2VzIHRvIHJldHJpZXZlIHRoZSByZWxldmFudCB2ZXJicyBhbmQgW1RhYmxlIFxAcmVmKHRhYjpzdHVkaWVkLXZlcmJzLXJldHJpZXZhbCldKCNzdHVkaWVkLXZlcmJzLXJldHJpZXZhbCkgc2hvd3MgdGhlIHNuaXBwZXQgb2YgdGhlIGRhdGFiYXNlLgoKYGBge3Igc3R1ZGllZC12ZXJicy1yZXRyaWV2YWx9CiMgbG9hZCB0aGUgZGF0YWJhc2UKcGFyc2VkX21lX25vdW4gPC0gcmVhZFJEUygiZGF0YS9tZV9wYXJzZWRfbm91bnRhZ2dlZGJhc2UucmRzIikKCiMgZmlsdGVyaW5nIHBhcmFtZXRlcnMKbWluX2ZyZXEgPC0gMjAgIyBmcmVxLiB0aHJlc2hvbGQKYmFzZV90eXBlIDwtICJub3VuIiAjIHJvb3QgY2F0ZWdvcnkKCiMgZmlsdGVyaW5nIHByb2Nlc3MKZGZfbm91biA8LSBwYXJzZWRfbWVfbm91biAlPiUgCiAgZmlsdGVyKG4gPiBtaW5fZnJlcSkgJT4lICMgcmV0cmlldmUgb25seSB2ZXJicyBvY2N1cnJpbmcgb3ZlciAyMCB0b2tlbnMKICBncm91cF9ieShiYXNlKSAlPiUgCiAgbXV0YXRlKG5fYWZmaXhfbmV3ID0gbl9kaXN0aW5jdChhZmZpeCkpICU+JSAKICBmaWx0ZXIobl9hZmZpeF9uZXcgPT0gMykgJT4lICMgbWFrZSBzdXJlIGVhY2ggcm9vdCBvY2N1cnMgaW4gdGhlIDMgc2NoZW1hcwogIHVuZ3JvdXAoKQoKIyByZXRyaWV2ZSB0aGUgdGFyZ2V0LXdvcmQgY2hhcmFjdGVyIHZlY3RvcnMKbWVfd29yZHMgPC0gZGZfbm91biR3b3JkIAoKCiMgcHJpbnQgdGhlIGRhdGFiYXNlIHNuaXBwZXQKZGZfbm91biAlPiUKICBzZWxlY3QoLW5fYWZmaXhfbmV3KSAlPiUgCiAgZmlsdGVyKGJhc2UgJWluJSBjKCJkYXNhciIpKSAlPiUgCiAgcmVuYW1lKGJhc2VfcG9zID0gYmFzZS5wb3MsCiAgICAgICAgIHRva2VuX2ZyZXEgPSBuKSAlPiUgCiAgbXV0YXRlKHdvcmQgPSBwYXN0ZSgiKiIsIHdvcmQsICIqIiwgc2VwID0gIiIpLAogICAgICAgICBiYXNlID0gcGFzdGUoIioiLCBiYXNlLCAiKiIsIHNlcCA9ICIiKSwKICAgICAgICAgYWZmaXggPSBwYXN0ZSgiKiIsIGFmZml4LCAiKiIsIHNlcCA9ICIiKSwKICAgICAgICAgbW9ycGhpbmQgPSBnc3ViKCIoPHw+KSIsICJcXFxcXFwxIiwgbW9ycGhpbmQsIHBlcmwgPSBUUlVFKSkgJT4lIAogIGtuaXRyOjprYWJsZShjYXB0aW9uID0gIlNuaXBwZXQgb2YgdGhlIGFuYWx5c2VkIGRlbm9taW5hbCB2ZXJicyIpCmBgYAoKSW4gdG90YWwsIHdlIGFuYWx5c2VkIGByIGxlbmd0aChtZV93b3JkcylgIGRlbm9taW5hbCB2ZXJicyBiYXNlZCBvbiBgciBsZW5ndGgodW5pcXVlKGRmX25vdW4kYmFzZSkpYCByb290IHR5cGVzIG9jY3VycmluZyBpbiB0aHJlZSBtb3JwaG9sb2dpY2FsIHNjaGVtYXMuCgpXZSBtZW50aW9uIGluIHRoZSBwYXBlciBhYm91dCBjaGVja2luZyB0aGUgZXhpc3RlbmNlIG9mIHRoZSBzdHVkaWVkIHZlcmJzIHdpdGggKk1BTElORE8gTW9ycGgqLCBhIG1vcnBob2xvZ2ljYWwgZGljdGlvbmFyeSBmb3IgSW5kb25lc2lhbiBhbmQgTWFsYXkgW0Bub21vdG9fbWFsaW5kb18yMDE4XS4gV2UgY2hlY2tlZCBpdCB3aXRoIHRoZSBsYXRlc3QgdmVyc2lvbiBvZiBNQUxJTkRPIE1vcnBoIGZyb20gdGhlIGZpbGUgbmFtZWQgYCJtYWxpbmRvX2RpY18yMDE4MTEyNS50c3YiYCB0aGF0IGhhcyBiZWVuIHNhdmVkIGFzIGAibWFsaW5kb19kYmFzZS5yZHMiYCAoYW4gUiB0eXBlIG9mIGRhdGEpIGFuZCB0YWItZGVsaW1pdGVkIGAuY3N2YCBmaWxlIChgIm1hbGluZG9fZGJhc2UuY3N2ImApLiBUaGUgZm9sbG93aW5nIGNvZGVzIGRvY3VtZW50IHRoZSBjaGVja2luZyBwcm9jZXNzZXMuIFRoZSBwcmludGVkIHZlcmJzIGFyZSB0aG9zZSBhYnNlbnQgZnJvbSAqTUFMSU5ETyBNb3JwaCogYnV0IGF2YWlsYWJsZSBpbiBvdXIgY29ycHVzIG9jY3VycmluZyBvdmVyIDIwIHRva2VucyBvdmVyYWxsLgoKYGBge3IgbWFsaW5kby1jaGVja30KIyBsb2FkIE1BTElORE8gRGljdGlvbmFyeSBkYXRhCm1hbGluZG8gPC0gcmVhZFJEUygiZGF0YS9tYWxpbmRvX2RiYXNlLnJkcyIpCgojIHByaW50IHRoZSB2ZXJicyB0aGF0IGFyZSBhdmFpbGFibGUgaW4gdGhlIGRhdGFzZXQgYnV0IGFic2VudCBpbiBNQUxJTkRPCihhYnNlbnRfaW5fbWFsaW5kbyA8LSBzZXRkaWZmKG1lX3dvcmRzLCBtYWxpbmRvJHdvcmRfZm9ybSkpCmBgYAoKQXMgKk1BTElORE8gTW9ycGgqIGlzIGFsc28gYmFzZWQgb24gdGhlIExlaXB6aWcgQ29ycG9yYSwgaXQgb25seSB0YWtlcyBpbnRvIGFjY291bnQgd29yZHMgb2NjdXJyaW5nIG92ZXIgdGVuIHRva2VucyBpbiBhbGwgdGhlIDMwMEstc2VudGVuY2VzIHZlcnNpb24gb2YgdGhlIGNvcnB1cyBbQG5vbW90b19tYWxpbmRvXzIwMThdLiBPdXIgZnJlcXVlbmN5IGNoZWNrIG9mIHRoZXNlIGFic2VudCB2ZXJicyBjb25maXJtcyB0aGF0IHRoZXkgYWxsIG9jY3VyIGxlc3MgdGhhbiB0ZW4gdG9rZW5zIGluIHRoZSAzMDBLLXNlbnRlbmNlIGZpbGVzIHRoYXQgd2UgdXNlLiBUaGUgZm9sbG93aW5nIGNvZGVzIHNob3cgdGhlc2UgaW5mb3JtYXRpb24uCgpgYGB7ciBtYWxpbmRvLWZyZXEtY2hlY2ssIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQojIGxvYWQgdGhlIGZyZXFsaXN0IHBlciBjb3JwdXMgYW5kIAojIGNoZWNrIGZyZXEuIG9mIHdvcmRzIGFic2VudCBpbiBNQUxJTkRPIDMwMEsgY29ycHVzCmRmX2FsbF9wcmVmIDwtIHJlYWRfdHN2KCJkYXRhL3dvcmRsaXN0X2xlaXB6aWdfTUVfRElfVEVSX3BlcmNvcnB1cy50c3YiLCBwcm9ncmVzcyA9IEZBTFNFKQpkZl9hbGxfcHJlZiAlPiUgCiAgZmlsdGVyKHdvcmQgJWluJSBhYnNlbnRfaW5fbWFsaW5kbywKICAgICAgICAgZ3JlcGwoIjMwMEsiLCBjb3JwdXMsIHBlcmwgPSBUUlVFKSkgJT4lIAogIG11dGF0ZSh3b3JkID0gcGFzdGUoIioiLCB3b3JkLCAiKiIsIHNlcCA9ICIiKSkgJT4lIAogIGFycmFuZ2Uod29yZCwgY29ycHVzKSAlPiUgCiAga25pdHI6OmthYmxlKHJvdy5uYW1lcyA9IFRSVUUsIGNhcHRpb24gPSAnVG9rZW4gZnJlcXVlbmN5IG9mIHRoZSBhYnNlbnQgdmVyYnMgaW4gdGhlIDMwMEstc2VudGVuY2UgZmlsZXMnKQpgYGAKCiMjIExvYWQgdGhlIHZlY3RvciBzcGFjZSBtb2RlbHMgZm9yIHRoZSBJbmRvbmVzaWFuIExlaXB6aWcgQ29ycG9yYQoKRGV0YWlsZWQgaW5mb3JtYXRpb24gY29uY2VybmluZyB0aGUgdHJhaW5pbmcgcGFyYW1ldGVycyBpcyBhdmFpbGFibGUgaW4gb3VyIHBhcGVyLiBJbiBzaG9ydCwgd2UgdHJhaW5lZCB0aGUgTGVpcHppZyBDb3Jwb3JhIG9uIHRoZSBbKk1vbkFSQ0ggSFBDKl0oaHR0cHM6Ly9jb25mbHVlbmNlLmFwcHMubW9uYXNoLmVkdS9kaXNwbGF5L21vbmFyY2gvTW9uQVJDSCtIb21lKSB1c2luZyB0aGUgKnNraXAtZ3JhbSogbGVhcm5pbmcgYWxnb3JpdGhtIGZyb20gdGhlICp3b3JkMnZlYyogbW9kZWwgW0BtaWtvbG92X2VmZmljaWVudF8yMDEzOyBAbWlrb2xvdl9kaXN0cmlidXRlZF8yMDEzOyBAbWlrb2xvdl9saW5ndWlzdGljXzIwMTNdIHZpYSB0aGUgd29yZFZlY3RvcnMgUiBwYWNrYWdlIFtAc2NobWlkdF93b3JkdmVjdG9yc18yMDE3XS4gVGhlIG91dHB1dCBtb2RlbCBpcyBhdmFpbGFibGUgYXMgLmJpbiBmaWxlIG5hbWVkIGAibGVpcHppZ193MnZfdmVjdG9yX2Z1bGwuYmluImAuIFRoZSBmb2xsb3dpbmcgY29kZXMgc2hvdyBob3cgdGhlIG1vZGVsIGlzIGxvYWRlZCBpbnRvIFIgdXNpbmcgYHJlYWQuYmluYXJ5LnZlY3RvcnMoKWAgZnJvbSB3b3JkVmVjdG9ycyBwYWNrYWdlLgoKYGBge3IgbG9hZC1tb2RlbC1zaG93LCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgZXJyb3IgPSBGQUxTRSwgaW5jbHVkZSA9IFRSVUUsIGV2YWwgPSBGQUxTRX0KdnNtIDwtIHJlYWQuYmluYXJ5LnZlY3RvcnMoImRhdGEvbGVpcHppZ193MnZfdmVjdG9yX2Z1bGwuYmluIikKYGBgCgoKYGBge3IgbG9hZC1tb2RlbC1ldmFsLCBpbmNsdWRlID0gRkFMU0V9CnZzbSA8LSByZWFkLmJpbmFyeS52ZWN0b3JzKCJkYXRhL2xlaXB6aWdfdzJ2X3ZlY3Rvcl9mdWxsLmJpbiIpCmBgYAoKClRvIHJldHJpZXZlIHRoZSB2ZWN0b3Igc3BhY2UgbW9kZWwgKFZTTSkgb2YgdGhlIHRhcmdldCBkZW5vbWluYWwgdmVyYnMsIHVzZSB0aGUgZm9sbG93aW5nIGNvZGVzLgoKYGBge3IgdnNtLWRlbm9taW5hbH0KIyBnZXQgdGhlIFZTTSBmb3IgdGhlIHN0dWRpZWQgZGVub21pbmFsIHZlcmJzCnZzbV90Z3QgPC0gdnNtW3Jvd25hbWVzKHZzbSkgJWluJSBtZV93b3JkcywgXSAKCiMgcHJpbnQgdGhlIHN1YnNldCBvZiB0aGUgbW9kZWwKdnNtX3RndCAKYGBgCgojIFJlc3VsdHMgYW5kIGRpc2N1c3Npb24KClRoZSBmb2xsb3dpbmcgY29kZXMgcnVuIHRoZSBfSGllcmFyY2hpY2FsIEFnZ2xvbWVyYXRpdmUgQW5hbHlzaXNfIChIQUMpIG9uIHRoZSB0YXJnZXQgdmVyYnMgdmVjdG9yIHNwYWNlIG1vZGVsIGFzIHdlbGwgYXMgdGhlIF9BdmVyYWdlIFNpbGhvdWV0dGUgV2lkdGhfIChBU1cpIHN0YXRpc3RpY3MuCgpgYGB7ciBoYWMtYW5hbHlzaXN9CiMgQSB3cmFwcGVyIGZ1bmN0aW9uIGZvciBIQ0EgYW5kIEFTVyBjb21wdXRhdGlvbnMgYW5kIGdhdGhlcmluZyB0aGUgcmVsZXZhbnQgcmVzdWx0cwpzdnNfaGNhIDwtIGZ1bmN0aW9uKHZlY3QgPSBOVUxMLCAKICAgICAgICAgICAgICAgICAgICBjbHVzdF9tZXRob2QgPSBjKCJjb21wbGV0ZSIsICJ3YXJkLkQiLCAid2FyZC5EMiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInNpbmdsZSIsICJhdmVyYWdlIiwgIm1jcXVpdHR5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibWVkaWFuIiwgImNlbnRyb2lkIikpIHsKICAKICAjIDEgY29zaW5lIGRpc3RhbmNlIHVzaW5nIGZ1bmN0aW9uIGZyb20gYHdvcmRWZWN0b3JzYAogIGNvc2Rpc3QgPC0gd29yZFZlY3RvcnM6OmNvc2luZURpc3QodmVjdCwgdmVjdCkKICBjb3NkaXN0IDwtIGFzLmRpc3QoY29zZGlzdCkKICAKICAjIDIgSGllcmFyY2hpY2FsIENsdXN0ZXIgQW5hbHlzaXMKICBoY2EgPC0gaGNsdXN0KGNvc2Rpc3QsIG1ldGhvZCA9IGNsdXN0X21ldGhvZCkKICAKICAjIDMgQ29tcHV0ZSB0aGUgJ2F2ZXJhZ2Ugc2lsaG91ZXR0ZSB3aWR0aCcgKEFTVykgCiAgIyAgIHVzaW5nIHRoZSAnY3V0cmVlJyBmdW5jdGlvbiBmb3IgSENBIHBhcnRpdGlvbmluZwogIGFzd19mIDwtIGZ1bmN0aW9uKHgpIHsKICAgIHN1bW1hcnkoY2x1c3Rlcjo6c2lsaG91ZXR0ZShzdGF0czo6Y3V0cmVlKGhjYSwgayA9IHgpLCBjb3NkaXN0KSkkYXZnLndpZHRoCiAgfQogIGFzd19jdXRyZWUgPC0gc2FwcGx5KDI6KGRpbSh2ZWN0KVsxXSAtIDEpLCBhc3dfZikKICBuYW1lcyhhc3dfY3V0cmVlKSA8LSAyOihkaW0odmVjdClbMV0gLSAxKQogIAogICMgMy4yIGdldCB0aGUgY2x1c3RlciBudW1iZXIgd2l0aCBoaWdoZXN0IEFTVyBzY29yZQogIG5fY2x1c3RlciA8LSBhcy5udW1lcmljKG5hbWVzKGFzd19jdXRyZWVbYXN3X2N1dHJlZSA9PSBtYXgoYXN3X2N1dHJlZSldKSkKICBtYXhfYXN3IDwtIGFzd19jdXRyZWVbYXN3X2N1dHJlZSA9PSBtYXgoYXN3X2N1dHJlZSldCiAgCiAgIyA0IFB1dCB0aGUgcmVzdWx0cyBpbnRvIGEgbGlzdAogIHJlcyA8LSBsaXN0KGNvc2Rpc3QsIGhjYSwgbl9jbHVzdGVyLCBtYXhfYXN3LCBhc3dfY3V0cmVlKQogIG5hbWVzKHJlcykgPC0gYygiY29zaW5lX2Rpc3QiLCAiaGNsdXN0ZXIiLCAibl9jbHVzdGVyIiwgImFzdyIsICJhc3dfYWxsIikKICByZXR1cm4ocmVzKQp9CgojIEhpZXJhcmNoaWNhbCBBZ2dsb21lcmF0aXZlIENsdXN0ZXIgKEhBQykgYW5hbHlzaXMgZm9yIHRoZSBkZW5vbWluYWwgdmVyYnMKY2x1c3RfbWV0aG9kIDwtICJ3YXJkLkQyIgpoY2FfcmVzIDwtIHN2c19oY2EodmVjdCA9IHZzbV90Z3QsCiAgICAgICAgICAgICAgICAgICBjbHVzdF9tZXRob2QgPSBjbHVzdF9tZXRob2QpCmBgYAoKVGhlIGZvbGxvd2luZyBjb2RlcyBnZW5lcmF0ZSB0aGUgcGxvdCBmb3IgdGhlIEFTVyBzY29yZXMgaW4gdGhlIHBhcGVyLgoKYGBge3IgaGNhLWFzdy1wbG90LCBmaWcuYXNwID0gLjksIGZpZy53aWR0aCA9IDYuMjUsIGZpZy5jYXAgPSAiQXZlcmFnZSBTaWxob3VldHRlIFdpZHRocyBmb3IgdGhlIHRlc3RlZCBjbHVzdGVyIHNvbHV0aW9ucy4ifQoKIyBwcmVwYXJpbmcgZGF0YSBmcmFtZSBmb3IgdGhlIEFTVyBhbmQgdGVzdGVkIGNsdXN0ZXJzCmFzd19kZiA8LSBoY2FfcmVzJGFzd19hbGwKYXN3X2RmIDwtIHRpYmJsZTo6dGliYmxlKHRlc3RlZF9jbHVzdGVyID0gbmFtZXMoYXN3X2RmKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGFzdyA9IHVubmFtZShhc3dfZGYpKQphc3dfZGZfc29ydCA8LSBkcGx5cjo6YXJyYW5nZShhc3dfZGYsIGRwbHlyOjpkZXNjKGFzdykpCgojIHBsb3Qgd2l0aCBnZ3Bsb3QyCmFzd19kZl9zb3J0ICU+JSAKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKHRlc3RlZF9jbHVzdGVyLCBhc3cpLCB5ID0gYXN3LCBncm91cCA9IDEpKSArCiAgZ2VvbV9zdGVwKCkgKwogIHlsaW0oYygwLCAxKSkgKwogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWVfbGlnaHQoKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKGFzdywgMykpLCBoanVzdCA9IC0wLjIsIHNpemUgPSAyLjUpICsKICBsYWJzKHggPSAiTnVtYmVyIG9mIHRlc3RlZCBjbHVzdGVyIHNvbHV0aW9ucyIsCiAgICAgICB5ID0gIkF2ZXJhZ2UgU2lsaG91ZXR0ZSBXaWR0aCAoQVNXKSIsCiAgICAgICBjYXB0aW9uID0gcGFzdGUoIlRoZSB0ZXN0ZWQgY2x1c3RlciBzb2x1dGlvbiByYW5nZXMgZnJvbSAyIHRvICIsIAogICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aChtZV93b3JkcykgLSAxLCAKICAgICAgICAgICAgICAgICAgICAgICAiIChpLmUuLCB0aGUgbGVuZ3RoIG9mIHRoZSBhbmFseXNlZCB3b3JkcyAoIiwgCiAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoKG1lX3dvcmRzKSwgIikgLSAxKS5cblRoZSBoaWdoZXN0IEFTVyBvZiAiLCAKICAgICAgICAgICAgICAgICAgICAgICByb3VuZChoY2FfcmVzJGFzdywgMyksIAogICAgICAgICAgICAgICAgICAgICAgICIgaXMgZm9yICIsIGhjYV9yZXMkbl9jbHVzdGVyLCAKICAgICAgICAgICAgICAgICAgICAgICAiLWNsdXN0ZXIgc29sdXRpb24iLCAKICAgICAgICAgICAgICAgICAgICAgICBzZXAgPSAiIikpCgpgYGAKClRoZSBkZW5kcm9ncmFtIHRyZWUgaXMgZ2VuZXJhdGVkIHVzaW5nIHRoZSBmb2xsb3dpbmcgY29kZXM6CgpgYGB7ciBoY2EtcGxvdCwgZmlnLmFzcCA9IDEuMywgZmlnLmNhcCA9ICJDbHVzdGVyIGRlbmRyb2dyYW0gZm9yIHRoZSBzdHVkaWVkIGRlbm9taW5hbCB2ZXJicyBiYXNlZCBvbiAqSGllcmFyY2hpY2FsIEFnZ2xvbWVyYXRpdmUgQ2x1c3RlcmluZyogKERpc3RhbmNlIG1lYXN1cmUgPSAqQ29zaW5lIERpc3RhbmNlKjsgQ2x1c3RlcmluZyBtZXRob2QgPSAqV2FyZC5EMiopOyBUaGUgMjEtY2x1c3RlciBzb2x1dGlvbiBpcyBiYXNlZCBvbiB0aGUgaGlnaGVzdCBBU1cgc2NvcmUgb2YgMC4zMDQgYW5kIGlzIGluZGljYXRlZCBieSB0aGUgcmVkIGJveGVzLiJ9Cm9wYXIgPC0gcGFyKG5vLnJlYWRvbmx5ID0gVFJVRSkKcGFyKG1hciA9IGMoMiwgMiwgMiwgMTApKQpkZW5kIDwtIGFzLmRlbmRyb2dyYW0oaGNhX3JlcyRoY2x1c3RlcikKZGVuZCA8LSBkZW5kZXh0ZW5kOjpzZXQoZGVuZCA9IGRlbmQsICJsYWJlbHNfY2V4IiwgLjkpCnBsb3QoZGVuZCwgaG9yaXogPSBUUlVFKQpkZW5kZXh0ZW5kOjpyZWN0LmRlbmRyb2dyYW0oZGVuZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsgPSBoY2FfcmVzJG5fY2x1c3RlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvcml6ID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvcmRlciA9IDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsd2QgPSAwLjM1KQpwYXIob3BhcikKYGBgCgpgYGB7ciBnZXQtd29yZC1mcmVxdWVuY3l9CiMgQSBmdW5jdGlvbiB0byByZXRyaWV2ZSB0aGUgdG9rZW4gZnJlcXVlbmN5IG9mIHRoZSBzdHVkaWVkIHZlcmJzCndmcmVxIDwtIGZ1bmN0aW9uKGRmID0gZGZfbm91biwgdywgZm9ybWF0dGVkID0gVFJVRSkgewogIGZyZXEgPC0gZHBseXI6OnB1bGwoZHBseXI6OmZpbHRlcihkZiwgd29yZCA9PSB3KSwgbikKICBpZiAoZm9ybWF0dGVkKSB7CiAgICBmcmVxIDwtIGZvcm1hdChmcmVxLCBiaWcubWFyayA9ICIsIikKICB9IAogIHJldHVybihmcmVxKQp9CmBgYAoKCiMjIFNlbWFudGljIGNsdXN0ZXIgeyNzZW1jbHVzdH0KClRoZSBzdWJjbHVzdGVyIG9mIHRoZSA8c3BhbiBzdHlsZSA9ICJmb250LXZhcmlhbnQ6c21hbGwtY2FwczsiPm1vdGlvbjwvc3Bhbj4gdmVyYnMgaXMgZXh0cmFjdGVkIHVzaW5nIHRoZSBmb2xsb3dpbmcgY29kZXM6CgpgYGB7ciBzdWJjbHVzdC1tb3Rpb24sIGZpZy5jYXAgPSAnQ2x1c3RlciBmb3IgdGhlIDxzcGFuIHN0eWxlID0gImZvbnQtdmFyaWFudDpzbWFsbC1jYXBzOyI+bW90aW9uPC9zcGFuPiB2ZXJicyd9CmNsdXN0ZXJzIDwtIGRlbmRleHRlbmQ6OmN1dHJlZShoY2FfcmVzJGhjbHVzdGVyLCBrID0gaGNhX3JlcyRuX2NsdXN0ZXIpCm9wYXIgPC0gcGFyKG5vLnJlYWRvbmx5ID0gVFJVRSkKcGFyKG1hciA9IGMoMiwgMiwgMiwgNykpCmRlbmQgPC0gYXMuZGVuZHJvZ3JhbShoY2FfcmVzJGhjbHVzdGVyKQp0b19wcnVuZSA8LSBuYW1lcyhjbHVzdGVyc1shbmFtZXMoY2x1c3RlcnMpICVpbiUgYygibWVsYW5na2Foa2FuIiwgIm1lbGFuZ2thaCIsICJtZW5hcGFrIiwgIm1lbmFwYWtpIiwgIm1lbmFwYWtrYW4iLCAibWVuamVqYWtrYW4iLCAibWVuamVqYWsiLCAibWVuamVqYWtpIildKQpwbG90KGRlbmRleHRlbmQ6OnBydW5lKGRlbmQsIHRvX3BydW5lKSwgaG9yaXogPSBUUlVFKQpwYXIob3BhcikKYGBgCgpJbiB0aGlzIHNlY3Rpb24sIHdlIHByZXNlbnQgdGhyZWUgdGFibGVzIGZvciBuLWdyYW1zIGRhdGEgb2YgdmVyYnMgd2l0aCB0aGUgcm9vdCAqdGFwYWsqICdzb2xlIG9mIHRoZSBmb290Jy4gVGhlIGRhdGEgY2FuIGJlIGxvYWRlZCBhcyBmb2xsb3dzOgoKYGBge3IgdGFwYWstZ3JhbSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9CnRhcGFrIDwtIHJlYWRyOjpyZWFkX3RzdigiZGF0YS9uZ3JhbWV4YW1wbF8zZ3JfbWVuYXBhay50eHQiKQp0YXBha2kgPC0gcmVhZHI6OnJlYWRfdHN2KCJkYXRhL25ncmFtZXhhbXBsXzNncl9tZW5hcGFraS50eHQiKQp0YXBha2thbiA8LSByZWFkcjo6cmVhZF90c3YoImRhdGEvbmdyYW1leGFtcGxfM2dyX21lbmFwYWtrYW4udHh0IikKYGBgCgpUaGUgZm9sbG93aW5nIGNvZGVzIGdlbmVyYXRlIHRoZSB0ZW4gbW9zdCBmcmVxdWVudCByaWdodC1zaWRlIDMtZ3JhbSBmb3IgKm1lbmFwYWsqLgoKYGBge3IgdGFwYWstZ3JhbS10YWJsZX0KdGFwYWtnciA8LSB0YXBhayAlPiUKICBmaWx0ZXIodzEgPT0gIm1lbmFwYWsiKSAlPiUgCiAgY291bnQobmdyYW1zLCBzb3J0ID0gVFJVRSkgJT4lIAogIC5bMToxMCwgXSAlPiUgCiAgbXV0YXRlKG5ncmFtcyA9IHBhc3RlKCIqIiwgbmdyYW1zLCAiKiIsIHNlcCA9ICIiKSkgIyBtYWtlIG5ncmFtcyBpdGFsaWNzCmtuaXRyOjprYWJsZSh0YXBha2dyLCBjYXB0aW9uID0gIlRoZSB0ZW4gbW9zdCBmcmVxdWVudCAzLWdyYW0gZm9yICptZW5hcGFrKiIsIHJvdy5uYW1lcyA9IFRSVUUpCmBgYAoKKk1lbmFwYWsqIGNhbiBiZSB1c2VkIGFzIHRyYW5zaXRpdmUgKGl0ZW0gMSwgNSwgYW5kIDcpIGFuZCBpbnRyYW5zaXRpdmUgdmVyYnMgKHRoZSByZW1haW5pbmcgaXRlbXMgaW4gW1RhYmxlIFxAcmVmKHRhYjp0YXBhay1ncmFtLXRhYmxlKV0oI3RhcGFrLWdyYW0tdGFibGUpKS4gSXRzIHRyYW5zaXRpdmUgdXNhZ2Ugc2hhcmVzIHNpbWlsYXIgcmlnaHQtc2lkZSBjb2xsb2NhdGlvbiBwYXR0ZXJucyB3aXRoIHRoZSAqTWVOKi0vLSppKiBmb3JtICptZW5hcGFraSosIGVzcGVjaWFsbHkgdGhlaXIgZGlyZWN0IG9iamVjdCB3aXRoICptYXNhIGRlcGFuKiAnZnV0dXJlJyBhbmQgKmthcmlyKiAnY2FyZWVyJyAoW1RhYmxlXEByZWYodGFiOnRhcGFraS1ncmFtLXRhYmxlKSBiZWxvd10oI3RhcGFraS1ncmFtLXRhYmxlKSkuCgpgYGB7ciB0YXBha2ktZ3JhbS10YWJsZX0KdGFwYWtpZ3IgPC0gdGFwYWtpICU+JQogIGZpbHRlcih3MSA9PSAibWVuYXBha2kiKSAlPiUgCiAgY291bnQobmdyYW1zLCBzb3J0ID0gVFJVRSkgJT4lIAogIC5bMToxMCwgXSAlPiUgCiAgbXV0YXRlKG5ncmFtcyA9IHBhc3RlKCIqIiwgbmdyYW1zLCAiKiIsIHNlcCA9ICIiKSkKa25pdHI6OmthYmxlKHRhcGFraWdyLCBjYXB0aW9uID0gIlRoZSB0ZW4gbW9zdCBmcmVxdWVudCAzLWdyYW0gZm9yICptZW5hcGFraSoiLCByb3cubmFtZXMgPSBUUlVFKQpgYGAKClRoaXMgaXMgZGlmZmVyZW50IGZyb20gdGhlIHRyYW5zaXRpdmUgdXNhZ2Ugd2l0aCAqTWVOKi0vLSprYW4qIHNjaGVtYSAoW1RhYmxlIFxAcmVmKHRhYjp0YXBha2thbi1ncmFtLXRhYmxlKSBiZWxvd10oI3RhcGFra2FuLWdyYW0tdGFibGUpKSwgd2hpY2ggcHJlZG9taW5hbnRseSBoYXMgKmtha2kqICdmb290JyBhcyBpdHMgZGlyZWN0IG9iamVjdCwgZm9sbG93ZWQgYnkgZWl0aGVyIGxvY2F0aW9uYWwvZGlyZWN0aW9uYWwgcHJlcG9zaXRpb25hbCBwaHJzZXMgb3IgbW90aW9uIHZlcmIgY29tcGxlbWVudHMgKGUuZy4sICptZW1hc3VraSogJ3RvIGVudGVyJyBbaXRlbSA1XSBhbmQgKm1hanUqICd0byBtb3ZlIGZvcndhcmQnIFtpdGVtIDhdKS4KCmBgYHtyIHRhcGFra2FuLWdyYW0tdGFibGV9CnRhcGFra2FuZ3IgPC0gdGFwYWtrYW4gJT4lCiAgZmlsdGVyKHcxID09ICJtZW5hcGFra2FuIikgJT4lIAogIGNvdW50KG5ncmFtcywgc29ydCA9IFRSVUUpICU+JSAKICAuWzE6MTAsIF0gJT4lIAogIG11dGF0ZShuZ3JhbXMgPSBwYXN0ZSgiKiIsIG5ncmFtcywgIioiLCBzZXAgPSAiIikpCmtuaXRyOjprYWJsZSh0YXBha2thbmdyLCBjYXB0aW9uID0gIlRoZSB0ZW4gbW9zdCBmcmVxdWVudCAzLWdyYW0gZm9yICptZW5hcGFra2FuKiIsIHJvdy5uYW1lcyA9IFRSVUUpCmBgYAoKQ29kZXMgZm9yIGV4dHJhY3RpbmcgdGhlIHN1YnNldCBvZiB0aGUgbWl4dHVyZSBvZiA8c3BhbiBzdHlsZSA9ICJmb250LXZhcmlhbnQ6c21hbGwtY2FwczsiPmNvbW11bmljYXRpb248L3NwYW4+IGFuZCA8c3BhbiBzdHlsZSA9ICJmb250LXZhcmlhbnQ6c21hbGwtY2FwczsiPnBzeWNoPC9zcGFuPiB2ZXJicyBhcmUgYXMgZm9sbG93cy4KCmBgYHtyIHN1YmNsdXN0ZXItcHN5Y2hzLTEsIGZpZy5jYXAgPSAnQ2x1c3RlciBvZiA8c3BhbiBzdHlsZSA9ICJmb250LXZhcmlhbnQ6c21hbGwtY2FwczsiPmNvbW11bmljYXRpb248L3NwYW4+IGFuZCA8c3BhbiBzdHlsZSA9ICJmb250LXZhcmlhbnQ6c21hbGwtY2FwczsiPnBzeWNoPC9zcGFuPiB2ZXJicyAoYSknfQpjbHVzdGVycyA8LSBkZW5kZXh0ZW5kOjpjdXRyZWUoaGNhX3JlcyRoY2x1c3RlciwgayA9IGhjYV9yZXMkbl9jbHVzdGVyKQpvcGFyIDwtIHBhcihuby5yZWFkb25seSA9IFRSVUUpCnBhcihtYXIgPSBjKDIsIDIsIDIsIDcpKQpkZW5kIDwtIGFzLmRlbmRyb2dyYW0oaGNhX3JlcyRoY2x1c3RlcikKdG9fcHJ1bmUgPC0gbmFtZXMoY2x1c3RlcnNbIW5hbWVzKGNsdXN0ZXJzKSAlaW4lIGMoIm1lbWJheWFuZ2thbiIsICJtZW55ZXNhbCIsICJtZW55ZXNhbGkiLCAibWVuZ2F0YWkiKV0pCnBsb3QoZGVuZGV4dGVuZDo6cHJ1bmUoZGVuZCwgdG9fcHJ1bmUpLCBob3JpeiA9IFRSVUUpCnBhcihvcGFyKQpgYGAKClRoZSBhYm92ZSBkZW5kcm9ncmFtIGlzIGZyb20gdGhlIHRvcCBjbHVzdGVyIGluIFtGaWd1cmUgXEByZWYoZmlnOmhjYS1wbG90KV0oI2hjYS1wbG90KSwgY29uc2lzdGluZyBvZiAoaSkgKm1lbnllc2FsKiAndG8gYmUgcmVncmV0ZnVsJyAoTiA9IGByIHdmcmVxKGRmX25vdW4sICJtZW55ZXNhbCIpYCksIChpaSkgKm1lbnllc2FsaSogJ3JlZ3JldCBzdGguJyAoTiA9IGByIHdmcmVxKGRmX25vdW4sICJtZW55ZXNhbGkiKWApLCBhbmQgKGlpaSkgKm1lbWJheWFuZ2thbiogJ2ltYWdpbmU7IHZpc3VhbGlzZScgKE4gPSBgciB3ZnJlcShkZl9ub3VuLCAibWVtYmF5YW5na2FuIilgKS4gVGhlIG90aGVyIHN1YnNldCBvZiA8c3BhbiBzdHlsZSA9ICJmb250LXZhcmlhbnQ6c21hbGwtY2FwczsiPmNvbW11bmljYXRpb248L3NwYW4+IGFuZCA8c3BhbiBzdHlsZSA9ICJmb250LXZhcmlhbnQ6c21hbGwtY2FwczsiPnBzeWNoPC9zcGFuPiB2ZXJicyAoaS5lLiwgKm1lbmdhdGFrYW4qICd0byBzYXkgc3RoLicgKE4gPSBgciB3ZnJlcShkZl9ub3VuLCAibWVuZ2F0YWthbiIpYCksICptZW5jb250b2hrYW4qICd0byBleGVtcGxpZnknIChOID0gYHIgd2ZyZXEoZGZfbm91biwgIm1lbmNvbnRvaGthbiIpYCksIGFuZCAqbWVueWVzYWxrYW4qICdyZWdyZXQgc3RoLicgKE4gPSBgciB3ZnJlcShkZl9ub3VuLCAibWVueWVzYWxrYW4iKWApKSBpcyBleHRyYWN0ZWQgYXMgZm9sbG93cy4KCmBgYHtyIHN1YmNsdXN0ZXItcHN5Y2hzLTIsIGZpZy5jYXAgPSAnQ2x1c3RlciBvZiA8c3BhbiBzdHlsZSA9ICJmb250LXZhcmlhbnQ6c21hbGwtY2FwczsiPmNvbW11bmljYXRpb248L3NwYW4+IGFuZCA8c3BhbiBzdHlsZSA9ICJmb250LXZhcmlhbnQ6c21hbGwtY2FwczsiPnBzeWNoPC9zcGFuPiB2ZXJicyAoYiknfQpjbHVzdGVycyA8LSBkZW5kZXh0ZW5kOjpjdXRyZWUoaGNhX3JlcyRoY2x1c3RlciwgayA9IGhjYV9yZXMkbl9jbHVzdGVyKQpvcGFyIDwtIHBhcihuby5yZWFkb25seSA9IFRSVUUpCnBhcihtYXIgPSBjKDIsIDIsIDIsIDcpKQpkZW5kIDwtIGFzLmRlbmRyb2dyYW0oaGNhX3JlcyRoY2x1c3RlcikKdG9fcHJ1bmUgPC0gbmFtZXMoY2x1c3RlcnNbIW5hbWVzKGNsdXN0ZXJzKSAlaW4lIGMoIm1lbmNvbnRvaGthbiIsICJtZW5nYXRha2FuIiwgIm1lbnllc2Fsa2FuIildKQpwbG90KGRlbmRleHRlbmQ6OnBydW5lKGRlbmQsIHRvX3BydW5lKSwgaG9yaXogPSBUUlVFKQpwYXIob3BhcikKYGBgCgpXaGF0IGludGVyZXN0aW5nIGJldHdlZW4gdmVyYnMgaW4gdGhlc2UgbGFzdCB0d28gY2x1c3RlcnMgaXMgdGhhdCB0aGUgKk1lTiotLy0qaSogKGkuZS4gKm1lbmdhdGFpKikgYW5kICpNZU4qLS8tKmthbiogdmVyYnMgKGkuZS4gKm1lbmdhdGFrYW4qKSB3aXRoIHRoZSByb290ICprYXRhKiAnd29yZCcgYXJlIHdheSBhcGFydCBpbiB0aGUgZGVuZHJvZ3JhbS4gU2ltaWxhciBjYXNlIGlzIGFwcGFyZW50IGJldHdlZW4gKm1lbnllc2Fsa2FuKiBzZXBhcmF0ZWQgd2l0aCAqbWVueWVzYWwqIGFuZCAqbWVueWVzYWxpKiwgd2hlcmUgdGhlIGxhdHRlciB0d28gdmVyYnMgY2x1c3RlciB0b2dldGhlciBhbmQgYXJlIG1lcmdlZCBmaXJzdCBpbiBbRmlndXJlIFxAcmVmKGZpZzpzdWJjbHVzdGVyLXBzeWNocy0xKV0oI3N1YmNsdXN0ZXItcHN5Y2hzLTEpIChzZWUgwqdbXEByZWYoY2x1c3Rlci1zcGxpdCldKCNjbHVzdGVyLXNwbGl0KSBmb3IgZnVydGhlciBkaXNjdXNzaW9uIG9uIHRoaXMgc3BsaXQpLgoKIyMgUm9vdC1iYXNlZCBjbHVzdGVyaW5nIHsjcm9vdC1jbHVzdGVyfQoKVGhpcyBjbHVzdGVyIHR5cGUgY2FwdHVyZXMgZGVub21pbmFsIHZlcmJzIG9mIGEgZ2l2ZW4gcm9vdCB3aXRoIHRoZSB0aHJlZSBkaWZmZXJlbnQgbW9ycGhvbG9naWNhbCBzY2hlbWFzIHRoYXQgY2x1c3RlciB0b2dldGhlciAoW0ZpZ3VyZSBcQHJlZihmaWc6c3ViY2x1c3Rlci1yb290LWJhc2VkKV0oI3N1YmNsdXN0ZXItcm9vdC1iYXNlZCkpLiBXZSBoYXZlIHNlZW4gZmV3IGV4YW1wbGVzIG9mIHRoZXNlIGluIHRoZSA8c3BhbiBzdHlsZSA9ICJmb250LXZhcmlhbnQ6c21hbGwtY2FwczsiPm1vdGlvbjwvc3Bhbj4gY2x1c3RlciB3aXRoIHRoZSByb290ICp0YXBhayogJ3NvbGUgb2YgdGhlIGZvb3QnIGFuZCAqamVqYWsqICdmb290cHJpbnQnLCB0aGUgZGVyaXZlZCBmb3JtcyBvZiB3aGljaCBmYWxsIGludG8gb25lIGNsdXN0ZXIgYnV0IGRpZmZlciBpbiB0ZXJtcyBvZiB0aGVpciB3aXRoaW4tY2x1c3RlciBicmFuY2hpbmcgKFtGaWd1cmUgXEByZWYoZmlnOnN1YmNsdXN0LW1vdGlvbildKCNzdWJjbHVzdC1tb3Rpb24pKS4gVGhlIG90aGVyIGV4YW1wbGVzIGFyZSBiYXNlZCBvbiB0aGUgZm9sbG93aW5nIHJvb3RzOgoKYS4gKnN1c3UqICdtaWxrJyAtPiAqbWVueXVzdSogJyhvZiBhIGJhYnkveW91bmcgYW5pbWFsKSB0byBzdWNrbGUnIChOID0gYHIgd2ZyZXEoZGZfbm91biwgIm1lbnl1c3UiKWApOyAqbWVueXVzdWkqICd0byBicmVhc3QtZmVlZCBzYi4nIChOID0gYHIgd2ZyZXEoZGZfbm91biwgIm1lbnl1c3VpIilgKTsgKm1lbnl1c3VrYW4qICd0byBsZXQgc2IuIHN1Y2tsZTsgdG8gYnJlYXN0LWZlZWQgc2IuJyAoTiA9IGByIHdmcmVxKGRmX25vdW4sICJtZW55dXN1a2FuIilgKQpiLiAqZGFzYXIqICdiYXNlJyAtPiAqbWVuZGFzYXIqICdiYXNpYzsgZm91bmRhdGlvbmFsJyAoTiA9IGByIHdmcmVxKGRmX25vdW4sICJtZW5kYXNhciIpYCk7ICptZW5kYXNhcmkqICd0byB1bmRlcmxpZSBzdGguJyAoTiA9IGByIHdmcmVxKGRmX25vdW4sICJtZW5kYXNhcmkiKWApOyAqbWVuZGFzYXJrYW4qICd0byBiYXNlIFggKG9uIFkpJyAoTiA9IGByIHdmcmVxKGRmX25vdW4sICJtZW5kYXNhcmthbiIpYCkKYy4gKnRlbXBhdCogJ3BsYWNlOyBsb2NhdGlvbicgLT4gKm1lbmVtcGF0KiAndG8gcGxhY2UvcG9zaXRpb24gKHN0aC4pIGF0JyAoTiA9IGByIHdmcmVxKGRmX25vdW4sICJtZW5lbXBhdCIpYCk7ICptZW5lbXBhdGkqICd0byBvY2N1cHk7IHRvIHNpdGUgYXQnIChOID0gYHIgd2ZyZXEoZGZfbm91biwgIm1lbmVtcGF0aSIpYCk7ICptZW5lbXBhdGthbiogJ3RvIHB1dC9wbGFjZS9wb3NpdGlvbiBYIGF0IFknIChOID0gYHIgd2ZyZXEoZGZfbm91biwgIm1lbmVtcGF0a2FuIilgKQpkLiAqd2FraWwqICd2aWNlOyByZXByZXNlbnRhdGl2ZTsgZGVwdXR5JyAtPiAqbWV3YWtpbCogJ3RvIChiZSBhKSByZXByZXNlbnQoYXRpdmUgb2YpIFgnIChOID0gYHIgd2ZyZXEoZGZfbm91biwgIm1ld2FraWwiKWApOyAqbWV3YWtpbGkqICd0byAoYmUgYSkgcmVwcmVzZW50KGF0aXZlIG9mKSBYJyAoTiA9IGByIHdmcmVxKGRmX25vdW4sICJtZXdha2lsaSIpYCk7ICptZXdha2lsa2FuKiAndG8gYXNzaWduIHNiLiBhcyBhIHJlcHJlc2VudGF0aXZlJyAoTiA9IGByIHdmcmVxKGRmX25vdW4sICJtZXdha2lsa2FuIilgKSAKClRoZSBjbHVzdGVyIHN1YnNldHMgb2YgdGhlc2UgdmVyYnMgYXJlIGV4dHJhY3RlZCBmcm9tIFtGaWd1cmUgXEByZWYoZmlnOmhjYS1wbG90KV0oI2hjYS1wbG90KSBpbnRvIFtGaWd1cmUgXEByZWYoZmlnOnN1YmNsdXN0ZXItcm9vdC1iYXNlZCldKCNzdWJjbHVzdGVyLXJvb3QtYmFzZWQpIHdpdGggdGhlIGNvZGVzIGJlbG93LgoKYGBge3Igc3ViY2x1c3Rlci1yb290LWJhc2VkLCBmaWcuY2FwID0gJ1Jvb3QtYmFzZWQgY2x1c3RlcmVkIGRlbm9taW5hbCB2ZXJicyd9CmNsdXN0ZXJzIDwtIGRlbmRleHRlbmQ6OmN1dHJlZShoY2FfcmVzJGhjbHVzdGVyLCBrID0gaGNhX3JlcyRuX2NsdXN0ZXIpCm9wYXIgPC0gcGFyKG5vLnJlYWRvbmx5ID0gVFJVRSkKcGFyKG1hciA9IGMoMiwgMiwgMiwgNykpCmRlbmQgPC0gYXMuZGVuZHJvZ3JhbShoY2FfcmVzJGhjbHVzdGVyKQp0b19wcnVuZSA8LSBuYW1lcyhjbHVzdGVyc1shbmFtZXMoY2x1c3RlcnMpICVpbiUgYygibWV3YWtpbGkiLCAibWV3YWtpbGthbiIsICJtZXdha2lsIiwgIm1lbnl1c3UiLCAibWVueXVzdWkiLCAibWVueXVzdWthbiIsICJtZW5lbXBhdGkiLCAibWVuZW1wYXRrYW4iLCAibWVuZW1wYXQiLCAibWVuZGFzYXJpIiwgIm1lbmRhc2Fya2FuIiwgIm1lbmRhc2FyIildKQpwbG90KGRlbmRleHRlbmQ6OnBydW5lKGRlbmQsIHRvX3BydW5lKSwgaG9yaXogPSBUUlVFKQpkZW5kZXh0ZW5kOjpyZWN0LmRlbmRyb2dyYW0oZGVuZGV4dGVuZDo6cHJ1bmUoZGVuZCwgdG9fcHJ1bmUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgayA9IDQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob3JpeiA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBib3JkZXIgPSAyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbHdkID0gMC4zNSkKcGFyKG9wYXIpCmBgYAoKSW4gdGhlIHBhcGVyLCB3ZSBwcmVzZW50IG4tZ3JhbXMgZGF0YSBjb250cmFzdGluZyAqbWV3YWtpbGkqIGFuZCAqbWV3YWtpbGthbiogaW4gdGVybXMgb2YgdGhlaXIgcmlkZS1zaWRlIGNvbGxvY2F0ZXMgaW4gdGhlaXIgMy1ncmFtcyBkYXRhLiBGaXJzdCwgdGhlIGNvZGVzIGZvciBnZW5lcmF0aW5nIG4tZ3JhbXMgZm9yICptZXdha2lsaSogJ3RvIChiZSBhKSByZXByZXNlbnQoYXRpdmUgb2YpIFgnIGFyZSBzaG93biBiZWxvdy4KCmBgYHtyIG1ld2FraWxpLWdyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgaW5jbHVkZSA9IFRSVUV9Cm1ld2FraWxpIDwtIHJlYWRyOjpyZWFkX3RzdigiZGF0YS9uZ3JhbWV4YW1wbF81Z3JfbWV3YWtpbGkudHh0IiwgcHJvZ3Jlc3MgPSBGQUxTRSkKbWV3YWtpbGlfbWluaSA8LSBkcGx5cjo6ZmlsdGVyKG1ld2FraWxpLCB3MSA9PSAibWV3YWtpbGkiKQptZXdha2lsaV9jb3VudCA8LSBkcGx5cjo6Y291bnQobWV3YWtpbGlfbWluaSwgdzEsIHcyLCB3Mywgc29ydCA9IFRSVUUpCm1ld2FraWxpX3ByaW50IDwtIG1ld2FraWxpX2NvdW50WzE6MTAsXQptZXdha2lsaV9wcmludCA8LSBkcGx5cjo6bXV0YXRlKG1ld2FraWxpX3ByaW50LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZ3JhbXMgPSBwYXN0ZSh3MSwgIl8iLCB3MiwgIl8iLCB3Mywgc2VwID0gIiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ncmFtcyA9IHBhc3RlKCIqIiwgbmdyYW1zLCAiKiIsIHNlcCA9ICIiKSkKbWV3YWtpbGlfcHJpbnQgPC0gZHBseXI6OnNlbGVjdChtZXdha2lsaV9wcmludCwgbmdyYW1zLCBuKQprbml0cjo6a2FibGUobWV3YWtpbGlfcHJpbnQsIGNhcHRpb24gPSAiMTAgbW9zdCBmcmVxdWVudCAzLWdyYW0gZm9yICptZXdha2lsaSogJ3RvIChiZSBhKSByZXByZXNlbnQoYXRpdmUgb2YpIFgnIiwgcm93Lm5hbWVzID0gVFJVRSkKYGBgCgpUaGVuLCB0aGUgY29kZXMgZm9yIDMtZ3JhbXMgb2YgKm1ld2FraWxrYW4qICd0byBtYWtlIFggYXMgdGhlIHJlcHJlc2VudGF0aXZlIChvZiBZKScuCgpgYGB7ciBtZXdha2lsa2FuLWdyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgaW5jbHVkZSA9IFRSVUV9Cm1ld2FraWxrYW4gPC0gcmVhZHI6OnJlYWRfdHN2KCJkYXRhL25ncmFtZXhhbXBsXzVncl9tZXdha2lsa2FuLnR4dCIsIHByb2dyZXNzID0gRkFMU0UpCm1ld2FraWxrYW5fbWluaSA8LSBkcGx5cjo6ZmlsdGVyKG1ld2FraWxrYW4sIHcxID09ICJtZXdha2lsa2FuIikKbWV3YWtpbGthbl9jb3VudCA8LSBkcGx5cjo6Y291bnQobWV3YWtpbGthbl9taW5pLCB3MSwgdzIsIHczLCBzb3J0ID0gVFJVRSkKbWV3YWtpbGthbl9wcmludCA8LSBtZXdha2lsa2FuX2NvdW50WzE6MTAsXQptZXdha2lsa2FuX3ByaW50IDwtIGRwbHlyOjptdXRhdGUobWV3YWtpbGthbl9wcmludCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmdyYW1zID0gcGFzdGUodzEsICJfIiwgdzIsICJfIiwgdzMsIHNlcCA9ICIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZ3JhbXMgPSBwYXN0ZSgiKiIsIG5ncmFtcywgIioiLCBzZXAgPSAiIikpCm1ld2FraWxrYW5fcHJpbnQgPC0gZHBseXI6OnNlbGVjdChtZXdha2lsa2FuX3ByaW50LCBuZ3JhbXMsIG4pCmtuaXRyOjprYWJsZShtZXdha2lsa2FuX3ByaW50LCBjYXB0aW9uID0gIjEwIG1vc3QgZnJlcXVlbnQgMy1ncmFtIGZvciAqbWV3YWtpbGthbiogJ3RvIGFwcG9pbnQvc2VsZWN0IFggYXMgdGhlIHJlcHJlc2VudGF0aXZlIG9mIFknIiwgcm93Lm5hbWVzID0gVFJVRSkKYGBgCgojIyBDbHVzdGVyaW5nLXNwbGl0IGJldHdlZW4gbW9ycGhvbG9naWNhbCBzY2hlbWFzIGZvciBhIGdpdmVuIHJvb3QgeyNjbHVzdGVyLXNwbGl0fQoKCgpUaGlzIHN1Yi1zZWN0aW9uIGFkZHJlc3NlcyBpbiBtb3JlIGRldGFpbHMgc3BsaXQgY2FzZXMgYmV0d2VlbiBtb3JwaG9sb2dpY2FsIHNjaGVtYXMgZm9yIGEgZ2l2ZW4gcm9vdC4gVGhlIHNwbGl0LCBlc3BlY2lhbGx5IGJldHdlZW4gKk1lTiotLy0qa2FuKiBhbmQgKk1lTiotLy0qaSogdmVyYnMsIHJlZmxlY3RzIFNuZWRkb24gZXQgYWwncyBbLUBzbmVkZG9uX2luZG9uZXNpYW5fMjAxMCwgMTAwLTEwMV0gaHlwb3RoZXNpcyBjb25jZXJuaW5nIGNsZWFyIHNlbWFudGljIGRpZmZlcmVuY2UgYmV0d2VlbiBzb21lIG9mIGEgcGFpciBvZiAqTWVOKi0vLSprYW4qIGFuZCAqTWVOKi0vLSppKiB2ZXJicyB3aXRoIHRoZSBzYW1lIHJvb3QuIE91ciBWU00tYmFzZWQgYXBwcm9hY2ggYWxsb3dzIHVzIHRvICp2aXN1YWxpc2UqIHN1Y2ggc3BsaXQgdGhyb3VnaCB0aGUgZGVuZHJvZ3JhbSBiYXNlZCBvbiBsYXJnZS1zY2FsZSB1c2FnZSBkYXRhLiBUaGUgc3ViLXNlY3Rpb24gYWxzbyBkZW1vbnN0cmF0ZXMgZnVydGhlciBlbnJpY2htZW50IGluIGNoYXJhY3RlcnNpbmcgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBtb3JwaG9sb2dpY2FsbHkgcmVsYXRlZCB2ZXJiIHBhaXJzIHVzaW5nIHRoZSB0ZWNobmlxdWUgb2YgX25lYXJlc3QgbmVpZ2hib3Vyc18gYmFzZWQgb24gdGhlIFZTTSBkYXRhLgoKSW4gwqdbXEByZWYoc2VtY2x1c3QpXSgjc2VtY2x1c3QpLCB3ZSBoYXZlIG1lbnRpb25lZCB0aGUgY2xlYXIgc3BsaXQgYmV0d2VlbiB0aGUgdHJhbnNpdGl2ZSAqbWVsYW5na2Foa2FuKiAndG8gbW92ZSB0aGUgZm9vdCBmb3J3YXJkJyBhbmQgKm1lbGFuZ2thaGkqICd0byBzdGVwIG92ZXInLiBMb29raW5nIGF0IHRoZSAyLWdyYW0gZGF0YSBmb3IgZWFjaCB2ZXJiIHNob3dzIHRoYXQgdGhleSBoYXZlIGRpZmZlcmVudCBzZW1hbnRpYyBvcmllbnRhdGlvbi4gVGhlIGZvbGxvd2luZyBjb2RlcyBnZW5lcmF0ZSB0aGUgMi1ncmFtIGRhdGEgZm9yICptZWxhbmdrYWhpKi4KCmBgYHtyIGxhbmdrYWhpLWdyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgaW5jbHVkZSA9IFRSVUV9CmxhbmdrYWhpIDwtIHJlYWRyOjpyZWFkX3RzdigiZGF0YS9uZ3JhbWV4YW1wbF8zZ3JfbWVsYW5na2FoaS50eHQiKQpsYW5na2FoaV9wcmludCA8LSBsYW5na2FoaSAlPiUgCiAgZmlsdGVyKHcxID09ICJtZWxhbmdrYWhpIikgJT4lIAogIG11dGF0ZShuZ3JhbXMgPSBwYXN0ZSh3MSwgIl8iLCB3Miwgc2VwID0gIiIpLAogICAgICAgICBuZ3JhbXMgPSBwYXN0ZSgiKiIsIG5ncmFtcywgIioiLCBzZXAgPSAiIikpICU+JSAKICBjb3VudChuZ3JhbXMsIHNvcnQgPSBUUlVFKSAlPiUgCiAgLlsxOjEwLCBdCmtuaXRyOjprYWJsZShsYW5na2FoaV9wcmludCwgY2FwdGlvbiA9ICJUZW4gbW9zdCBmcmVxdWVudCAyLWdyYW0gZm9yIHJpZ2h0LXNpZGUgY29sbG9jYXRlcyBvZiAqbWVsYW5na2FoaSoiLCByb3cubmFtZXMgPSBUUlVFKQpgYGAKCipNZWxhbmdrYWhpKiBwcmVkb21pbmFudGx5IGNvbnZleXMgbWV0YXBob3JpY2FsIHNlbnNlIHJlbGF0ZWQgdG8gZGlzb2JleWluZy9kaXNyZWdhcmRpbmcgY2VydGFpbiAoaSkgcnVsZXMvcHJvdG9jb2xzIChpLmUuLCAqYXR1cmFuKiwgKmJhdGFzLWJhdGFzKi8qYmF0YXNhbiogJ2xpbWl0czsgcmVzdHJpY3Rpb24nLCAqbWVrYW5pc21lKiAnbWVjaGFuaXNtJyksIChpaSkgZm91bmRhdGlvbiAoKmRhc2FyLWRhc2FyKiksIG9yIChpaWkpIGF1dGhvcml0eSAoKmtld2VuYW5nYW4qKS4KCkluIGNvbnRyYXN0LCAqbWVsYW5na2Foa2FuKiBwcmVkb21pbmFudGx5IGNvbGxvY2F0ZXMgd2l0aCAqa2FraSogJ2Zvb3QnIGFzIGl0cyBkaXJlY3Qgb2JqZWN0IGNvbGxvY2F0ZXMsIHdoaWNoIGNhbiBiZSB1c2VkIGluIHRoZSBsaXRlcmFsLCB0cmFuc2xhdGlvbmFsIG1vdGlvbiBhbmQgbWV0YXBob3JpY2FsIG1vdGlvbiAoc2VlIG91ciBwYXBlciBmb3IgdGhlIGV4YW1wbGUgc2VudGVuY2VzKS4KCmBgYHtyIGxhbmdrYWhrYW4tZ3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBpbmNsdWRlID0gVFJVRX0KbGFuZ2thaGthbiA8LSByZWFkcjo6cmVhZF90c3YoImRhdGEvbmdyYW1leGFtcGxfM2dyX21lbGFuZ2thaGthbi50eHQiKQpsYW5na2Foa2FuX3ByaW50IDwtIGxhbmdrYWhrYW4gJT4lIAogIGZpbHRlcih3MSA9PSAibWVsYW5na2Foa2FuIikgJT4lIAogIG11dGF0ZShuZ3JhbXMgPSBwYXN0ZSh3MSwgIl8iLCB3Miwgc2VwID0gIiIpLAogICAgICAgICBuZ3JhbXMgPSBwYXN0ZSgiKiIsIG5ncmFtcywgIioiLCBzZXAgPSAiIikpICU+JSAKICBjb3VudChuZ3JhbXMsIHNvcnQgPSBUUlVFKSAlPiUgCiAgLlsxOjEwLCBdCmtuaXRyOjprYWJsZShsYW5na2Foa2FuX3ByaW50LCBjYXB0aW9uID0gIlRlbiBtb3N0IGZyZXF1ZW50IDItZ3JhbSBmb3IgcmlnaHQtc2lkZSBjb2xsb2NhdGVzIG9mICptZWxhbmdrYWhrYW4qIiwgcm93Lm5hbWVzID0gVFJVRSkKYGBgCgpPYnNlcnZhdGlvbiBvbiB0aGUgbi1ncmFtIGNhbiBiZSBlbnJpY2hlZCB1c2luZyBpbmZvcm1hdGlvbiBmcm9tIHRoZSBWU00gb2Ygd29yZHMuIEdpdmVuIHRoYXQgdGhlICpza2lwLWdyYW0qIGFsZ29yaXRobSBvZiAqd29yZDJ2ZWMqIGxlYXJucyB0byBwcmVkaWN0IHRoZSBjb250ZXh0dWFsIGVudmlyb25tZW50cyBnaXZlbiBhIHRhcmdldCB3b3JkIFtjZi4gQG1pa29sb3ZfZWZmaWNpZW50XzIwMTNdLCBvbmUgY2FuIHJldHJpZXZlIGZyb20gdGhlIFZTTSBhIHNldCBvZiB3b3JkcyB0aGF0IGhhdmUgc2ltaWxhciBjb250ZXh0dWFsLXZlY3RvciBkaXN0cmlidXRpb24gdG8gYSBnaXZlbiB0YXJnZXQgdmVyYiBvbiB0aGUgYmFzaXMgdGhlaXIgY29zaW5lIHNpbWlsYXJpdGllczsgdGhlc2Ugd29yZHMgY2FuIGJlIG1ldGFwaG9yaWNhbGx5IHJlZmVycmVkIHRvIGFzIHRoZSB2ZXJiJ3MgKm5lYXJlc3QgbmVpZ2hib3VycyouIFtUYWJsZSBcQHJlZih0YWI6bmVhcmVzdC10by1tZWxhbmdrYWhpKV0oI25lYXJlc3QtdG8tbWVsYW5na2FoaSkgaWxsdXN0cmF0ZXMgdGhlIGlkZWEgZm9yICptZWxhbmdrYWhpKiAndG8gc3RlcCBvdmVyJy4KCmBgYHtyIG5lYXJlc3QtdG8tbWVsYW5na2FoaX0KIyBmdW5jdGlvbiB0byByZXRyaWV2ZSBhbmQgcHJpbnQgdG9wLTEwIG5lYXJlc3QgbmVpZ2hib3VycwpuZWlnaGJvdXJzIDwtIGZ1bmN0aW9uKG1vZGVsLCBzZWVkX3dvcmQsIG4gPSAxMCkgewogIHRvcG4gPC0gbiArIDEKICBkZiA8LSB3b3JkVmVjdG9yczo6Y2xvc2VzdF90byhtb2RlbCwgc2VlZF93b3JkLCB0b3BuKQogIAogICMgcmVtb3ZlIHRoZSBzZWVkIHdvcmRzIGJlY2F1c2UgaXQgaXMgc2ltaWxhciB0byBpdHNlbGYgYW5kIGJlY29tZSB0aGUgZmlyc3QgbmVhcmVzdCB3b3JkLiBXZSB0aHVzIGNvdW50IHRvcC0xMCBuZWFyZXN0IG5laWdoYm91cnMgZnJvbSB0aGUgcmFuayAyIHRvIDExCiAgZGYgPC0gZHBseXI6OmZpbHRlcihkZiwgd29yZCAhPSBzZWVkX3dvcmQpIAogIGRmIDwtIGRwbHlyOjptdXRhdGUoZGYsIHdvcmQgPSBwYXN0ZSgiKiIsIHdvcmQsICIqIiwgc2VwID0gIiIpKQogIGRmIDwtIGFzLmRhdGEuZnJhbWUoZGYpCiAgY29sbmFtZXMoZGYpWzJdIDwtIHBhc3RlKCdzaW1pbGFyaXR5IHRvICIqJywgc2VlZF93b3JkLCAnKiInLCBzZXAgPSAiIikKICByZXR1cm4oZGYpCn0KCiMgZ2V0IHRoZSBuZWFyZXN0IG5laWdoYm91cnMgZm9yICptZWxhbmdrYWhpKgpuZWFyX2xhbmdrYWhpIDwtIG5laWdoYm91cnModnNtLCBzZWVkX3dvcmQgPSAibWVsYW5na2FoaSIpCmtuaXRyOjprYWJsZShuZWFyX2xhbmdrYWhpLCAKICAgICAgICAgICAgIGNhcHRpb24gPSAiMTAgY2xvc2VzdCB3b3JkcyB0byAqbWVsYW5na2FoaSogJ3RvIHN0ZXAgb3ZlciciLAogICAgICAgICAgICAgcm93Lm5hbWVzID0gVFJVRSkKYGBgCgpUaGUgY2xvc2VzdCB3b3JkcyBtYXkgbm90IG5lY2Vzc2FyaWx5IHNpbWlsYXIgaW4gbWVhbmluZyAoZS5nLiwgbmVhci1zeW5vbnltcyksIGJ1dCBtYXkgZXhoaWJpdCBkaWZmZXJlbnQga2luZCBvZiByZWxhdGlvbnNoaXBzLCBzdWNoIGFzIGFudG9ueW1zLiBXb3JkcyBpbiBbVGFibGUgXEByZWYodGFiOm5lYXJlc3QtdG8tbWVsYW5na2FoaSldKCNuZWFyZXN0LXRvLW1lbGFuZ2thaGkpIGNvbnZleWluZyBtb3JlIG9yIGxlc3MgYW50b255bW91cyBzZW5zZSB0byAqbWVsYW5na2FoaSogJ3RvIHN0ZXAgb3ZlcjsgdG8gZGlzcmVnYXJkJyBpbmNsdWRlICptZW5nYWN1aGthbiogJ3RvIGNhcmUgYWJvdXQvaGVlZCBzdGguJywgKm1lbWF0dWhpKiAndG8gb2JleScsIGFuZCAodG8gYSBkZWdyZWUpICptZW1wZXJoaXR1bmdrYW5ueWEqICd0byB0YWtlIHN0aC4gaW50byBhY2NvdW50Jy4gKk1lbmdhbmdrYW5naSogJ3RvIHN0cmFkZGxlIHN0aC4nIGlzIHRoZSBjbG9zZXN0IGluIG1lYW5pbmcgd2l0aCAqbWVsYW5na2FoaSogYXMgaXQgY2FuIGJlIGV4dGVuZGVkIGludG8gJ2Rpc3JlZ2FyZGluZycgc2Vuc2UgZnJvbSBpdHMgcGh5c2ljYWwsIHBvc3R1cmUgc2Vuc2U6IHRoZSAyLWdyYW0gZGF0YSBmb3IgKm1lbmdhbmdrYW5naSogYWNyb3NzIHRoZSB3aG9sZSBjb3JwdXMgKFtUYWJsZSBcQHJlZih0YWI6a2FuZ2thbmdpLWdyKV0oI2thbmdrYW5naS1ncikpIHJldmVhbHMgdGhhdCBpdCBkb2VzIGNvLW9jY3VyIHdpdGggcnVsZXMtcmVsYXRlZCBkaXJlY3Qgb2JqZWN0cywgc3VjaCBhcyAqaHVrdW0qICdsYXcnICgzIHRva2VucyksICpwZXJhdHVyYW4qICdyZWd1bGF0aW9uJyAoMyksICprZWJlbmFyYW4qICd0aGUgdHJ1dGgnICgyKSwgKnByaW5zaXAqICdwcmluY2lwbGVzJyAoMiksICp1bmRhbmctdW5kYW5nKiAnY29uc3RpdHV0aW9uJyAoMiksICphdHVyYW4qICdydWxlcycgKDEpLCAqaW50ZXIgYWxpYSouCgpgYGB7ciBrYW5na2FuZ2ktZ3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBpbmNsdWRlID0gVFJVRX0KbmdhbmdrYW5naSA8LSByZWFkcjo6cmVhZF90c3YoImRhdGEvbmdyYW1leGFtcGxfM2dyX21lbmdhbmdrYW5naS50eHQiKQpuZ2FuZ2thbmdpX3ByaW50IDwtIG5nYW5na2FuZ2kgJT4lIAogIGZpbHRlcih3MSA9PSAibWVuZ2FuZ2thbmdpIikgJT4lIAogIG11dGF0ZShuZ3JhbXMgPSBwYXN0ZSh3MSwgIl8iLCB3Miwgc2VwID0gIiIpLAogICAgICAgICBuZ3JhbXMgPSBwYXN0ZSgiKiIsIG5ncmFtcywgIioiLCBzZXAgPSAiIikpICU+JSAKICBjb3VudChuZ3JhbXMsIHNvcnQgPSBUUlVFKQprbml0cjo6a2FibGUobmdhbmdrYW5naV9wcmludFtuZ2FuZ2thbmdpX3ByaW50JG4gPiAxLCBdLCBjYXB0aW9uID0gIlRoZSAyLWdyYW0gZGF0YSBmb3IgcmlnaHQtc2lkZSBjb2xsb2NhdGVzIG9mICptZW5nYW5na2FuZ2kqIChuID49IDIpIiwgcm93Lm5hbWVzID0gVFJVRSkKYGBgCgpUaGUgZm9sbG93aW5nIGNvZGVzIHJldHJpZXZlIHdvcmRzIG5lYXJlc3QgdG8gKm1lbGFuZ2thaGthbiouCgpgYGB7ciBuZWFyZXN0LXRvLW1lbGFuZ2thaGthbn0Ka25pdHI6OmthYmxlKG5laWdoYm91cnModnNtLCAibWVsYW5na2Foa2FuIiwgbiA9IDEwKSwgY2FwdGlvbiA9ICJUZW4gY2xvc2VzdCB3b3JkcyB0byAqbWVsYW5na2Foa2FuKiIsIHJvdy5uYW1lcyA9IFRSVUUpCmBgYAoKVGhlIGNvZGVzIHRvIHJldHJpZXZlIHRoZSBuZWFyZXN0IHdvcmRzIG9mICptZW5nYXRhaSogJ3RvIHJlYnVrZTsgc3BlYWtlIG9mIG9uZSdzIGJhZG5lc3MnLgoKYGBge3IgbmVhcmVzdC10by1tZW5nYXRhaX0Ka25pdHI6OmthYmxlKG5laWdoYm91cnModnNtLCAibWVuZ2F0YWkiLCBuID0gMTApLCBjYXB0aW9uID0gIlRlbiBjbG9zZXN0IHdvcmRzIHRvICptZW5nYXRhaSoiLCByb3cubmFtZXMgPSBUUlVFKQpgYGAKCkluIGNvbnRyYXN0LCAqbWVuZ2F0YWthbiogbW9zdGx5IGFwcGVhcnMgYXMgY29tbXVuaWNhdGlvbiB2ZXJiIHdpdGggc2ltaWxhciBkaXN0cmlidXRpb24gd2l0aCBvdGhlciByZXBvcnRlZCBzcGVlY2ggdmVyYnMuCgpgYGB7ciBuZWFyZXN0LXRvLW1lbmdhdGFrYW59CmtuaXRyOjprYWJsZShuZWlnaGJvdXJzKHZzbSwgIm1lbmdhdGFrYW4iLCBuID0gMTApLCBjYXB0aW9uID0gIlRlbiBjbG9zZXN0IHdvcmRzIHRvICptZW5nYXRha2FuKiIsIHJvdy5uYW1lcyA9IFRSVUUpCmBgYAoKTmVhcmVzdCB3b3JkcyB0byAqbWVtYnVhaGkqICd0byBicmVlZCBzdGguJyBhcmUgcmV0cmlldmVkIGFzIGZvbGxvd3MuCgpgYGB7ciBuZWFyZXN0LXRvLW1lbWJ1YWhpfQprbml0cjo6a2FibGUobmVpZ2hib3Vycyh2c20sICJtZW1idWFoaSIsIG4gPSAxMCksIGNhcHRpb24gPSAiVGVuIGNsb3Nlc3Qgd29yZHMgdG8gKm1lbWJ1YWhpKiIsIHJvdy5uYW1lcyA9IFRSVUUpCmBgYAoKQ29kZXMgZm9yIGV4dHJhY3RpbmcgY2xvc2VzdCB3b3JkcyB0byAqbWVtYnVhaGthbiogJ3RvIGJlYXIgYSBmcnVpdDsgdG8gcmVzdWx0IGluIHN0aC4nLgoKYGBge3IgbmVhcmVzdC10by1tZW1idWFoa2FufQprbml0cjo6a2FibGUobmVpZ2hib3Vycyh2c20sICJtZW1idWFoa2FuIiwgbiA9IDEwKSwgY2FwdGlvbiA9ICJUZW4gY2xvc2VzdCB3b3JkcyB0byAqbWVtYnVhaGthbioiLCByb3cubmFtZXMgPSBUUlVFKQpgYGAKCk5vdGVzIG9uIHRoZSB1c2FnZSBzZW50ZW5jZXMgZm9yICptZW1idWFoKiBhcmUgYmVsb3cuIEJ1dCBmaXJzdCBsb2FkIHRoZSBzZW50ZW5jZSBjaXRhdGlvbnMgZm9yICptZW1idWFoKiBpbnRvIFIgYW5kIHByaW50IHRoZW0gaW50byB0aGUgY29uc29sZS4gQWZ0ZXIgdGhhdCB0aGUgbm90ZXMgYXJlIG1hbnVhbGx5IGNyZWF0ZWQgYnkgbWFudWFsbHkgaW5zcGVjdGluZyBhbGwgdGhlIHVzYWdlIHNlbnRlbmNlcy4gVGhlIHNlbnRlbmNlIGRhdGEgaXMgYXZhaWxhYmxlIGFzIGAucmRzYCBmaWxlIG9mIGBsaXN0YCAoYHNlbnRlbmNlX21lbWJ1YWgucmRzYCkgYW5kIGAudHh0YCBmaWxlIGFzIHBsYWluIHRleHQgb2Ygc2VudGVuY2VzIChgc2VudGVuY2VfbWVtYnVhaC50eHRgKS4gCgpgYGB7ciBsb2FkLW1lbWJ1YWgtc2VudGVuY2V9Cm1lbWJ1YWggPC0gcmVhZFJEUygiZGF0YS9zZW50ZW5jZV9tZW1idWFoLnJkcyIpCm1lbWJ1YWgkaW5kX21peGVkXzIwMTJfMU0gIyBmb3IgaW5zdGFuY2UsIHJldHJpZXZlIHNlbnRlbmNlcyBmb3VuZCBpbiBgaW5kX21peGVkXzIwMTJfMU0tc2VudGVuY2VzLnR4dGAKYGBgCgpUaGUgc2VudGVuY2UgZm9ybWF0IGlzIGBjb3JwdXMtZmlsZS1uYW1lX3NlbnRlbmNlLWlkLW51bWJlcl9zZW50ZW5jZS1jaXRhdGlvbmAuIFRoZSBgPG0+Li4uPC9tPmAgdGFnIGluZGljYXRlcyB0aGUgY29ycmVzcG9uZGluZyBtYXRjaC93b3JkL3ZlcmIuCgotICptZW1idWFoKiAoNTYgY2l0YXRpb25zOyBTdW1tYXJ5OiBhbmFsb2d5IHRvICptZW1idWFoa2FuKiA9IDI0IGNpdGF0aW9uczsgc3BsaXQgd2l0aCAqLWthbiogPSAxOyBtaXNwZWxsIGZvciAqbWVtYnVhdCogPSAyNTsgbWlzcGVsbCBmb3IgKm1lbWJ1YW5nKiA9IDU7IHVuY2xlYXIgPSAxKQoKICAgIC0gaW5kX21peGVkXzIwMTJfMU06IDQgY2l0YXRpb25zIChhbGwgRlVMTCBGT1JNKQogICAgLSBpbmRfbmV3c18yMDA4XzMwMEs6IDUgY2l0YXRpb25zICgyIG1pc3BlbGwgZm9yICptZW1idWF0KiBbaWQgNTM2NjYgJiAxNTU1NjldOyAzIEZVTEwgRk9STSBhbmFsb2d5IHRvICptZW1idWFoa2FuKikKICAgIC0gaW5kX25ld3NfMjAwOV8zMDBLOiAzIGNpdGF0aW9ucyAoMSBtaXNwZWxsIGZvciAqbWVtYnVhdCogW2lkIDIwMDAyN10gMiBGVUxMIEZPUk0gYW5hbG9neSB0byAqbWVtYnVhaGthbiopCiAgICAtIGluZF9uZXdzXzIwMTBfMzAwSzogMSBjaXRhdGlvbiAoYWxsIG1pc3BlbGwgZm9yICptZW1idWF0KikKICAgIC0gaW5kX25ld3NfMjAxMV8zMDBLOiAyIGNpdGF0aW9ucyAoMSBtaXNwZWxsIGZvciAqbWVtYnVhdCogW2lkIDI2NjgxNF07IDEgRlVMTCBGT1JNIGFuYWxvZ3kgdG8gKm1lbWJ1YWhrYW4qKQogICAgLSBpbmRfbmV3c18yMDEyXzMwMEs6IDUgY2l0YXRpb25zICg0IG1pc3BlbGwgZm9yICptZW1idWF0KiBbaWQgMjAwOTUyLCAyMDY5ODAsIDI2ODQwNywgMjY5ODk4XTsgMSBGVUxMIEZPUk0gYW5hbG9neSB0byAqbWVtYnVhaGthbiopCiAgICAtIGluZF9uZXdzY3Jhd2xfMjAxMV8xTTogNiBjaXRhdGlvbnMgKDMgRlVMTCBGT1JNIGFuYWxvZ3kgdG8gKm1lbWJ1YWhrYW4qOyAzIG1pc3BlbGwgZm9yICptZW1idWF0KiBbaWQgMTE4NDE5LCAxNTEwOTUsIDIwNTIzOV0pCiAgICAtIGluZF9uZXdzY3Jhd2xfMjAxMl8xTTogMyBjaXRhdGlvbnMgKDEgbWlzcGVsbCBmb3IgKm1lbWJ1YXQqIFtpZCAyMDEyMTddOyAxIG1pc3BlbGwgZm9yICptZW1idWFuZyogW2lkIDQwMTE1OF07IDEgZ290IHNwbGl0IHdpdGggKi1rYW4qIFtpZCA1OTU2NjJdKQogICAgLSBpbmRfd2ViXzIwMTFfMzAwSzogMSBjaXRhdGlvbiAobWlzcGVsbCBmb3IgKm1lbWJ1YXQqKQogICAgLSBpbmRfd2ViXzIwMTJfMU06IDQgY2l0YXRpb25zICgxIG1pc3BlbGwgZm9yICptZW1idWF0KiBbaWQgNjAyMjc0XTsgMSB1bmNsZWFyIGZvciBtaXNwZWxsIGZvciAqbWVtYnVhdCogW2lkIDM2NTUxMF07IDIgRlVMTCBGT1JNIGFuYWxvZ3kgdG8gKm1lbWJ1YWhrYW4qKQogICAgLSBpbmRfd2lraXBlZGlhXzIwMTZfMU06IDUgY2l0YXRpb25zICgyIG1pc3BlbGwgZm9yICptZW1idWF0KiBbaWQgMzIwOTgxLCA1OTYyMDVdOyAzIEZVTEwgRk9STSBhbmFsb2d5IHRvICptZW1idWFoa2FuKikKICAgIC0gaW5kLWlkX3dlYl8yMDEzXzFNOiA1IGNpdGF0aW9ucyAoMSBtaXNwZWxsIGZvciAqbWVtYnVhbmcqIFtpZCA4ODYwNzZdOyA0IEZVTEwgRk9STSBhcyAqbWVtYnVhaGthbiopCiAgICAtIGluZC1pZF93ZWJfMjAxNV8zTTogMTIgY2l0YXRpb25zICgxIEZVTEwgRk9STSBhcyAqbWVtYnVhaGthbiogW2lkIDEzOTYyODVdOyAzIG1pc3BlbGwgZm9yICptZW1idWFuZyogW2lkIDEzNjIyMjMsIDE1NDk2NTMsIDE1NjQ1MzZdLCB0aGUgcmVtYWluaW5nIDggbWlzcGVsbCBmb3IgKm1lbWJ1YXQqKQoKVGhlIGZvbGxvd2luZyBjb2RlcyByZXRyaWV2ZSB0aGUgbmVhcmVzdCB3b3JkcyB0byAqbWVuZ2FraGlyaSogKE4gPSBgciB3ZnJlcShkZl9ub3VuLCAibWVuZ2FraGlyaSIpYCkuCgpgYGB7ciBuZWFyZXN0LXRvLW1lbmdha2hpcml9CmtuaXRyOjprYWJsZShuZWlnaGJvdXJzKHZzbSwgIm1lbmdha2hpcmkiLCBuID0gMTApLCBjYXB0aW9uID0gIlRlbiBjbG9zZXN0IHdvcmRzIHRvICptZW5nYWtoaXJpKiIsIHJvdy5uYW1lcyA9IFRSVUUpCmBgYAoKSWYgcmVhZGVyIHdpc2hlcyB0byBjaGVjayBhbGwgdXNhZ2Ugc2VudGVuY2VzIGZvciAqbWVuZ2FraGlyKiB0byBjb25maXJtIHRoYXQgaXQgb2NjdXJzIGFzIGEgZnVsbCB3b3JkLWZvcm0gYW5kIGhhcyBzaW1pbGFyIHVzYWdlIHBhdHRlcm5zIHdpdGggKm1lTi0qLy0qaSogZm9ybSAqbWVuZ2FraGlyaSogKGkuZS4gaW4gdHJhbnNpdGl2ZSBjb25zdHJ1Y3Rpb25zKSwgdXNlIHRoZSBmb2xsb3dpbmcgY29kZS4gSXQgd2lsbCBwcmludCBhbGwgc2VudGVuY2VzIGZvciAqbWVuZ2FraGlyKiBpbnRvIFIgY29uc29sZS4KCmBgYHtyIGxvYWQtbWVuZ2FraGlyLXNlbnRlbmNlLCBldmFsID0gRkFMU0V9Cm1lbmdha2hpciA8LSByZWFkUkRTKCJkYXRhL3NlbnRlbmNlX21lbmdha2hpci5yZHMiKQp1bmxpc3QodW5uYW1lKG1lbmdha2hpcikpICMgcHJpbnQgYWxsIDU3IHNlbnRlbmNlcyBpbiB0aGUgY29uc29sZQpgYGAKCgpOZXh0LCB0aGUgbmVhcmVzdCB3b3JkcyB0byAqbWVuZ2FraGlya2FuKiAoTiA9IGByIHdmcmVxKGRmX25vdW4sICJtZW5nYWtoaXJrYW4iKWApIGFyZSBzaG93biBiZWxvdy4KCmBgYHtyIG5lYXJlc3QtdG8tbWVuZ2FraGlya2FufQprbml0cjo6a2FibGUobmVpZ2hib3Vycyh2c20sICJtZW5nYWtoaXJrYW4iLCBuID0gMTApLCBjYXB0aW9uID0gIlRlbiBjbG9zZXN0IHdvcmRzIHRvICptZW5nYWtoaXJrYW4qIiwgcm93Lm5hbWVzID0gVFJVRSkKYGBgCgojIyBJc3N1ZXMgYW5kIGNoYWxsZW5nZXMgeyNpc3N1ZXN9CgpDb2RlcyB0byBleHRyYWN0IHRoZSBuZWFyZXN0IHdvcmRzIHRvICptZW5nYW50dW5nKiAndG8gaGFuZycgKE4gPSBgciB3ZnJlcShkZl9ub3VuLCAibWVuZ2FudHVuZyIpYCksIHdoaWNoIGlzIGEgbWlzc3BlbGxpbmcgb2YgKm1lbmdnYW50dW5nKiAndG8gaGFuZycgKHdpdGggZG91YmxlICpnKikgKE4gPSBgciBmb3JtYXQoc3VtKHN1YnNldChkZl9hbGxfcHJlZiwgd29yZCA9PSAibWVuZ2dhbnR1bmciKSRuKSwgYmlnLm1hcmsgPSAiLCIpYCkuIE5lYXJlc3Qgd29yZHMgb3V0cHV0IHNob3dzIHRoYXQgKm1lbmdhbnR1bmcqIGlzIGluZGVlZCB0aGUgY2xvc2VzdCB3b3JkIHRvICptZW5nZ2FudHVuZyogaW4gdGhlaXIgdXNhZ2UgY28tb2NjdXJyZW5jZS4KCmBgYHtyIG5lYXJlc3QtdG8tbWVuZ2FudHVuZ30Ka25pdHI6OmthYmxlKG5laWdoYm91cnModnNtLCAibWVuZ2FudHVuZyIsIG4gPSAxMCksIGNhcHRpb24gPSAiVGVuIGNsb3Nlc3Qgd29yZHMgdG8gKm1lbmdhbnR1bmcqIiwgcm93Lm5hbWVzID0gVFJVRSkKYGBgCgpUaGUgY29kZXMgYmVsb3cgZXh0cmFjdCB0aGUgbmVhcmVzdCB3b3JkcyBmb3IgKm1lbmdhbnR1bmdrYW4qIChOID0gYHIgd2ZyZXEoZGZfbm91biwgIm1lbmdhbnR1bmdrYW4iKWApLCBhIG1pc3NwZWxsaW5nIGZvciAqbWVuZ2dhbnR1bmdrYW4qICd0byBoYW5nIHN0aC4gKG9udG8gc3RoLiknIChOID0gYHIgZm9ybWF0KHN1bShzdWJzZXQoZGZfYWxsX3ByZWYsIHdvcmQgPT0gIm1lbmdnYW50dW5na2FuIikkbiksIGJpZy5tYXJrID0gIiwiKWApLgoKYGBge3IgbmVhcmVzdC10by1tZW5nYW50dW5na2FufQprbml0cjo6a2FibGUobmVpZ2hib3Vycyh2c20sICJtZW5nYW50dW5na2FuIiwgbiA9IDEwKSwgY2FwdGlvbiA9ICJUZW4gY2xvc2VzdCB3b3JkcyB0byAqbWVuZ2FudHVuZ2thbioiLCByb3cubmFtZXMgPSBUUlVFKQpgYGAKClRoZW4sIHRoZSBuZWFyZXN0IHdvcmRzIGZvciAqbWVuZ2FudHVuZ2kqIChOID0gYHIgd2ZyZXEoZGZfbm91biwgIm1lbmdhbnR1bmdpIilgKSB3aGljaCBpcyBjbG9zZXN0IHRvIHRoZSBjb21tb24gc3BlbGxpbmcgd2l0aCBfbWVuZ2FudCoqbyoqbmdpXyAoTiA9IGByIGZvcm1hdChzdW0oc3Vic2V0KGRmX2FsbF9wcmVmLCB3b3JkID09ICJtZW5nYW50b25naSIpJG4pLCBiaWcubWFyayA9ICIsIilgKSBiYXNlZCBvbiB0aGUgcm9vdCAqa2FudG9uZyogJ3BvY2tldCcuCgpgYGB7ciBuZWFyZXN0LXRvLW1lbmdhbnR1bmdpfQprbml0cjo6a2FibGUobmVpZ2hib3Vycyh2c20sICJtZW5nYW50dW5naSIsIG4gPSAxMCksIGNhcHRpb24gPSAiVGVuIGNsb3Nlc3Qgd29yZHMgdG8gKm1lbmdhbnR1bmdpKiIsIHJvdy5uYW1lcyA9IFRSVUUpCmBgYAoKRmluYWxseSwgdGhlIGNhc2Ugd2hlcmUgcGFydCBvZiB0aGUgY29tcGxleCB3b3JkIGlzIHNwbGl0LiBUaGUgcGFwZXIgaWxsdXN0cmF0ZXMgdGhpcyB3aXRoICptZW5hbmRhKiB3aGljaCBpcyBwYXJ0IG9mICptZW5hbmRhdGFuZ2FuaSogJ3RvIGdpdmUgc2lnbmF0dXJlOyB0byBzaWduJyBidXQgaXMgd3JpdHRlbiBzZXBhcmF0ZWx5IHdpdGggd2hpdGVzcGFjZSwgdGh1cywgKm1lbmFuZGEgdGFuZ2FuaSosIHdoZXJlIHRoZSB3aGl0ZXNwYWNlIGdvdCB0b2tlbmlzZWQuCgpgYGB7ciBuZWFyZXN0LXRvLW1lbmFuZGF9CmtuaXRyOjprYWJsZShuZWlnaGJvdXJzKHZzbSwgIm1lbmFuZGEiLCBuID0gMTApLCBjYXB0aW9uID0gIlRlbiBjbG9zZXN0IHdvcmRzIHRvICptZW5hbmRhKiIsIHJvdy5uYW1lcyA9IFRSVUUpCmBgYAoKCgoKCi0gKm1lbmFuZGEqIChOID0gYHIgd2ZyZXEodyA9ICJtZW5hbmRhIilgOyBTdW1tYXJ5OiBzcGxpdCA9IDExMzsgaW50cmFuc2l0aXZlIHVzYWdlID0gNTsgdHJhbnNpdGl2ZSB1c2FnZSBhbmFsb2d5ID0gMjsgYW1iaWd1b3VzID0gMSkKCiAgICAtIGluZF9taXhlZF8yMDEyXzFNICgyMiBjaXRhdGlvbnM6IDE4IHNwbGl0IGZyb20gKm1lbmFuZGF0YW5nYW5pKjsgNCBjaXRhdGlvbnMgYXMgaW50cmFuc2l0aXZlIHdpdGggKnBhZGEqICgxMzgzMDcsIDI3ODE5MywgNTQyMTkxLCA3NTQ1MjkpKQogICAgLSBpbmRfbmV3c18yMDA4XzMwMEsgKDEgY2l0YXRpb246IDEgc3BsaXQgZnJvbSAqbWVuYW5kYXRhbmdhbmkqKQogICAgLSBpbmRfbmV3c18yMDA5XzMwMEsgKDIgY2l0YXRpb25zOiAyIHNwbGl0IGZyb20gKm1lbmFuZGF0YW5nYW5pKikKICAgIC0gaW5kX25ld3NfMjAxMF8zMDBLICgyIGNpdGF0aW9uczogMiBzcGxpdCBmcm9tICptZW5hbmRhdGFuZ2FuaSopCiAgICAtIGluZF9uZXdzXzIwMTFfMzAwSyAoMyBjaXRhdGlvbnM6IDMgc3BsaXQgZnJvbSAqbWVuYW5kYXRhbmdhbmkqKQogICAgLSBpbmRfbmV3c2NyYXdsXzIwMTFfMU0gKDEwIGNpdGF0aW9uczogMTAgc3BsaXQgZnJvbSAqbWVuYW5kYXRhbmdhbmkqKQogICAgLSBpbmRfbmV3c2NyYXdsXzIwMTJfMU0gKDkgY2l0YXRpb25zOiA5IHNwbGl0IGZyb20gKm1lbmFuZGF0YW5nYW5pKikKICAgIC0gaW5kX3dlYl8yMDExXzMwMEsgKDQgY2l0YXRpb25zOiA0IHNwbGl0IGZyb20gKm1lbmFuZGF0YW5nYW5pKikKICAgIC0gaW5kX3dlYl8yMDEyXzFNICgxOCBjaXRhdGlvbnMpOgogICAgICAgIC0gMTQgY2l0YXRpb25zIHNwbGl0IGZyb20gKm1lbmFuZGF0YW5nYW5pKgogICAgICAgIDwhLS0gLSAxIGNpdGF0aW9uIG9mIHJlZHVwbGljYXRpb24gKnRhbmRhLSBtZW5hbmRhKiAoNTUyNzApOiBBbmNhbmdhbiBTZW1pb3Rpa2EgZGFuIFBlbmdrYWppYW4gU3VzYXN0cmEgYWRhbGFoIGJ1a3UgdGVvcmkgZGFuIGtyaXRpayBzYXN0cmEgeWFuZyBtZW11bXB1bmthbiB0ZWxhYWhueWEgcGFkYSBtYXNhbGFoIGlsbXUgdGFuZGEtIDxtPm1lbmFuZGE8L20+ICBkYWxhbSBodWJ1bmdhbm55YSBkZW5nYW4ga29tdW5pa2FzaSBkYW4gcGVtYWtuYWFuIHNhc3RyYSAuIiAtLT4KICAgICAgICAtIDEgY2l0YXRpb24gb2YgdHJhbnNpdGl2ZSB1c2FnZSBpbiBhbmFsb2d5IHRvICptZW5hbmRhaSogKDQ0MDQzKTogIklJIC4gbWFuZ2FydXMgcnVwYSAsIG1lbmVya2EgLCBtZW5jb2JhICAmbHQ7bSZndDttZW5hbmRhJmx0OyYjNDc7bSZndDsgIHNpYXBhIG9yYW5nIGluaSAuIgogICAgICAgIC0gMSBjaXRhdGlvbiBvZiB0cmFuc2l0aXZlIHVzYWdlIGluIGFuYWxvZ3kgdG8gKm1lbmFuZGFrYW4qICd0byBtYXJrL3NpZ25hbCAodGhlIGV4aXN0ZW5jZSBvZikgc3RoLicgKDM2ODAwNCk6ICJNYWpsaXMgdGFtYXQgLCBoYWRpciBiZXJkdXl1biBzZWt1bXB1bGFuIHBlbmFyaSBkZW5nYW4gbWVyaWFobnlhICwgICZsdDttJmd0O21lbmFuZGEmbHQ7JiM0NzttJmd0OyAgdGVtYXN5YSBrZWNpbCBrYW1wdW5nIGJha2FsIGJlcm11bGEgLCBzZWRpa2l0IGRlbWkgc2VkaWtpdCBzYWh1dGFuIHBlbmR1ZHVrIGthbXB1bmcgbWVuZ2dpbGEgc2VwZW51aCBuYWZzdSBtZW5hcmkgc2VrYWxpIGJlcnNhbWEgcGVuYXJpIC4iIChNYWxheXNpYW4gTWFsYXk/KQogICAgICAgIC0gMSBjaXRhdGlvbiBvZiBpbnRyYW5zaXRpdmUgdXNhZ2UgKDU0NDM5NSk6ICJCYWdpIGFrdSAsIGthbGF1IHRpZGFrIHNlbXBhdCAgJmx0O20mZ3Q7bWVuYW5kYSZsdDsmIzQ3O20mZ3Q7ICBkaSBzZWtvbGFoICggbWVtYW5nIHRhayBjdWt1cCBtYXNhICkgLCB0ZXJwYWtzYWxhaCBiYXdhIGRpIHJ1bWFoIC4iIAogICAgICAgIC0gMSBjaXRhdGlvbiBvZiBhbWJpZ3VvdXMgdXNhZ2UgKDk4MTM4NCk6ICJOYW1hIGRhbiBObyBLYWQgUGVuZ2VuYWxhbiBkaXNlYnV0ICwgZGFuIG1lcmVrYSAgJmx0O20mZ3Q7bWVuYW5kYSZsdDsmIzQ3O20mZ3Q7ICAuIgogICAgLSBpbmRfd2lraXBlZGlhXzIwMTZfMU0gKDE2IGNpdGF0aW9uczogMTYgc3BsaXQgZnJvbSAqbWVuYW5kYXRhbmdhbihpKSopCiAgICAtIGluZC1pZF93ZWJfMjAxM18xTSAoMTYgY2l0YXRpb25zOiAxNiBzcGxpdCBmcm9tICptZW5hbmRhdGFuZ2FuKGkpKikKICAgIC0gaW5kLWlkX3dlYl8yMDE1XzNNICgxOCBjaXRhdGlvbnM6IDE4IHNwbGl0IGZyb20gKm1lbmFuZGF0YW5nYW4oaSkqKQoKCiMgU2Vzc2lvbiBJbmZvIHstfQoKYGBge3Igc2Vzc2luZm99CmRldnRvb2xzOjpzZXNzaW9uX2luZm8oKQpgYGAKCgojIFJlZmVyZW5jZXMgey19