Overview

In todays workshop we will be looking to:

We will also see how to:

Motifs and how to the find them

What are motifs and why try and find them?

Sequence motifs are conserved sequences of nucleotides in DNA/RNA or amino acids in proteins that relate to some function. These functions can be regulatory or structural in the case of DNA/RNA or they may be key elements of biochemical function of a protein, just to name a few. The point is that motifs exist because there has been selective pressure to maintain them in DNA, RNA, and proteins. Therefore, detecting them provides us the ability to make predictions about possible functions.

Finding motifs

There are a wide variety of methods to detect motifs. The simplest involves generating position specific scoring matrices (PSSM) or sometimes called positional weight matrices (PWM).

A general workflow for finding a motif involves:

  1. Identifying regions of DNA, RNA, or proteins (30-100 residues) that you believe to be related in function
  2. Performing sequence alignment between the regions to find similar segments*
  3. Defining boundaries of smaller aligned segments
  4. Determining the amount of information at each position of the alignment

This workflow is very general and often motif detection algorithms add or remove various pieces. To get started, let’s start with the following small set of sequences provided in FASTA format. These have already been aligned and regions not aligning have been removed (i.e. we can start at step 4).

>aldB -18->4
attcgtgatagctgtcgtaaag
>ansB 103->125
ttttgttacctgcctctaactt
>araB1 109->131
aagtgtgacgccgtgcaaataa
>araB2 147->169 
tgccgtgattatagacactttt
>cdd 1 107->129
atttgcgatgcgtcgcgcattt
>crp 1 115->137
taatgtgacgtcctttgcatac
>cya 151->173 
aggtgttaaattgatcacgttt
>cytR 1 125->147
cgatgcgaggcggatcgaaaaa
>dadAX 1 95->117
agatgtgagccagctcaccata
>deoP2 1 75->97
aattgtgatgtgtatcgaagtg
>fur 136->158
aaatgtaagctgtgccacgttt

We’ll start by assessing the information at each position of our alignment. Visit: https://weblogo.berkeley.edu/logo.cgi

Input our sequences above, click “Create Logo”, and let’s see what we get. You should see a graphical representation of the information (or weighted bias) of nucleotides at each position. Notably, we see the classic inverted repeat elements we would expect from a dimeric transcription factor.

Calculating PSSM is a bit more tedious and can be done by hand, but there is some built in functionality to do this in the R package Biostrings.

library(Biostrings)

x <- c(
  'attcgtgatagctgtcgtaaag',
  'ttttgttacctgcctctaactt',
  'aagtgtgacgccgtgcaaataa',
  'tgccgtgattatagacactttt',
  'tgccgtgattatagacactttt',
  'atttgcgatgcgtcgcgcattt',
  'taatgtgacgtcctttgcatac',
  'aggtgttaaattgatcacgttt',
  'cgatgcgaggcggatcgaaaaa',
  'agatgtgagccagctcaccata',
  'aattgtgatgtgtatcgaagtg',
  'aaatgtaagctgtgccacgttt'
)

pwm <- PWM(x, type = c("log2probratio"),
    prior.params = c(A=0.25, C=0.25, G=0.25, T=0.25))

print(pwm) # a PWM
         [,1]        [,2]       [,3]        [,4]        [,5]        [,6]        [,7]        [,8]       [,9]
A  0.04636581  0.03628188 0.03628188 -0.01721157 -0.01721157 -0.01721157  0.01317597  0.05626927 0.01317597
C  0.01317597 -0.01721157 0.02427388  0.03121683 -0.01721157  0.02427388 -0.01721157 -0.01721157 0.03121683
G -0.01721157  0.04027158 0.02427388 -0.01721157  0.05626927 -0.01721157  0.05096560 -0.01721157 0.03121683
T  0.03628188  0.03121683 0.03628188  0.05096560 -0.01721157  0.05290380  0.02427388 -0.01721157 0.04027158
       [,10]      [,11]      [,12]      [,13]      [,14]      [,15]       [,16]       [,17]       [,18]
A 0.02427388 0.02427388 0.01317597 0.02427388 0.03121683 0.02427388 -0.01721157  0.04356351  0.03628188
C 0.03121683 0.03628188 0.03121683 0.02427388 0.03121683 0.01317597  0.05466142 -0.01721157  0.04636581
G 0.04027158 0.01317597 0.04027158 0.03628188 0.03628188 0.02427388 -0.01721157  0.04027158 -0.01721157
T 0.02427388 0.04027158 0.03121683 0.03628188 0.02427388 0.04636581  0.01317597  0.01317597  0.01317597
       [,19]      [,20]       [,21]      [,22]
A 0.04636581 0.03121683  0.03628188 0.03121683
C 0.01317597 0.01317597 -0.01721157 0.01317597
G 0.02427388 0.01317597 -0.01721157 0.02427388
T 0.02427388 0.04636581  0.04880544 0.04356351
print(-log10(pwm)) # a PSSM
Warning in print(-log10(pwm)) : NaNs produced
      [,1]     [,2]     [,3]     [,4]     [,5]     [,6]     [,7]     [,8]     [,9]    [,10]    [,11]
A 1.333802 1.440310 1.440310      NaN      NaN      NaN 1.880217 1.249729 1.880217 1.614861 1.614861
C 1.880217      NaN 1.614861 1.505611      NaN 1.614861      NaN      NaN 1.505611 1.505611 1.440310
G      NaN 1.395001 1.614861      NaN 1.249729      NaN 1.292723      NaN 1.505611 1.395001 1.880217
T 1.440310 1.505611 1.440310 1.292723      NaN 1.276513 1.614861      NaN 1.395001 1.614861 1.395001
     [,12]    [,13]    [,14]    [,15]    [,16]    [,17]    [,18]    [,19]    [,20]    [,21]    [,22]
A 1.880217 1.614861 1.505611 1.614861      NaN 1.360877 1.440310 1.333802 1.505611 1.440310 1.505611
C 1.505611 1.614861 1.505611 1.880217 1.262319      NaN 1.333802 1.880217 1.880217      NaN 1.880217
G 1.395001 1.440310 1.440310 1.614861      NaN 1.395001      NaN 1.614861 1.880217      NaN 1.614861
T 1.505611 1.440310 1.614861 1.333802 1.880217 1.880217 1.880217 1.614861 1.333802 1.311532 1.360877

Now, with our PSSM (or PWM in this case) you can begin to search for this same motif in new sequences. Let’s have R do this for us. There is simple functionality in the Biostring package to do this, as well.

subject_string = 'CCGCTTGCTGCAACTCTCTCAGGGCCAGGCGGTGAAGGGCAATCAGCTGTTGCCCGTCTCACTGGTGAAAAGAAAAACCACCCTGGCGCCCAATACGCAAACCGCCTCTCCCCGCGCGTTGGCCGATTCATTAATGCAGCTGGCACGACAGGTTTCCCGACTGGAAAGCGGGCAGTGAGCGCAACGCAATTAATGTGAGTTAGCTCACTCATTAGGCACCCCAGGCTTTACACTTTATGCTTCCGGCTCGTATGTTGTGTGGAATTGTGAGCGGATAACAATTTCACACAGGAAACAGCT'

matchPWM(pwm,subject_string)
Views on a 300-letter DNAString subject
subject: CCGCTTGCTGCAACTCTCTCAGGGCCAGGCGGTGAAGGGCAATCAGCT...TGTTGTGTGGAATTGTGAGCGGATAACAATTTCACACAGGAAACAGCT
views:
      start end width
  [1]   191 212    22 [TAATGTGAGTTAGCTCACTCAT]

Online tools for motifs

There are wide variety of online tools for motif generation and searching. One useful online toolkit is the MEME-Suite (https://meme-suite.org/meme/). MEME-Suite uses a probability-based framework (Bayesian) to identify motifs and use them in subsequent searches. There are a variety of tools for various purposes. Let’s explore!

>lacZ
CCGCTTGCTG CAACTCTCTC AGGGCCAGGC GGTGAAGGGC AATCAGCTGT TGCCCGTCTC
ACTGGTGAAA AGAAAAACCA CCCTGGCGCC CAATACGCAA ACCGCCTCTC CCCGCGCGTT
GGCCGATTCA TTAATGCAGC TGGCACGACA GGTTTCCCGA CTGGAAAGCG GGCAGTGAGC
GCAACGCAAT TAATGTGAGT TAGCTCACTC ATTAGGCACC CCAGGCTTTA CACTTTATGC
TTCCGGCTCG TATGTTGTGT GGAATTGTGA GCGGATAACA ATTTCACACA GGAAACAGCT
>araB
GTCCATATTG CATCAGACAT TGCCGTCACT GCGTCTTTTA CTGGCTCTTC TCGCTAACCC
AACCGGTAAC CCCGCTTATT AAAAGCATTC TGTAACAAAG CGGGACCAAA GCCATGACAA
AAACGCGTAA CAAAAGTGTC TATAATCACG GCAGAAAAGT CCACATTGAT TATTTGCACG
GCGTCACACT TTGCTATGCC ATAGCATTTT TATCCATAAG ATTAGCGGAT CCTACCTGAC
GCTTTTTATC GCAACTCTCT ACTGTTTCTC CATACCCGTT TTTTTGGATG GAGTGAAACG
>xylA
CAATTTTTAG CAACTAAACA GGGGAAAACA ATTACAGATT TTTATCTTTC GATTACGATT
TTTGGTTTAT TTCTTGATTT ATGACCGAGA TCTTACTTTT GTTGCGCAAT TGTACTTATT
GCATTTTTCT CTTCGAGGAA TTACCCAGTT TCATCATTCC ATTTTATTTT GCGAGCGAGC
GCACACTTGT GAATTATCTC AATAGCAGTG TGAAATAACA TAATTGAGCA ACTGAAAGGG
AGTGCCCAAT ATTACGACAT CATCCATCAC CCGCGGCATT ACCTGATTAT GGAGTTCAAT
>marR
CCAAGAAATA ACGCGACAGT TGTTAATGGG TTAGCTAACG GCAGCAACAC CACCAGCCCC
AGGCCAATTG CTTTAAACAA ATCTAACATT GGTGGTTGTT ATCCTGTGTA TCTGGGTTAT
CAGCGAAAAG TATAAGGGGT AAACAAGGAT AAAGTGTCAC TCTTTAGCTA GCCTTGCATC
GCATTGAACA AAACTTGAAC CGATTTAGCA AAACGTGGCA TCGGTCAATT CATTCATTTG
ACTTATACTT GCCTGGGCAA TATTATCCCC TGCAACTAAT TACTTGCCAG GGCAACTAAT

Question

Why do you suspect the motifs found by creating a PWM and searching were different than those found using MEME suite?

Genome browsers and their general properties

How are genome browsers helpful?

The answer to this basic question is pretty straightforward: genome browsers aggregate a lot of useful information about the genetic information of an organism into one place. By analogy, we might think of genome browsers as the Amazon of genetic information - there is a lot of information available that serves a wide variety of interests.

Assembling a genome browser is a painstaking effort. All of the information within a genome browser is a reflection if that data being held within a database. In fact, not just one database but a variety of different distinct databases. That said these projects are not perfect and are under constant refinement.

Genome browsers are often tailored for specific needs. We will take a look at a few examples today. Each has similar, yet different, focuses. The UCSC Genome Browser, for example, is very focused on providing users with a highly flexible interface whereas the NCBI Genome Viewer (which is newer) is focused on providing a streamlined user experience and integration into other NCBI tools (e.g. BLAST). Both share nearly identical data since both draw information from the same sources.

Genome browsers provide a visual representation of complex genetic information. In simple terms, we get to look at the physical map of an organisms genome. Ask any geneticist 50 years ago what they would think about this and most would describe this as absolutely revolutionary. This visual representation is the gateway to myriad data we can explore through the click of a link. The best way to get aquainted with genome browsers is to use them!

UCSC Genome Browser

The UCSC Genome Browser is one of the oldest (modern) genome browser interfaces. It is highly extensible and even allows users to upload their own genomic data for visualization. Let’s check it out.

https://genome.ucsc.edu/

Select the hg19 assembly for our exercises below. Once hg19 is selected, perform a search for ACE2.

Tracks

In the UCSC browser, information is organized into tracks. These tracks a distinct components of information related to that region of DNA. There a lot of tracks that can be added or removed based on user preferences in the menus at the bottom. The default settings provide the most general use for novice users.

Let’s look at the gene expression information for a minute.

Question

What tissue has the highest levels of ACE2 expression?

R and the UCSC Genome Brower

There are extensive R packages allowing R to interact with or use data in the UCSC Genome Browser.

The following is a short example of how the package rtracklayer can be used to

###################################################
### chunk number 1: rtl-init
###################################################
library(rtracklayer)
data(targets)

###################################################
### chunk number 2: rtl-miRNA-track
###################################################
targetTrack <- makeGRangesFromDataFrame(targets,
                   keep.extra.columns=TRUE)


###################################################
### chunk number 3: rtl-export eval=FALSE
###################################################
## export(targetTrack, "targets.wig")


###################################################
### chunk number 4: rtl-ucsc-start
###################################################
session <- browserSession()
genome(session) <- "hg18"


###################################################
### chunk number 5: rtl-ucsc-lay
###################################################
session$targets <- targetTrack


###################################################
### chunk number 6: rtl-ucsc-view eval=FALSE
###################################################
top <- targetTrack$target == targets$target[1]
range <- targetTrack[top,] * -10
view <- browserView(session, range,
                    hide = c("refGene", "mgcFullMrna", "intronEst"),
                    dense = "knownGene", squish = "cons44way")

NCBI Genome Data Viewer

The NCBI Genome Data Viewer is a newer platform that allows extensive integration into the NCBI toolkit. Chief among these is the BLAST framework. As we’ll see, for many purposes the UCSC and NCBI interfaces differ slightly with respect to information. For many users, use really comes down to personal and/or historical preference. Notably, there are no well-vetted R packages available to interact with the NCBI Genome Viewer at this time.

Go to: https://www.ncbi.nlm.nih.gov/genome/gdv/

Simple searching

Select the Homo sapiens link and search for ACE2.

Question

What is one similarity and one difference you note between the UCSC and NCBI interfaces?

Integration into NCBI toolkits (BLAST)

If we zoom into the gene and hover our cursor over the protein or nucleotide sequence, we will see a series of links to NCBI record entries as well as various BLAST tools. Go ahead and hover over the protein sequence (red) of isoform 2. Navigate to the NCBI BLASTP interface via the link in the pop-up menu. You’ll note the NCBI RefSeq number has been pasted into the search field. Now you can adjust your BLAST search as you see fit for your purposes.

Note, the homework question will require you to BLAST search with the peptide sequence of an exon and not the entire protein.

Adding and removing tracks

The default viewer settings for NCBI are minimal but don’t let that fool you. If you click on the tracks menu, you will see you can add and remove many other tracks to modify your viewing experience.

LS0tCnRpdGxlOiAiTW9kdWxlIDMgV29ya3Nob3AgRXhlcmNpc2VzIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKIyBPdmVydmlldwoKSW4gdG9kYXlzIHdvcmtzaG9wIHdlIHdpbGwgYmUgbG9va2luZyB0bzoKCi0gVXNlIHNvbWUgUFNTTSBhbmQgSE1NIHRvb2xzIHRvIGlkZW50aWZ5IHNlcXVlbmNlIG1vdGlmcwotIEV4cGxvcmUgZ2Vub21lcyB1c2luZyBkaWZmZXJlbnQgZ2Vub21lIGJyb3dzZXIgcGxhdGZvcm1zCgpXZSB3aWxsIGFsc28gc2VlIGhvdyB0bzoKCi0gVXNlIFIgdG8gcGVyZm9ybSBtb3RpZiBmaW5kaW5nCi0gVXNlIFIgdG8gcGVyZm9ybSBiYXNpYyBnZW5vbWUgYnJvd3NlciBvcGVyYXRpb25zCgoKIyBNb3RpZnMgYW5kIGhvdyB0byB0aGUgZmluZCB0aGVtCgojIyBXaGF0IGFyZSBtb3RpZnMgYW5kIHdoeSB0cnkgYW5kIGZpbmQgdGhlbT8KClNlcXVlbmNlIG1vdGlmcyBhcmUgY29uc2VydmVkIHNlcXVlbmNlcyBvZiBudWNsZW90aWRlcyBpbiBETkEvUk5BIG9yIGFtaW5vIGFjaWRzIGluIHByb3RlaW5zIHRoYXQgcmVsYXRlIHRvIHNvbWUgZnVuY3Rpb24uIFRoZXNlIGZ1bmN0aW9ucyBjYW4gYmUgcmVndWxhdG9yeSBvciBzdHJ1Y3R1cmFsIGluIHRoZSBjYXNlIG9mIEROQS9STkEgb3IgdGhleSBtYXkgYmUga2V5IGVsZW1lbnRzIG9mIGJpb2NoZW1pY2FsIGZ1bmN0aW9uIG9mIGEgcHJvdGVpbiwganVzdCB0byBuYW1lIGEgZmV3LiBUaGUgcG9pbnQgaXMgdGhhdCBtb3RpZnMgZXhpc3QgYmVjYXVzZSB0aGVyZSBoYXMgYmVlbiBzZWxlY3RpdmUgcHJlc3N1cmUgdG8gbWFpbnRhaW4gdGhlbSBpbiBETkEsIFJOQSwgYW5kIHByb3RlaW5zLiBUaGVyZWZvcmUsIGRldGVjdGluZyB0aGVtIHByb3ZpZGVzIHVzIHRoZSBhYmlsaXR5IHRvIG1ha2UgcHJlZGljdGlvbnMgYWJvdXQgcG9zc2libGUgZnVuY3Rpb25zLgoKIyMgRmluZGluZyBtb3RpZnMKClRoZXJlIGFyZSBhIHdpZGUgdmFyaWV0eSBvZiBtZXRob2RzIHRvIGRldGVjdCBtb3RpZnMuIFRoZSBzaW1wbGVzdCBpbnZvbHZlcyBnZW5lcmF0aW5nIHBvc2l0aW9uIHNwZWNpZmljIHNjb3JpbmcgbWF0cmljZXMgKFBTU00pIG9yIHNvbWV0aW1lcyBjYWxsZWQgcG9zaXRpb25hbCB3ZWlnaHQgbWF0cmljZXMgKFBXTSkuCgpBIGdlbmVyYWwgd29ya2Zsb3cgZm9yIGZpbmRpbmcgYSBtb3RpZiBpbnZvbHZlczoKCjEuICAgIElkZW50aWZ5aW5nIHJlZ2lvbnMgb2YgRE5BLCBSTkEsIG9yIHByb3RlaW5zICgzMC0xMDAgcmVzaWR1ZXMpIHRoYXQgeW91IGJlbGlldmUgdG8gYmUgcmVsYXRlZCBpbiBmdW5jdGlvbgoyLiAgICBQZXJmb3JtaW5nIHNlcXVlbmNlIGFsaWdubWVudCBiZXR3ZWVuIHRoZSByZWdpb25zIHRvIGZpbmQgc2ltaWxhciBzZWdtZW50cyoKMy4gICAgRGVmaW5pbmcgYm91bmRhcmllcyBvZiBzbWFsbGVyIGFsaWduZWQgc2VnbWVudHMKNC4gICAgRGV0ZXJtaW5pbmcgdGhlIGFtb3VudCBvZiBpbmZvcm1hdGlvbiBhdCBlYWNoIHBvc2l0aW9uIG9mIHRoZSBhbGlnbm1lbnQKClRoaXMgd29ya2Zsb3cgaXMgdmVyeSBnZW5lcmFsIGFuZCBvZnRlbiBtb3RpZiBkZXRlY3Rpb24gYWxnb3JpdGhtcyBhZGQgb3IgcmVtb3ZlIHZhcmlvdXMgcGllY2VzLiBUbyBnZXQgc3RhcnRlZCwgbGV0J3Mgc3RhcnQgd2l0aCB0aGUgZm9sbG93aW5nIHNtYWxsIHNldCBvZiBzZXF1ZW5jZXMgcHJvdmlkZWQgaW4gRkFTVEEgZm9ybWF0LiBUaGVzZSBoYXZlIGFscmVhZHkgYmVlbiBhbGlnbmVkIGFuZCByZWdpb25zIG5vdCBhbGlnbmluZyBoYXZlIGJlZW4gcmVtb3ZlZCAoaS5lLiB3ZSBjYW4gc3RhcnQgYXQgc3RlcCA0KS4KCiAgICA+YWxkQiAtMTgtPjQKICAgIGF0dGNndGdhdGFnY3RndGNndGFhYWcKICAgID5hbnNCIDEwMy0+MTI1CiAgICB0dHR0Z3R0YWNjdGdjY3RjdGFhY3R0CiAgICA+YXJhQjEgMTA5LT4xMzEKICAgIGFhZ3RndGdhY2djY2d0Z2NhYWF0YWEKICAgID5hcmFCMiAxNDctPjE2OSAKICAgIHRnY2NndGdhdHRhdGFnYWNhY3R0dHQKICAgID5jZGQgMSAxMDctPjEyOQogICAgYXR0dGdjZ2F0Z2NndGNnY2djYXR0dAogICAgPmNycCAxIDExNS0+MTM3CiAgICB0YWF0Z3RnYWNndGNjdHR0Z2NhdGFjCiAgICA+Y3lhIDE1MS0+MTczIAogICAgYWdndGd0dGFhYXR0Z2F0Y2FjZ3R0dAogICAgPmN5dFIgMSAxMjUtPjE0NwogICAgY2dhdGdjZ2FnZ2NnZ2F0Y2dhYWFhYQogICAgPmRhZEFYIDEgOTUtPjExNwogICAgYWdhdGd0Z2FnY2NhZ2N0Y2FjY2F0YQogICAgPmRlb1AyIDEgNzUtPjk3CiAgICBhYXR0Z3RnYXRndGd0YXRjZ2FhZ3RnCiAgICA+ZnVyIDEzNi0+MTU4CiAgICBhYWF0Z3RhYWdjdGd0Z2NjYWNndHR0CgpXZSdsbCBzdGFydCBieSBhc3Nlc3NpbmcgdGhlIGluZm9ybWF0aW9uIGF0IGVhY2ggcG9zaXRpb24gb2Ygb3VyIGFsaWdubWVudC4gVmlzaXQ6IGh0dHBzOi8vd2VibG9nby5iZXJrZWxleS5lZHUvbG9nby5jZ2kKCklucHV0IG91ciBzZXF1ZW5jZXMgYWJvdmUsIGNsaWNrICJDcmVhdGUgTG9nbyIsIGFuZCBsZXQncyBzZWUgd2hhdCB3ZSBnZXQuIFlvdSBzaG91bGQgc2VlIGEgZ3JhcGhpY2FsIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBpbmZvcm1hdGlvbiAob3Igd2VpZ2h0ZWQgYmlhcykgb2YgbnVjbGVvdGlkZXMgYXQgZWFjaCBwb3NpdGlvbi4gTm90YWJseSwgd2Ugc2VlIHRoZSBjbGFzc2ljIGludmVydGVkIHJlcGVhdCBlbGVtZW50cyB3ZSB3b3VsZCBleHBlY3QgZnJvbSBhIGRpbWVyaWMgdHJhbnNjcmlwdGlvbiBmYWN0b3IuCgpDYWxjdWxhdGluZyBQU1NNIGlzIGEgYml0IG1vcmUgdGVkaW91cyBhbmQgY2FuIGJlIGRvbmUgYnkgaGFuZCwgYnV0IHRoZXJlIGlzIHNvbWUgYnVpbHQgaW4gZnVuY3Rpb25hbGl0eSB0byBkbyB0aGlzIGluIHRoZSBSIHBhY2thZ2UgYEJpb3N0cmluZ3NgLgoKYGBge3J9CmxpYnJhcnkoQmlvc3RyaW5ncykKCnggPC0gYygKICAnYXR0Y2d0Z2F0YWdjdGd0Y2d0YWFhZycsCiAgJ3R0dHRndHRhY2N0Z2NjdGN0YWFjdHQnLAogICdhYWd0Z3RnYWNnY2NndGdjYWFhdGFhJywKICAndGdjY2d0Z2F0dGF0YWdhY2FjdHR0dCcsCiAgJ3RnY2NndGdhdHRhdGFnYWNhY3R0dHQnLAogICdhdHR0Z2NnYXRnY2d0Y2djZ2NhdHR0JywKICAndGFhdGd0Z2FjZ3RjY3R0dGdjYXRhYycsCiAgJ2FnZ3RndHRhYWF0dGdhdGNhY2d0dHQnLAogICdjZ2F0Z2NnYWdnY2dnYXRjZ2FhYWFhJywKICAnYWdhdGd0Z2FnY2NhZ2N0Y2FjY2F0YScsCiAgJ2FhdHRndGdhdGd0Z3RhdGNnYWFndGcnLAogICdhYWF0Z3RhYWdjdGd0Z2NjYWNndHR0JwopCgpwd20gPC0gUFdNKHgsIHR5cGUgPSBjKCJsb2cycHJvYnJhdGlvIiksCiAgICBwcmlvci5wYXJhbXMgPSBjKEE9MC4yNSwgQz0wLjI1LCBHPTAuMjUsIFQ9MC4yNSkpCgpwcmludChwd20pICMgYSBQV00KYGBgCgpOb3csIHdpdGggb3VyIFBTU00gKG9yIFBXTSBpbiB0aGlzIGNhc2UpIHlvdSBjYW4gYmVnaW4gdG8gc2VhcmNoIGZvciB0aGlzIHNhbWUgbW90aWYgaW4gbmV3IHNlcXVlbmNlcy4gTGV0J3MgaGF2ZSBSIGRvIHRoaXMgZm9yIHVzLiBUaGVyZSBpcyBzaW1wbGUgZnVuY3Rpb25hbGl0eSBpbiB0aGUgQmlvc3RyaW5nIHBhY2thZ2UgdG8gZG8gdGhpcywgYXMgd2VsbC4KCmBgYHtyfQpzdWJqZWN0X3N0cmluZyA9ICdDQ0dDVFRHQ1RHQ0FBQ1RDVENUQ0FHR0dDQ0FHR0NHR1RHQUFHR0dDQUFUQ0FHQ1RHVFRHQ0NDR1RDVENBQ1RHR1RHQUFBQUdBQUFBQUNDQUNDQ1RHR0NHQ0NDQUFUQUNHQ0FBQUNDR0NDVENUQ0NDQ0dDR0NHVFRHR0NDR0FUVENBVFRBQVRHQ0FHQ1RHR0NBQ0dBQ0FHR1RUVENDQ0dBQ1RHR0FBQUdDR0dHQ0FHVEdBR0NHQ0FBQ0dDQUFUVEFBVEdUR0FHVFRBR0NUQ0FDVENBVFRBR0dDQUNDQ0NBR0dDVFRUQUNBQ1RUVEFUR0NUVENDR0dDVENHVEFUR1RUR1RHVEdHQUFUVEdUR0FHQ0dHQVRBQUNBQVRUVENBQ0FDQUdHQUFBQ0FHQ1QnCgptYXRjaFBXTShwd20sc3ViamVjdF9zdHJpbmcpCmBgYAoKIyMgT25saW5lIHRvb2xzIGZvciBtb3RpZnMKClRoZXJlIGFyZSB3aWRlIHZhcmlldHkgb2Ygb25saW5lIHRvb2xzIGZvciBtb3RpZiBnZW5lcmF0aW9uIGFuZCBzZWFyY2hpbmcuIE9uZSB1c2VmdWwgb25saW5lIHRvb2xraXQgaXMgdGhlIE1FTUUtU3VpdGUgKGh0dHBzOi8vbWVtZS1zdWl0ZS5vcmcvbWVtZS8pLiBNRU1FLVN1aXRlIHVzZXMgYSBwcm9iYWJpbGl0eS1iYXNlZCBmcmFtZXdvcmsgKEJheWVzaWFuKSB0byBpZGVudGlmeSBtb3RpZnMgYW5kIHVzZSB0aGVtIGluIHN1YnNlcXVlbnQgc2VhcmNoZXMuIFRoZXJlIGFyZSBhIHZhcmlldHkgb2YgdG9vbHMgZm9yIHZhcmlvdXMgcHVycG9zZXMuIExldCdzIGV4cGxvcmUhCgogICAgPmxhY1oKICAgIENDR0NUVEdDVEcgQ0FBQ1RDVENUQyBBR0dHQ0NBR0dDIEdHVEdBQUdHR0MgQUFUQ0FHQ1RHVCBUR0NDQ0dUQ1RDCiAgICBBQ1RHR1RHQUFBIEFHQUFBQUFDQ0EgQ0NDVEdHQ0dDQyBDQUFUQUNHQ0FBIEFDQ0dDQ1RDVEMgQ0NDR0NHQ0dUVAogICAgR0dDQ0dBVFRDQSBUVEFBVEdDQUdDIFRHR0NBQ0dBQ0EgR0dUVFRDQ0NHQSBDVEdHQUFBR0NHIEdHQ0FHVEdBR0MKICAgIEdDQUFDR0NBQVQgVEFBVEdUR0FHVCBUQUdDVENBQ1RDIEFUVEFHR0NBQ0MgQ0NBR0dDVFRUQSBDQUNUVFRBVEdDCiAgICBUVENDR0dDVENHIFRBVEdUVEdUR1QgR0dBQVRUR1RHQSBHQ0dHQVRBQUNBIEFUVFRDQUNBQ0EgR0dBQUFDQUdDVAogICAgPmFyYUIKICAgIEdUQ0NBVEFUVEcgQ0FUQ0FHQUNBVCBUR0NDR1RDQUNUIEdDR1RDVFRUVEEgQ1RHR0NUQ1RUQyBUQ0dDVEFBQ0NDCiAgICBBQUNDR0dUQUFDIENDQ0dDVFRBVFQgQUFBQUdDQVRUQyBUR1RBQUNBQUFHIENHR0dBQ0NBQUEgR0NDQVRHQUNBQQogICAgQUFBQ0dDR1RBQSBDQUFBQUdUR1RDIFRBVEFBVENBQ0cgR0NBR0FBQUFHVCBDQ0FDQVRUR0FUIFRBVFRUR0NBQ0cKICAgIEdDR1RDQUNBQ1QgVFRHQ1RBVEdDQyBBVEFHQ0FUVFRUIFRBVENDQVRBQUcgQVRUQUdDR0dBVCBDQ1RBQ0NUR0FDCiAgICBHQ1RUVFRUQVRDIEdDQUFDVENUQ1QgQUNUR1RUVENUQyBDQVRBQ0NDR1RUIFRUVFRUR0dBVEcgR0FHVEdBQUFDRwogICAgPnh5bEEKICAgIENBQVRUVFRUQUcgQ0FBQ1RBQUFDQSBHR0dHQUFBQUNBIEFUVEFDQUdBVFQgVFRUQVRDVFRUQyBHQVRUQUNHQVRUCiAgICBUVFRHR1RUVEFUIFRUQ1RUR0FUVFQgQVRHQUNDR0FHQSBUQ1RUQUNUVFRUIEdUVEdDR0NBQVQgVEdUQUNUVEFUVAogICAgR0NBVFRUVFRDVCBDVFRDR0FHR0FBIFRUQUNDQ0FHVFQgVENBVENBVFRDQyBBVFRUVEFUVFRUIEdDR0FHQ0dBR0MKICAgIEdDQUNBQ1RUR1QgR0FBVFRBVENUQyBBQVRBR0NBR1RHIFRHQUFBVEFBQ0EgVEFBVFRHQUdDQSBBQ1RHQUFBR0dHCiAgICBBR1RHQ0NDQUFUIEFUVEFDR0FDQVQgQ0FUQ0NBVENBQyBDQ0dDR0dDQVRUIEFDQ1RHQVRUQVQgR0dBR1RUQ0FBVAogICAgPm1hclIKICAgIENDQUFHQUFBVEEgQUNHQ0dBQ0FHVCBUR1RUQUFUR0dHIFRUQUdDVEFBQ0cgR0NBR0NBQUNBQyBDQUNDQUdDQ0NDCiAgICBBR0dDQ0FBVFRHIENUVFRBQUFDQUEgQVRDVEFBQ0FUVCBHR1RHR1RUR1RUIEFUQ0NUR1RHVEEgVENUR0dHVFRBVAogICAgQ0FHQ0dBQUFBRyBUQVRBQUdHR0dUIEFBQUNBQUdHQVQgQUFBR1RHVENBQyBUQ1RUVEFHQ1RBIEdDQ1RUR0NBVEMKICAgIEdDQVRUR0FBQ0EgQUFBQ1RUR0FBQyBDR0FUVFRBR0NBIEFBQUNHVEdHQ0EgVENHR1RDQUFUVCBDQVRUQ0FUVFRHCiAgICBBQ1RUQVRBQ1RUIEdDQ1RHR0dDQUEgVEFUVEFUQ0NDQyBUR0NBQUNUQUFUIFRBQ1RUR0NDQUcgR0dDQUFDVEFBVAoKIyMjCioqUXVlc3Rpb24qKgoKV2h5IGRvIHlvdSBzdXNwZWN0IHRoZSBtb3RpZnMgZm91bmQgYnkgY3JlYXRpbmcgYSBQV00gYW5kIHNlYXJjaGluZyB3ZXJlIGRpZmZlcmVudCB0aGFuIHRob3NlIGZvdW5kIHVzaW5nIE1FTUUgc3VpdGU/CgojIyMKCiMgR2Vub21lIGJyb3dzZXJzIGFuZCB0aGVpciBnZW5lcmFsIHByb3BlcnRpZXMKCiMjIEhvdyBhcmUgZ2Vub21lIGJyb3dzZXJzIGhlbHBmdWw/CgpUaGUgYW5zd2VyIHRvIHRoaXMgYmFzaWMgcXVlc3Rpb24gaXMgcHJldHR5IHN0cmFpZ2h0Zm9yd2FyZDogZ2Vub21lIGJyb3dzZXJzIGFnZ3JlZ2F0ZSBhIGxvdCBvZiB1c2VmdWwgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGdlbmV0aWMgaW5mb3JtYXRpb24gb2YgYW4gb3JnYW5pc20gaW50byBvbmUgcGxhY2UuIEJ5IGFuYWxvZ3ksIHdlIG1pZ2h0IHRoaW5rIG9mIGdlbm9tZSBicm93c2VycyBhcyB0aGUgQW1hem9uIG9mIGdlbmV0aWMgaW5mb3JtYXRpb24gLSB0aGVyZSBpcyBhIGxvdCBvZiBpbmZvcm1hdGlvbiBhdmFpbGFibGUgdGhhdCBzZXJ2ZXMgYSB3aWRlIHZhcmlldHkgb2YgaW50ZXJlc3RzLgoKQXNzZW1ibGluZyBhIGdlbm9tZSBicm93c2VyIGlzIGEgcGFpbnN0YWtpbmcgZWZmb3J0LiBBbGwgb2YgdGhlIGluZm9ybWF0aW9uIHdpdGhpbiBhIGdlbm9tZSBicm93c2VyIGlzIGEgcmVmbGVjdGlvbiBpZiB0aGF0IGRhdGEgYmVpbmcgaGVsZCB3aXRoaW4gYSBkYXRhYmFzZS4gSW4gZmFjdCwgbm90IGp1c3Qgb25lIGRhdGFiYXNlIGJ1dCBhIHZhcmlldHkgb2YgZGlmZmVyZW50IGRpc3RpbmN0IGRhdGFiYXNlcy4gVGhhdCBzYWlkIHRoZXNlIHByb2plY3RzIGFyZSBub3QgcGVyZmVjdCBhbmQgYXJlIHVuZGVyIGNvbnN0YW50IHJlZmluZW1lbnQuCgpHZW5vbWUgYnJvd3NlcnMgYXJlIG9mdGVuIHRhaWxvcmVkIGZvciBzcGVjaWZpYyBuZWVkcy4gV2Ugd2lsbCB0YWtlIGEgbG9vayBhdCBhIGZldyBleGFtcGxlcyB0b2RheS4gRWFjaCBoYXMgc2ltaWxhciwgeWV0IGRpZmZlcmVudCwgZm9jdXNlcy4gVGhlIFVDU0MgR2Vub21lIEJyb3dzZXIsIGZvciBleGFtcGxlLCBpcyB2ZXJ5IGZvY3VzZWQgb24gcHJvdmlkaW5nIHVzZXJzIHdpdGggYSBoaWdobHkgZmxleGlibGUgaW50ZXJmYWNlIHdoZXJlYXMgdGhlIE5DQkkgR2Vub21lIFZpZXdlciAod2hpY2ggaXMgbmV3ZXIpIGlzIGZvY3VzZWQgb24gcHJvdmlkaW5nIGEgc3RyZWFtbGluZWQgdXNlciBleHBlcmllbmNlIGFuZCBpbnRlZ3JhdGlvbiBpbnRvIG90aGVyIE5DQkkgdG9vbHMgKGUuZy4gQkxBU1QpLiBCb3RoIHNoYXJlIG5lYXJseSBpZGVudGljYWwgZGF0YSBzaW5jZSBib3RoIGRyYXcgaW5mb3JtYXRpb24gZnJvbSB0aGUgc2FtZSBzb3VyY2VzLgoKR2Vub21lIGJyb3dzZXJzIHByb3ZpZGUgYSB2aXN1YWwgcmVwcmVzZW50YXRpb24gb2YgY29tcGxleCBnZW5ldGljIGluZm9ybWF0aW9uLiBJbiBzaW1wbGUgdGVybXMsIHdlIGdldCB0byBsb29rIGF0IHRoZSBwaHlzaWNhbCBtYXAgb2YgYW4gb3JnYW5pc21zIGdlbm9tZS4gQXNrIGFueSBnZW5ldGljaXN0IDUwIHllYXJzIGFnbyB3aGF0IHRoZXkgd291bGQgdGhpbmsgYWJvdXQgdGhpcyBhbmQgbW9zdCB3b3VsZCBkZXNjcmliZSB0aGlzIGFzIGFic29sdXRlbHkgcmV2b2x1dGlvbmFyeS4gVGhpcyB2aXN1YWwgcmVwcmVzZW50YXRpb24gaXMgdGhlIGdhdGV3YXkgdG8gbXlyaWFkIGRhdGEgd2UgY2FuIGV4cGxvcmUgdGhyb3VnaCB0aGUgY2xpY2sgb2YgYSBsaW5rLiBUaGUgYmVzdCB3YXkgdG8gZ2V0IGFxdWFpbnRlZCB3aXRoIGdlbm9tZSBicm93c2VycyBpcyB0byB1c2UgdGhlbSEKCiMgVUNTQyBHZW5vbWUgQnJvd3NlcgoKVGhlIFVDU0MgR2Vub21lIEJyb3dzZXIgaXMgb25lIG9mIHRoZSBvbGRlc3QgKG1vZGVybikgZ2Vub21lIGJyb3dzZXIgaW50ZXJmYWNlcy4gSXQgaXMgaGlnaGx5IGV4dGVuc2libGUgYW5kIGV2ZW4gYWxsb3dzIHVzZXJzIHRvIHVwbG9hZCB0aGVpciBvd24gZ2Vub21pYyBkYXRhIGZvciB2aXN1YWxpemF0aW9uLiBMZXQncyBjaGVjayBpdCBvdXQuCgpodHRwczovL2dlbm9tZS51Y3NjLmVkdS8KClNlbGVjdCB0aGUgaGcxOSBhc3NlbWJseSBmb3Igb3VyIGV4ZXJjaXNlcyBiZWxvdy4gT25jZSBoZzE5IGlzIHNlbGVjdGVkLCBwZXJmb3JtIGEgc2VhcmNoIGZvciAqQUNFMiouCgojIyBUcmFja3MKCkluIHRoZSBVQ1NDIGJyb3dzZXIsIGluZm9ybWF0aW9uIGlzIG9yZ2FuaXplZCBpbnRvICp0cmFja3MqLiBUaGVzZSB0cmFja3MgYSBkaXN0aW5jdCBjb21wb25lbnRzIG9mIGluZm9ybWF0aW9uIHJlbGF0ZWQgdG8gdGhhdCByZWdpb24gb2YgRE5BLiBUaGVyZSBhIGxvdCBvZiB0cmFja3MgdGhhdCBjYW4gYmUgYWRkZWQgb3IgcmVtb3ZlZCBiYXNlZCBvbiB1c2VyIHByZWZlcmVuY2VzIGluIHRoZSBtZW51cyBhdCB0aGUgYm90dG9tLiBUaGUgZGVmYXVsdCBzZXR0aW5ncyBwcm92aWRlIHRoZSBtb3N0IGdlbmVyYWwgdXNlIGZvciBub3ZpY2UgdXNlcnMuCgpMZXQncyBsb29rIGF0IHRoZSBnZW5lIGV4cHJlc3Npb24gaW5mb3JtYXRpb24gZm9yIGEgbWludXRlLgoKIyMjCioqUXVlc3Rpb24qKgoKV2hhdCB0aXNzdWUgaGFzIHRoZSBoaWdoZXN0IGxldmVscyBvZiAqQUNFMiogZXhwcmVzc2lvbj8KCiMjIwoKIyMgUiBhbmQgdGhlIFVDU0MgR2Vub21lIEJyb3dlcgoKVGhlcmUgYXJlIGV4dGVuc2l2ZSBSIHBhY2thZ2VzIGFsbG93aW5nIFIgdG8gaW50ZXJhY3Qgd2l0aCBvciB1c2UgZGF0YSBpbiB0aGUgVUNTQyBHZW5vbWUgQnJvd3Nlci4KClRoZSBmb2xsb3dpbmcgaXMgYSBzaG9ydCBleGFtcGxlIG9mIGhvdyB0aGUgcGFja2FnZSBgcnRyYWNrbGF5ZXJgIGNhbiBiZSB1c2VkIHRvIAoKYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMgY2h1bmsgbnVtYmVyIDE6IHJ0bC1pbml0CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpsaWJyYXJ5KHJ0cmFja2xheWVyKQpkYXRhKHRhcmdldHMpCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIGNodW5rIG51bWJlciAyOiBydGwtbWlSTkEtdHJhY2sKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCnRhcmdldFRyYWNrIDwtIG1ha2VHUmFuZ2VzRnJvbURhdGFGcmFtZSh0YXJnZXRzLAogICAgICAgICAgICAgICAgICAga2VlcC5leHRyYS5jb2x1bW5zPVRSVUUpCgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyBjaHVuayBudW1iZXIgMzogcnRsLWV4cG9ydCBldmFsPUZBTFNFCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyBleHBvcnQodGFyZ2V0VHJhY2ssICJ0YXJnZXRzLndpZyIpCgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyBjaHVuayBudW1iZXIgNDogcnRsLXVjc2Mtc3RhcnQKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCnNlc3Npb24gPC0gYnJvd3NlclNlc3Npb24oKQpnZW5vbWUoc2Vzc2lvbikgPC0gImhnMTgiCgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyBjaHVuayBudW1iZXIgNTogcnRsLXVjc2MtbGF5CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpzZXNzaW9uJHRhcmdldHMgPC0gdGFyZ2V0VHJhY2sKCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIGNodW5rIG51bWJlciA2OiBydGwtdWNzYy12aWV3IGV2YWw9RkFMU0UKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCnRvcCA8LSB0YXJnZXRUcmFjayR0YXJnZXQgPT0gdGFyZ2V0cyR0YXJnZXRbMV0KcmFuZ2UgPC0gdGFyZ2V0VHJhY2tbdG9wLF0gKiAtMTAKdmlldyA8LSBicm93c2VyVmlldyhzZXNzaW9uLCByYW5nZSwKICAgICAgICAgICAgICAgICAgICBoaWRlID0gYygicmVmR2VuZSIsICJtZ2NGdWxsTXJuYSIsICJpbnRyb25Fc3QiKSwKICAgICAgICAgICAgICAgICAgICBkZW5zZSA9ICJrbm93bkdlbmUiLCBzcXVpc2ggPSAiY29uczQ0d2F5IikKYGBgCgoKIyBOQ0JJIEdlbm9tZSBEYXRhIFZpZXdlcgoKVGhlIE5DQkkgR2Vub21lIERhdGEgVmlld2VyIGlzIGEgbmV3ZXIgcGxhdGZvcm0gdGhhdCBhbGxvd3MgZXh0ZW5zaXZlIGludGVncmF0aW9uIGludG8gdGhlIE5DQkkgdG9vbGtpdC4gQ2hpZWYgYW1vbmcgdGhlc2UgaXMgdGhlIEJMQVNUIGZyYW1ld29yay4gQXMgd2UnbGwgc2VlLCBmb3IgbWFueSBwdXJwb3NlcyB0aGUgVUNTQyBhbmQgTkNCSSBpbnRlcmZhY2VzIGRpZmZlciBzbGlnaHRseSB3aXRoIHJlc3BlY3QgdG8gaW5mb3JtYXRpb24uIEZvciBtYW55IHVzZXJzLCB1c2UgcmVhbGx5IGNvbWVzIGRvd24gdG8gcGVyc29uYWwgYW5kL29yIGhpc3RvcmljYWwgcHJlZmVyZW5jZS4gTm90YWJseSwgdGhlcmUgYXJlIG5vIHdlbGwtdmV0dGVkIFIgcGFja2FnZXMgYXZhaWxhYmxlIHRvIGludGVyYWN0IHdpdGggdGhlIE5DQkkgR2Vub21lIFZpZXdlciBhdCB0aGlzIHRpbWUuCgpHbyB0bzogaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9nZW5vbWUvZ2R2LwoKIyMgU2ltcGxlIHNlYXJjaGluZwoKU2VsZWN0IHRoZSAqSG9tbyBzYXBpZW5zKiBsaW5rIGFuZCBzZWFyY2ggZm9yICpBQ0UyKi4KCiMjIwoqKlF1ZXN0aW9uKioKCldoYXQgaXMgb25lIHNpbWlsYXJpdHkgYW5kIG9uZSBkaWZmZXJlbmNlIHlvdSBub3RlIGJldHdlZW4gdGhlIFVDU0MgYW5kIE5DQkkgaW50ZXJmYWNlcz8KCiMjIwoKCiMjIEludGVncmF0aW9uIGludG8gTkNCSSB0b29sa2l0cyAoQkxBU1QpCgpJZiB3ZSB6b29tIGludG8gdGhlIGdlbmUgYW5kIGhvdmVyIG91ciBjdXJzb3Igb3ZlciB0aGUgcHJvdGVpbiBvciBudWNsZW90aWRlIHNlcXVlbmNlLCB3ZSB3aWxsIHNlZSBhIHNlcmllcyBvZiBsaW5rcyB0byBOQ0JJIHJlY29yZCBlbnRyaWVzIGFzIHdlbGwgYXMgdmFyaW91cyBCTEFTVCB0b29scy4gR28gYWhlYWQgYW5kIGhvdmVyIG92ZXIgdGhlIHByb3RlaW4gc2VxdWVuY2UgKHJlZCkgb2YgaXNvZm9ybSAyLiBOYXZpZ2F0ZSB0byB0aGUgTkNCSSBCTEFTVFAgaW50ZXJmYWNlIHZpYSB0aGUgbGluayBpbiB0aGUgcG9wLXVwIG1lbnUuIFlvdSdsbCBub3RlIHRoZSBOQ0JJIFJlZlNlcSBudW1iZXIgaGFzIGJlZW4gcGFzdGVkIGludG8gdGhlIHNlYXJjaCBmaWVsZC4gTm93IHlvdSBjYW4gYWRqdXN0IHlvdXIgQkxBU1Qgc2VhcmNoIGFzIHlvdSBzZWUgZml0IGZvciB5b3VyIHB1cnBvc2VzLgoKTm90ZSwgdGhlIGhvbWV3b3JrIHF1ZXN0aW9uIHdpbGwgcmVxdWlyZSB5b3UgdG8gQkxBU1Qgc2VhcmNoIHdpdGggdGhlIHBlcHRpZGUgc2VxdWVuY2Ugb2YgYW4gZXhvbiBhbmQgbm90IHRoZSBlbnRpcmUgcHJvdGVpbi4KCiMjIEFkZGluZyBhbmQgcmVtb3ZpbmcgdHJhY2tzCgpUaGUgZGVmYXVsdCB2aWV3ZXIgc2V0dGluZ3MgZm9yIE5DQkkgYXJlIG1pbmltYWwgYnV0IGRvbid0IGxldCB0aGF0IGZvb2wgeW91LiBJZiB5b3UgY2xpY2sgb24gdGhlIHRyYWNrcyBtZW51LCB5b3Ugd2lsbCBzZWUgeW91IGNhbiBhZGQgYW5kIHJlbW92ZSBtYW55IG90aGVyIHRyYWNrcyB0byBtb2RpZnkgeW91ciB2aWV3aW5nIGV4cGVyaWVuY2UuCgoK