Olá, esta é mais uma de um conjunto de práticas em bioinformática desenvolvidas para o curso de Biomedicina da PUC MG. Você pode encontrar as demais práticas aqui.
Arquivos .fasta e .fastq
Na prática passada você aprendeu a utilizar um script bioinformático para realizar a tradução de uma sequência de nucleotídeos na sequência correspondente de AA, a partir de um arquivo .fasta. Hoje iremos explorar mais este tipo de arquivo tão utilizado na bioinfo.
Como já vimos, os arquivos .fasta são arquivos que armazenam sequências de DNA, RNA ou proteínas. Cada arquivo pode conter uma única sequência ou várias, sendo ocasionalmente referido como multifasta. É neste formato que são armazenados genomas de referência e genes. Este também é o arquivo utilizado para alinhamentos e buscas por similaridade, como o BLAST.
Já os arquivos .fastq são arquivos que armazenam sequências burtas geradas por sequenciadores de nova geração (NGS), e apresentam, além da sequência das reads, identificadores de qualidade baseados na métrica de qualidade PHRED. Estes arquivos podem armazenar centenas de milhares de sequências, que precisam ser processadas para fornecer alguma informação biológica.
Como veremos a seguir, há funcionalidades específicas para cada um desses arquivos. No entanto, algumas avaliações mais simples podem ser realizadas com ambos, observando suas diferenças estruturais.
Acessando servidores
Como sabemos pela prática, a instalação de alguns programas de bioinformática na plataforma WSL requer privilégios de administrador, o que dificulta seu uso em computadores institucionais, como os das aulas práticas. Assim, hoje iremos conectar diretamente a um servidor computacional para realizar nossas análises. Servidor ou Servidora é um dos nomes que se dá a um computador em que uma ou mais pessoas trabalham remotamente, ou seja, você conecta a ele a partir do seu computador, que serve apenas como uma interface. Enquanto conectado, todo o processamento computacional é realizado no Servidor. Assim, eventualmente, os arquivos que forem usados, precisam ser tranferidos de um computador para o outro, e aprenderemos como fazer isso hoje.
Os servidores são computadores muito poderosos, e, por isso, muito visados por hackers. Desta maneira, a conexão com eles deve ser realizada de maneira segura, e não se deve compartilhar credenciais de acesso sem os devidos cuidados. Assim, esta prática não apresentará todas as informações necessárias para a conexão. Estas informações serão transmitidas apenas durante a aula.Mas, caso você esteja realizando as práticas no seu próprio computador, você pode instalar os programas que utilizaremos sem restrição, e pode realizar todos os passos práticos localmente. Não será uma tarefa simples para iniciantes, mas as instruções para a instalação de cada programa estão disponíveis nos respectivos links, e qualquer suporte pode ser solicitado diretametne comigo.
Instalando os programas
Caso você vá realizar a prática durante a aula, no servidor, pode ir para a próxima sessão. Mas caso você vá realizar a prática no seu própiro computador, os programas que utilizaremos podem ser encontrados aqui:
Os arquivos que utilizaremos podem ser baixados aqui.
Conexão por SSH
A maneira mais utilizada para a conexão com servidores ou outros computadores é a conexão por SSH. Este é um protocolo de rede criptografado, que se baseia na utilização de usuários e senhas para tornar segura a conexão entre dois computadores. Assim, cada usuário precisa ter uma conta (login e senha) cadastrada no computador alvo (o Servidor). Para nossas práticas, criei um usuário geral para todos conectarmos simultaneamente num de nossos Servidores.
Utilizando as credenciais fornecidas durante a aula, conecte no servidor de trabalho via SSH. Quando solicitado, forneça a senha:
#ex:
#ssh usuario@111.222.333.444
ssh $USER@$IP
Caso a conexão seja realizada com sucesso, você verá uma tela de boas vindas com informações sobre o servidor.
Utilizando o comando htop verifique as características de hardware e os processos que estão rodando no servidor. Para retornar para a linha de comando, saia utilzando a tecla q.
htop
Preparativos
Como todos estamos utilizando um mesmo usuário no servidor, todos podemos alterar ou remover os arquivos gerados por outras pessoas. Assim, para evitar ações indesejadas iremos criar pastas para cada aluno e sempre realizar os comandos dentro das respectivas pastas. Além disso, sempre utilizar caminhos completos e confira os comandos antes de executá-los, especialmente comandos de remoção.. Caso tenha dúvida não execute o comando sem solicitar ajuda. E lembre-se:
\(\underline{NÃO\space EXISTE\space DESFAZER\space NA\space LINHA\space DE\space COMANDO!!!!}\)
Crie sua pasta
Cada aluno criará uma pasta para organizar seus arquivos de trabalho.
Na pasta correspondente à sua $TURMA, dentro da home do usuário, crie uma pasta com um nome único. Caso haja alguém com nome parecido na sala, use suas iniciais ou apelido para diferenciar:
cd #para ir para a home
cd $TURMA
mkdir heronoh #por exemplo, no meu caso
cd heronoh
pwd
Copie os arquivos
Copie os arquivos que iremos utilizar para a sua pasta.
Se estiver trabalhando localmente, ou seja, no seu computador, os arquivos que utilizaremos podem ser baixados aqui.
Utilizando caminhos completos, copie os arquivos da pasta principal para a sua pasta, substituindo as variáveis $ALUNO e $TURMA pelos nomes correspondentes:
DICA: utilize tab para autocompletar e evitar erros!
#confira onde você está
pwd
# verifique que sua pasta está vazia
ls -lh ~/$TURMA/$ALUNO/
#copie os arquivos
cp -r ~/arquivos ~/$TURMA/$ALUNO/
# verifique se foram copiados corretamente
ls -lh ~/$TURMA/$ALUNO/
#veja a estrutura da pasta que você copiou
tree ~/$TURMA/$ALUNO/
Contando sequências
Em arquivos .fasta
Como já sabemos, arquivos .fasta e .fastq são arquivos de texto. Assim, qualquer programa/função/script desenvolvido para trabalhar com arquivos de texto podem ser utilizados nestes arquivos. Vejamos algumas.
Vamos vizualizar os arquivos fasta presentes na pasta ~/\(TURMA/\)ALUNO/arquivos/fasta/mito. Entre nesta pasta e liste os arquivos:
DICA: utilize tab para autocompletar e evitar erros!
#entre na pasta
cd ~/$TURMA/$ALUNO/arquivos/fasta/mito
#confira onde você está
pwd
#liste os arquivos
ls
#liste os arquivos com mais informações
ls -lah
Vamos vizualizar o arquivo human_mtDNA_genome.fasta de 4 maneiras diferentes. Observe o output de cada comando e entenda as diferenças. Varie os argumentos para compreender sua função:
#abrir o arquivo inteiro
cat human_mtDNA_genome.fasta
#abrir o começo do arquivo
head -10 human_mtDNA_genome.fasta
#abrir o final do arquivo
tail -14 human_mtDNA_genome.fasta
#abrir o arquivo inteiro, interativamente
less human_mtDNA_genome.fasta
#---> utilize as setas para mover, e saia com a tecla "q"
Como já sabemos, arquivos .fasta tem uma estrutura definida: uma linha de cabeçalho, sempre iniciada por > seguida de uma ou mais linhas de sequência. Cada cabeçalho representa uma sequência no arquivo. Assim, como saber quantas sequências temos num arquivo? O comando grep é utilizado para localizar/buscar/extrair/contar padrões de texto em arquivos de texto. Vamos usá-lo:
Experimente as variações do comando grep:
#veja o arquivo com que trabalharemos agora
less human_mtDNA_CDSs.fasta
#extrair linhas de cabeçalho no arquivo fasta
grep ">" human_mtDNA_CDSs.fasta
#contar linhas de cabeçalho no arquivo fasta
grep -c ">" human_mtDNA_CDSs.fasta
#extrair uma sequência usando o grep
#---->extraia apenas a sequência do gene COX1
grep "COX1" -A10 human_mtDNA_proteins.fasta
grep "COX1" -A8 human_mtDNA_proteins.fasta
#salve a sequência e seu cabeçalho em um novo arquivo
grep "COX1" -A8 human_mtDNA_proteins.fasta > human_COX1_protein.fasta
#confira o resultado
cat human_COX1_protein.fasta
Em arquivos .fastq
Entendendo os arquivos .fastq
Utilizando o mesmo raciocínio da sessão anterior, podemos investigar os arquivos .fastq.
Vamos vizualizar os arquivos fasta presentes na pasta ~/\(TURMA/\)ALUNO/arquivos/fastq. Entre nesta pasta e liste os arquivos:
DICA: utilize tab para autocompletar e evitar erros!
#entre na pasta
cd ~/$TURMA/$ALUNO/arquivos/fastq
#confira onde você está
pwd
#liste os arquivos
ls
#liste os arquivos com mais informações
ls -lah
Veja os nomes dos arquivos. Observe que eles estão organizados em pares que diferem apenas pelo radical R1 e R2. Esses radicais representam os pares de reads, ou seja, duas extremidades de um mesmo DNA sequenciado em uma posição da flow cell. Apesar de separados, cada sequência num arquivo tem sua correspondente no outro.
Vamos vizualizar o arquivo amostra_137_S135_L001_R1_001.fastq de 4 maneiras diferentes. Observe o output de cada comando e entenda as diferenças. Varie os argumentos para compreender sua função:
#abrir o arquivo inteiro
cat amostra_137_S135_L001_R1_001.fastq
#abrir o começo do arquivo
head -10 amostra_137_S135_L001_R1_001.fastq
#abrir o final do arquivo
tail -14 amostra_137_S135_L001_R1_001.fastq
#abrir o arquivo inteiro, interativamente
less amostra_137_S135_L001_R1_001.fastq
#---> utilize as setas para mover, e saia com a tecla "q"
Veja que este é um arquivo bem grande e mais complexo. Não faz sentido vizualizá-lo completamente. Vamos entender sua estrutura:
Utilizando o comando wc conte quantas linhas temos em cada arquivo nesta pasta:
#contar linhas
wc -l amostra_*
Com o comando head abra o começo do arquivo para entendermos sua estrutura
#contar linhas
head amostra_137_S135_L001_R1_001.fastq
### Estrutura do .fastq
# @........... = cabeçalho
# ACTGACTGA... = sequência
# + = separador
# 123ABC*&%... = código ASCII para qualidade PHRED de cada base
@M02913:268:000000000-JGD64:1:1101:21802:2015 1:N:0:ACTGAGCG+CTATTATG
TCAACCAACCACAAAGACATTGGCACCCTCTACTTAGTATTCGGTGCCTTAGCCGCAATATTTTGCACAGCCCTTAGCCTTCTAATTCGGGCAGAGCTTTCCCAACCTGGCGCCCTCTAGGTGA
+
AAC-AFGGGGEGGFFAFGGGGFAFGFFGFFGF<FFGGGGGG9,,B,@FC,,;CC@++6@9,CE,,6,,,:<CCEF,,6CCD@F,,EFE<,+@@?,BEF,,9CFE,BCC,,B+8
Contando seqs em arquivos .fastq
Como vimos acima, arquivos .fastq tem uma estrutura definida: uma linha de cabeçalho, **sempre iniciada por _@_** seguida de uma linha de sequência, seguida por uma linha de separador (+) e a última linha de indicadores de qualidade PHRED. Cada read do arquivo é representada por 4 linha sequenciais, contadas a partir do cabeçalho.
O comando grep também pode ser utilizado para contar reads num .fastq, mas, como o sinal @ pode ser também um indicador de qualidade, devemos ser mais específicos. Observe:
Conte o número de reads no arquivo com o comando grep:
#conte os sinais @ presentes no arquivo
grep -c "@" amostra_137_S135_L001_R1_001.fastq
#conte os sinais @ presentes NO COMEÇO DAS LINHAS do arquivo
grep -c "^@" amostra_137_S135_L001_R1_001.fastq
#reveja a estrutura do arquivo. Qual é o próximo caracter após o @ nos cabeçalhos?
head amostra_137_S135_L001_R1_001.fastq
#conte os sinais @ presentes NO COMEÇO DAS LINHAS do arquivo, seguidos do próximo caracter comum no cabeçalho
grep -c "^@M" amostra_137_S135_L001_R1_001.fastq
# conte todas as linhas no arquivo .fastq
wc -l amostra_137_S135_L001_R1_001.fastq
expr 1 + 1
expr 2 * 2
# use o comando expr pra calcular o valor obtido dividido por quatro (use espaços entre os termos)
## entenda o que será o primeiro termo
cat fastq/amostra_131_S158_L001_R1_001.fastq | wc -l
## substitua o primeiro termo da equação utilizando `` para delimitá-lo
expr `cat fastq/amostra_131_S158_L001_R1_001.fastq | wc -l` / 4
Controle de qualidade
Uma máxima da bioinformática e das ciências de dados em geral é trash in, trash out, que se traduz em onde entra lixo, sai lixo, ou seja, análises com inputs ruins geram outputs ruins. Assim, é extremamente importante separar o joio do trigo. A primeira etapa de uma análise - e talvez a mais importante - é a curadoria da informação que se vai utilizar; sua qualidade irá influenciar todo o resto.
Uma vez que os arquivos .fastq apresentam indicadores de qualidade para todas as bases de todas as reads, é possível selecionar apenas as reads (ou suas partes) que apresentem qualidade satisfatória para utilização nas análises subsequentes, minimizando a propagação de erros através do pipeline, que podem resultar em ruído ou mesmo em padrões biológicos inexistentes. Mas, como fazer essa avaliação para tantas sequências e arquivos de uma só vez?
Os programas FastQC & MultiQC possibilitam uma inspeção qualitativa e quantitativa de conjuntos de dados provenientes de sequenciadores de nova geração. Estes programas leem todos indicadores de qualidade de todas as reads e os convertem em diversos sumários gráficos que facilitam a avaliação de um ou múltiplos arquivos .fastq.
FastQC
O programa FastQC foi desenvolvido em 2010, e é escrito na linguagem de programação Java. Ele gera reports em HTML para cada arquivo .fastq por vez, o que reflete o estado da arte das aplicações NGS de sua época, onde geralmente uma ou poucas amostras eram sequenciadas por corrida.
Sua utilização é extremamente simples, como veremos a seguir.
Crie uma pasta qualidade para armazenarmos os resultados do FastQC. Em seguida, rode o programa para ambas as reads de um par de arquivos da sua escolha:
# entre na pasta correspondente a esta aula
cd ~/$TURMA/$ALUNO/
# crie uma subpasta
mkdir qualidade
# veja as instuções de uso do programa (saia com "q")
fastqc --help | less
# rode o programa, apontando o caminho completo para os arquivos de entrada (input) e para a pasta de saída (output)
fastqc $CAMINHO_COMPLETO/$ARQUIVO_FASTQ_R1 -o $CAMINHO_COMPLETO/qualidade
# repita a análise para o arquivo R2 correspondente
fastqc $CAMINHO_COMPLETO/$ARQUIVO_FASTQ_R2 -o $CAMINHO_COMPLETO/qualidade
# veja os outputs criados
ls $CAMINHO_COMPLETO/qualidade
Observe que foram gerados 2 arquivos para cada arquivo .fastq. Um deles, o .zip, contém as informações geradas na análise, que são sumarizdas no outro arquivo, o .html.
Transferindo arquivos
Para a visualização desse report em .html é necessário um navegador de internet, que não existe na linha de comando, pois requer uma interface gráfica. Assim, estes arquivos precisam ser copiados para o computador local, via linha de comando, para depois serem abertos num navegador de internet.
Essa transferência de arquivos é feita de maneira semelhante à conexão por SSH do computador local com o servidor, e utiliza o comando scp. Vamos fazer isso.
Identifique o caminho completo, no servidor, para os arquivos que se deseja copiar
# liste os arquivos html usando o caminho completo
ls $CAMINHO_COMPLETO/qualidade/*html
Abra um novo terminal linux. Utilize o comando scp para copiar os arquivos do servidor para o computador local. Substitua as variáveis $TURMA e $ALUNO pelo conteúdo respectivo à suas pastas, ou use o caminho completo que você identificou no passo anterior.
#crie uma pasta localmente para armazenar os arquivos
cd
mkdir qualidade
cd qualidade
# utilize o comanod scp para copiar
# estrutura do comando:
# scp endereço:o_que para_onde
# scp -P $PORTA $USUARIO@$IP:$CAMINHO_COMPLETO/$ARQUIVO_QUE_SE_QUER_COPIAR $PASTA_DE_DESTINO_NO_COMPUTADOR_LOCAL
scp -P 8722 $USER@$IP:/home/biomed/$TURMA/$ALUNO/arquivos/qualidade/*html .
#lembre-se que . sigifica "aqui, na pasta onde estou"
# liste os arquivos que você copiou
ls -lh
# abra o navegdor de arquivos do windows na pasta onde está
explorer.exe .
# clique 2x no arquivo para abrí-lo no navegador
Pronto! Agora podemos explorar esse report!
Analise o conteúdo do report.
MultiQC
O programa MultiQC foi desenvolvido em 2016, e é escrito na linguagem de programação Python. Ele foi desenvolvido para facilitar a avaliação de múltiplos arquivos .fastq por vez, dado que, com o avanço e barateamento das plataformas NGS, múltiplas amostras e bibliotecas passaram a ser sequenciadas simultâneamente. Este programa utiliza os diversos relatórios gerados pelo FastQC e os combina em um único sumário gráfico, também em HTML, com uma apresentação mais moderna e interativa.
Vamos criar utilizá-lo para criar um único report, desta vez para os reports do FastQC para todos arquivos de reads.
Utilizando o FastQC, gere reports para todos arquivos .fastq, em um único comando:
# volte para a pasta onde estão os primeiros reports
cd qualidade
# rode o FastQC para todos arquivos simultaneamente
fastqc $CAMINHO_COMPLETO/arquivos/fastq/*.fastq -o $CAMINHO_COMPLETO/qualidade
# veja os outputs criados
ls $CAMINHO_COMPLETO/qualidade
Utilizando o MultiQC, gere um report sumarizando todos arquivos criados pelo FastQC:
# volte para a pasta onde estão os primeiros reports
cd qualidade
# crie uma pasta para o multiqc
mkdir multiqc
# entre na pasta
cd multiqc
#confira o caminho onde está
pwd
# veja as instuções de uso do programa (saia com "q")
multiqc --help | less
# rode o programa
multiqc --interactive $CAMINHO_COMPLETO/quality/multiqc --outdir .
# veja os outputs criados
ls $CAMINHO_COMPLETO/qualidade/multiqc
Transferindo arquivos
Agora, de maneira semelhante ao que já fizemos, vamos copiar esse report gerado pelo MultiQC para o computador local, para podermos visualizá-lo.
Abra um novo terminal linux. Utilize o comando scp para copiar os arquivos do servidor para o computador local. Substitua as variáveis $TURMA e $ALUNO pelo conteúdo respectivo à suas pastas, ou use o caminho completo que você identificou no passo anterior.
#crie uma pasta localmente para armazenar os arquivos
cd qualidade
mkdir multiqc
cd multiqc
pwd
# utilize o comanod scp para copiar
# estrutura do comando:
# scp endereço:o_que para_onde
# scp -P $PORTA $USUARIO@$IP:$CAMINHO_COMPLETO/$ARQUIVO_QUE_SE_QUER_COPIAR $PASTA_DE_DESTINO_NO_COMPUTADOR_LOCAL
scp -P 8722 $USER@$IP:/home/biomed/$TURMA/$ALUNO/arquivos/qualidade/multiqc/*html .
#lembre-se que . sigifica "aqui, na pasta onde estou"
# liste os arquivos que você copiou
ls -lh
# abra o navegdor de arquivos do windows na pasta onde está
explorer.exe .
# clique 2x no arquivo para abrí-lo no navegador
Pronto! Agora podemos explorar esse report!
Analise o conteúdo do report.
Voltar para a página inicial
LS0tCnRpdGxlOiAiUHLDoXRpY2FzIGVtIEJpb2luZm8gSVYiCmF1dGhvcjogIlByb2YuIEhlcm9uIE9IIgpwbGFjZTogIkJpb21lZGljaW5hIC0gUFVDIE1pbmFzIgpkYXRlOiAyMDIzLzAxCm91dHB1dDogCiAgcm1kZm9ybWF0czo6ZG93bmN1dGU6CiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICB0b2NfZGVwdGg6IDUKICAgIHRvY19mbG9hdDogeWVzCiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIGNvZGVfZG93bmxvYWQ6IHllcwplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCmBgYHtyIGNvbG9yLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30KI2NvbmZpZ3VyYXIgcHJvcyByZXN1bHRhZG9zIGRvIGJhc2ggc2FpcmVtIGNvbG9yaWRvcyBlIG7Do28gQU5TSQoKb2xkX2hvb2tzIDwtIGZhbnNpOjpzZXRfa25pdF9ob29rcygKICBrbml0cjo6a25pdF9ob29rcywgCiAgd2hpY2ggPSBjKCJvdXRwdXQiLCAibWVzc2FnZSIsICJlcnJvciIpCikKYGBgCgo8c3R5bGU+CmJvZHkgewp0ZXh0LWFsaWduOiBqdXN0aWZ5fQo8L3N0eWxlPgoKPHN0eWxlPgojdG9jIHVsLm5hdiBsaSB1bCBsaSB7CiAgICBkaXNwbGF5OiBub25lOwogICAgbWF4LWhlaWdodDogbm9uZTsKfQoKI3RvYyB1bC5uYXYgbGkuYWN0aXZlIHVsIGxpICB7CiAgICBkaXNwbGF5OiBibG9jazsKICAgIG1heC1oZWlnaHQ6IG5vbmU7Cn0KCiN0b2MgdWwubmF2IGxpIHVsIGxpIHVsIGxpIHsKICAgIG1heC1oZWlnaHQ6IG5vbmU7CiAgICBkaXNwbGF5OiBub25lICFpbXBvcnRhbnQ7Cn0KCiN0b2MgdWwubmF2IGxpIHVsIGxpLmFjdGl2ZSB1bCBsaSB7CiAgICBtYXgtaGVpZ2h0OiBub25lOwogICAgZGlzcGxheTogYmxvY2sgIWltcG9ydGFudDsKfQo8L3N0eWxlPgoKCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwpPbMOhLCBlc3RhIMOpIG1haXMgdW1hIGRlIHVtIGNvbmp1bnRvIGRlIHByw6F0aWNhcyBlbSBiaW9pbmZvcm3DoXRpY2EgZGVzZW52b2x2aWRhcyBwYXJhIG8gY3Vyc28gZGUgQmlvbWVkaWNpbmEgZGEgUFVDIE1HLgpWb2PDqiBwb2RlIGVuY29udHJhciBhcyBkZW1haXMgcHLDoXRpY2FzIFsqYXF1aSpdKGh0dHBzOi8vaGVyb25vaC5naXRodWIuaW8vYmlvaW5mbykuCgojIyBBcnF1aXZvcyBfLmZhc3RhXyBlIF8uZmFzdHFfCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKTmEgcHLDoXRpY2EgcGFzc2FkYSB2b2PDqiBhcHJlbmRldSBhIHV0aWxpemFyIHVtIF9zY3JpcHRfIGJpb2luZm9ybcOhdGljbyBwYXJhIHJlYWxpemFyIGEgdHJhZHXDp8OjbyBkZSB1bWEgc2VxdcOqbmNpYSBkZSBudWNsZW90w61kZW9zIG5hIHNlcXXDqm5jaWEgY29ycmVzcG9uZGVudGUgZGUgQUEsIGEgcGFydGlyIGRlIHVtIGFycXVpdm8gXy5mYXN0YV8uIEhvamUgaXJlbW9zIGV4cGxvcmFyIG1haXMgZXN0ZSB0aXBvIGRlIGFycXVpdm8gdMOjbyB1dGlsaXphZG8gbmEgYmlvaW5mby4KCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwpDb21vIGrDoSB2aW1vcywgb3MgYXJxdWl2b3MgXy5mYXN0YV8gc8OjbyBhcnF1aXZvcyBxdWUgYXJtYXplbmFtIHNlcXXDqm5jaWFzIGRlIEROQSwgUk5BIG91IHByb3Rlw61uYXMuIENhZGEgYXJxdWl2byBwb2RlIGNvbnRlciB1bWEgw7puaWNhIHNlcXXDqm5jaWEgb3UgdsOhcmlhcywgc2VuZG8gb2Nhc2lvbmFsbWVudGUgcmVmZXJpZG8gY29tbyBfbXVsdGlmYXN0YV8uIMOJIG5lc3RlIGZvcm1hdG8gcXVlIHPDo28gYXJtYXplbmFkb3MgZ2Vub21hcyBkZSByZWZlcsOqbmNpYSBlIGdlbmVzLiBFc3RlIHRhbWLDqW0gw6kgbyBhcnF1aXZvIHV0aWxpemFkbyBwYXJhIGFsaW5oYW1lbnRvcyBlIGJ1c2NhcyBwb3Igc2ltaWxhcmlkYWRlLCBjb21vIG8gW0JMQVNUXShodHRwczovL2JsYXN0Lm5jYmkubmxtLm5paC5nb3YvQmxhc3QuY2dpKS4KCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwpKw6Egb3MgYXJxdWl2b3MgXy5mYXN0cV8gc8OjbyBhcnF1aXZvcyBxdWUgYXJtYXplbmFtIHNlcXXDqm5jaWFzIGJ1cnRhcyBnZXJhZGFzIHBvciBzZXF1ZW5jaWFkb3JlcyBkZSBub3ZhIGdlcmHDp8OjbyAoTkdTKSwgZSBhcHJlc2VudGFtLCBhbMOpbSBkYSBzZXF1w6puY2lhIGRhcyBfcmVhZHNfLCBpZGVudGlmaWNhZG9yZXMgZGUgcXVhbGlkYWRlIGJhc2VhZG9zIG5hIG3DqXRyaWNhIGRlIHF1YWxpZGFkZSBbKioqUEhSRUQqKipdKGh0dHBzOi8vc3VwcG9ydC5pbGx1bWluYS5jb20vaGVscC9CYXNlU3BhY2VfT0xIXzAwOTAwOC9Db250ZW50L1NvdXJjZS9JbmZvcm1hdGljcy9CUy9RdWFsaXR5U2NvcmVFbmNvZGluZ19zd0JTLmh0bSkuIEVzdGVzIGFycXVpdm9zIHBvZGVtIGFybWF6ZW5hciBjZW50ZW5hcyBkZSBtaWxoYXJlcyBkZSBzZXF1w6puY2lhcywgcXVlIHByZWNpc2FtIHNlciBwcm9jZXNzYWRhcyBwYXJhIGZvcm5lY2VyIGFsZ3VtYSBpbmZvcm1hw6fDo28gYmlvbMOzZ2ljYS4KCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwpDb21vIHZlcmVtb3MgYSBzZWd1aXIsIGjDoSBmdW5jaW9uYWxpZGFkZXMgZXNwZWPDrWZpY2FzIHBhcmEgY2FkYSB1bSBkZXNzZXMgYXJxdWl2b3MuIE5vIGVudGFudG8sIGFsZ3VtYXMgYXZhbGlhw6fDtWVzIG1haXMgc2ltcGxlcyBwb2RlbSBzZXIgcmVhbGl6YWRhcyBjb20gYW1ib3MsIG9ic2VydmFuZG8gc3VhcyBkaWZlcmVuw6dhcyBlc3RydXR1cmFpcy4KCgojIyBBY2Vzc2FuZG8gc2Vydmlkb3JlcwoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7CkNvbW8gc2FiZW1vcyBwZWxhIHByw6F0aWNhLCBhIGluc3RhbGHDp8OjbyBkZSBhbGd1bnMgcHJvZ3JhbWFzIGRlIGJpb2luZm9ybcOhdGljYSBuYSBwbGF0YWZvcm1hIF9XU0xfIHJlcXVlciBwcml2aWzDqWdpb3MgZGUgYWRtaW5pc3RyYWRvciwgbyBxdWUgZGlmaWN1bHRhIHNldSB1c28gZW0gY29tcHV0YWRvcmVzIGluc3RpdHVjaW9uYWlzLCBjb21vIG9zIGRhcyBhdWxhcyBwcsOhdGljYXMuIEFzc2ltLCBob2plIGlyZW1vcyBjb25lY3RhciBkaXJldGFtZW50ZSBhIHVtIHNlcnZpZG9yIGNvbXB1dGFjaW9uYWwgcGFyYSByZWFsaXphciBub3NzYXMgYW7DoWxpc2VzLiAqKipTZXJ2aWRvcioqKiBvdSAqKipTZXJ2aWRvcmEqKiogw6kgdW0gZG9zIG5vbWVzIHF1ZSBzZSBkw6EgYSB1bSBjb21wdXRhZG9yIGVtIHF1ZSB1bWEgb3UgbWFpcyBwZXNzb2FzIHRyYWJhbGhhbSByZW1vdGFtZW50ZSwgb3Ugc2VqYSwgdm9jw6ogY29uZWN0YSBhIGVsZSBhIHBhcnRpciBkbyBzZXUgY29tcHV0YWRvciwgcXVlIHNlcnZlIGFwZW5hcyBjb21vIHVtYSBpbnRlcmZhY2UuIEVucXVhbnRvIGNvbmVjdGFkbywgdG9kbyBvIHByb2Nlc3NhbWVudG8gY29tcHV0YWNpb25hbCDDqSByZWFsaXphZG8gbm8gKioqU2Vydmlkb3IqKiouIEFzc2ltLCBldmVudHVhbG1lbnRlLCBvcyBhcnF1aXZvcyBxdWUgZm9yZW0gdXNhZG9zLCBwcmVjaXNhbSBzZXIgdHJhbmZlcmlkb3MgZGUgdW0gY29tcHV0YWRvciBwYXJhIG8gb3V0cm8sIGUgYXByZW5kZXJlbW9zIGNvbW8gZmF6ZXIgaXNzbyBob2plLgoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Ck9zIHNlcnZpZG9yZXMgc8OjbyBjb21wdXRhZG9yZXMgbXVpdG8gcG9kZXJvc29zLCBlLCBwb3IgaXNzbywgbXVpdG8gdmlzYWRvcyBwb3IgaGFja2Vycy4gRGVzdGEgbWFuZWlyYSwgYSBjb25leMOjbyBjb20gZWxlcyBkZXZlIHNlciByZWFsaXphZGEgZGUgbWFuZWlyYSBzZWd1cmEsIGUgbsOjbyBzZSBkZXZlIGNvbXBhcnRpbGhhciBjcmVkZW5jaWFpcyBkZSBhY2Vzc28gc2VtIG9zIGRldmlkb3MgY3VpZGFkb3MuIEFzc2ltLCBlc3RhIHByw6F0aWNhIG7Do28gYXByZXNlbnRhcsOhIHRvZGFzIGFzIGluZm9ybWHDp8O1ZXMgbmVjZXNzw6FyaWFzIHBhcmEgYSBjb25leMOjby4gKipFc3RhcyBpbmZvcm1hw6fDtWVzIHNlcsOjbyB0cmFuc21pdGlkYXMgYXBlbmFzIGR1cmFudGUgYSBhdWxhLioqTWFzLCBjYXNvIHZvY8OqIGVzdGVqYSByZWFsaXphbmRvIGFzIHByw6F0aWNhcyBubyBzZXUgcHLDs3ByaW8gY29tcHV0YWRvciwgdm9jw6ogcG9kZSBpbnN0YWxhciBvcyBwcm9ncmFtYXMgcXVlIHV0aWxpemFyZW1vcyBzZW0gcmVzdHJpw6fDo28sIGUgcG9kZSByZWFsaXphciB0b2RvcyBvcyBwYXNzb3MgcHLDoXRpY29zIGxvY2FsbWVudGUuIE7Do28gc2Vyw6EgdW1hIHRhcmVmYSBzaW1wbGVzIHBhcmEgaW5pY2lhbnRlcywgbWFzIGFzIGluc3RydcOnw7VlcyBwYXJhIGEgaW5zdGFsYcOnw6NvIGRlIGNhZGEgcHJvZ3JhbWEgZXN0w6NvIGRpc3BvbsOtdmVpcyBub3MgcmVzcGVjdGl2b3MgX2xpbmtzXywgZSBxdWFscXVlciBzdXBvcnRlIHBvZGUgc2VyIHNvbGljaXRhZG8gZGlyZXRhbWV0bmUgY29taWdvLgoKIyMgSW5zdGFsYW5kbyBvcyBwcm9ncmFtYXMKCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwpDYXNvIHZvY8OqIHbDoSByZWFsaXphciBhIHByw6F0aWNhIGR1cmFudGUgYSBhdWxhLCBubyBzZXJ2aWRvciwgcG9kZSBpciBwYXJhIGEgcHLDs3hpbWEgc2Vzc8Ojby4gTWFzICoqY2FzbyB2b2PDqiB2w6EgcmVhbGl6YXIgYSBwcsOhdGljYSBubyBzZXUgcHLDs3Bpcm8gY29tcHV0YWRvcioqLCBvcyBwcm9ncmFtYXMgcXVlIHV0aWxpemFyZW1vcyBwb2RlbSBzZXIgZW5jb250cmFkb3MgYXF1aToKCiogW2V4b25lcmF0ZV0oaHR0cHM6Ly93d3cuZWJpLmFjLnVrL2Fib3V0L3ZlcnRlYnJhdGUtZ2Vub21pY3Mvc29mdHdhcmUvZXhvbmVyYXRlKTogRGl2ZXJzYXMgZnVuY2lvbmFsaWRhZGVzIHBhcmEgYXJxdWl2b3MgXy5mYXN0YV8uCgoqIFtGYXN0UUNdKGh0dHBzOi8vd3d3LmJpb2luZm9ybWF0aWNzLmJhYnJhaGFtLmFjLnVrL3Byb2plY3RzL2Zhc3RxYy8pOiBHZXJhZG9yIGRlIHJlbGF0w7NyaW9zIGRlIHF1YWxpZGFkZSBwYXJhIGFycXVpdm9zIF8uZmFzdHFfIGluZGl2aWR1YWlzLgoKKiBbTXVsdGlRQ10oaHR0cHM6Ly9tdWx0aXFjLmluZm8vKTogR2VyYWRvciBkZSByZWxhdMOzcmlvcyBkZSBxdWFsaWRhZGUgcGFyYSBhcnF1aXZvcyBfLmZhc3RxXyBtw7psdGlwbG9zLgoKKiBbVHV0b3JpYWlzIGRvICoqKkxHQyBQVUMgTWluYXMqKiogZGUgaW5zdGFsYcOnw6NvIGUgdXNvIGRvIF9GYXN0UUNfICYgX011bHRpUUNfXShodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PWFUbEhRTkx3Zy0wKQoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Ck9zIGFycXVpdm9zIHF1ZSB1dGlsaXphcmVtb3MgcG9kZW0gc2VyIGJhaXhhZG9zIFthcXVpXShodHRwczovL2RyaXZlLmdvb2dsZS5jb20vZHJpdmUvZm9sZGVycy8xYjhsbFA0N0E4eUNMZ3JZRUtHLXhRZ25oZ2FNVWtqUTY/dXNwPXNoYXJpbmcpLgoKIyMgQ29uZXjDo28gcG9yIF9TU0hfCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKQSBtYW5laXJhIG1haXMgdXRpbGl6YWRhIHBhcmEgYSBjb25leMOjbyBjb20gc2Vydmlkb3JlcyBvdSBvdXRyb3MgY29tcHV0YWRvcmVzIMOpIGEgY29uZXjDo28gcG9yIFsqKipTU0gqKipdKGh0dHBzOi8vcHQud2lraXBlZGlhLm9yZy93aWtpL1NlY3VyZV9TaGVsbCkuIEVzdGUgw6kgdW0gcHJvdG9jb2xvIGRlIHJlZGUgY3JpcHRvZ3JhZmFkbywgcXVlIHNlIGJhc2VpYSBuYSB1dGlsaXphw6fDo28gZGUgdXN1w6FyaW9zIGUgc2VuaGFzIHBhcmEgdG9ybmFyIHNlZ3VyYSBhIGNvbmV4w6NvIGVudHJlIGRvaXMgY29tcHV0YWRvcmVzLiBBc3NpbSwgY2FkYSB1c3XDoXJpbyBwcmVjaXNhIHRlciB1bWEgY29udGEgKF9sb2dpbl8gZSBzZW5oYSkgY2FkYXN0cmFkYSBubyBjb21wdXRhZG9yIGFsdm8gKG8gU2Vydmlkb3IpLiBQYXJhIG5vc3NhcyBwcsOhdGljYXMsIGNyaWVpIHVtIHVzdcOhcmlvIGdlcmFsIHBhcmEgdG9kb3MgY29uZWN0YXJtb3Mgc2ltdWx0YW5lYW1lbnRlIG51bSBkZSBub3Nzb3MgU2Vydmlkb3Jlcy4KCj4gVXRpbGl6YW5kbyBhcyBjcmVkZW5jaWFpcyAqKipmb3JuZWNpZGFzIGR1cmFudGUgYSBhdWxhKioqLCBjb25lY3RlIG5vIHNlcnZpZG9yIGRlIHRyYWJhbGhvIHZpYSBTU0guIFF1YW5kbyBzb2xpY2l0YWRvLCBmb3JuZcOnYSBhIHNlbmhhOgoKYGBge2Jhc2gsIGVjaG89VFJVRSxldmFsPUZBTFNFfQojZXg6CiNzc2ggdXN1YXJpb0AxMTEuMjIyLjMzMy40NDQKCnNzaCAkVVNFUkAkSVAKYGBgCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKQ2FzbyBhIGNvbmV4w6NvIHNlamEgcmVhbGl6YWRhIGNvbSBzdWNlc3NvLCB2b2PDqiB2ZXLDoSB1bWEgdGVsYSBkZSBib2FzIHZpbmRhcyBjb20gaW5mb3JtYcOnw7VlcyBzb2JyZSBvIHNlcnZpZG9yLgoKPiBVdGlsaXphbmRvIG8gY29tYW5kbyBfaHRvcF8gdmVyaWZpcXVlIGFzIGNhcmFjdGVyw61zdGljYXMgZGUgX2hhcmR3YXJlXyBlIG9zIHByb2Nlc3NvcyBxdWUgZXN0w6NvIHJvZGFuZG8gbm8gc2Vydmlkb3IuIApQYXJhIHJldG9ybmFyIHBhcmEgYSBsaW5oYSBkZSBjb21hbmRvLCBzYWlhIHV0aWx6YW5kbyBhIHRlY2xhICoqKnEqKiouCgpgYGB7YmFzaCwgZWNobz1UUlVFLGV2YWw9RkFMU0V9Cmh0b3AKYGBgCgojIyBQcmVwYXJhdGl2b3MKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7CkNvbW8gdG9kb3MgZXN0YW1vcyB1dGlsaXphbmRvIHVtIG1lc21vIF91c3XDoXJpb18gbm8gc2Vydmlkb3IsIHRvZG9zIHBvZGVtb3MgYWx0ZXJhciBvdSByZW1vdmVyIG9zIGFycXVpdm9zIGdlcmFkb3MgcG9yIG91dHJhcyBwZXNzb2FzLiBBc3NpbSwgcGFyYSBldml0YXIgYcOnw7VlcyBpbmRlc2VqYWRhcyAqKippcmVtb3MgY3JpYXIgcGFzdGFzIHBhcmEgY2FkYSBhbHVubyBlIHNlbXByZSByZWFsaXphciBvcyBjb21hbmRvcyBkZW50cm8gZGFzIHJlc3BlY3RpdmFzIHBhc3RhcyoqKi4gQWzDqW0gZGlzc28sICoqKnNlbXByZSB1dGlsaXphciBjYW1pbmhvcyBjb21wbGV0b3MgZSBjb25maXJhIG9zIGNvbWFuZG9zIGFudGVzIGRlIGV4ZWN1dMOhLWxvcywgZXNwZWNpYWxtZW50ZSBjb21hbmRvcyBkZSByZW1vw6fDo28uKioqLiBDYXNvIHRlbmhhIGTDunZpZGEgKioqbsOjbyBleGVjdXRlIG8gY29tYW5kbyBzZW0gc29saWNpdGFyIGFqdWRhKioqLiBFIGxlbWJyZS1zZToKCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwokXHVuZGVybGluZXtOw4NPXHNwYWNlIEVYSVNURVxzcGFjZSBERVNGQVpFUlxzcGFjZSBOQVxzcGFjZSBMSU5IQVxzcGFjZSBERVxzcGFjZSBDT01BTkRPISEhIX0kCgojIyMgQ3JpZSBzdWEgcGFzdGEKCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwpDYWRhIGFsdW5vIGNyaWFyw6EgdW1hIHBhc3RhIHBhcmEgb3JnYW5pemFyIHNldXMgYXJxdWl2b3MgZGUgdHJhYmFsaG8uCgo+IE5hIHBhc3RhIGNvcnJlc3BvbmRlbnRlIMOgIHN1YSAkVFVSTUEsIGRlbnRybyBkYSAqKipob21lKioqIGRvIHVzdcOhcmlvLCBjcmllIHVtYSBwYXN0YSBjb20gdW0gbm9tZSDDum5pY28uIENhc28gaGFqYSBhbGd1w6ltIGNvbSBub21lIHBhcmVjaWRvIG5hIHNhbGEsIHVzZSBzdWFzIGluaWNpYWlzIG91IGFwZWxpZG8gcGFyYSBkaWZlcmVuY2lhcjoKCmBgYHtiYXNoLCBlY2hvPVRSVUUsZXZhbD1GQUxTRX0KY2QgI3BhcmEgaXIgcGFyYSBhIGhvbWUKCmNkICRUVVJNQQoKbWtkaXIgaGVyb25vaCAjcG9yIGV4ZW1wbG8sIG5vIG1ldSBjYXNvCgpjZCBoZXJvbm9oCgpwd2QKCmBgYAoKIyMjIENvcGllIG9zIGFycXVpdm9zCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKQ29waWUgb3MgYXJxdWl2b3MgcXVlIGlyZW1vcyB1dGlsaXphciBwYXJhIGEgc3VhIHBhc3RhLgoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7ClNlIGVzdGl2ZXIgdHJhYmFsaGFuZG8gbG9jYWxtZW50ZSwgb3Ugc2VqYSwgbm8gc2V1IGNvbXB1dGFkb3IsIG9zIGFycXVpdm9zIHF1ZSB1dGlsaXphcmVtb3MgcG9kZW0gc2VyIGJhaXhhZG9zIFthcXVpXShodHRwczovL2RyaXZlLmdvb2dsZS5jb20vZHJpdmUvZm9sZGVycy8xYjhsbFA0N0E4eUNMZ3JZRUtHLXhRZ25oZ2FNVWtqUTY/dXNwPXNoYXJpbmcpLgoKCj4gVXRpbGl6YW5kbyAqKipjYW1pbmhvcyBjb21wbGV0b3MqKiosIGNvcGllIG9zIGFycXVpdm9zIGRhIHBhc3RhIHByaW5jaXBhbCBwYXJhIGEgc3VhIHBhc3RhLCBzdWJzdGl0dWluZG8gYXMgdmFyacOhdmVpcyAkQUxVTk8gZSAkVFVSTUEgcGVsb3Mgbm9tZXMgY29ycmVzcG9uZGVudGVzOgoKPj4gRElDQTogdXRpbGl6ZSAqKnRhYioqIHBhcmEgYXV0b2NvbXBsZXRhciBlIGV2aXRhciBlcnJvcyEKCmBgYHtiYXNoLCBlY2hvPVRSVUUsZXZhbD1GQUxTRX0KI2NvbmZpcmEgb25kZSB2b2PDqiBlc3TDoQpwd2QgCgojIHZlcmlmaXF1ZSBxdWUgc3VhIHBhc3RhIGVzdMOhIHZhemlhCmxzIC1saCB+LyRUVVJNQS8kQUxVTk8vIAoKI2NvcGllIG9zIGFycXVpdm9zCmNwIC1yIH4vYXJxdWl2b3Mgfi8kVFVSTUEvJEFMVU5PLwoKIyB2ZXJpZmlxdWUgc2UgZm9yYW0gY29waWFkb3MgY29ycmV0YW1lbnRlCmxzIC1saCB+LyRUVVJNQS8kQUxVTk8vCgojdmVqYSBhIGVzdHJ1dHVyYSBkYSBwYXN0YSBxdWUgdm9jw6ogY29waW91CnRyZWUgfi8kVFVSTUEvJEFMVU5PLwoKYGBgCgojIyBDb250YW5kbyBzZXF1w6puY2lhcwoKIyMjIEVtIGFycXVpdm9zIC5mYXN0YQoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7CkNvbW8gasOhIHNhYmVtb3MsIGFycXVpdm9zIF8uZmFzdGFfIGUgXy5mYXN0cV8gc8OjbyBhcnF1aXZvcyBkZSB0ZXh0by4gQXNzaW0sIHF1YWxxdWVyIHByb2dyYW1hL2Z1bsOnw6NvL19zY3JpcHRfIGRlc2Vudm9sdmlkbyBwYXJhIHRyYWJhbGhhciBjb20gYXJxdWl2b3MgZGUgdGV4dG8gcG9kZW0gc2VyIHV0aWxpemFkb3MgbmVzdGVzIGFycXVpdm9zLiBWZWphbW9zIGFsZ3VtYXMuCgo+IFZhbW9zIHZpenVhbGl6YXIgb3MgYXJxdWl2b3MgZmFzdGEgcHJlc2VudGVzIG5hIHBhc3RhICp+LyRUVVJNQS8kQUxVTk8vYXJxdWl2b3MvZmFzdGEvbWl0byouIEVudHJlIG5lc3RhIHBhc3RhIGUgbGlzdGUgb3MgYXJxdWl2b3M6Cgo+PiBESUNBOiB1dGlsaXplICoqdGFiKiogcGFyYSBhdXRvY29tcGxldGFyIGUgZXZpdGFyIGVycm9zIQoKYGBge2Jhc2gsIGVjaG89VFJVRSxldmFsPUZBTFNFfQojZW50cmUgbmEgcGFzdGEKY2Qgfi8kVFVSTUEvJEFMVU5PL2FycXVpdm9zL2Zhc3RhL21pdG8KCiNjb25maXJhIG9uZGUgdm9jw6ogZXN0w6EKcHdkCgojbGlzdGUgb3MgYXJxdWl2b3MKbHMKCiNsaXN0ZSBvcyBhcnF1aXZvcyBjb20gbWFpcyBpbmZvcm1hw6fDtWVzCmxzIC1sYWgKYGBgCgo+IFZhbW9zIHZpenVhbGl6YXIgbyBhcnF1aXZvICBfaHVtYW5fbXRETkFfZ2Vub21lLmZhc3RhXyBkZSA0IG1hbmVpcmFzIGRpZmVyZW50ZXMuIE9ic2VydmUgbyBfb3V0cHV0XyBkZSBjYWRhIGNvbWFuZG8gZSBlbnRlbmRhIGFzIGRpZmVyZW7Dp2FzLiBWYXJpZSBvcyBhcmd1bWVudG9zIHBhcmEgY29tcHJlZW5kZXIgc3VhIGZ1bsOnw6NvOgoKYGBge2Jhc2gsIGVjaG89VFJVRSxldmFsPUZBTFNFfQojYWJyaXIgbyBhcnF1aXZvIGludGVpcm8KY2F0IGh1bWFuX210RE5BX2dlbm9tZS5mYXN0YQoKI2FicmlyIG8gY29tZcOnbyBkbyBhcnF1aXZvCmhlYWQgLTEwIGh1bWFuX210RE5BX2dlbm9tZS5mYXN0YQoKI2FicmlyIG8gZmluYWwgZG8gYXJxdWl2bwp0YWlsIC0xNCBodW1hbl9tdEROQV9nZW5vbWUuZmFzdGEKCiNhYnJpciBvIGFycXVpdm8gaW50ZWlybywgaW50ZXJhdGl2YW1lbnRlCmxlc3MgaHVtYW5fbXRETkFfZ2Vub21lLmZhc3RhCiMtLS0+IHV0aWxpemUgYXMgc2V0YXMgcGFyYSBtb3ZlciwgZSBzYWlhIGNvbSBhIHRlY2xhICJxIgpgYGAKCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwpDb21vIGrDoSBzYWJlbW9zLCBhcnF1aXZvcyBfLmZhc3RhXyB0ZW0gdW1hIGVzdHJ1dHVyYSBkZWZpbmlkYTogdW1hIGxpbmhhIGRlICoqKmNhYmXDp2FsaG8qKiosICoqc2VtcHJlIGluaWNpYWRhIHBvciBfPl8qKiBzZWd1aWRhIGRlIHVtYSBvdSBtYWlzIGxpbmhhcyBkZSAqKipzZXF1w6puY2lhKioqLiBDYWRhICoqKmNhYmXDp2FsaG8qKiogcmVwcmVzZW50YSB1bWEgc2VxdcOqbmNpYSBubyBhcnF1aXZvLiBBc3NpbSwgY29tbyBzYWJlciBxdWFudGFzIHNlcXXDqm5jaWFzIHRlbW9zIG51bSBhcnF1aXZvPyBPIGNvbWFuZG8gKioqZ3JlcCoqKiDDqSB1dGlsaXphZG8gcGFyYSBsb2NhbGl6YXIvYnVzY2FyL2V4dHJhaXIvY29udGFyIHBhZHLDtWVzIGRlIHRleHRvIGVtIGFycXVpdm9zIGRlIHRleHRvLiBWYW1vcyB1c8OhLWxvOiAKCj4gRXhwZXJpbWVudGUgYXMgdmFyaWHDp8O1ZXMgZG8gY29tYW5kbyBfZ3JlcF86CgpgYGB7YmFzaCwgZWNobz1UUlVFLGV2YWw9RkFMU0V9CiN2ZWphIG8gYXJxdWl2byBjb20gcXVlIHRyYWJhbGhhcmVtb3MgYWdvcmEKbGVzcyBodW1hbl9tdEROQV9DRFNzLmZhc3RhCgojZXh0cmFpciBsaW5oYXMgZGUgY2FiZcOnYWxobyBubyBhcnF1aXZvIGZhc3RhCmdyZXAgIj4iIGh1bWFuX210RE5BX0NEU3MuZmFzdGEKCiNjb250YXIgbGluaGFzIGRlIGNhYmXDp2FsaG8gbm8gYXJxdWl2byBmYXN0YQpncmVwIC1jICI+IiBodW1hbl9tdEROQV9DRFNzLmZhc3RhCgojZXh0cmFpciB1bWEgc2VxdcOqbmNpYSB1c2FuZG8gbyBncmVwCiMtLS0tPmV4dHJhaWEgYXBlbmFzIGEgc2VxdcOqbmNpYSBkbyBnZW5lIENPWDEKZ3JlcCAiQ09YMSIgLUExMCBodW1hbl9tdEROQV9wcm90ZWlucy5mYXN0YQoKZ3JlcCAiQ09YMSIgLUE4IGh1bWFuX210RE5BX3Byb3RlaW5zLmZhc3RhCgojc2FsdmUgYSBzZXF1w6puY2lhIGUgc2V1IGNhYmXDp2FsaG8gZW0gdW0gbm92byBhcnF1aXZvCmdyZXAgIkNPWDEiIC1BOCBodW1hbl9tdEROQV9wcm90ZWlucy5mYXN0YSA+IGh1bWFuX0NPWDFfcHJvdGVpbi5mYXN0YQoKI2NvbmZpcmEgbyByZXN1bHRhZG8KY2F0IGh1bWFuX0NPWDFfcHJvdGVpbi5mYXN0YQoKYGBgCgojIyMgRW0gYXJxdWl2b3MgLmZhc3RxCgojIyMjIEVudGVuZGVuZG8gb3MgYXJxdWl2b3MgLmZhc3RxCgoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7ClV0aWxpemFuZG8gbyBtZXNtbyByYWNpb2PDrW5pbyBkYSBzZXNzw6NvIGFudGVyaW9yLCBwb2RlbW9zIGludmVzdGlnYXIgb3MgYXJxdWl2b3MgXy5mYXN0cV8uCgo+IFZhbW9zIHZpenVhbGl6YXIgb3MgYXJxdWl2b3MgZmFzdGEgcHJlc2VudGVzIG5hIHBhc3RhICp+LyRUVVJNQS8kQUxVTk8vYXJxdWl2b3MvZmFzdHEqLiBFbnRyZSBuZXN0YSBwYXN0YSBlIGxpc3RlIG9zIGFycXVpdm9zOgoKPj4gRElDQTogdXRpbGl6ZSAqKnRhYioqIHBhcmEgYXV0b2NvbXBsZXRhciBlIGV2aXRhciBlcnJvcyEKCmBgYHtiYXNoLCBlY2hvPVRSVUUsZXZhbD1GQUxTRX0KI2VudHJlIG5hIHBhc3RhCmNkIH4vJFRVUk1BLyRBTFVOTy9hcnF1aXZvcy9mYXN0cQoKI2NvbmZpcmEgb25kZSB2b2PDqiBlc3TDoQpwd2QKCiNsaXN0ZSBvcyBhcnF1aXZvcwpscwoKI2xpc3RlIG9zIGFycXVpdm9zIGNvbSBtYWlzIGluZm9ybWHDp8O1ZXMKbHMgLWxhaApgYGAKCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwpWZWphIG9zIG5vbWVzIGRvcyBhcnF1aXZvcy4gT2JzZXJ2ZSBxdWUgZWxlcyBlc3TDo28gb3JnYW5pemFkb3MgZW0gcGFyZXMgcXVlIGRpZmVyZW0gYXBlbmFzIHBlbG8gcmFkaWNhbCAqKipSMSoqKiBlICoqKlIyKioqLiBFc3NlcyByYWRpY2FpcyByZXByZXNlbnRhbSBvcyBwYXJlcyBkZSBfcmVhZHNfLCBvdSBzZWphLCBkdWFzIGV4dHJlbWlkYWRlcyBkZSB1bSBtZXNtbyBETkEgc2VxdWVuY2lhZG8gZW0gdW1hIHBvc2nDp8OjbyBkYSBfZmxvdyBjZWxsXy4gQXBlc2FyIGRlIHNlcGFyYWRvcywgY2FkYSBzZXF1w6puY2lhIG51bSBhcnF1aXZvIHRlbSBzdWEgY29ycmVzcG9uZGVudGUgbm8gb3V0cm8uCgo+IFZhbW9zIHZpenVhbGl6YXIgbyBhcnF1aXZvIF9hbW9zdHJhXzEzN19TMTM1X0wwMDFfUjFfMDAxLmZhc3RxXyBkZSA0IG1hbmVpcmFzIGRpZmVyZW50ZXMuIE9ic2VydmUgbyBfb3V0cHV0XyBkZSBjYWRhIGNvbWFuZG8gZSBlbnRlbmRhIGFzIGRpZmVyZW7Dp2FzLiBWYXJpZSBvcyBhcmd1bWVudG9zIHBhcmEgY29tcHJlZW5kZXIgc3VhIGZ1bsOnw6NvOgoKYGBge2Jhc2gsIGVjaG89VFJVRSxldmFsPUZBTFNFfQojYWJyaXIgbyBhcnF1aXZvIGludGVpcm8KY2F0IGFtb3N0cmFfMTM3X1MxMzVfTDAwMV9SMV8wMDEuZmFzdHEKCiNhYnJpciBvIGNvbWXDp28gZG8gYXJxdWl2bwpoZWFkIC0xMCBhbW9zdHJhXzEzN19TMTM1X0wwMDFfUjFfMDAxLmZhc3RxCgojYWJyaXIgbyBmaW5hbCBkbyBhcnF1aXZvCnRhaWwgLTE0IGFtb3N0cmFfMTM3X1MxMzVfTDAwMV9SMV8wMDEuZmFzdHEKCiNhYnJpciBvIGFycXVpdm8gaW50ZWlybywgaW50ZXJhdGl2YW1lbnRlCmxlc3MgYW1vc3RyYV8xMzdfUzEzNV9MMDAxX1IxXzAwMS5mYXN0cQojLS0tPiB1dGlsaXplIGFzIHNldGFzIHBhcmEgbW92ZXIsIGUgc2FpYSBjb20gYSB0ZWNsYSAicSIKYGBgCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKVmVqYSBxdWUgZXN0ZSDDqSB1bSBhcnF1aXZvIGJlbSBncmFuZGUgZSBtYWlzIGNvbXBsZXhvLiBOw6NvIGZheiBzZW50aWRvIHZpenVhbGl6w6EtbG8gY29tcGxldGFtZW50ZS4gVmFtb3MgZW50ZW5kZXIgc3VhIGVzdHJ1dHVyYTogCgo+IFV0aWxpemFuZG8gbyBjb21hbmRvIF93Y18gY29udGUgcXVhbnRhcyBsaW5oYXMgdGVtb3MgZW0gY2FkYSBhcnF1aXZvIG5lc3RhIHBhc3RhOgoKYGBge2Jhc2gsIGVjaG89VFJVRSxldmFsPUZBTFNFfQojY29udGFyIGxpbmhhcwp3YyAtbCBhbW9zdHJhXyoKYGBgCgo+IENvbSBvIGNvbWFuZG8gX2hlYWRfIGFicmEgbyBjb21lw6dvIGRvIGFycXVpdm8gcGFyYSBlbnRlbmRlcm1vcyBzdWEgZXN0cnV0dXJhCgpgYGB7YmFzaCwgZWNobz1UUlVFLGV2YWw9RkFMU0V9CiNjb250YXIgbGluaGFzCmhlYWQgYW1vc3RyYV8xMzdfUzEzNV9MMDAxX1IxXzAwMS5mYXN0cQpgYGAKCjxzdHlsZT4KZGl2LmJsdWUgcHJlIHsgYmFja2dyb3VuZC1jb2xvcjpsaWdodGJsdWU7IH0KPC9zdHlsZT4KCjxkaXYgY2xhc3MgPSAiYmx1ZSI+CmBgYHtiYXNoIGZhc3RxZmlsZSwgZWNobz1UUlVFLGV2YWw9RkFMU0V9CiMjIyAgICAgICAgRXN0cnV0dXJhIGRvIC5mYXN0cQojICBALi4uLi4uLi4uLi4gICAgPSBjYWJlw6dhbGhvCiMgIEFDVEdBQ1RHQS4uLiAgICA9IHNlcXXDqm5jaWEKIyAgKyAgICAgICAgICAgICAgID0gc2VwYXJhZG9yCiMgIDEyM0FCQyomJS4uLiAgICA9IGPDs2RpZ28gQVNDSUkgcGFyYSBxdWFsaWRhZGUgUEhSRUQgZGUgY2FkYSBiYXNlCgpATTAyOTEzOjI2ODowMDAwMDAwMDAtSkdENjQ6MToxMTAxOjIxODAyOjIwMTUgMTpOOjA6QUNUR0FHQ0crQ1RBVFRBVEcKVENBQUNDQUFDQ0FDQUFBR0FDQVRUR0dDQUNDQ1RDVEFDVFRBR1RBVFRDR0dUR0NDVFRBR0NDR0NBQVRBVFRUVEdDQUNBR0NDQ1RUQUdDQ1RUQ1RBQVRUQ0dHR0NBR0FHQ1RUVENDQ0FBQ0NUR0dDR0NDQ1RDVEFHR1RHQQorCkFBQy1BRkdHR0dFR0dGRkFGR0dHR0ZBRkdGRkdGRkdGPEZGR0dHR0dHOSwsQixARkMsLDtDQ0ArKzZAOSxDRSwsNiwsLDo8Q0NFRiwsNkNDREBGLCxFRkU8LCtAQD8sQkVGLCw5Q0ZFLEJDQywsQis4CmBgYAo8L2Rpdj4KCiMjIyMgQ29udGFuZG8gc2VxcyBlbSBhcnF1aXZvcyAuZmFzdHEKCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwpDb21vIHZpbW9zIGFjaW1hLCBhcnF1aXZvcyBfLmZhc3RxXyB0ZW0gdW1hIGVzdHJ1dHVyYSBkZWZpbmlkYTogdW1hIGxpbmhhIGRlICoqKmNhYmXDp2FsaG8qKiosICoqc2VtcHJlIGluaWNpYWRhIHBvciBfQF8qKiBzZWd1aWRhIGRlIHVtYSBsaW5oYSBkZSAqKipzZXF1w6puY2lhKioqLCBzZWd1aWRhIHBvciB1bWEgbGluaGEgZGUgc2VwYXJhZG9yICgrKSBlIGEgw7psdGltYSBsaW5oYSBkZSAqKippbmRpY2Fkb3JlcyBkZSBxdWFsaWRhZGUgUEhSRUQqKiouIENhZGEgX3JlYWRfIGRvIGFycXVpdm8gw6kgcmVwcmVzZW50YWRhIHBvciA0IGxpbmhhIHNlcXVlbmNpYWlzLCBjb250YWRhcyBhIHBhcnRpciBkbyBjYWJlw6dhbGhvLgoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Ck8gY29tYW5kbyAqKipncmVwKioqIHRhbWLDqW0gcG9kZSBzZXIgdXRpbGl6YWRvIHBhcmEgY29udGFyIF9yZWFkc18gbnVtIF8uZmFzdHFfLCBtYXMsIGNvbW8gbyBzaW5hbCBAIHBvZGUgc2VyIHRhbWLDqW0gdW0gaW5kaWNhZG9yIGRlIHF1YWxpZGFkZSwgZGV2ZW1vcyBzZXIgbWFpcyBlc3BlY8OtZmljb3MuIE9ic2VydmU6Cgo+IENvbnRlIG8gbsO6bWVybyBkZSBfcmVhZHNfIG5vIGFycXVpdm8gY29tIG8gY29tYW5kbyBfZ3JlcF86CgpgYGB7YmFzaCwgZWNobz1UUlVFLGV2YWw9RkFMU0V9CiNjb250ZSBvcyBzaW5haXMgQCBwcmVzZW50ZXMgbm8gYXJxdWl2bwpncmVwIC1jICJAIiBhbW9zdHJhXzEzN19TMTM1X0wwMDFfUjFfMDAxLmZhc3RxCgojY29udGUgb3Mgc2luYWlzIEAgcHJlc2VudGVzIE5PIENPTUXDh08gREFTIExJTkhBUyBkbyBhcnF1aXZvCmdyZXAgLWMgIl5AIiBhbW9zdHJhXzEzN19TMTM1X0wwMDFfUjFfMDAxLmZhc3RxCgojcmV2ZWphIGEgZXN0cnV0dXJhIGRvIGFycXVpdm8uIFF1YWwgw6kgbyBwcsOzeGltbyBjYXJhY3RlciBhcMOzcyBvIEAgbm9zIGNhYmXDp2FsaG9zPwpoZWFkIGFtb3N0cmFfMTM3X1MxMzVfTDAwMV9SMV8wMDEuZmFzdHEKCiNjb250ZSBvcyBzaW5haXMgQCBwcmVzZW50ZXMgTk8gQ09NRcOHTyBEQVMgTElOSEFTIGRvIGFycXVpdm8sIHNlZ3VpZG9zIGRvIHByw7N4aW1vIGNhcmFjdGVyIGNvbXVtIG5vIGNhYmXDp2FsaG8KZ3JlcCAtYyAiXkBNIiBhbW9zdHJhXzEzN19TMTM1X0wwMDFfUjFfMDAxLmZhc3RxCgojIGNvbnRlIHRvZGFzIGFzIGxpbmhhcyBubyBhcnF1aXZvIC5mYXN0cQp3YyAtbCBhbW9zdHJhXzEzN19TMTM1X0wwMDFfUjFfMDAxLmZhc3RxCgpleHByIDEgKyAxCgpleHByIDIgKiAyCgoKIyB1c2UgbyBjb21hbmRvIGV4cHIgcHJhIGNhbGN1bGFyIG8gdmFsb3Igb2J0aWRvIGRpdmlkaWRvIHBvciBxdWF0cm8gKHVzZSBlc3Bhw6dvcyBlbnRyZSBvcyB0ZXJtb3MpCiMjIGVudGVuZGEgbyBxdWUgc2Vyw6EgbyBwcmltZWlybyB0ZXJtbwpjYXQgZmFzdHEvYW1vc3RyYV8xMzFfUzE1OF9MMDAxX1IxXzAwMS5mYXN0cSB8IHdjIC1sCgojIyBzdWJzdGl0dWEgbyBwcmltZWlybyB0ZXJtbyBkYSBlcXVhw6fDo28gdXRpbGl6YW5kbyBgYCBwYXJhIGRlbGltaXTDoS1sbwpleHByIGBjYXQgZmFzdHEvYW1vc3RyYV8xMzFfUzE1OF9MMDAxX1IxXzAwMS5mYXN0cSB8IHdjIC1sYCAvIDQKCmBgYAoKIyMgQ29udHJvbGUgZGUgcXVhbGlkYWRlCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKVW1hIG3DoXhpbWEgZGEgYmlvaW5mb3Jtw6F0aWNhIGUgZGFzIGNpw6puY2lhcyBkZSBkYWRvcyBlbSBnZXJhbCDDqSAqKip0cmFzaCBpbiwgdHJhc2ggb3V0KioqLCBxdWUgc2UgdHJhZHV6IGVtICpvbmRlIGVudHJhIGxpeG8sIHNhaSBsaXhvKiwgb3Ugc2VqYSwgYW7DoWxpc2VzIGNvbSBfaW5wdXRzXyBydWlucyBnZXJhbSBfb3V0cHV0c18gcnVpbnMuIEFzc2ltLCDDqSBleHRyZW1hbWVudGUgaW1wb3J0YW50ZSBfc2VwYXJhciBvIGpvaW8gZG8gdHJpZ29fLiBBIHByaW1laXJhIGV0YXBhIGRlIHVtYSBhbsOhbGlzZSAtIGUgdGFsdmV6IGEgbWFpcyBpbXBvcnRhbnRlIC0gw6kgYSBjdXJhZG9yaWEgZGEgaW5mb3JtYcOnw6NvIHF1ZSBzZSB2YWkgdXRpbGl6YXI7IHN1YSBxdWFsaWRhZGUgaXLDoSBpbmZsdWVuY2lhciB0b2RvIG8gcmVzdG8uCgohW190cmFzaCBpbiwgdHJhc2ggb3V0X10oL2hvbWUvaGVyb24vcHJqY3RzL2Jpb2luZm8vbWlzYy90cmFzaElOdHJhc2hPVVQuanBnKQoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7ClVtYSB2ZXogcXVlIG9zIGFycXVpdm9zIF8uZmFzdHFfIGFwcmVzZW50YW0gaW5kaWNhZG9yZXMgZGUgcXVhbGlkYWRlIHBhcmEgdG9kYXMgYXMgYmFzZXMgZGUgdG9kYXMgYXMgX3JlYWRzXywgw6kgcG9zc8OtdmVsIHNlbGVjaW9uYXIgYXBlbmFzIGFzIF9yZWFkc18gKG91IHN1YXMgcGFydGVzKSBxdWUgYXByZXNlbnRlbSBxdWFsaWRhZGUgc2F0aXNmYXTDs3JpYSBwYXJhIHV0aWxpemHDp8OjbyBuYXMgYW7DoWxpc2VzIHN1YnNlcXVlbnRlcywgbWluaW1pemFuZG8gYSBwcm9wYWdhw6fDo28gZGUgZXJyb3MgYXRyYXbDqXMgZG8gX3BpcGVsaW5lXywgcXVlIHBvZGVtIHJlc3VsdGFyIGVtIHJ1w61kbyBvdSBtZXNtbyBlbSBwYWRyw7VlcyBiaW9sw7NnaWNvcyBpbmV4aXN0ZW50ZXMuIE1hcywgY29tbyBmYXplciBlc3NhIGF2YWxpYcOnw6NvIHBhcmEgdGFudGFzIHNlcXXDqm5jaWFzIGUgYXJxdWl2b3MgZGUgdW1hIHPDsyB2ZXo/CgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKT3MgcHJvZ3JhbWFzICpGYXN0UUMqICYgKk11bHRpUUMqIHBvc3NpYmlsaXRhbSB1bWEgaW5zcGXDp8OjbyBxdWFsaXRhdGl2YSBlIHF1YW50aXRhdGl2YSBkZSBjb25qdW50b3MgZGUgZGFkb3MgcHJvdmVuaWVudGVzIGRlIHNlcXVlbmNpYWRvcmVzIGRlIG5vdmEgZ2VyYcOnw6NvLiBFc3RlcyBwcm9ncmFtYXMgX2xlZW1fIHRvZG9zIGluZGljYWRvcmVzIGRlIHF1YWxpZGFkZSBkZSB0b2RhcyBhcyBfcmVhZHNfIGUgb3MgY29udmVydGVtIGVtIGRpdmVyc29zIHN1bcOhcmlvcyBncsOhZmljb3MgcXVlIGZhY2lsaXRhbSBhIGF2YWxpYcOnw6NvIGRlIHVtIG91IG3Dumx0aXBsb3MgYXJxdWl2b3MgXy5mYXN0cV8uCgojIyMgRmFzdFFDCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKTyBwcm9ncmFtYSBbKkZhc3RRQypdKGh0dHBzOi8vd3d3LmJpb2luZm9ybWF0aWNzLmJhYnJhaGFtLmFjLnVrL3Byb2plY3RzL2Zhc3RxYy8pIGZvaSBkZXNlbnZvbHZpZG8gZW0gMjAxMCwgZSDDqSBlc2NyaXRvIG5hIF9saW5ndWFnZW0gZGUgcHJvZ3JhbWHDp8Ojb18KWypKYXZhKl0oaHR0cHM6Ly9wdC53aWtpcGVkaWEub3JnL3dpa2kvSmF2YV8obGluZ3VhZ2VtX2RlX3Byb2dyYW1hJUMzJUE3JUMzJUEzbykpLiBFbGUgZ2VyYSBfcmVwb3J0c18gZW0gWypIVE1MKl0oaHR0cHM6Ly9wdC53aWtpcGVkaWEub3JnL3dpa2kvSFRNTCkgcGFyYSBjYWRhIGFycXVpdm8gXy5mYXN0cV8gcG9yIHZleiwgbyBxdWUgcmVmbGV0ZSBvIF9lc3RhZG8gZGEgYXJ0ZV8gZGFzIGFwbGljYcOnw7VlcyBOR1MgZGUgc3VhIMOpcG9jYSwgb25kZSBnZXJhbG1lbnRlIHVtYSBvdSBwb3VjYXMgYW1vc3RyYXMgZXJhbSBzZXF1ZW5jaWFkYXMgcG9yIGNvcnJpZGEuCgoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7ClN1YSB1dGlsaXphw6fDo28gw6kgZXh0cmVtYW1lbnRlIHNpbXBsZXMsIGNvbW8gdmVyZW1vcyBhIHNlZ3Vpci4KCj4gQ3JpZSB1bWEgcGFzdGEgX3F1YWxpZGFkZV8gcGFyYSBhcm1hemVuYXJtb3Mgb3MgcmVzdWx0YWRvcyBkbyAqRmFzdFFDKi4gRW0gc2VndWlkYSwgcm9kZSBvIHByb2dyYW1hIHBhcmEgYW1iYXMgYXMgX3JlYWRzXyBkZSB1bSBwYXIgZGUgYXJxdWl2b3MgZGEgc3VhIGVzY29saGE6CgpgYGB7YmFzaCwgZWNobz1UUlVFLGV2YWw9RkFMU0V9CiMgZW50cmUgbmEgcGFzdGEgY29ycmVzcG9uZGVudGUgYSBlc3RhIGF1bGEKY2Qgfi8kVFVSTUEvJEFMVU5PLwoKIyBjcmllIHVtYSBzdWJwYXN0YSAKbWtkaXIgcXVhbGlkYWRlCgojIHZlamEgYXMgaW5zdHXDp8O1ZXMgZGUgdXNvIGRvIHByb2dyYW1hIChzYWlhIGNvbSAicSIpCmZhc3RxYyAgLS1oZWxwIHwgbGVzcwoKIyByb2RlIG8gcHJvZ3JhbWEsIGFwb250YW5kbyBvIGNhbWluaG8gY29tcGxldG8gcGFyYSBvcyBhcnF1aXZvcyBkZSBlbnRyYWRhIChpbnB1dCkgZSBwYXJhIGEgcGFzdGEgZGUgc2HDrWRhIChvdXRwdXQpCmZhc3RxYyAkQ0FNSU5IT19DT01QTEVUTy8kQVJRVUlWT19GQVNUUV9SMSAtbyAkQ0FNSU5IT19DT01QTEVUTy9xdWFsaWRhZGUKCiMgcmVwaXRhIGEgYW7DoWxpc2UgcGFyYSBvIGFycXVpdm8gUjIgY29ycmVzcG9uZGVudGUKZmFzdHFjICRDQU1JTkhPX0NPTVBMRVRPLyRBUlFVSVZPX0ZBU1RRX1IyIC1vICRDQU1JTkhPX0NPTVBMRVRPL3F1YWxpZGFkZQoKIyB2ZWphIG9zIG91dHB1dHMgY3JpYWRvcwpscyAkQ0FNSU5IT19DT01QTEVUTy9xdWFsaWRhZGUKCmBgYAoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Ck9ic2VydmUgcXVlIGZvcmFtIGdlcmFkb3MgMiBhcnF1aXZvcyBwYXJhIGNhZGEgYXJxdWl2byBfLmZhc3RxXy4gVW0gZGVsZXMsIG8gXy56aXBfLCBjb250w6ltIGFzIGluZm9ybWHDp8O1ZXMgZ2VyYWRhcyBuYSBhbsOhbGlzZSwgcXVlIHPDo28gc3VtYXJpemRhcyBubyBvdXRybyBhcnF1aXZvLCBvIF8uaHRtbF8uCgojIyMjIFRyYW5zZmVyaW5kbyBhcnF1aXZvcwoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7ClBhcmEgYSB2aXN1YWxpemHDp8OjbyBkZXNzZSBfcmVwb3J0XyBlbSBfLmh0bWxfIMOpIG5lY2Vzc8OhcmlvIHVtIG5hdmVnYWRvciBkZSBpbnRlcm5ldCwgcXVlIG7Do28gZXhpc3RlIG5hIGxpbmhhIGRlIGNvbWFuZG8sIHBvaXMgcmVxdWVyIHVtYSBpbnRlcmZhY2UgZ3LDoWZpY2EuIEFzc2ltLCBlc3RlcyBhcnF1aXZvcyBwcmVjaXNhbSBzZXIgY29waWFkb3MgcGFyYSBvIGNvbXB1dGFkb3IgbG9jYWwsIHZpYSBsaW5oYSBkZSBjb21hbmRvLCBwYXJhIGRlcG9pcyBzZXJlbSBhYmVydG9zIG51bSBuYXZlZ2Fkb3IgZGUgaW50ZXJuZXQuIAoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7CkVzc2EgdHJhbnNmZXLDqm5jaWEgZGUgYXJxdWl2b3Mgw6kgZmVpdGEgZGUgbWFuZWlyYSBzZW1lbGhhbnRlIMOgIGNvbmV4w6NvIHBvciBTU0ggZG8gY29tcHV0YWRvciBsb2NhbCBjb20gbyBzZXJ2aWRvciwgZSB1dGlsaXphIG8gY29tYW5kbyAqKipzY3AqKiouClZhbW9zIGZhemVyIGlzc28uCgo+IElkZW50aWZpcXVlIG8gY2FtaW5obyBjb21wbGV0bywgKm5vIHNlcnZpZG9yKiwgcGFyYSBvcyBhcnF1aXZvcyBxdWUgc2UgZGVzZWphIGNvcGlhcgoKYGBge2Jhc2gsIGVjaG89VFJVRSxldmFsPUZBTFNFfQoKIyBsaXN0ZSBvcyBhcnF1aXZvcyBodG1sIHVzYW5kbyBvIGNhbWluaG8gY29tcGxldG8KbHMgJENBTUlOSE9fQ09NUExFVE8vcXVhbGlkYWRlLypodG1sCgpgYGAKCgoKPiBBYnJhIHVtIG5vdm8gdGVybWluYWwgX2xpbnV4Xy4gVXRpbGl6ZSBvIGNvbWFuZG8gKnNjcCogcGFyYSBjb3BpYXIgb3MgYXJxdWl2b3MgZG8gc2Vydmlkb3IgcGFyYSBvIGNvbXB1dGFkb3IgbG9jYWwuIFN1YnN0aXR1YSBhcyB2YXJpw6F2ZWlzICRUVVJNQSBlICRBTFVOTyBwZWxvIGNvbnRlw7pkbyByZXNwZWN0aXZvIMOgIHN1YXMgcGFzdGFzLCBvdSB1c2UgbyBjYW1pbmhvIGNvbXBsZXRvIHF1ZSB2b2PDqiBpZGVudGlmaWNvdSBubyBwYXNzbyBhbnRlcmlvci4KCmBgYHtiYXNoLCBlY2hvPVRSVUUsZXZhbD1GQUxTRX0KI2NyaWUgdW1hIHBhc3RhIGxvY2FsbWVudGUgcGFyYSBhcm1hemVuYXIgb3MgYXJxdWl2b3MKY2QKCm1rZGlyIHF1YWxpZGFkZQoKY2QgcXVhbGlkYWRlCgojIHV0aWxpemUgbyBjb21hbm9kIHNjcCBwYXJhIGNvcGlhcgojIGVzdHJ1dHVyYSBkbyBjb21hbmRvOgojICAgICBzY3AgICAgICAgICAgICAgICBlbmRlcmXDp286b19xdWUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFfb25kZQojICAgICBzY3AgLVAgJFBPUlRBICRVU1VBUklPQCRJUDokQ0FNSU5IT19DT01QTEVUTy8kQVJRVUlWT19RVUVfU0VfUVVFUl9DT1BJQVIgJFBBU1RBX0RFX0RFU1RJTk9fTk9fQ09NUFVUQURPUl9MT0NBTApzY3AgICAgICAgLVAgODcyMiAgICAgICRVU0VSQCRJUDovaG9tZS9iaW9tZWQvJFRVUk1BLyRBTFVOTy9hcnF1aXZvcy9xdWFsaWRhZGUvKmh0bWwgICAgIC4KCiNsZW1icmUtc2UgcXVlIC4gc2lnaWZpY2EgImFxdWksIG5hIHBhc3RhIG9uZGUgZXN0b3UiCgojIGxpc3RlIG9zIGFycXVpdm9zIHF1ZSB2b2PDqiBjb3Bpb3UKbHMgLWxoCgojIGFicmEgbyBuYXZlZ2RvciBkZSBhcnF1aXZvcyBkbyB3aW5kb3dzIG5hIHBhc3RhIG9uZGUgZXN0w6EKZXhwbG9yZXIuZXhlIC4KCiMgY2xpcXVlIDJ4IG5vIGFycXVpdm8gcGFyYSBhYnLDrS1sbyBubyBuYXZlZ2Fkb3IKYGBgCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKUHJvbnRvISBBZ29yYSBwb2RlbW9zIGV4cGxvcmFyIGVzc2UgX3JlcG9ydF8hIAoKPiBBbmFsaXNlIG8gY29udGXDumRvIGRvIF9yZXBvcnRfLgoKCiMjIyBNdWx0aVFDCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKTyBwcm9ncmFtYSBbKk11bHRpUUMqXShodHRwczovL211bHRpcWMuaW5mby8pIGZvaSBkZXNlbnZvbHZpZG8gZW0gMjAxNiwgZSDDqSBlc2NyaXRvIG5hIF9saW5ndWFnZW0gZGUgcHJvZ3JhbWHDp8Ojb18KWypQeXRob24qXShodHRwczovL3B0Lndpa2lwZWRpYS5vcmcvd2lraS9QeXRob24pLiBFbGUgZm9pIGRlc2Vudm9sdmlkbyBwYXJhIGZhY2lsaXRhciBhIGF2YWxpYcOnw6NvIGRlIG3Dumx0aXBsb3MgYXJxdWl2b3MgXy5mYXN0cV8gcG9yIHZleiwgZGFkbyBxdWUsIGNvbSBvIGF2YW7Dp28gZSBiYXJhdGVhbWVudG8gZGFzIHBsYXRhZm9ybWFzIE5HUywgbcO6bHRpcGxhcyBhbW9zdHJhcyBlIGJpYmxpb3RlY2FzIHBhc3NhcmFtIGEgc2VyIHNlcXVlbmNpYWRhcyBzaW11bHTDom5lYW1lbnRlLiBFc3RlIHByb2dyYW1hIHV0aWxpemEgb3MgZGl2ZXJzb3MgcmVsYXTDs3Jpb3MgZ2VyYWRvcyBwZWxvICpGYXN0UUMqIGUgb3MgY29tYmluYSBlbSB1bSDDum5pY28gc3Vtw6FyaW8gZ3LDoWZpY28sIHRhbWLDqW0gZW0gWypIVE1MKl0oaHR0cHM6Ly9wdC53aWtpcGVkaWEub3JnL3dpa2kvSFRNTCksIGNvbSB1bWEgYXByZXNlbnRhw6fDo28gbWFpcyBtb2Rlcm5hIGUgaW50ZXJhdGl2YS4KCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKVmFtb3MgY3JpYXIgdXRpbGl6w6EtbG8gcGFyYSBjcmlhciB1bSDDum5pY28gX3JlcG9ydF8sIGRlc3RhIHZleiBwYXJhIG9zIF9yZXBvcnRzXyBkbyAqRmFzdFFDKiBwYXJhIHRvZG9zIGFycXVpdm9zIGRlIF9yZWFkc18uCgo+IFV0aWxpemFuZG8gbyAqRmFzdFFDKiwgZ2VyZSBfcmVwb3J0c18gcGFyYSB0b2RvcyBhcnF1aXZvcyBfLmZhc3RxXywgZW0gdW0gw7puaWNvIGNvbWFuZG86CgpgYGB7YmFzaCwgZWNobz1UUlVFLGV2YWw9RkFMU0V9CiMgdm9sdGUgcGFyYSBhIHBhc3RhIG9uZGUgZXN0w6NvIG9zIHByaW1laXJvcyByZXBvcnRzCmNkIHF1YWxpZGFkZQoKIyByb2RlIG8gRmFzdFFDIHBhcmEgdG9kb3MgYXJxdWl2b3Mgc2ltdWx0YW5lYW1lbnRlCmZhc3RxYyAkQ0FNSU5IT19DT01QTEVUTy9hcnF1aXZvcy9mYXN0cS8qLmZhc3RxIC1vICRDQU1JTkhPX0NPTVBMRVRPL3F1YWxpZGFkZQoKIyB2ZWphIG9zIG91dHB1dHMgY3JpYWRvcwpscyAkQ0FNSU5IT19DT01QTEVUTy9xdWFsaWRhZGUKCmBgYAoKPiBVdGlsaXphbmRvIG8gKk11bHRpUUMqLCBnZXJlICB1bSBfcmVwb3J0XyBzdW1hcml6YW5kbyB0b2RvcyBhcnF1aXZvcyBjcmlhZG9zIHBlbG8gKkZhc3RRQyo6CgpgYGB7YmFzaCwgZWNobz1UUlVFLGV2YWw9RkFMU0V9CiMgdm9sdGUgcGFyYSBhIHBhc3RhIG9uZGUgZXN0w6NvIG9zIHByaW1laXJvcyByZXBvcnRzCmNkIHF1YWxpZGFkZQoKIyBjcmllIHVtYSBwYXN0YSBwYXJhIG8gbXVsdGlxYwpta2RpciBtdWx0aXFjCgojIGVudHJlIG5hIHBhc3RhCmNkIG11bHRpcWMKCiNjb25maXJhIG8gY2FtaW5obyBvbmRlIGVzdMOhCnB3ZAoKIyB2ZWphIGFzIGluc3R1w6fDtWVzIGRlIHVzbyBkbyBwcm9ncmFtYSAoc2FpYSBjb20gInEiKQptdWx0aXFjICAtLWhlbHAgfCBsZXNzCgojIHJvZGUgbyBwcm9ncmFtYQptdWx0aXFjIC0taW50ZXJhY3RpdmUgJENBTUlOSE9fQ09NUExFVE8vcXVhbGl0eS9tdWx0aXFjIC0tb3V0ZGlyIC4KCiMgdmVqYSBvcyBvdXRwdXRzIGNyaWFkb3MKbHMgJENBTUlOSE9fQ09NUExFVE8vcXVhbGlkYWRlL211bHRpcWMKCmBgYAoKIyMjIFRyYW5zZmVyaW5kbyBhcnF1aXZvcwoKCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwpBZ29yYSwgZGUgbWFuZWlyYSBzZW1lbGhhbnRlIGFvIHF1ZSBqw6EgZml6ZW1vcywgdmFtb3MgY29waWFyIGVzc2UgX3JlcG9ydF8gZ2VyYWRvIHBlbG8gKk11bHRpUUMqIHBhcmEgbyBjb21wdXRhZG9yIGxvY2FsLCBwYXJhIHBvZGVybW9zIHZpc3VhbGl6w6EtbG8uCgoKPiBBYnJhIHVtIG5vdm8gdGVybWluYWwgX2xpbnV4Xy4gVXRpbGl6ZSBvIGNvbWFuZG8gKnNjcCogcGFyYSBjb3BpYXIgb3MgYXJxdWl2b3MgZG8gc2Vydmlkb3IgcGFyYSBvIGNvbXB1dGFkb3IgbG9jYWwuIFN1YnN0aXR1YSBhcyB2YXJpw6F2ZWlzICRUVVJNQSBlICRBTFVOTyBwZWxvIGNvbnRlw7pkbyByZXNwZWN0aXZvIMOgIHN1YXMgcGFzdGFzLCBvdSB1c2UgbyBjYW1pbmhvIGNvbXBsZXRvIHF1ZSB2b2PDqiBpZGVudGlmaWNvdSBubyBwYXNzbyBhbnRlcmlvci4KCmBgYHtiYXNoLCBlY2hvPVRSVUUsZXZhbD1GQUxTRX0KI2NyaWUgdW1hIHBhc3RhIGxvY2FsbWVudGUgcGFyYSBhcm1hemVuYXIgb3MgYXJxdWl2b3MKY2QgcXVhbGlkYWRlCgpta2RpciBtdWx0aXFjCgpjZCBtdWx0aXFjCgpwd2QKCiMgdXRpbGl6ZSBvIGNvbWFub2Qgc2NwIHBhcmEgY29waWFyCiMgZXN0cnV0dXJhIGRvIGNvbWFuZG86CiMgICAgIHNjcCAgICAgICAgICAgICAgIGVuZGVyZcOnbzpvX3F1ZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYV9vbmRlCiMgICAgIHNjcCAtUCAkUE9SVEEgJFVTVUFSSU9AJElQOiRDQU1JTkhPX0NPTVBMRVRPLyRBUlFVSVZPX1FVRV9TRV9RVUVSX0NPUElBUiAkUEFTVEFfREVfREVTVElOT19OT19DT01QVVRBRE9SX0xPQ0FMCnNjcCAgICAgICAtUCA4NzIyICAgICAgJFVTRVJAJElQOi9ob21lL2Jpb21lZC8kVFVSTUEvJEFMVU5PL2FycXVpdm9zL3F1YWxpZGFkZS9tdWx0aXFjLypodG1sICAgICAuCgojbGVtYnJlLXNlIHF1ZSAuIHNpZ2lmaWNhICJhcXVpLCBuYSBwYXN0YSBvbmRlIGVzdG91IgoKIyBsaXN0ZSBvcyBhcnF1aXZvcyBxdWUgdm9jw6ogY29waW91CmxzIC1saAoKIyBhYnJhIG8gbmF2ZWdkb3IgZGUgYXJxdWl2b3MgZG8gd2luZG93cyBuYSBwYXN0YSBvbmRlIGVzdMOhCmV4cGxvcmVyLmV4ZSAuCgojIGNsaXF1ZSAyeCBubyBhcnF1aXZvIHBhcmEgYWJyw60tbG8gbm8gbmF2ZWdhZG9yCmBgYAoKCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwpQcm9udG8hIEFnb3JhIHBvZGVtb3MgZXhwbG9yYXIgZXNzZSBfcmVwb3J0XyEgCgo+IEFuYWxpc2UgbyBjb250ZcO6ZG8gZG8gX3JlcG9ydF8uCgoKKioqCgo+Pj4+IFZvbHRhciBwYXJhIGEgWypww6FnaW5hIGluaWNpYWwqXShodHRwczovL2hlcm9ub2guZ2l0aHViLmlvL2Jpb2luZm8pCgoKCgoKCg==