Preface

This tutorial presumes that you have R and R Studio installed, or that you have an account on rstudio.cloud. If you do not already have R and/or R Studio you will need to download and install them. You must first install R from R Project and then the R Studio IDE from R Studio.

R Notebooks vs R Scripts

There are several distinct ways to write R code and to program in R: R Notebooks, Quatro Documents, and R Scripts. An R Markdown Notebook (.Rmd file) and an R Script (.R file) are both tools used in the R programming environment, but they serve different purposes and have distinct features:

R Markdown Notebook

  1. Integrated Documentation and Code:
    • R Markdown allows you to combine narrative text, code, and output in a single document. It supports Markdown syntax for text formatting, making it easy to create well-documented reports, presentations, and interactive notebooks. The code blocks can be a mix of R, Python, SQL, among many other programming languages. R Notebooks are similar to Jupyter Notebooks often used in Python.
  2. Dynamic Report Generation:
    • You can execute code chunks within the document and immediately see the results, including plots, tables, and other outputs. This makes R Markdown ideal for creating dynamic and reproducible research documents.
  3. Interactive Features:
    • Notebooks in R Markdown can include interactive features, such as HTML widgets and Shiny apps, which can be embedded directly into the document.
  4. Output Formats:
    • R Markdown documents can be rendered into various formats, including HTML, PDF, Word, and slideshows. This flexibility allows for easy sharing and presentation of the results.
  5. Ease of Collaboration:
    • The combination of code and its output with narrative text makes it easier to share complete analyses with collaborators, who can see both the methods and the results in context.

R Script (.R file)

  1. Code Only:
    • An R Script is a plain text file containing only R code. It does not support Markdown or other types of text formatting.
  2. Execution:
    • R Scripts are typically run line-by-line or as a whole in an R console or RStudio environment. They are straightforward for writing and executing R code but do not provide integrated documentation or immediate visual feedback within the script itself.
  3. Simplicity:
    • The simplicity of R Scripts makes them ideal for writing and testing R code quickly. They are less cumbersome than R Markdown files when you only need to write and execute code without the need for extensive documentation or presentation of results.
  4. Use Cases:
    • R Scripts are commonly used for scripting tasks, data manipulation, analysis pipelines, and batch processing where the primary focus is on code execution rather than presentation.

R Markdown Notebook (.Rmd file) are best for creating comprehensive, reproducible documents that integrate code, results, and narrative text. They can contain a mix of code chunks (blocks) in R, Python, SQL, C++, Java, D3, and many other languages. Ideal for reports, interactive documents, and presentations. On the other hand, R Script (.R file) are preferable for straightforward coding tasks, scripting, and batch processing where the focus is solely on the code without the need for integrated documentation or presentation. They are “programs” similar to Python programs. Both types of “programs” are essential in the R ecosystem, and their use depends on the specific needs of your project. This tutorial will focus on R Markdown Notebooks.

R Notebooks

R Notebooks are documents that combine code and text, allowing for reproducible research and data analysis. They are created in Posit (formerly R Studio), an integrated development environment (IDE) for the R and Python programming languages.

R Notebooks use a text-based document writing system called R Markdown for literate programming, which allows you to embed executable R (as well as Python, C++, SQL, and bash) code within Markdown text. This means you can write narrative text, add headings, insert figures, embed images, link to URLs, and include mathematical LaTeX-formatted equations in your document, while also executing R code chunks and displaying the results inline.

The R Markdown syntax is based on the Markdown syntax, which is a lightweight markup language used for formatting text documents. R Notebooks allow you to write documents that are both human-readable and executable. They make it easy to share your code, data, and analysis with others, while also providing a clear and organized record of your analysis process.

Workflow

All of your work must be done within an R Project, so create a project first, or, if you already have one, open the project before doing any work.

New R Notebook

To build a new R Notebook, you should follow these steps:

  1. Open RStudio
  2. Click on “File” in the top left-hand corner, and then click on “New File” and select “R Notebook”.
  3. This will create a new R Notebook with some pre-populated text and code. You can modify this as needed.
  4. You can add new code chunks by clicking on the “+” icon in the top left-hand corner of the notebook or by using the keyboard shortcut “Ctrl + Alt + I”.
  5. Write your R code within the code chunks.
  6. Write narrative text using Markdown syntax in between the code chunks.
  7. Test each code chunk by clicking the “Run” button within the chunk or using the keyboard shortcut “Ctrl + Enter”.
  8. To save your R Notebook, click on “File” and then click on “Save As…”. You can then save your notebook in your desired location.
  9. Knit the R Notebook to the desired document format (HTML or PDF).

With an R Notebook, you can mix R code with narrative text, which makes it easy to document your analysis and share it with others. Additionally, you can include visualizations and other outputs directly in the notebook, which makes it easy to present your results.

Knitting

Once your R Notebook is written, it must be knitted. Knitting generates a markdown document which is then converted to a document, commonly PDF or HTML. This process is often called knitting or rendering; it is a form of compilation. During the knitting process, code chunks are executed and any output is embedded in the result document, unless chunks are marked to not be evaluated or not being included.

While writing the R Notebook, code chunks can be executed individually which can be helpful for development. During knitting, the chunks are run in sequence starting with the first code chunk.

Tutorial

Before proceeding with the remainder of this lesson and the specific R Notebook writing elements, watch this short narrated tutorial that demonstrates how to build R Notebooks and knit them to HTML and PDF documents.

Knitting to PDF requires installation of TeX tools which may prove to be difficult on some operating systems, notably MacOS. A work-around is to upload your R Notebook and supporting files to posit.cloud and knit there and then download the resulting PDF to your local project folder. The tutorial below demonstrates this workflow.

R Studio Projects

Projects are a better way to manage code rather than creating individual R Notebooks, R Scripts, and other code files. Projects allows all files, including data files, to be managed as a single unit, shared, and version controlled using services such as git and GitHub. Consult Lesson 6.202 – Working with R Projects for more details on how to create R Projects.

Literate Programming

Literate Programming is a document-centric programming paradigm introduced by Donald Knuth around 1984. A literate computer program is a “document” written in a natural language such as English, interspersed with chunks of source code in various programming languages, from which compilable source code can be generated. This programming approach is commonly used in scientific computing, data programming, and data science with the goal of producing reproducible data pipelines and data analyses. Jupyter Notebooks and R Notebooks are two common implementations of this paradigm.

A literate program must be “compiled” into code suitable for execution and a representation that can be viewed. The latter is commonly an HTML or PDF document. The former is commonly R or Python code interspersed with C++, Java, and SQL code and embedded formatting directives in a markup language such HTML, Markdown, and LaTeX.

The knitr package implements the programming paradigm within R Notebooks, which are, in turn, a variant of R Markdown. R Markdown is a superset of Markdown.

From the perspective of information science, a document is an aggregation of information objects, some of which are created programmatically.

R Markdown in a Nutshell

The key markdown directives are illustrated below with their result right afterwards:

This is _markdown_. Markdown contains embedded formatting 
such as _italics_, **boldfacing**, and ~~strikes~~. 
Of course we can also do superscripts
like x^2^ or subscripts like x~i~. 

Headers are marked with hash marks ###

#### LaTeX Equations

More complex formatting of math expressions can be done 
with embedded [LaTeX](https://latex-tutorial.com/) 
like this $x_i$ or on a separate line:

$\bar{x}=\frac{1}{n}\sum_{i=0}^{n}(x_i)$

or centered like this:

$$
\bar{x}=\frac{1}{n}\sum_{i=0}^{n}(x_i)
$$

Did you see how I created an embedded link to a URL?

Numbered lists are produced with:

1. item 1
2. item 2
  a. sub item a
  b. sub item b
3. item 3

Bulleted lists can be produced with:

- bullet item
- bullet item

Task lists can be produced with:

- [ ] task 1
- [ ] task 2
- [x] task 3 is done

> Lastly, you can use > to make blockquotes for calling out important
  information.
  
Did you notice how the second line in the block quote was intented?

The markdown above is knitted to the following format:


This is markdown. Markdown contains embedded formatting such as italics, boldfacing, and strikes. Of course we can also do superscripts like x2 or subscripts like xi.

Headers are marked with hash marks ###

LaTeX Equations

More complex formatting of math expressions can be done with embedded LaTeX like this \(x_i\) or on a separate line:

\(\bar{x}=\frac{1}{n}\sum_{i=0}^{n}(x_i)\)

or centered like this:

\[ \bar{x}=\frac{1}{n}\sum_{i=0}^{n}(x_i) \]

Did you see how I created an embedded link to a URL?

Numbered lists are produced with:

  1. item 1
  2. item 2
  1. sub item a
  2. sub item b
  1. item 3

Bulleted lists can be produced with:

  • bullet item
  • bullet item

Task lists can be produced with:

Lastly, you can use > to make blockquotes for calling out important information.

Did you notice how the second line in the block quote was intented?


See the R Markdown Reference Guide for a complete list of markdown elements.

R Notebook Elements

Document Meta Tags

The key meta tags that you must provide are title, author, and date. You may also wish to provide email. They are in the meta section of your notebook:

---
title: "Literate Programming with R Notebooks"
date: "<small>2024-06-06</small>"
author: "<small>Martin Schedlbauer</small>"
email: "m.schedlbauer@neu.edu"
...
---

Embedded Code

One of the most useful elements of an R Notebook is the ability to embed code fragments within text. Code within a code block (or code chunk or code fence) is generally in R but can also be in Python, Java, C++, bash, or SQL.

Embedding R Code

A code chunk is created with three backticks in a row followed by a set of braces with the programming language.

```{r echo=F}
```

Code can also be embedded inline within text like so: `r a+b` The result of the code in then added in the output document.

Named Code Chunks

Code chunks should be named so they can be more easily found. Adding a name after the language creates a label for the code chunk:

```{r chunk-name-without-spaces}
# code goes here
```
Hiding Code Chunks in Output

Often, we want the code to run but we do not want the code to be part of the output document. To do that, add “echo=F” after the code chunk name, like so:

```{r chunk-name-no-spaces, echo=F}
# code goes here
```
Suppress Evaluation

The code in a code chunk can be included (or not) in the document even though the code is not run. That is affected with the “eval=F” parameter.

```{r chunk-name-no-spaces, eval=F}
# code goes here
```
Code Chunks with Line Numbers

To add line numbers to the code, add “attr.source=‘.numberLines’” to the parameters.

```{r codeNoLines, attr.source='.numberLines'}
if (TRUE) {
  x <- 1:10
  x + 1
}
```

The above will produce:

if (TRUE) {
  x <- 1:10
  x + 1
}

Embedding C++ Code

To embed C++ code, use either {Rcpp} or {r engine=‘Rcpp’} for the fence header.

```{Rcpp fibCode, eval=T}
#include <Rcpp.h>

// [[Rcpp::export]]
int Fibonacci(const int x) {
  if (x == 0 || x == 1) 
    return(x);
    
  return (Fibonacci(x - 1)) + Fibonacci(x - 2);
}
```

Because the function Fibonacci() was defined with the Rcpp::export attribute it is accessible to R code chunks as a normal R function:

```{r eval=F, echo=T}
print(paste0("10! = ", Fibonacci(10L)))
fact20 <- Fibonacci(20L)

print(paste0("20! = ", fact20))
```

Note that caching should not be used with Rcpp code chunks (since the compiled C++ function will not survive past the lifetime of the current R session).

Headings

Heading levels are specified with hashmarks (#). One hashmark is a first-level header (the title for the document), a second-level header is a section headings, and so forth.

---
title: "Predicting Car Sales"
date: "August 23, 2022"
author: "<small>Martin Schedlbauer</small>"

## Introduction

## Analysis

### Data Cleaning

### Factor Analysis

## Conclusion
---

Embedding LaTeX

LaTeX equations can be embedded in three different ways:

  1. inline by enclosing the equation in a text blow like so $z = (x - ) / $
  2. in a separate block by enclosing within $ but the equation is on its own line
  3. in double $$ which puts the equation in its own block and is centered

The fragment below illustrates how to embed LaTeX.

In mathematical terms, two relations $R_1$ and $R_2$ are union compatible if and only if

$degree(R_1)=degree(R_2)$, and $\mathfrak{D}(R^{A_i}_{1}) = \mathfrak{D}(R^{A_i}_{2})$, where $A_i$ is the *ith* attribute and $\mathfrak{D}(R^{A_i}_{k})$ is the domain of the *ith* attribute of relation $R_k$.

For example, the two relations $A$ and $B$ below are union compatible:

$A(a_1(char),a_2(char),a_3(date))$

$B(b_1(char),b_2(char),b_3(date))$

Embedding Images

Images can be embedded in several ways, the most common being the markdown shown below:

![image caption](URL or filename){style-parameters}

You can optionally add style parameters such as {width=50%} which are only meaningful when knitting to HTML.

Here’s an example:

![CRISP-DM Process](images/crisp-dm.png){width=30%}

The above would render as:

CRISP-DM Process
CRISP-DM Process

Embedding HTML

If the target document format is HTML, then it is permitted to insert HTML code fragments directly into the markdown document. This is useful when embedding external objects in HTML documents as illustrated below:

<iframe src="https://player.vimeo.com/video/821398"
        width="480" height="270" frameborder="0" 
        title="Journaling with Markdown" 
        data-external="1"></iframe>

To ensure that embedded videos are playable, you must add the attribute data-external=“1” to any <iframe>.

Code Style

To render text as “code” using a monospaced front, enclose the text in single backticks. The fragment below illustrates this:

The correlation coefficient can be calculating using the 
`cor()` function in R.

The above markdown would render as:

The correlation coefficient can be calculating using the cor() function in R.

Chunk Options

Chunk output can be customized with knitr options, arguments set in the {} of a chunk header. Above, we use five arguments:

  • include = FALSE prevents code and results from appearing in the finished file. R Markdown still runs the code in the chunk, and the results can be used by other chunks.
  • echo = FALSE prevents code, but not the results from appearing in the finished file. This is a useful way to embed figures.
  • message = FALSE prevents messages that are generated by code from appearing in the finished file.
  • warning = FALSE prevents warnings that are generated by code from appearing in the finished.
  • fig.cap = “…” adds a caption to graphical results.
  • comment = “…” ???
  • attr.source = “.numberLines” adds line numbers to a code chunk

See the R Markdown Reference Guide for a complete list of knitr chunk options.

Global Options

To set global options that apply to every chunk in your file, call knitr::opts_chunk$set in a code chunk. Knitr will treat each option that you pass to knitr::opts_chunk$set as a global default that can be overwritten in individual chunk headers.

Markdown Tables

While tables can be generated through R code using various R functions such as kable(), they can also be created in markdown. Naturally, tables that contain calculated data or data from files should be included using R code chunks.

In Markdown, a table is a structured presentation of data, organized into rows and columns. To create a table in Markdown, you can use the vertical line “|” to separate each column and three or more dashes “—” to create the header for each column. Additionally, you should include a vertical line at both ends of the row to separate it from other content.

The markdown below produces this table:

| Month    | Budget |
| -------- | -------|
| January  | $2500  |
| February | $3000  |
| March    | $4200  |
Month Budget
January $2500
February $3000
March $4200

The cell width do not have to align.

Align text in the columns to the left, right, or center by adding a colon “:” to the left, right, or on both side of the dashes — within the header row. The example is rendered below:

| Course            | Credits | Term   |
| :---------------- | :------:| ----:  |
| Intro to Python   |   2     | Fall   |
| SQL for Beginners |   3     | Fall   |
| Statistics with R |   4     | Spring |
| OOD with C++      |   4     | Summer |
Course Credits Term
Intro to Python 2 Fall
SQL for Beginners 3 Fall
Statistics with R 4 Spring
OOD with C++ 4 Summer
  • :– means the column is left aligned
  • –: means the column is right aligned
  • :-: means the column is center aligned

Text can be formatted within tables using general markdown. However, some formatting options are not available within tables, including:

  • Embedded R
  • Headings
  • Blockquotes
  • Horizontal Lines
  • Images
  • Lists
  • Embedded HTML

Summary

R Markdown is a tool that allows you to combine text and code to create documents that are both human-readable and executable. R Notebooks are a specific type of R Markdown document that are designed for interactive data analysis and reproducible research. By using R Markdown and R Notebooks, you can write documents that include code, text, equations, figures, and interactive visualizations, making it easy to document your analysis process and share your results with others. In this tutorial, you’ll learn how to create R Markdown documents and R Notebooks, and how to use Markdown syntax to format your text and embed code chunks in your documents.

Combining code and text in a Markdown document offers several benefits:

  • Reproducibility: By embedding code in a Markdown document, you can ensure that others can easily reproduce your work. They can see exactly what code you used to generate your results, and they can run that code themselves to verify your findings.

  • Transparency: By providing a clear and detailed record of your analysis process, you can increase transparency and build trust with your audience. This is especially important in fields like data science, where reproducibility and transparency are essential.

  • Documentation: Embedding code in a Markdown document can also make it easier to document your work. By including narrative text alongside your code, you can provide context and explanations for your analysis, making it easier for others to understand and replicate your work.

  • Presentation: Markdown documents can be easily converted into a variety of formats, such as HTML, PDF, and Word documents. This makes it easy to present your analysis in a polished and professional manner, without having to manually copy and paste your code and results into a separate document.

Overall, embedding code in a Markdown document can make your analysis more transparent, reproducible, and well-documented, which can improve the quality and credibility of your analysis.

This lesson provided an introduction. There are many more advanced markdown and R Notebook techniques, including writing books and building full websites. In fact, the :artificium lesson repository was full built in R Notebooks and the source for this lesson is an R Notebook.


Files & Resources

All Files for Lesson 6.204

References

Xie, X., Dervieux, C., Riederer, E. (n.d.). R Markdown Cookbook. Available at bookdown.org

Overview of R Markdown

R Markdown Cheat Sheet

Wikipedia: Literate Programming

Embedding Verbatim Code Chunks in Markdown

Errata

None collected yet. Let us know.

LS0tCnRpdGxlOiAiTGl0ZXJhdGUgUHJvZ3JhbW1pbmcgd2l0aCBSIE5vdGVib29rcyIKcGFyYW1zOgogIGNhdGVnb3J5OiA2CiAgbnVtYmVyOiAyMDQKICB0aW1lOiA0NQogIGxldmVsOiBiZWdpbm5lcgogIHRhZ3M6ICJyLHIgc3R1ZGlvLHIgbWFya2Rvd24sbGl0ZXJhdGUgcHJvZ3JhbW1pbmciCiAgZGVzY3JpcHRpb246ICJFeHBsYWlucyB0aGUgYmVuZWZpdHMgb2Ygd29ya2luZyB3aXRoIFIgTm90ZWJvb2tzIGFuZCBob3cgdG8KICAgICAgICAgICAgICAgIGxldmVyYWdlIGNvZGUgY2h1bmtzIGFuZCBmb2xsb3cgdGhlIHByaW5jaXBsZXMgb2YgTGl0ZXJhdGUKICAgICAgICAgICAgICAgIFByb2dyYW1taW5nLiIKZGF0ZTogIjxzbWFsbD5gciBTeXMuRGF0ZSgpYDwvc21hbGw+IgphdXRob3I6ICI8c21hbGw+TWFydGluIFNjaGVkbGJhdWVyPC9zbWFsbD4iCmVtYWlsOiAibS5zY2hlZGxiYXVlckBuZXUuZWR1IgphZmZpbGl0YXRpb246ICJOb3J0aGVhc3Rlcm4gVW5pdmVyc2l0eSIKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29sbGFwc2VkOiBmYWxzZQogICAgbnVtYmVyX3NlY3Rpb25zOiBmYWxzZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdGhlbWU6IHNwYWNlbGFiCiAgICBoaWdobGlnaHQ6IHRhbmdvCi0tLQoKLS0tCnRpdGxlOiAiPHNtYWxsPmByIHBhcmFtcyRjYXRlZ29yeWAuYHIgcGFyYW1zJG51bWJlcmA8L3NtYWxsPjxici8+PHNwYW4gc3R5bGU9J2NvbG9yOiAjMkU0MDUzOyBmb250LXNpemU6IDAuOWVtJz5gciBybWFya2Rvd246Om1ldGFkYXRhJHRpdGxlYDwvc3Bhbj4iCi0tLQoKYGBge3IgY29kZT14ZnVuOjpyZWFkX3V0ZjgocGFzdGUwKGhlcmU6OmhlcmUoKSwnL1IvX2luc2VydDJEQi5SJykpLCBpbmNsdWRlID0gRkFMU0V9CmBgYAoKIyMgUHJlZmFjZQoKVGhpcyB0dXRvcmlhbCBwcmVzdW1lcyB0aGF0IHlvdSBoYXZlIFIgYW5kIFIgU3R1ZGlvIGluc3RhbGxlZCwgb3IgdGhhdCB5b3UgaGF2ZSBhbiBhY2NvdW50IG9uIFtyc3R1ZGlvLmNsb3VkXShodHRwOi8vcnN0dWRpby5jbG91ZCkuIElmIHlvdSBkbyBub3QgYWxyZWFkeSBoYXZlIFIgYW5kL29yIFIgU3R1ZGlvIHlvdSB3aWxsIG5lZWQgdG8gZG93bmxvYWQgYW5kIGluc3RhbGwgdGhlbS4gWW91IG11c3QgZmlyc3QgaW5zdGFsbCBSIGZyb20gW1IgUHJvamVjdF0oaHR0cHM6Ly9jbG91ZC5yLXByb2plY3Qub3JnLykgYW5kIHRoZW4gdGhlIFIgU3R1ZGlvIElERSBmcm9tIFtSIFN0dWRpb10oaHR0cHM6Ly9yc3R1ZGlvLmNvbS9wcm9kdWN0cy9yc3R1ZGlvL2Rvd25sb2FkLykuCgojIyBSIE5vdGVib29rcyB2cyBSIFNjcmlwdHMKClRoZXJlIGFyZSBzZXZlcmFsIGRpc3RpbmN0IHdheXMgdG8gd3JpdGUgUiBjb2RlIGFuZCB0byBwcm9ncmFtIGluIFI6IFIgTm90ZWJvb2tzLCBRdWF0cm8gRG9jdW1lbnRzLCBhbmQgUiBTY3JpcHRzLiBBbiBSIE1hcmtkb3duIE5vdGVib29rICgqLlJtZCogZmlsZSkgYW5kIGFuIFIgU2NyaXB0ICgqLlIqIGZpbGUpIGFyZSBib3RoIHRvb2xzIHVzZWQgaW4gdGhlIFIgcHJvZ3JhbW1pbmcgZW52aXJvbm1lbnQsIGJ1dCB0aGV5IHNlcnZlIGRpZmZlcmVudCBwdXJwb3NlcyBhbmQgaGF2ZSBkaXN0aW5jdCBmZWF0dXJlczoKCiMjIyBSIE1hcmtkb3duIE5vdGVib29rCgoxLiAgKipJbnRlZ3JhdGVkIERvY3VtZW50YXRpb24gYW5kIENvZGUqKjoKICAgIC0gICBSIE1hcmtkb3duIGFsbG93cyB5b3UgdG8gY29tYmluZSBuYXJyYXRpdmUgdGV4dCwgY29kZSwgYW5kIG91dHB1dCBpbiBhIHNpbmdsZSBkb2N1bWVudC4gSXQgc3VwcG9ydHMgTWFya2Rvd24gc3ludGF4IGZvciB0ZXh0IGZvcm1hdHRpbmcsIG1ha2luZyBpdCBlYXN5IHRvIGNyZWF0ZSB3ZWxsLWRvY3VtZW50ZWQgcmVwb3J0cywgcHJlc2VudGF0aW9ucywgYW5kIGludGVyYWN0aXZlIG5vdGVib29rcy4gVGhlIGNvZGUgYmxvY2tzIGNhbiBiZSBhIG1peCBvZiBSLCBQeXRob24sIFNRTCwgYW1vbmcgbWFueSBvdGhlciBwcm9ncmFtbWluZyBsYW5ndWFnZXMuIFIgTm90ZWJvb2tzIGFyZSBzaW1pbGFyIHRvIEp1cHl0ZXIgTm90ZWJvb2tzIG9mdGVuIHVzZWQgaW4gUHl0aG9uLgoyLiAgKipEeW5hbWljIFJlcG9ydCBHZW5lcmF0aW9uKio6CiAgICAtICAgWW91IGNhbiBleGVjdXRlIGNvZGUgY2h1bmtzIHdpdGhpbiB0aGUgZG9jdW1lbnQgYW5kIGltbWVkaWF0ZWx5IHNlZSB0aGUgcmVzdWx0cywgaW5jbHVkaW5nIHBsb3RzLCB0YWJsZXMsIGFuZCBvdGhlciBvdXRwdXRzLiBUaGlzIG1ha2VzIFIgTWFya2Rvd24gaWRlYWwgZm9yIGNyZWF0aW5nIGR5bmFtaWMgYW5kIHJlcHJvZHVjaWJsZSByZXNlYXJjaCBkb2N1bWVudHMuCjMuICAqKkludGVyYWN0aXZlIEZlYXR1cmVzKio6CiAgICAtICAgTm90ZWJvb2tzIGluIFIgTWFya2Rvd24gY2FuIGluY2x1ZGUgaW50ZXJhY3RpdmUgZmVhdHVyZXMsIHN1Y2ggYXMgSFRNTCB3aWRnZXRzIGFuZCBTaGlueSBhcHBzLCB3aGljaCBjYW4gYmUgZW1iZWRkZWQgZGlyZWN0bHkgaW50byB0aGUgZG9jdW1lbnQuCjQuICAqKk91dHB1dCBGb3JtYXRzKio6CiAgICAtICAgUiBNYXJrZG93biBkb2N1bWVudHMgY2FuIGJlIHJlbmRlcmVkIGludG8gdmFyaW91cyBmb3JtYXRzLCBpbmNsdWRpbmcgSFRNTCwgUERGLCBXb3JkLCBhbmQgc2xpZGVzaG93cy4gVGhpcyBmbGV4aWJpbGl0eSBhbGxvd3MgZm9yIGVhc3kgc2hhcmluZyBhbmQgcHJlc2VudGF0aW9uIG9mIHRoZSByZXN1bHRzLgo1LiAgKipFYXNlIG9mIENvbGxhYm9yYXRpb24qKjoKICAgIC0gICBUaGUgY29tYmluYXRpb24gb2YgY29kZSBhbmQgaXRzIG91dHB1dCB3aXRoIG5hcnJhdGl2ZSB0ZXh0IG1ha2VzIGl0IGVhc2llciB0byBzaGFyZSBjb21wbGV0ZSBhbmFseXNlcyB3aXRoIGNvbGxhYm9yYXRvcnMsIHdobyBjYW4gc2VlIGJvdGggdGhlIG1ldGhvZHMgYW5kIHRoZSByZXN1bHRzIGluIGNvbnRleHQuCgojIyMgUiBTY3JpcHQgKC5SIGZpbGUpCgoxLiAgKipDb2RlIE9ubHkqKjoKICAgIC0gICBBbiBSIFNjcmlwdCBpcyBhIHBsYWluIHRleHQgZmlsZSBjb250YWluaW5nIG9ubHkgUiBjb2RlLiBJdCBkb2VzIG5vdCBzdXBwb3J0IE1hcmtkb3duIG9yIG90aGVyIHR5cGVzIG9mIHRleHQgZm9ybWF0dGluZy4KMi4gICoqRXhlY3V0aW9uKio6CiAgICAtICAgUiBTY3JpcHRzIGFyZSB0eXBpY2FsbHkgcnVuIGxpbmUtYnktbGluZSBvciBhcyBhIHdob2xlIGluIGFuIFIgY29uc29sZSBvciBSU3R1ZGlvIGVudmlyb25tZW50LiBUaGV5IGFyZSBzdHJhaWdodGZvcndhcmQgZm9yIHdyaXRpbmcgYW5kIGV4ZWN1dGluZyBSIGNvZGUgYnV0IGRvIG5vdCBwcm92aWRlIGludGVncmF0ZWQgZG9jdW1lbnRhdGlvbiBvciBpbW1lZGlhdGUgdmlzdWFsIGZlZWRiYWNrIHdpdGhpbiB0aGUgc2NyaXB0IGl0c2VsZi4KMy4gICoqU2ltcGxpY2l0eSoqOgogICAgLSAgIFRoZSBzaW1wbGljaXR5IG9mIFIgU2NyaXB0cyBtYWtlcyB0aGVtIGlkZWFsIGZvciB3cml0aW5nIGFuZCB0ZXN0aW5nIFIgY29kZSBxdWlja2x5LiBUaGV5IGFyZSBsZXNzIGN1bWJlcnNvbWUgdGhhbiBSIE1hcmtkb3duIGZpbGVzIHdoZW4geW91IG9ubHkgbmVlZCB0byB3cml0ZSBhbmQgZXhlY3V0ZSBjb2RlIHdpdGhvdXQgdGhlIG5lZWQgZm9yIGV4dGVuc2l2ZSBkb2N1bWVudGF0aW9uIG9yIHByZXNlbnRhdGlvbiBvZiByZXN1bHRzLgo0LiAgKipVc2UgQ2FzZXMqKjoKICAgIC0gICBSIFNjcmlwdHMgYXJlIGNvbW1vbmx5IHVzZWQgZm9yIHNjcmlwdGluZyB0YXNrcywgZGF0YSBtYW5pcHVsYXRpb24sIGFuYWx5c2lzIHBpcGVsaW5lcywgYW5kIGJhdGNoIHByb2Nlc3Npbmcgd2hlcmUgdGhlIHByaW1hcnkgZm9jdXMgaXMgb24gY29kZSBleGVjdXRpb24gcmF0aGVyIHRoYW4gcHJlc2VudGF0aW9uLgoKKipSIE1hcmtkb3duIE5vdGVib29rICguUm1kIGZpbGUpKiogYXJlIGJlc3QgZm9yIGNyZWF0aW5nIGNvbXByZWhlbnNpdmUsIHJlcHJvZHVjaWJsZSBkb2N1bWVudHMgdGhhdCBpbnRlZ3JhdGUgY29kZSwgcmVzdWx0cywgYW5kIG5hcnJhdGl2ZSB0ZXh0LiBUaGV5IGNhbiBjb250YWluIGEgbWl4IG9mIGNvZGUgY2h1bmtzIChibG9ja3MpIGluIFIsIFB5dGhvbiwgU1FMLCBDKyssIEphdmEsIEQzLCBhbmQgbWFueSBvdGhlciBsYW5ndWFnZXMuIElkZWFsIGZvciByZXBvcnRzLCBpbnRlcmFjdGl2ZSBkb2N1bWVudHMsIGFuZCBwcmVzZW50YXRpb25zLiBPbiB0aGUgb3RoZXIgaGFuZCwgKipSIFNjcmlwdCAoLlIgZmlsZSkqKiBhcmUgcHJlZmVyYWJsZSBmb3Igc3RyYWlnaHRmb3J3YXJkIGNvZGluZyB0YXNrcywgc2NyaXB0aW5nLCBhbmQgYmF0Y2ggcHJvY2Vzc2luZyB3aGVyZSB0aGUgZm9jdXMgaXMgc29sZWx5IG9uIHRoZSBjb2RlIHdpdGhvdXQgdGhlIG5lZWQgZm9yIGludGVncmF0ZWQgZG9jdW1lbnRhdGlvbiBvciBwcmVzZW50YXRpb24uIFRoZXkgYXJlICJwcm9ncmFtcyIgc2ltaWxhciB0byBQeXRob24gcHJvZ3JhbXMuIEJvdGggdHlwZXMgb2YgInByb2dyYW1zIiBhcmUgZXNzZW50aWFsIGluIHRoZSBSIGVjb3N5c3RlbSwgYW5kIHRoZWlyIHVzZSBkZXBlbmRzIG9uIHRoZSBzcGVjaWZpYyBuZWVkcyBvZiB5b3VyIHByb2plY3QuIFRoaXMgdHV0b3JpYWwgd2lsbCBmb2N1cyBvbiBSIE1hcmtkb3duIE5vdGVib29rcy4KCiMjIFIgTm90ZWJvb2tzCgpSIE5vdGVib29rcyBhcmUgZG9jdW1lbnRzIHRoYXQgY29tYmluZSBjb2RlIGFuZCB0ZXh0LCBhbGxvd2luZyBmb3IgcmVwcm9kdWNpYmxlIHJlc2VhcmNoIGFuZCBkYXRhIGFuYWx5c2lzLiBUaGV5IGFyZSBjcmVhdGVkIGluIFtQb3NpdCAoZm9ybWVybHkgUiBTdHVkaW8pXShodHRwczovL3Bvc2l0LmNvLyksIGFuIGludGVncmF0ZWQgZGV2ZWxvcG1lbnQgZW52aXJvbm1lbnQgKElERSkgZm9yIHRoZSBSIGFuZCBQeXRob24gcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzLgoKUiBOb3RlYm9va3MgdXNlIGEgdGV4dC1iYXNlZCBkb2N1bWVudCB3cml0aW5nIHN5c3RlbSBjYWxsZWQgUiBNYXJrZG93biBmb3IgbGl0ZXJhdGUgcHJvZ3JhbW1pbmcsIHdoaWNoIGFsbG93cyB5b3UgdG8gZW1iZWQgZXhlY3V0YWJsZSBSIChhcyB3ZWxsIGFzIFB5dGhvbiwgQysrLCBTUUwsIGFuZCBiYXNoKSBjb2RlIHdpdGhpbiBNYXJrZG93biB0ZXh0LiBUaGlzIG1lYW5zIHlvdSBjYW4gd3JpdGUgbmFycmF0aXZlIHRleHQsIGFkZCBoZWFkaW5ncywgaW5zZXJ0IGZpZ3VyZXMsIGVtYmVkIGltYWdlcywgbGluayB0byBVUkxzLCBhbmQgaW5jbHVkZSBtYXRoZW1hdGljYWwgTGFUZVgtZm9ybWF0dGVkIGVxdWF0aW9ucyBpbiB5b3VyIGRvY3VtZW50LCB3aGlsZSBhbHNvIGV4ZWN1dGluZyBSIGNvZGUgY2h1bmtzIGFuZCBkaXNwbGF5aW5nIHRoZSByZXN1bHRzIGlubGluZS4KClRoZSBSIE1hcmtkb3duIHN5bnRheCBpcyBiYXNlZCBvbiB0aGUgTWFya2Rvd24gc3ludGF4LCB3aGljaCBpcyBhIGxpZ2h0d2VpZ2h0IG1hcmt1cCBsYW5ndWFnZSB1c2VkIGZvciBmb3JtYXR0aW5nIHRleHQgZG9jdW1lbnRzLiBSIE5vdGVib29rcyBhbGxvdyB5b3UgdG8gd3JpdGUgZG9jdW1lbnRzIHRoYXQgYXJlIGJvdGggaHVtYW4tcmVhZGFibGUgYW5kIGV4ZWN1dGFibGUuIFRoZXkgbWFrZSBpdCBlYXN5IHRvIHNoYXJlIHlvdXIgY29kZSwgZGF0YSwgYW5kIGFuYWx5c2lzIHdpdGggb3RoZXJzLCB3aGlsZSBhbHNvIHByb3ZpZGluZyBhIGNsZWFyIGFuZCBvcmdhbml6ZWQgcmVjb3JkIG9mIHlvdXIgYW5hbHlzaXMgcHJvY2Vzcy4KCiMjIFdvcmtmbG93CgpBbGwgb2YgeW91ciB3b3JrIG11c3QgYmUgZG9uZSB3aXRoaW4gYW4gUiBQcm9qZWN0LCBzbyBjcmVhdGUgYSBwcm9qZWN0IGZpcnN0LCBvciwgaWYgeW91IGFscmVhZHkgaGF2ZSBvbmUsIG9wZW4gdGhlIHByb2plY3QgYmVmb3JlIGRvaW5nIGFueSB3b3JrLgoKIyMjIE5ldyBSIE5vdGVib29rCgpUbyBidWlsZCBhIG5ldyBSIE5vdGVib29rLCB5b3Ugc2hvdWxkIGZvbGxvdyB0aGVzZSBzdGVwczoKCjEuICBPcGVuIFJTdHVkaW8KMi4gIENsaWNrIG9uICJGaWxlIiBpbiB0aGUgdG9wIGxlZnQtaGFuZCBjb3JuZXIsIGFuZCB0aGVuIGNsaWNrIG9uICJOZXcgRmlsZSIgYW5kIHNlbGVjdCAiUiBOb3RlYm9vayIuCjMuICBUaGlzIHdpbGwgY3JlYXRlIGEgbmV3IFIgTm90ZWJvb2sgd2l0aCBzb21lIHByZS1wb3B1bGF0ZWQgdGV4dCBhbmQgY29kZS4gWW91IGNhbiBtb2RpZnkgdGhpcyBhcyBuZWVkZWQuCjQuICBZb3UgY2FuIGFkZCBuZXcgY29kZSBjaHVua3MgYnkgY2xpY2tpbmcgb24gdGhlICIrIiBpY29uIGluIHRoZSB0b3AgbGVmdC1oYW5kIGNvcm5lciBvZiB0aGUgbm90ZWJvb2sgb3IgYnkgdXNpbmcgdGhlIGtleWJvYXJkIHNob3J0Y3V0ICJDdHJsICsgQWx0ICsgSSIuCjUuICBXcml0ZSB5b3VyIFIgY29kZSB3aXRoaW4gdGhlIGNvZGUgY2h1bmtzLgo2LiAgV3JpdGUgbmFycmF0aXZlIHRleHQgdXNpbmcgTWFya2Rvd24gc3ludGF4IGluIGJldHdlZW4gdGhlIGNvZGUgY2h1bmtzLgo3LiAgVGVzdCBlYWNoIGNvZGUgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICJSdW4iIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIHVzaW5nIHRoZSBrZXlib2FyZCBzaG9ydGN1dCAiQ3RybCArIEVudGVyIi4KOC4gIFRvIHNhdmUgeW91ciBSIE5vdGVib29rLCBjbGljayBvbiAiRmlsZSIgYW5kIHRoZW4gY2xpY2sgb24gIlNhdmUgQXMuLi4iLiBZb3UgY2FuIHRoZW4gc2F2ZSB5b3VyIG5vdGVib29rIGluIHlvdXIgZGVzaXJlZCBsb2NhdGlvbi4KOS4gIEtuaXQgdGhlIFIgTm90ZWJvb2sgdG8gdGhlIGRlc2lyZWQgZG9jdW1lbnQgZm9ybWF0IChIVE1MIG9yIFBERikuCgpXaXRoIGFuIFIgTm90ZWJvb2ssIHlvdSBjYW4gbWl4IFIgY29kZSB3aXRoIG5hcnJhdGl2ZSB0ZXh0LCB3aGljaCBtYWtlcyBpdCBlYXN5IHRvIGRvY3VtZW50IHlvdXIgYW5hbHlzaXMgYW5kIHNoYXJlIGl0IHdpdGggb3RoZXJzLiBBZGRpdGlvbmFsbHksIHlvdSBjYW4gaW5jbHVkZSB2aXN1YWxpemF0aW9ucyBhbmQgb3RoZXIgb3V0cHV0cyBkaXJlY3RseSBpbiB0aGUgbm90ZWJvb2ssIHdoaWNoIG1ha2VzIGl0IGVhc3kgdG8gcHJlc2VudCB5b3VyIHJlc3VsdHMuCgojIyMgS25pdHRpbmcKCk9uY2UgeW91ciBSIE5vdGVib29rIGlzIHdyaXR0ZW4sIGl0IG11c3QgYmUgKmtuaXR0ZWQqLiBLbml0dGluZyBnZW5lcmF0ZXMgYSBtYXJrZG93biBkb2N1bWVudCB3aGljaCBpcyB0aGVuIGNvbnZlcnRlZCB0byBhIGRvY3VtZW50LCBjb21tb25seSBQREYgb3IgSFRNTC4gVGhpcyBwcm9jZXNzIGlzIG9mdGVuIGNhbGxlZCBrbml0dGluZyBvciByZW5kZXJpbmc7IGl0IGlzIGEgZm9ybSBvZiBjb21waWxhdGlvbi4gRHVyaW5nIHRoZSBrbml0dGluZyBwcm9jZXNzLCBjb2RlIGNodW5rcyBhcmUgZXhlY3V0ZWQgYW5kIGFueSBvdXRwdXQgaXMgZW1iZWRkZWQgaW4gdGhlIHJlc3VsdCBkb2N1bWVudCwgdW5sZXNzIGNodW5rcyBhcmUgbWFya2VkIHRvIG5vdCBiZSBldmFsdWF0ZWQgb3Igbm90IGJlaW5nIGluY2x1ZGVkLgoKV2hpbGUgd3JpdGluZyB0aGUgUiBOb3RlYm9vaywgY29kZSBjaHVua3MgY2FuIGJlIGV4ZWN1dGVkIGluZGl2aWR1YWxseSB3aGljaCBjYW4gYmUgaGVscGZ1bCBmb3IgZGV2ZWxvcG1lbnQuIER1cmluZyBrbml0dGluZywgdGhlIGNodW5rcyBhcmUgcnVuIGluIHNlcXVlbmNlIHN0YXJ0aW5nIHdpdGggdGhlIGZpcnN0IGNvZGUgY2h1bmsuCgojIyBUdXRvcmlhbAoKQmVmb3JlIHByb2NlZWRpbmcgd2l0aCB0aGUgcmVtYWluZGVyIG9mIHRoaXMgbGVzc29uIGFuZCB0aGUgc3BlY2lmaWMgUiBOb3RlYm9vayB3cml0aW5nIGVsZW1lbnRzLCB3YXRjaCB0aGlzIHNob3J0IG5hcnJhdGVkIHR1dG9yaWFsIHRoYXQgZGVtb25zdHJhdGVzIGhvdyB0byBidWlsZCBSIE5vdGVib29rcyBhbmQga25pdCB0aGVtIHRvIEhUTUwgYW5kIFBERiBkb2N1bWVudHMuCgo8aWZyYW1lIHNyYz0iaHR0cHM6Ly9wbGF5ZXIudmltZW8uY29tL3ZpZGVvLzgyMTM5ODk2OT9oPTM3MTNkMzc2NDEmYW1wO3RpdGxlPTAmYW1wO2J5bGluZT0wJmFtcDtwb3J0cmFpdD0wJmFtcDtzcGVlZD0wJmFtcDtiYWRnZT0wJmFtcDthdXRvcGF1c2U9MCZhbXA7cGxheWVyX2lkPTAmYW1wO2FwcF9pZD01ODQ3OSIgd2lkdGg9IjQ4MCIgaGVpZ2h0PSIzMDkiIGZyYW1lYm9yZGVyPSIxIiBhbGxvdz0iYXV0b3BsYXk7IGZ1bGxzY3JlZW47IHBpY3R1cmUtaW4tcGljdHVyZSIgYWxsb3dmdWxsc2NyZWVuIHRpdGxlPSJSIE5vdGVib29rcyBmb3IgSm91cm5hbGluZyBhbmQgTWFya2Rvd24iIGRhdGEtZXh0ZXJuYWw9IjEiPgoKPC9pZnJhbWU+CgpLbml0dGluZyB0byBQREYgcmVxdWlyZXMgaW5zdGFsbGF0aW9uIG9mIFRlWCB0b29scyB3aGljaCBtYXkgcHJvdmUgdG8gYmUgZGlmZmljdWx0IG9uIHNvbWUgb3BlcmF0aW5nIHN5c3RlbXMsIG5vdGFibHkgTWFjT1MuIEEgd29yay1hcm91bmQgaXMgdG8gdXBsb2FkIHlvdXIgUiBOb3RlYm9vayBhbmQgc3VwcG9ydGluZyBmaWxlcyB0byBbcG9zaXQuY2xvdWRdKGh0dHA6Ly9wb3NpdC5jbG91ZCkgYW5kIGtuaXQgdGhlcmUgYW5kIHRoZW4gZG93bmxvYWQgdGhlIHJlc3VsdGluZyBQREYgdG8geW91ciBsb2NhbCBwcm9qZWN0IGZvbGRlci4gVGhlIHR1dG9yaWFsIGJlbG93IGRlbW9uc3RyYXRlcyB0aGlzIHdvcmtmbG93LgoKPGlmcmFtZSBzcmM9Imh0dHBzOi8vcGxheWVyLnZpbWVvLmNvbS92aWRlby84ODExNTYzMzM/dGl0bGU9MCZhbXA7YnlsaW5lPTAmYW1wO3BvcnRyYWl0PTAmYW1wO3NwZWVkPTAmYW1wO2JhZGdlPTAmYW1wO2F1dG9wYXVzZT0wJmFtcDthaXJwbGF5PTAmYW1wO2F1ZGlvX3RyYWNrcz0wJmFtcDtjaGFwdGVycz0wJmFtcDtjaHJvbWVjYXN0PTAmYW1wO2Nsb3NlZF9jYXB0aW9ucz0wJmFtcDt0cmFuc2NyaXB0PTAmYW1wO3BsYXllcl9pZD0wJmFtcDthcHBfaWQ9NTg0NzkiIHdpZHRoPSI0ODAiIGhlaWdodD0iMjcwIiBmcmFtZWJvcmRlcj0iMSIgYWxsb3c9ImF1dG9wbGF5OyBmdWxsc2NyZWVuOyBwaWN0dXJlLWluLXBpY3R1cmUiIHRpdGxlPSJLbml0IFIgTm90ZWJvb2sgdG8gUERGIHVzaW5nIFIgU3R1ZGlvIChQb3NpdCkgQ2xvdWQiIGRhdGEtZXh0ZXJuYWw9IjEiPgoKPC9pZnJhbWU+CgojIyBSIFN0dWRpbyBQcm9qZWN0cwoKUHJvamVjdHMgYXJlIGEgYmV0dGVyIHdheSB0byBtYW5hZ2UgY29kZSByYXRoZXIgdGhhbiBjcmVhdGluZyBpbmRpdmlkdWFsIFIgTm90ZWJvb2tzLCBSIFNjcmlwdHMsIGFuZCBvdGhlciBjb2RlIGZpbGVzLiBQcm9qZWN0cyBhbGxvd3MgYWxsIGZpbGVzLCBpbmNsdWRpbmcgZGF0YSBmaWxlcywgdG8gYmUgbWFuYWdlZCBhcyBhIHNpbmdsZSB1bml0LCBzaGFyZWQsIGFuZCB2ZXJzaW9uIGNvbnRyb2xsZWQgdXNpbmcgc2VydmljZXMgc3VjaCBhcyAqZ2l0KiBhbmQgKkdpdEh1YiouIENvbnN1bHQgW0xlc3NvbiA2LjIwMiAtLSBXb3JraW5nIHdpdGggUiBQcm9qZWN0c10oaHR0cDovL2FydGlmaWNpdW0udXMvbGVzc29ucy8wNi5yL2wtNi0yMDItci1wcm9qZWN0cy9sLTYtMjAyLmh0bWwpIGZvciBtb3JlIGRldGFpbHMgb24gaG93IHRvIGNyZWF0ZSBSIFByb2plY3RzLgoKIyMgTGl0ZXJhdGUgUHJvZ3JhbW1pbmcKCipMaXRlcmF0ZSBQcm9ncmFtbWluZyogaXMgYSBkb2N1bWVudC1jZW50cmljIHByb2dyYW1taW5nIHBhcmFkaWdtIGludHJvZHVjZWQgYnkgRG9uYWxkIEtudXRoIGFyb3VuZCAxOTg0LiBBIGxpdGVyYXRlIGNvbXB1dGVyIHByb2dyYW0gaXMgYSAiZG9jdW1lbnQiIHdyaXR0ZW4gaW4gYSBuYXR1cmFsIGxhbmd1YWdlIHN1Y2ggYXMgRW5nbGlzaCwgaW50ZXJzcGVyc2VkIHdpdGggY2h1bmtzIG9mIHNvdXJjZSBjb2RlIGluIHZhcmlvdXMgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzLCBmcm9tIHdoaWNoIGNvbXBpbGFibGUgc291cmNlIGNvZGUgY2FuIGJlIGdlbmVyYXRlZC4gVGhpcyBwcm9ncmFtbWluZyBhcHByb2FjaCBpcyBjb21tb25seSB1c2VkIGluIHNjaWVudGlmaWMgY29tcHV0aW5nLCBkYXRhIHByb2dyYW1taW5nLCBhbmQgZGF0YSBzY2llbmNlIHdpdGggdGhlIGdvYWwgb2YgcHJvZHVjaW5nIHJlcHJvZHVjaWJsZSBkYXRhIHBpcGVsaW5lcyBhbmQgZGF0YSBhbmFseXNlcy4gSnVweXRlciBOb3RlYm9va3MgYW5kIFIgTm90ZWJvb2tzIGFyZSB0d28gY29tbW9uIGltcGxlbWVudGF0aW9ucyBvZiB0aGlzIHBhcmFkaWdtLgoKQSBsaXRlcmF0ZSBwcm9ncmFtIG11c3QgYmUgImNvbXBpbGVkIiBpbnRvIGNvZGUgc3VpdGFibGUgZm9yIGV4ZWN1dGlvbiBhbmQgYSByZXByZXNlbnRhdGlvbiB0aGF0IGNhbiBiZSB2aWV3ZWQuIFRoZSBsYXR0ZXIgaXMgY29tbW9ubHkgYW4gSFRNTCBvciBQREYgZG9jdW1lbnQuIFRoZSBmb3JtZXIgaXMgY29tbW9ubHkgUiBvciBQeXRob24gY29kZSBpbnRlcnNwZXJzZWQgd2l0aCBDKyssIEphdmEsIGFuZCBTUUwgY29kZSBhbmQgZW1iZWRkZWQgZm9ybWF0dGluZyBkaXJlY3RpdmVzIGluIGEgbWFya3VwIGxhbmd1YWdlIHN1Y2ggSFRNTCwgTWFya2Rvd24sIGFuZCBMYVRlWC4KClRoZSAqKmtuaXRyKiogcGFja2FnZSBpbXBsZW1lbnRzIHRoZSBwcm9ncmFtbWluZyBwYXJhZGlnbSB3aXRoaW4gUiBOb3RlYm9va3MsIHdoaWNoIGFyZSwgaW4gdHVybiwgYSB2YXJpYW50IG9mIFIgTWFya2Rvd24uIFIgTWFya2Rvd24gaXMgYSBzdXBlcnNldCBvZiBNYXJrZG93bi4KCkZyb20gdGhlIHBlcnNwZWN0aXZlIG9mIGluZm9ybWF0aW9uIHNjaWVuY2UsIGEgZG9jdW1lbnQgaXMgYW4gYWdncmVnYXRpb24gb2YgaW5mb3JtYXRpb24gb2JqZWN0cywgc29tZSBvZiB3aGljaCBhcmUgY3JlYXRlZCBwcm9ncmFtbWF0aWNhbGx5LgoKIyMgUiBNYXJrZG93biBpbiBhIE51dHNoZWxsCgpUaGUga2V5IG1hcmtkb3duIGRpcmVjdGl2ZXMgYXJlIGlsbHVzdHJhdGVkIGJlbG93IHdpdGggdGhlaXIgcmVzdWx0IHJpZ2h0IGFmdGVyd2FyZHM6CgpgYGAgICAgICAgICAKVGhpcyBpcyBfbWFya2Rvd25fLiBNYXJrZG93biBjb250YWlucyBlbWJlZGRlZCBmb3JtYXR0aW5nIApzdWNoIGFzIF9pdGFsaWNzXywgKipib2xkZmFjaW5nKiosIGFuZCB+fnN0cmlrZXN+fi4gCk9mIGNvdXJzZSB3ZSBjYW4gYWxzbyBkbyBzdXBlcnNjcmlwdHMKbGlrZSB4XjJeIG9yIHN1YnNjcmlwdHMgbGlrZSB4fml+LiAKCkhlYWRlcnMgYXJlIG1hcmtlZCB3aXRoIGhhc2ggbWFya3MgIyMjCgojIyMjIExhVGVYIEVxdWF0aW9ucwoKTW9yZSBjb21wbGV4IGZvcm1hdHRpbmcgb2YgbWF0aCBleHByZXNzaW9ucyBjYW4gYmUgZG9uZSAKd2l0aCBlbWJlZGRlZCBbTGFUZVhdKGh0dHBzOi8vbGF0ZXgtdHV0b3JpYWwuY29tLykgCmxpa2UgdGhpcyAkeF9pJCBvciBvbiBhIHNlcGFyYXRlIGxpbmU6CgokXGJhcnt4fT1cZnJhY3sxfXtufVxzdW1fe2k9MH1ee259KHhfaSkkCgpvciBjZW50ZXJlZCBsaWtlIHRoaXM6CgokJApcYmFye3h9PVxmcmFjezF9e259XHN1bV97aT0wfV57bn0oeF9pKQokJAoKRGlkIHlvdSBzZWUgaG93IEkgY3JlYXRlZCBhbiBlbWJlZGRlZCBsaW5rIHRvIGEgVVJMPwoKTnVtYmVyZWQgbGlzdHMgYXJlIHByb2R1Y2VkIHdpdGg6CgoxLiBpdGVtIDEKMi4gaXRlbSAyCiAgYS4gc3ViIGl0ZW0gYQogIGIuIHN1YiBpdGVtIGIKMy4gaXRlbSAzCgpCdWxsZXRlZCBsaXN0cyBjYW4gYmUgcHJvZHVjZWQgd2l0aDoKCi0gYnVsbGV0IGl0ZW0KLSBidWxsZXQgaXRlbQoKVGFzayBsaXN0cyBjYW4gYmUgcHJvZHVjZWQgd2l0aDoKCi0gWyBdIHRhc2sgMQotIFsgXSB0YXNrIDIKLSBbeF0gdGFzayAzIGlzIGRvbmUKCj4gTGFzdGx5LCB5b3UgY2FuIHVzZSA+IHRvIG1ha2UgYmxvY2txdW90ZXMgZm9yIGNhbGxpbmcgb3V0IGltcG9ydGFudAogIGluZm9ybWF0aW9uLgogIApEaWQgeW91IG5vdGljZSBob3cgdGhlIHNlY29uZCBsaW5lIGluIHRoZSBibG9jayBxdW90ZSB3YXMgaW50ZW50ZWQ/CmBgYAoKVGhlIG1hcmtkb3duIGFib3ZlIGlzIGtuaXR0ZWQgdG8gdGhlIGZvbGxvd2luZyBmb3JtYXQ6CgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KClRoaXMgaXMgKm1hcmtkb3duKi4gTWFya2Rvd24gY29udGFpbnMgZW1iZWRkZWQgZm9ybWF0dGluZyBzdWNoIGFzICppdGFsaWNzKiwgKipib2xkZmFjaW5nKiosIGFuZCB+fnN0cmlrZXN+fi4gT2YgY291cnNlIHdlIGNhbiBhbHNvIGRvIHN1cGVyc2NyaXB0cyBsaWtlIHheMl4gb3Igc3Vic2NyaXB0cyBsaWtlIHh+aX4uCgpIZWFkZXJzIGFyZSBtYXJrZWQgd2l0aCBoYXNoIG1hcmtzIFwjIyMKCiMjIyMgTGFUZVggRXF1YXRpb25zCgpNb3JlIGNvbXBsZXggZm9ybWF0dGluZyBvZiBtYXRoIGV4cHJlc3Npb25zIGNhbiBiZSBkb25lIHdpdGggZW1iZWRkZWQgW0xhVGVYXShodHRwczovL2xhdGV4LXR1dG9yaWFsLmNvbS8pIGxpa2UgdGhpcyAkeF9pJCBvciBvbiBhIHNlcGFyYXRlIGxpbmU6CgokXGJhcnt4fT1cZnJhY3sxfXtufVxzdW1fe2k9MH1ee259KHhfaSkkCgpvciBjZW50ZXJlZCBsaWtlIHRoaXM6CgokJApcYmFye3h9PVxmcmFjezF9e259XHN1bV97aT0wfV57bn0oeF9pKQokJAoKRGlkIHlvdSBzZWUgaG93IEkgY3JlYXRlZCBhbiBlbWJlZGRlZCBsaW5rIHRvIGEgVVJMPwoKTnVtYmVyZWQgbGlzdHMgYXJlIHByb2R1Y2VkIHdpdGg6CgoxLiAgaXRlbSAxCjIuICBpdGVtIDIKCjwhLS0gLS0+CgphLiAgc3ViIGl0ZW0gYQpiLiAgc3ViIGl0ZW0gYgoKPCEtLSAtLT4KCjMuICBpdGVtIDMKCkJ1bGxldGVkIGxpc3RzIGNhbiBiZSBwcm9kdWNlZCB3aXRoOgoKLSAgIGJ1bGxldCBpdGVtCi0gICBidWxsZXQgaXRlbQoKVGFzayBsaXN0cyBjYW4gYmUgcHJvZHVjZWQgd2l0aDoKCi0gICBbIF0gdGFzayAxCi0gICBbIF0gdGFzayAyCi0gICBbeF0gdGFzayAzIGlzIGRvbmUKCj4gTGFzdGx5LCB5b3UgY2FuIHVzZSBcPiB0byBtYWtlIGJsb2NrcXVvdGVzIGZvciBjYWxsaW5nIG91dCBpbXBvcnRhbnQgaW5mb3JtYXRpb24uCgpEaWQgeW91IG5vdGljZSBob3cgdGhlIHNlY29uZCBsaW5lIGluIHRoZSBibG9jayBxdW90ZSB3YXMgaW50ZW50ZWQ/CgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KClNlZSB0aGUgW1IgTWFya2Rvd24gUmVmZXJlbmNlIEd1aWRlXShodHRwczovL3d3dy5yc3R1ZGlvLmNvbS93cC1jb250ZW50L3VwbG9hZHMvMjAxNS8wMy9ybWFya2Rvd24tcmVmZXJlbmNlLnBkZj9fZ2E9Mi41OTE4NDE3My4xMjE0MjUyOTI4LjE2MzU5ODA0NzQtMTk0OTk1NTE3LjE2MzU0MzM3NTcpIGZvciBhIGNvbXBsZXRlIGxpc3Qgb2YgbWFya2Rvd24gZWxlbWVudHMuCgojIyBSIE5vdGVib29rIEVsZW1lbnRzCgojIyMgRG9jdW1lbnQgTWV0YSBUYWdzCgpUaGUga2V5IG1ldGEgdGFncyB0aGF0IHlvdSBtdXN0IHByb3ZpZGUgYXJlICp0aXRsZSosICphdXRob3IqLCBhbmQgKmRhdGUqLiBZb3UgbWF5IGFsc28gd2lzaCB0byBwcm92aWRlICplbWFpbCouIFRoZXkgYXJlIGluIHRoZSBtZXRhIHNlY3Rpb24gb2YgeW91ciBub3RlYm9vazoKCmBgYCAgICAgICAgIAotLS0KdGl0bGU6ICJMaXRlcmF0ZSBQcm9ncmFtbWluZyB3aXRoIFIgTm90ZWJvb2tzIgpkYXRlOiAiPHNtYWxsPmByIFN5cy5EYXRlKClgPC9zbWFsbD4iCmF1dGhvcjogIjxzbWFsbD5NYXJ0aW4gU2NoZWRsYmF1ZXI8L3NtYWxsPiIKZW1haWw6ICJtLnNjaGVkbGJhdWVyQG5ldS5lZHUiCi4uLgotLS0KYGBgCgojIyMgRW1iZWRkZWQgQ29kZQoKT25lIG9mIHRoZSBtb3N0IHVzZWZ1bCBlbGVtZW50cyBvZiBhbiBSIE5vdGVib29rIGlzIHRoZSBhYmlsaXR5IHRvIGVtYmVkIGNvZGUgZnJhZ21lbnRzIHdpdGhpbiB0ZXh0LiBDb2RlIHdpdGhpbiBhIGNvZGUgYmxvY2sgKG9yIGNvZGUgY2h1bmsgb3IgY29kZSBmZW5jZSkgaXMgZ2VuZXJhbGx5IGluIFIgYnV0IGNhbiBhbHNvIGJlIGluIFB5dGhvbiwgSmF2YSwgQysrLCBiYXNoLCBvciBTUUwuCgojIyMjIEVtYmVkZGluZyBSIENvZGUgeyNlbWJSfQoKQSBjb2RlIGNodW5rIGlzIGNyZWF0ZWQgd2l0aCB0aHJlZSBiYWNrdGlja3MgaW4gYSByb3cgZm9sbG93ZWQgYnkgYSBzZXQgb2YgYnJhY2VzIHdpdGggdGhlIHByb2dyYW1taW5nIGxhbmd1YWdlLgoKYGBge3IgZWNobz1GfQprbml0cjo6cmF3X2h0bWwoIjxwcmU+IikKa25pdHI6OnJhd19odG1sKHBhc3RlKAogICImIzk2OyYjOTY7JiM5Njt7ciBlY2hvPUZ9IiwKICAiJiM5NjsmIzk2OyYjOTY7IiwKICBzZXA9Ijxici8+IikpCmtuaXRyOjpyYXdfaHRtbCgiPC9wcmU+IikKYGBgCgpDb2RlIGNhbiBhbHNvIGJlIGVtYmVkZGVkIGlubGluZSB3aXRoaW4gdGV4dCBsaWtlIHNvOiBgYCBgciBrbml0cjo6aW5saW5lX2V4cHIoImErYiIpYCBgYCBUaGUgcmVzdWx0IG9mIHRoZSBjb2RlIGluIHRoZW4gYWRkZWQgaW4gdGhlIG91dHB1dCBkb2N1bWVudC4KCiMjIyMjIE5hbWVkIENvZGUgQ2h1bmtzCgpDb2RlIGNodW5rcyBzaG91bGQgYmUgbmFtZWQgc28gdGhleSBjYW4gYmUgbW9yZSBlYXNpbHkgZm91bmQuIEFkZGluZyBhIG5hbWUgYWZ0ZXIgdGhlIGxhbmd1YWdlIGNyZWF0ZXMgYSBsYWJlbCBmb3IgdGhlIGNvZGUgY2h1bms6CgpgYGBge3ZlcmJhdGltfQpgYGB7ciBjaHVuay1uYW1lLXdpdGhvdXQtc3BhY2VzfQojIGNvZGUgZ29lcyBoZXJlCmBgYApgYGBgCgojIyMjIyBIaWRpbmcgQ29kZSBDaHVua3MgaW4gT3V0cHV0CgpPZnRlbiwgd2Ugd2FudCB0aGUgY29kZSB0byBydW4gYnV0IHdlIGRvIG5vdCB3YW50IHRoZSBjb2RlIHRvIGJlIHBhcnQgb2YgdGhlIG91dHB1dCBkb2N1bWVudC4gVG8gZG8gdGhhdCwgYWRkICJlY2hvPUYiIGFmdGVyIHRoZSBjb2RlIGNodW5rIG5hbWUsIGxpa2Ugc286CgpgYGBge3ZlcmJhdGltfQpgYGB7ciBjaHVuay1uYW1lLW5vLXNwYWNlcywgZWNobz1GfQojIGNvZGUgZ29lcyBoZXJlCmBgYApgYGBgCgojIyMjIyBTdXBwcmVzcyBFdmFsdWF0aW9uCgpUaGUgY29kZSBpbiBhIGNvZGUgY2h1bmsgY2FuIGJlIGluY2x1ZGVkIChvciBub3QpIGluIHRoZSBkb2N1bWVudCBldmVuIHRob3VnaCB0aGUgY29kZSBpcyBub3QgcnVuLiBUaGF0IGlzIGFmZmVjdGVkIHdpdGggdGhlICJldmFsPUYiIHBhcmFtZXRlci4KCmBgYGB7dmVyYmF0aW19CmBgYHtyIGNodW5rLW5hbWUtbm8tc3BhY2VzLCBldmFsPUZ9CiMgY29kZSBnb2VzIGhlcmUKYGBgCmBgYGAKCiMjIyMjIENvZGUgQ2h1bmtzIHdpdGggTGluZSBOdW1iZXJzCgpUbyBhZGQgbGluZSBudW1iZXJzIHRvIHRoZSBjb2RlLCBhZGQgImF0dHIuc291cmNlPScubnVtYmVyTGluZXMnIiB0byB0aGUgcGFyYW1ldGVycy4KCmBgYGB7dmVyYmF0aW19CmBgYHtyIGNvZGVOb0xpbmVzLCBhdHRyLnNvdXJjZT0nLm51bWJlckxpbmVzJ30KaWYgKFRSVUUpIHsKICB4IDwtIDE6MTAKICB4ICsgMQp9CmBgYApgYGBgCgpUaGUgYWJvdmUgd2lsbCBwcm9kdWNlOgoKYGBge3IgYXR0ci5zb3VyY2U9Jy5udW1iZXJMaW5lcycsIGV2YWw9Rn0KaWYgKFRSVUUpIHsKICB4IDwtIDE6MTAKICB4ICsgMQp9CmBgYAoKIyMjIyMgTmF2aWdhdGluZyBDb2RlIENodW5rcwoKSW4gZ2VuZXJhbCwgYSBjb2RlIGNodW5rIHN0YXJ0cyB3aXRoIHRoZSBsYW5ndWFnZSBmb2xsb3dlZCBieSBhbiBvcHRpb25hbCBuYW1lIGZvciB0aGUgY2h1bmsuIFRoZSBuYW1lIChvciBjaHVuayBsYWJlbCkgaXMgdXNlZnVsIGZvciBxdWljayBuYXZpZ2F0aW9uIGFuZCBmb3IgcmVmZXJlbmNpbmcgd2l0aGluIHRoZSBkb2N1bWVudC4gSW4gUiBTdHVkaW8sIGl0IGNhbiBiZSB1c2VkIGZvciBxdWlja2x5IGp1bXBpbmcgdG8gYSBzZWN0aW9uIG9mIGNvZGUuCgohW0p1bXBpbmcgdG8gQSBDaHVuayBieSBOYW1lXShpbWFnZXMvY2h1bmstbGFiZWxzLmpwZyl7d2lkdGg9IjI1JSJ9CgojIyMjIEVtYmVkZGluZyBDKysgQ29kZQoKVG8gZW1iZWQgQysrIGNvZGUsIHVzZSBlaXRoZXIge1JjcHB9IG9yIHtyIGVuZ2luZT0nUmNwcCd9IGZvciB0aGUgZmVuY2UgaGVhZGVyLgoKYGBgYHt2ZXJiYXRpbX0KYGBge1JjcHAgZmliQ29kZSwgZXZhbD1UfQojaW5jbHVkZSA8UmNwcC5oPgoKLy8gW1tSY3BwOjpleHBvcnRdXQppbnQgRmlib25hY2NpKGNvbnN0IGludCB4KSB7CiAgaWYgKHggPT0gMCB8fCB4ID09IDEpIAogICAgcmV0dXJuKHgpOwogICAgCiAgcmV0dXJuIChGaWJvbmFjY2koeCAtIDEpKSArIEZpYm9uYWNjaSh4IC0gMik7Cn0KYGBgCmBgYGAKCkJlY2F1c2UgdGhlIGZ1bmN0aW9uIGBGaWJvbmFjY2koKWAgd2FzIGRlZmluZWQgd2l0aCB0aGUgKlJjcHA6OmV4cG9ydCogYXR0cmlidXRlIGl0IGlzIGFjY2Vzc2libGUgdG8gUiBjb2RlIGNodW5rcyBhcyBhIG5vcm1hbCBSIGZ1bmN0aW9uOgoKYGBgYHt2ZXJiYXRpbX0KYGBge3IgZXZhbD1GLCBlY2hvPVR9CnByaW50KHBhc3RlMCgiMTAhID0gIiwgRmlib25hY2NpKDEwTCkpKQpmYWN0MjAgPC0gRmlib25hY2NpKDIwTCkKCnByaW50KHBhc3RlMCgiMjAhID0gIiwgZmFjdDIwKSkKYGBgCmBgYGAKCk5vdGUgdGhhdCBjYWNoaW5nIHNob3VsZCBub3QgYmUgdXNlZCB3aXRoIFJjcHAgY29kZSBjaHVua3MgKHNpbmNlIHRoZSBjb21waWxlZCBDKysgZnVuY3Rpb24gd2lsbCBub3Qgc3Vydml2ZSBwYXN0IHRoZSBsaWZldGltZSBvZiB0aGUgY3VycmVudCBSIHNlc3Npb24pLgoKIyMjIEhlYWRpbmdzCgpIZWFkaW5nIGxldmVscyBhcmUgc3BlY2lmaWVkIHdpdGggaGFzaG1hcmtzIChcIykuIE9uZSBoYXNobWFyayBpcyBhIGZpcnN0LWxldmVsIGhlYWRlciAodGhlIHRpdGxlIGZvciB0aGUgZG9jdW1lbnQpLCBhIHNlY29uZC1sZXZlbCBoZWFkZXIgaXMgYSBzZWN0aW9uIGhlYWRpbmdzLCBhbmQgc28gZm9ydGguCgpgYGAgICAgICAgICAKLS0tCnRpdGxlOiAiUHJlZGljdGluZyBDYXIgU2FsZXMiCmRhdGU6ICJBdWd1c3QgMjMsIDIwMjIiCmF1dGhvcjogIjxzbWFsbD5NYXJ0aW4gU2NoZWRsYmF1ZXI8L3NtYWxsPiIKCiMjIEludHJvZHVjdGlvbgoKIyMgQW5hbHlzaXMKCiMjIyBEYXRhIENsZWFuaW5nCgojIyMgRmFjdG9yIEFuYWx5c2lzCgojIyBDb25jbHVzaW9uCi0tLQpgYGAKCiMjIyBFbWJlZGRpbmcgTGFUZVgKCkxhVGVYIGVxdWF0aW9ucyBjYW4gYmUgZW1iZWRkZWQgaW4gdGhyZWUgZGlmZmVyZW50IHdheXM6CgoxLiAgaW5saW5lIGJ5IGVuY2xvc2luZyB0aGUgZXF1YXRpb24gaW4gYSB0ZXh0IGJsb3cgbGlrZSBzbyBcJHogPSAoeCAtIFxtdSkgLyBcc2lnbWFcJAoyLiAgaW4gYSBzZXBhcmF0ZSBibG9jayBieSBlbmNsb3Npbmcgd2l0aGluIFwkIGJ1dCB0aGUgZXF1YXRpb24gaXMgb24gaXRzIG93biBsaW5lCjMuICBpbiBkb3VibGUgXCRcJCB3aGljaCBwdXRzIHRoZSBlcXVhdGlvbiBpbiBpdHMgb3duIGJsb2NrIGFuZCBpcyBjZW50ZXJlZAoKVGhlIGZyYWdtZW50IGJlbG93IGlsbHVzdHJhdGVzIGhvdyB0byBlbWJlZCBMYVRlWC4KCmBgYCAgICAgICAgIApJbiBtYXRoZW1hdGljYWwgdGVybXMsIHR3byByZWxhdGlvbnMgJFJfMSQgYW5kICRSXzIkIGFyZSB1bmlvbiBjb21wYXRpYmxlIGlmIGFuZCBvbmx5IGlmCgokZGVncmVlKFJfMSk9ZGVncmVlKFJfMikkLCBhbmQgJFxtYXRoZnJha3tEfShSXntBX2l9X3sxfSkgPSBcbWF0aGZyYWt7RH0oUl57QV9pfV97Mn0pJCwgd2hlcmUgJEFfaSQgaXMgdGhlICppdGgqIGF0dHJpYnV0ZSBhbmQgJFxtYXRoZnJha3tEfShSXntBX2l9X3trfSkkIGlzIHRoZSBkb21haW4gb2YgdGhlICppdGgqIGF0dHJpYnV0ZSBvZiByZWxhdGlvbiAkUl9rJC4KCkZvciBleGFtcGxlLCB0aGUgdHdvIHJlbGF0aW9ucyAkQSQgYW5kICRCJCBiZWxvdyBhcmUgdW5pb24gY29tcGF0aWJsZToKCiRBKGFfMShjaGFyKSxhXzIoY2hhciksYV8zKGRhdGUpKSQKCiRCKGJfMShjaGFyKSxiXzIoY2hhciksYl8zKGRhdGUpKSQKYGBgCgojIyMgRW1iZWRkaW5nIEltYWdlcwoKSW1hZ2VzIGNhbiBiZSBlbWJlZGRlZCBpbiBzZXZlcmFsIHdheXMsIHRoZSBtb3N0IGNvbW1vbiBiZWluZyB0aGUgbWFya2Rvd24gc2hvd24gYmVsb3c6CgpgYGAgICAgICAgICAKIVtpbWFnZSBjYXB0aW9uXShVUkwgb3IgZmlsZW5hbWUpe3N0eWxlLXBhcmFtZXRlcnN9CmBgYAoKWW91IGNhbiBvcHRpb25hbGx5IGFkZCBzdHlsZSBwYXJhbWV0ZXJzIHN1Y2ggYXMge3dpZHRoPTUwJX0gd2hpY2ggYXJlIG9ubHkgbWVhbmluZ2Z1bCB3aGVuIGtuaXR0aW5nIHRvIEhUTUwuCgpIZXJlJ3MgYW4gZXhhbXBsZToKCmBgYCAgICAgICAgIAohW0NSSVNQLURNIFByb2Nlc3NdKGltYWdlcy9jcmlzcC1kbS5wbmcpe3dpZHRoPTMwJX0KYGBgCgpUaGUgYWJvdmUgd291bGQgcmVuZGVyIGFzOgoKIVtDUklTUC1ETSBQcm9jZXNzXShpbWFnZXMvY3Jpc3AtZG0ucG5nKXt3aWR0aD0iMzAlIn0KCiMjIyBFbWJlZGRpbmcgSFRNTAoKSWYgdGhlIHRhcmdldCBkb2N1bWVudCBmb3JtYXQgaXMgSFRNTCwgdGhlbiBpdCBpcyBwZXJtaXR0ZWQgdG8gaW5zZXJ0IEhUTUwgY29kZSBmcmFnbWVudHMgZGlyZWN0bHkgaW50byB0aGUgbWFya2Rvd24gZG9jdW1lbnQuIFRoaXMgaXMgdXNlZnVsIHdoZW4gZW1iZWRkaW5nIGV4dGVybmFsIG9iamVjdHMgaW4gSFRNTCBkb2N1bWVudHMgYXMgaWxsdXN0cmF0ZWQgYmVsb3c6CgpgYGB7dmVyYmF0aW19CjxpZnJhbWUgc3JjPSJodHRwczovL3BsYXllci52aW1lby5jb20vdmlkZW8vODIxMzk4IgogICAgICAgIHdpZHRoPSI0ODAiIGhlaWdodD0iMjcwIiBmcmFtZWJvcmRlcj0iMCIgCiAgICAgICAgdGl0bGU9IkpvdXJuYWxpbmcgd2l0aCBNYXJrZG93biIgCiAgICAgICAgZGF0YS1leHRlcm5hbD0iMSI+PC9pZnJhbWU+CmBgYAoKPiBUbyBlbnN1cmUgdGhhdCBlbWJlZGRlZCB2aWRlb3MgYXJlIHBsYXlhYmxlLCB5b3UgbXVzdCBhZGQgdGhlIGF0dHJpYnV0ZSAqZGF0YS1leHRlcm5hbD0iMSIqIHRvIGFueSBcPGlmcmFtZVw+LgoKIyMjIENvZGUgU3R5bGUKClRvIHJlbmRlciB0ZXh0IGFzICJjb2RlIiB1c2luZyBhIG1vbm9zcGFjZWQgZnJvbnQsIGVuY2xvc2UgdGhlIHRleHQgaW4gc2luZ2xlIGJhY2t0aWNrcy4gVGhlIGZyYWdtZW50IGJlbG93IGlsbHVzdHJhdGVzIHRoaXM6CgpgYGAgICAgICAgICAKVGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IGNhbiBiZSBjYWxjdWxhdGluZyB1c2luZyB0aGUgCmBjb3IoKWAgZnVuY3Rpb24gaW4gUi4KYGBgCgpUaGUgYWJvdmUgbWFya2Rvd24gd291bGQgcmVuZGVyIGFzOgoKfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwKfCBUaGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgY2FuIGJlIGNhbGN1bGF0aW5nIHVzaW5nIHRoZSBgY29yKClgIGZ1bmN0aW9uIGluIFIuIHwKCiMjIyBDaHVuayBPcHRpb25zCgpDaHVuayBvdXRwdXQgY2FuIGJlIGN1c3RvbWl6ZWQgd2l0aCBba25pdHIgb3B0aW9uc10oaHR0cHM6Ly95aWh1aS5vcmcva25pdHIvb3B0aW9ucy8pLCBhcmd1bWVudHMgc2V0IGluIHRoZSB7fSBvZiBhIGNodW5rIGhlYWRlci4gQWJvdmUsIHdlIHVzZSBmaXZlIGFyZ3VtZW50czoKCi0gICA8Y29kZT5pbmNsdWRlID0gRkFMU0U8L2NvZGU+IHByZXZlbnRzIGNvZGUgYW5kIHJlc3VsdHMgZnJvbSBhcHBlYXJpbmcgaW4gdGhlIGZpbmlzaGVkIGZpbGUuIFIgTWFya2Rvd24gc3RpbGwgcnVucyB0aGUgY29kZSBpbiB0aGUgY2h1bmssIGFuZCB0aGUgcmVzdWx0cyBjYW4gYmUgdXNlZCBieSBvdGhlciBjaHVua3MuCi0gICA8Y29kZT5lY2hvID0gRkFMU0U8L2NvZGU+IHByZXZlbnRzIGNvZGUsIGJ1dCBub3QgdGhlIHJlc3VsdHMgZnJvbSBhcHBlYXJpbmcgaW4gdGhlIGZpbmlzaGVkIGZpbGUuIFRoaXMgaXMgYSB1c2VmdWwgd2F5IHRvIGVtYmVkIGZpZ3VyZXMuCi0gICA8Y29kZT5tZXNzYWdlID0gRkFMU0U8L2NvZGU+IHByZXZlbnRzIG1lc3NhZ2VzIHRoYXQgYXJlIGdlbmVyYXRlZCBieSBjb2RlIGZyb20gYXBwZWFyaW5nIGluIHRoZSBmaW5pc2hlZCBmaWxlLgotICAgPGNvZGU+d2FybmluZyA9IEZBTFNFPC9jb2RlPiBwcmV2ZW50cyB3YXJuaW5ncyB0aGF0IGFyZSBnZW5lcmF0ZWQgYnkgY29kZSBmcm9tIGFwcGVhcmluZyBpbiB0aGUgZmluaXNoZWQuCi0gICA8Y29kZT5maWcuY2FwID0gIi4uLiI8L2NvZGU+IGFkZHMgYSBjYXB0aW9uIHRvIGdyYXBoaWNhbCByZXN1bHRzLgotICAgPGNvZGU+Y29tbWVudCA9ICIuLi4iPC9jb2RlPiA/Pz8KLSAgIDxjb2RlPmF0dHIuc291cmNlID0gIi5udW1iZXJMaW5lcyI8L2NvZGU+IGFkZHMgbGluZSBudW1iZXJzIHRvIGEgY29kZSBjaHVuawoKU2VlIHRoZSBbUiBNYXJrZG93biBSZWZlcmVuY2UgR3VpZGVdKGh0dHBzOi8vd3d3LnJzdHVkaW8uY29tL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDE1LzAzL3JtYXJrZG93bi1yZWZlcmVuY2UucGRmP19nYT0yLjU5MTg0MTczLjEyMTQyNTI5MjguMTYzNTk4MDQ3NC0xOTQ5OTU1MTcuMTYzNTQzMzc1NykgZm9yIGEgY29tcGxldGUgbGlzdCBvZiBrbml0ciBjaHVuayBvcHRpb25zLgoKIyMjIEdsb2JhbCBPcHRpb25zCgpUbyBzZXQgZ2xvYmFsIG9wdGlvbnMgdGhhdCBhcHBseSB0byBldmVyeSBjaHVuayBpbiB5b3VyIGZpbGUsIGNhbGwgPGNvZGU+a25pdHI6Om9wdHNfY2h1bmtcJHNldDwvY29kZT4gaW4gYSBjb2RlIGNodW5rLiBLbml0ciB3aWxsIHRyZWF0IGVhY2ggb3B0aW9uIHRoYXQgeW91IHBhc3MgdG8ga25pdHI6Om9wdHNfY2h1bmtcJHNldCBhcyBhIGdsb2JhbCBkZWZhdWx0IHRoYXQgY2FuIGJlIG92ZXJ3cml0dGVuIGluIGluZGl2aWR1YWwgY2h1bmsgaGVhZGVycy4KCiMjIE1hcmtkb3duIFRhYmxlcwoKV2hpbGUgdGFibGVzIGNhbiBiZSBnZW5lcmF0ZWQgdGhyb3VnaCBSIGNvZGUgdXNpbmcgdmFyaW91cyBSIGZ1bmN0aW9ucyBzdWNoIGFzIGBrYWJsZSgpYCwgdGhleSBjYW4gYWxzbyBiZSBjcmVhdGVkIGluIG1hcmtkb3duLiBOYXR1cmFsbHksIHRhYmxlcyB0aGF0IGNvbnRhaW4gY2FsY3VsYXRlZCBkYXRhIG9yIGRhdGEgZnJvbSBmaWxlcyBzaG91bGQgYmUgaW5jbHVkZWQgdXNpbmcgUiBjb2RlIGNodW5rcy4KCkluIE1hcmtkb3duLCBhIHRhYmxlIGlzIGEgc3RydWN0dXJlZCBwcmVzZW50YXRpb24gb2YgZGF0YSwgb3JnYW5pemVkIGludG8gcm93cyBhbmQgY29sdW1ucy4gVG8gY3JlYXRlIGEgdGFibGUgaW4gTWFya2Rvd24sIHlvdSBjYW4gdXNlIHRoZSB2ZXJ0aWNhbCBsaW5lICJcfCIgdG8gc2VwYXJhdGUgZWFjaCBjb2x1bW4gYW5kIHRocmVlIG9yIG1vcmUgZGFzaGVzICItLS0iIHRvIGNyZWF0ZSB0aGUgaGVhZGVyIGZvciBlYWNoIGNvbHVtbi4gQWRkaXRpb25hbGx5LCB5b3Ugc2hvdWxkIGluY2x1ZGUgYSB2ZXJ0aWNhbCBsaW5lIGF0IGJvdGggZW5kcyBvZiB0aGUgcm93IHRvIHNlcGFyYXRlIGl0IGZyb20gb3RoZXIgY29udGVudC4KClRoZSBtYXJrZG93biBiZWxvdyBwcm9kdWNlcyB0aGlzIHRhYmxlOgoKYGBgICAgICAgICAgCnwgTW9udGggICAgfCBCdWRnZXQgfAp8IC0tLS0tLS0tIHwgLS0tLS0tLXwKfCBKYW51YXJ5ICB8ICQyNTAwICB8CnwgRmVicnVhcnkgfCAkMzAwMCAgfAp8IE1hcmNoICAgIHwgJDQyMDAgIHwKYGBgCgp8IE1vbnRoICAgIHwgQnVkZ2V0IHwKfC0tLS0tLS0tLS18LS0tLS0tLS18CnwgSmFudWFyeSAgfCBcJDI1MDAgfAp8IEZlYnJ1YXJ5IHwgXCQzMDAwIHwKfCBNYXJjaCAgICB8IFwkNDIwMCB8CgpUaGUgY2VsbCB3aWR0aCBkbyBub3QgaGF2ZSB0byBhbGlnbi4KCkFsaWduIHRleHQgaW4gdGhlIGNvbHVtbnMgdG8gdGhlIGxlZnQsIHJpZ2h0LCBvciBjZW50ZXIgYnkgYWRkaW5nIGEgY29sb24gIjoiIHRvIHRoZSBsZWZ0LCByaWdodCwgb3Igb24gYm90aCBzaWRlIG9mIHRoZSBkYXNoZXMgLS0tIHdpdGhpbiB0aGUgaGVhZGVyIHJvdy4gVGhlIGV4YW1wbGUgaXMgcmVuZGVyZWQgYmVsb3c6CgpgYGAgICAgICAgICAKfCBDb3Vyc2UgICAgICAgICAgICB8IENyZWRpdHMgfCBUZXJtICAgfAp8IDotLS0tLS0tLS0tLS0tLS0tIHwgOi0tLS0tLTp8IC0tLS06ICB8CnwgSW50cm8gdG8gUHl0aG9uICAgfCAgIDIgICAgIHwgRmFsbCAgIHwKfCBTUUwgZm9yIEJlZ2lubmVycyB8ICAgMyAgICAgfCBGYWxsICAgfAp8IFN0YXRpc3RpY3Mgd2l0aCBSIHwgICA0ICAgICB8IFNwcmluZyB8CnwgT09EIHdpdGggQysrICAgICAgfCAgIDQgICAgIHwgU3VtbWVyIHwKYGBgCgp8IENvdXJzZSAgICAgICAgICAgIHwgQ3JlZGl0cyB8ICAgVGVybSB8Cnw6LS0tLS0tLS0tLS0tLS0tLS0tfDotLS0tLS0tOnwtLS0tLS0tOnwKfCBJbnRybyB0byBQeXRob24gICB8ICAgIDIgICAgfCAgIEZhbGwgfAp8IFNRTCBmb3IgQmVnaW5uZXJzIHwgICAgMyAgICB8ICAgRmFsbCB8CnwgU3RhdGlzdGljcyB3aXRoIFIgfCAgICA0ICAgIHwgU3ByaW5nIHwKfCBPT0Qgd2l0aCBDKysgICAgICB8ICAgIDQgICAgfCBTdW1tZXIgfAoKLSAgIDotLSBtZWFucyB0aGUgY29sdW1uIGlzIGxlZnQgYWxpZ25lZAotICAgLS06IG1lYW5zIHRoZSBjb2x1bW4gaXMgcmlnaHQgYWxpZ25lZAotICAgOi06IG1lYW5zIHRoZSBjb2x1bW4gaXMgY2VudGVyIGFsaWduZWQKClRleHQgY2FuIGJlIGZvcm1hdHRlZCB3aXRoaW4gdGFibGVzIHVzaW5nIGdlbmVyYWwgbWFya2Rvd24uIEhvd2V2ZXIsIHNvbWUgZm9ybWF0dGluZyBvcHRpb25zIGFyZSBub3QgYXZhaWxhYmxlIHdpdGhpbiB0YWJsZXMsIGluY2x1ZGluZzoKCi0gICBFbWJlZGRlZCBSCi0gICBIZWFkaW5ncwotICAgQmxvY2txdW90ZXMKLSAgIEhvcml6b250YWwgTGluZXMKLSAgIEltYWdlcwotICAgTGlzdHMKLSAgIEVtYmVkZGVkIEhUTUwKCiMjIFN1bW1hcnkKClIgTWFya2Rvd24gaXMgYSB0b29sIHRoYXQgYWxsb3dzIHlvdSB0byBjb21iaW5lIHRleHQgYW5kIGNvZGUgdG8gY3JlYXRlIGRvY3VtZW50cyB0aGF0IGFyZSBib3RoIGh1bWFuLXJlYWRhYmxlIGFuZCBleGVjdXRhYmxlLiBSIE5vdGVib29rcyBhcmUgYSBzcGVjaWZpYyB0eXBlIG9mIFIgTWFya2Rvd24gZG9jdW1lbnQgdGhhdCBhcmUgZGVzaWduZWQgZm9yIGludGVyYWN0aXZlIGRhdGEgYW5hbHlzaXMgYW5kIHJlcHJvZHVjaWJsZSByZXNlYXJjaC4gQnkgdXNpbmcgUiBNYXJrZG93biBhbmQgUiBOb3RlYm9va3MsIHlvdSBjYW4gd3JpdGUgZG9jdW1lbnRzIHRoYXQgaW5jbHVkZSBjb2RlLCB0ZXh0LCBlcXVhdGlvbnMsIGZpZ3VyZXMsIGFuZCBpbnRlcmFjdGl2ZSB2aXN1YWxpemF0aW9ucywgbWFraW5nIGl0IGVhc3kgdG8gZG9jdW1lbnQgeW91ciBhbmFseXNpcyBwcm9jZXNzIGFuZCBzaGFyZSB5b3VyIHJlc3VsdHMgd2l0aCBvdGhlcnMuIEluIHRoaXMgdHV0b3JpYWwsIHlvdSdsbCBsZWFybiBob3cgdG8gY3JlYXRlIFIgTWFya2Rvd24gZG9jdW1lbnRzIGFuZCBSIE5vdGVib29rcywgYW5kIGhvdyB0byB1c2UgTWFya2Rvd24gc3ludGF4IHRvIGZvcm1hdCB5b3VyIHRleHQgYW5kIGVtYmVkIGNvZGUgY2h1bmtzIGluIHlvdXIgZG9jdW1lbnRzLgoKQ29tYmluaW5nIGNvZGUgYW5kIHRleHQgaW4gYSBNYXJrZG93biBkb2N1bWVudCBvZmZlcnMgc2V2ZXJhbCBiZW5lZml0czoKCi0gICAqKlJlcHJvZHVjaWJpbGl0eSoqOiBCeSBlbWJlZGRpbmcgY29kZSBpbiBhIE1hcmtkb3duIGRvY3VtZW50LCB5b3UgY2FuIGVuc3VyZSB0aGF0IG90aGVycyBjYW4gZWFzaWx5IHJlcHJvZHVjZSB5b3VyIHdvcmsuIFRoZXkgY2FuIHNlZSBleGFjdGx5IHdoYXQgY29kZSB5b3UgdXNlZCB0byBnZW5lcmF0ZSB5b3VyIHJlc3VsdHMsIGFuZCB0aGV5IGNhbiBydW4gdGhhdCBjb2RlIHRoZW1zZWx2ZXMgdG8gdmVyaWZ5IHlvdXIgZmluZGluZ3MuCgotICAgKipUcmFuc3BhcmVuY3kqKjogQnkgcHJvdmlkaW5nIGEgY2xlYXIgYW5kIGRldGFpbGVkIHJlY29yZCBvZiB5b3VyIGFuYWx5c2lzIHByb2Nlc3MsIHlvdSBjYW4gaW5jcmVhc2UgdHJhbnNwYXJlbmN5IGFuZCBidWlsZCB0cnVzdCB3aXRoIHlvdXIgYXVkaWVuY2UuIFRoaXMgaXMgZXNwZWNpYWxseSBpbXBvcnRhbnQgaW4gZmllbGRzIGxpa2UgZGF0YSBzY2llbmNlLCB3aGVyZSByZXByb2R1Y2liaWxpdHkgYW5kIHRyYW5zcGFyZW5jeSBhcmUgZXNzZW50aWFsLgoKLSAgICoqRG9jdW1lbnRhdGlvbioqOiBFbWJlZGRpbmcgY29kZSBpbiBhIE1hcmtkb3duIGRvY3VtZW50IGNhbiBhbHNvIG1ha2UgaXQgZWFzaWVyIHRvIGRvY3VtZW50IHlvdXIgd29yay4gQnkgaW5jbHVkaW5nIG5hcnJhdGl2ZSB0ZXh0IGFsb25nc2lkZSB5b3VyIGNvZGUsIHlvdSBjYW4gcHJvdmlkZSBjb250ZXh0IGFuZCBleHBsYW5hdGlvbnMgZm9yIHlvdXIgYW5hbHlzaXMsIG1ha2luZyBpdCBlYXNpZXIgZm9yIG90aGVycyB0byB1bmRlcnN0YW5kIGFuZCByZXBsaWNhdGUgeW91ciB3b3JrLgoKLSAgICoqUHJlc2VudGF0aW9uKio6IE1hcmtkb3duIGRvY3VtZW50cyBjYW4gYmUgZWFzaWx5IGNvbnZlcnRlZCBpbnRvIGEgdmFyaWV0eSBvZiBmb3JtYXRzLCBzdWNoIGFzIEhUTUwsIFBERiwgYW5kIFdvcmQgZG9jdW1lbnRzLiBUaGlzIG1ha2VzIGl0IGVhc3kgdG8gcHJlc2VudCB5b3VyIGFuYWx5c2lzIGluIGEgcG9saXNoZWQgYW5kIHByb2Zlc3Npb25hbCBtYW5uZXIsIHdpdGhvdXQgaGF2aW5nIHRvIG1hbnVhbGx5IGNvcHkgYW5kIHBhc3RlIHlvdXIgY29kZSBhbmQgcmVzdWx0cyBpbnRvIGEgc2VwYXJhdGUgZG9jdW1lbnQuCgpPdmVyYWxsLCBlbWJlZGRpbmcgY29kZSBpbiBhIE1hcmtkb3duIGRvY3VtZW50IGNhbiBtYWtlIHlvdXIgYW5hbHlzaXMgbW9yZSB0cmFuc3BhcmVudCwgcmVwcm9kdWNpYmxlLCBhbmQgd2VsbC1kb2N1bWVudGVkLCB3aGljaCBjYW4gaW1wcm92ZSB0aGUgcXVhbGl0eSBhbmQgY3JlZGliaWxpdHkgb2YgeW91ciBhbmFseXNpcy4KClRoaXMgbGVzc29uIHByb3ZpZGVkIGFuIGludHJvZHVjdGlvbi4gVGhlcmUgYXJlIG1hbnkgbW9yZSBhZHZhbmNlZCBtYXJrZG93biBhbmQgUiBOb3RlYm9vayB0ZWNobmlxdWVzLCBpbmNsdWRpbmcgd3JpdGluZyBib29rcyBhbmQgYnVpbGRpbmcgZnVsbCB3ZWJzaXRlcy4gSW4gZmFjdCwgdGhlIFs6YXJ0aWZpY2l1bV0oaHR0cDovL2FydGlmaWNpdW0udXMpIGxlc3NvbiByZXBvc2l0b3J5IHdhcyBmdWxsIGJ1aWx0IGluIFIgTm90ZWJvb2tzIGFuZCB0aGUgc291cmNlIGZvciB0aGlzIGxlc3NvbiBpcyBhbiBbUiBOb3RlYm9va10obC02LTIwNC5SbWQpLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyBGaWxlcyAmIFJlc291cmNlcwoKYGBge3IgemlwRmlsZXMsIGVjaG89RkFMU0V9CnppcE5hbWUgPSBzcHJpbnRmKCJMZXNzb25GaWxlcy0lcy0lcy56aXAiLCAKICAgICAgICAgICAgICAgICBwYXJhbXMkY2F0ZWdvcnksCiAgICAgICAgICAgICAgICAgcGFyYW1zJG51bWJlcikKCnRleHRBTGluayA9IHBhc3RlMCgiQWxsIEZpbGVzIGZvciBMZXNzb24gIiwgCiAgICAgICAgICAgICAgIHBhcmFtcyRjYXRlZ29yeSwiLiIscGFyYW1zJG51bWJlcikKCiMgZG93bmxvYWRGaWxlc0xpbmsoKSBpcyBpbmNsdWRlZCBmcm9tIF9pbnNlcnQyREIuUgprbml0cjo6cmF3X2h0bWwoZG93bmxvYWRGaWxlc0xpbmsoIi4iLCB6aXBOYW1lLCB0ZXh0QUxpbmspKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgUmVmZXJlbmNlcwoKWGllLCBYLiwgRGVydmlldXgsIEMuLCBSaWVkZXJlciwgRS4gKG4uZC4pLiBSIE1hcmtkb3duIENvb2tib29rLiBBdmFpbGFibGUgYXQgW2Jvb2tkb3duLm9yZ10oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duLWNvb2tib29rLykKCltPdmVydmlldyBvZiBSIE1hcmtkb3duXShodHRwczovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbS8pCgpbUiBNYXJrZG93biBDaGVhdCBTaGVldF0oaHR0cHM6Ly93d3cucnN0dWRpby5jb20vd3AtY29udGVudC91cGxvYWRzLzIwMTUvMDMvcm1hcmtkb3duLXJlZmVyZW5jZS5wZGY/X2dhPTIuNTkxODQxNzMuMTIxNDI1MjkyOC4xNjM1OTgwNDc0LTE5NDk5NTUxNy4xNjM1NDMzNzU3KQoKW1dpa2lwZWRpYTogTGl0ZXJhdGUgUHJvZ3JhbW1pbmddKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0xpdGVyYXRlX3Byb2dyYW1taW5nKQoKW0VtYmVkZGluZyBWZXJiYXRpbSBDb2RlIENodW5rcyBpbiBNYXJrZG93bl0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duLWNvb2tib29rL3ZlcmJhdGltLWNvZGUtY2h1bmtzLmh0bWwpCgojIyBFcnJhdGEKCk5vbmUgY29sbGVjdGVkIHlldC4gTGV0IHVzIGtub3cuCgpgYGB7PWh0bWx9CjxzY3JpcHQgc3JjPSJodHRwczovL2Zvcm0uam90Zm9ybS5jb20vc3RhdGljL2ZlZWRiYWNrMi5qcyIgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4KICBuZXcgSm90Zm9ybUZlZWRiYWNrKHsKICAgIGZvcm1JZDogIjIxMjE4NzA3Mjc4NDE1NyIsCiAgICBidXR0b25UZXh0OiAiRmVlZGJhY2siLAogICAgYmFzZTogImh0dHBzOi8vZm9ybS5qb3Rmb3JtLmNvbS8iLAogICAgYmFja2dyb3VuZDogIiNGNTkyMDIiLAogICAgZm9udENvbG9yOiAiI0ZGRkZGRiIsCiAgICBidXR0b25TaWRlOiAibGVmdCIsCiAgICBidXR0b25BbGlnbjogImNlbnRlciIsCiAgICB0eXBlOiBmYWxzZSwKICAgIHdpZHRoOiA3MDAsCiAgICBoZWlnaHQ6IDUwMCwKICAgIGlzQ2FyZEZvcm06IGZhbHNlCiAgfSk7Cjwvc2NyaXB0PgpgYGAKYGBge3IgY29kZT14ZnVuOjpyZWFkX3V0ZjgocGFzdGUwKGhlcmU6OmhlcmUoKSwnL1IvX2RlcGxveUtuaXQuUicpKSwgaW5jbHVkZSA9IEZBTFNFfQpgYGAK