Welcome to the second lab of dapR 1. This week, we will introduce R Markdown (Rmd), an extremely versatile and powerful tool for writing reproducible documents of all sorts and formats. We promise you that once you get the hang of it, you will never again want to use your ordinary word processor/text editor for writing esssays, coursework, papers, or even presentations or your CV. In fact, all the teaching materials in this course, from the lecture slides to these lab sheets, have been written in Rmd.

By the end of this lab you will:

 

So what is R Markdown? Well, it is a language - or a system - for telling computers how to process and format text. Unlike the more familiar WYSIWYG word processors/text editors, R Markdown (as well as other markup languages) uses plain text symbols for all formatting. In other words, there is no higlighting text and then clicking on a B icon to make it bold. What you do instead, that is the topic of today’s lab. At this point you might be thinking “why on Earth should I be learning this when I can just use the text editor on my computer?!”. That is a good question and the answer to it is that, when it comes to Rmd, its intergration with R Studio makes it an incredibly useful tool for wiriting documents that include the results of a statistical analysis or data visualisations. Just how useful Rmd is should become apparent by the end of this lab.

Hold your hats…

 

Getting things ready

Before you do anything else, open R Studio and install the rmarkdown package if you have not yet done so. This package will enable you to convert files written in Rmd to output of your choice.

Task 10: Type exactly the following command into the console and press ↵ Enter:

 

 

The best way to learn how R markdown (and programming languages really) works is to compare the source and the output and notice the relationships between the two. So let’s do that and take a look at what the Rmd version of this lab sheet looks like.

Task 11: Click on the Code ▾ button in the top-right corner of this document and select “Download Rmd”. Save the file in your “Week_02”1 folder.

R markdown files have the .Rmd extension after their names though it is possible that your computer is set up to hide file extensions (a setting we would encourage you to change). This file type should be automatically associated with R Studio on your computer. If your computer offers you a selection of programs to open the file in, just choose R Studio and tick the “always use this app/program to open files of this type” box, if there is one.

 

Now, unless you have a two-screen setting where you can put windows side-by-side, you will have to frequently switch between your web browser and R Studio. To save time, here is a handy shortcut: Press Alt + ↹ Tab (Windows) or ⌘ Command + ⇥ Tab (Mac OS)2 to switch between the two most recently viewed windows. If you hold down the first of the two keys, you can toggle all currently open windows by pressing Tab multiple times.

Task 12: Open the Week02_Rmd_into.Rmd file (in R Studio) and try out switching between your browser and R Studio using the key shortcut.

 

R Markdown basics

Before we delve into the nitty-gritty of Rmd, let’s have a look at how to do some basic formatting you know from your text editor by comparing this section of the the lab sheet and its corresponding source file:

This is level 1 heading (main heading)

This is level 2 heading (subheading)

This is level 3 heading

And so on…

 

  • Single dash and space after a blank line creates an unordered list (bulletpoints).
    • Lists can be nested by indenting using four spaces (or two Tabs).
      • Deeper and deeper…
  • This is italics.
  • This is also italics.
  • This is boldface.
  • This is also boldface (two underscores).
  • This is strikethrough.
  • This is monospace (backticks are usually right above Tab).

 

  1. This is an ordered list
  2. It is numbered
    • Nested elements cannot be ordered. 2.1 You can try but it will look like this.

 

  1. If you don’t want to worry about numbering lists manually.
  2. You can create them like this
  3. Easy, isn’t it?

A single line break doesn’t do anything.

More than one line break…

…creates a new paragraph.

The \ (there is an important blank space after it!) is a non-bkreaing space; any two words separated by it will be forced to stay on the same line and will not be split over two lines.

 

 

Here, we use it to create a gap between paragraphs by inserting two empty lines.

 

And most importantly for the Rmd-R integration:

[1] 42

 

Any R code can also be evaluated in-line like this: 2 + 3 = 5.

 

 

Feel free to take a moment to make sure you understand the relationship between the R Markdown notation and the resulting output. For a quick reference guide to Rmd, see this cool cheat sheet.

 

Rmd read-along

OK, now that you know the very basics, let’s look at the .Rmd file step-by-step.

The first thing to realise is that an .Rmd file is just a plain text file (such as .txt). You could open it in Notepad, MS Word, or OpenOffice3 and would basically see the same thing as in R Studio. The only reason for the special .Rmd extension is for R Studio to know to put all the nice colours in to aid readability and offer you options associated with R Markdown, such as the option to actually generate a document from the file. So don’t go away thinking there’s some magic going on here: There are just text files.

With that out of the way, keep reading on the document in your browser but let’s scroll all the way up in the .Rmd file. There, you can see this header:

---
title: "Introducing R Markdown"
author: "dapR 1 -- Lab 2"
output:
  html_notebook:
    theme: flatly
    code_folding: show
---

For reasons you don’t need to worry about, this header is written in a different markup language called YAML (Yet Another Markup Language – no kiddin’!). Here, you provide the title of the document, the output format, and many other general options.

In our document, we set the title and author and define the output to be an R notebook. R notebook is a HTML4 file just like most websites, which is why we can easily put it online like this. The neat feature of R notebooks is their ability to show/hide and evaluate code chunks and the fact that you can easily download and edit them in R Studio. That is why we will be using them in our dapR labs.

The theme parameter indented under html_notebook specifies what the document looks like. While you can customise the aesthetics of your documents to your heart’s delight, some nice and smart people have provided us with several basic themes that, in our view, look pretty neat.

Finally, the code_folding parameter governs whether the code chunks should be shown or hidden by default.

While there’s a host of options you can play around with, it is a good idea to always include at least the title and output.

 

OK, next, there are two code chunks. The first one gets generated automatically by R Studio when you create a new .Rmd file (more on that later) and is there to set a very basic default “code chunk option” echo=TRUE. This option tells R Studio to create the ouput file with the code chunks visible. Changing it to echo=FALSE will create a document with code not displayed. You can specify other default options if you wish but that’s a bit of an advanced topic.

Notice two further things about the chunk:

Taken together, the last two paragraphs mean that there are two ways of setting code chunk options:

  1. Globally – Just like the code inside of the first chunk does. Once set like this, the options will apply to all subsequent code chunks.
  2. Locally – Inside the {r, ...} bit at the top of each chunk. These options will apply only to the given code chunk.

There are, again, lots of useful options you can set and, using local options, you can change the behaviour of each individual chunk regardless of what the default—global—setting is. A comprehensive and by no means necessary list can be found in this R markdown reference guide.

 

The second code chunk illustrates this rather nicely. Despite setting echo to TRUE in global options in the first chunk, the second one sets it to FALSE. This means that, for this chunk only, the code will get executed and its output displayed but the code chunk itself will not show up in the final document. However, as it happents, the code in this chunk doesn’t have any output so, in this case echo=FALSE is indistinguishable from include=FALSE. To see the difference, have a look at this chunk:

Here, output gets included in the document but the code does not!

With respect to the actual contents of the second chunk, don’t worry about it too much. You are not supposed to understand at this stage. If you’re really curious though, the code creates a function that puts the “Task X:” before the actual wording of the tasks so that we don’t have to type it all out and worry about which number this particular task is. We’re lazy like that, you see…

 

The rest of the .Rmd file should be fairly readable, especially with the benefit of knowing the markdown syntax for text formatting we talked about above. Remember that, by comparing the .Rmd with the lab sheet, you can always figure out how to do things you haven’t explicitly been taught (e.g., writing in superscript or in subscript).

Perhaps the only slightly puzzling looking bits are the links to other websites. It is not immediately important for you to know how to include these links (AKA hyperlinks, or URLs) so feel free to skip the next section.

 


A short aside on URLs in R Markdown

The anatomy of URL markdown (again, that’s links to you and me) is pretty straightforward. If you want to display the actual URL and make it “clickable”, put the address inside < >:

https://www.some.site (not an acutal website)

If you want to link to a website using custom text, this is how you do it (the bit in quotes is optional):

text you want to make “clickable” (also doesn’t work)

By default, links open in the same tab which can be annoying. To make a link open in a new tab, add {target="_blank"} after the ()s:

Actual example (opens in new tab) – hover over this with your mouse for a moment to see the mouseover info appear.


 

Code chunks

Let’s talk a little more about code chunks (and in-line code), since they are the main reason why Rmd is so useful when it comes to reports of statistical analysis. For one, they are great for creating tables and figures. As a basic demonstration, we can create a simple histogram. Again, at this point, you don’t have to worry about understainding the code itselt. The important bit is that, once you know how to create fancy plots and tables, you can create them directly in your .Rmd file to put them in your paper/report/presentation:

Registered S3 method overwritten by 'dplyr':
  method           from
  print.rowwise_df     

That’s pretty cool, isn’t it? What’s arguable even cooler is the fact, that you can incorporate code in the actual body text. Let’s say we have a chunk of code that runs some analysis, for example takes the mean age of our sample.

With Rmd, we don’t really even have to know what the value of the mean is when writing the results. We can simply use in-line code to have R Studio generate a document that say that the mean age was 28.85.

For the time being, don’t worry about how this is actually done. We will cover that later in depth. For now, simply rejoice in the fact that it can be done ;).

This feature has a very useful consequence: You can write a document in such a way that, if something about your data or analysis changes, you can simply edit the code in the appropriate chunks, re-generate the output file and all the values will get updated. Imagine having to redo a table of 40, 50, 100 numbers – that’s an awfully teatious task and it’s prone to human error. With a proper use of R Markdown you will never have to do it! Imagine how many hours of work that will save you (trust us, it’s a lot). How amazing is that?

 

Generating documents

Now that you have an understanding of the basics of Rmd along with some nifty tricks and can read the source file, let’s talk about how to generate output from the .Rmd’s.

The simplest way of turning the source into output is using the pre-defined shortcuts.

Task 13: Press Ctrl + ⇧ Shift + K (Windows/Linux) or ⌘ Command + ⇧ Shift + K (Mac OS) to turn generate a HTML version of this document.

Hopefully, nothing happend and maybe you spotter R giving you an error statement of some sort written all in red! The reason for this is that, before we generate the file, we need to “run” all the code chunks so that R studio has access to their output.

There are several ways of doing this but the easiest is, once again, with a shortcut.

Task 14: Press Ctrl + Alt + R (Windows/Linux) or ⌘ Command + Alt + R (Mac OS) to run all chunks in this .Rmd file.

Task 15: Wait a few seconds for R to execute your command and then try creating the HTML document again.

The first time you generate a document like this, it can take a while for R to install and run all the tools necessary to produce your output. After a moment, the result should pop out in R Studio’s internal viewer. Take a minute to marvel at your creation!

 

 

OK, that’s plenty now! Close the viewer window and check your “Week_02” folder. Therein, you should find a file called “Week02_Rmd_intro.nb.html” (the .nb bit indicates it’s an R notebook file). This is your actual output. If you open it, it should appear in your default web browser because HTML files are the stuff websites are made from.

 

Next, let’s test the editability feature we have so lauded above! Check the value of the mean of the age variable. In the original file, it should be 28.85.

Task 16: Try changing some numbers in the age variable in the corresponding code chunk, re-run all chunks, and re-generate the file to convince yourself that the mean age will get updated automatically.

Lo and behold, the value is still 28.85… (seriously, change it to something else!)

 

Now, let’s imagine you don’t want a HTML file but a .doc (Word document). In order to get that, you need to change the YAML header so that it reads exactly output: word_document.

Task 17: Generate a Word document from your .Rmd file. If you don’t have MS Office installed on your computer but are using OpenOffice, change the header to output: odt_document.

 

Task 18: For your final task, get your notes from last week’s tutorial and turn them into a nice document written using R Markdown and render it as PDF, R Notebook, or Word (OpenOffice) document.

Well done!

 

That is all we have in store for you for this lab. We suggest you go over what you learnt today to help your newly acquired knowledge settle.

See you next week!


  1. If you have not created a neat folder structure for this course (and all others too!) yet, now is the time to do it. We suggest you create a “Uni” folder whenever you find convenient (e.g., in Documents but please not on your desktop). This folder will store all your files related to your degree. Within it, create a “Year_1” folder, inside of it a “Sem_1” folder, then “dapR_1”, and inside that “Week_01” and “Week_02” folders.

  2. As for Linux, the shortcut depends on your system configuration. Though, if you are using Linux, you probably know how it works.

  3. Other text editors are available but now that you know about Rmd, you won’t be needing any of them.

  4. HyperText Markup Language – there we go again…

LS0tDQp0aXRsZTogIkludHJvZHVjaW5nIFIgTWFya2Rvd24iDQphdXRob3I6ICJkYXBSIDEgLS0gTGFiIDIiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgdGhlbWU6IGZsYXRseQ0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCiAgIyB3b3JkX2RvY3VtZW50OiBkZWZhdWx0DQogICMgb2R0X2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KYGBge3IgdGFza19mdW4sIGVjaG89RkFMU0V9DQp0IDwtIDEgIyBUYXNrIGNvdW50ZXINCnRhc2sgPC0gZnVuY3Rpb24oeCA9IHQpIHsNCiAgdCA8PC0geCArIDENCiAgcmV0dXJuKHBhc3RlMCgiKipUYXNrICIsIHgsICI6ICoqIikpDQp9DQpgYGANCg0KV2VsY29tZSB0byB0aGUgc2Vjb25kIGxhYiBvZiBkYXBSIDEuDQpUaGlzIHdlZWssIHdlIHdpbGwgaW50cm9kdWNlICoqUiBNYXJrZG93bioqIChSbWQpLCBhbiBleHRyZW1lbHkgdmVyc2F0aWxlIGFuZCBwb3dlcmZ1bCB0b29sIGZvciB3cml0aW5nIHJlcHJvZHVjaWJsZSBkb2N1bWVudHMgb2YgYWxsIHNvcnRzIGFuZCBmb3JtYXRzLg0KV2UgcHJvbWlzZSB5b3UgdGhhdCBvbmNlIHlvdSBnZXQgdGhlIGhhbmcgb2YgaXQsIHlvdSB3aWxsIG5ldmVyIGFnYWluIHdhbnQgdG8gdXNlIHlvdXIgb3JkaW5hcnkgd29yZCBwcm9jZXNzb3IvdGV4dCBlZGl0b3IgZm9yIHdyaXRpbmcgZXNzc2F5cywgY291cnNld29yaywgcGFwZXJzLCBvciBldmVuIHByZXNlbnRhdGlvbnMgb3IgeW91ciBDVi4NCkluIGZhY3QsIGFsbCB0aGUgdGVhY2hpbmcgbWF0ZXJpYWxzIGluIHRoaXMgY291cnNlLCBmcm9tIHRoZSBsZWN0dXJlIHNsaWRlcyB0byB0aGVzZSBsYWIgc2hlZXRzLCBoYXZlIGJlZW4gd3JpdHRlbiBpbiBSbWQuDQoNCkJ5IHRoZSBlbmQgb2YgdGhpcyBsYWIgeW91IHdpbGw6DQoNCiAgLSBmaW5kIG91dCBhYm91dCBtYXJrdXAgbGFuZ3VhZ2VzDQogIC0gbGVhcm4gYmFzaWMgdGV4dCBmb3JtYXR0aW5nIHVzaW5nIFIgTWFya2Rvd24NCiAgLSBkaXNjb3ZlciB0aGUgcG93ZXJmdWwgaW50ZWdyYXRpb24gb2YgYFJgIGFuZCB0ZXh0IGVkaXRpbmcgdGhhdCBSIE1hcmtkb3duIG9mZmVycw0KICAtIGxlYXJuIGhvdyB0byB3cml0ZSBIVE1MLCBXb3JkLCBhbmQgT3Blbk9mZmljZSBmaWxlcyBwdXJlbHkgaW4gUiBTdHVkaW8NCg0KXCANCg0KU28gd2hhdCBpcyBSIE1hcmtkb3duPw0KV2VsbCwgaXQgaXMgYSBsYW5ndWFnZSAtIG9yIGEgc3lzdGVtIC0gZm9yIHRlbGxpbmcgY29tcHV0ZXJzIGhvdyB0byBwcm9jZXNzIGFuZCBmb3JtYXQgdGV4dC4NClVubGlrZSB0aGUgbW9yZSBmYW1pbGlhciBbV1lTSVdZR10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvV1lTSVdZRyAiV2hhdCB5b3Ugc2VlIGlzIHdoYXQgeW91IGdldCIpe3RhcmdldD0iX2JsYW5rIn0gd29yZCBwcm9jZXNzb3JzL3RleHQgZWRpdG9ycywgUiBNYXJrZG93biAoYXMgd2VsbCBhcyBvdGhlciBbbWFya3VwIGxhbmd1YWdlc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTWFya3VwX2xhbmd1YWdlKXt0YXJnZXQ9Il9ibGFuayJ9KSB1c2VzIHBsYWluIHRleHQgc3ltYm9scyBmb3IgYWxsIGZvcm1hdHRpbmcuDQpJbiBvdGhlciB3b3JkcywgdGhlcmUgaXMgbm8gaGlnbGlnaHRpbmcgdGV4dCBhbmQgdGhlbiBjbGlja2luZyBvbiBhICoqQioqIGljb24gdG8gbWFrZSBpdCAqKmJvbGQqKi4NCldoYXQgeW91IGRvIGluc3RlYWQsIHRoYXQgaXMgdGhlIHRvcGljIG9mIHRvZGF5J3MgbGFiLg0KQXQgdGhpcyBwb2ludCB5b3UgbWlnaHQgYmUgdGhpbmtpbmcgIndoeSBvbiBFYXJ0aCBzaG91bGQgSSBiZSBsZWFybmluZyB0aGlzIHdoZW4gSSBjYW4ganVzdCB1c2UgdGhlIHRleHQgZWRpdG9yIG9uIG15IGNvbXB1dGVyPyEiLg0KVGhhdCBpcyBhIGdvb2QgcXVlc3Rpb24gYW5kIHRoZSBhbnN3ZXIgdG8gaXQgaXMgdGhhdCwgd2hlbiBpdCBjb21lcyB0byBSbWQsIGl0cyBpbnRlcmdyYXRpb24gd2l0aCBSIFN0dWRpbyBtYWtlcyBpdCBhbiBpbmNyZWRpYmx5IHVzZWZ1bCB0b29sIGZvciB3aXJpdGluZyBkb2N1bWVudHMgdGhhdCBpbmNsdWRlIHRoZSByZXN1bHRzIG9mIGEgc3RhdGlzdGljYWwgYW5hbHlzaXMgb3IgZGF0YSB2aXN1YWxpc2F0aW9ucy4NCkp1c3QgaG93IHVzZWZ1bCBSbWQgaXMgc2hvdWxkIGJlY29tZSBhcHBhcmVudCBieSB0aGUgZW5kIG9mIHRoaXMgbGFiLg0KDQpIb2xkIHlvdXIgaGF0cy4uLg0KDQpcIA0KDQojIEdldHRpbmcgdGhpbmdzIHJlYWR5DQoNCkJlZm9yZSB5b3UgZG8gYW55dGhpbmcgZWxzZSwgb3BlbiBSIFN0dWRpbyBhbmQgaW5zdGFsbCB0aGUgYHJtYXJrZG93bmAgcGFja2FnZSBpZiB5b3UgaGF2ZSBub3QgeWV0IGRvbmUgc28uDQpUaGlzIHBhY2thZ2Ugd2lsbCBlbmFibGUgeW91IHRvIGNvbnZlcnQgZmlsZXMgd3JpdHRlbiBpbiBSbWQgdG8gb3V0cHV0IG9mIHlvdXIgY2hvaWNlLg0KDQpgciB0YXNrKClgVHlwZSAqZXhhY3RseSogdGhlIGZvbGxvd2luZyBjb21tYW5kIGludG8gdGhlIGNvbnNvbGUgYW5kIHByZXNzIDxrYmQ+JmNyYXJyOyBFbnRlcjwva2JkPjoNCg0KYGBge3IgaW5zdGFsbF9ybWQsIGV2YWwgPSBGfQ0KaW5zdGFsbC5wYWNrYWdlcygicm1hcmtkb3duIikNCmBgYA0KDQpcIA0KDQpcIA0KDQpUaGUgYmVzdCB3YXkgdG8gbGVhcm4gaG93IFIgbWFya2Rvd24gKGFuZCBwcm9ncmFtbWluZyBsYW5ndWFnZXMgcmVhbGx5KSB3b3JrcyBpcyB0byBjb21wYXJlIHRoZSBzb3VyY2UgYW5kIHRoZSBvdXRwdXQgYW5kIG5vdGljZSB0aGUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIHRoZSB0d28uDQpTbyBsZXQncyBkbyB0aGF0IGFuZCB0YWtlIGEgbG9vayBhdCB3aGF0IHRoZSBSbWQgdmVyc2lvbiBvZiB0aGlzIGxhYiBzaGVldCBsb29rcyBsaWtlLg0KDQpgciB0YXNrKClgQ2xpY2sgb24gdGhlIDxrYmQ+Q29kZSAmIzk2NjI7PC9rYmQ+IGJ1dHRvbiBpbiB0aGUgdG9wLXJpZ2h0IGNvcm5lciBvZiB0aGlzIGRvY3VtZW50IGFuZCBzZWxlY3QgIkRvd25sb2FkIFJtZCIuDQpTYXZlIHRoZSBmaWxlIGluIHlvdXIgIldlZWtfMDIiW14xXSBmb2xkZXIuDQoNClteMV06IElmIHlvdSBoYXZlIG5vdCBjcmVhdGVkIGEgbmVhdCBmb2xkZXIgc3RydWN0dXJlIGZvciB0aGlzIGNvdXJzZSAoYW5kIGFsbCBvdGhlcnMgdG9vISkgeWV0LCBub3cgaXMgdGhlIHRpbWUgdG8gZG8gaXQuDQpXZSBzdWdnZXN0IHlvdSBjcmVhdGUgYSAiVW5pIiBmb2xkZXIgd2hlbmV2ZXIgeW91IGZpbmQgY29udmVuaWVudCAoKmUuZy4sKiBpbiBEb2N1bWVudHMgYnV0IHBsZWFzZSBub3Qgb24geW91ciBkZXNrdG9wKS4NClRoaXMgZm9sZGVyIHdpbGwgc3RvcmUgYWxsIHlvdXIgZmlsZXMgcmVsYXRlZCB0byB5b3VyIGRlZ3JlZS4NCldpdGhpbiBpdCwgY3JlYXRlIGEgIlllYXJfMSIgZm9sZGVyLCBpbnNpZGUgb2YgaXQgYSAiU2VtXzEiIGZvbGRlciwgdGhlbiAiZGFwUl8xIiwgYW5kIGluc2lkZSB0aGF0ICJXZWVrXzAxIiBhbmQgIldlZWtfMDIiIGZvbGRlcnMuDQoNClIgbWFya2Rvd24gZmlsZXMgaGF2ZSB0aGUgLlJtZCBleHRlbnNpb24gYWZ0ZXIgdGhlaXIgbmFtZXMgdGhvdWdoIGl0IGlzIHBvc3NpYmxlIHRoYXQgeW91ciBjb21wdXRlciBpcyBzZXQgdXAgdG8gaGlkZSBmaWxlIGV4dGVuc2lvbnMgKGEgc2V0dGluZyB3ZSB3b3VsZCBlbmNvdXJhZ2UgeW91IHRvIGNoYW5nZSkuDQpUaGlzIGZpbGUgdHlwZSBzaG91bGQgYmUgYXV0b21hdGljYWxseSBhc3NvY2lhdGVkIHdpdGggUiBTdHVkaW8gb24geW91ciBjb21wdXRlci4NCklmIHlvdXIgY29tcHV0ZXIgb2ZmZXJzIHlvdSBhIHNlbGVjdGlvbiBvZiBwcm9ncmFtcyB0byBvcGVuIHRoZSBmaWxlIGluLCBqdXN0IGNob29zZSBSIFN0dWRpbyBhbmQgdGljayB0aGUgImFsd2F5cyB1c2UgdGhpcyBhcHAvcHJvZ3JhbSB0byBvcGVuIGZpbGVzIG9mIHRoaXMgdHlwZSIgYm94LCBpZiB0aGVyZSBpcyBvbmUuDQoNClwgDQoNCk5vdywgdW5sZXNzIHlvdSBoYXZlIGEgdHdvLXNjcmVlbiBzZXR0aW5nIHdoZXJlIHlvdSBjYW4gcHV0IHdpbmRvd3Mgc2lkZS1ieS1zaWRlLCB5b3Ugd2lsbCBoYXZlIHRvIGZyZXF1ZW50bHkgc3dpdGNoIGJldHdlZW4geW91ciB3ZWIgYnJvd3NlciBhbmQgUiBTdHVkaW8uDQpUbyBzYXZlIHRpbWUsIGhlcmUgaXMgYSBoYW5keSBzaG9ydGN1dDogUHJlc3MgPGtiZD5BbHQ8L2tiZD4gKyA8a2JkPiYjODYzMzsgVGFiPC9rYmQ+IChXaW5kb3dzKSBvciA8a2JkPiYjODk4NDsgQ29tbWFuZDwva2JkPiArIDxrYmQ+JnJhcnJiOyBUYWI8L2tiZD4gKE1hYyBPUylbXjJdIHRvIHN3aXRjaCBiZXR3ZWVuIHRoZSB0d28gbW9zdCByZWNlbnRseSB2aWV3ZWQgd2luZG93cy4NCklmIHlvdSBob2xkIGRvd24gdGhlIGZpcnN0IG9mIHRoZSB0d28ga2V5cywgeW91IGNhbiB0b2dnbGUgYWxsIGN1cnJlbnRseSBvcGVuIHdpbmRvd3MgYnkgcHJlc3NpbmcgPGtiZD5UYWI8L2tiZD4gbXVsdGlwbGUgdGltZXMuDQoNClteMl06IEFzIGZvciBMaW51eCwgdGhlIHNob3J0Y3V0IGRlcGVuZHMgb24geW91ciBzeXN0ZW0gY29uZmlndXJhdGlvbi4NClRob3VnaCwgaWYgeW91IGFyZSB1c2luZyBMaW51eCwgeW91IHByb2JhYmx5IGtub3cgaG93IGl0IHdvcmtzLg0KDQpgciB0YXNrKClgT3BlbiB0aGUgV2VlazAyX1JtZF9pbnRvLlJtZCBmaWxlIChpbiBSIFN0dWRpbykgYW5kIHRyeSBvdXQgc3dpdGNoaW5nIGJldHdlZW4geW91ciBicm93c2VyIGFuZCBSIFN0dWRpbyB1c2luZyB0aGUga2V5IHNob3J0Y3V0Lg0KDQpcIA0KDQojIFIgTWFya2Rvd24gYmFzaWNzDQoNCkJlZm9yZSB3ZSBkZWx2ZSBpbnRvIHRoZSBuaXR0eS1ncml0dHkgb2YgUm1kLCBsZXQncyBoYXZlIGEgbG9vayBhdCBob3cgdG8gZG8gc29tZSBiYXNpYyBmb3JtYXR0aW5nIHlvdSBrbm93IGZyb20geW91ciB0ZXh0IGVkaXRvciBieSBjb21wYXJpbmcgdGhpcyBzZWN0aW9uIG9mIHRoZSB0aGUgbGFiIHNoZWV0IGFuZCBpdHMgY29ycmVzcG9uZGluZyBzb3VyY2UgZmlsZToNCg0KIyBUaGlzIGlzIGxldmVsIDEgaGVhZGluZyAobWFpbiBoZWFkaW5nKQ0KDQojIyBUaGlzIGlzIGxldmVsIDIgaGVhZGluZyAoc3ViaGVhZGluZykNCg0KIyMjIFRoaXMgaXMgbGV2ZWwgMyBoZWFkaW5nDQoNCiMjIyMgQW5kIHNvIG9uLi4uDQoNClwgDQoNCi0gU2luZ2xlIGRhc2ggYW5kIHNwYWNlIGFmdGVyIGEgYmxhbmsgbGluZSBjcmVhdGVzIGFuIHVub3JkZXJlZCBsaXN0IChidWxsZXRwb2ludHMpLg0KICAgIC0gTGlzdHMgY2FuIGJlIG5lc3RlZCBieSBpbmRlbnRpbmcgdXNpbmcgZm91ciBzcGFjZXMgKG9yIHR3byA8a2JkPlRhYjwva2JkPnMpLg0KICAgICAgICAtIERlZXBlciBhbmQgZGVlcGVyLi4uDQotIFRoaXMgaXMgKml0YWxpY3MqLg0KLSBUaGlzIGlzIF9hbHNvIGl0YWxpY3NfLg0KLSBUaGlzIGlzICoqYm9sZGZhY2UqKi4NCi0gVGhpcyBpcyBfX2Fsc28gYm9sZGZhY2VfXyAodHdvIHVuZGVyc2NvcmVzKS4NCi0gVGhpcyBpcyB+fnN0cmlrZXRocm91Z2h+fi4NCi0gVGhpcyBpcyBgbW9ub3NwYWNlYCAoYmFja3RpY2tzIGFyZSB1c3VhbGx5IHJpZ2h0IGFib3ZlIDxrYmQ+VGFiPC9rYmQ+KS4NCg0KXCANCg0KMS4gVGhpcyBpcyBhbiBvcmRlcmVkIGxpc3QNCjIuIEl0IGlzIG51bWJlcmVkDQogICAgLSBOZXN0ZWQgZWxlbWVudHMgY2Fubm90IGJlIG9yZGVyZWQuDQogICAgMi4xIFlvdSBjYW4gdHJ5IGJ1dCBpdCB3aWxsIGxvb2sgbGlrZSB0aGlzLg0KICAgIA0KXCANCg0KIy4gSWYgeW91IGRvbid0IHdhbnQgdG8gd29ycnkgYWJvdXQgbnVtYmVyaW5nIGxpc3RzIG1hbnVhbGx5Lg0KIy4gWW91IGNhbiBjcmVhdGUgdGhlbSBsaWtlIHRoaXMNCiMuIEVhc3ksIGlzbid0IGl0Pw0KDQoNCkEgc2luZ2xlIGxpbmUgYnJlYWsNCmRvZXNuJ3QgZG8gYW55dGhpbmcuDQoNCk1vcmUgdGhhbiBvbmUgbGluZSBicmVhay4uLg0KDQoNCg0KDQouLi5jcmVhdGVzIGEgbmV3IHBhcmFncmFwaC4NCg0KVGhlIFxcICh0aGVyZSBpcyBhbiBpbXBvcnRhbnQgYmxhbmsgc3BhY2UgYWZ0ZXIgaXQhKSBpcyBhIG5vbi1ia3JlYWluZyBzcGFjZTsgYW55IHR3byB3b3JkcyBzZXBhcmF0ZWQgYnkgaXQgd2lsbCBiZSBmb3JjZWRcIHRvXCBzdGF5XCBvblwgdGhlXCBzYW1lXCBsaW5lXCBhbmQgd2lsbCBub3QgYmUgc3BsaXQgb3ZlciB0d28gbGluZXMuDQoNClwgDQoNClwgDQoNCkhlcmUsIHdlIHVzZSBpdCB0byBjcmVhdGUgYSBnYXAgYmV0d2VlbiBwYXJhZ3JhcGhzIGJ5IGluc2VydGluZyB0d28gZW1wdHkgbGluZXMuDQoNClwgDQoNCkFuZCBtb3N0IGltcG9ydGFudGx5IGZvciB0aGUgUm1kLWBSYCBpbnRlZ3JhdGlvbjoNCg0KYGBge3IgYmFzaWNfY2h1bmt9DQojIFRoaXMgaXMgYW4gUiBjb2RlIGNodW5rDQojIEhlcmUgeW91IGNhbiB3cml0ZSBjb2RlIGFuZCBSIHdpbGwgcnVuIGl0IHdoZW4geW91IGdlbmVyYXRlIHlvdXIgZG9jdW1lbnQNCiMgYW5kIGRpc3BsYXkgdGhlIG91dHB1dCBiZWxvdw0KNiAqIDcNCmBgYA0KDQpcIA0KDQpBbnkgYFJgIGNvZGUgY2FuIGFsc28gYmUgZXZhbHVhdGVkIGluLWxpbmUgbGlrZSB0aGlzOiAyICsgMyA9IGByIDIgKyAzYC4NCg0KXCANCg0KXCANCg0KRmVlbCBmcmVlIHRvIHRha2UgYSBtb21lbnQgdG8gbWFrZSBzdXJlIHlvdSB1bmRlcnN0YW5kIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgUiBNYXJrZG93biBub3RhdGlvbiBhbmQgdGhlIHJlc3VsdGluZyBvdXRwdXQuDQpGb3IgYSBxdWljayByZWZlcmVuY2UgZ3VpZGUgdG8gUm1kLCBzZWUgdGhpcyBjb29sIFtjaGVhdCBzaGVldF0oaHR0cHM6Ly93d3cucnN0dWRpby5jb20vd3AtY29udGVudC91cGxvYWRzLzIwMTYvMDMvcm1hcmtkb3duLWNoZWF0c2hlZXQtMi4wLnBkZil7dGFyZ2V0PSJfYmxhbmsifS4NCg0KXCANCg0KIyBSbWQgcmVhZC1hbG9uZw0KDQpPSywgbm93IHRoYXQgeW91IGtub3cgdGhlIHZlcnkgYmFzaWNzLCBsZXQncyBsb29rIGF0IHRoZSAuUm1kIGZpbGUgc3RlcC1ieS1zdGVwLg0KDQpUaGUgZmlyc3QgdGhpbmcgdG8gcmVhbGlzZSBpcyB0aGF0IGFuIC5SbWQgZmlsZSBpcyBqdXN0IGEgKnBsYWluIHRleHQqIGZpbGUgKHN1Y2ggYXMgLnR4dCkuDQpZb3UgY291bGQgb3BlbiBpdCBpbiBOb3RlcGFkLCBNUyBXb3JkLCBvciBPcGVuT2ZmaWNlW14zXSBhbmQgd291bGQgYmFzaWNhbGx5IHNlZSB0aGUgc2FtZSB0aGluZyBhcyBpbiBSIFN0dWRpby4NClRoZSBvbmx5IHJlYXNvbiBmb3IgdGhlIHNwZWNpYWwgLlJtZCBleHRlbnNpb24gaXMgZm9yIFIgU3R1ZGlvIHRvIGtub3cgdG8gcHV0IGFsbCB0aGUgbmljZSBjb2xvdXJzIGluIHRvIGFpZCByZWFkYWJpbGl0eSBhbmQgb2ZmZXIgeW91IG9wdGlvbnMgYXNzb2NpYXRlZCB3aXRoIFIgTWFya2Rvd24sIHN1Y2ggYXMgdGhlIG9wdGlvbiB0byBhY3R1YWxseSBnZW5lcmF0ZSBhIGRvY3VtZW50IGZyb20gdGhlIGZpbGUuDQpTbyBkb24ndCBnbyBhd2F5IHRoaW5raW5nIHRoZXJlJ3Mgc29tZSBtYWdpYyBnb2luZyBvbiBoZXJlOiBUaGVyZSBhcmUganVzdCB0ZXh0IGZpbGVzLg0KDQpbXjNdOiBPdGhlciB0ZXh0IGVkaXRvcnMgYXJlIGF2YWlsYWJsZSBidXQgbm93IHRoYXQgeW91IGtub3cgYWJvdXQgUm1kLCB5b3Ugd29uJ3QgYmUgbmVlZGluZyBhbnkgb2YgdGhlbS4NCg0KV2l0aCB0aGF0IG91dCBvZiB0aGUgd2F5LCBrZWVwIHJlYWRpbmcgb24gdGhlIGRvY3VtZW50IGluIHlvdXIgYnJvd3NlciBidXQgbGV0J3Mgc2Nyb2xsIGFsbCB0aGUgd2F5IHVwIGluIHRoZSAuUm1kIGZpbGUuDQpUaGVyZSwgeW91IGNhbiBzZWUgdGhpcyBoZWFkZXI6DQoNCmBgYA0KLS0tDQp0aXRsZTogIkludHJvZHVjaW5nIFIgTWFya2Rvd24iDQphdXRob3I6ICJkYXBSIDEgLS0gTGFiIDIiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgdGhlbWU6IGZsYXRseQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KLS0tDQpgYGANCg0KRm9yIHJlYXNvbnMgeW91IGRvbid0IG5lZWQgdG8gd29ycnkgYWJvdXQsIHRoaXMgaGVhZGVyIGlzIHdyaXR0ZW4gaW4gYSBkaWZmZXJlbnQgbWFya3VwIGxhbmd1YWdlIGNhbGxlZCBZQU1MIChZZXQgQW5vdGhlciBNYXJrdXAgTGFuZ3VhZ2UgLS0gbm8ga2lkZGluJyEpLg0KSGVyZSwgeW91IHByb3ZpZGUgdGhlIHRpdGxlIG9mIHRoZSBkb2N1bWVudCwgdGhlIG91dHB1dCBmb3JtYXQsIGFuZCBtYW55IG90aGVyIGdlbmVyYWwgW29wdGlvbnNdKGh0dHBzOi8vYm9va2Rvd24ub3JnL3lpaHVpL3JtYXJrZG93bi9odG1sLWRvY3VtZW50Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0uDQoNCkluIG91ciBkb2N1bWVudCwgd2Ugc2V0IHRoZSB0aXRsZSBhbmQgYXV0aG9yIGFuZCBkZWZpbmUgdGhlIG91dHB1dCB0byBiZSBhbiBSIG5vdGVib29rLg0KUiBub3RlYm9vayBpcyBhIEhUTUxbXjRdIGZpbGUganVzdCBsaWtlIG1vc3Qgd2Vic2l0ZXMsIHdoaWNoIGlzIHdoeSB3ZSBjYW4gZWFzaWx5IHB1dCBpdCBvbmxpbmUgbGlrZSB0aGlzLg0KVGhlIG5lYXQgZmVhdHVyZSBvZiBSIG5vdGVib29rcyBpcyB0aGVpciBhYmlsaXR5IHRvIHNob3cvaGlkZSBhbmQgZXZhbHVhdGUgY29kZSBjaHVua3MgYW5kIHRoZSBmYWN0IHRoYXQgeW91IGNhbiBlYXNpbHkgZG93bmxvYWQgYW5kIGVkaXQgdGhlbSBpbiBSIFN0dWRpby4NClRoYXQgaXMgd2h5IHdlIHdpbGwgYmUgdXNpbmcgdGhlbSBpbiBvdXIgZGFwUiBsYWJzLg0KDQpbXjRdOiBIeXBlclRleHQgTWFya3VwIExhbmd1YWdlIC0tIHRoZXJlIHdlIGdvIGFnYWluLi4uDQoNClRoZSBgdGhlbWVgIHBhcmFtZXRlciBpbmRlbnRlZCB1bmRlciBgaHRtbF9ub3RlYm9va2Agc3BlY2lmaWVzIHdoYXQgdGhlIGRvY3VtZW50IGxvb2tzIGxpa2UuDQpXaGlsZSB5b3UgY2FuIGN1c3RvbWlzZSB0aGUgYWVzdGhldGljcyBvZiB5b3VyIGRvY3VtZW50cyB0byB5b3VyIGhlYXJ0J3MgZGVsaWdodCwgc29tZSBuaWNlIGFuZCBzbWFydCBwZW9wbGUgaGF2ZSBwcm92aWRlZCB1cyB3aXRoIHNldmVyYWwgYmFzaWMgdGhlbWVzIHRoYXQsIGluIG91ciB2aWV3LCBsb29rIHByZXR0eSBuZWF0Lg0KDQpGaW5hbGx5LCB0aGUgYGNvZGVfZm9sZGluZ2AgcGFyYW1ldGVyIGdvdmVybnMgd2hldGhlciB0aGUgY29kZSBjaHVua3Mgc2hvdWxkIGJlIHNob3duIG9yIGhpZGRlbiBieSBkZWZhdWx0Lg0KDQpXaGlsZSB0aGVyZSdzIGEgaG9zdCBvZiBvcHRpb25zIHlvdSBjYW4gcGxheSBhcm91bmQgd2l0aCwgaXQgaXMgYSBnb29kIGlkZWEgdG8gKiphbHdheXMgaW5jbHVkZSoqIGF0IGxlYXN0IHRoZSB0aXRsZSBhbmQgb3V0cHV0Lg0KDQpcIA0KDQpPSywgbmV4dCwgdGhlcmUgYXJlIHR3byBjb2RlIGNodW5rcy4NClRoZSBmaXJzdCBvbmUgZ2V0cyBnZW5lcmF0ZWQgYXV0b21hdGljYWxseSBieSBSIFN0dWRpbyB3aGVuIHlvdSBjcmVhdGUgYSBuZXcgLlJtZCBmaWxlIChtb3JlIG9uIHRoYXQgbGF0ZXIpIGFuZCBpcyB0aGVyZSB0byBzZXQgYSB2ZXJ5IGJhc2ljIGRlZmF1bHQgImNvZGUgY2h1bmsgb3B0aW9uIiBgZWNobz1UUlVFYC4NClRoaXMgb3B0aW9uIHRlbGxzIFIgU3R1ZGlvIHRvIGNyZWF0ZSB0aGUgb3VwdXQgZmlsZSB3aXRoIHRoZSBjb2RlIGNodW5rcyB2aXNpYmxlLg0KQ2hhbmdpbmcgaXQgdG8gYGVjaG89RkFMU0VgIHdpbGwgY3JlYXRlIGEgZG9jdW1lbnQgd2l0aCBjb2RlIG5vdCBkaXNwbGF5ZWQuDQpZb3UgY2FuIHNwZWNpZnkgb3RoZXIgZGVmYXVsdCBvcHRpb25zIGlmIHlvdSB3aXNoIGJ1dCB0aGF0J3MgYSBiaXQgb2YgYW4gYWR2YW5jZWQgdG9waWMuDQoNCk5vdGljZSB0d28gZnVydGhlciB0aGluZ3MgYWJvdXQgdGhlIGNodW5rOg0KDQogIC0gSXQgaXMgbmFtZWQgKGBzZXR1cGApIC0tIFRoaXMgZG9lc24ndCByZWFsbHkgZG8gYW55dGhpbmcgYnV0IGl0IGNhbiBiZSBoZWxwZnVsIHdoZW4gZGlhZ25vc3RpbmcgY29kZSBlcnJvcnMgYW5kIGl0J3Mga2luZCBvZiB0aWR5Lg0KICAtIFRoZXJlIGFyZSBmdXJ0aGVyIGNodW5rIG9wdGlvbnM7IGluIHRoaXMgY2FzZSBgaW5jbHVkZT1GQUxTRWAuIFRoaXMgcGFydGljdWxhciBvcHRpb24gbWFrZXMgdGhlIGNvZGUgY2h1bmsgZ2V0IGV2YWx1YXRlZCBidXQgc2hvd3MgbmVpdGhlciB0aGUgY29kZSBub3IgaXRzIG91dHB1dCBpbiB0aGUgZmluYWwgZG9jdW1lbnQuIEluIG90aGVyIHdvcmRzLCBpdCBleGVjdXRlcyB0aGUgY29kZSAqcXVpZXRseSogaW4gdGhlIGJhY2tncm91bmQuDQoNClRha2VuIHRvZ2V0aGVyLCB0aGUgbGFzdCB0d28gcGFyYWdyYXBocyBtZWFuIHRoYXQgdGhlcmUgYXJlIHR3byB3YXlzIG9mIHNldHRpbmcgY29kZSBjaHVuayBvcHRpb25zOg0KDQoxLiAqR2xvYmFsbHkqIC0tIEp1c3QgbGlrZSB0aGUgY29kZSBpbnNpZGUgb2YgdGhlIGZpcnN0IGNodW5rIGRvZXMuIE9uY2Ugc2V0IGxpa2UgdGhpcywgdGhlIG9wdGlvbnMgd2lsbCBhcHBseSB0byBhbGwgc3Vic2VxdWVudCBjb2RlIGNodW5rcy4NCjIuICpMb2NhbGx5KiAtLSBJbnNpZGUgdGhlIGB7ciwgLi4ufWAgYml0IGF0IHRoZSB0b3Agb2YgZWFjaCBjaHVuay4gVGhlc2Ugb3B0aW9ucyB3aWxsIGFwcGx5IG9ubHkgdG8gdGhlIGdpdmVuIGNvZGUgY2h1bmsuDQoNCg0KVGhlcmUgYXJlLCBhZ2FpbiwgbG90cyBvZiB1c2VmdWwgb3B0aW9ucyB5b3UgY2FuIHNldCBhbmQsIHVzaW5nIGxvY2FsIG9wdGlvbnMsIHlvdSBjYW4gY2hhbmdlIHRoZSBiZWhhdmlvdXIgb2YgZWFjaCBpbmRpdmlkdWFsIGNodW5rIHJlZ2FyZGxlc3Mgb2Ygd2hhdCB0aGUgZGVmYXVsdC0tLWdsb2JhbC0tLXNldHRpbmcgaXMuDQpBIGNvbXByZWhlbnNpdmUgYW5kIGJ5IG5vIG1lYW5zIG5lY2Vzc2FyeSBsaXN0IGNhbiBiZSBmb3VuZCBpbiB0aGlzIFtSIG1hcmtkb3duIHJlZmVyZW5jZSBndWlkZV0oaHR0cHM6Ly93d3cucnN0dWRpby5jb20vd3AtY29udGVudC91cGxvYWRzLzIwMTUvMDMvcm1hcmtkb3duLXJlZmVyZW5jZS5wZGYgIkFyZSB5b3UgZ29pbmcgdG8gY2hlY2sgYWxsIGxpbmtzIGZvciBoaWRkZW4gbWVzc2FnZXMgbm93PyIpe3RhcmdldD0iX2JsYW5rIn0uDQoNClwgDQoNClRoZSBzZWNvbmQgY29kZSBjaHVuayBpbGx1c3RyYXRlcyB0aGlzIHJhdGhlciBuaWNlbHkuIERlc3BpdGUgc2V0dGluZyBgZWNob2AgdG8gYFRSVUVgIGluIGdsb2JhbCBvcHRpb25zIGluIHRoZSBmaXJzdCBjaHVuaywgdGhlIHNlY29uZCBvbmUgc2V0cyBpdCB0byBgRkFMU0VgLg0KVGhpcyBtZWFucyB0aGF0LCBmb3IgdGhpcyBjaHVuayBvbmx5LCB0aGUgY29kZSB3aWxsIGdldCBleGVjdXRlZCBhbmQgaXRzIG91dHB1dCBkaXNwbGF5ZWQgYnV0IHRoZSBjb2RlIGNodW5rIGl0c2VsZiB3aWxsIG5vdCBzaG93IHVwIGluIHRoZSBmaW5hbCBkb2N1bWVudC4NCkhvd2V2ZXIsIGFzIGl0IGhhcHBlbnRzLCB0aGUgY29kZSBpbiB0aGlzIGNodW5rIGRvZXNuJ3QgaGF2ZSBhbnkgb3V0cHV0IHNvLCBpbiB0aGlzIGNhc2UgYGVjaG89RkFMU0VgIGlzIGluZGlzdGluZ3Vpc2hhYmxlIGZyb20gYGluY2x1ZGU9RkFMU0VgLg0KVG8gc2VlIHRoZSBkaWZmZXJlbmNlLCBoYXZlIGEgbG9vayBhdCB0aGlzIGNodW5rOg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCnNlbnRlbmNlIDwtICJIZXJlLCBvdXRwdXQgZ2V0cyBpbmNsdWRlZCBpbiB0aGUgZG9jdW1lbnQgYnV0IHRoZSBjb2RlIGRvZXMgbm90ISINCmNhdChzZW50ZW5jZSkNCmBgYA0KDQpXaXRoIHJlc3BlY3QgdG8gdGhlIGFjdHVhbCBjb250ZW50cyBvZiB0aGUgc2Vjb25kIGNodW5rLCBkb24ndCB3b3JyeSBhYm91dCBpdCB0b28gbXVjaC4NCllvdSBhcmUgbm90IHN1cHBvc2VkIHRvIHVuZGVyc3RhbmQgYXQgdGhpcyBzdGFnZS4NCklmIHlvdSdyZSByZWFsbHkgY3VyaW91cyB0aG91Z2gsIHRoZSBjb2RlIGNyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHB1dHMgdGhlICIqKlRhc2sgWDoqKiIgYmVmb3JlIHRoZSBhY3R1YWwgd29yZGluZyBvZiB0aGUgdGFza3Mgc28gdGhhdCB3ZSBkb24ndCBoYXZlIHRvIHR5cGUgaXQgYWxsIG91dCBhbmQgd29ycnkgYWJvdXQgd2hpY2ggbnVtYmVyIHRoaXMgcGFydGljdWxhciB0YXNrIGlzLg0KV2UncmUgbGF6eSBsaWtlIHRoYXQsIHlvdSBzZWUuLi4NCg0KXCANCg0KVGhlIHJlc3Qgb2YgdGhlIC5SbWQgZmlsZSBzaG91bGQgYmUgZmFpcmx5IHJlYWRhYmxlLCBlc3BlY2lhbGx5IHdpdGggdGhlIGJlbmVmaXQgb2Yga25vd2luZyB0aGUgbWFya2Rvd24gc3ludGF4IGZvciB0ZXh0IGZvcm1hdHRpbmcgd2UgdGFsa2VkIGFib3V0IGFib3ZlLg0KUmVtZW1iZXIgdGhhdCwgYnkgY29tcGFyaW5nIHRoZSAuUm1kIHdpdGggdGhlIGxhYiBzaGVldCwgeW91IGNhbiBhbHdheXMgZmlndXJlIG91dCBob3cgdG8gZG8gdGhpbmdzIHlvdSBoYXZlbid0IGV4cGxpY2l0bHkgYmVlbiB0YXVnaHQgKCplLmcuLCogd3JpdGluZyBpbiBec3VwZXJzY3JpcHReIG9yIGluIH5zdWJzY3JpcHR+KS4NCg0KUGVyaGFwcyB0aGUgb25seSBzbGlnaHRseSBwdXp6bGluZyBsb29raW5nIGJpdHMgYXJlIHRoZSBsaW5rcyB0byBvdGhlciB3ZWJzaXRlcy4NCkl0IGlzIG5vdCBpbW1lZGlhdGVseSBpbXBvcnRhbnQgZm9yIHlvdSB0byBrbm93IGhvdyB0byBpbmNsdWRlIHRoZXNlIGxpbmtzIChBS0EgaHlwZXJsaW5rcywgb3IgVVJMcykgc28gZmVlbCBmcmVlIHRvIHNraXAgdGhlIG5leHQgc2VjdGlvbi4NCg0KXCANCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyBBIHNob3J0IGFzaWRlIG9uIFVSTHMgaW4gUiBNYXJrZG93bg0KDQpUaGUgYW5hdG9teSBvZiBVUkwgbWFya2Rvd24gKGFnYWluLCB0aGF0J3MgbGlua3MgdG8geW91IGFuZCBtZSkgaXMgcHJldHR5IHN0cmFpZ2h0Zm9yd2FyZC4NCklmIHlvdSB3YW50IHRvIGRpc3BsYXkgdGhlIGFjdHVhbCBVUkwgYW5kIG1ha2UgaXQgImNsaWNrYWJsZSIsIHB1dCB0aGUgYWRkcmVzcyBpbnNpZGUgPCA+Og0KDQo8aHR0cHM6Ly93d3cuc29tZS5zaXRlPiAobm90IGFuIGFjdXRhbCB3ZWJzaXRlKQ0KDQpJZiB5b3Ugd2FudCB0byBsaW5rIHRvIGEgd2Vic2l0ZSB1c2luZyBjdXN0b20gdGV4dCwgdGhpcyBpcyBob3cgeW91IGRvIGl0ICh0aGUgYml0IGluIHF1b3RlcyBpcyBvcHRpb25hbCk6DQoNClt0ZXh0IHlvdSB3YW50IHRvIG1ha2UgImNsaWNrYWJsZSJdKFVSTCAibW91c2VvdmVyIGluZm8iKSAoYWxzbyBkb2Vzbid0IHdvcmspDQoNCkJ5IGRlZmF1bHQsIGxpbmtzIG9wZW4gaW4gdGhlIHNhbWUgdGFiIHdoaWNoIGNhbiBiZSBhbm5veWluZy4gVG8gbWFrZSBhIGxpbmsgb3BlbiBpbiBhIG5ldyB0YWIsIGFkZCBge3RhcmdldD0iX2JsYW5rIn1gIGFmdGVyIHRoZSAoKXM6DQoNCltBY3R1YWwgZXhhbXBsZSAob3BlbnMgaW4gbmV3IHRhYildKGh0dHBzOi8vZ2lwaHkuY29tL2dpZnMvbDBOaFowYVVTRThmWGFnMTIvaHRtbDUgIk1pbmQgPSBibG93biIpe3RhcmdldD0iX2JsYW5rIn0gLS0gaG92ZXIgb3ZlciB0aGlzIHdpdGggeW91ciBtb3VzZSBmb3IgYSBtb21lbnQgdG8gc2VlIHRoZSBtb3VzZW92ZXIgaW5mbyBhcHBlYXIuDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQpcIA0KDQojIENvZGUgY2h1bmtzDQoNCkxldCdzIHRhbGsgYSBsaXR0bGUgbW9yZSBhYm91dCBjb2RlIGNodW5rcyAoYW5kIGluLWxpbmUgY29kZSksIHNpbmNlIHRoZXkgYXJlIHRoZSBtYWluIHJlYXNvbiB3aHkgUm1kIGlzIHNvIHVzZWZ1bCB3aGVuIGl0IGNvbWVzIHRvIHJlcG9ydHMgb2Ygc3RhdGlzdGljYWwgYW5hbHlzaXMuDQpGb3Igb25lLCB0aGV5IGFyZSBncmVhdCBmb3IgY3JlYXRpbmcgdGFibGVzIGFuZCBmaWd1cmVzLg0KQXMgYSBiYXNpYyBkZW1vbnN0cmF0aW9uLCB3ZSBjYW4gY3JlYXRlIGEgc2ltcGxlICpoaXN0b2dyYW0qLg0KQWdhaW4sIGF0IHRoaXMgcG9pbnQsIHlvdSBkb24ndCBoYXZlIHRvIHdvcnJ5IGFib3V0IHVuZGVyc3RhaW5kaW5nIHRoZSBjb2RlIGl0c2VsdC4NClRoZSBpbXBvcnRhbnQgYml0IGlzIHRoYXQsIG9uY2UgeW91IGtub3cgaG93IHRvIGNyZWF0ZSBmYW5jeSBwbG90cyBhbmQgdGFibGVzLCB5b3UgY2FuIGNyZWF0ZSB0aGVtIGRpcmVjdGx5IGluIHlvdXIgLlJtZCBmaWxlIHRvIHB1dCB0aGVtIGluIHlvdXIgcGFwZXIvcmVwb3J0L3ByZXNlbnRhdGlvbjoNCg0KYGBge3IgaGlzdG9ncmFtfQ0KbGlicmFyeShnZ3Bsb3QyKSAjIGxvYWQgdGhlIGdncGxvdDIgcGFja2FnZQ0KcXBsb3Qocm5vcm0oMTAwMCksIHhsYWIgPSAiVmFsdWUiLCB5bGFiID0gIkZyZXF1ZW5jeSIpICMgYmFzaWMgcXVpY2sgaGlzdG9ncmFtDQpgYGANCg0KVGhhdCdzIHByZXR0eSBjb29sLCBpc24ndCBpdD8gV2hhdCdzIGFyZ3VhYmxlIGV2ZW4gY29vbGVyIGlzIHRoZSBmYWN0LCB0aGF0IHlvdSBjYW4gaW5jb3Jwb3JhdGUgY29kZSBpbiB0aGUgYWN0dWFsIGJvZHkgdGV4dC4gTGV0J3Mgc2F5IHdlIGhhdmUgYSBjaHVuayBvZiBjb2RlIHRoYXQgcnVucyBzb21lIGFuYWx5c2lzLCBmb3IgZXhhbXBsZSB0YWtlcyB0aGUgbWVhbiBhZ2Ugb2Ygb3VyIHNhbXBsZS4NCg0KYGBge3J9DQojIGNyZWF0ZSBhIG1hZGUgdXAgc2VxdWVuY2Ugb2YgbnVtYmVycyBhbmQgcHJldGVuZCB0aGV5IGFyZSB0aGUgYWdlcyBvZiBvdXIgcGFydGljaXBhbnRzDQphZ2UgPC0gYygzNCwgMjIsIDI2LCAyNSwgNDMsMTksIDE5LCAyMCwgMzMsIDI3LCAyNywgMjYsIDU0KQ0KIyBjYWxjdWxhdGUgdGhlaXIgbWVhbiwgcm91bmRlZCB0byAyIGRlY2ltYWwgcGxhY2VzDQptZWFuX2FnZSA8LSByb3VuZChtZWFuKGFnZSksIGRpZ2l0cyA9IDIpDQpgYGANCg0KV2l0aCBSbWQsIHdlIGRvbid0IHJlYWxseSBldmVuIGhhdmUgdG8ga25vdyB3aGF0IHRoZSB2YWx1ZSBvZiB0aGUgbWVhbiBpcyB3aGVuIHdyaXRpbmcgdGhlIHJlc3VsdHMuIFdlIGNhbiBzaW1wbHkgdXNlIGluLWxpbmUgY29kZSB0byBoYXZlIFIgU3R1ZGlvIGdlbmVyYXRlIGEgZG9jdW1lbnQgdGhhdCBzYXkgdGhhdCB0aGUgbWVhbiBhZ2Ugd2FzIGByIG1lYW5fYWdlYC4NCg0KRm9yIHRoZSB0aW1lIGJlaW5nLCBkb24ndCB3b3JyeSBhYm91dCBob3cgdGhpcyBpcyBhY3R1YWxseSBkb25lLiBXZSB3aWxsIGNvdmVyIHRoYXQgbGF0ZXIgaW4gZGVwdGguIEZvciBub3csIHNpbXBseSByZWpvaWNlIGluIHRoZSBmYWN0IHRoYXQgaXQgKmNhbiogYmUgZG9uZSA7KS4NCg0KVGhpcyBmZWF0dXJlIGhhcyBhIHZlcnkgdXNlZnVsIGNvbnNlcXVlbmNlOg0KWW91IGNhbiB3cml0ZSBhIGRvY3VtZW50IGluIHN1Y2ggYSB3YXkgdGhhdCwgaWYgc29tZXRoaW5nIGFib3V0IHlvdXIgZGF0YSBvciBhbmFseXNpcyBjaGFuZ2VzLCB5b3UgY2FuIHNpbXBseSBlZGl0IHRoZSBjb2RlIGluIHRoZSBhcHByb3ByaWF0ZSBjaHVua3MsIHJlLWdlbmVyYXRlIHRoZSBvdXRwdXQgZmlsZSBhbmQgYWxsIHRoZSB2YWx1ZXMgd2lsbCBnZXQgdXBkYXRlZC4NCkltYWdpbmUgaGF2aW5nIHRvIHJlZG8gYSB0YWJsZSBvZiA0MCwgNTAsIDEwMCBudW1iZXJzIC0tIHRoYXQncyBhbiBhd2Z1bGx5IHRlYXRpb3VzIHRhc2sgYW5kIGl0J3MgcHJvbmUgdG8gaHVtYW4gZXJyb3IuDQpXaXRoIGEgcHJvcGVyIHVzZSBvZiBSIE1hcmtkb3duIHlvdSB3aWxsIG5ldmVyIGhhdmUgdG8gZG8gaXQhIEltYWdpbmUgaG93IG1hbnkgaG91cnMgb2Ygd29yayB0aGF0IHdpbGwgc2F2ZSB5b3UgKHRydXN0IHVzLCBpdCdzIGEgbG90KS4gSG93IGFtYXppbmcgaXMgdGhhdD8NCg0KXCANCg0KIyBHZW5lcmF0aW5nIGRvY3VtZW50cw0KDQpOb3cgdGhhdCB5b3UgaGF2ZSBhbiB1bmRlcnN0YW5kaW5nIG9mIHRoZSBiYXNpY3Mgb2YgUm1kIGFsb25nIHdpdGggc29tZSBuaWZ0eSB0cmlja3MgYW5kIGNhbiByZWFkIHRoZSBzb3VyY2UgZmlsZSwgbGV0J3MgdGFsayBhYm91dCBob3cgdG8gZ2VuZXJhdGUgb3V0cHV0IGZyb20gdGhlIC5SbWQncy4NCg0KVGhlIHNpbXBsZXN0IHdheSBvZiB0dXJuaW5nIHRoZSBzb3VyY2UgaW50byBvdXRwdXQgaXMgdXNpbmcgdGhlIHByZS1kZWZpbmVkIHNob3J0Y3V0cy4NCg0KYHIgdGFzaygpYFByZXNzIDxrYmQ+Q3RybDwva2JkPiArIDxrYmQ+JiM4Njc5OyBTaGlmdDwva2JkPiArIDxrYmQ+Szwva2JkPiAoV2luZG93cy9MaW51eCkgb3IgPGtiZD4mIzg5ODQ7IENvbW1hbmQ8L2tiZD4gKyA8a2JkPiYjODY3OTsgU2hpZnQ8L2tiZD4gKyA8a2JkPks8L2tiZD4gKE1hYyBPUykgdG8gdHVybiBnZW5lcmF0ZSBhIEhUTUwgdmVyc2lvbiBvZiB0aGlzIGRvY3VtZW50Lg0KDQpIb3BlZnVsbHksIG5vdGhpbmcgaGFwcGVuZCBhbmQgbWF5YmUgeW91IHNwb3R0ZXIgYFJgIGdpdmluZyB5b3UgYW4gZXJyb3Igc3RhdGVtZW50IG9mIHNvbWUgc29ydCB3cml0dGVuIGFsbCBpbiByZWQhDQpUaGUgcmVhc29uIGZvciB0aGlzIGlzIHRoYXQsIGJlZm9yZSB3ZSBnZW5lcmF0ZSB0aGUgZmlsZSwgd2UgbmVlZCB0byAicnVuIiBhbGwgdGhlIGNvZGUgY2h1bmtzIHNvIHRoYXQgUiBzdHVkaW8gaGFzIGFjY2VzcyB0byB0aGVpciBvdXRwdXQuDQoNClRoZXJlIGFyZSBzZXZlcmFsIHdheXMgb2YgZG9pbmcgdGhpcyBidXQgdGhlIGVhc2llc3QgaXMsIG9uY2UgYWdhaW4sIHdpdGggYSBzaG9ydGN1dC4NCg0KYHIgdGFzaygpYFByZXNzIDxrYmQ+Q3RybDwva2JkPiArIDxrYmQ+QWx0PC9rYmQ+ICsgPGtiZD5SPC9rYmQ+IChXaW5kb3dzL0xpbnV4KSBvciA8a2JkPiYjODk4NDsgQ29tbWFuZDwva2JkPiArIDxrYmQ+QWx0PC9rYmQ+ICsgPGtiZD5SPC9rYmQ+IChNYWMgT1MpIHRvIHJ1biBhbGwgY2h1bmtzIGluIHRoaXMgLlJtZCBmaWxlLg0KDQpgciB0YXNrKClgV2FpdCBhIGZldyBzZWNvbmRzIGZvciBgUmAgdG8gZXhlY3V0ZSB5b3VyIGNvbW1hbmQgYW5kIHRoZW4gdHJ5IGNyZWF0aW5nIHRoZSBIVE1MIGRvY3VtZW50IGFnYWluLg0KDQpUaGUgZmlyc3QgdGltZSB5b3UgZ2VuZXJhdGUgYSBkb2N1bWVudCBsaWtlIHRoaXMsIGl0IGNhbiB0YWtlIGEgd2hpbGUgZm9yIGBSYCB0byBpbnN0YWxsIGFuZCBydW4gYWxsIHRoZSB0b29scyBuZWNlc3NhcnkgdG8gcHJvZHVjZSB5b3VyIG91dHB1dC4NCkFmdGVyIGEgbW9tZW50LCB0aGUgcmVzdWx0IHNob3VsZCBwb3Agb3V0IGluIFIgU3R1ZGlvJ3MgaW50ZXJuYWwgdmlld2VyLg0KVGFrZSBhIG1pbnV0ZSB0byBtYXJ2ZWwgYXQgeW91ciBjcmVhdGlvbiENCg0KXCANCg0KLi4uDQoNClwgDQoNCk9LLCB0aGF0J3MgcGxlbnR5IG5vdyEgQ2xvc2UgdGhlIHZpZXdlciB3aW5kb3cgYW5kIGNoZWNrIHlvdXIgIldlZWtfMDIiIGZvbGRlci4NClRoZXJlaW4sIHlvdSBzaG91bGQgZmluZCBhIGZpbGUgY2FsbGVkICJXZWVrMDJfUm1kX2ludHJvLm5iLmh0bWwiICh0aGUgLm5iIGJpdCBpbmRpY2F0ZXMgaXQncyBhbiBSIG5vdGVib29rIGZpbGUpLg0KVGhpcyBpcyB5b3VyIGFjdHVhbCBvdXRwdXQuDQpJZiB5b3Ugb3BlbiBpdCwgaXQgc2hvdWxkIGFwcGVhciBpbiB5b3VyIGRlZmF1bHQgd2ViIGJyb3dzZXIgYmVjYXVzZSBIVE1MIGZpbGVzIGFyZSB0aGUgc3R1ZmYgd2Vic2l0ZXMgYXJlIG1hZGUgZnJvbS4NCg0KXCANCg0KTmV4dCwgbGV0J3MgdGVzdCB0aGUgZWRpdGFiaWxpdHkgZmVhdHVyZSB3ZSBoYXZlIHNvIGxhdWRlZCBhYm92ZSENCkNoZWNrIHRoZSB2YWx1ZSBvZiB0aGUgbWVhbiBvZiB0aGUgYWdlIHZhcmlhYmxlLg0KSW4gdGhlIG9yaWdpbmFsIGZpbGUsIGl0IHNob3VsZCBiZSAyOC44NS4NCg0KYHIgdGFzaygpYFRyeSBjaGFuZ2luZyBzb21lIG51bWJlcnMgaW4gdGhlIGBhZ2VgIHZhcmlhYmxlIGluIHRoZSBjb3JyZXNwb25kaW5nIGNvZGUgY2h1bmssICpyZS1ydW4gYWxsIGNodW5rcyosIGFuZCByZS1nZW5lcmF0ZSB0aGUgZmlsZSB0byBjb252aW5jZSB5b3Vyc2VsZiB0aGF0IHRoZSBtZWFuIGFnZSB3aWxsIGdldCB1cGRhdGVkIGF1dG9tYXRpY2FsbHkuDQoNCkxvIGFuZCBiZWhvbGQsIHRoZSB2YWx1ZSBpcyBgciBpZmVsc2UobWVhbl9hZ2UgPT0gMjguODUsIHBhc3RlMCgiKipzdGlsbCoqICIsIG1lYW5fYWdlLCAiLi4uIChzZXJpb3VzbHksIGNoYW5nZSBpdCB0byBzb21ldGhpbmcgZWxzZSEpIiksIHBhc3RlMCgibm93ICIsIG1lYW5fYWdlLCAiISBOZWF0Li4uIikpYA0KDQpcIA0KDQpOb3csIGxldCdzIGltYWdpbmUgeW91IGRvbid0IHdhbnQgYSBIVE1MIGZpbGUgYnV0IGEgLmRvYyAoV29yZCBkb2N1bWVudCkuDQpJbiBvcmRlciB0byBnZXQgdGhhdCwgeW91IG5lZWQgdG8gY2hhbmdlIHRoZSBZQU1MIGhlYWRlciBzbyB0aGF0IGl0IHJlYWRzICpleGFjdGx5KiBgb3V0cHV0OiB3b3JkX2RvY3VtZW50YC4gDQoNCmByIHRhc2soKWBHZW5lcmF0ZSBhIFdvcmQgZG9jdW1lbnQgZnJvbSB5b3VyIC5SbWQgZmlsZS4NCklmIHlvdSBkb24ndCBoYXZlIE1TIE9mZmljZSBpbnN0YWxsZWQgb24geW91ciBjb21wdXRlciBidXQgYXJlIHVzaW5nIE9wZW5PZmZpY2UsIGNoYW5nZSB0aGUgaGVhZGVyIHRvIGBvdXRwdXQ6IG9kdF9kb2N1bWVudGAuDQoNClwgDQoNCmByIHRhc2soKWBGb3IgeW91ciBmaW5hbCB0YXNrLCBnZXQgeW91ciBub3RlcyBmcm9tIGxhc3Qgd2VlaydzIHR1dG9yaWFsIGFuZCB0dXJuIHRoZW0gaW50byBhIG5pY2UgZG9jdW1lbnQgd3JpdHRlbiB1c2luZyBSIE1hcmtkb3duIGFuZCByZW5kZXIgaXQgYXMgUERGLCBSIE5vdGVib29rLCBvciBXb3JkIChPcGVuT2ZmaWNlKSBkb2N1bWVudC4NCg0KV2VsbCBkb25lIQ0KDQpcIA0KDQpUaGF0IGlzIGFsbCB3ZSBoYXZlIGluIHN0b3JlIGZvciB5b3UgZm9yIHRoaXMgbGFiLg0KV2Ugc3VnZ2VzdCB5b3UgZ28gb3ZlciB3aGF0IHlvdSBsZWFybnQgdG9kYXkgdG8gaGVscCB5b3VyIG5ld2x5IGFjcXVpcmVkIGtub3dsZWRnZSBzZXR0bGUuDQoNClNlZSB5b3UgbmV4dCB3ZWVrIQ0K