Abstract
This project reports a methodological advancement on how topic
modeling can be used to analyze qualitative data from transcripts of
focus groups conducted with participants in an international
professional development program. The program is designed to prepare
inservice educators for culturally-responsive teaching (CRT) through
practice with the development of technical representations of cultural
themes in an international context. Themes developed using topic
modeling can be compared to existing thematic analysis conducted by
researchers on the same data. This will provide insight into the
strengths and weaknesses of each approach and demonstrate the potential
of topic modeling to enhance qualitative data analysis. This will be
useful for future researchers interested in the interaction between
qualitative methodology and topic modeling.
1. PREPARE
1a. Data sources used for text analysis
Context: Professional Development Abroad
The data are from an ongoing, international, professional development
program for inservice teachers. It includes three Saturday classes in
the spring, two weeks of a study abroad program in the summer to an
international destination (in 2022, to Munich Germany) and one follow up
session in the fall. In this professional development abroad, teachers
build a portfolio that represents a chosen cultural theme, including a
lesson plan illustrating how they plan to apply technical cultural
representation and/or analysis in their own classrooms. The program aims
to provide teachers with experiences practicing with cultural frames and
representational tools, so they can work with their own students to
elicit and represent diverse cultural identities and perspectives.
Data Collection and Analysis
First, using qualitative methods, the research team analyzed data
collected during focus groups, from digital portfolios, and from
observations during the professional development program. Data collected
consisted of researcher memos, projects and artifacts created by 19
teachers, and post-reflective focus groups after the professional
development experience. Using the transcripts from the focus groups,
participants’ portfolios, and researcher observations, Braun and
Clarke’s (2022) process of reflexive thematic analysis to analyze focus
group data was used.
Initial findings from thematic analysis of focus group data indicated
that
1.) Self-selected digital projects allowed participants to develop
professional knowledge related to their specific
teaching content, curriculum, and classroom;
2.) International immersive experience with targeted professional
development provided an opportunity for reflections on
pandemic/post-pandemic instruction; and
3.) Teachers reflected that the experience had an impact on their
teaching dispositions and plans for the future.
This project will outline a second step in this process, in which the
same data will be analyzed using topic modeling. Topic modeling is a
machine learning technique that automatically analyzes text data to
determine cluster words for a set of documents. This is known as
‘unsupervised’ machine learning because it doesn’t require a predefined
list of tags or training data that’s been previously classified by
humans. This additional step in analyzing the data advances the field of
qualitative research as it offers a means of reflecting on the
comparison of the two sets of results.
1b. Guiding Question
With the increasing amount of qualitative data being generated in
research studies, it is essential to have effective methods for
analyzing and interpreting this information. The use of topic modeling
in the analysis of textual data has gained popularity in recent years
due to its ability to identify hidden themes and patterns within large
datasets. This project describes a potential methodological advancement
on how topic modeling can be used to analyze qualitative data.
Thus, the primary research question is:
What does topic modeling in the analysis of textual data from
focus groups with inservice teachers participating in international
professional development reveal about how topic modeling can enhance
qualitative research data?
2. WRANGLE
To analyze the textual data using topic modeling, the workflow of the
process will include data wrangling, modeling, and exploration as
follows:
The data will be wrangled, a process which involves some combination
of cleaning, reshaping, transforming, and merging data (Wickham &
Grolemund, 2017). The text will be preprocessed, including converting
the data into a tidy text format. This includes data tokenization,
removal of stop words, and stemming.
The text will then be analyzed by fitting a topic modeling algorithm
using Latent Dirichlet Allocation (LDA). Then beta values were created
to explore the findings. A number of topics were selected. This process
was repeated until the appropriate number of topics was decided upon.
While topic modeling involves many decisions and can be as much art as
science (Bail, 2018), the purpose of topic modeling in this context was
to develop a simple mathematical summary of the dataset which can help
further explore trends and patterns in the data.
2a. Project Set Up and Import Interview Data
library(tidyverse)
library(tidytext)
library(SnowballC)
library(topicmodels)
library(stm)
library(ldatuning)
library(knitr)
library(LDAvis)
library(ggplot2)
library(dplyr)
After setting up the project in R, the data will be imported into
R.
CIDRE_interviews <- read_csv("data/Independent Analysis April 18 2023.csv",
col_types = cols(
Interview = col_character(),
Interviewee = col_character(),
Topic = col_character()
)
)
CIDRE_interviews <- CIDRE_interviews %>%
mutate(Interview = strsplit(as.character(Interview), "\n\n\n")) %>%
unnest(Interview)
CIDRE_interviews
## # A tibble: 333 × 3
## Interview Inter…¹ Topic
## <chr> <chr> <chr>
## 1 "Next is Chris and my picture. Let me make it bigger. Okay, th… Chris … <NA>
## 2 "making sure that she remembered in the photo that they were" Chris … <NA>
## 3 "…so this is the German theatre Museum. This one I went to on … Chris … <NA>
## 4 "Those are very grown up answers." Chris … <NA>
## 5 "We have to be grown up at some point.\n" Chris … <NA>
## 6 "\nThis is my photo of my personal experience. It was taken by… Kaitli… <NA>
## 7 "for the tape No it's a very it's a very like peaceful setting… Kaitli… <NA>
## 8 "Yeah, for the tape, it’s a swan, surrounded by its own feces … Kaitli… <NA>
## 9 "I feel badly that I already bailed on the public school syste… Karen … <NA>
## 10 "you did so much photographing. Do you have some favorite phot… Karen … <NA>
## # … with 323 more rows, and abbreviated variable name ¹Interviewee
2b. Cast a Document Term Matrix
The text was preprocessed, including converting the data into a tidy
text format. This included data tokenization and removal of stop
words.
First, the text was tokenized and stop words were removed. Additional
stop words were added such as: like, just, well, yeah, lot, stuff,
gonna
interviews_tidy <- CIDRE_interviews %>%
unnest_tokens(output = word, input = Interview) %>%
anti_join(stop_words, by = "word") %>%
filter(!word == "lot"& !word == "stuff"& !word == "gonna"& !word == "like"& !word == "just"& !word == "well"& !word == "yeah")
interviews_tidy
## # A tibble: 8,136 × 3
## Interviewee Topic word
## <chr> <chr> <chr>
## 1 Chris Alston <NA> chris
## 2 Chris Alston <NA> picture
## 3 Chris Alston <NA> bigger
## 4 Chris Alston <NA> picture
## 5 Chris Alston <NA> image
## 6 Chris Alston <NA> modern
## 7 Chris Alston <NA> art
## 8 Chris Alston <NA> museum
## 9 Chris Alston <NA> floor
## 10 Chris Alston <NA> chairs
## # … with 8,126 more rows
A word count to determine the most common words in the interviews was
conducted. These word counts would be later used for creating a document
term matrix for topic modeling.
interviews_tidy %>%
count(word, sort = TRUE)
## # A tibble: 2,759 × 2
## word n
## <chr> <int>
## 1 people 117
## 2 feel 68
## 3 time 68
## 4 experience 65
## 5 cool 45
## 6 world 45
## 7 kids 43
## 8 germany 42
## 9 picture 41
## 10 students 39
## # … with 2,749 more rows
The terms “people,” “feel,” “time,” and “experience” emerged as most
common, reflecting that the study topic was an international learning
experience. The terms “community,” “connections” and “professional” are
worth attention as well. The terms “white” with 14 instances and
“black,” with 13 instances suggests the potential to to explore a
potential theme of race.
Creating a Document Term Matrix
Each interview group was treated as a unique document, with a total
of ten documents with 2759 terms. Using the existing word counts, a
matrix was created that contained a column for each word in the corpus
and a value of n for how many times that word occurs in each post.
To create this document term matrix from the interview counts, the
cast_dtm() function was used and assigned to the variable
interviews_dtm.
interviews_dtm <- interviews_tidy %>%
count(Topic, word) %>%
cast_dtm(Topic, word, n)
## [1] "DocumentTermMatrix" "simple_triplet_matrix"
## <<DocumentTermMatrix (documents: 10, terms: 2759)>>
## Non-/sparse entries: 3128/24462
## Sparsity : 89%
## Maximal term length: 17
## Weighting : term frequency (tf)
2c. Preprocessing and (not) Stemming
Next the original data set for structural topic modeling was prepared
using the textProcessor() function to remove punctuation
elements and stop words to simplify results.
temp <- textProcessor(CIDRE_interviews$Interview,
metadata = CIDRE_interviews,
lowercase=TRUE,
removestopwords=TRUE,
removenumbers=TRUE,
removepunctuation=TRUE,
wordLengths=c(3,Inf),
stem=TRUE,
onlycharacter= FALSE,
striphtml=TRUE,
customstopwords=NULL)
## Building corpus...
## Converting to Lower Case...
## Removing punctuation...
## Removing stopwords...
## Removing numbers...
## Stemming...
## Creating Output...
Stemming was considered as a preprocessing step to reduce the size of
the vocabulary in natural language and thus simplify the model. Stemming
reduced the number of terms from 2920 to 2241. This reduction in corpus
size of 679 terms does not justify the risk of losing subtleties in
meaning between words with similar word stems, such as “support” and
“supported” that would be relevant to the findings of the study.
Therefore, this project does not use stemming.
meta <- temp$meta
vocab <- temp$vocab
docs <- temp$documents
3. MODEL
The text was modeled to create a mathematical summary of the dataset.
The resulting summaries can help trends and patterns in the data to
surface, particularly when compared to thematic analysis. Topic Modeling
is an unsupervised learning approach that can provide insight into the
structure of the dataset.
Three steps were undertaken:
- Fitting a Topic Modeling with LDA. The
topicmodels package and associated LDA()
function for unsupervised classification of the interview data was used
to find natural groupings of words, or topics.
- Fitting a Structural Topic Model. The
stm package and stm() function were used to
fit our model and used metadata about documents to improve the
assignment of words to “topics” in the corpus.
- Choosing K. Finally, an appropriate number of
topics was selected.
3a. Fitting a Topic Modeling with LDA
The LDA function or Latent Dirichlet allocation was used because
every document contains a mixture of topics and every topic contains a
mixture of words. This means that a focus group interview could have an
estimated topic proportion of 80% for Topic 1 but also be partly about
topic 2. Likewise, words can be shared between topics and words germane
to the topic such as “community” and “language” might appear in an
individual topic equally.
LDA requires a k value to be specified for the number of topics in
the focus group interviews. K was selected as 20 as a starting point. K
was then run as 15 by way of comparison.
interviews_lda <- LDA(interviews_dtm,
k = 20,
control = list(seed = 588)
)
interviews_lda
## A LDA_VEM topic model with 20 topics.
ap_topics <- tidy(interviews_lda, matrix = "beta")
ap_top_terms <- ap_topics %>%
group_by(topic) %>%
slice_max(beta, n = 6) %>%
ungroup() %>%
arrange(topic, -beta)
ap_top_terms %>%
mutate(term = reorder_within(term, beta, topic)) %>%
ggplot(aes(beta, term, fill = factor(topic))) +
geom_col(show.legend = FALSE) +
facet_wrap(~ topic, scales = "free") +
scale_y_reordered()
LDA employs the Term Frequency-Inverse Document Frequency (TF-IDF)
metric to assign probabilities.
3b. Fitting a Structural Topic Model
Bail (2018) argues that one reason STM has rising in popularity and
use is that it employs meta data about documents to improve the
assignment of words to topics in a corpus and that can be used to
examine relationships between covariates and documents. This was useful
for this project in confirming that topics related to themes revealed in
qualtitative data.
The stm Package
Before fitting an STM model, it was necessary to extract the
following elements:
docs <- temp$documents
meta <- temp$meta
vocab <- temp$vocab
These elements were then used to fit the model using the same topics
for K that were specified for the LDA topic model.
interviews_stm <- stm(documents=docs,
data=meta,
vocab=vocab,
K=20,
max.em.its=25,
verbose = FALSE)
interviews_stm
## A topic model with 20 topics, 308 documents and a 2329 word dictionary.
The function allows for viewing the most probable words assigned to
each topic.
plot.STM(interviews_stm, n = 5)

plot(interviews_stm, n = 5)

3c. Finding K
As alluded to earlier, selecting the number of topics for your model
is a non-trivial decision and can dramatically impact your results. Bail
(2018) notes that
The results of topic models should not be over-interpreted unless
the researcher has strong theoretical apriori about the number of topics
in a given corpus, or if the researcher has carefully validated the
results of a topic model using both the quantitative and qualitative
techniques described above.
The FindTopicsNumber Function
The ldatuning package was used to assist with finding K
value.
k_metrics <- FindTopicsNumber(
interviews_dtm,
topics = seq(10, 75, by = 5),
metrics = "Griffiths2004",
method = "Gibbs",
control = list(),
mc.cores = NA,
return_models = FALSE,
verbose = FALSE,
libpath = NULL
)
FindTopicsNumber_plot(k_metrics)
Note that the FindTopicNumbers() function contains three
additional metrics for calculating metrics that can be used to estimate
the most preferable number of topics for LDA model. We used the
Griffiths2004 metrics included in the default example and I’ve also
found this to produce the most interpretable results as show in the
figure below:

As a general rule of thumb and overly simplistic heuristic, we’re
looking for an inflection point in our plot which indicates an optimal
number of topics to select for a value of K.
The LDAvis Explorer
The LDAvis explorere was used to expore topic and word
distributions.
toLDAvis(mod = interviews_stm, docs = docs)
## Loading required namespace: servr
4. EXPLORE & MODEL
Silge and Robinson (2018) note that fitting at topic model is the
“easy part.” The hard part is making sense of the model results and that
the rest of the analysis involves exploring and interpreting the model
using a variety of approaches which we’ll walkthrough in in this
section.
Bail (2018) cautions, however, that:
…post-hoc interpretation of topic models is rather dangerous… and
can quickly come to resemble the process of “reading tea leaves,” or
finding meaning in patterns that are in fact quite arbitrary or even
random.
4a. Exploring Beta Values
The 5 most likely terms assigned to each topic were explored. These
per-topic-per-word probabilities, or β (“beta”) values provide the
probability of a term (word) belonging to a topic.
terms(interviews_lda, 5)
## Topic 1 Topic 2 Topic 3 Topic 4 Topic 5
## [1,] "people" "world" "wearing" "happened" "connections"
## [2,] "time" "lesson" "people" "culture" "teachers"
## [3,] "students" "garden" "traditional" "world" "traditions"
## [4,] "experience" "sustainable" "clothing" "understanding" "teaching"
## [5,] "world" "plan" "lederhosen" "learned" "program"
## Topic 6 Topic 7 Topic 8 Topic 9 Topic 10 Topic 11
## [1,] "people" "people" "time" "people" "experience" "people"
## [2,] "time" "time" "experience" "feel" "people" "experience"
## [3,] "picture" "world" "people" "experience" "time" "kids"
## [4,] "germany" "picture" "cool" "kids" "cool" "pictures"
## [5,] "kids" "guess" "read" "cool" "germany" "feel"
## Topic 12 Topic 13 Topic 14 Topic 15 Topic 16
## [1,] "feel" "cool" "similar" "cream" "time"
## [2,] "people" "world" "love" "picture" "experience"
## [3,] "experience" "favorite" "opportunities" "ice" "kids"
## [4,] "german" "padlet" "combination" "professional" "picture"
## [5,] "museum" "war" "learner" "museum" "thinking"
## Topic 17 Topic 18 Topic 19 Topic 20
## [1,] "people" "people" "people" "time"
## [2,] "time" "experience" "germany" "feel"
## [3,] "thinking" "picture" "guess" "cool"
## [4,] "trip" "kids" "talking" "students"
## [5,] "pictures" "world" "kids" "pictures"
Topic 10 (experience, time, people, cool, Germany) seems to be about
participants experience in Germany.This correlates with the kind of data
found in qualitative research on the same data.
tidy_lda <- tidy(interviews_lda)
tidy_lda
## # A tibble: 55,180 × 3
## topic term beta
## <int> <chr> <dbl>
## 1 1 american 1.15e- 3
## 2 2 american 6.21e-42
## 3 3 american 4.83e-42
## 4 4 american 2.54e-37
## 5 5 american 8.77e- 3
## 6 6 american 7.09e- 4
## 7 7 american 9.35e- 5
## 8 8 american 2.40e- 4
## 9 9 american 2.08e- 3
## 10 10 american 1.10e- 3
## # … with 55,170 more rows
top_terms <- tidy_lda %>%
group_by(topic) %>%
slice_max(beta, n = 5, with_ties = FALSE) %>%
ungroup() %>%
arrange(topic, -beta)
top_terms %>%
mutate(term = reorder_within(term, beta, topic)) %>%
group_by(topic, term) %>%
arrange(desc(beta)) %>%
ungroup() %>%
ggplot(aes(beta, term, fill = as.factor(topic))) +
geom_col(show.legend = FALSE) +
scale_y_reordered() +
labs(title = "Top 5 terms in each LDA topic",
x = expression(beta), y = NULL) +
facet_wrap(~ topic, ncol = 4, scales = "free")

5. COMMUNICATE
As Silge and Robinson note (2018), fitting the topic model is easy
relative to the more challenging work of interpreting the model
results.
Comparing results of thematic analysis conducted by researchers to
topic modeling conducted in R can provide insights into the limitations
and benefits of both forms of qualitative research. As Bail (2018)
warns, “…post-hoc interpretation of topic models is rather dangerous…
and can quickly come to resemble the process of ‘reading tea leaves,’ or
finding meaning in patterns that are in fact quite arbitrary or even
random.”
The same description could be applied to thematic analysis, a process
which is creative, time consuming, and can reflect the biases of the
researchers. By comparing the results of both approaches, researchers
and practitioners can gain a deeper understanding of the data and the
context in which it was collected. This can lead to transformative
insights into how qualitative research can be conducted in a more
rigorous and systematic manner, while still allowing for the creativity
and subjectivity that are inherent in this type of research. Moreover,
reflecting on the limitations and benefits of both thematic analysis and
topic modeling can help researchers and practitioners to identify areas
for improvement in their own research practices, as well as provide
guidance for future research studies. Ultimately, this can lead to more
robust and meaningful qualitative research that contributes to the
advancement of knowledge in a range of fields.
Initial findings from thematic analysis of focus group data indicated
that
1.) Self-selected digital projects allowed participants to develop
professional knowledge related to their specific
teaching content, curriculum, and classroom;
2.) International immersive experience with targeted professional
development provided an opportunity for reflections on
pandemic/post-pandemic instruction; and
3.) Teachers reflected that the experience had an impact on their
teaching dispositions and plans for the future.
Comparing topics to intitial findings from thematic analysis suggest
that topic analysis reflects general, superficial interperetations of
the expeirence. Words such as “cool” “experience” “people” “feel”
reflect a postive, but superficial experience in Germany. Thematic
analysis, conducted by researchers with personal relationships with
participants suggests a nuanced, more sophisticated reading of the data.
This anaylsis reflects outcomes from the experience with suggest deep
change in teacher values and practices which do not seem to be suggested
from topic modeling. While the text minign approach allows for analysis
of a large corpus of data, qualitative reseearch from a team offers a
more in-depth analysis. The two have value together in that topic
modeling can be used with a larger corpus of data and can offer a
confirmation of the general direction of themes created in thematic
analysis. The use of topic modeling in addition to thematic analysis can
provide a form of triangulation valuable to the credibility of a
qualitative research study.
Experience examining which words tend to follow others immediately,
or that tend to co-occur within the same documents.
Comparing results of thematic analysis conducted by researchers to
topic modeling conducted in R can provide insights into the limitations
and benefits of both forms of qualitative research. As Bail (2018)
warns, “…post-hoc interpretation of topic models is rather dangerous…
and can quickly come to resemble the process of ‘reading tea leaves,’ or
finding meaning in patterns that are in fact quite arbitrary or even
random.” The same description could be applied to thematic analysis, a
process which is creative, time consuming, and can reflect the biases of
the researchers. By comparing the results of both approaches,
researchers and practitioners can gain a deeper understanding of the
data and the context in which it was collected. This can lead to
transformative insights into how qualitative research can be conducted
in a more rigorous and systematic manner, while still allowing for the
creativity and subjectivity that are inherent in this type of research.
Moreover, reflecting on the limitations and benefits of both thematic
analysis and topic modeling can help researchers and practitioners to
identify areas for improvement in their own research practices, as well
as provide guidance for future research studies. Ultimately, this can
lead to more robust and meaningful qualitative research that contributes
to the advancement of knowledge in a range of fields.
References
Braun, V., & Clarke, V. (2022). Conceptual and design thinking
for thematic analysis. Qualitative Psychology, 9(1), 3–26. https://doi.org/10.1037/qup0000196
Bail, C. (2018). Strengths and weaknesses of text as data. Retrieved
from https://sicss.io/2019/materials/day3-text-analysis/topic-modeling/rmarkdown/Topic_Modeling.html
Gillies, M., Murthy, D., Brenton, H., & Olaniyan, R. (2022).
Theme and topic: How qualitative research and topic modeling can be
brought together. arXiv preprint arXiv:2210.00707. https://doi.org/10.48550/arXiv.2210.00707
Silge, J., & Robinson, D. (2017). Text mining with R: A tidy
approach. O’Reilly Media, Inc. Retrieved from: https://www.tidytextmining.com/topicmodeling.html
Wickham, H. & Grolemund, G. (2017). R for Data Science: Import,
Tidy, Transform, Visualize, and Model Data. O’Reilly Media,
Inc. Retrieved from https://r4ds.had.co.nz/
LS0tCnRpdGxlOiAiVXNpbmcgUiB0byBBbmFseXplIFF1YWxpdGF0aXZlIERhdGEgZnJvbSBUZWFjaGVyc+KAmSBJbnRlcm5hdGlvbmFsIFByb2Zlc3Npb25hbCBEZXZlbG9wbWVudCBFeHBlcmllbmNlIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgY29kZV9kb3dubG9hZDogVFJVRQplZGl0b3Jfb3B0aW9uczogCiAgbWFya2Rvd246IAogICAgd3JhcDogNzIKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCiMjIyBBYnN0cmFjdAoKVGhpcyBwcm9qZWN0IHJlcG9ydHMgYSBtZXRob2RvbG9naWNhbCBhZHZhbmNlbWVudCBvbiBob3cgdG9waWMgbW9kZWxpbmcKY2FuIGJlIHVzZWQgdG8gYW5hbHl6ZSBxdWFsaXRhdGl2ZSBkYXRhIGZyb20gdHJhbnNjcmlwdHMgb2YgZm9jdXMgZ3JvdXBzCmNvbmR1Y3RlZCB3aXRoIHBhcnRpY2lwYW50cyBpbiBhbiBpbnRlcm5hdGlvbmFsIHByb2Zlc3Npb25hbCBkZXZlbG9wbWVudApwcm9ncmFtLiBUaGUgcHJvZ3JhbSBpcyBkZXNpZ25lZCB0byBwcmVwYXJlIGluc2VydmljZSBlZHVjYXRvcnMgZm9yIGN1bHR1cmFsbHktcmVzcG9uc2l2ZQp0ZWFjaGluZyAoQ1JUKSB0aHJvdWdoIHByYWN0aWNlIHdpdGggdGhlIGRldmVsb3BtZW50IG9mIHRlY2huaWNhbApyZXByZXNlbnRhdGlvbnMgb2YgY3VsdHVyYWwgdGhlbWVzIGluIGFuIGludGVybmF0aW9uYWwgY29udGV4dC4gVGhlbWVzCmRldmVsb3BlZCB1c2luZyB0b3BpYyBtb2RlbGluZyBjYW4gYmUgY29tcGFyZWQgdG8gZXhpc3RpbmcgdGhlbWF0aWMKYW5hbHlzaXMgY29uZHVjdGVkIGJ5IHJlc2VhcmNoZXJzIG9uIHRoZSBzYW1lIGRhdGEuIFRoaXMgd2lsbCBwcm92aWRlCmluc2lnaHQgaW50byB0aGUgc3RyZW5ndGhzIGFuZCB3ZWFrbmVzc2VzIG9mIGVhY2ggYXBwcm9hY2ggYW5kCmRlbW9uc3RyYXRlIHRoZSBwb3RlbnRpYWwgb2YgdG9waWMgbW9kZWxpbmcgdG8gZW5oYW5jZSBxdWFsaXRhdGl2ZSBkYXRhCmFuYWx5c2lzLiBUaGlzIHdpbGwgYmUgdXNlZnVsIGZvciBmdXR1cmUgcmVzZWFyY2hlcnMgaW50ZXJlc3RlZCBpbiB0aGUKaW50ZXJhY3Rpb24gYmV0d2VlbiBxdWFsaXRhdGl2ZSBtZXRob2RvbG9neSBhbmQgdG9waWMgbW9kZWxpbmcuCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIDEuIFBSRVBBUkUKCiMjIyAxYS4gKipEYXRhIHNvdXJjZXMgdXNlZCBmb3IgdGV4dCBhbmFseXNpcyoqCgoqKkNvbnRleHQ6IFByb2Zlc3Npb25hbCBEZXZlbG9wbWVudCBBYnJvYWQqKgoKVGhlIGRhdGEgYXJlIGZyb20gYW4gb25nb2luZywgaW50ZXJuYXRpb25hbCwgcHJvZmVzc2lvbmFsIGRldmVsb3BtZW50CnByb2dyYW0gZm9yIGluc2VydmljZSB0ZWFjaGVycy4gSXQgaW5jbHVkZXMgdGhyZWUgU2F0dXJkYXkgY2xhc3NlcyBpbgp0aGUgc3ByaW5nLCB0d28gd2Vla3Mgb2YgYSBzdHVkeSBhYnJvYWQgcHJvZ3JhbSBpbiB0aGUgc3VtbWVyIHRvIGFuCmludGVybmF0aW9uYWwgZGVzdGluYXRpb24gKGluIDIwMjIsIHRvIE11bmljaCBHZXJtYW55KSBhbmQgb25lIGZvbGxvdyB1cApzZXNzaW9uIGluIHRoZSBmYWxsLiBJbiB0aGlzIHByb2Zlc3Npb25hbCBkZXZlbG9wbWVudCBhYnJvYWQsIHRlYWNoZXJzCmJ1aWxkIGEgcG9ydGZvbGlvIHRoYXQgcmVwcmVzZW50cyBhIGNob3NlbiBjdWx0dXJhbCB0aGVtZSwgaW5jbHVkaW5nIGEKbGVzc29uIHBsYW4gaWxsdXN0cmF0aW5nIGhvdyB0aGV5IHBsYW4gdG8gYXBwbHkgdGVjaG5pY2FsIGN1bHR1cmFsCnJlcHJlc2VudGF0aW9uIGFuZC9vciBhbmFseXNpcyBpbiB0aGVpciBvd24gY2xhc3Nyb29tcy4gVGhlIHByb2dyYW0gYWltcwp0byBwcm92aWRlIHRlYWNoZXJzIHdpdGggZXhwZXJpZW5jZXMgcHJhY3RpY2luZyB3aXRoIGN1bHR1cmFsIGZyYW1lcyBhbmQKcmVwcmVzZW50YXRpb25hbCB0b29scywgc28gdGhleSBjYW4gd29yayB3aXRoIHRoZWlyIG93biBzdHVkZW50cyB0bwplbGljaXQgYW5kIHJlcHJlc2VudCBkaXZlcnNlIGN1bHR1cmFsIGlkZW50aXRpZXMgYW5kIHBlcnNwZWN0aXZlcy4KCioqRGF0YSBDb2xsZWN0aW9uIGFuZCBBbmFseXNpcyoqCgpGaXJzdCwgdXNpbmcgcXVhbGl0YXRpdmUgbWV0aG9kcywgdGhlIHJlc2VhcmNoIHRlYW0gYW5hbHl6ZWQgZGF0YQpjb2xsZWN0ZWQgZHVyaW5nIGZvY3VzIGdyb3VwcywgZnJvbSBkaWdpdGFsIHBvcnRmb2xpb3MsIGFuZCBmcm9tCm9ic2VydmF0aW9ucyBkdXJpbmcgdGhlIHByb2Zlc3Npb25hbCBkZXZlbG9wbWVudCBwcm9ncmFtLiBEYXRhIGNvbGxlY3RlZApjb25zaXN0ZWQgb2YgcmVzZWFyY2hlciBtZW1vcywgcHJvamVjdHMgYW5kIGFydGlmYWN0cyBjcmVhdGVkIGJ5IDE5CnRlYWNoZXJzLCBhbmQgcG9zdC1yZWZsZWN0aXZlIGZvY3VzIGdyb3VwcyBhZnRlciB0aGUgcHJvZmVzc2lvbmFsCmRldmVsb3BtZW50IGV4cGVyaWVuY2UuIFVzaW5nIHRoZSB0cmFuc2NyaXB0cyBmcm9tIHRoZSBmb2N1cyBncm91cHMsCnBhcnRpY2lwYW50cycgcG9ydGZvbGlvcywgYW5kIHJlc2VhcmNoZXIgb2JzZXJ2YXRpb25zLCBCcmF1biBhbmQKQ2xhcmtlJ3MgKDIwMjIpIHByb2Nlc3Mgb2YgcmVmbGV4aXZlIHRoZW1hdGljIGFuYWx5c2lzIHRvIGFuYWx5emUgZm9jdXMKZ3JvdXAgZGF0YSB3YXMgdXNlZC7CoAoKSW5pdGlhbCBmaW5kaW5ncyBmcm9tIHRoZW1hdGljIGFuYWx5c2lzIG9mIGZvY3VzIGdyb3VwIGRhdGEgaW5kaWNhdGVkCnRoYXQKCjEuKSBTZWxmLXNlbGVjdGVkIGRpZ2l0YWwgcHJvamVjdHMgYWxsb3dlZCBwYXJ0aWNpcGFudHMgdG8gZGV2ZWxvcAoqKnByb2Zlc3Npb25hbCBrbm93bGVkZ2UqKiByZWxhdGVkIHRvIHRoZWlyIHNwZWNpZmljIHRlYWNoaW5nIGNvbnRlbnQsCmN1cnJpY3VsdW0sIGFuZCBjbGFzc3Jvb207CgoyLikgSW50ZXJuYXRpb25hbCBpbW1lcnNpdmUgZXhwZXJpZW5jZSB3aXRoIHRhcmdldGVkIHByb2Zlc3Npb25hbApkZXZlbG9wbWVudCBwcm92aWRlZCBhbiBvcHBvcnR1bml0eSBmb3IgKipyZWZsZWN0aW9ucyBvbgpwYW5kZW1pYy9wb3N0LXBhbmRlbWljIGluc3RydWN0aW9uKio7IGFuZAoKMy4pIFRlYWNoZXJzIHJlZmxlY3RlZCB0aGF0IHRoZSBleHBlcmllbmNlIGhhZCBhbiBpbXBhY3Qgb24gdGhlaXIKKip0ZWFjaGluZyBkaXNwb3NpdGlvbnMgYW5kIHBsYW5zIGZvciB0aGUgZnV0dXJlLioqCgpUaGlzIHByb2plY3Qgd2lsbCBvdXRsaW5lIGEgc2Vjb25kIHN0ZXAgaW4gdGhpcyBwcm9jZXNzLCBpbiB3aGljaCB0aGUKc2FtZSBkYXRhIHdpbGwgYmUgYW5hbHl6ZWQgdXNpbmcgdG9waWMgbW9kZWxpbmcuIFRvcGljIG1vZGVsaW5nIGlzIGEKbWFjaGluZSBsZWFybmluZyB0ZWNobmlxdWUgdGhhdCBhdXRvbWF0aWNhbGx5IGFuYWx5emVzIHRleHQgZGF0YSB0bwpkZXRlcm1pbmUgY2x1c3RlciB3b3JkcyBmb3IgYSBzZXQgb2YgZG9jdW1lbnRzLiBUaGlzIGlzIGtub3duIGFzCid1bnN1cGVydmlzZWQnIG1hY2hpbmUgbGVhcm5pbmcgYmVjYXVzZSBpdCBkb2Vzbid0IHJlcXVpcmUgYSBwcmVkZWZpbmVkCmxpc3Qgb2YgdGFncyBvciB0cmFpbmluZyBkYXRhIHRoYXQncyBiZWVuIHByZXZpb3VzbHkgY2xhc3NpZmllZCBieQpodW1hbnMuIFRoaXMgYWRkaXRpb25hbCBzdGVwIGluIGFuYWx5emluZyB0aGUgZGF0YSBhZHZhbmNlcyB0aGUgZmllbGQgb2YKcXVhbGl0YXRpdmUgcmVzZWFyY2ggYXMgaXQgb2ZmZXJzIGEgbWVhbnMgb2YgcmVmbGVjdGluZyBvbiB0aGUKY29tcGFyaXNvbiBvZiB0aGUgdHdvIHNldHMgb2YgcmVzdWx0cy4KCiMjIyAxYi4gR3VpZGluZyBRdWVzdGlvbgoKV2l0aCB0aGUgaW5jcmVhc2luZyBhbW91bnQgb2YgcXVhbGl0YXRpdmUgZGF0YSBiZWluZyBnZW5lcmF0ZWQgaW4KcmVzZWFyY2ggc3R1ZGllcywgaXQgaXMgZXNzZW50aWFsIHRvIGhhdmUgZWZmZWN0aXZlIG1ldGhvZHMgZm9yCmFuYWx5emluZyBhbmQgaW50ZXJwcmV0aW5nIHRoaXMgaW5mb3JtYXRpb24uIFRoZSB1c2Ugb2YgdG9waWMgbW9kZWxpbmcKaW4gdGhlIGFuYWx5c2lzIG9mIHRleHR1YWwgZGF0YSBoYXMgZ2FpbmVkIHBvcHVsYXJpdHkgaW4gcmVjZW50IHllYXJzCmR1ZSB0byBpdHMgYWJpbGl0eSB0byBpZGVudGlmeSBoaWRkZW4gdGhlbWVzIGFuZCBwYXR0ZXJucyB3aXRoaW4gbGFyZ2UKZGF0YXNldHMuIFRoaXMgcHJvamVjdCBkZXNjcmliZXMgYSBwb3RlbnRpYWwgbWV0aG9kb2xvZ2ljYWwgYWR2YW5jZW1lbnQKb24gaG93IHRvcGljIG1vZGVsaW5nIGNhbiBiZSB1c2VkIHRvIGFuYWx5emUgcXVhbGl0YXRpdmUgZGF0YS4KClRodXMsIHRoZSBwcmltYXJ5IHJlc2VhcmNoIHF1ZXN0aW9uIGlzOgoKKipXaGF0IGRvZXMgdG9waWMgbW9kZWxpbmcgaW4gdGhlIGFuYWx5c2lzIG9mIHRleHR1YWwgZGF0YSBmcm9tIGZvY3VzCmdyb3VwcyB3aXRoIGluc2VydmljZSB0ZWFjaGVycyBwYXJ0aWNpcGF0aW5nIGluIGludGVybmF0aW9uYWwKcHJvZmVzc2lvbmFsIGRldmVsb3BtZW50IHJldmVhbCBhYm91dCBob3cgdG9waWMgbW9kZWxpbmcgY2FuIGVuaGFuY2UKcXVhbGl0YXRpdmUgcmVzZWFyY2ggZGF0YT8qKgoKIyMgMi4gV1JBTkdMRQoKVG8gYW5hbHl6ZSB0aGUgdGV4dHVhbCBkYXRhIHVzaW5nIHRvcGljIG1vZGVsaW5nLCB0aGUgd29ya2Zsb3cgb2YgdGhlCnByb2Nlc3Mgd2lsbCBpbmNsdWRlIGRhdGEgd3JhbmdsaW5nLCBtb2RlbGluZywgYW5kIGV4cGxvcmF0aW9uIGFzCmZvbGxvd3M6wqAKClRoZSBkYXRhIHdpbGwgYmUgd3JhbmdsZWQsIGEgcHJvY2VzcyB3aGljaCBpbnZvbHZlcyBzb21lIGNvbWJpbmF0aW9uIG9mCmNsZWFuaW5nLCByZXNoYXBpbmcsIHRyYW5zZm9ybWluZywgYW5kIG1lcmdpbmcgZGF0YSAoV2lja2hhbSAmCkdyb2xlbXVuZCwgMjAxNykuIFRoZSB0ZXh0IHdpbGwgYmUgcHJlcHJvY2Vzc2VkLCBpbmNsdWRpbmcgY29udmVydGluZwp0aGUgZGF0YSBpbnRvIGEgdGlkeSB0ZXh0IGZvcm1hdC4gVGhpcyBpbmNsdWRlcyBkYXRhIHRva2VuaXphdGlvbiwKcmVtb3ZhbCBvZiBzdG9wIHdvcmRzLCBhbmQgc3RlbW1pbmcuCgpUaGUgdGV4dCB3aWxsIHRoZW4gYmUgYW5hbHl6ZWQgYnkgZml0dGluZyBhIHRvcGljIG1vZGVsaW5nIGFsZ29yaXRobQp1c2luZyBMYXRlbnQgRGlyaWNobGV0IEFsbG9jYXRpb24gKExEQSkuIFRoZW4gYmV0YSB2YWx1ZXMgd2VyZSBjcmVhdGVkIHRvCmV4cGxvcmUgdGhlIGZpbmRpbmdzLiBBIG51bWJlciBvZiB0b3BpY3Mgd2VyZSBzZWxlY3RlZC4gVGhpcyBwcm9jZXNzIHdhcyByZXBlYXRlZAp1bnRpbCB0aGUgYXBwcm9wcmlhdGUgbnVtYmVyIG9mIHRvcGljcyB3YXMgZGVjaWRlZCB1cG9uLiBXaGlsZSB0b3BpYwptb2RlbGluZyBpbnZvbHZlcyBtYW55IGRlY2lzaW9ucyBhbmQgY2FuIGJlIGFzIG11Y2ggYXJ0IGFzIHNjaWVuY2UKKEJhaWwsIDIwMTgpLCB0aGUgcHVycG9zZSBvZiB0b3BpYyBtb2RlbGluZyBpbiB0aGlzIGNvbnRleHQgd2FzIHRvCmRldmVsb3AgYSBzaW1wbGUgbWF0aGVtYXRpY2FsIHN1bW1hcnkgb2YgdGhlIGRhdGFzZXQgd2hpY2ggY2FuIGhlbHAgZnVydGhlciBleHBsb3JlIHRyZW5kcyBhbmQgcGF0dGVybnMgaW4gdGhlIGRhdGEuCgojIyMgMmEuIFByb2plY3QgU2V0IFVwIGFuZCBJbXBvcnQgSW50ZXJ2aWV3IERhdGEKCmBgYHtyIGxvYWQtcGFja2FnZXMsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHRpZHl0ZXh0KQpsaWJyYXJ5KFNub3diYWxsQykKbGlicmFyeSh0b3BpY21vZGVscykKbGlicmFyeShzdG0pCmxpYnJhcnkobGRhdHVuaW5nKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KExEQXZpcykKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpgYGAKCkFmdGVyIHNldHRpbmcgdXAgdGhlIHByb2plY3QgaW4gUiwgdGhlIGRhdGEgd2lsbCBiZSBpbXBvcnRlZCBpbnRvIFIuCgpgYGB7ciByZWFkLWNzdn0KQ0lEUkVfaW50ZXJ2aWV3cyA8LSByZWFkX2NzdigiZGF0YS9JbmRlcGVuZGVudCBBbmFseXNpcyBBcHJpbCAxOCAyMDIzLmNzdiIsIAogICAgIGNvbF90eXBlcyA9IGNvbHMoCiAgICAgICAgICAgICAgICAgICBJbnRlcnZpZXcgPSBjb2xfY2hhcmFjdGVyKCksIAogICAgICAgICAgICAgICAgICAgSW50ZXJ2aWV3ZWUgPSBjb2xfY2hhcmFjdGVyKCksIAogICAgICAgICAgICAgICAgICAgVG9waWMgPSBjb2xfY2hhcmFjdGVyKCkKICAgICAgICAgICAgICAgICAgICkKICAgICkKCkNJRFJFX2ludGVydmlld3MgPC0gQ0lEUkVfaW50ZXJ2aWV3cyAlPiUgCiAgICBtdXRhdGUoSW50ZXJ2aWV3ID0gc3Ryc3BsaXQoYXMuY2hhcmFjdGVyKEludGVydmlldyksICJcblxuXG4iKSkgJT4lIAogICAgdW5uZXN0KEludGVydmlldykKCkNJRFJFX2ludGVydmlld3MKYGBgCgojIyMgMmIuIENhc3QgYSBEb2N1bWVudCBUZXJtIE1hdHJpeAoKVGhlIHRleHQgd2FzIHByZXByb2Nlc3NlZCwgaW5jbHVkaW5nIGNvbnZlcnRpbmcgdGhlIGRhdGEgaW50byBhIHRpZHkKdGV4dCBmb3JtYXQuIFRoaXMgaW5jbHVkZWQgZGF0YSB0b2tlbml6YXRpb24gYW5kIHJlbW92YWwgb2Ygc3RvcCB3b3Jkcy4KCkZpcnN0LCB0aGUgdGV4dCB3YXMgdG9rZW5pemVkIGFuZCBzdG9wIHdvcmRzIHdlcmUgcmVtb3ZlZC4gQWRkaXRpb25hbApzdG9wIHdvcmRzIHdlcmUgYWRkZWQgc3VjaCBhczogbGlrZSwganVzdCwgd2VsbCwgeWVhaCwgbG90LCBzdHVmZiwgZ29ubmEKCmBgYHtyIHRva2VuaXplLWludGVydmlld3N9CmludGVydmlld3NfdGlkeSA8LSBDSURSRV9pbnRlcnZpZXdzICU+JSAKICB1bm5lc3RfdG9rZW5zKG91dHB1dCA9IHdvcmQsIGlucHV0ID0gSW50ZXJ2aWV3KSAlPiUKICBhbnRpX2pvaW4oc3RvcF93b3JkcywgYnkgPSAid29yZCIpICU+JQogIGZpbHRlcighd29yZCA9PSAibG90IiYgIXdvcmQgPT0gInN0dWZmIiYgIXdvcmQgPT0gImdvbm5hIiYgIXdvcmQgPT0gImxpa2UiJiAhd29yZCA9PSAianVzdCImICF3b3JkID09ICJ3ZWxsIiYgIXdvcmQgPT0gInllYWgiKSAKCgoKaW50ZXJ2aWV3c190aWR5CmBgYAoKQSB3b3JkIGNvdW50IHRvIGRldGVybWluZSB0aGUgbW9zdCBjb21tb24gd29yZHMgaW4gdGhlIGludGVydmlld3Mgd2FzCmNvbmR1Y3RlZC4gVGhlc2Ugd29yZCBjb3VudHMgd291bGQgYmUgbGF0ZXIgdXNlZCBmb3IgY3JlYXRpbmcgYSBkb2N1bWVudAp0ZXJtIG1hdHJpeCBmb3IgdG9waWMgbW9kZWxpbmcuCgpgYGB7ciBjb3VudC13b3Jkc30KaW50ZXJ2aWV3c190aWR5ICU+JQogIGNvdW50KHdvcmQsIHNvcnQgPSBUUlVFKQpgYGAKClRoZSB0ZXJtcyAicGVvcGxlLCIgImZlZWwsIiAidGltZSwiIGFuZCAiZXhwZXJpZW5jZSIgZW1lcmdlZCBhcyBtb3N0CmNvbW1vbiwgcmVmbGVjdGluZyB0aGF0IHRoZSBzdHVkeSB0b3BpYyB3YXMgYW4gaW50ZXJuYXRpb25hbCBsZWFybmluZwpleHBlcmllbmNlLiBUaGUgdGVybXMgImNvbW11bml0eSwiICJjb25uZWN0aW9ucyIgYW5kICJwcm9mZXNzaW9uYWwiIGFyZQp3b3J0aCBhdHRlbnRpb24gYXMgd2VsbC4gVGhlIHRlcm1zICJ3aGl0ZSIgd2l0aCAxNCBpbnN0YW5jZXMgYW5kCiJibGFjaywiIHdpdGggMTMgaW5zdGFuY2VzIHN1Z2dlc3RzIHRoZSBwb3RlbnRpYWwgdG8gCnRvIGV4cGxvcmUgYSBwb3RlbnRpYWwgdGhlbWUgb2YgcmFjZS4KCgoKIyMjIyBDcmVhdGluZyBhIERvY3VtZW50IFRlcm0gTWF0cml4CgpFYWNoIGludGVydmlldyBncm91cCB3YXMgdHJlYXRlZCBhcyBhIHVuaXF1ZSBkb2N1bWVudCwgd2l0aCBhIHRvdGFsIG9mCnRlbiBkb2N1bWVudHMgd2l0aCAyNzU5IHRlcm1zLiBVc2luZyB0aGUgZXhpc3Rpbmcgd29yZCBjb3VudHMsIGEgbWF0cml4CndhcyBjcmVhdGVkIHRoYXQgY29udGFpbmVkIGEgY29sdW1uIGZvciBlYWNoIHdvcmQgaW4gdGhlIGNvcnB1cyBhbmQgYQp2YWx1ZSBvZiBuIGZvciBob3cgbWFueSB0aW1lcyB0aGF0IHdvcmQgb2NjdXJzIGluIGVhY2ggcG9zdC4KClRvIGNyZWF0ZSB0aGlzIGRvY3VtZW50IHRlcm0gbWF0cml4IGZyb20gdGhlIGludGVydmlldyBjb3VudHMsIHRoZQpjYXN0X2R0bSgpIGZ1bmN0aW9uIHdhcyB1c2VkIGFuZCBhc3NpZ25lZCB0byB0aGUgdmFyaWFibGUKaW50ZXJ2aWV3c19kdG0uCgpgYGB7ciBjYXN0LWR0bX0KaW50ZXJ2aWV3c19kdG0gPC0gaW50ZXJ2aWV3c190aWR5ICU+JQogIGNvdW50KFRvcGljLCB3b3JkKSAlPiUKICBjYXN0X2R0bShUb3BpYywgd29yZCwgbikKYGBgCgpgYGB7ciBjbGFzcy1kdG0sIGVjaG89RkFMU0V9CmNsYXNzKGludGVydmlld3NfZHRtKQoKaW50ZXJ2aWV3c19kdG0KYGBgCgojIyMgMmMuIFByZXByb2Nlc3NpbmcgYW5kIChub3QpIFN0ZW1taW5nCgpOZXh0IHRoZSBvcmlnaW5hbCBkYXRhIHNldCBmb3Igc3RydWN0dXJhbCB0b3BpYyBtb2RlbGluZyB3YXMgcHJlcGFyZWQKdXNpbmcgdGhlIGB0ZXh0UHJvY2Vzc29yKClgIGZ1bmN0aW9uIHRvIHJlbW92ZSBwdW5jdHVhdGlvbiBlbGVtZW50cyBhbmQKc3RvcCB3b3JkcyB0byBzaW1wbGlmeSByZXN1bHRzLgoKYGBge3IgdGV4dFByb2Nlc3Nvcn0KdGVtcCA8LSB0ZXh0UHJvY2Vzc29yKENJRFJFX2ludGVydmlld3MkSW50ZXJ2aWV3LCAKICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YSA9IENJRFJFX2ludGVydmlld3MsICAKICAgICAgICAgICAgICAgICAgICBsb3dlcmNhc2U9VFJVRSwgCiAgICAgICAgICAgICAgICAgICAgcmVtb3Zlc3RvcHdvcmRzPVRSVUUsIAogICAgICAgICAgICAgICAgICAgIHJlbW92ZW51bWJlcnM9VFJVRSwgIAogICAgICAgICAgICAgICAgICAgIHJlbW92ZXB1bmN0dWF0aW9uPVRSVUUsIAogICAgICAgICAgICAgICAgICAgIHdvcmRMZW5ndGhzPWMoMyxJbmYpLAogICAgICAgICAgICAgICAgICAgIHN0ZW09VFJVRSwKICAgICAgICAgICAgICAgICAgICBvbmx5Y2hhcmFjdGVyPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgc3RyaXBodG1sPVRSVUUsIAogICAgICAgICAgICAgICAgICAgIGN1c3RvbXN0b3B3b3Jkcz1OVUxMKQpgYGAKClN0ZW1taW5nIHdhcyBjb25zaWRlcmVkIGFzIGEgcHJlcHJvY2Vzc2luZyBzdGVwIHRvIHJlZHVjZSB0aGUgc2l6ZSBvZgp0aGUgdm9jYWJ1bGFyeSBpbiBuYXR1cmFsIGxhbmd1YWdlIGFuZCB0aHVzIHNpbXBsaWZ5IHRoZSBtb2RlbC4gU3RlbW1pbmcKcmVkdWNlZCB0aGUgbnVtYmVyIG9mIHRlcm1zIGZyb20gMjkyMCB0byAyMjQxLiBUaGlzIHJlZHVjdGlvbiBpbiBjb3JwdXMKc2l6ZSBvZiA2NzkgdGVybXMgZG9lcyBub3QganVzdGlmeSB0aGUgcmlzayBvZiBsb3Npbmcgc3VidGxldGllcyBpbgptZWFuaW5nIGJldHdlZW4gd29yZHMgd2l0aCBzaW1pbGFyIHdvcmQgc3RlbXMsIHN1Y2ggYXMgInN1cHBvcnQiIGFuZAoic3VwcG9ydGVkIiB0aGF0IHdvdWxkIGJlIHJlbGV2YW50IHRvIHRoZSBmaW5kaW5ncyBvZiB0aGUgc3R1ZHkuClRoZXJlZm9yZSwgdGhpcyBwcm9qZWN0IGRvZXMgbm90IHVzZSBzdGVtbWluZy4KCmBgYHtyIHN0bS1pbnB1dHN9Cm1ldGEgPC0gdGVtcCRtZXRhCnZvY2FiIDwtIHRlbXAkdm9jYWIKZG9jcyA8LSB0ZW1wJGRvY3VtZW50cwpgYGAKCiMjIDMuIE1PREVMCgpUaGUgdGV4dCB3YXMgbW9kZWxlZCB0byBjcmVhdGUgYSBtYXRoZW1hdGljYWwgc3VtbWFyeSBvZiB0aGUgZGF0YXNldC4KVGhlIHJlc3VsdGluZyBzdW1tYXJpZXMgY2FuIGhlbHAgdHJlbmRzIGFuZCBwYXR0ZXJucyBpbiB0aGUgZGF0YSB0bwpzdXJmYWNlLCBwYXJ0aWN1bGFybHkgd2hlbiBjb21wYXJlZCB0byB0aGVtYXRpYyBhbmFseXNpcy4gVG9waWMgTW9kZWxpbmcKaXMgYW4gdW5zdXBlcnZpc2VkIGxlYXJuaW5nIGFwcHJvYWNoIHRoYXQgY2FuIHByb3ZpZGUgaW5zaWdodCBpbnRvIHRoZQpzdHJ1Y3R1cmUgb2YgdGhlIGRhdGFzZXQuCgpUaHJlZSBzdGVwcyB3ZXJlIHVuZGVydGFrZW46CgphLiAgKipGaXR0aW5nIGEgVG9waWMgTW9kZWxpbmcgd2l0aCBMREEqKi4gVGhlIGB0b3BpY21vZGVsc2AgcGFja2FnZSBhbmQKICAgIGFzc29jaWF0ZWQgYExEQSgpYCBmdW5jdGlvbiBmb3IgdW5zdXBlcnZpc2VkIGNsYXNzaWZpY2F0aW9uIG9mIHRoZQogICAgaW50ZXJ2aWV3IGRhdGEgd2FzIHVzZWQgdG8gZmluZCBuYXR1cmFsIGdyb3VwaW5ncyBvZiB3b3Jkcywgb3IKICAgIHRvcGljcy4KYi4gICoqRml0dGluZyBhIFN0cnVjdHVyYWwgVG9waWMgTW9kZWwqKi4gVGhlIGBzdG1gIHBhY2thZ2UgYW5kIGBzdG0oKWAKICAgIGZ1bmN0aW9uIHdlcmUgdXNlZCB0byBmaXQgb3VyIG1vZGVsIGFuZCB1c2VkIG1ldGFkYXRhIGFib3V0CiAgICBkb2N1bWVudHMgdG8gaW1wcm92ZSB0aGUgYXNzaWdubWVudCBvZiB3b3JkcyB0byAidG9waWNzIiBpbiB0aGUKICAgIGNvcnB1cy4KYy4gICoqQ2hvb3NpbmcgSy4qKiBGaW5hbGx5LCBhbiBhcHByb3ByaWF0ZSBudW1iZXIgb2YgdG9waWNzIHdhcwogICAgc2VsZWN0ZWQuCgojIyMgM2EuIEZpdHRpbmcgYSBUb3BpYyBNb2RlbGluZyB3aXRoIExEQQoKVGhlIExEQSBmdW5jdGlvbiBvciBMYXRlbnQgRGlyaWNobGV0IGFsbG9jYXRpb24gd2FzIHVzZWQgYmVjYXVzZSBldmVyeQpkb2N1bWVudCBjb250YWlucyBhIG1peHR1cmUgb2YgdG9waWNzIGFuZCBldmVyeSB0b3BpYyBjb250YWlucyBhIG1peHR1cmUKb2Ygd29yZHMuIFRoaXMgbWVhbnMgdGhhdCBhIGZvY3VzIGdyb3VwIGludGVydmlldyBjb3VsZCBoYXZlIGFuCmVzdGltYXRlZCB0b3BpYyBwcm9wb3J0aW9uIG9mIDgwJSBmb3IgVG9waWMgMSBidXQgYWxzbyBiZSBwYXJ0bHkgYWJvdXQKdG9waWMgMi4gTGlrZXdpc2UsIHdvcmRzIGNhbiBiZSBzaGFyZWQgYmV0d2VlbiB0b3BpY3MgYW5kIHdvcmRzIGdlcm1hbmUKdG8gdGhlIHRvcGljIHN1Y2ggYXMgImNvbW11bml0eSIgYW5kICJsYW5ndWFnZSIgbWlnaHQgYXBwZWFyIGluIGFuCmluZGl2aWR1YWwgdG9waWMgZXF1YWxseS4KCkxEQSByZXF1aXJlcyBhIGsgdmFsdWUgdG8gYmUgc3BlY2lmaWVkIGZvciB0aGUgbnVtYmVyIG9mIHRvcGljcyBpbiB0aGUKZm9jdXMgZ3JvdXAgaW50ZXJ2aWV3cy4gSyB3YXMgc2VsZWN0ZWQgYXMgMjAgYXMgYSBzdGFydGluZyBwb2ludC4gSyB3YXMKdGhlbiBydW4gYXMgMTUgYnkgd2F5IG9mIGNvbXBhcmlzb24uCgpgYGB7ciBMREF9CgppbnRlcnZpZXdzX2xkYSA8LSBMREEoaW50ZXJ2aWV3c19kdG0sIAogICAgICAgICAgICAgICAgICBrID0gMjAsCiAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KHNlZWQgPSA1ODgpCiAgICAgICAgICAgICAgICAgICkKCmludGVydmlld3NfbGRhCmBgYAoKYGBge3J9CmFwX3RvcGljcyA8LSB0aWR5KGludGVydmlld3NfbGRhLCBtYXRyaXggPSAiYmV0YSIpCmFwX3RvcF90ZXJtcyA8LSBhcF90b3BpY3MgJT4lCiAgZ3JvdXBfYnkodG9waWMpICU+JQogIHNsaWNlX21heChiZXRhLCBuID0gNikgJT4lIAogIHVuZ3JvdXAoKSAlPiUKICBhcnJhbmdlKHRvcGljLCAtYmV0YSkKCmFwX3RvcF90ZXJtcyAlPiUKICBtdXRhdGUodGVybSA9IHJlb3JkZXJfd2l0aGluKHRlcm0sIGJldGEsIHRvcGljKSkgJT4lCiAgZ2dwbG90KGFlcyhiZXRhLCB0ZXJtLCBmaWxsID0gZmFjdG9yKHRvcGljKSkpICsKICBnZW9tX2NvbChzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZmFjZXRfd3JhcCh+IHRvcGljLCBzY2FsZXMgPSAiZnJlZSIpICsKICBzY2FsZV95X3Jlb3JkZXJlZCgpCmBgYApMREEgZW1wbG95cyB0aGUgVGVybSBGcmVxdWVuY3ktSW52ZXJzZSBEb2N1bWVudCBGcmVxdWVuY3kgKFRGLUlERikKbWV0cmljIHRvIGFzc2lnbiBwcm9iYWJpbGl0aWVzLgoKIyMjIDNiLiBGaXR0aW5nIGEgU3RydWN0dXJhbCBUb3BpYyBNb2RlbAoKQmFpbCAoMjAxOCkgYXJndWVzIHRoYXQgb25lIHJlYXNvbiBTVE0gaGFzIHJpc2luZyBpbiBwb3B1bGFyaXR5IGFuZCB1c2UgaXMgdGhhdCBpdCBlbXBsb3lzIG1ldGEgZGF0YSBhYm91dCBkb2N1bWVudHMgdG8gaW1wcm92ZSB0aGUgYXNzaWdubWVudCBvZiB3b3JkcyB0byB0b3BpY3MgaW4gYSBjb3JwdXMgYW5kIHRoYXQgY2FuIGJlIHVzZWQgdG8gZXhhbWluZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gY292YXJpYXRlcyBhbmQgZG9jdW1lbnRzLiBUaGlzIHdhcyB1c2VmdWwgZm9yIHRoaXMgcHJvamVjdCBpbiBjb25maXJtaW5nIHRoYXQgdG9waWNzIHJlbGF0ZWQgdG8gdGhlbWVzIHJldmVhbGVkIGluIHF1YWx0aXRhdGl2ZSBkYXRhLiAKCiMjIyMgVGhlIGBzdG1gIFBhY2thZ2UKCkJlZm9yZSBmaXR0aW5nIGFuIFNUTSBtb2RlbCwgaXQgd2FzIG5lY2Vzc2FyeSB0byBleHRyYWN0IHRoZSBmb2xsb3dpbmcgZWxlbWVudHM6CgpgYGB7ciBzdG0tZG9jc30KZG9jcyA8LSB0ZW1wJGRvY3VtZW50cyAKbWV0YSA8LSB0ZW1wJG1ldGEgCnZvY2FiIDwtIHRlbXAkdm9jYWIgCmBgYAoKVGhlc2UgZWxlbWVudHMgd2VyZSB0aGVuIHVzZWQgdG8gZml0IHRoZSBtb2RlbCB1c2luZyB0aGUgc2FtZSB0b3BpY3MgZm9yICpLKiB0aGF0IHdlcmUgc3BlY2lmaWVkIGZvciB0aGUgTERBIHRvcGljIG1vZGVsLiAKCmBgYHtyIHN0bX0KaW50ZXJ2aWV3c19zdG0gPC0gc3RtKGRvY3VtZW50cz1kb2NzLCAKICAgICAgICAgZGF0YT1tZXRhLAogICAgICAgICB2b2NhYj12b2NhYiwgCiAgICAgICAgIEs9MjAsCiAgICAgICAgIG1heC5lbS5pdHM9MjUsCiAgICAgICAgIHZlcmJvc2UgPSBGQUxTRSkKCmludGVydmlld3Nfc3RtCmBgYAoKVGhlIGZ1bmN0aW9uIGFsbG93cyBmb3Igdmlld2luZyB0aGUgbW9zdCBwcm9iYWJsZSB3b3JkcyBhc3NpZ25lZCB0byBlYWNoIHRvcGljLgoKYGBge3IgcGxvdC1zdG19CnBsb3QuU1RNKGludGVydmlld3Nfc3RtLCBuID0gNSkKYGBgCgoKYGBge3IgcGxvdH0KcGxvdChpbnRlcnZpZXdzX3N0bSwgbiA9IDUpCmBgYAoKIyMjIyMgCgojIyMgM2MuIEZpbmRpbmcgKksqCgpBcyBhbGx1ZGVkIHRvIGVhcmxpZXIsIHNlbGVjdGluZyB0aGUgbnVtYmVyIG9mIHRvcGljcyBmb3IgeW91ciBtb2RlbCBpcwphIG5vbi10cml2aWFsIGRlY2lzaW9uIGFuZCBjYW4gZHJhbWF0aWNhbGx5IGltcGFjdCB5b3VyIHJlc3VsdHMuIEJhaWwKKDIwMTgpIG5vdGVzIHRoYXQKCj4gKlRoZSByZXN1bHRzIG9mIHRvcGljIG1vZGVscyBzaG91bGQgbm90IGJlIG92ZXItaW50ZXJwcmV0ZWQgdW5sZXNzIHRoZQo+IHJlc2VhcmNoZXIgaGFzIHN0cm9uZyB0aGVvcmV0aWNhbCBhcHJpb3JpIGFib3V0IHRoZSBudW1iZXIgb2YgdG9waWNzCj4gaW4gYSBnaXZlbiBjb3JwdXMsIG9yIGlmIHRoZSByZXNlYXJjaGVyIGhhcyBjYXJlZnVsbHkgdmFsaWRhdGVkIHRoZQo+IHJlc3VsdHMgb2YgYSB0b3BpYyBtb2RlbCB1c2luZyBib3RoIHRoZSBxdWFudGl0YXRpdmUgYW5kIHF1YWxpdGF0aXZlCj4gdGVjaG5pcXVlcyBkZXNjcmliZWQgYWJvdmUuKgoKCiMjIyMgVGhlIEZpbmRUb3BpY3NOdW1iZXIgRnVuY3Rpb24KClRoZSBgbGRhdHVuaW5nYCBwYWNrYWdlIHdhcyB1c2VkIHRvIGFzc2lzdCB3aXRoIGZpbmRpbmcgSyB2YWx1ZS4KCmBgYHtyIGZpbmQtdG9waWMsIGV2YWw9RkFMU0V9CmtfbWV0cmljcyA8LSBGaW5kVG9waWNzTnVtYmVyKAogIGludGVydmlld3NfZHRtLAogIHRvcGljcyA9IHNlcSgxMCwgNzUsIGJ5ID0gNSksCiAgbWV0cmljcyA9ICJHcmlmZml0aHMyMDA0IiwKICBtZXRob2QgPSAiR2liYnMiLAogIGNvbnRyb2wgPSBsaXN0KCksCiAgbWMuY29yZXMgPSBOQSwKICByZXR1cm5fbW9kZWxzID0gRkFMU0UsCiAgdmVyYm9zZSA9IEZBTFNFLAogIGxpYnBhdGggPSBOVUxMCikKCkZpbmRUb3BpY3NOdW1iZXJfcGxvdChrX21ldHJpY3MpCmBgYAoKTm90ZSB0aGF0IHRoZSBgRmluZFRvcGljTnVtYmVycygpYCBmdW5jdGlvbiBjb250YWlucyB0aHJlZSBhZGRpdGlvbmFsCm1ldHJpY3MgZm9yIGNhbGN1bGF0aW5nIG1ldHJpY3MgdGhhdCBjYW4gYmUgdXNlZCB0byBlc3RpbWF0ZSB0aGUgbW9zdApwcmVmZXJhYmxlIG51bWJlciBvZiB0b3BpY3MgZm9yIExEQSBtb2RlbC4gV2UgdXNlZCB0aGUgR3JpZmZpdGhzMjAwNAptZXRyaWNzIGluY2x1ZGVkIGluIHRoZSBkZWZhdWx0IGV4YW1wbGUgYW5kIEkndmUgYWxzbyBmb3VuZCB0aGlzIHRvCnByb2R1Y2UgdGhlIG1vc3QgaW50ZXJwcmV0YWJsZSByZXN1bHRzIGFzIHNob3cgaW4gdGhlIGZpZ3VyZSBiZWxvdzoKCiFbXShpbWcva19tZXRyaWNzLnBuZyl7d2lkdGg9IjkwJSJ9CgpBcyBhIGdlbmVyYWwgcnVsZSBvZiB0aHVtYiBhbmQgb3Zlcmx5IHNpbXBsaXN0aWMgaGV1cmlzdGljLCB3ZSdyZQpsb29raW5nIGZvciBhbiBpbmZsZWN0aW9uIHBvaW50IGluIG91ciBwbG90IHdoaWNoIGluZGljYXRlcyBhbiBvcHRpbWFsCm51bWJlciBvZiB0b3BpY3MgdG8gc2VsZWN0IGZvciBhIHZhbHVlIG9mIEsuCgojIyMjIFRoZSBMREF2aXMgRXhwbG9yZXIKClRoZSBMREF2aXMgZXhwbG9yZXJlIHdhcyB1c2VkIHRvIGV4cG9yZSB0b3BpYyBhbmQgd29yZCBkaXN0cmlidXRpb25zLgoKYGBge3IgTERBdmlzfQp0b0xEQXZpcyhtb2QgPSBpbnRlcnZpZXdzX3N0bSwgZG9jcyA9IGRvY3MpCmBgYAoKIyMgNC4gRVhQTE9SRSAmIE1PREVMCgpTaWxnZSBhbmQgUm9iaW5zb24gKDIwMTgpIG5vdGUgdGhhdCBmaXR0aW5nIGF0IHRvcGljIG1vZGVsIGlzIHRoZSAiZWFzeQpwYXJ0LiIgVGhlIGhhcmQgcGFydCBpcyBtYWtpbmcgc2Vuc2Ugb2YgdGhlIG1vZGVsIHJlc3VsdHMgYW5kIHRoYXQgdGhlCnJlc3Qgb2YgdGhlIGFuYWx5c2lzIGludm9sdmVzIGV4cGxvcmluZyBhbmQgaW50ZXJwcmV0aW5nIHRoZSBtb2RlbCB1c2luZwphIHZhcmlldHkgb2YgYXBwcm9hY2hlcyB3aGljaCB3ZSdsbCB3YWxrdGhyb3VnaCBpbiBpbiB0aGlzIHNlY3Rpb24uCgpCYWlsICgyMDE4KSBjYXV0aW9ucywgaG93ZXZlciwgdGhhdDoKCj4gKi4uLnBvc3QtaG9jIGludGVycHJldGF0aW9uIG9mIHRvcGljIG1vZGVscyBpcyByYXRoZXIgZGFuZ2Vyb3VzLi4uIGFuZAo+IGNhbiBxdWlja2x5IGNvbWUgdG8gcmVzZW1ibGUgdGhlIHByb2Nlc3Mgb2YgInJlYWRpbmcgdGVhIGxlYXZlcywiIG9yCj4gZmluZGluZyBtZWFuaW5nIGluIHBhdHRlcm5zIHRoYXQgYXJlIGluIGZhY3QgcXVpdGUgYXJiaXRyYXJ5IG9yIGV2ZW4KPiByYW5kb20uKgoKIyMjIDRhLiBFeHBsb3JpbmcgQmV0YSBWYWx1ZXMKClRoZSA1IG1vc3QgbGlrZWx5IHRlcm1zIGFzc2lnbmVkIHRvIGVhY2ggdG9waWMgd2VyZSBleHBsb3JlZC4gVGhlc2UgcGVyLXRvcGljLXBlci13b3JkIHByb2JhYmlsaXRpZXMsIG9yICDOsiAoImJldGEiKSB2YWx1ZXMgcHJvdmlkZSB0aGUgcHJvYmFiaWxpdHkgb2YgYSB0ZXJtICh3b3JkKSBiZWxvbmdpbmcgdG8gYSB0b3BpYy4KCgpgYGB7ciB0ZXJtc30KdGVybXMoaW50ZXJ2aWV3c19sZGEsIDUpCmBgYAoKVG9waWMgMTAgKGV4cGVyaWVuY2UsIHRpbWUsIHBlb3BsZSwgY29vbCwKR2VybWFueSkgc2VlbXMgdG8gYmUgYWJvdXQgcGFydGljaXBhbnRzIGV4cGVyaWVuY2UgaW4gR2VybWFueS5UaGlzIGNvcnJlbGF0ZXMgd2l0aCB0aGUga2luZCBvZiBkYXRhIGZvdW5kIGluIHF1YWxpdGF0aXZlIHJlc2VhcmNoIG9uIHRoZSBzYW1lIGRhdGEuIAoKYGBge3IgdGlkeV9sZGF9Cgp0aWR5X2xkYSA8LSB0aWR5KGludGVydmlld3NfbGRhKQoKdGlkeV9sZGEKYGBgCgoKYGBge3IgdG9wX3Rlcm1zfQoKdG9wX3Rlcm1zIDwtIHRpZHlfbGRhICU+JQogIGdyb3VwX2J5KHRvcGljKSAlPiUKICBzbGljZV9tYXgoYmV0YSwgbiA9IDUsIHdpdGhfdGllcyA9IEZBTFNFKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgYXJyYW5nZSh0b3BpYywgLWJldGEpCgp0b3BfdGVybXMgJT4lCiAgbXV0YXRlKHRlcm0gPSByZW9yZGVyX3dpdGhpbih0ZXJtLCBiZXRhLCB0b3BpYykpICU+JQogIGdyb3VwX2J5KHRvcGljLCB0ZXJtKSAlPiUgICAgCiAgYXJyYW5nZShkZXNjKGJldGEpKSAlPiUgIAogIHVuZ3JvdXAoKSAlPiUKICBnZ3Bsb3QoYWVzKGJldGEsIHRlcm0sIGZpbGwgPSBhcy5mYWN0b3IodG9waWMpKSkgKwogIGdlb21fY29sKHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV95X3Jlb3JkZXJlZCgpICsKICBsYWJzKHRpdGxlID0gIlRvcCA1IHRlcm1zIGluIGVhY2ggTERBIHRvcGljIiwKICAgICAgIHggPSBleHByZXNzaW9uKGJldGEpLCB5ID0gTlVMTCkgKwogIGZhY2V0X3dyYXAofiB0b3BpYywgbmNvbCA9IDQsIHNjYWxlcyA9ICJmcmVlIikKYGBgCgojIyMgCgojIyA1LiBDT01NVU5JQ0FURQoKQXMgU2lsZ2UgYW5kIFJvYmluc29uIG5vdGUgKDIwMTgpLCBmaXR0aW5nIHRoZSB0b3BpYyBtb2RlbCBpcyBlYXN5CnJlbGF0aXZlIHRvIHRoZSBtb3JlIGNoYWxsZW5naW5nIHdvcmsgb2YgaW50ZXJwcmV0aW5nIHRoZSBtb2RlbCByZXN1bHRzLgoKQ29tcGFyaW5nIHJlc3VsdHMgb2YgdGhlbWF0aWMgYW5hbHlzaXMgY29uZHVjdGVkIGJ5IHJlc2VhcmNoZXJzIHRvIHRvcGljCm1vZGVsaW5nIGNvbmR1Y3RlZCBpbiBSIGNhbiBwcm92aWRlIGluc2lnaHRzIGludG8gdGhlIGxpbWl0YXRpb25zIGFuZApiZW5lZml0cyBvZiBib3RoIGZvcm1zIG9mIHF1YWxpdGF0aXZlIHJlc2VhcmNoLiBBcyBCYWlsICgyMDE4KSB3YXJucywKIi4uLnBvc3QtaG9jIGludGVycHJldGF0aW9uIG9mIHRvcGljIG1vZGVscyBpcyByYXRoZXIgZGFuZ2Vyb3VzLi4uIGFuZApjYW4gcXVpY2tseSBjb21lIHRvIHJlc2VtYmxlIHRoZSBwcm9jZXNzIG9mICdyZWFkaW5nIHRlYSBsZWF2ZXMsJyBvcgpmaW5kaW5nIG1lYW5pbmcgaW4gcGF0dGVybnMgdGhhdCBhcmUgaW4gZmFjdCBxdWl0ZSBhcmJpdHJhcnkgb3IgZXZlbgpyYW5kb20uIgoKVGhlIHNhbWUgZGVzY3JpcHRpb24gY291bGQgYmUgYXBwbGllZCB0byB0aGVtYXRpYyBhbmFseXNpcywgYSBwcm9jZXNzCndoaWNoIGlzIGNyZWF0aXZlLCB0aW1lIGNvbnN1bWluZywgYW5kIGNhbiByZWZsZWN0IHRoZSBiaWFzZXMgb2YgdGhlCnJlc2VhcmNoZXJzLiBCeSBjb21wYXJpbmcgdGhlIHJlc3VsdHMgb2YgYm90aCBhcHByb2FjaGVzLCByZXNlYXJjaGVycwphbmQgcHJhY3RpdGlvbmVycyBjYW4gZ2FpbiBhIGRlZXBlciB1bmRlcnN0YW5kaW5nIG9mIHRoZSBkYXRhIGFuZCB0aGUKY29udGV4dCBpbiB3aGljaCBpdCB3YXMgY29sbGVjdGVkLiBUaGlzIGNhbiBsZWFkIHRvIHRyYW5zZm9ybWF0aXZlCmluc2lnaHRzIGludG8gaG93IHF1YWxpdGF0aXZlIHJlc2VhcmNoIGNhbiBiZSBjb25kdWN0ZWQgaW4gYSBtb3JlCnJpZ29yb3VzIGFuZCBzeXN0ZW1hdGljIG1hbm5lciwgd2hpbGUgc3RpbGwgYWxsb3dpbmcgZm9yIHRoZSBjcmVhdGl2aXR5CmFuZCBzdWJqZWN0aXZpdHkgdGhhdCBhcmUgaW5oZXJlbnQgaW4gdGhpcyB0eXBlIG9mIHJlc2VhcmNoLiBNb3Jlb3ZlciwKcmVmbGVjdGluZyBvbiB0aGUgbGltaXRhdGlvbnMgYW5kIGJlbmVmaXRzIG9mIGJvdGggdGhlbWF0aWMgYW5hbHlzaXMgYW5kCnRvcGljIG1vZGVsaW5nIGNhbiBoZWxwIHJlc2VhcmNoZXJzIGFuZCBwcmFjdGl0aW9uZXJzIHRvIGlkZW50aWZ5IGFyZWFzCmZvciBpbXByb3ZlbWVudCBpbiB0aGVpciBvd24gcmVzZWFyY2ggcHJhY3RpY2VzLCBhcyB3ZWxsIGFzIHByb3ZpZGUKZ3VpZGFuY2UgZm9yIGZ1dHVyZSByZXNlYXJjaCBzdHVkaWVzLiBVbHRpbWF0ZWx5LCB0aGlzIGNhbiBsZWFkIHRvIG1vcmUKcm9idXN0IGFuZCBtZWFuaW5nZnVsIHF1YWxpdGF0aXZlIHJlc2VhcmNoIHRoYXQgY29udHJpYnV0ZXMgdG8gdGhlCmFkdmFuY2VtZW50IG9mIGtub3dsZWRnZSBpbiBhIHJhbmdlIG9mIGZpZWxkcy4KCgpJbml0aWFsIGZpbmRpbmdzIGZyb20gdGhlbWF0aWMgYW5hbHlzaXMgb2YgZm9jdXMgZ3JvdXAgZGF0YSBpbmRpY2F0ZWQKdGhhdAoKMS4pIFNlbGYtc2VsZWN0ZWQgZGlnaXRhbCBwcm9qZWN0cyBhbGxvd2VkIHBhcnRpY2lwYW50cyB0byBkZXZlbG9wCioqcHJvZmVzc2lvbmFsIGtub3dsZWRnZSoqIHJlbGF0ZWQgdG8gdGhlaXIgc3BlY2lmaWMgdGVhY2hpbmcgY29udGVudCwKY3VycmljdWx1bSwgYW5kIGNsYXNzcm9vbTsKCjIuKSBJbnRlcm5hdGlvbmFsIGltbWVyc2l2ZSBleHBlcmllbmNlIHdpdGggdGFyZ2V0ZWQgcHJvZmVzc2lvbmFsCmRldmVsb3BtZW50IHByb3ZpZGVkIGFuIG9wcG9ydHVuaXR5IGZvciAqKnJlZmxlY3Rpb25zIG9uCnBhbmRlbWljL3Bvc3QtcGFuZGVtaWMgaW5zdHJ1Y3Rpb24qKjsgYW5kCgozLikgVGVhY2hlcnMgcmVmbGVjdGVkIHRoYXQgdGhlIGV4cGVyaWVuY2UgaGFkIGFuIGltcGFjdCBvbiB0aGVpcgoqKnRlYWNoaW5nIGRpc3Bvc2l0aW9ucyBhbmQgcGxhbnMgZm9yIHRoZSBmdXR1cmUuKioKCkNvbXBhcmluZyB0b3BpY3MgdG8gaW50aXRpYWwgZmluZGluZ3MgZnJvbSB0aGVtYXRpYyBhbmFseXNpcyBzdWdnZXN0CnRoYXQgdG9waWMgYW5hbHlzaXMgcmVmbGVjdHMgZ2VuZXJhbCwgc3VwZXJmaWNpYWwgaW50ZXJwZXJldGF0aW9ucyBvZgp0aGUgZXhwZWlyZW5jZS4gV29yZHMgc3VjaCBhcyAiY29vbCIgImV4cGVyaWVuY2UiICJwZW9wbGUiICJmZWVsIgpyZWZsZWN0IGEgcG9zdGl2ZSwgYnV0IHN1cGVyZmljaWFsIGV4cGVyaWVuY2UgaW4gR2VybWFueS4gVGhlbWF0aWMKYW5hbHlzaXMsIGNvbmR1Y3RlZCBieSByZXNlYXJjaGVycyB3aXRoIHBlcnNvbmFsIHJlbGF0aW9uc2hpcHMgd2l0aApwYXJ0aWNpcGFudHMgc3VnZ2VzdHMgYSBudWFuY2VkLCBtb3JlIHNvcGhpc3RpY2F0ZWQgcmVhZGluZyBvZiB0aGUgZGF0YS4KVGhpcyBhbmF5bHNpcyByZWZsZWN0cyBvdXRjb21lcyBmcm9tIHRoZSBleHBlcmllbmNlIHdpdGggc3VnZ2VzdCBkZWVwCmNoYW5nZSBpbiB0ZWFjaGVyIHZhbHVlcyBhbmQgcHJhY3RpY2VzIHdoaWNoIGRvIG5vdCBzZWVtIHRvIGJlIHN1Z2dlc3RlZApmcm9tIHRvcGljIG1vZGVsaW5nLiBXaGlsZSB0aGUgdGV4dCBtaW5pZ24gYXBwcm9hY2ggYWxsb3dzIGZvciBhbmFseXNpcwpvZiBhIGxhcmdlIGNvcnB1cyBvZiBkYXRhLCBxdWFsaXRhdGl2ZSByZXNlZWFyY2ggZnJvbSBhIHRlYW0gb2ZmZXJzIGEKbW9yZSBpbi1kZXB0aCBhbmFseXNpcy4gVGhlIHR3byBoYXZlIHZhbHVlIHRvZ2V0aGVyIGluIHRoYXQgdG9waWMKbW9kZWxpbmcgY2FuIGJlIHVzZWQgd2l0aCBhIGxhcmdlciBjb3JwdXMgb2YgZGF0YSBhbmQgY2FuIG9mZmVyIGEKY29uZmlybWF0aW9uIG9mIHRoZSBnZW5lcmFsIGRpcmVjdGlvbiBvZiB0aGVtZXMgY3JlYXRlZCBpbiB0aGVtYXRpYwphbmFseXNpcy4gVGhlIHVzZSBvZiB0b3BpYyBtb2RlbGluZyBpbiBhZGRpdGlvbiB0byB0aGVtYXRpYyBhbmFseXNpcyBjYW4KcHJvdmlkZSBhIGZvcm0gb2YgdHJpYW5ndWxhdGlvbiB2YWx1YWJsZSB0byB0aGUgY3JlZGliaWxpdHkgb2YgYQpxdWFsaXRhdGl2ZSByZXNlYXJjaCBzdHVkeS4KCkV4cGVyaWVuY2UgZXhhbWluaW5nIHdoaWNoIHdvcmRzIHRlbmQgdG8gZm9sbG93IG90aGVycyBpbW1lZGlhdGVseSwgb3IKdGhhdCB0ZW5kIHRvIGNvLW9jY3VyIHdpdGhpbiB0aGUgc2FtZSBkb2N1bWVudHMuCgpDb21wYXJpbmcgcmVzdWx0cyBvZiB0aGVtYXRpYyBhbmFseXNpcyBjb25kdWN0ZWQgYnkgcmVzZWFyY2hlcnMgdG8gdG9waWMKbW9kZWxpbmcgY29uZHVjdGVkIGluIFIgY2FuIHByb3ZpZGUgaW5zaWdodHMgaW50byB0aGUgbGltaXRhdGlvbnMgYW5kCmJlbmVmaXRzIG9mIGJvdGggZm9ybXMgb2YgcXVhbGl0YXRpdmUgcmVzZWFyY2guIEFzIEJhaWwgKDIwMTgpIHdhcm5zLAoiLi4ucG9zdC1ob2MgaW50ZXJwcmV0YXRpb24gb2YgdG9waWMgbW9kZWxzIGlzIHJhdGhlciBkYW5nZXJvdXMuLi4gYW5kCmNhbiBxdWlja2x5IGNvbWUgdG8gcmVzZW1ibGUgdGhlIHByb2Nlc3Mgb2YgJ3JlYWRpbmcgdGVhIGxlYXZlcywnIG9yCmZpbmRpbmcgbWVhbmluZyBpbiBwYXR0ZXJucyB0aGF0IGFyZSBpbiBmYWN0IHF1aXRlIGFyYml0cmFyeSBvciBldmVuCnJhbmRvbS4iIFRoZSBzYW1lIGRlc2NyaXB0aW9uIGNvdWxkIGJlIGFwcGxpZWQgdG8gdGhlbWF0aWMgYW5hbHlzaXMsIGEKcHJvY2VzcyB3aGljaCBpcyBjcmVhdGl2ZSwgdGltZSBjb25zdW1pbmcsIGFuZCBjYW4gcmVmbGVjdCB0aGUgYmlhc2VzIG9mCnRoZSByZXNlYXJjaGVycy4gQnkgY29tcGFyaW5nIHRoZSByZXN1bHRzIG9mIGJvdGggYXBwcm9hY2hlcywKcmVzZWFyY2hlcnMgYW5kIHByYWN0aXRpb25lcnMgY2FuIGdhaW4gYSBkZWVwZXIgdW5kZXJzdGFuZGluZyBvZiB0aGUKZGF0YSBhbmQgdGhlIGNvbnRleHQgaW4gd2hpY2ggaXQgd2FzIGNvbGxlY3RlZC4gVGhpcyBjYW4gbGVhZCB0bwp0cmFuc2Zvcm1hdGl2ZSBpbnNpZ2h0cyBpbnRvIGhvdyBxdWFsaXRhdGl2ZSByZXNlYXJjaCBjYW4gYmUgY29uZHVjdGVkCmluIGEgbW9yZSByaWdvcm91cyBhbmQgc3lzdGVtYXRpYyBtYW5uZXIsIHdoaWxlIHN0aWxsIGFsbG93aW5nIGZvciB0aGUKY3JlYXRpdml0eSBhbmQgc3ViamVjdGl2aXR5IHRoYXQgYXJlIGluaGVyZW50IGluIHRoaXMgdHlwZSBvZiByZXNlYXJjaC4KTW9yZW92ZXIsIHJlZmxlY3Rpbmcgb24gdGhlIGxpbWl0YXRpb25zIGFuZCBiZW5lZml0cyBvZiBib3RoIHRoZW1hdGljCmFuYWx5c2lzIGFuZCB0b3BpYyBtb2RlbGluZyBjYW4gaGVscCByZXNlYXJjaGVycyBhbmQgcHJhY3RpdGlvbmVycyB0bwppZGVudGlmeSBhcmVhcyBmb3IgaW1wcm92ZW1lbnQgaW4gdGhlaXIgb3duIHJlc2VhcmNoIHByYWN0aWNlcywgYXMgd2VsbAphcyBwcm92aWRlIGd1aWRhbmNlIGZvciBmdXR1cmUgcmVzZWFyY2ggc3R1ZGllcy4gVWx0aW1hdGVseSwgdGhpcyBjYW4KbGVhZCB0byBtb3JlIHJvYnVzdCBhbmQgbWVhbmluZ2Z1bCBxdWFsaXRhdGl2ZSByZXNlYXJjaCB0aGF0IGNvbnRyaWJ1dGVzCnRvIHRoZSBhZHZhbmNlbWVudCBvZiBrbm93bGVkZ2UgaW4gYSByYW5nZSBvZiBmaWVsZHMuCgoKKipSZWZlcmVuY2VzKioKCkJyYXVuLCBWLiwgJiBDbGFya2UsIFYuICgyMDIyKS4gQ29uY2VwdHVhbCBhbmQgZGVzaWduIHRoaW5raW5nIGZvcgp0aGVtYXRpYyBhbmFseXNpcy4gUXVhbGl0YXRpdmUgUHN5Y2hvbG9neSwgOSgxKSwgMy0tMjYuCltodHRwczovL2RvaS5vcmcvMTAuMTAzNy9xdXAwMDAwMTk2XShodHRwczovL3BzeWNuZXQuYXBhLm9yZy9kb2kvMTAuMTAzNy9xdXAwMDAwMTk2KQoKQmFpbCwgQy4gKDIwMTgpLiBTdHJlbmd0aHMgYW5kIHdlYWtuZXNzZXMgb2YgdGV4dCBhcyBkYXRhLiBSZXRyaWV2ZWQKZnJvbQo8aHR0cHM6Ly9zaWNzcy5pby8yMDE5L21hdGVyaWFscy9kYXkzLXRleHQtYW5hbHlzaXMvdG9waWMtbW9kZWxpbmcvcm1hcmtkb3duL1RvcGljX01vZGVsaW5nLmh0bWw+CgpHaWxsaWVzLCBNLiwgTXVydGh5LCBELiwgQnJlbnRvbiwgSC4sICYgT2xhbml5YW4sIFIuICgyMDIyKS4gVGhlbWUgYW5kCnRvcGljOiBIb3cgcXVhbGl0YXRpdmUgcmVzZWFyY2ggYW5kIHRvcGljIG1vZGVsaW5nIGNhbiBiZSBicm91Z2h0CnRvZ2V0aGVyLiBhclhpdiBwcmVwcmludCBhclhpdjoyMjEwLjAwNzA3Lgo8aHR0cHM6Ly9kb2kub3JnLzEwLjQ4NTUwL2FyWGl2LjIyMTAuMDA3MDc+CgpTaWxnZSwgSi4sICYgUm9iaW5zb24sIEQuICgyMDE3KS4gVGV4dCBtaW5pbmcgd2l0aCBSOiBBIHRpZHkgYXBwcm9hY2guCk8nUmVpbGx5IE1lZGlhLCBJbmMuIFJldHJpZXZlZCBmcm9tOgo8aHR0cHM6Ly93d3cudGlkeXRleHRtaW5pbmcuY29tL3RvcGljbW9kZWxpbmcuaHRtbD4KCldpY2toYW0sIEguICYgR3JvbGVtdW5kLCBHLiAoMjAxNykuIFIgZm9yIERhdGEgU2NpZW5jZTogSW1wb3J0LCBUaWR5LApUcmFuc2Zvcm0sIFZpc3VhbGl6ZSwgYW5kIE1vZGVsIERhdGEuIE8nUmVpbGx5IE1lZGlhLCBJbmMuIFJldHJpZXZlZApmcm9tIDxodHRwczovL3I0ZHMuaGFkLmNvLm56Lz4KClwK