Você está na página 1de 149

Giovanni Allan Buranello

Instrumenta
c
ao de programas Delphi para
implementa
c
ao de crit
erios de teste
estrutural

Marlia - SP
Dezembro / 2006

Giovanni Allan Buranello

Instrumenta
c
ao de programas Delphi para
implementa
c
ao de crit
erios de teste
estrutural
Dissertacao apresentada ao Programa
Mestrado em Ciencia da Computacao
Fundacao Eurpides Soares da Rocha
Marlia para a obtencao da qualificacao
Mestrado em Ciencia da Computacao.

de
da
de
no

Orientador:
o

Prof . Dr . Marcio Eduardo Delamaro

ncia da Computac
o
Mestrado em Cie
a
s-graduac
o em Cie
ncia da Computac
o
PPGCC - Programa de Po
a
a
o Eurpides Soares da Rocha
Fundac
a

Marlia - SP
Novembro / 2006

Agradecimentos
Dedico meus sinceros agradecimentos:
ao professor doutor Marcio Eduardo Delamaro, pela orientacao e incentivo;
ao professor doutor Auri Marcelo Rizzo Vicenzi, pelo seu inestimavel auxlio na
conclusao deste trabalho;
ao professor doutor Adenilso da Silva Simao, pela criacao da Ferramenta IDeL e
pelo apoio e incentivo;
a Gustavo Rondina, que foi peca fundamental para realizacao deste trabalho;
a Roque Maitino Neto, pelo apoio e amizade;
`a Fundacao Eurpides de Marlia;
a todos os colegas do Mestrado em Ciencia da Computacao da UNIVEM Marlia.

Uma coisa so e impossvel ate que alguem


duvida e acaba provando o contrario.
Albert Einstein

Resumo
Os softwares tem sido cada vez mais utilizados em tarefas importantes, estando em
evidencia a procura de confianca nos mesmos.
Devido `a quantidade de falhas e erros encontrados nos softwares, um grande esforco
tem sido feito visando solucionar esse crescente problema. Para tanto, foram desenvolvidas
diversas tecnicas, criterios e ferramentas de teste para garantir a qualidade e confianca do
produto.
Uma das fases do teste de software e a instrumentacao, no qual sao inseridos pontos de provas sobre o codigo de um programa feito em uma determinada linguagem de
programacao, afim de auxiliar o testador a reconhecer onde e o que foi executado.
Ferramentas de teste de software para linguagem de programacao Delphi sao escassas.
Sendo assim, o presente trabalho foi desenvolvido no sentido de diminuir a escassez, e
tem como objetivo o desenvolvimento de um instrumentador de codigo para a linguagem
Delphi, com o auxlio da linguagem de descricao de instrumentacao IDeL, que torna o
processo de desenvolvimento de instrumentadores mais eficientes atraves da confeccao de
uma gramatica e uma descricao para a instrumentacao.
Palavras-chaves: Instrumentacao, Delphi, IDel, IDelGen, Gramatica, Yacc, lex, Teste
de Software e Criterio de Teste.

Abstract
Software systems have been more used in important tasks each day, in evidence,
nowadays, is also the search for trust on them.
Because of the quantity of fails and errors found in these softwares, a great effort
has been made, trying to solve this increasing problem. For such result, many technique,
testing criteria and testing tools were developed to guarantee the quality of the product.
One of software testing phases is the instrumentation, where checking points are
inserted into a program code written in a certain programming language, in such a way,
to help the recognize where and what has been executed.
Delphi programming language software testing tools deficient. This way, the present
dissertation was developed in a way to fulfill this deficiency, and has as an objective,
the development of an instrumenter code for Delphi language, with the help of IDeL
instrumentation description language, which makes the process of the development of
intrumenters more efficient through the arrangement of grammar and a description for
the instrumentation.
keyworks: Instrumentation, Delphi, IDel, IDelGen, Grammar, Yacc, lex, Software
Testing e Testing criteria.

Sum
ario

Lista de Figuras
1 Introduc
ao

p. 13

1.1

Contexto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 13

1.2

Motivacao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 14

1.3

Organizacao do trabalho . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 15

2 A Atividade de Teste
2.1

2.2

2.3

2.4

p. 16

Tecnicas de Teste de Software . . . . . . . . . . . . . . . . . . . . . . .

p. 17

2.1.1

Teste Funcional . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 17

2.1.2

Teste Baseado em Erro . . . . . . . . . . . . . . . . . . . . . . .

p. 18

2.1.3

Teste Estrutural . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 18

Fases da Atividade de Teste . . . . . . . . . . . . . . . . . . . . . . . .

p. 21

2.2.1

Teste de Unidade . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 21

2.2.2

Teste de Integracao . . . . . . . . . . . . . . . . . . . . . . . . .

p. 22

2.2.3

Teste de Sistema . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 23

Ferramentas de Teste Estrutural . . . . . . . . . . . . . . . . . . . . . .

p. 23

2.3.1

Ferramenta POKE-TOOL . . . . . . . . . . . . . . . . . . . . .

p. 24

2.3.2

Ferramenta JaBUTi

. . . . . . . . . . . . . . . . . . . . . . . .

p. 25

2.3.3

Ferramenta Discover . . . . . . . . . . . . . . . . . . . . . . . .

p. 28

Consideracoes Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 30

3 Geradores de Compiladores

p. 32

3.1

Principais Caractersticas de uma Gramatica . . . . . . . . . . . . . . .

p. 32

3.2

Yacc e Lex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 37

3.3

Consideracoes Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 40

4 IDeL e IDeLGen
4.1

4.2

4.3

p. 41

Principais Caractersticas . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 42

4.1.1

Aspecto Operacional . . . . . . . . . . . . . . . . . . . . . . . .

p. 42

4.1.2

Estrutura do IDeL . . . . . . . . . . . . . . . . . . . . . . . . .

p. 43

4.1.2.1

Unidade de Identificacao . . . . . . . . . . . . . . . . .

p. 43

4.1.2.2

Unidade de Processamento

. . . . . . . . . . . . . . .

p. 43

4.1.2.3

Implementacao . . . . . . . . . . . . . . . . . . . . . .

p. 46

Execucao e Exemplos . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 46

4.2.1

Exemplos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 47

Consideracoes Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 48

5 Instrumentador para a linguagem Delphi


5.1

5.2

p. 51

Principais caractersticas da Linguagem Delphi . . . . . . . . . . . . . .

p. 52

5.1.1

Controladores de fluxo . . . . . . . . . . . . . . . . . . . . . . .

p. 52

5.1.2

Excecoes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 55

Aspectos de implementacao . . . . . . . . . . . . . . . . . . . . . . . .

p. 55

5.2.1

Geracao do arquivo delphi.idel . . . . . . . . . . . . . . . . . . .

p. 56

5.2.1.1

Identificacao das Unidades . . . . . . . . . . . . . . . .

p. 57

5.2.1.2

Processamento das Unidades . . . . . . . . . . . . . .

p. 58

Passo FindFunction . . . . . . . . . . . . . . . . . . . . . . . . .

p. 59

Passo MarkStatements . . . . . . . . . . . . . . . . . . . . . . .

p. 60

Passo LinkStatement . . . . . . . . . . . . . . . . . . . . . . . .

p. 61

Passo JoinStatement . . . . . . . . . . . . . . . . . . . . . . . .

p. 62

Passo JoinToFunction . . . . . . . . . . . . . . . . . . . . . . .

p. 63

Passo MakeGraph . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 65

Secao de Implementacao . . . . . . . . . . . . . . . . . . . . . .

p. 73

5.3

Execucao do Instrumentador . . . . . . . . . . . . . . . . . . . . . . . .

p. 74

5.4

Consideracoes Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 76

5.2.2

6 Estudo de Caso

p. 79

6.1

Descricao do Programa . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 79

6.2

Tamanho do Programa . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 80

6.3

Tempo de execucao . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 83

6.4

Consideracoes Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 86

7 Conclus
oes e trabalhos futuros
7.1

Trabalhos Futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 91
p. 92

Refer
encias

p. 94

Apendice A - Gram
atica do Delphi (delphi.y)

p. 96

Ap
endice B - Gram
atica do Delphi (delphi.l)

p. 128

Ap
endice C - Descric
ao do Delphi na IDeL (delphi.idel)

p. 133

Lista de Figuras
2.1

Grafo de Fluxo de Controle . . . . . . . . . . . . . . . . . . . . . . . .

p. 19

2.2

Grafo de fluxo de controle . . . . . . . . . . . . . . . . . . . . . . . . .

p. 21

2.3

Opcoes disponveis na ferramenta POKE-TOOL . . . . . . . . . . . . .

p. 25

2.4

Tela para criar uma sessao de teste na POKE-TOOL . . . . . . . . . .

p. 25

2.5

Exemplo da tela JaBUTi, visualizacao pelo codigo-fonte . . . . . . . . .

p. 26

2.6

Grafo gerado pela JaBUTi no criterios Todos-Arcos-ei . . . . . . . . . .

p. 27

2.7

JaBUTi - codigo bytecode . . . . . . . . . . . . . . . . . . . . . . . . .

p. 28

2.8

JaBUTi - Sumario de cobertura por criterio . . . . . . . . . . . . . . .

p. 28

2.9

JaBUTi - Cobertura da classe por criterio . . . . . . . . . . . . . . . .

p. 28

2.10 JaBUTi - Cobertura por metodos . . . . . . . . . . . . . . . . . . . . .

p. 29

2.11 Tela de execucao de teste na Ferramenta Discover . . . . . . . . . . . .

p. 30

2.12 Pasta Linker do Delphi . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 30

3.1

Programa exemplo while . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 33

3.2

Arvore
sintatica while

. . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 33

3.3

Exemplo da gramatica BNF . . . . . . . . . . . . . . . . . . . . . . . .

p. 35

3.4

Programa exemplo - gramatica BNF . . . . . . . . . . . . . . . . . . .

p. 35

3.5

Exemplo de uma producao

p. 36

3.6

Exemplo de uma producao opcional

3.7

Exemplo de uma producao com repeticao

. . . . . . . . . . . . . . . .

p. 36

3.8

Exemplo de uma producao com repeticao

. . . . . . . . . . . . . . . .

p. 37

3.9

Gramatica de uma declaracao de variavel em C simplificada . . . . . .

p. 37

3.10 Arquivo com regras lexico . . . . . . . . . . . . . . . . . . . . . . . . .

p. 38

. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .

p. 36

3.11 Arquivo sintatico para a producao do analisador sintatico . . . . . . . .

p. 39

4.1

Execucao IDeLgen . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 43

4.2

Regra de instrumentacao do comando while

. . . . . . . . . . . . . . .

p. 44

4.3

Grafo de como funciona a regra while . . . . . . . . . . . . . . . . . . .

p. 46

4.4

P - programateste.C . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 48

4.5

Arquivo programateste-instrumentado.C . . . . . . . . . . . . . . . . .

p. 48

4.6

Arquivo programateste.main.dot . . . . . . . . . . . . . . . . . . . . . .

p. 49

4.7

Grafo gerado pela Ferramenta Graphviz

. . . . . . . . . . . . . . . . .

p. 49

5.1

Geracao do instrumentador idel.delphi . . . . . . . . . . . . . . . . . .

p. 56

5.2

Secao de identificacao das unidades do arquivo delphi.idel. . . . . . . .

p. 57

5.3

Arvore
de padroes da producao :head. . . . . . . . . . . . . . . . . . . .

p. 58

5.4

Programa Exemplo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 59

5.5

Padrao FindFunction. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 60

5.6

Grafo do Padrao FindFunction. . . . . . . . . . . . . . . . . . . . . . .

p. 60

5.7

Arvore
sintatica fplist. . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 60

5.8

Padrao MarkSatatements. . . . . . . . . . . . . . . . . . . . . . . . . .

p. 61

5.9

Grafo do Padrao MarkStatements. . . . . . . . . . . . . . . . . . . . . .

p. 61

5.10 Padrao LinkStatementList. . . . . . . . . . . . . . . . . . . . . . . . . .

p. 62

5.11 Grafo do Padrao LinkStatement. . . . . . . . . . . . . . . . . . . . . .

p. 62

5.12 Padrao JoinStantemet. . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 63

5.13 Grafo do Passo JoinStatement. . . . . . . . . . . . . . . . . . . . . . .

p. 63

5.14 Padrao JoinToFunction. . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 64

5.15 Grafo do Passo JoinToFunction. . . . . . . . . . . . . . . . . . . . . . .

p. 64

5.16 Instrumentacao do Passo JoinToFunction. . . . . . . . . . . . . . . . .

p. 65

5.17 Padrao While. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 66

5.18 Grafo Padrao While. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 67

5.19 Instrumentacao do padrao While. . . . . . . . . . . . . . . . . . . . . .

p. 67

5.20 Padrao Try2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 68

5.21 Grafo Padrao Try2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 68

5.22 Padrao if-then. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 69

5.23 Grafo Padrao if-then. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 69

5.24 Instrumentacao do padrao If-Then . . . . . . . . . . . . . . . . . . . . .

p. 70

5.25 Passo IfThenElse. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 70

5.26 Grafo Padrao if-then-else. . . . . . . . . . . . . . . . . . . . . . . . . .

p. 71

5.27 Instrumentacao do padrao If-Then-else . . . . . . . . . . . . . . . . . .

p. 71

5.28 Padrao RepeatUntil. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 72

5.29 Grafo do Padrao RepeatUntil. . . . . . . . . . . . . . . . . . . . . . . .

p. 72

5.30 Codigo nao instrumentado (a) codigo instrumentado (b) . . . . . . . .

p. 73

5.31 Padrao ForTo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 73

5.32 Grafo do Padrao ForTo. . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 74

5.33 Codigo nao instrumentado (a) codigo instrumentado (b). . . . . . . . .

p. 75

5.34 Implementacao do checkopoint before. . . . . . . . . . . . . . . . . . .

p. 75

5.35 Programa exemplo funcao exittest. . . . . . . . . . . . . . . . . . . . .

p. 76

5.36 Execucao da IDeL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 76

5.37 Funcao exittest instrumentada . . . . . . . . . . . . . . . . . . . . . . .

p. 77

5.38 Grafo da funcao exittest. . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 77

5.39 Arquivo DOT da funcao exittest. . . . . . . . . . . . . . . . . . . . . .

p. 78

6.1

Exemplo de realce de contraste com o filtro Butterworth (NUNES, 2001)

p. 80

6.2

Exemplo de equalizacao de Histograma (NUNES, 2001) . . . . . . . . .

p. 81

6.3

Realce de contraste pela Curva Caracterstica . . . . . . . . . . . . . .

p. 85

6.4

Realce de Contraste pelos Coeficientes de Atenuacao e Segmentacao . .

p. 85

6.5

Realce de Contraste pela Modificacao do Histograma e Segmentacao . .

p. 88

6.6

Arquivo DOT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

p. 88

6.7

Grafo da Procedure Pacotelocal . . . . . . . . . . . . . . . . . . . . . .

p. 89

6.8

Grafo da Procedure Pacotelocal Percorrido . . . . . . . . . . . . . . . .

p. 90

13

Introdu
c
ao

Neste captulo serao apresentados o contexto, a motivacao para realizar o trabalho e


os objetivos a serem atingidos. No final do captulo, e apresentada a estrutura para esta
dissertacao.

1.1

Contexto

A Engenharia de Software tem crescido tanto em importancia, quanto em abrangencia


de atuacao. Na decada de 60, o software exercia papel secundario em detrimento ao
hardware (PRESSMAN, 2001). Com a crescente necessidade de produtos mais confiaveis,
o planejamento e o uso de tecnicas passaram a fazer parte do desenvolvimento do software.
No tocante `a abrangencia de sua atuacao, a engenharia de software passou a englobar
atividades que dizem respeito nao apenas `a fase de construcao do produto, mas tambem
aos processos posteriores `a sua implantacao. A depuracao, a visualizacao da informacao e
a analise de codigo sao exemplos de atividades realizadas, muitas vezes apos a implantacao
do sistema, mas que mantem o mesmo nvel de importancia em relacao aos processos
preliminares da engenharia de sistemas.
O desenvolvimento de software envolve uma serie de atividades humanas nas quais a
possibilidade de inclusao de falhas e erros no projeto podem ser enormes e ocasionarem
grande dano. Erros podem comecar a surgir imperceptivelmente, logo no incio do processo
de desenvolvimento de um produto. Assim, a atividade de teste e de vital importancia
na garantia da qualidade do software, representando a u
ltima revisao da especificacao,
projeto e codificacao (PRESSMAN, 2001).
A visibilidade crescente do software como um elemento do sistema e o custo associado `a
falha motivam esforcos para a pratica de testes em software(PRESSMAN, 2001) . Segundo
Pressman (2001) nao e raro que uma empresa de desenvolvimento de software consuma
entre trinta e quarenta por cento do custo total do projeto em testes.

1.2 Motivac
ao

14

No intuito de reduzir tais custos, varias tecnicas e criterios que auxiliam na conducao
e avaliacao da atividade de teste tem sido desenvolvidos e aprimorados. A diferenca entre
estas tecnicas esta, basicamente, na origem da informacao que e utilizada para avaliar ou
construir conjuntos de casos de teste, possuindo cada tecnica uma variedade de criterios
para esse fim. Na tecnica Funcional (caixa-preta), os requisitos e testes sao obtidos a
partir da especificacao do produto; na tecnica Estrutural (caixa branca), os requisitos sao
obtidos a partir da propria implementacao do software. Finalmente, na tecnica Baseada
em Erros, os elementos requeridos para caracterizar a atividade de teste sao baseados
em erros comuns que podem ocorrer durante o desenvolvimento de software (VINCENZI,
1997).

1.2

Motivac
ao

Para a aplicacao de teste e necessaria a existencia de uma ferramenta de teste automatizada que o apoie. Pelo uso de ferramentas e possvel obter maior eficacia e uma
reducao do esforco necessario para a realizacao do teste, bem como diminuir os erros que
sao causados pela intervencao humana nesta atividade.
A instrumentacao e uma tecnica frenq
uentemente usada na engenharia de software
por diferentes propositos, por exemplo, programa para rastrear a execucao, programa para
analisar corbertura de codigos em teste de software; usada tambem na engenharia reversa.
A instrumentacao de programas e uma das atividades realizadas pelas ferramentas de
teste. Este processo realiza a insercao de pontos de provas em lugares estrategicos, junto
ao codigo fonte de uma linguagem de programacao, sendo assim, e possvel a execucao do
programa fazendo um mapeamento do que e onde foi executado (SIMAO et al., 2001).
Varias ferramentas tem sido desenvolvidas com o objetivo de realizar instrumentacao
de codigo. Particularmente, a IDeL e IDeLgen (SIMAO et al., 2001) foram construdas
para serem integradas em um ambiente generico de teste baseado em fluxo de dados.
O que impulsionou o desenvolvimento deste trabalho foi a falta de ferramentas de
apoio ao teste estrutural para a linguagem de programacao Delphi. Com base nas ferramentas IDel e IDeLgen, foi desenvolvida uma aplicacao de suporte `a tecnica de teste
estrutural, que tem como objetivo instrumentar codigos escritos em Delphi. A IDeL realiza instrumentacao de codigos escritos em qualquer linguagem desde que, uma gramatica
e uma descricao de como instrumentar seja passada como parametro para a ferramenta
IDeLgen produzir o instrumentador para a linguagem em questao. Antes deste trabalho

1.3 Organizaca
o do trabalho

15

a IDeL contava somente com a gramatica e descricao de intrumentacao para a linguagem


de programacao C. No entanto, foi possvel a confeccao de uma gramatica para a linguagem Delphi e uma descricao de instrumentacao para a mesma, contribuindo assim, com
a ferramenta para atender mais uma linguagem de programacao (SIMAO et al., 2001).
No Captulo 4 serao abordadas as Ferramentas IDeL e IDeLgen em questao com
maiores detalhes.

1.3

Organizac
ao do trabalho

O presente trabalho inicia-se com a introducao. Em seguida, no Captulo 2, e descrito


o teste de software, ressaltando suas varias tecnicas, abordagens e fases. No Captulo 3 e
descrita a complexidade da confeccao da uma gramatica e tambem a adaptacao da mesma
nas ferramentas Yacc e Lex. No Captulo 4 sao descritas, detalhadamente, as ferramentas
IDel e IDeLgen, com a apresentacao de exemplos. No Captulo 5 e apresentado o proposito
deste trabalho e os exemplos de como foi confeccionada a descricao de intrumentacao para
linguagem Delphi. Ja no Captulo 6 e apresentado o estudo de caso, com o exemplo de um
programa propositalmente grande para averiguacao da ferramenta, escrita na linguagem
Delphi. No Captulo 7 sao apresentadas as consideracoes finais e sugestoes para futuros
trabalhos. Nos apendices sao apresentados os arquivos confeccionados. Os Apendices A e
B apresentam os arquivos delphi.y e delphi.l, respectivamente, nesta ordem, eles formam
a gramatica da linguagem Delphi; em seguida o Apendice C, que e o arquivo delphi.idel
que contem regras de como instrumentar a linguagem Delphi.

16

A Atividade de Teste

Sistematicamente, com o passar dos anos, as empresas desenvolvedoras de software


espalhadas pelo mundo tem investido recursos na missao de melhorar, em sentido amplo,
a qualidade de seu produto final. Novas abordagens de analise, tecnicas avancadas de
programacao e meios como teste tem sido usados em busca da qualidade. A engenharia de
software evoluiu significativamente nas u
ltimas decadas procurando estabelecer tecnicas,
criterios, metodos e ferramentas para producao de software. A crescente utilizacao de
sistemas baseados em computacao, em praticamente todas as areas de atividade humana,
provoca uma crescente procura por qualidade e confianca no software (SIMAO et al., 2001;
VINCENZI, 1997).

Desenvolver softwares com qualidade nao e uma tarefa facil. Pesquisadores na area de
Engenharia de Software tem trabalhado, desenvolvendo metodos, tecnicas e ferramentas
para propiciar o desenvolvimento de softwares com alta qualidade. Uma das atividades
que ajuda a garantir a qualidade e o teste de software. Este tem por objetivo identificar
possveis erros introduzidos durante o processo de desenvolvimento. A atividade de teste
consiste em executar um programa com o objetivo de encontrar erros, atraves dos seguintes
passos: 1) construcao de conjunto de casos de teste; 2) execucao de um programa com esse
conjunto de casos de teste; 3) analise do comportamento do programa para determinar
se o mesmo esta correto. Esses passos se repetem ate que se tenha confianca de que o
programa realiza o esperado com o mnimo de erros possvel (MALDONADO et al., 2004).
Duas abordagens sao utilizadas com o objetivo de encontrar formas economicas e produtivas: a abordagem teorica e a abordagem emprica. Na abordagem teorica, procuramse estabelecer propriedades e caractersticas dos criterios de teste, tais como, a eficacia de
uma estrategia de teste ou a relacao de inclusao entre os criterios. Entende-se por criterio
de teste a definicao de quais propriedades precisam ser testadas para encontrar o maior
n
umero de erros possvel. Na abordagem emprica, dados e estatsticas sao coletados, os
quais registram, por exemplo, a freq
uencia com que diferentes estrategias de teste revelam
a presenca de erros em uma determinada colecao de programas, fornecendo diretrizes para

2.1 Tecnicas de Teste de Software

17

a escolha entre os diversos criterios disponveis (HOWDEN, 1986).


O processo de desenvolvimento de software abrange uma diversidade de atividades
em que, apesar dos metodos, tecnicas e ferramentas empregados, erros ainda podem
ocorrer. Podem ocorrer desde o incio do desenvolvimento, por exemplo, especificando
erroneamente os requisitos do sistema, como tambem nos estagios finais pela insercao de
defeitos no projeto ou na implementacao do sistema (PRESSMAN, 2001).

2.1

T
ecnicas de Teste de Software

Os criterios de teste podem ser classificados basicamente em tres tecnicas: funcional,


estrutural e baseada em erros.
Segundo Maldonado (1991),
a diferenca entre essas tecnicas esta na origem da informac
ao utilizada
para avaliar ou construir os conjuntos de casos de teste, sendo que cada
uma delas possui um conjunto de criterios para esse fim.

No entanto, nenhuma destas tecnicas de teste e suficiente para garantir a qualidade


do teste. Na verdade, elas se complementam e devem ser aplicadas em conjunto a fim de
assegurar um teste de boa qualidade (PRESSMAN, 2001).

2.1.1

Teste Funcional

No teste funcional (ou teste caixa-preta), os requisitos de teste sao estabelecidos a partir das especificacoes do software, sua implementacao nao e necessariamente considerada.
O objetivo do teste funcional e encontrar discrepancias entre o comportamento atual do
sistema e o descrito em sua especificacao. Assim, consideram-se apenas as entradas, as
sadas e o estado do programa e o testador nao tem necessariamente acesso ao codigo
fonte do software (ROCHA et al., 2004). O sistema e uma caixa preta cujo comportamento somente pode ser determinado estudando suas entradas e sadas relacionadas. O
testador esta preocupado somente com a funcionalidade, e nao com a implementacao do
software (SOMMERVILLE, 2003). Pressman (2001) sustenta que o teste funcional tende a
ser exercido no u
ltimo estagio de teste, enquanto o teste estrutural e executado no inicio
do processo de teste, porque o teste funcional tem o proposito diferente do estrutural.
Um problema com a tecnica funcional e a dificuldade de quantificar a atividade de
teste, visto que nao se pode garantir que partes essenciais ou crticas do programa sejam

2.1 Tecnicas de Teste de Software

18

executadas (MALDONADO et al., 2004).

2.1.2

Teste Baseado em Erro

A tecnica de teste baseado em erro utiliza informacoes sobre os erros mais freq
uentes
cometidos no processo de desenvolvimento de software para derivar os requisitos de teste.
O destaque da tecnica esta nos erros que o programador ou projetista pode cometer
durante o desenvolvimento e nas abordagens que podem ser usadas para detectar sua
ocorrencia (MALDONADO et al., 2004). Dois criterios de teste baseado em erro sao:
semeadura de erros: neste criterio uma quantidade conhecida de erros e introduzida
no programa. Apos o teste, do total de erros encontrados, verificam-se quais sao
naturais e quais foram introduzidos. Usando de probabilidade estatstica, o n
umero
de erros naturais ainda existentes no programa pode ser estimado;
analise de mutantes: e um criterio que utiliza um conjunto de programas ligeiramente modificados, obtidos a partir de um determinado programa P, para avaliar o
quanto um conjunto de casos de teste T e adequado para o teste de P. O objetivo
e encontrar um conjunto de casos de teste capaz de revelar as diferencas de comportamento existentes entre P e seus mutantes (DEMILLO; LIPTON; SAYWARD,
1978).
.

2.1.3

Teste Estrutural

A tecnica de teste estrutural, conhecida como teste caixa branca (em oposicao ao
nome caixa preta), tem o mesmo objetivo das outras tecnicas. A diferenca encontra-se no
fato de o teste estrutural levar em consideracao a implementacao do programa. A maioria
dos criterios dessa tecnica utiliza uma representacao de programa conhecida como grafo
de programa ou grafo de fluxo de controle, mostrada na Figura2.1 (MALDONADO et al.,
2004).
Para que o grafo seja gerado, deve-se abstrair os nos e arestas a partir do codigo-fonte
do programa. Cada no do grafo, identificado na Figura-2.1 por um n
umero, representa
um bloco indivisvel de comandos. Segundo Maldonado et al. (2004), cada bloco tem as
seguintes caractersticas: uma vez que o primeiro comando do bloco e executado, todos

2.1 Tecnicas de Teste de Software

19

os demais sao executados sequencialmente e nao existe desvio de execucao para nenhum
comando dentro do bloco.
Assim, um desvio na execucao seq
uencial do codigo originada atraves de um comando if ou while, por exemplo acarretaria na criacao de um novo no no grafo. As
arestas, representadas por uma seta, indicam o fluxo entre os nos. Pode-se observar na
Figura 2.1 que, partindo do no 1, o fluxo pode tomar dois caminhos possveis: a aresta do
no 1 ao no 3 ou a aresta do no 1 ao no 2. Tal fato explica-se pela presenca do comando
if no codigo.

Figura 2.1: Grafo de Fluxo de Controle


Ntafos (1988) sustenta que a tecnica de teste estrutural e provavelmente a mais usada,
devido principalmente `a simplicidade de aplicacao. Alem disso, a maioria dos testes
estruturais nao fornece orientacoes para a selecao de dados de teste num certo sub-domnio
de caminhos de execucao, e alguns erros so serao descobertos pelo teste se o caminho e
executado com valores de um pequeno subdomnio do domnio maior. Mesmo com estes
potenciais inconvenientes, mais e mais criterios de teste estrutural tem sido desenvolvidos
e estudados, dentre eles os de Todos-Nos, Todos-Arcos e Todos-Caminhos. O criterio
de teste Todos-Nos requer que cada no do grafo seja executado pelo menos uma vez, ou
seja, que cada comando do programa seja executado uma vez pelo menos. O criterio
Todos-Arcos requer que cada aresta do grafo, ou seja, cada desvio de fluxo de controle
do programa, seja exercitado pelo menos uma vez. O criterio de teste Todos-Caminhos

2.1 Tecnicas de Teste de Software

20

requer que todos os caminhos possveis caminho ou desvio de fluxo do programa sejam
executados (MALDONADO et al., 2004; NTAFOS, 1988; VINCENZI, 1997).
Um exemplo demonstra de forma simplificada o uso destes criterios: considerando um
programa como o da Figura 2.1 e considerando o criterio Todos-Nos, supondo que (i) a
condicao de execucao do comando if (no 1) seja verdadeira (ou seja, a variavel escolha
seja verdadeira), (ii) a condicao de execucao do comando while (no 2) seja verdadeira (ou
seja, nao esteja configurado o final de arquivo de table) e (iii) a condicao de execucao do
comando if no no 5 seja verdadeira (ou seja, a variavel tablestatus contenha o valor
falso), serao entao exercitados os nos (1,2,5,6,7,2,8).
No entanto, se for criado outro caso de teste em que a variavel escolha seja definida como falsa, serao exercitados os nos (1,3,8). Nesta situacao, ja esta satisfeito o
criterio Todos-Nos, mas nao os criterios Todos-Caminhos e Todos-Arcos. Erros podem
ser encontrados mais facilmente com o criterio de Todos-Caminhos, mas este criterio exige
muito esforco. Caso fosse possvel utiliza-lo, seriam exercitados todos os criterios, ou seja,
executando o criterio Todos-Caminhos, automaticamente seriam exercitados Todos-Nos e
Todos-Arcos.
Por volta da decada de 1970, surgiram os criterios baseados em analise de fluxo de
dados (HERMAN, 1976), que utilizam informacoes do fluxo de dados para derivar os
requisitos de teste. Na Figura 2.2 e ilustrada este tipo de criterio. Rapps e Weyuker
(1982) propuseram o Grafo Def-uso que consiste em uma extensao do grafo de programa.
Neste grafo, sao exploradas as associacoes entre a definicao e o uso das variaveis determinando os caminhos a serem exercitados. Quando a variavel e usada em uma computacao, diz-se que seu uso e computacional (c-uso); quando usada em uma condicao,
seu uso e predicativo (p-uso). Alguns criterios desta classe sao: Todas-Definicoes (alldefs), Todos-Usos (all-uses), Todos-Du-Caminhos (all-du-paths), Todos-P-Usos (all-puses), Todos-P-Usos/Alguns-C-Usos (all-p-uses/some-c-uses) e Todos-C-Usos/Alguns-PUsos (all-c-uses/some-p-uses) (VINCENZI, 1997).
Por exemplo, para exercitar a variavel z definida no no 4 (Figura 2.2), de acordo
com o criterio Todas-Definicoes, poderiam ser executados um dos seguintes subcaminhos:
(4,5,6); (4,5,7,8); e (4,5,7,9).
O teste estrutural e, em geral, aplicado a unidades de programa relativamente pequenas, como sub-rotina, ou `as operacoes associadas com um objeto. Como o nome sugere, o
testador pode analisar o codigo e utilizar conhecimentos sobre a estrutura de um componente, a fim de escolher os dados para teste. A analise do codigo pode ser utilizada para

2.2 Fases da Atividade de Teste

21

Figura 2.2: Grafo de fluxo de controle


levantar os casos de teste e tambem para descobrir quantos casos de teste sao necessarios
para cobrir todas as definicoes e uso no programa, para que os mesmos sejam executados
pelo menos uma vez durante o processo de teste (SOMMERVILLE, 2003).

2.2

Fases da Atividade de Teste

Segundo Pressman (2001), a estrategia convencional de teste prima pela realizacao


de teste de forma incremental, ou seja, inicia-se pelo teste de unidade, em seguida o de
integracao e finalmente o teste do sistema como um todo. A menor unidade de teste
e o sub-programa (modulo, procedimento ou componente) e, via de regra, tais partes
do programa sao testadas em primeiro lugar e individualmente. Em seguida, elas sao
integradas e testes de integracao sao executados, para que, no final, o sistema todo seja
testado.

2.2.1

Teste de Unidade

O teste de unidade concentra-se na verificacao da menor unidade de projeto de software: metodo ou classe. Usando a descricao do projeto como guia, caminhos de controle
importantes sao testados para descobrir erros dentro das fronteiras do modulo. No caso

2.2 Fases da Atividade de Teste

22

de programas orientados a objeto, uma classe pode conter varias operacoes diferentes, e
uma operacao pode existir como parte de varias classes diferentes. O significado de teste
de unidade muda e nao se pode mais testar uma u
nica operacao isoladamente, como no
teste de unidade convencional (PRESSMAN, 2001).
Alguns autores entendem que a classe e a menor unidade no contexto de software
orientado a Objeto (MCGREGOR; SYKES, 2001), sendo que o teste de unidade poderia
envolver o teste intra-metodo, inter-metodo e intra-classe e o teste de integracao que
corresponde ao teste inter-classe. Na Tabela 2.1, sao listados os tipos de teste de software
OO que podem ser aplicados.
Tabela 2.1: Relacao entre Menor Metodo
Menor Unidade: M
etodo
Unidade
Intra-metodo
Intregracao Inter-metodo, Intra-classe e Inter-classe
Sistema
Toda aplicacao
Menor Unidade: Classe
Unidade
Intra-metodo, Inter-metodo e Intra-classe
Integracao
Inter-classe
Sistema
Toda aplicacao

Mcgregor e Sykes (2001) afirmam que os modulos ou classes sao geralmente testados
atraves da criacao de um driver 1 de teste que cria instancias da classe e tambem um
ambiente apropriado para tais instancias. O driver envia uma ou mais mensagens para
uma instancia, conforme especificado pelo caso de teste. Em seguida, checa o resultado
daquelas mensagens baseado num valor de resposta, altera a instancia e um ou mais
parametros da mensagem. O driver de teste geralmente executa a exclusao de quaisquer
instancias que tenha criado se a linguagem, tal como o C++, possui alocacao de memoria
gerenciada pelo programador. Um stub e a unidade que substitui, na hora do teste, uma
outra unidade chamada pela unidade que esta sendo testada. Em geral, um stub simula
o comportamento da unidade chamada.

2.2.2

Teste de Integrac
ao

O teste de integracao e uma tecnica sistematica para a construcao da estrutura do


programa, realizando-se, ao mesmo tempo, teste para descobrir erros associados nas interacoes das unidades. O objetivo e, a partir dos modulos testados no nvel de unidade,
1

Um driver e geralmente um trecho de codigo usado para fornecer valores de entrada a uma classe ou
modulos a serem testados.

2.3 Ferramentas de Teste Estrutural

23

construir a estrutura do programa que foi determinada pelo projeto. Existem dois tipos
de integracao: a nao-incremental e a incremental. Na integracao nao incremental, todos
os modulos sao combinados antecipadamente e o programa e testado como um todo. Na
integracao incremental, o programa e construdo e testado em pequenos segmentos, nos
quais os erros sao mais faceis de serem corrigidos.
As tecnicas de projeto de casos de teste funcional sao as mais utilizadas durante esta
fase. No entanto, iniciativas de utilizacao de criterios usados no teste de unidade para
o teste de integracao sao encontradas na literatura, tais como a extensao de criterios
baseados em fluxo de dados e criterios baseados na analise de mutantes (DELAMARO,
1997; PRESSMAN, 2001).
Existem tambem diferencas na abordagem de teste de integracao entre programas
convencionais e orientados a objeto. A integracao no paradigma de orientacao a objeto
pode ser vista como a interacao entre os objetos em um programa. Tal teste torna-se
indispensavel ao se levar em conta que uma instancia de uma classe pode nao conter
falhas, mas se os servicos daquela instancia nao forem usados corretamente pelos outros
componentes do programa entao este contem falha(s). Desta forma, a correta interacao
ou colaboracao dos objetos em um programa, e crtica para a forma correta do programa
(MCGREGOR; SYKES, 2001).

2.2.3

Teste de Sistema

Depois do teste de unidade e integracao, o software foi integrado, o sistema funciona


como um todo, sao realizados os testes de sistema. O objetivo e assegurar que o software
e os demais elementos que compoem o sistema, tais como, hardware e banco de dados,
combinem-se adequadamente e que o desempenho geral desejado seja obtido.

2.3

Ferramentas de Teste Estrutural

O objetivo de ferramentas de teste e sempre voltado para custo e mao-de-obra. Com


ferramentas de teste e possvel apoiar-se em criterios e precisao, tornando muito mais
baixo o custo do teste e mais rapido.
A disponibilidade de ferramentas de teste permite uma evolucao de tecnologia para
as ind
ustrias, fator indispensavel para a producao de software de alta qualidade. Tais
ferramentas auxiliam pesquisadores e alunos de Engenharia de Software a adquirir os

2.3 Ferramentas de Teste Estrutural

24

conceitos basicos e experiencia na comparacao, selecao e estabelecimento de estrategias


de teste (PRESSMAN, 2001).
Varias ferramentas foram desenvolvidas para esta finalidade: a Ferramenta POKETOOL (MALDONADO; CHAIM; JINO, 1991) que apoia a aplicacao dos criterios PotenciaisUsos e tambem de outros criterios estruturais como Todos-Nos e Todos-Arcos; a ferramenta Discover que apoia o teste estrutural de unidade para a Linguagem Delphi; a Ferramenta Jabuti (VINCENZI et al., 2003) que trabalha com Java bytecode em teste estrutural
tambem; a ferramenta Proteum (DELAMARO, 1993) que apoia o teste de mutacao para
programas C, e outras. A seguir serao apresentadas algumas ferramentas de suporte ao
teste estrutural.

2.3.1

Ferramenta POKE-TOOL

O objetivo inicial da Ferramenta POKE-TOOL (POtencial uses criteria TOOL for


program testing) foi testar software trabalhando com o criterio Potencial-Uso(PU) (MALDONADO, 1991). Este crit
erio requer basicamente que para todo no i e para toda variavel

x, para a qual existe uma definicao em i, que pelo menos um caminho livre de definicao
com relacao `a variavel x do no i para todo no e para todo arco possvel de ser alcancado
a partir de i por um caminho livre de definicao de x seja exercitado. (MALDONADO et
al., 2004). A ferramenta cont
em dois outros criterios tambem: Todos-Nos e Todos-Arcos.

Na Figura 2.3 e mostrada a tela principal da ferramenta e as opcoes disponveis.


Maldonado, Chaim e Jino (1991) criaram esta ferramenta motivados neste criterio,
sendo ela desenvolvida com o recurso multi-linguagem, podendo ser adaptada para quaisquer linguagens.
A Ferramenta POKE-TOOL e orientada `a sessao de trabalho, e e utilizada para as
atividades envolvendo um teste. O teste pode ser realizado em etapas, permitindo ao
usuario encerrar o teste de um programa, bem como retoma-lo a partir de onde este
foi interrompido. Basicamente, o usuario entra com o programa a ser testado, com o
conjunto de casos de teste e seleciona todos ou alguns dos criterios disponveis (Figura
2.4). Como sada, a ferramenta fornece ao usuario o conjunto de arcos, o Grafo Def obtido
do programa em teste, o programa instrumentado para teste, o conjunto de associacoes
necessarias para satisfazer o criterio selecionado e o conjunto de associacoes ainda nao
exercitadas. O conjunto de arcos primitivos consiste de arcos que uma vez executados
garantem a execucao de todos os demais arcos do grafo de programa (MALDONADO;
CHAIM; JINO, 1991; MALDONADO et al., 2004).

2.3 Ferramentas de Teste Estrutural

25

Figura 2.3: Opcoes disponveis na ferramenta POKE-TOOL


Na Figura 2.4 e mostrada a criacao de uma sessao de teste de um programa utilizando
todos os criterios disponveis.

Figura 2.4: Tela para criar uma sessao de teste na POKE-TOOL


Com os relatorios gerados pela POKE-TOOL, o testador podera avaliar de forma mais
abrangente o andamento da atividade de teste, em diferentes aspectos, dependendo dos
criterios desejados.

2.3 Ferramentas de Teste Estrutural

2.3.2

26

Ferramenta JaBUTi

A Ferramenta JaBUTi (Java Bytecode Understanding Testing) visa a ser um ambiente completo para o entendimento e teste de programas e componentes Java. JaBUTi
fornece ao testador diferentes criterios de testes estruturais para a analise de cobertura.
A JaBUTi implementa atualmente criterios de teste intra-metodos sendo quatro de
fluxo de controle (Todos-Nos-ei, Todos-Nos-ed, Todas-Arestas-ei, Todas-Arestas-ed), e
quatro criterios de fluxo de dados (Todos-Usos-ei, Todos-Usos-ed, Todos-Pot-Uso-ei, TodosPot-Uso-ed). Observe que os pares Todos-Nos-ei, Todos-Nos-ed, Todas-Arestas-ei e TodasArestas-ed compoem os criterios Todos-Nos e Todos-Arcos, respectivamente; da mesma
forma ocorre com os Todos-Usos-ei e Todos-Usos-ed que compoem o criterio Todos-Usos,
a diferenca entre os criterios com ei e ed, e independente de excecao e dependente de
excecao respectivamente. A JaBUTi realiza a analise de cobertura instrumentando um
arquivo .class; apos isso, ela coleta informacoes de cobertura durante a execucao do programa e determina se cada um dos metodos de todas as classes foram testados de acordo
com os criterios de teste disponveis (VINCENZI et al., 2003).
Uma das caractersticas do software JaBUTi e a facil visualizacao de blocos de codigos
que sao marcados com um peso, que facilitam a geracao de casos de teste, de modo a
maximizar a cobertura em relacao aos criterios de teste. Estes blocos mostram de forma
inteligente qual o requisito de teste que, se coberto, aumentaria de forma consideravel a
cobertura em relacao ao criterio considerado, como mostrado na Figura 2.5.
A Ferramenta JaBUTi permite que os requisitos de teste de cada um de seus criterios
possam ser visualizados no bytecode, codigo fonte e no grafo de cada metodo de cada uma
das classes em teste. Sao associadas diferentes cores para indicar seus pesos. Podem ser
vistas nas Figuras 2.5 , 2.6 e 2.7 cada uma destas representacoes.
Um exemplo, na Figura 2.7, mostra a cobertura de um determinado programa, em
que a parte coberta indica o valor do peso como 0. Deste modo o testador e auxiliado,
sabendo que executou um caso de teste e que, de certa forma, executou aqueles blocos de
comando.
Pode ser importante avaliar a cobertura de todo projeto em relacao a cada um dos
criterios de teste. Esta informacao pode ajudar o testador a decidir se cada criterio ja
atingiu seu objetivo. Caso tenha atingido, um criterio de teste mais forte pode ser utilizado para continuar a evolucao do conjunto de teste, por exemplo, passar do criterio
Todos-Nos, para o criterio Todas-Arestas. A ferramenta JaBUTi gera este tipo de re-

2.3 Ferramentas de Teste Estrutural

27

Figura 2.5: Exemplo da tela JaBUTi, visualizacao pelo codigo-fonte

Figura 2.6: Grafo gerado pela JaBUTi no criterios Todos-Arcos-ei


latorio considerando os oitos criterios de testes estruturais implementados : Todos-Nos-ei,
Todas-Aresta-ei, Todos-Usos-ei, Todos-Nos-ed, Todas-Arestas-ed, Todos-Usos-ed, TodosPot-Uso-ei e Todos-Pot-Uso-ed. As Figuras 2.8, 2.9, 2.10 ilustram esse tipo de relatorio

2.3 Ferramentas de Teste Estrutural

28

Figura 2.7: JaBUTi - codigo bytecode


(VINCENZI et al., 2003).

Figura 2.8: JaBUTi - Sumario de cobertura por criterio

Figura 2.9: JaBUTi - Cobertura da classe por criterio


A JaBUTi pode tambem gerar relatorios mais completos como por exemplo, exportar

2.3 Ferramentas de Teste Estrutural

29

Figura 2.10: JaBUTi - Cobertura por metodos


relatorios para html com todos os dados de cobertura. Gerar informacoes de cobertura de
cada criterio, e em cada caso de teste individualmente. Tambem e gerado neste mesmo
relatorio, para cada criterio, todos que foram cobertos e todos que nao foram cobertos
ainda.

2.3.3

Ferramenta Discover

A Discover e uma ferramenta que permite testar programas desenvolvidos na linguagem de programacao Delphi. Usando uma interface grafica, ela auxilia o testador de forma
pratica na cobertura do codigo. A Discover trabalha com teste de unidades somente para
plataforma Windows.(CYAMON SOFTWARE, 2005)
Ao contrario das outras ferramentas apresentadas neste trabalho, a Discover somente
trabalha com o Delphi, ou melhor, nao ha uma forma de introduzir outra linguagem nesta
ferramenta. Nao possui tambem um metodo que gere um grafo de controle ou de fluxo
de dados. Ela apenas auxilia o testador diretamente pelo codigo-fonte, mostrando os

codigos que foram testados atraves dos smbolos e . A ferramenta baseia-se somente
no criterio Todos-Nos e no teste estrutural (caixa branca) (CYAMON SOFTWARE, 2005).
De acordo com a Figura 2.11, a Discover marca os trechos de codigo cobertos com o

smbolo
e, os nao cobertos, com o smbolo . Do lado esquerdo da Figura 2.11 ficam
as unidades do programa em teste. Do lado direito, situa-se o codigo-fonte de uma das
unidades escolhidas para a analise de cobertura. A ferramenta disponibiliza relatorios que
mostram todas as unidades e suas respectivas coberturas, tamanho, n
umero de rotinas,
alem de quantidades de rotinas com 0% e 100% de cobertura.
Para que a Discover possa fazer o teste de um programa, primeiro o Map file do Delphi

2.3 Ferramentas de Teste Estrutural

30

Figura 2.11: Tela de execucao de teste na Ferramenta Discover


deve ser gerado durante a compilacao do programa a ser testado. Este Map file gera um
arquivo que armazena uma lista de segmentos, enderecos de inicializacao do programa,
avisos ou erros produzidos durante a compilacao do codigo executavel e uma lista de
smbolos p
ublicos ordenada alfabeticamente, incluindo o endereco, tamanho em bytes,
nome, grupo do segmento e a informacao do modulo do programa. Para isso, e necessario
configurar algumas opcoes no Delphi a partir do menu project, Options; na pasta linker,
marcar a opcao Detailed, conforme a Figura 2.12.

Figura 2.12: Pasta Linker do Delphi

2.4 Consideraco
es Finais

2.4

31

Considerac
oes Finais

Neste captulo foi dada uma visao geral a respeito da atividade de teste e sua importancia no processo de desenvolvimento de software. Alem disso, foi fornecida uma
descricao de diversas fases das principais tecnicas e criterios de teste de software. Foram tambem apresentados exemplos das ferramentas POKE-TOLL, JaBUTi e Discover,
descrevendo suas funcionalidades e aplicacoes no teste de software.
No proximo captulo, sera abordada a confeccao da gramatica de uma linguagem
de programacao, mostrara tambem as adaptacoes necessarias para ser utilizadas pelas
ferramentas Lex e Yacc no proposito de gerar um analisador sintatico.

32

Geradores de Compiladores

Este captulo aborda o conceito de gramaticas visando a geracao de compiladores. Sera


exemplificado o funcionamento da gramatica BNF (Backus-Naur Form) e consideracoes
sobre o funcionamento das ferramentas Yacc (Yet Another Compiler-Compiler ) e Lex (A
Lexical Analyzer Generator ).
A gramatica de uma linguagem de programacao serve para determinar regras sintaticas
e semanticas para a mesma, de forma que esta linguagem de programacao seja escrita
apoiada nesta gramatica.

3.1

Principais Caractersticas de uma Gram


atica

As gramaticas sintaticas sao dispositivos finitos que sao usados freq


uentemente para
descrever linguagens infinitas. Quase todas as linguagens de programacao sao caracterizadas por uma gramatica. Certamente, a gramatica e parte da definicao da linguagem.
As gramaticas podem ser classificadas baseadas no tipo de producoes que possuem. Uma
importante classe e a gramatica livre de contexto. Sao simples, mas bastante utilizadas
pela maioria das linguagens de programacao. Alem disso, os algoritmos para reconhece-las
sao computacionalmente trataveis (SIMAO et al., 2001).
Uma arvore sintatica representa a estrutura de um programa. Um instrumentador
pode usar esta estrutura para derivar o grafo de um programa. Na Figura 3.2 e mostrado
um exemplo de arvore sintatica de um pequeno programa ilustrado na Figura 3.1, que e
definida por uma gramatica BNF abaixo:
hSi hW i
hSi hIF i
hSi break ;
hSi hIDi = hEi ;

3.1 Principais Caractersticas de uma Gram


atica

hW i while ( hEi ) hSi


hIF i if ( hEi ) hSi else hSi
hEi hIDi >= hCi
hEi hIDi + hIDi
hEi hIDi ( hEi )
hEi hEi , hEi
hIDi identifier
hCi integer
Gramatica BNF usada para escrever o programa da Figura 3.1
WHILE (A >= 1)
IF (B >= 0)
BREAK;
ELSE
A = A - B;
Figura 3.1: Programa exemplo while

Figura 3.2: Arvore


sintatica while

33

3.1 Principais Caractersticas de uma Gram


atica

34

Aho, Sethi e Ullman (1986) afirmam que muitas construcoes de linguagens de programacao possuem uma estrutura inerentemente recursiva que pode ser identificada por
gramatica livre de contexto. Por exemplo, poder-se-ia ter um enunciado condicional definido por uma regra tal como:
se S1 e S2 sao enunciados e E e uma expressao, entao
if E then S1 else S2 e um enunciado.
A Backus-Naur Form (BNF) foi criada (em meados da decada de 1950) em um esforco
conjunto de John Backus e Noam Chomsky. A BNF e o metodo mais popular para
descrever concisamente a sintaxe de uma linguagem de programacao.
As ferramentas usadas neste trabalho adotaram o uso da gramatica BNF que e uma
metalinguagem1 que representa a gramatica livre de contexto. A nova notacao foi ligeiramente alterada um pouco mais tarde para se descrever a linguagem ALGOL-60 por Peter
Naur. Este metodo revisado para descricao de sintaxe passou a ser conhecido como Forma
Backus-Naur ou, simplesmente, BNF (Backus-Naur Form). Este tipo de gramatica simplificadamente consiste em terminais, nao-terminais, um smbolo de partida e producoes.
Uma gramatica BNF e composta por um conjunto finito de regras que definem uma
linguagem de programacao. Alem disso, BNF usa abstracoes para representar estruturas
sintaticas. As abstracoes na descricao BNF sao freq
uentemente chamadas de smbolos naoterminais, ou simplesmente nao-terminais. A representacao para os nomes das abstracoes
(nao-terminais) em BNF e um nome cercado pelos smbolos de menor e maior < e > . Os
itens lexicos da linguagem, tambem conhecidos como lexemas ou tokens, sao representados
por nomes em negrito. Os itens lexicos sao freq
uentemente chamados de terminais. Os
terminais sao smbolos basicos a partir dos quais as cadeias sao formadas. A palavra
token sera um sinonimo de terminal. No contexto de linguagem de programacao,
cada uma das palavras chaves if, then, else e begin e um terminal, e todas as palavras
que sao reservadas da linguagem de programacao como operadores logicos, aritmeticos
entre outros.
Os nao-terminais sao variaveis sintaticas que denotam cadeias de caracteres. Os naoterminais definem conjuntos de cadeias que auxiliam a definicao da linguagem gerada pela
gramatica e tambem impoem uma estrutura hierarquica na linguagem que e u
til tanto
para a analise sintatica quanto para a traducao.
1

Uma metalinguagem e uma linguagem que e usada para descrever uma outra linguagem. BNF e uma
metalinguagem para linguagens de programacao

3.1 Principais Caractersticas de uma Gram


atica

35

Uma regra BNF tem sempre um nao-terminal em seu lado esquerdo, e composto por
terminais e/ou nao terminais em seu lado direito. O smbolo ::= e usado com o sentido
de e definido por e une o lado esquerdo ao direito da regra. O smbolo | e usado com o
significado de ou e e usado para nao se precisar escrever o lado esquerdo repetidas vezes.
Na Figura 3.3 e exemplificada esta gramatica e na Figura 3.4 e mostrado um exemplo de
sua producao (AHO; SETHI; ULLMAN, 1986).

Figura 3.3: Exemplo da gramatica BNF


Como se pode observar na Figura 3.3, os nao-terminais da gramatica BNF sao 5
(programa, lista-sentencas, sentenca, variavel e expressao). Os terminais sao 11 (begin, end, ; , :=
, A, B, C, D, E, +e). Um programa valido nesta linguagem e o que se encontra na Figura
3.4.
Begin
A:=B + C;
B:=B - D;
A:=B
End
Figura 3.4: Programa exemplo - gramatica BNF
A Forma de Backus-Naur (BNF) nos permite que o lado direito das producoes possua

3.1 Principais Caractersticas de uma Gram


atica

36

alguns operadores para facilitar a escrita da gramatica. Operadores estes apresentados a


seguir:
Sele
c
ao - Entre o parentese e separado por um | podem ser utilizados na producao para
optar por uma producao ou outra como mostra a Figura 3.5
exemplo hdigitoi (1|2)x esta producao resulta em:
hdigitoi 1x ou
hdigitoi 2x
Figura 3.5: Exemplo de uma producao

Opcional - Como ilustra a Figura 3.6, sao colchetes e o que estiver dentro deles possibilitam a opcao de aplicar na producao ou nao.
exemplo hdigitoi (1|2)[x] essa producao tem como valida o seguinte:
hdigitoi 1 ou
hdigitoi 2 ou
hdigitoi 1x ou
hdigitoi 2x
Figura 3.6: Exemplo de uma producao opcional

Repetic
ao de 0 ou mais vezes - O que estiver entre parentese pode ser usado com
um indicando que a producao que esta dentro do parentese pode se repetir zero
ou mais vezes, representada pela Figura 3.7.
exemplo hdigitoi (1|2) x a producao resultaria no seguinte:
hdigitoi x ou
hdigitoi 1x ou
hdigitoi 2x ou
hdigitoi 11111x ou
hdigitoi 222222x ou
hdigitoi 1212122x
Figura 3.7: Exemplo de uma producao com repeticao

Repetic
ao de 1 ou mais vezes - O que estiver entre parentese pode ser usado com
um + inidicando que a producao que esta dentro do parentese pode se repetir uma
ou mais vezes, como mostra a Figura 3.8.

3.2 Yacc e Lex

37

exemplo hdigitoi (1|2)+ x a producao resultaria no seguinte:


hdigitoi 1x ou
hdigitoi 2x ou
hdigitoi 11111x ou
hdigitoi 222222x ou
hdigitoi 1212122x
Figura 3.8: Exemplo de uma producao com repeticao

3.2

Yacc e Lex

Lex e Yacc sao ferramentas desenvolvidas para escrever compiladores e interpretadores, no entanto sao usadas para varios outros tipos de aplicacoes.
As Ferramentas IDel E IDelGen usadas neste trabalho, utilizam as ferramentas Lex e
Yacc para fazer um analisador sintatico para linguagem de programacao fornecida a ela.
Mas para que isso seja possvel ha necessidade do desenvolvimento de uma gramatica para
o analisador sintatico (Yacc) e o lexico (Lex).
Como exemplo, pode-se tomar uma gramatica de uma declaracao de variavel em C
simplificada mostrada pela Figura 3.9
<dec>::=<tipo> <var> {, <var>};
<tipo>::=[signed|unsigned] (int|char)
<var>::={*} identificador {[ numero ]}
<letra> := a|b|c|d|e|f|g|h|i|j|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z
<digito> := 0|1|2|3|4|5|6|7|8|9
<identificador> ::= <letra> { <letra>|<digito>|_ }
<numero> ::= digito { digito }
Figura 3.9: Gramatica de uma declaracao de variavel em C simplificada

Gramatica simplificada no formato BNF


Esta gramatica no formato BNF tem as seguintes caractersticas:
Smbolos terminais: signed, unsigned, int, char, [, ], , Smbolos nao-terminais:
<dec>, <tipo>, <var>, <identificador>, <numero> Smbolo inicial: <dec>. As seq
uencias
validas para ela sao, por exemplo:
int a,**b[3][4];
unsigned char *p;
signed char str[100];

3.2 Yacc e Lex

38

As Ferramentas Lex e Yacc trabalham juntas. O analisador lexico produzido pela


ferramenta Lex separa o texto de entrada em varios smbolos, tambem conhecido como
tokens e repassa para o analisador sintatico. O analisador sintatico produzido pela ferramenta Yacc consome tokens com o objetivo de construir uma frase valida segundo uma
determinada gramatica.
Para a gramatica descrita acima o arquivo lexico(3.10) ficaria assim:
01
02
03
04
05
06
07
08
09
10
11
12

DIGITO
[0-9]
LETRA
[a-zA-Z_]
%%
[signed|unsigned] (int|char) { RETURN(TIPO); }
{LETRA}({LETRA}|{DIGITO})*
{ RETURN(IDENTIFICADOR); }
{DIGITO}{DIGITO}*
{ RETURN(NUMERO); }
"*"+
{ RETURN(ASTERISCO); }
";"
{ RETURN(PONTOEVIRGULA); }
","
{ RETURN(VIRGULA); }
"["
{ RETURN(ABRECOLCHETES); }
"]"
{ RETURN(FECHACOLCHETES); }
%%
Figura 3.10: Arquivo com regras lexico

Exemplo de um arquivo lexico


O arquivo lexico, conforme citado anteriormente, tem a tarefa de reconhecer os tokens.
Em outras palavras, trata-se de um scanner que busca os padroes escritos em forma de
expressao regular. Neste arquivo, nas linhas 01 e 02, e possvel observar duas definicoes
para digito e letra, que serao usados na secoes iniciadas por "%%", que se estende da linha
04 a 10.
Na linha 4, observa-se uma expressao regular exigindo que para validar o retorno de
TIPO, seja encontrado um signed, um unsigned ou nenhum deles, mas que tenha
um int ou um char ao menos.
Na linha 05 ve-se outra expressao regular, formada por uma letra e mais uma combinacao de letras ou n
umeros. Na linha 5 tambem existe uma expressao regular que combina um n
umero ou um n
umero mais uma combinacao de n
umeros. Pode-se tomar como
exemplo a expressao {NUMERO}{NUMERO}*. O asterisco usado no segundo NUMERO
significa que pode haver mais de uma repeticao de n
umero ou nenhuma. No entanto,
tem-se o primeiro NUMERO forcando que um n
umero pelo menos seja reconhecido.

3.2 Yacc e Lex

39

O arquivo sintatico para a producao do analisador sintatico(3.11) ficaria assim:


01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

%token IDENTIFICADOR
%token NUMERO
%token ASTETISCO
%token PONTOEVIRGULA
%token VIRGULA
%token ABRECOLCHETES
%token FECHACOLCHETES
%token TIPO
%%
dec :TIPO varlist PONTOEVIRGULA
;
var : ASTERISCO var_decl
| var_decl
;
var_decl: IDENTIFICADOR
| INDETIFICADOR array_index
;
array_index : ABRECOLCHETE NUMERO FECHACOLCHETE
| array_index ABRECOLCHETE NUMERO FECHACOLCHETE
;
varlist : var
| varlist VIRGULA var
;
%%
Figura 3.11: Arquivo sintatico para a producao do analisador sintatico

Arquivo sintatico
Deve-se observar que a gramatica BNF e escrita de forma u
nica, ou seja, para que
a gramatica seja analisada sintaticamente e preciso construir um analisador lexico como
mostrado anteriormente e um analisador sintatico. Na verdade, o analisador lexico vai
servir como um scanner que busca padroes escritos em forma de expressao regular e envia
para o analisador sintatico que, por sua vez, vai formar frases e validar de acordo com os
padroes descritos no arquivo sintatico acima.
O arquivo sintatico define os tokens em letras mai
usculas e as regras em letras
min
usculas somente para facil vizualizacao, nao e regra do gerador de analisador sintatico,

3.3 Consideraco
es Finais

40

ou seja, os terminais em letra mai


uscula e os nao-terminais em min
usculas. Observa-se que
as linhas 01 a 08 servem para informar quais sao os tokens que serao usados. Nas linhas
10 a 28 estao presentes as regras da gramatica. Pode-se observar na linha 10 uma regra
chamada dec (declaracao), cuja satisfacao se da atraves de tres argumentos validos.
Um TIPO, varlist, PONTOEVIRGULA, TIPO e PONTOEVIRGULA sao
retornados direto pelo analisador lexico. O varlist e uma regra cujas caractersticas
encontram-se na Linha 25 da Figura 3.11.

3.3

Considerac
oes Finais

Neste captulo foram apresentadas tecnicas de construcoes de gramatica, que foram


utilizadas para a confeccao da gramatica da linguagem Delphi. Este captulo e importante para a compreensao da complexidade da construcao da gramatica utilizada neste
trabalho. A gramatica Delphi foi muito trabalhosa de se construir, a propria linguagem
Delphi tem uma gramatica no padrao BNF, mas nao se encontra completa, muitas pesquisas e testes foram realizado para o termino desta gramatica. Este capitulo tambem
ressalta sobre as ferramentas Yacc e Lex, que sao utilizadas para geracao do instrumentado
Delphi juntamente com a ferramenta IDeLGen. No proximo captulo serao apresentadas
detalhadamente as ferramentas IDeLGen e IDeL que seu proposito e gerar um instrumentador para uma determinada linguagem de programacao, e este trabalho utiliza estas
ferramentas para gerar um instrumentador para Linguagem Delphi.

41

IDeL e IDeLGen

Varias atividades na engenharia de software inserem-se no contexto da analise de um


programa: engenharia reversa, analise de performance, visualizacao de programas e depuracao. Instrumentacao e uma tecnica freq
uentemente usada na engenharia de software
para estes diferentes propositos.
Na atividade de teste de software, os grafos de programas sao indicados para manipulacao e analise. Para a sua analise, e freq
uente a necessidade de uma visao mais
detalhada de um programa em execucao. Pode-se querer saber, por exemplo, qual caminho foi percorrido. Para este proposito, e necessaria a insercao de comandos no codigo
do programa sem mudar a funcionalidade do mesmo, mas inserindo informacoes como log
para percorre-lo.
Um programa de teste pode usar estes logs para registrar a informacao de execucao,
ou seja, qual no, aresta, arcos, definicao e uso foram alcancados. Pode-se desejar tambem
o valor de uma variavel, no momento em que o programa executa determinado no.
Simao et al. (2001) propuseram uma instrumentacao orientada `a metalinguagem, chamada IDeL1 , projetada para suportar ambas tarefas de instrumentacao: a derivacao estrutural do produto e a inclusao de instrucoes de comando. Esta metalinguagem deve ser
instanciada fornecendo-se uma gramatica livre de contexto para uma linguagem especfica.
Para promover seu uso pratico, IDeL e tambem suportada por um sistema, conhecido
como IDelgen2 , que pode ser visto como um gerador da aplicacao feito sob medida para
processo de instrumentacao, facilitando o reuso e a evolucao da instrumentacao.
1
2

Instrumentation Description Language


Instrumentation Description Language Generator

4.1 Principais Caractersticas

4.1

42

Principais Caractersticas

A fim de projetar um mecanismo abstrato para instrumentar programas, e necessario


criar um arquivo em que as regras de instrumentacao proprias da linguagem sejam descritas. Atraves deste arquivo, o programa podera ser instrumentado para determinada
linguagem cujas regras estejam nele descritas.
Simao et al. (2001) decidiram usar as arvores sintaticas como formato intermediario.
Primeiramente, programas escritos na maioria das linguagens podem (com mais ou menos
esforco) ser traduzidos em uma arvore sintatica e as tecnicas para isso sao bem estabelecidas e bem definidas na literatura. Em segundo lugar, usando conceitos do paradigma da
programacao transformacional (exemplificado por linguagens tais como a TXL e Refine),
e possivel definir metodos para manusear a arvore sintatica (SIMAO et al., 2001).

4.1.1

Aspecto Operacional

Uma vez selecionada uma gramatica, um programa nesta gramatica e uma descricao de
instrumentacao para a mesma, podem ser gerados os grafos e instrumentacao do programa.
Para esta tarefa foi desenvolvido o IDeLgen, que tem como objetivo gerar um programa
de instrumentacao especfico de uma gramatica. Na Figura 4.1 e mostrada a execucao do
IDeLgen, onde observa-se que, para o IDeLgen gerar o programa IDel.grm, sera necessaria
uma gramatica especfica para o programa que sera instrumentado, deste ponto em diante,
o programa deve ser executado com uma descricao de instrumentacao chamado de desc e
um programa P, gerando finalmente os grafos e a instrumentacao.(SIMAO et al., 2001)
A gramatica e composta por dois arquivos, um deles contem expressoes lexicas, que
geralmente e representado com a extensao .l. O outro arquivo e descrito por uma
gramatica livre de contexto para analise sintatica. Ela e representada pela extensao .y,
como se pode ver na Figura 4.1. A Idel funciona da seguinte maneira: dado uma gramatica
.l e .y, a Idel produz um programa chamado IDeL.grm. Este por sua vez recebera um
codigo escrito na linguagem em questao e um esquema de como sera instrumentado, como
representado na Figura 4.1 com o nome de desc. Desta forma, quando executado, sao
gerados os grafos e o programa instrumentado.

4.1 Principais Caractersticas

43

Figura 4.1: Execucao IDeLgen

4.1.2

Estrutura do IDeL

A instrumentacao na IDeL esta dividida em tres partes principais: Unidade de identificacao, Unidade de processamento e Implementacao.
4.1.2.1

Unidade de Identifica
c
ao

A primeira etapa da instrumentacao dedica-se `a identificacao das unidades de alto


nvel no programa a ser instrumentado. O codigo e analisado e sao extradas as unidades,
que podem ser funcoes, metodos ou procedimentos, dependendo da linguagem. Na instrumentacao, as unidades sao caracterizadas por uma lista de padroes. Padroes sao como
dados para pesquisa que procuram funcoes, metodos ou procedimentos. Toda vez que um
destes padroes for encontrado, a unidade sera processada, ou seja, apos encontrado um
padrao a unidade de processamento descrita abaixo e acionada (SIMAO et al., 2001).
4.1.2.2

Unidade de Processamento

A Unidade de processamento e a parte principal de um instrumentador, ela e responsavel por definir, produzir o grafo de programa e adicionar marcas especiais `a lista de
insercao dos nos da arvore sintatica quando necessario. Estas marcas indicam que tipo

4.1 Principais Caractersticas

44

de transformacao devera ser feita na arvore sintatica, de modo a inserir pontas de provas.
A unidade de processamento e dividida dentro de uma seq
uencia de etapas de processo.
Esta consiste de uma seq
uencia de regras para instrumentacao. Por exemplo, regras que
decidirao como tratar comandos como while, if e outros.
Dependendo do tipo de instrumentacao desejada, pode ser necessario alterar o programa para monitorar sua execucao. Tal alteracao depende da estrutura do programa e
da semantica da linguagem. Na maioria das vezes, as alteracoes sao realizadas antes ou
depois de uma determinada estrutura, e estao relacionadas com um no da arvore em particular. Para isso, o instrumentador mantem em cada no da arvore uma tabela que contem
as alteracoes que devem ser feita nos componentes. Na u
ltima fase da instrumentacao
a arvore e percorrida e cada alteracao e realizada baseada nas informacoes presentes na
tabela de implementacao de cada um dos nos.
Simao et al. (2001) criaram regras no programa IDeL que e composto de sete secoes:
definicao de nome, declaracao de meta-variavel, definicao de padrao, geracao de nos,
definicao da topologia do grafo, atribuicao e insercoes de marcas.
Estas regras servem para determinar como sera gerado um grafo e instrumentado o
codigo fonte da linguagem de programacao fornecida. Elas estao contidas no arquivo desc
(Figura 4.1) usado pela IDeL. Este arquivo pode ser alterado para que haja compatibilidade `as varias linguagens de programacao existentes.

Figura 4.2: Regra de instrumentacao do comando while


Pode-se ter uma ideia destas regras de acordo com a regra de instrumentacao mostrada
pela Figura 4.2. Para se entender melhor como funcionam estas regras de instrumentacao,
observa-se na linha 1, que e uma definicao do nome, que neste caso, define o nome da regra

4.1 Principais Caractersticas

45

como While. Isto tem somente a finalidade de documentar, e nao tem nenhum impacto
sobre a semantica da regra. A linha 2 ate a 4 e a secao da declaracao de meta-variaveis.
As linhas 5 e 6 fazem parte da secao da definicao de padrao, a que as sub-arvores
da arvore sintatica devem combinar para que esta regra de instrumentacao seja aplicada,
conforme as meta-variaveis. Neste padrao, as meta-variaveis :e e :s sao unificadas a expressao de controle e ao corpo do while respectivamente. A linha 7 e a secao de declaracao
do no. Neste exemplo, ela (a tarefa) cria um novo no, adiciona-o ao grafo e atribui ao
nome simbolico $control no mapeamento de no do grafo correspondente `a sub-arvore
que combina com o padrao.
Para entender como (e porque) a instrumentacao funciona, e necessario primeiro explicar algumas coisas que sao assumidas neste padrao (ou modelo). Todo comando tem
dois nomes simbolicos: $begin e $end. Estes sao, respectivamente, os nos logo antes e
logo depois do comando. Na verdade, estes nomes simbolicos assumidos sao fornecidos
por passos de processamento anteriores, responsaveis por criar e atribuir valor a eles.
As linhas 8 a 12 referem-se `a secao da definicao da topologia do grafo, na qual declaram
as arestas no grafo. Neste exemplo, a linha 9 cria a aresta que liga o no atribudo a $begin
ao o no do grafo atribudo a $control. A linha 10 cria a aresta que liga o no atribudo a
$control ao no atribudo a $begin na sub-arvore unificada para a meta-variavel :s.
A linha 14 atribui o nome simbolico $break:s ao no do grafo $end, isto significa que
quando o instrumentador esta analisando os comandos na sub-arvore :s, uma referencia
ao no break sera direcionada ao no apos o while. Esta forma e utilizada no comando
break na linguagem C.
A linha 16 atribui o nome simbolico $puse:e ao no do grafo atribudo a $control.
As linhas 17 a 20 sao a secao da atribuicao e insercoes de logs. Nesta secao, a regra da
instrumentacao adiciona marcas especiais (comandos log) `as listas da insercao, a fim de
apontar onde as indicacoes do registro devem ser inseridas (SIMAO et al., 2001).
A Figura 4.3 ilustra como a regra while funciona. Os nomes simbolicos $begin,
$begin:s, $end:s e $end sao atribudos aos nos apropriados antes de aplicar esta regra.
O no e as arestas que foram criadas por esta regra sao destacados com linhas tracejadas,
e os novos nomes simbolicos estao em italico (SIMAO et al., 2001).

4.2 Execuca
o e Exemplos

46

Figura 4.3: Grafo de como funciona a regra while


4.1.2.3

Implementa
c
ao

Na unidade de processamento, as declaracoes instrument sao abstratas. A instrumentacao pode variar de linguagem para linguagem. A implementacao da uma sintaxe
concreta para a declaracao instrument e define na unidade de processamento como aplicar
entao a linguagem em questao. Nesta secao, e definido como o programa deve ser mudado
a fim de introduzir os comandos (SIMAO et al., 2001).

4.2

Execuc
ao e Exemplos

A instrumentacao de um programa na IDeL pode ser realizada em uma linguagem


qualquer, desde que uma gramatica livre de contexto e uma descricao de instrumentacao
estejam de acordo com esta linguagem. Esta descricao de instrumentacao sao regras
criadas para que se gere a instrumentacao e o grafo de acordo com a flexibilidade de cada
linguagem.

4.2 Execuca
o e Exemplos

4.2.1

47

Exemplos

O comando abaixo gera o aplicativo (instrumentador) com o nome de idel.C, recebe o


parametro C e espera encontrar os dois arquivos C.l e C.y como foi exemplificado
na Secao 4.1.1.
comando: idelgen C
Dado um programa P, que e uma simples calculadora de peso ideal mostrado na
Figura 4.4, pode-se executar na IDeL, usando o seguinte comando:
comando: ./IDeL.C -p <Programa> -i IDeL.grm -g <Nome do Programa>
-o <Nome do arquivo instrumentada>
O comando IDeL.C , na linha acima, e o aplicativo que foi gerado pelo IDeLgen
(instrumentador) com as devidas gramaticas que, por sua vez, ira receber os parametros
para a instrumentacao. A opcao -i aponta a descricao IDeL do instrumentador. A opcao
-p serve para indicar qual sera o arquivo a ser instrumentado. A opcao -g define o nome
base que sera utilizado para gerar os arquivos do tipo DOT posteriormente utilizado
pela Ferramenta Graphiz3 para gerar as figuras dos grafos e a opcao -o informa o arquivo
final instrumentado. O arquivo IDeL.grm acima sao as descricoes para gerar os grafos
(Secao 4.1.2.2). Logo abaixo e mostrado um exemplo com o programa programateste.C.
exemplo: ./IDeL.C -p programateste.C -i IDeL.grm -g programateste
-o programateste_instrumentado.C
Na verdade, a execucao e bastante simples. Passando como argumento o nome dos dois
arquivos, o instrumentador realiza a tarefa. Sao gerados dois arquivos: o programatesteinstrumentado.C e o programateste.main.dot. O arquivo programa-instrumentado.C (Figura 4.5) e o programa instrumentado, o arquivo.main.dot (Figura 4.6) e o grafo. Conforme mostra a Figura 4.5, pode-se observar as pontas de prova de intrumentacao indicadas
pelas flechas. A ferramenta IDeL gera um grafo em modo texto (Figura 4.6) que e usado
na Ferramenta Graphvizpara producao de um grafo em forma de figura. O grafo do
programa representado pela Figura 4.6 e passado para a Ferramenta Graphviz que produz
um grafo mostrado pela Figura 4.7.
3

Graph Visualization Software - e uma ferramenta que faz o layout e renderiza um grafo fornecido no
forma de texto.

4.3 Consideraco
es Finais

48

Figura 4.4: P - programateste.C

Figura 4.5: Arquivo programateste-instrumentado.C

4.3

Considerac
oes Finais

Neste captulo foi dada uma visao geral a respeito das Ferramentas IDeL e IDeLgen.
Como visto, as ferramentas apresentam condicoes necessarias para gerar um instrumenta-

4.3 Consideraco
es Finais

49

Figura 4.6: Arquivo programateste.main.dot

Figura 4.7: Grafo gerado pela Ferramenta Graphviz


dor competente para qualquer tipo de linguagem de programacao, sendo possvel descrever
como sera inserido pontas de provas no codigo da linguagem em questao, pois cada linguagem de programacao tem caracteriscas diferentes. Este captulo apresenta tambem

4.3 Consideraco
es Finais

50

exemplos da funcionalidade e aplicacao das Ferramentas IDeL e IDeLGen.


No proximo captulo as Ferramentas IDel e IDeLgen serao utilizadas na geracao de
um instrumentador para linguagem de programacao Delphi, discutindo sobre a confeccao
dos artefatos necessarios na producao do instrumentador.

51

Instrumentador para a
linguagem Delphi

Conforme visto nos captulos anteriores, o principal objetivo da atividade de teste


e aumentar a confiabilidade e garantir a qualidade de um produto para que este seja
liberado com o mnimo de defeitos possvel.
Procurando reduzir o custo e o tempo associado `a atividade de teste, bem como
aumentar a sua eficacia, varias tecnicas e criterios de teste tem sido propostos. Devido ao
aspecto complementar destas tecnicas, o testador deve aplica-las em conjunto para obter
um teste de boa qualidade. O desenvolvimento de ferramentas de teste tambem contribui
para a reducao dos custos associados a esta atividade, alem de evitar que erros sejam
introduzidos pela intervencao humana durante a realizacao dos testes. Embora haja uma
variedade de programas para teste de software, surge a necessidade de uma ferramenta
para teste de software em Delphi, que hoje e largamente usada para producao de software.
Por isso, o proposito deste trabalho e produzir um mecanismo que instrumente o codigo
fonte e gere o grafo. Com o auxlio das Ferramentas IDeL e IDeLGen isso se tornou
possvel atraves da construcao de uma gramatica e uma descricao de instrumentacao
requerida para a geracao de um instrumentador.
Neste captulo sao mostradas as principais caractersticas de um instrumentador para
a Linguagem Delphi utilizando as Ferramentas IDeL e IDeLGen e apresentado tambem
caractersticas da Linguagem Delphi. Este captulo inicia com as principais caractersticas
da linguagem de programacao Delphi. Em seguinda, inicia a confeccao do instrumentador.
Para que a IDeL instrumente o programa em Delphi ha necessidade de se passar por
duas etapas:
Preparacao e construcao da gramatica do Delphi;
Adequacao da descricao de instrumentacao da Ferramenta IDeL.

5.1 Principais caractersticas da Linguagem Delphi

5.1

52

Principais caractersticas da Linguagem Delphi

Delphi e uma ferramenta predominantemente visual, embora deva-se codificar para


que o programa possa fazer o que se deseja dele.
A linguagem que esta por tras dos programas Delphi e a Object Pascal, derivada
da Linguagem Pascal, criada por Niklaus Wirth. Originalmente, ela era apenas uma
linguagem estruturada. Com o tempo a Borland criou o Turbo Pascal e, a partir da
Versao 5.5, criou extensoes orientadas a objeto.
A Linguagem Pascal nao e sensvel a caixa, isto e, nao faz diferenca entre letra
mai
uscula e min
uscula. As linhas podem ser quebradas em qualquer lugar (menos no
meio de uma cadeia de caracteres).
O Delphi permite tres tipos de comentarios:
{ a chave indica que inicia um comentario com varias linhas ate que haja outra
chave } fechando entao o comentario.
(* o abre parentese mais o asterstico e outra forma de comentar varias linhas e
termina com asterstico mais fecha parentese *).
// e um tipo de comentario que funciona somente para uma unica linha, se houver
quebra de linha ele nao satisfaz mais.
A Linguagem Pascal que e usada no Delphi e fortemente tipada, isto e, para se usar
uma variavel deve-se declara-la, determinando o tipo a ela associado. Por exemplo:
var
varint

Integer;

Esta declaracao cria uma variavel do tipo inteira.

5.1.1

Controladores de fluxo

Toda linguagem de programacao tem a necessidade de controlar o fluxo. A Linguagem


Delphi tem uma serie de comandos que faz isso. Por exemplo:
if..then..else: Este comando permite desviar o fluxo, apos a palavra chave if vem
uma expressao que, se verdadeira, executa o comando apos o then e, se for falsa, executa

5.1 Principais caractersticas da Linguagem Delphi

53

o comando apos o else. O else e opcional e, se nao for utilizado, nao executara nada de
especial caso a expressao seja falsa:
if a = 3 then
b := 5
else
c := 10
Nota-se que nao ha ; antes do else, pois a linguagem determina que haja um ; para
separar uma instrucao de outra instrucao, o comando b := 5 else c := 10 forma uma
unica instrucao. O begin e o end sao opcionais no exemplo acima, mas no exemplo abaixo
nao, o begin e o end servem para separar blocos de comando. Se nao forem utilizados
entende-se que somente um comando depois do then e um comando depois do else sejam
executados.
if a = 3 then
begin
b := 5;
c := 10
end else
begin
c := 12;
b := 4
end;
Case: Varias vezes e necessario usar seq
uencia muito grande de teste, o Delphi tem
um comando que permite substituir esta seq
uencia, quando se quer testar uma variavel
para verificar se ela e um determinado n
umero (ou tipo ordinal caracteres, enumerados,
inteiro): o case tem a estrutura semelhante `a seguinte:
case a of
1: ...;
2: ...;
3: ...;
else ...;

5.1 Principais caractersticas da Linguagem Delphi

54

For: Quando for preciso executar uma mesma acao repetidas vezes, pode-se usar um
dos comandos de repeticao disponveis no Delphi.
O for e usado quando se sabe com antecedencia o n
umero de vezes que a operacao
sera executada. Sua sintaxe e:
for i := 1 to 10 do
...
i e uma variavel definida anteriormente, que guarda um contador que mostra quantas
vezes o comando foi executado. Ele pode aumentar de valor, como mostrado acima, ou
diminuir de valor, como em:
for i := 10 downto 1 do
...
Neste caso, usa-se a palavra-chave downto para indicar o decrescimo d variavel.
While: O for permite incrementos no contador de 1 ou mais de 1, nao possibilitando
testes de condicoes mais complexas. Uma repeticao mais flexvel e o while. Sua sintaxe e:
while <condi
c~
ao> do
<condi
c~
ao> pode ser qualquer expressao boleana desejada. Por exemplo:
j := 0;
while j < 100 do begin
// executa algum procedimento
j := j+2;
end;
Repeat: A repeticao while pode nao ser executada nenhuma vez, caso a condicao
de teste nao seja satisfeita, porque o programa nem entra na repeticao. Quando se quer
obrigar a execucao do procedimento de repeticao ao menos uma vez e testar a condicao
ao final, pode-se usar o repeat:
repeat
...
until <condi
c~
ao>;

5.2 Aspectos de implementac


ao

55

Este loop e executado pelo menos uma vez e repetindo ate que a condicao seja verdadeira.

5.1.2

Excec
oes

No Delphi 1 foram introduzidas as excecoes. Quando ocorre algo que nao deveria
acontecer ou uma condicao de erro, e levantada uma excecao. O fluxo do programa se
interrompe, sendo capturado por um manipulador de excecoes, que trata o erro, exemplo:
if num = 0 then
raise exception.create(N
umero inv
alido);
num := 3000/num;
Inicialmente, testa-se a variavel num para verificar se ela e igual a 0. Se for, e levantada
uma excecao. Neste caso, a linha seguinte nao e executada.
Normalmente, as excecoes sao tratadas no manipulador padrao do delphi, que mostra
um quadro com a mensagem. Porem, ha casos em que se deseja um tratamento especial
de excecao. Quando isso e necessario, usa-se um bloco try ... except, como mostrado a
seguir:
try
if num = 0 then
raise exception.create(N
umero inv
alido);
num := 5000 / num;
except
showmessage(O Numero n~
ao pode ser 0);
end;

5.2

Aspectos de implementac
ao

Para a geracao de um instrumentador sao necessarios na IDeLGen dois arquivos.


A IDeLGen aceita a entrada de arquivos com as extensoes .l(Lex) e .y(Yacc), os dois
formam uma gramatica. Estes arquivos sao produzidos conforme as ferramentas Lex e
Yacc requerem. Na Figura 4.1 e mostrada a implantacao e execucao da IDeLGen.

5.2 Aspectos de implementac


ao

56

Na Figura 5.1 e mostrada na pratica como executar o IDeLGen e gerar um instrumentador, no comando simples da Figura 5.1 o Delphi representa os arquivos delphi.l
e delphi.y

Figura 5.1: Geracao do instrumentador idel.delphi

5.2.1

Gerac
ao do arquivo delphi.idel

A descricao do instrumentador para a Linguagem Delphi esta contida no arquivo


delphi.idel. Este arquivo e dividido em tres secoes: (i) Identificacao das unidades,
(ii) Processamentos das unidades e (iii) Implementacao. O exemplo a seguir mostra um
esquema de como o arquivo delphi.idel e estruturado.

Instrumenter <nome_do_instrumentador>
## Parte 1
unit
# Identifica
c~
ao da unidade
end unit
## Parte 2
setp <nome_do_passo>
pattern <nome_do_padrao>
# Defini
c~
ao do padr~
ao
end pattern
## Parte 3
implementation
implement
# implementa
c~
ao

5.2 Aspectos de implementac


ao

57

end implement
end instrument

5.2.1.1

Identifica
c
ao das Unidades

A unidade e uma estrutura de alto nvel que contem o codigo e a logica do programa.
Nos programas Delphi existem tres tipos de unidade: funcao, procedimento e o corpo
do programa principal. No arquivo delphi.idel encontra-se a secao da identificacao de
unidades, que visa encontrar estas construcoes da Linguagem Delphi. A partir de entao,
pode-se construir as arvores sintaticas. Para cada unidade encontrada sera gerado um
novo grafo. A unidade em questao encontrara funcoes e procedimentos e, a partir de cada
um deles, sera entao gerado um grafo.
Uma limitacao da IDeL e a nao capacidade de reconhecer varios tipos de unidades.
No caso da Linguagem C ou Java isto nao representaria problemas, pois toda a logica
do programa esta localizada dentro de funcoes e metodos, respectivamente. Para resolver
este problema, optou-se por generalizar na gramatica do Delphi funcao e procedimento,

Figura 5.2: Secao de identificacao das unidades do arquivo delphi.idel.


Na Figura 5.2 e mostrada a secao de identificacao de unidades no arquivo delphi.idel.
A palavra unit e reservada, da linha 2 a 8 sao declaradas as meta-variaveis que sao
utilizadas na linha 12. Estas metas variaveis casam com as regras gramaticais definidas na gramatica pelo arquivo delphi.y. As linhas 9 e 10 definem o nome pelo
qual a unidade vai ser identificada, que neste caso se casa com a regra da gramatica
[func_or_proc_or_method_name] que e o proprio nome da funcao ou procedimento.
As linhas 11 e 12 constituem a secao de comparacao e contem o padrao que deve ser

5.2 Aspectos de implementac


ao

58

encontrado na arvore sintatica para que uma unidade seja identificada. Esse padrao esta
de acordo com as producoes existentes na gramatica Delphi, conforme pode ser observada
na arvore sintatica de padroes na Figura 5.3, que corresponde `a producao main_impl da
gramatica. Quando esse padrao for identificado na arvore sintatica do programa, a fase
do processamento das unidades se inicia.

Figura 5.3: Arvore


de padroes da producao :head.

5.2.1.2

Processamento das Unidades

A secao de processamento das unidades e composta de zero ou mais passos iniciados


com a palavra reservada step, os nomes dos passos nao sao palavras reservadas da ferramenta. Cada passo contem uma serie de padroes que sao testados e aplicados na arvore
sintatica caso seja possvel.
Seguem os passos utilizados para o instrumentador de Delphi:
Passo FindFunction - Responsavel por encontrar uma unidade, ou seja, uma funcao
ou um procedimento;
Passo MarkStatements - Este passo tem por objetivo encontrar, dentro de cada
unidade, seus comandos;
Passo LinkStatement - Tem o proposito de determinar os nos iniciais e finais de
cada lista de comando.
Passo JoinStatement - Este passo cuida da ligacao dos nos do grafo, ele cria arestas
que liga nos de um bloco de comando ao outro.
Passo JoinToFunction - Este passo, alem de cuidar dos nos do grafo, tambem adiciona duas pontas de provas afim de identificar no codigo os n
umeros dos nos logo

5.2 Aspectos de implementac


ao

59

antes do no $init e logo depois do no $exit que sao os nos do inicio da funcao e
do fim da funcao respectivamente, e faz alteracao para a instrumentacao.
Passo MakeGraph - Este passo e responsavel pela instrumentacao e a construcao do
grafo das principais construcoes da linguagem Delphi.
A Figura 5.4 servira como exemplo para o entendimento dos passos da Ferramenta
IDeL.

Figura 5.4: Programa Exemplo.

Passo FindFunction
Assim que a unidade for identificada, o primeiro passo e o FindFunction que tem como
finalidade procurar cada funcao ou procedimento e criar dois nos o $init e $exit. A linha
1 da Figura 5.5 define o nome do passo como FindFunction. Este passo e composto
apenas pelo padrao Function, cuja declaracao e iniciada na linha 3. As linhas 4 a 10 sao
as declaracoes das meta-variaveis que sao usadas para encontrar o padrao dado pela linha
12. As linhas 13 e 14 declaram os nos $init e $exit mostrado na Figura 5.6. As linhas
15 e 16 correspondem a uma secao de atribuicao de nomes simbolicos. A atribuicao da
linha 16 serve para indicar que ocorre uma definicao dos parametros formais da funcao
no no $init, ou seja, ele esta associando o no $parameterdefinition unificado com a
meta-variavel :par, que e atribuda pela regra fp_list da gramatica do Delphi. Ela
representa os parametros de uma funcao ou procedimento da linguagem Delphi. A figura
5.7 mostra uma arvore sintatica de uma producao como ( var keys : Word ), isso tudo
e ligado ao no simbolico $init.
No caso do procedimento compararda Figura 5.4, as variaveis ae bsao associadas ao no $init a fim de marcar as atribuicoes das variaveis.

5.2 Aspectos de implementac


ao

60

Figura 5.5: Padrao FindFunction.

Figura 5.6: Grafo do Padrao FindFunction.

Figura 5.7: Arvore


sintatica fplist.
Passo MarkStatements
O proximo passo a ser aplicado na arvore e o MarkStatements (Figura 5.8). Ele e
composto pelo padrao FooStatement, declarado na linha 3. Esse padrao tem o objetivo
de encontrar todos os comandos presentes na arvore sintatica de acordo com a linha 7, e
declarar um no $begin e um no $end (linhas 8 e 9), que correspondem ao incio e ao fim

5.2 Aspectos de implementac


ao

61

do comando, respectivamente. A Figura 5.9 exemplifica a acao das linhas 8 e 9 da Figura


5.8.

Figura 5.8: Padrao MarkSatatements.

Figura 5.9: Grafo do Padrao MarkStatements.

Passo LinkStatement
Apos o passo MarkStatements, o passo LinkStatement percorre a arvore com o intuito
de determinar os nos iniciais e finais de cada lista de comandos a partir dos nos iniciais
e finais de cada comando individual. Como pode ser visto na Figura 5.10, esse passo e
composto pelos padroes Statement (linha 3) e List (linha 13).
As linhas 9,10,22 e 23 dos dois padroes ligam os nos $begin e $end com os $begin:s e
$end:s dos padroes encontrados, ou seja, este passo determina o no final e inicial de cada
lista de comandos. As linhas 19 e 20 sao responsaveis pela topologia do grafo, cria uma

5.2 Aspectos de implementac


ao

62

Figura 5.10: Padrao LinkStatementList.


aresta que parte do u
ltimo no da lista de comandos e vai ate o primeiro no do proximo
comando. Na Figura 5.11 e mostrado como e construido o grafo neste passo.

Figura 5.11: Grafo do Padrao LinkStatement.

Passo JoinStatement
O passo JoinStatement (Figura 5.12) possui apenas o padrao Join (Linha 3), que cria
duas arestas no grafo, uma partindo do no inicial do comando e chegando no no inicial da

5.2 Aspectos de implementac


ao

63

lista de comandos, e uma partindo do no final da lista de comandos e chegando no no final


do comando como mostra a Figura 5.13. Dessa forma, quando uma lista de comandos for
encontrada na arvore sintatica (Linhas 6 e 7), ela sera conectada ao grafo.

Figura 5.12: Padrao JoinStantemet.

Figura 5.13: Grafo do Passo JoinStatement.

Passo JoinToFunction
O passo JoinToFunction mostrado na Figura 5.14 utiliza apenas o padrao Function1
(Linha 3) que conecta o no inicial da unidade ($init) com o primeiro no da lista statement
($begin:ss) (Linhas 13 - 15), e tambem, o u
ltimo no da lista statement ($end:ss) com
o no final da funcao ($exit) exemplificado na Figura 5.15. A secao de instrumentacao
(Linhas 16 a 18) marca na tabela de implementacao dos nos $init e $exit que serao
realizadas duas alteracoes no codigo associado a esses nos, uma logo antes do no $init
e outra logo depois do no $exit mostrado na Figura 5.16, afim de adicionar pontas de

5.2 Aspectos de implementac


ao

64

provas para que quando executado seja possvel identificar onde e quais comandos foram
executados.

Figura 5.14: Padrao JoinToFunction.

Figura 5.15: Grafo do Passo JoinToFunction.

5.2 Aspectos de implementac


ao

65

Figura 5.16: Instrumentacao do Passo JoinToFunction.


Passo MakeGraph
O passo MakeGraph e responsavel pela instrumentacao das principais construcoes
da linguagem Delphi, como comandos de repeticao e comandos condicionais. Por ser um
passo extenso, apenas os principais padroes serao detalhados neste trabalho. Todo o passo
pode ser encontrado na ntegra no Apendice C.
Comando de Repetic
ao While
Pode-se compreender o padrao while observando a Figura 5.17. Na Linha 1, que e
uma definicao do nome, que neste caso, define o nome da regra como While. Isto tem
somente a finalidade de documentar, e nao tem nenhum impacto sobre a semantica da
regra. Da Linha 2 ate a 4 e a secao da declaracao de meta-variaveis, que sao atribudas de
acordo com a gramatica do Delphi (Apendice A). As Linhas 5 e 6 fazem parte da secao da
definicao de padrao, as sub-arvores da arvore sintatica devem combinar para que esta
regra de instrumentacao seja aplicada, conforme as meta-variaveis. Neste padrao, as metavariaveis :e e :s sao unificadas `a expressao de controle e ao corpo do while respectivamente.
A Linha 7 e a secao de declaracao do no. Neste exemplo, ele (o padrao) cria um novo
no, adiciona-o ao grafo e atribui ao nome simbolico $control no mapa de no do grafo

5.2 Aspectos de implementac


ao

66

correspondente `a sub-arvore que combina com o padrao.


Todo comando tem dois nomes simbolicos: $begin e $end criados no passo MarkStatements. Estes sao, respectivamente, os nos antes e depois do comando. As Linhas 8 a 12
fazem parte da secao graph, no qual declara as arestas no grafo. A Linha 9 cria a aresta
que liga o no $begin ao o no do grafo $control. A Linha 10, cria a aresta que liga o no
$control ao o no $begin unificada com a meta-variavel :s. A Linha 14 atribui o nome
simbolico $raise:s ao no do grafo atribudo com o nome $exit, isto significa que quando
o instrumentador esta analisando os comandos em :s, uma referencia ao no $raise e
feita ao no apos o while. Na Linha 17, atribui-se o nome simbolico $pusage:e ao no do
grafo atribudo a $control. Conseq
uentemente, toda a regra da instrumentacao aplicada
a :e pode referir a $pusage. As Linhas 17 a 20 sao a secao da atribuicao e insercoes
de pontas de provas. Nesta secao, a regra da instrumentacao adiciona pontas de provas
(comandos), a fim de indicar onde e o que foi exercitado por um determinado caso de
teste.

Figura 5.17: Padrao While.


O grafo gerado pelas Linhas 9 a 12 da Figura 5.17 e mostrado na Figura 5.18. Um no
$control e declarado na linha 7 para controlar o fluxo do comando while, ele recebera
as variaveis de definicao e de uso predicativo, as declaracoes das variaveis sao denominadas como variaveis de definicao, as variaveis que sao utilizadas para testes logicos em
linguagem de programacao sao denominadas variaveis de uso predicativo.
As linhas 19 a 22 do padrao While mostrada pela Figura 5.17 fazem alteracoes no
codigo do programa. Como mostrada na Figura 5.19, cada linha identificada na figura e
responsavel por uma modificacao, com estas modificacoes que inserem pontas de provas

5.2 Aspectos de implementac


ao

67

sera possvel apos a execucao do programa gerar um arquivo trace para verificacao do
fluxo do programa.

Figura 5.18: Grafo Padrao While.

Figura 5.19: Instrumentacao do padrao While.


A seguir sao apresentados os padroes Padr
ao Try2
Um outro padrao e o Try2 mostrado pela Figura 5.20 , nas Linhas 3 e 4 as metas
variaveis sao atribuidas como uma lista de comando. Assim quando e encontrado o padrao
da Linha 6, o grafo e modificado, devido `as Linhas 8, 9 e 10 como mostrada na Figura
5.21. Apos isso, na Linha 12 atribui o no $raise:s1 ao no $begin:s2.

5.2 Aspectos de implementac


ao

68

Figura 5.20: Padrao Try2.

Figura 5.21: Grafo Padrao Try2.


Padr
ao if-then
O padrao if-then mostrado na Figura 5.22 encontra a producao do comando if-then
pela expressao da linha 6. As variaveis :e e :s que sao as expressoes e os comandos
de cada if-then respectivamente, estao declaradas nas linhas 3 e 4. As linhas 9, 10 e 11
sao responsaveis pela construcao do grafo mostrado na Figura 5.23. As linhas 14 e 15 sao
atribuidos as definicoes das variaveis e uso predicativo junto ao no $begin. As linhas 17
a 20 fazem alteracao no codigo como mostrado na Figura 5.24.
Padr
ao if-then-else
Neste padrao, observado na Figura 5.25 as Linhas 3 a 5 atribuem as metavariaveis de
acordo com a gramatica do Delphi. A Linha 7 e responsavel pelo padrao procurado quando
percorrido na unidade. As Linhas de 9 a 12 fazem parte da construcao dos nos do grafo

5.2 Aspectos de implementac


ao

69

Figura 5.22: Padrao if-then.

Figura 5.23: Grafo Padrao if-then.


um exemplo mostra a Figura 5.26. As Linhas 19 a 23 sao instrucoes de intrumentacao
no codigo fonte do Delphi, ou seja, ela indica como inserir pontas de provas no codigo
mostrado pela Figura 5.27.
Padr
ao RepeatUntil
O padrao RepeatUntil mostrado pela Figura 5.28 encontra o comando repeat pela
producao da Linha 6. As Linhas 9 a 12 sao responsaveis pela producao do grafo mostrada
na Figura 5.29. A Linha 9 cria uma aresta que parte do no $begin ao no $begin:s, outra
aresta e criada do no $end:ss ao no $control pela Linha 10, na linha 11 uma aresta

5.2 Aspectos de implementac


ao

70

Figura 5.24: Instrumentacao do padrao If-Then .

Figura 5.25: Passo IfThenElse.


parte do no $control e chega ao no $begin:ss e por fim mais uma aresta parte do no
$control para o no $end.
Na secao instrument iniciada pela Linha 19 da Figura 5.28, sao inseridas pontas de
provas no codigo, de maneira que e possvel saber quais comandos foram executados. A
Figura 5.30(a) e revelado o codigo sem instrumentar e na Figura 5.30(b) e apresentado o
programa instrumentado.
Padr
ao ForTo
O padrao ForTo e utilizado quando o instrumentador encontra um comando for no
codigo. Esse comando e encontrado pela escrita da Linha 9 da secao match da Figura 5.31,
para a producao dessa linha foram usadas as variaveis das Linhas 3 a 7 que sao atribuidas
pelos padroes da gramatica do Delphi, na Figura 5.33 e mostrado que cada variavel recebe
como valor. As Linhas 10 a 12 declaram nos que serao utilizados na construcao do grafo

5.2 Aspectos de implementac


ao

71

Figura 5.26: Grafo Padrao if-then-else.

Figura 5.27: Instrumentacao do padrao If-Then-else .


e na instrumentacao.
As Linhas 14 a 19 ligam os nos atraves de arestas a Figura 5.32 mostra a construcao
desta secao. As Linhas 21 a 27 atribuem os valores como definicao de variaveis, uso
predicativo de variaveis e uso computacional de variaveis, afim de atender diversos tipos
de criterios de teste. Um deles e o criterio de teste Todos-Usos, tem como objetivo
que todas as associacoes entre uma definicao de variavel e seu uso predicativo e uso
computacional sejam exercitadas pelos casos de teste, atraves de pelo menos um caminho
livre de definicao, ou seja, um caminho cujo a variavel nao e redefinida.

5.2 Aspectos de implementac


ao

72

Figura 5.28: Padrao RepeatUntil.

Figura 5.29: Grafo do Padrao RepeatUntil.


As Linhas 29 a 32 integram a secao de instrumentacao. Estes comandos fazem modificacao no codigo inserindo pontas de provas, a Figura 5.33(a) e um exemplo desta
instrumentacao, apresenta cada linha desta secao, comparando com a Figura 5.33(b) e
visvel a alteracao que a secao de instrumentacao faz com o codigo.

5.2 Aspectos de implementac


ao

73

Figura 5.30: Codigo nao instrumentado (a) codigo instrumentado (b)

Figura 5.31: Padrao ForTo.

5.2.2

Sec
ao de Implementac
ao

A implementacao consiste em adicionar pontas de provas para as declaracoes instrument localizadas na secao de processamento das unidades. Essa secao e composta por

5.3 Execuca
o do Instrumentador

74

Figura 5.32: Grafo do Padrao ForTo.


uma lista de declaracoes implement que contem as acoes que devem ser tomadas para
alterar o programa.
Por exemplo, a implementacao da declaracao instrument presente na Linha 19 da
Figura 5.17 esta sendo utilizada para alterar o programa de forma que inclua um checkpoint
antes de uma lista de comandos. Isso e implementado na secao de implement, Conforme
mostrada na Figura 5.34. Esta implementacao escreve no programa instrumentado o que
e descrito na Linha 9. A meta-variavel :n representa o n
umero do no controlado pela
IDeL. O codigo alterado insere o comando writeln para escrever no arquivo TraceFile
o n
umero do no. Quando da execucao do programa instrumentado, o arquivo sera gerado
com os n
umeros dos nos criados na execucao.

5.3

Execuc
ao do Instrumentador

Como exemplo de uma instrumentacao foi usado um programa simples criado propositalmente para testar as regras descritas no arquivo delphi.idel. Na Figura 5.35 e
representado o teste da funcao exittest do arquivo funcoes.pas. Depois de gerado o
instrumentador com os arquivos delphi.l e delphi.y utiliza-se as regras descritas do

5.3 Execuca
o do Instrumentador

75

Figura 5.33: Codigo nao instrumentado (a) codigo instrumentado (b).

Figura 5.34: Implementacao do checkopoint before.


arquivo delphi.idel sobre o programa.
A execucao e bem simples, no comando utilizado para instrumentar o arquivo funcoes.pas, a opcao -p indica qual sera o arquivo a ser instrumentado. A opcao -i aponta a
descricao IDeL do instrumentador. A opcao -g define o nome base que sera utilizado nos
arquivos DOT gerados e a opcao -o informa o nome do arquivo final instrumentado, esta

5.4 Consideraco
es Finais

76

Figura 5.35: Programa exemplo funcao exittest.


execucao e exemplificada pela Figura 5.36.

Figura 5.36: Execucao da IDeL.


Como resultado, obtem-se a funcao instrumentada no arquivo funcoes.inst.pas mostrada na Figura 5.37.
O grafo da Figura 5.38 refere-se ao programa da Figura 5.35, o arquivo que e responsavel pela geracao do grafo e o da Figura 5.39

5.4

Considerac
oes Finais

Neste captulo foram apresentados os principais passos da ferramenta para instrumentacao e seus principais padroes. Estes padroes foram adicionados conforme a necessidade da Linguagem Delphi, adaptando-se `a instrumentacao existente para Linguagem C.
No entanto, existe grande diferenca na sintaxe da linguagem C para linguagem Delphi,
valido dizer que tanto
considerando que o Delphi e uma linguagem orientada a objetos. E

5.4 Consideraco
es Finais

77

function exittest ( a : integer ; b : integer ) : integer ;


var
TraceFile : TextFile ;
function check ( n : integer ) : boolean ;
begin
writeln ( TraceFile , n ) ;
check := true ;
end ;
function checkfor ( n : integer ) : integer ;
begin
writeln ( tracefile , n ) ;
checkfor := 0 ;
end ;
begin
assignfile ( tracefile , exittest.trace.tc ) ;
if fileexists ( exittest.trace.tc ) then reset ( tracefile )
else
rewrite ( tracefile ) ;
append ( tracefile ) ;
begin
try
begin
writeln ( TraceFile , 1 ) ;
begin
while check ( 2 ) and ( a >= 1 ) do
begin
writeln ( TraceFile , 3 ) ;
begin
begin
writeln ( TraceFile , 3 ) ;
begin

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

if check ( 3 ) and ( b >= 0 ) then


begin
writeln ( TraceFile , 4 ) ;
exit
end
else
begin
writeln ( TraceFile , 5 ) ;
a := a + b
end ;
writeln ( TraceFile , 5 )
end
end ;
begin
writeln ( TraceFile , 6 ) ;
begin
if check ( 6 ) and ( b > 0 ) then
begin
writeln ( TraceFile , 7 ) ;
b := b + 1
end
else
begin
writeln ( TraceFile , 8 ) ;
b := b - 1
end ;
writeln ( TraceFile , 9 )
end
end ;
exittest := 0 ;
finally
close ( TraceFile )
end
end
end ;

Figura 5.37: Funcao exittest instrumentada

Figura 5.38: Grafo da funcao exittest.


a gramatica, como a descricao da IDeL foram complexas em sua confeccao. Este captulo
e importante para o entendimento deste trabalho, porque explica como e instrumentada
a Linguagem Delphi, ou seja, como sao usados as pontas de provas que o instrumentador
insere em lugares estrategicos para o entendimento da execucao do programa. Por exemplo, para saber se a expressao do comando for foi verdadeira, e necessario adicionar
uma funcao chamada checkfor (Figura 5.33(b)), que somada com a expressao ja existente
nao causara nenhum efeito alem do que a propria expressao original causa.

5.4 Consideraco
es Finais

78

Figura 5.39: Arquivo DOT da funcao exittest.


A confeccao da descricao da IDeL foi complexa devido `a variedade de comandos que a
linguagem Delphi contem. Neste captulo foram exemplificadas algumas delas, e o arquivo
na ntegra esta no Apendice C. No proximo captulo sera apresentado um estudo de casos
com o instrumentador de Delphi nele, sao feitas algumas medicoes relevantes sobre o
tamanho do arquivo e o tempo de execucao do programa instrumentado e do programa
original sem instrumentacao.

79

Estudo de Caso

Neste captulo, sao exemplificados casos de instrumentacao para Linguagem Delphi,


comparando o tamanho do arquivo compilado instrumentado com o tamanho do arquivo
compilado nao instrumentado, tambem aborda sobre o tempo de execucao. Estes testes
foram feitos com um software cujo seu codigo em Delphi e consideravelmente grande para
a verificacao do instrumentador, entre estes casos de testes sao exemplificados o processo
de instrumentacao.

6.1

Descric
ao do Programa

Foi utilizado como estudo de caso, um software desenvolvido na linguagem de programacao Delphi, que foi tese de doutorado, defendido pela Dra. Fatima Marques, na
USP- Sao Carlos, cujo o tema e Realce de Contraste de Mamas Densas Para Deteccao
de Clusters de microcalcificacao mamaria (NUNES, 2001).
Este software possibilita a identificacao precoce de microcalcificacao mamaria em
imagens de baixo contraste, nao detectadas em processamento convencional antes do
realce de contraste.
O software usa tecnicas para realce de contraste neste programa que sao:
Filtro Butterworth
Equalizacao de histograma.
Funcao logartmica.
Funcao de potenciacao.
Filtro passa-alta.
Correcao gama.

6.2 Tamanho do Programa

80

Todas estas tecnicas sao para realce de contraste. A tecnica de filtro Butterworth que
aplicada em uma imagem como a Figura 6.1(a) resulta na Figura 6.1(b) (NUNES, 2001).

Figura 6.1: Exemplo de realce de contraste com o filtro Butterworth (NUNES, 2001)
Outra tecnica utilizada e a de equalizacao de histograma. Ela tem a finalidade de
obter um histograma uniforme, atraves do espalhamento da distribuicao dos nveis de
cinza ao longo de toda a escala de resolucao de contraste. Na Figura 6.2 e exemplificada
esta tecnica (NUNES, 2001).
A linguagem de programacao Delphi foi utilizada por Nunes (2001) em sua tese, o qual
e propositalmente utilizado neste trabalho por revelar extensos codigos de programacao.
Nas proximas secoes serao feitas algumas analises considerando-se caractersticas do
codigo instrumentado em comparacao ao programa original.

6.2

Tamanho do Programa

Programas feitos em Delphi sao divididos em unidades, cada unidade geralmente


representada por uma unit e um arquivo com extensao .pas. Uma unidade em Delphi
pode conter apenas funcoes e procedimentos para dar suporte ao desenvolvimento do
software.
A maior unidade do programa de realce de contraste de mamas densas para deteccao
de clusters de microcalcificacao mamaria e o arquivo UImagem.pas, ele contem 5388 linhas entre programacao e comentarios. Esta unidade e responsavel por quase toda a

6.2 Tamanho do Programa

81

Figura 6.2: Exemplo de equalizacao de Histograma (NUNES, 2001)


compilacao realizada pelo software. Haja vista o software instrumentado nao necessitar
de uma boa legibilidade, ou seja, o desenvolvedor nao tera que ler ou entender o codigo
instrumentado, o instrumentador gera em apenas uma u
nica linha o codigo instrumentado, impossibilitando assim a comparacao de quantidades de linhas do instrumentado
com o original.
Comparando o executavel do programa nao instrumentado que tem 1.231.360kb, ou
seja 1.2mb, com o programa instrumentado que tem 1.320.448kb ou 1.3mb, nota-se que
o programa instrumentado aumentou em 89.088kb ou seja, teve um aumento de apenas
7,2%. Estes 7,2% nao significa que o resultado de tempo de compilacao ou de execucao
sejam parecidos percentualmente.
Exemplo da execucao de instrumentacao da UImagem.pas:
giovanni@notbook:~/delphi$ ./idel.delphi -p UImagem.pas -i delphi.idel -g teste -o teste.instru.pas
Main-tg.cpp
0x40233920
0x40233920
Options::getOption() OK
processing source...
processing instrumenter...
running ...
generating teste.tfimagem.salvaimagem.dot
generating teste.tfimagem.carregaimagem.dot

6.2 Tamanho do Programa


generating teste.tfimagem.formclose.dot
generating teste.tfimagem.formpaint.dot
generating teste.tfimagem.segmentao1click.dot
generating teste.tfimagem.transfapclick.dot
generating teste.tfimagem.clusterclick.dot
generating teste.tfimagem.crescimentorclick.dot
generating teste.tfimagem.redimensionarclick.dot
generating teste.tfimagem.transformacao_ap.dot
generating teste.tfimagem.maxvalorrgb.dot
generating teste.tfimagem.minvalorrgb.dot
generating teste.tfimagem.mostrarelogioinicio.dot
generating teste.tfimagem.terminarelogio.dot
generating teste.tfimagem.clusterizacao.dot
generating teste.tfimagem.min.dot
generating teste.tfimagem.max.dot
generating teste.tfimagem.redimens.dot
generating teste.tfimagem.imagemmousedown.dot
generating teste.tfimagem.imagemmousemove.dot
generating teste.tfimagem.imagemmouseup.dot
generating teste.tfimagem.filtragemmedianaclick.dot
generating teste.tfimagem.colar1click.dot
generating teste.tfimagem.recortar1click.dot
generating teste.tfimagem.copiar1click.dot
generating teste.tfimagem.crescimento.dot
generating teste.tfimagem.iniciapaleta.dot
generating teste.tfimagem.localizacluster.dot
generating teste.tfimagem.marcacluster.dot
generating teste.tfimagem.segmenta.dot
generating teste.tfimagem.iniciaimgaux.dot
generating teste.tfimagem.aplicar_boxrim.dot
generating teste.tfimagem.thresholdglobal.dot
generating teste.tfimagem.morfologiamatematicabinaria.dot
generating teste.tfimagem.thresholdlocal.dot
generating teste.thresholdpixel.dot
generating teste.tfimagem.histograma1click.dot
generating teste.tfimagem.regiesdeinteresseclick.dot
generating teste.tfimagem.regiaointeresse.dot
generating teste.tfimagem.formclick.dot
generating teste.tfimagem.histograma2.dot
generating teste.tfimagem.realce2.dot
generating teste.tfimagem.realceparcial.dot
generating teste.tfimagem.segmenta2.dot
generating teste.tfimagem.passaalta.dot
generating teste.tfimagem.aplicar_boxrim2.dot
generating teste.tfimagem.thresholdglobal2.dot
generating teste.tfimagem.morfologiamatematicabinaria2.dot
generating teste.tfimagem.thresholdlocal2.dot
generating teste.thresholdpixel2.dot
generating teste.tfimagem.pacoteimagens.dot
generating teste.tfimagem.pacotelocal.dot
generating teste.histogramalocal.dot
generating teste.tfimagem.realcelocal.dot
generating teste.tfimagem.realceatenuacaolocal.dot
generating teste.tfimagem.juntaimagens.dot

82

6.3 Tempo de execuc


ao

83

generating teste.tfimagem.clusterizacao2.dot
generating teste.tfimagem.transformacao_ap2.dot
generating teste.tfimagem.procurareg.dot
done.

6.3

Tempo de execuc
ao

Este estudo de caso mostra a execucao do programa levando em consideracao o tempo


de execucao do programa que esta instrumentado comparado ao mesmo programa no estado original. Foram realizadas trinta execucoes de teste em cada uma das tres rotinas:
realce de contraste pela curva caracterstica, realce de contraste pelos coeficientes de atenuacao e segmentacao e realce de contraste pela modificacao do histograma e segmentacao.
Para este estudo de caso, e muito importante saber com precisao o tempo de execucao
destas rotinas. Para isso foi necessario modificar o codigo-fonte do programa para que
estas rotinas fossem executadas automaticamente. Um componente TTimer do Delphi
foi utilizado para esta tarefa, manipulando as opcoes do programa de forma identica para
cada um dos trinta casos de teste e gerando um arquivo com o tempo de execucao de cada
rotina. Na Figura 6.3 e mostrada a execucao desta rotina.
O caso n
umero 1 que processa as imagens para o realce de contraste pela curva caracterstica conforme a Tabela 6.1 foram necesarios 16,05 segundos para realcar o contraste
de 55 figuras, com o software instrumentado foi preciso 20,72 segundos para este processo,
ou seja, 4,67 segundos ou 29,09% a mais que o original.
No segundo caso, foi analisado a execucao de uma rotina do sistema um pouco mais
pesada, que e para realce de contraste pelos coeficientes de atenuacao e segmentacao
exemplificado pela tela da execucao pela Figura 6.4. Neste caso, foram necessarios, em
media, 77,96 segundos usando o programa original contra 152,12 segundos do programa
instrumentado, ou seja, um aumento de 74,16 segundos a mais nesta execucao. Na Tabela
6.1 sao apresentados estes resultados.
E no terceiro caso de teste, o realce de contraste pela modificacao do histograma e
segmentacao, e mais processado que o segundo, ele leva 89,05 segundos, ou seja 1 minuto e
29 segundos para ser realizado pelo programa original contra 155,92 segundos (2 minutos
e 36 segundos) pelo programa instrumentado, este aumento e significativo devido a sua
maior atividade de processamento. Mostrada na Figura 6.5. Na Tabela 6.3 sao mostrados
estes resultados.
Contudo, estes tres casos de testes realizados, executaram as seguintes rotinas da

6.3 Tempo de execuc


ao

84

Tabela 6.1: Tempo de execucao de Realce de Contraste pela Curva Caracterstica


N
umero
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
M
edia
Desv.Pad.

Tempo n
ao instrumentado
16,20
16,00
16,01
16,06
15,95
16,06
16,07
15,94
16,11
15,96
16,03
16,03
16,08
16,00
16,07
16,02
16,12
16,09
16,39
16,05
15,96
15,94
16,11
16,01
16,04
15,94
16,01
16,01
16,07
16,05
16,05 segundos
0,09 segundos

Tempo instrumentado
20,77
20,77
20,72
22,71
21,42
22,77
20,27
20,57
20,24
20,21
20,27
20,57
20,24
20,21
17,43
20,19
20,24
20,17
20,24
21,81
20,59
22,81
21,43
22,77
20,12
21,10
20,14
20,25
20,24
20,21
20,72 segundos
1,08 segundos

unidade de imagem gerando o arquivo trace com a extensao tc para cada arquivo:
histograma
carregaimagem
pacotelocal
formclick
formpaint
histograma2
maxcalorrgb
minvalorrgb
pacoteimagens
procurareg
realce2
realceparcial
salvaimagem

6.3 Tempo de execuc


ao

85

Figura 6.3: Realce de contraste pela Curva Caracterstica

Figura 6.4: Realce de Contraste pelos Coeficientes de Atenuacao e Segmentacao


A unidade pacotelocal que sera exemplificada a seguir foi executada no primeiro caso
de teste, e a ferramenta de instrumentacao gerou um grafo desta rotina, como mostrada
na Figura 6.7. Depois de executado, ela gera um arquivo trace com os n
umeros dos nos

6.4 Consideraco
es Finais

86

Tabela 6.2: Tempo de execucao do Realce de Contraste pelos Coeficientes de Atenuacao


e Segmentacao
N
umero
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
M
edia
Desv.Pad.

Tempo n
ao instrumentado
78,89
78,02
77,60
77,45
77,71
77,76
78,24
77,72
77,72
78,16
77,82
77,80
77,85
77,84
78,00
77,87
77,67
78,08
78,00
78,68
78,10
77,91
77,81
78,06
77,89
78,38
77,88
77,84
77,90
77,94
77,96 segundos
0,30 segundos

Tempo instrumentado
144,22
164,91
157,34
147,23
159,73
158,45
153,69
147,32
152,25
158,45
153,69
147,32
152,25
151,22
147,72
136,59
150,41
135,77
157,90
158,19
157,34
147,25
159,73
158,45
153,89
146,82
152,25
147,32
152,25
153,69
152,12 segundos
6,63 segundos

cobertos.
Um arquivo dot mostrado pela Figura 6.6 , especifica como deve ser gerado o grafo
em forma de figura pela Ferramenta Graphviz.
Uma das seq
uencias observadas de sua execucao foi a dos nos 1, 2, 3, 4, 5, 7, 9, 11, 13,
15, 17, 20, 21, 22, 23, 24, 25, 27, 29, 32, 33, 35, 36, 35, 37, 32, 33, 34, 20 e volta para o no
21 fazendo este mesmo caminho varias vezes ate sair do procedimento. Na Figura 6.8 sao
representados os nos executados. Vale lembrar que a pintura escura dos nos mostrados
na figura 6.8 nao foi feita pelo programa, e apenas uma ilustracao para vizualizar quais
nos foram executados.

6.4

Considerac
oes Finais

Neste captulo foi apresentado o estudo de caso, apresentando o tamanho do arquivo executavel e o tempo de execucao. Foi exemplificado em um programa proposital-

6.4 Consideraco
es Finais

87

Tabela 6.3: Tempo de execucao do Realce de Contraste pela Modificacao do Histograma


e Segmentacao
N
umero
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
M
edia
Desv.Pad.

Tempo n
ao instrumentado
92,12
88,44
98,71
88,40
88,38
88,73
88,95
88,32
88,54
88,87
88,43
88,50
88,43
88,55
88,65
88,59
88,47
88,55
88,51
89,88
88,69
88,49
88,35
88,39
88,70
88,53
88,47
88,58
88,60
88,71
89,05 segundos
1,96 segundos

Tempo instrumentado
152,07
150,75
157,91
161,89
151,66
166,81
152,43
151,66
151,72
166,81
152,43
151,66
151,72
152,68
168,33
152,54
165,31
152,63
164,88
152,73
158,11
161,84
151,85
166,81
152,12
151,68
150,82
151,66
151,72
152,43
155,92 segundos
6,10 segundos

mente escrito na linguagem Delphi com 5.388 linhas de programacao, para averiguacao
da gramatica e a descricao do instrumentador. O aumento de tempo consideravelmente
extense e devido a quantidade de codigo que e processado nos casos de teste, pois o processamento de imagens utiliza muitos lacos ou comandos de repeticao. Mesmo assim, o
tempo que o programa demorou a mais para a execucao das rotinas revela-se insignificante
comparado com o proposito da ferramenta, mesmo porque, o software instrumentado so
sera utilizado para encontrar/rastrear erros, ou seja, auxiliar o testador de software a
encontrar erros. No proximo captulo serao apresentadas as consideracoes finais, as quais
ressaltarao a importancia do teste de software e descreverao o proposito deste trabalho,
alem disso oferecendo sugestoes para trabalhos futuros.

6.4 Consideraco
es Finais

88

Figura 6.5: Realce de Contraste pela Modificacao do Histograma e Segmentacao


digraph gfc {
node [shape = doublecircle] 31;
node [shape = circle] 1;
/* pusage of icancelapacote at 1 */
node [shape = circle] 19;
node [shape = circle] 2;
/* pusage of lexecmh at 2 */
/* pusage of lexecca at 2 */
node [shape = circle] 18;
node [shape = circle] 3;
/* pusage of lexecca at 3 */
node [shape = circle] 4;
node [shape = circle] 5;
/* pusage of lexecmh at 5 */
node [shape = circle] 6;
node [shape = circle] 7;
/* pusage of lexecsegorig at 7 */
/* pusage of lexecsegrealce at 7 */
node [shape = circle] 8;
node [shape = circle] 9;
/* pusage of lexectap at 9 */
node [shape = circle] 10;
node [shape = circle] 11;
/* pusage of lexecdc at 11 */
node [shape = circle] 12;
node [shape = circle] 13;
/* pusage of lexeccurva at 13 */
node [shape = circle] 14;
node [shape = circle] 15;
node [shape = circle] 16;
node [shape = circle] 21;
/* pusage of lusaporcfibra at 21 */
node [shape = circle] 24;
node [shape = circle] 22;
/* pusage of nporcfibra at 22 */
node [shape = circle] 23;
node [shape = circle] 25;
/* pusage of lexecsegorig at 25 */
node [shape = circle] 26;
node [shape = circle] 27;
/* pusage of lexecmh at 27 */
/* pusage of lexecca at 27 */
/* pusage of lexecfp at 27 */
/* pusage of lexectap at 27 */
node [shape = circle] 28;
node [shape = circle] 30;
node [shape = circle] 20;

/* cusage of vetornomes[nindicepacote] at 20 */
/* cusage of nindicepacote at 20 */
/* cusage of nomearq at 20 */
/* cusage of round(procurareg(tabporc,arquivooriginal)*100) at 20 */
/* cusage of procurareg(tabporc,arquivooriginal) at 20 */
/* cusage of tabporc at 20 */
/* cusage of arquivooriginal at 20 */
/* cusage of fpacote.caporcfibra.value at 20 */
/* cusage of nporcfibra at 20 */
/* cusage of vetornomes[nindicepacote] at 20 */
/* cusage of nindicepacote at 20 */
/* cusage of nomearq at 20 */
/* cusage of nomearq at 20 */
/* cusage of vetornomes[nindicepacote] at 20 */
/* cusage of nindicepacote at 20 */
/* cusage of nomearq at 20 */
node [shape = circle] 17;
node [shape = circle] 34;
/* cusage of quantimagens at 34 */
node [shape = circle] 32;
node [shape = circle] 29;
node [shape = circle] 37;
/* cusage of grdauximagem.rowcount at 37 */
node [shape = circle] 35;
/* cusage of grdimagem.cells[j,i] at 35 */
/* cusage of j at 35 */
/* cusage of i at 35 */
node [shape = circle] 33;
node [shape = circle] 36;
/* cusage of grdauximagem.colcount at 36 */
30 -> 31; 11 -> 13;
11 -> 12; 12 -> 13;
13 -> 15; 13 -> 14;
14 -> 15; 15 -> 16;
16 -> 17; 15 -> 16;
16 -> 17; 17 -> 20;
20 -> 21; 20 -> 30;
34 -> 20; 21 -> 25;
21 -> 22; 24 -> 25;
22 -> 24; 22 -> 23;
23 -> 24; 25 -> 27;
25 -> 26; 26 -> 27;
27 -> 29; 27 -> 28;
28 -> 29; 29 -> 32;
32 -> 33; 32 -> 34;
37 -> 32; 33 -> 35;
35 -> 36; 35 -> 37;

Figura 6.6: Arquivo DOT

36 -> 35;
1 -> 19;
2 -> 3;
18 -> 31;
3 -> 4;
5 -> 7;
6 -> 7;
7 -> 8;
9 -> 11;
10 -> 11;

1 -> 2;
19 -> 31;
2 -> 18;
3 -> 5;
4 -> 5;
5 -> 6;
7 -> 9;
8 -> 9;
9 -> 10;

6.4 Consideraco
es Finais

Figura 6.7: Grafo da Procedure Pacotelocal

89

6.4 Consideraco
es Finais

Figura 6.8: Grafo da Procedure Pacotelocal Percorrido

90

91

Conclus
oes e trabalhos futuros

A linguagem de programacao Delphi e muito utilizada por ser uma linguagem facil e
familiar como e a linguagem de programacao Pascal. A visibilidade crescente do software
como um elemento do sistema e o custo associado `a falha motivam esforcos para a pratica
de testes de software. Atividades agregadas sobre o nome Garantia de Qualidade de
Software tem sido introduzida ao longo do processo de desenvolvimento, e a falta de
ferramentas de apoio ao teste estrutural para a linguagem de programacao Delphi foi
o que impulsionou este trabalho. Encontra-se no mercado apenas uma ferramentas de
apoio ao teste estrutural para Linguagem Delphi, que atende apenas o criterio Todos
Nos. Com este trabalho alem deste criterio Todos Nos sera possvel utilizar o criterio
Todos os Caminhos que nao e comum em ferramentas de teste de software, e tambem
criterio Todos os Usos que dificilmente encontra-se em ferramentas de teste.
O processo de instrumentacao e de fundamental importancia em diversas areas da
Engenharia de Software, tornando-se mais confiavel e preciso quando realizado com o
auxlio de um software instrumentador com proposito especfico. O instrumentador Delphi
foi desenvolvido com o apoio da linguagem de descricao de instrumentacao IDeL e seu
respectivo compilador IDeLGen. Mesmo com pesquisas e revisoes bibliograficas, nao foi
possvel encontrar uma representacao BNF completa da gramatica do Delphi. Assim, seu
desenvolvimento foi parte integrante deste trabalho.
A gramatica do Delphi foi desenvolvida para os programas Lex (analisador lexico) e
Yacc (analisador sintatico). No entanto, foram desenvolvidos dois arquivos: o delphi.y
(Apendice A), com 320 producoes e o delphi.l (Apendice B) que reconhece 147 tokens
(terminais). O analisador lexico reconhece o token e repassa para o analisador sintatico
realizar a analise sintatica. O Lex e Yacc, responsaveis pela construcao do analisador
lexico e sintatico respectivamente, foram usados pela ferramenta IDeLGen para gerar o
instrumentador.
A obtencao da gramatica apresentou consideravel dificuldade e se revelou de suma

7.1 Trabalhos Futuros

92

importancia no contexto do projeto. Conforme visto no Captulo 3, a complexidade para


confeccionar uma gramatica e grande, tendo em vista que a Linguagem Delphi possui
uma gramatica mais complexa do que as Linguagens C ou Pascal. Outros fatores
de complexidades sao a sua flexibilidade na programacao estruturada e seu atendimento
a varios tipos de componentes visuais. Foi despendido um esforco muito grande para
a confeccao da descricao da IDeL, pois a falta de documentacao para a confeccao dos
requisitos requeridos por ela dificultou muito o trabalho.
O u
nico documento disponvel para consulta sobre os aspectos operacionais do sistema e um relatorio tecnico (SIMAO et al., 2001) que, apesar de grande utilidade para este
trabalho, nao abrange toda a complexidade do gerador de instrumentador. Uma linha
errada no arquivo de descricao causa um erro complicadssimo de ser rastreado. Baseado no arquivo de descricao, de como instrumentar a Linguagem C, foram alteradas e
adicionadas varias outras regras para atender `a sintaxe da Linguagem Delphi.
Por fim, tendo em vista que a linguagem de programacao Delphi e largamente utilizada, a possibilidade de instrumentar codigos Delphi e de suma importancia, pois com a
confeccao da gramatica e a descricao de instrumentacao, junto com as ferramentas IDeL
e IDeLGen e possvel atender a esta necessidade. Assim este trabalho contribui com a
instrumentacao e teste para a linguagem Delphi.

7.1

Trabalhos Futuros

Ao longo da confeccao deste projeto foi possvel identificar melhorias que envolvem a
alteracao dos sistemas IDeL e IDeLGen. Um dos problemas encontrados foi na descricao
de instrumentacao da IDeL. A ferramenta permite encontrar apenas uma u
nica unidade
de identificacao, unidade esta, que encontra cada funcao ou procedimento do programa
Delphi para a instrumentacao. Seria de muita utilidade se fosse possvel identificar varias
unidades. A solucao encontrada para resolver este problema foi generalizar a funcao e
procedimento direto na gramatica do Delphi (arquivo delphi.y Apendice A - Pagina 96),
possibilitando a escrita de apenas uma unidade.
Outra melhoria envolve a alteracao na gramatica da descricao de como instrumentar
(arquivo delphi.idel Apendice C - Pagina 133), para que seja possvel especificar a criacao
de nos e arestas diferenciados, ja que a IDeL utiliza o programa Graphviz para gerar os
de grande importancia
grafos. Este programa aceita in
umeros tipos de arestas e nos. E
a possibilidade de saber quais codigos fazem parte de qual no, possibilitando ao testador

7.1 Trabalhos Futuros

93

uma facil escolha para caso de teste.


Uma interface grafica poderia ser construda para manipular toda a ferramenta. Esta
ferramenta tambem poderia levantar os requisitos de teste para a cobertura de varios
criterios e ainda obter varios tipos de relatorios de testes. Em um trabalho futuro, podese utilizar o instrumentador gerado para linguagem Delphi deste projeto e confeccionar
uma ferramenta visual que oriente o testador em varios criterios existentes em teste de
software, exemplo a JaBUTi apresentado no Captulo 2 Pagina 25

94

Refer
encias
AHO, A. V.; SETHI, R.; ULLMAN, J. D. Compiladores Princpios, Tecnicas e Ferramentas. Massachusetts, 01867, USA: LTC-Livros Tecnicos e cientficos Editora S.A,
1986.
CYAMON SOFTWARE. Discover for Delphi. 2005. Discover Ferramenta de teste para
Delphi. Disponvel em: <http://www.cyamon.com/discover1.htm>. Acesso em: 27
mar. 2005.
DELAMARO, M. E. Proteum: Um ambiente de teste baseado na analise de mutantes.
Dissertacao (Mestrado) Instituto de Ciencias Matematicas e de Computacao da
Universidade de Sao Paulo, Outubro 1993.
DELAMARO, M. E. Mutacao de interface: Um criterio de adequacao inter-procedimental
para o teste de integracao. 1997.
DEMILLO, R.; LIPTON, R.; SAYWARD, F. Hints on test data selection: Help for the
practicing programmer. IEEE Computer, v. 11, p. 3441, 1978.
HARROLD, M. J.; ROTHERNEL, G. Performing data flow testing on classes. Australian
Comtuter Journal, p. 9296, 1994.
HERMAN, P. M. A data flow analysis approach to program testing. Australian Computer
Journal, 1976.
HOWDEN, W. E. Functional program testing and analysis. New York, NY, USA:
McGraw-Hill, Inc., 1986. ISBN 0-070-30550-1.
KUNG, D. C.; HSIA, P. Object orientado integration testing. In Third IEEE International
High-Assurance Systems Engineering Symposium, p. 411426, Nov 1998.
MALDONADO, J. C. Criterios Potenciais Usos: Uma Contribuic
ao ao Teste Estrutural
de Software. Tese (Doutorado) DCA/FEE/UNICAMP, Campinas, SP, Brasil,
Julho 1991.
MALDONADO, J. C. et al. Introduc
ao ao teste de software. Sao Carlos, Janeiro 2004.
Instituto de Ciencias Matematicas e de Computacao.
MALDONADO, J. C.; CHAIM, M. L.; JINO, M. A brief view of potential uses criteria
and of poke-tool testing tool. Instituto de Ciencias Matematicas e de Computacao
da Universidade de Sao Paulo. 1991.
MCGREGOR, J. D.; SYKES, D. A. A pratical guide to testing object-oriented. AddisonWesley. 2001.

Referencias

95

NTAFOS, S. C. A comparison of some structural testing strategies. IEEE Trans. Softw.


Eng., IEEE Press, Piscataway, NJ, USA, v. 14, n. 6, p. 868874, 1988. ISSN 00985589.
NUNES, F. L. S. Investigac
oes em processamento de imagens mamogr
aficas para auxlio
ao diagnostico de mamas densas. Tese (Doutorado) IFSC/USP, S.Carlos (SP),
2001.
PRESSMAN, R. S. Software Engineering: A Practitioners Approach. New York, NY,
USA: McGraw-Hill Higher Education, 2001. ISBN 0072496681.
RAPPS, S.; WEYUKER, E. J. Data flow analysis techniques for test data selection. In:
ICSE 82: Proceedings of the 6th international conference on Software engineering.
[S.l.]: IEEE Computer Society Press, 1982. p. 272278.
ROCHA, A. D. et al. Teste Funcional: Uma abordagem Auxiliada por Aspectos. Sao
Carlos, SP, Brasil, 2004.
SIMAO, A. S. et al. A Language for the Description of Program Instrumentation and
Automatic Generation of Instrumenters. Sao Carlos, 2001. 23 p.
SOMMERVILLE, I. Software Engineering. New York, NY, USA: Addison Wesley, 2003.
ISBN 8588639076.
VINCENZI, A. M. R. Subsdios para o Estabelecimento de Estrategias de Teste Baseadas na Tecnica de Mutac
ao. Dissertacao (Mestrado) Instituto de Ciencias Matematicas de Sao Carlos - USP, Sao Carlos, abril 1997.
VINCENZI, A. M. R. et al. JaBUTi: A coverage analysis tool for Java programs. In:
XVII SBES Simposio Brasileiro de Engenharia de Software. Manaus, AM, Brasil:
[s.n.], 2003. p. 7984.

96

Apendice A - Gram
atica do Delphi
(delphi.y)
%token ABSOLUTE
%token ABSTRACT
%token AND
%token ANPARSANT
%token ARRAY
%token AS
%token ASM
%token ASSEMBLER
%token AT
%token ATSIGN
%token ATTRIB
%token AUTOMATED
%token _BEGIN
%token CASE
%token CDECL
%token CIRC
%token CLASS
%token CLOSEBRACKET
%token CLOSECURL
%token CLOSEPAR
%token COLON
%token COMMA
%token CONST
%token CONSTRUCTOR
%token CONTAINS
%token DEFAULT
%token DESTRUCTOR
%token DIFF
%token DISPID
%token DISPINTERFACE
%token DIV
%token DO
%token DOT
%token DOTDOT
%token DOWNTO
%token DYNAMIC
%token ELSE
%token END
%token EQUAL
%token EXPORT
%token EXPORTS
%token EXTERNAL

Apendice A - Gram
atica do Delphi (delphi.y)
%token EXIT
%token FAR
%token _FILE
%token FINALIZATION
%token FINALLY
%token FOR
%token FORWARD
%token FUNCTION
%token GE
%token GOTO
%token GT
%token HALT
%token IDENTIFIER
%token IF
%token IMMCHAR_ID
%token IMPLEMENTATION
%token IMPLEMENTS
%token IN
%token INDEX
%token INHERITED
%token INITIALIZATION
%token INLINE
%token INTERFACE
%token INTERRUPT
%token IS
%token LABEL
%token LE
%token LIBRARY
%token LT
%token MESSAGE
%token MINUS
%token MOD
%token NAME
%token NEAR
%token NIL
%token NODEFAULT
%token NOT
%token OBJECT
%token OF
%token ON
%token OPENBRACKET
%token OPENCURL
%token OPENPAR
%token OR
%token OUT
%token OVERLOAD
%token OVERRIDE
%token PACKAGE
%token PACKED
%token PASCAL
%token PLUS
%token PRIVATE
%token PROCEDURE
%token PROGRAM

97

Apendice A - Gram
atica do Delphi (delphi.y)
%token PROPERTY
%token PROTECTED
%token PUBLIC
%token PUBLISHED
%token RAISE
%token READ
%token RECORD
%token REGISTER
%token REINTRODUCE
%token REPEAT
%token REQUIRES
%token RESIDENT
%token RESOURCESTRING
%token SAFECALL
%token SEMICOLON
%token SET
%token SHL
%token SHR
%token SLASH
%token STAR
%token STARSTAR
%token STDCALL
%token STORED
%token STRING
%token STRING_CONST
%token THEN
%token THREADVAR
%token TILDE
%token TO
%token TOP
%token TRY
%token TYPE
%token UNIT
%token UNSIGNED_INTEGER
%token UNSIGNED_REAL
%token UNTIL
%token USES
%token VAR
%token VIRTUAL
%token WHILE
%token WITH
%token XOR
%token EXCEPT
%token ARRAY_RANGE
%%
program
: program_file
| unit_file
| library_file
| package_file
;
package_file

98

Apendice A - Gram
atica do Delphi (delphi.y)
: PACKAGE IDENTIFIER SEMICOLON
requires_clause
contains_clause
;
requires_clause
:
| REQUIRES requires_units_list SEMICOLON
;
requires_units_list
: requires_units_list COMMA IDENTIFIER
| IDENTIFIER
;
contains_clause
:
| CONTAINS contains_units_list SEMICOLON
;
contains_units_list
: contains_units_list COMMA contains_unit_name
| contains_unit_name
;
contains_unit_name
: IDENTIFIER
| IDENTIFIER

keyword_in string

;
library_file
: library_heading main_uses_clause
library_block DOT
;
library_heading
: LIBRARY IDENTIFIER SEMICOLON
;
library_block
: library_impl_decl_sect_list compound_stmt
;
library_impl_decl_sect_list
:
| library_impl_decl_sect_list library_impl_decl_sect
;
library_impl_decl_sect
: impl_decl_sect
| export_clause
;
export_clause

99

Apendice A - Gram
atica do Delphi (delphi.y)
:
| EXPORTS exports_list SEMICOLON
;
exports_list
: exports_entry
| exports_list COMMA exports_entry
;
exports_entry
: exports_identifier exports_index exports_name exports_resident
;
exports_identifier
: qualified_identifier
;
exports_index
:
| INDEX integer_const
;
exports_name
:
| NAME string_const_2
;
exports_resident
:
| RESIDENT
;
program_file
: program_heading main_uses_clause
program_block DOT
;
program_heading
:
| PROGRAM IDENTIFIER program_heading_2
;
program_heading_2
: SEMICOLON
| OPENPAR program_param_list CLOSEPAR SEMICOLON
;
program_param_list
: IDENTIFIER
| program_param_list COMMA IDENTIFIER
;
program_block
: program_decl_sect_list compound_stmt

100

Apendice A - Gram
atica do Delphi (delphi.y)
;
program_decl_sect_list
:
| program_decl_sect_list impl_decl_sect
| program_decl_sect_list export_clause
;
uses_clause
:
| USES used_units_list SEMICOLON
;
used_units_list
: used_units_list COMMA IDENTIFIER
| IDENTIFIER
;
main_uses_clause
:
| USES main_used_units_list SEMICOLON
;
main_used_units_list
: main_used_units_list COMMA main_used_unit_name
| main_used_unit_name
;
main_used_unit_name
: IDENTIFIER
| IDENTIFIER

keyword_in string

;
unit_file
: unit_heading interface_part implementation_part initialization_part DOT
;
unit_heading
: UNIT IDENTIFIER SEMICOLON
;
interface_part
: INTERFACE uses_clause int_decl_sect_list
;
implementation_part
: IMPLEMENTATION uses_clause impl_decl_sect_list export_clause
;
initialization_part
: compound_stmt
| new_initialization_part END
| new_initialization_part new_finalization_part END
| END

101

Apendice A - Gram
atica do Delphi (delphi.y)
;
new_initialization_part
: INITIALIZATION stmt_list
;
new_finalization_part
: FINALIZATION stmt_list
;
impl_decl_sect_list
:
| impl_decl_sect_list impl_decl_sect
;
impl_decl_sect
: block_decl_sect
| threadvar_decl_sect
| constructor_impl
| destructor_impl
;
block_decl_sect
: const_type_var_decl
| label_decl_sect
| main_impl
;
const_type_var_decl
: const_decl_sect
| type_decl_sect
| var_decl_sect
;
label_decl_sect
: LABEL label_list SEMICOLON
;
label_list
: label
| label_list COMMA label
;
label
: IDENTIFIER
;
const_decl_sect
: const_decl_sect_old
| const_decl_sect_resourcestring
;
const_decl_sect_old
: CONST const_decl

102

Apendice A - Gram
atica do Delphi (delphi.y)
| const_decl_sect_old const_decl
;
const_decl_sect_resourcestring
: RESOURCESTRING const_decl_resourcestring
| const_decl_sect_resourcestring const_decl_resourcestring
;
const_decl_resourcestring
: IDENTIFIER EQUAL res_string
;
res_string
: qualified_identifier
| string
| res_string PLUS qualified_identifier
| res_string PLUS string
;
type_decl_sect
: TYPE type_decl
| type_decl_sect type_decl
;
var_decl_sect
: VAR var_decl
| var_decl_sect var_decl
;
threadvar_decl_sect
: THREADVAR threadvar_decl
| threadvar_decl_sect threadvar_decl
;
int_decl_sect_list
:
| int_decl_sect_list int_decl_sect
;
int_decl_sect
: const_type_var_decl
| threadvar_decl_sect
| proc_heading
| func_heading
;
const_decl
: const_name EQUAL const SEMICOLON
| const_name COLON type EQUAL typed_const SEMICOLON
;
const_name
: IDENTIFIER
;

103

Apendice A - Gram
atica do Delphi (delphi.y)

const

: const_simple_expr
| const_simple_expr const_relop const_simple_expr
;

const_relop
: EQUAL
| DIFF
| LT
| GT
| LE
| GE
| keyword_in
;
const_simple_expr
: const_term
| const_simple_expr add_op const_term
;
const_term
: const_factor
| const_term const_mulop const_factor
;
const_mulop
: STAR
| SLASH
| DIV
| MOD
| SHL
| SHR
| AND
;
const_factor
: const_variable
| unsigned_number
| string
| NIL
| ATSIGN const_factor
| OPENPAR const CLOSEPAR
| NOT const_factor
| sign const_factor
| set_const
;
const_variable
: qualified_identifier
| const_variable const_variable_2
;
const_variable_2
: OPENBRACKET const_expr_list CLOSEBRACKET

104

Apendice A - Gram
atica do Delphi (delphi.y)
| DOT IDENTIFIER
| CIRC
| OPENPAR const_func_expr_list CLOSEPAR
;
const_expr_list
: const
| const_expr_list COMMA const
;
const_func_expr_list
: const
| const COMMA const
;
const_elem_list
:
| const_elem_list1
;
const_elem_list1
: const_elem
| const_elem_list1 COMMA const_elem
;
const_elem
: const
| const DOTDOT const
;
unsigned_number
: unsigend_integer
| UNSIGNED_REAL
;
sign
: PLUS
| MINUS
;
typed_const
: const
| array_const
| record_const
| OPENPAR CLOSEPAR
;
array_const
: OPENPAR typed_const_list CLOSEPAR
;
typed_const_list
: typed_const COMMA typed_const
| typed_const_list COMMA typed_const

105

Apendice A - Gram
atica do Delphi (delphi.y)
;
record_const
: OPENPAR const_field_list CLOSEPAR
;
const_field_list
: const_field
| const_field_list SEMICOLON
;
const_field
: const_field_name COLON typed_const
;
const_field_name
: IDENTIFIER
;
set_const
: OPENBRACKET const_elem_list CLOSEBRACKET
;
type_decl
: IDENTIFIER EQUAL type_decl_type SEMICOLON
;
type_decl_type
: type
| TYPE type
| object_type
;
type

: simple_type
| pointer_type
| structured_type
| string_type
| procedural_type
;

simple_type
: simple_type_ident
| const_simple_expr DOTDOT const_simple_expr
| OPENPAR enumeration_id_list CLOSEPAR
;
simple_type_ident
: qualified_identifier
;
enumeration_id_list
: enumeration_id COMMA enumeration_id
| enumeration_id_list COMMA enumeration_id
;

106

Apendice A - Gram
atica do Delphi (delphi.y)

enumeration_id
: IDENTIFIER
;
pointer_type
: CIRC IDENTIFIER
;
structured_type
: unpacked_structured_type
| PACKED unpacked_structured_type
;
unpacked_structured_type
: array_type
| record_type
| set_type
| file_type
;
array_type
: ARRAY array_index_decl OF type
;
array_index_decl
:
| OPENBRACKET simple_type_list CLOSEBRACKET
;
simple_type_list
: simple_type
| simple_type_list COMMA simple_type
| ARRAY_RANGE
;
record_type
: RECORD field_list END
;
field_list
:
| fixed_part
| variant_part
| fixed_part_2 SEMICOLON variant_part
;
fixed_part
: fixed_part_2
| fixed_part_2 SEMICOLON
;
fixed_part_2
: record_section

107

Apendice A - Gram
atica do Delphi (delphi.y)
| fixed_part_2 SEMICOLON record_section
;
record_section
: record_section_id_list COLON type
;
record_section_id_list
: record_section_id
| record_section_id_list COMMA record_section_id
;
record_section_id
: IDENTIFIER
;
variant_part
: CASE tag_field OF variant_list
;
tag_field
: tag_field_typename
| tag_field_name COMMA tag_field_typename
;
tag_field_name
: IDENTIFIER
;
tag_field_typename
: qualified_identifier
;
variant_list
: variant_list_2
| variant_list_2 SEMICOLON
;
variant_list_2
: variant
| variant_list_2 SEMICOLON variant
;
variant : case_tag_list COLON OPENPAR variant_field_list CLOSEPAR
;
variant_field_list
: field_list
;
case_tag_list
: const
| case_tag_list COMMA const
;

108

Apendice A - Gram
atica do Delphi (delphi.y)

set_type
: SET OF simple_type
;
file_type
: _FILE OF type
| _FILE
;
string_type
: STRING
| STRING OPENBRACKET const CLOSEBRACKET
;
procedural_type
: procedural_type_0 proctype_calling_conv
;
proctype_calling_conv
:
| calling_convention
;
procedural_type_0
: procedural_type_decl
| procedural_type_decl OF OBJECT
;
procedural_type_decl
: PROCEDURE fp_list
| FUNCTION fp_list COLON fptype
;
object_type
: new_object_type
| old_object_type
| it_interface_type
;
old_object_type
: OBJECT oot_successor oot_component_list oot_privat_list END
;
oot_privat_list
:
| PRIVATE oot_component_list
;
oot_component_list
:
| oot_field_list
| oot_field_list oot_method_list
| oot_method_list

109

Apendice A - Gram
atica do Delphi (delphi.y)
;
oot_successor
: OPENPAR oot_typeidentifier CLOSEPAR
;
oot_typeidentifier
: qualified_identifier
;
oot_field_list
: oot_field
| oot_field_list oot_field
;
oot_field
: oot_id_list COLON type SEMICOLON
;
oot_id_list
: oot_field_identifier
| oot_id_list COMMA oot_field_identifier
;
oot_field_identifier
: IDENTIFIER
;
oot_method_list
: oot_method
| oot_method_list oot_method
;
oot_method
: oot_method_head
| oot_method_head VIRTUAL SEMICOLON
;
oot_method_head
: proc_heading
| func_heading
| oot_constructor_head
| oot_destructor_head
;
oot_constructor_head
: CONSTRUCTOR IDENTIFIER fp_list SEMICOLON
;
oot_destructor_head
: DESTRUCTOR IDENTIFIER fp_list SEMICOLON
;
new_object_type

110

Apendice A - Gram
atica do Delphi (delphi.y)
: not_class_reference_type
| not_object_type
;
not_class_reference_type
: CLASS OF not_class_type_identifier
;
not_class_type_identifier
: IDENTIFIER
;
not_object_type
: CLASS
| CLASS not_heritage
| CLASS not_component_list_seq END
| CLASS not_heritage not_component_list_seq END
;
not_component_list_seq
: not_component_list
| not_component_list_seq not_visibility_specifier not_component_list
;
not_heritage
: OPENPAR not_object_type_identifier CLOSEPAR
;
not_object_type_identifier
: qualified_identifier
| qualified_identifier COMMA it_interface_list
;
it_interface_list
: it_qualified_interfacename
| it_interface_list COMMA it_qualified_interfacename
;
not_visibility_specifier
: PUBLISHED
| PUBLIC
| PROTECTED
| PRIVATE
| AUTOMATED
;
not_component_list
:
| not_component_list_1
| not_component_list_2
| not_component_list_1 not_component_list_2
;
not_component_list_1

111

Apendice A - Gram
atica do Delphi (delphi.y)
: not_field_definition
| not_component_list_1 not_field_definition
;
not_component_list_2
: not_method_definition
| not_property_definition
| not_component_list_2 not_method_definition
| not_component_list_2 not_property_definition
;
not_field_definition
: not_field_identifier_list COLON type SEMICOLON
;
not_field_identifier_list
: not_field_identifier
| not_field_identifier_list COMMA not_field_identifier
;
not_field_identifier
: IDENTIFIER
;
not_method_definition
: not_method_heading not_method_directives
;
not_method_heading
: CLASS proc_heading
| CLASS func_heading
| func_heading
| proc_heading
| it_method_attribution
| not_constructor_heading_decl
| not_destructor_heading_decl
;
not_constructor_heading_decl
: CONSTRUCTOR IDENTIFIER fp_list SEMICOLON
;
not_destructor_heading_decl
: DESTRUCTOR IDENTIFIER fp_list SEMICOLON
;
not_method_directives
: not_method_directives_0
| not_method_directives_0 not_dispid_specifier
;
not_method_directives_0
: not_method_directives_reintroduce
not_method_directives_overload

112

Apendice A - Gram
atica do Delphi (delphi.y)
not_method_directives_1
;
not_method_directives_reintroduce
:
| REINTRODUCE SEMICOLON
;
not_method_directives_overload
:
| OVERLOAD SEMICOLON
;
not_method_directives_1
:
| VIRTUAL SEMICOLON not_method_directives_2
| DYNAMIC SEMICOLON not_method_directives_2
| MESSAGE

integer_const SEMICOLON not_method_directives_2

| OVERRIDE SEMICOLON
;
not_method_directives_2
: not_method_directives_cdecl not_method_directives_export
not_method_directives_abstract
;
not_method_directives_cdecl
:
| calling_convention SEMICOLON
;
not_method_directives_export
:
| EXPORT SEMICOLON
;
not_method_directives_abstract
:
| ABSTRACT SEMICOLON
;
integer_const
: const_simple_expr
;
not_property_definition
: PROPERTY IDENTIFIER not_property_interface
not_property_specifiers SEMICOLON not_array_defaultproperty
;
not_array_defaultproperty
:
| DEFAULT SEMICOLON
;

113

Apendice A - Gram
atica do Delphi (delphi.y)

not_property_interface
:
| not_property_parameter_list COLON not_type_identifier
not_property_interface_index
;
not_type_identifier
: qualified_identifier
| STRING
;
not_property_interface_index
:
| INDEX integer_const
;
not_property_parameter_list
:
| OPENBRACKET not_parameter_decl_list CLOSEBRACKET
;
not_parameter_decl_list
: not_parameter_decl
| not_parameter_decl_list SEMICOLON not_parameter_decl
;
not_parameter_decl
: not_parameter_name_list COLON fptype
;
not_parameter_name_list
: not_parameter_name
| not_parameter_name_list COMMA not_parameter_name
;
not_parameter_name
: IDENTIFIER
;
not_property_specifiers_0
: not_read_specifier
;
not_property_specifiers
: not_property_specifiers_0

not_stored_specifier

not_default_specifier not_implements_specifier
| not_property_specifiers_0
;
not_dispid_specifier
: DISPID integer_const
;

not_dispid_specifier

114

Apendice A - Gram
atica do Delphi (delphi.y)
not_default_specifier
:
| DEFAULT const
| NODEFAULT
;
not_stored_specifier
:
| STORED not_stored_bool_const
;
not_stored_bool_const
: const
;
not_read_specifier
:
| READ not_field_or_method
;
not_field_or_method
: IDENTIFIER
;
not_implements_specifier
:
| IMPLEMENTS not_interfacename_list
;
not_interfacename_list
: not_interfacename
| not_interfacename_list COMMA not_interfacename
;
not_interfacename
: IDENTIFIER
;
optGUID
:
| OPENBRACKET string CLOSEBRACKET
;
it_interface_type
: it_dispinterface_type
| it_normalinterface_type
;
it_normalinterface_type
: INTERFACE SEMICOLON
| INTERFACE it_heritage optGUID it_interface_elementlist END SEMICOLON
| INTERFACE it_heritage optGUID END SEMICOLON
;

115

Apendice A - Gram
atica do Delphi (delphi.y)
it_heritage
:
| OPENPAR it_qualified_interfacename CLOSEPAR
;
it_dispinterface_type
: DISPINTERFACE SEMICOLON
| DISPINTERFACE optGUID it_interface_elementlist END SEMICOLON
;
it_qualified_interfacename
: qualified_identifier
;
it_interface_elementlist
: it_method_or_property
| it_interface_elementlist it_method_or_property
;
it_method_or_property
: it_method_definition
| it_property_definition
;
it_method_definition
: it_method_heading it_method_directives
;
it_method_heading
: func_heading
| proc_heading
| it_method_attribution
| it_constructor_heading_decl
| it_destructor_heading_decl
;
it_constructor_heading_decl
: not_constructor_heading_decl
;
it_destructor_heading_decl
: not_destructor_heading_decl
;
it_method_attribution
: FUNCTION it_interfacename DOT IDENTIFIER EQUAL IDENTIFIER SEMICOLON
| PROCEDURE

it_interfacename DOT IDENTIFIER DOT IDENTIFIER SEMICOLON

;
it_interfacename
: IDENTIFIER
;
it_method_directives

116

Apendice A - Gram
atica do Delphi (delphi.y)
: not_dispid_specifier
;
it_property_definition
: not_property_definition
;
var_decl
: var_name_list COLON type absolute_clause_or_init_var SEMICOLON
;
threadvar_decl
: var_name_list COLON type SEMICOLON
;
var_name_list
: var_name
| var_name_list COMMA var_name
;
var_name
: IDENTIFIER
;
absolute_clause_or_init_var
: absolute_clause
| EQUAL typed_const
;
absolute_clause
:
| ABSOLUTE unsigend_integer COLON unsigend_integer
| ABSOLUTE unsigend_integer
| ABSOLUTE declared_var_name
;
declared_var_name
: qualified_identifier
;
constructor_impl
: not_constructor_heading not_constructor_block_decl
;
destructor_impl
: not_destructor_heading not_constructor_block_decl
;
not_constructor_heading
: CONSTRUCTOR ot_qualified_identifier fp_list SEMICOLON
;
not_destructor_heading
: DESTRUCTOR ot_qualified_identifier fp_list SEMICOLON

117

Apendice A - Gram
atica do Delphi (delphi.y)
;
ot_qualified_identifier
: IDENTIFIER DOT IDENTIFIER
;
not_constructor_block_decl
: block
| external_directr
| asm_block
;
name_impl
: PROCEDURE
| FUNCTION
;
main_impl
: proc_impl
| func_impl
;
proc_impl
: name_impl func_or_proc_or_method_head proc_block
;
func_impl
: name_impl func_or_proc_or_method_head func_block
;
proc_or_func_fptype
:
| COLON fptype
;
func_or_proc_or_method_head
: func_or_proc_or_method_name fp_list

proc_or_func_fptype SEMICOLON

;
func_or_proc_or_method_name
: ot_qualified_identifier
| IDENTIFIER
;
proc_heading
: PROCEDURE proc_or_func_head
;
func_heading
: FUNCTION proc_or_func_head
;
proc_or_func_head
: proc_or_func_name fp_list proc_or_func_fptype SEMICOLON
;

118

Apendice A - Gram
atica do Delphi (delphi.y)

proc_or_func_name
: IDENTIFIER
;
proc_block
: proc_block_prefix proc_block_decl
| inline_directr SEMICOLON
;
proc_block_prefix
: func_block_prefix
| INTERRUPT SEMICOLON
;
func_block
: func_block_prefix func_block_overload proc_block_decl
| inline_directr SEMICOLON
;
func_block_prefix
:
| NEAR SEMICOLON
| FAR SEMICOLON
| EXPORT SEMICOLON
| calling_convention SEMICOLON
;
calling_convention
: CDECL
| REGISTER
| STDCALL
| SAFECALL
| PASCAL
;
proc_block_decl
: block
| external_directr
| asm_block
| FORWARD SEMICOLON
;
func_block_overload
:
| OVERLOAD
;
external_directr
: EXTERNAL SEMICOLON
| EXTERNAL string_const_2 external_directr_2
;
external_directr_2

119

Apendice A - Gram
atica do Delphi (delphi.y)
: SEMICOLON
| NAME string_const_2 SEMICOLON
| INDEX external_directr_3 SEMICOLON
;
external_directr_3
: unsigend_integer
;
string_const_2
: const_simple_expr
;
asm_block
: ASSEMBLER SEMICOLON impl_decl_sect_list asm_stmt SEMICOLON
;
inline_directr
: INLINE OPENPAR inline_element CLOSEPAR
;
inline_element
: inline_param
| inline_element SLASH inline_param
;
inline_param
: GT inline_const
| inline_param_variable
;
inline_param_variable
: variable_reference
| inline_param_variable sign inline_const
;
inline_const
: const_factor
;
block
: impl_decl_sect_list compound_stmt SEMICOLON
;
fp_list
:
| OPENPAR fp_sect_list CLOSEPAR
| OPENPAR CLOSEPAR
;
fp_sect_list
: fp_sect
| fp_sect_list SEMICOLON fp_sect
;

120

Apendice A - Gram
atica do Delphi (delphi.y)

fp_sect
: keyword_in param_name_list fp_sect_typedef fp_sect_const
| VAR param_name_list fp_sect_typedef
| CONST param_name_list

fp_sect_typedef fp_sect_const

| OUT param_name_list fp_sect_typedef


| VAR param_name_list
| CONST param_name_list
| OUT param_name_list
;
keyword_in
:
| IN
;
fp_sect_typedef
: COLON fptype_new
;
fp_sect_const
:
| EQUAL const
;
param_name_list
: param_name
| param_name_list COMMA param_name
;
param_name
: IDENTIFIER
;
fptype
: func_res_type_name
| STRING
;
fptype_new
: fptype
| ARRAY OF fptype
| ARRAY OF CONST
;
func_res_type_name
: qualified_identifier
;
stmt
: unlabelled_stmt
| label COLON unlabelled_stmt
;

121

Apendice A - Gram
atica do Delphi (delphi.y)
unlabelled_stmt
:
| attribution
| proc_call
| goto_stmt
| compound_stmt
| if_stmt
| case_stmt
| repeat_stmt
| while_stmt
| for_stmt
| with_stmt
| asm_stmt
| inline_directr
| inherited_stmt
| try_stmt
| raise_stmt
| exit_stmt
| halt_stmt
;
exit_stmt
: EXIT
;
attribution
: variable_reference attrib_sign expr
;
proc_call
: variable_reference
;
goto_stmt
: GOTO label
;
compound_stmt
: _BEGIN stmt_list END
;
stmt_list
: stmt
| stmt_list SEMICOLON stmt
;
if_stmt
: IF expr if_then_else_branch
;
if_then_else_branch
: THEN then_branch
| THEN then_branch ELSE else_branch
;

122

Apendice A - Gram
atica do Delphi (delphi.y)

then_branch
: stmt
;
else_branch
: stmt
;
case_stmt
: CASE expr OF case_list else_case END
;
case_list
: case
| case_list SEMICOLON case
;
case

:
| case_label_list COLON stmt
;

case_label_list
: case_label
| case_label_list COMMA case_label
;
case_label
: const
| const DOTDOT const
;
else_case
:
| ELSE stmt_list
;
repeat_stmt
: REPEAT stmt_list UNTIL expr
;
while_stmt
: WHILE expr DO stmt
;
for_stmt
: FOR attribution TO expr DO stmt
| FOR attribution DOWNTO expr DO stmt
;
with_stmt
: WITH variable_list DO stmt
| WITH OPENPAR variable_list CLOSEPAR DO stmt
;

123

Apendice A - Gram
atica do Delphi (delphi.y)

variable_list
: variable_reference
| variable_list COMMA variable_reference
;
inherited_stmt
: INHERITED
| INHERITED proc_call
;
try_stmt
: TRY stmt_list try_stmt_2
;
try_stmt_2
: FINALLY stmt_list END
| EXCEPT exception_block END
;
exception_block
: exception_handler_list exception_block_else_branch
| exception_handler_list SEMICOLON exception_block_else_branch
| stmt_list
;
exception_handler_list
: exception_handler
| exception_handler_list SEMICOLON exception_handler
;
exception_block_else_branch
:
| ELSE stmt_list
;
exception_handler
: ON exception_identifier DO stmt
;
exception_identifier
: exception_class_type_identifier
| exception_variable COLON exception_class_type_identifier
;
exception_class_type_identifier
: qualified_identifier
;
exception_variable
: IDENTIFIER
;
raise_stmt

124

Apendice A - Gram
atica do Delphi (delphi.y)
: RAISE
| RAISE variable_reference
| RAISE variable_reference AT raise_at_stmt_2
;
raise_at_stmt_2
: variable_reference
| NIL
;
variable_reference
: variable_reference_at variable
| variable
;
variable_reference_at
: ATSIGN
| variable_reference_at ATSIGN
;
variable
: qualified_identifier
| INHERITED IDENTIFIER
| variable variable_2
;
variable_2
: OPENBRACKET expr_list CLOSEBRACKET
| DOT IDENTIFIER
| CIRC
| OPENPAR expr_list CLOSEPAR
;
expr_list
:
| expr_list2
;
expr_list2
: expr
| expr_list2 COMMA expr
| expr_list2 DOT expr
;
expr : simple_expr
| simple_expr rel_op simple_expr
| simple_expr COLON simple_expr
| simple_expr COLON simple_expr COLON simple_expr
;
rel_op
: const_relop
| IS
;

125

Apendice A - Gram
atica do Delphi (delphi.y)

simple_expr
: term
| simple_expr add_op term
;
add_op
: PLUS
| MINUS
| OR
| XOR
;
term
: factor
| term mul_op factor
;
mul_op
: const_mulop
| AS
;
factor
: variable_reference
| unsigned_number
| string
| OPENBRACKET elem_list CLOSEBRACKET
| NIL
| NOT factor
| parenth_factor
| sign factor
;
parenth_factor
: OPENPAR expr CLOSEPAR
| parenth_factor CIRC
;
elem_list
:
| elem_list1
;
elem_list1
: elem
| elem_list1 COMMA elem
;
elem
: expr
| expr DOTDOT expr
;
qualified_identifier

126

Apendice A - Gram
atica do Delphi (delphi.y)
: UNIT DOT IDENTIFIER
| IDENTIFIER
;
asm_stmt
: ASM END SEMICOLON
;
halt_stmt
: HALT
;
constant
: UNSIGNED_INTEGER
;
unsigend_integer
: constant
;
attrib_sign
: ATTRIB
;
string
: STRING_CONST
| CIRC IMMCHAR_ID
;
%%

127

128

Ap
endice B - Gram
atica do Delphi
(delphi.l)
A [aA]
B [bB]
C [cC]
D [dD]
E [eE]
F [fF]
G [gG]
H [hH]
I [iI]
J [jJ]
K [kK]
L [lL]
M [mM]
N [nN]
O [oO]
P [pP]
Q [qQ]
R [rR]
S [sS]
T [tT]
U [uU]
V [vV]
W [wW]
X [xX]
Y [yY]
Z [zZ]
DIGIT [0-9]
LETTER [a-zA-Z_]
HEX [a-fA-F0-9]
EXP [Ee][+-]?{D}+
NQUOTE [^]
%{
#include <stdio.h>
static void count();
%}
%%
"//".*"\n" { }
"{".*"}" { }
[{}]* { }

Apendice B - Gram
atica do Delphi (delphi.l)
{A}{N}{D} { count(); RETURN(AND); }
{A}{R}{R}{A}{Y} { count(); RETURN(ARRAY); }
{A}{B}{S}{O}{L}{U}{T}{E} { count(); RETURN(ABSOLUTE); }
{A}{B}{S}{T}{R}{A}{C}{T} { count(); RETURN(ABSTRACT); }
"<>" { count(); RETURN(DIFF); }
{C}{A}{S}{E} { count(); RETURN(CASE); }
{B}{E}{G}{I}{N} { count(); RETURN(_BEGIN); }
{C}{L}{A}{S}{S} { count(); RETURN(CLASS); }
{C}{O}{N}{S}{T} { count(); RETURN(CONST); }
{C}{O}{N}{S}{T}{R}{U}{C}{T}{O}{R} { count(); RETURN(CONSTRUCTOR); }
{A}{S} { count(); RETURN(AS); }
{A}{S}{N} { count(); RETURN(ASM); }
{A}{S}{S}{E}{M}{B}{L}{E}{R} { count(); RETURN(ASSEMBLER); }
{A}{T} { count(); RETURN(AT); }
{A}{U}{T}{O}{M}{A}{T}{E}{D} { count(); RETURN(AUTOMATED); }
{C}{D}{E}{C}{L} { count(); RETURN(CDECL); }
{C}{O}{N}{T}{A}{I}{N}{S} { count(); RETURN(CONTAINS); }
{D}{E}{F}{A}{U}{L}{T} { count(); RETURN(DEFAULT); }
{D}{E}{S}{T}{R}{U}{C}{T}{O}{R}

{ count(); RETURN(DESTRUCTOR); }

{D}{I}{S}{P}{I}{D} { count(); RETURN(DISPID); }


{D}{I}{S}{P}{I}{N}{T}{E}{R}{F}{A}{C}{E} { count(); RETURN(DISPINTERFACE); }
{D}{I}{V} { count(); RETURN(DIV); }
{D}{O} { count(); RETURN(DO); }
{D}{O}{W}{N}{T}{O} { count(); RETURN(DOWNTO); }
{D}{Y}{N}{A}{M}{I}{C} { count(); RETURN(DYNAMIC); }
{E}{L}{S}{E} { count(); RETURN(ELSE); }
{E}{N}{D} { count(); RETURN(END); }
{E}{X}{P}{O}{R}{T} { count(); RETURN(EXPORT); }
{E}{X}{I}{T} { count(); RETURN(EXIT); }
{E}{X}{P}{O}{R}{T}{S} { count(); RETURN(EXPORTS); }
{E}{X}{T}{E}{R}{N}{A}{L} { count(); RETURN(EXTERNAL); }
{E}{X}{C}{E}{P}{T} { count(); RETURN(EXCEPT); }
{F}{A}{R} { count(); RETURN(FAR); }
{F}{I}{L}{E} { count(); RETURN(_FILE); }
{F}{I}{N}{A}{L}{I}{Z}{A}{T}{I}{O}{N}

{ count(); RETURN(FINALIZATION); }

{F}{I}{N}{A}{L}{L}{Y} { count(); RETURN(FINALLY); }


{F}{O}{R} { count(); RETURN(FOR); }
{F}{O}{R}{W}{A}{R}{D} { count(); RETURN(FORWARD); }
{F}{U}{N}{C}{T}{I}{O}{N} { count(); RETURN(FUNCTION); }
{G}{O}{T}{O} { count(); RETURN(GOTO); }
{H}{A}{L}{T} { count(); RETURN(HALT); }
{I}{F} { count(); RETURN(IF); }
{I}{M}{P}{L}{E}{M}{E}{N}{T}{S}

{ count(); RETURN(IMPLEMENTS); }

{I}{N} { count(); RETURN(IN); }


{I}{N}{D}{E}{X} { count(); RETURN(INDEX); }
{I}{N}{H}{E}{R}{I}{T}{E}{D}

{ count(); RETURN(INHERITED); }

{I}{N}{L}{I}{N}{E} { count(); RETURN(INLINE); }


{I}{N}{T}{E}{R}{F}{A}{C}{E} { count(); RETURN(INTERFACE); }
{I}{N}{T}{E}{R}{R}{U}{P}{T} { count(); RETURN(INTERRUPT); }
{I}{S} { count(); RETURN(IS); }
{L}{A}{B}{E}{L} { count(); RETURN(LABEL); }
{L}{I}{B}{R}{A}{R}{Y} { count(); RETURN(LIBRARY); }
{M}{E}{S}{S}{A}{G}{E} { count(); RETURN(MESSAGE); }
{M}{O}{D} { count(); RETURN(MOD); }

129

Apendice B - Gram
atica do Delphi (delphi.l)
{N}{A}{M}{E} { count(); RETURN(NAME); }
{N}{E}{A}{R} { count(); RETURN(NEAR); }
{N}{I}{L} { count(); RETURN(NIL); }
{N}{O}{D}{E}{F}{A}{U}{L}{T}

{ count(); RETURN(NODEFAULT); }

{N}{O}{T} { count(); RETURN(NOT); }


{O}{B}{J}{E}{C}{T} { count(); RETURN(OBJECT); }
{O}{F} { count(); RETURN(OF); }
{O}{N} { count(); RETURN(ON); }
{O}{R} { count(); RETURN(OR); }
{O}{U}{T} { count(); RETURN(OUT); }
{O}{V}{E}{R}{L}{O}{A}{D} { count(); RETURN(OVERLOAD); }
{O}{V}{E}{R}{R}{I}{D}{E} { count(); RETURN(OVERRIDE); }
{P}{A}{C}{K}{A}{G}{E} { count(); RETURN(PACKAGE); }
{P}{A}{C}{K}{E}{D} { count(); RETURN(PACKED); }
{P}{A}{S}{C}{A}{L} { count(); RETURN(PASCAL); }
{P}{R}{I}{V}{A}{T}{E} { count(); RETURN(PRIVATE); }
{P}{R}{O}{C}{E}{D}{U}{R}{E}

{ count(); RETURN(PROCEDURE); }

{P}{R}{O}{G}{R}{A}{M} { count(); RETURN(PROGRAM); }


{P}{R}{O}{P}{E}{R}{T}{Y} { count(); RETURN(PROPERTY); }
{P}{R}{O}{T}{E}{C}{T}{E}{D}

{ count(); RETURN(PROTECTED); }

{P}{U}{B}{L}{I}{C} { count(); RETURN(PUBLIC); }


{P}{U}{B}{L}{I}{S}{H}{E}{D}

{ count(); RETURN(PUBLISHED); }

{R}{A}{I}{S}{E} { count(); RETURN(RAISE); }


{R}{E}{A}{D} { count(); RETURN(READ); }
{R}{E}{C}{O}{R}{D} { count(); RETURN(RECORD); }
{R}{E}{G}{I}{S}{T}{E}{R} { count(); RETURN(REGISTER); }
{R}{E}{I}{N}{T}{R}{O}{D}{U}{C}{E} { count(); RETURN(REINTRODUCE); }
{R}{E}{P}{E}{A}{T} { count(); RETURN(REPEAT); }
{R}{E}{Q}{U}{I}{R}{E}{S} { count(); RETURN(REQUIRES); }
{R}{E}{S}{I}{D}{E}{N}{T} { count(); RETURN(RESIDENT); }
{S}{A}{F}{E}{C}{A}{L}{L} { count(); RETURN(SAFECALL); }
{S}{E}{T} { count(); RETURN(SET); }
{S}{H}{L} { count(); RETURN(SHL); }
{S}{H}{R} { count(); RETURN(SHR); }
{S}{T}{D}{C}{A}{L}{L} { count(); RETURN(STDCALL); }
{S}{T}{O}{R}{E}{D} { count(); RETURN(STORED); }
{S}{T}{R}{I}{N}{G} { count(); RETURN(STRING); }
{T}{H}{E}{N} { count(); RETURN(THEN); }
{T}{H}{R}{E}{A}{D}{V}{A}{R}

{ count(); RETURN(THREADVAR); }

{T}{O} { count(); RETURN(TO); }


{T}{R}{Y} { count(); RETURN(TRY); }
{T}{Y}{P}{E} { count(); RETURN(TYPE); }
{U}{N}{I}{T} { count(); RETURN(UNIT); }
{U}{N}{T}{I}{L} { count(); RETURN(UNTIL); }
{U}{S}{E}{S} { count(); RETURN(USES); }
{V}{A}{R} { count(); RETURN(VAR); }
{V}{I}{R}{T}{U}{A}{L} { count(); RETURN(VIRTUAL); }
{W}{H}{I}{L}{E} { count(); RETURN(WHILE); }
{W}{I}{T}{H} { count(); RETURN(WITH); }
{X}{O}{R} { count(); RETURN(XOR); }
{I}{N}{I}{T}{I}{A}{L}{I}{Z}{A}{T}{I}{O}{N} { count(); RETURN(INITIALIZATION); }
{I}{M}{P}{L}{E}{M}{E}{N}{T}{A}{T}{I}{O}{N} { count(); RETURN(IMPLEMENTATION); }
{R}{E}{S}{O}{U}{R}{C}{E}{S}{T}{R}{I}{N}{G} { count(); RETURN(RESOURCESTRING); }
":=" { count(); RETURN(ATTRIB); }

130

Apendice B - Gram
atica do Delphi (delphi.l)
".." { count(); RETURN(DOTDOT); }
"." { count(); RETURN(DOT); }
"-" { count(); RETURN(MINUS); }
"+" { count(); RETURN(PLUS); }
"*" { count(); RETURN(STAR); }
"/" { count(); RETURN(SLASH); }
"^" { count(); RETURN(CIRC); }
"@" { count(); RETURN(ATSIGN); }
"<" { count(); RETURN(LT); }
">" { count(); RETURN(GT); }
"<=" { count(); RETURN(LE); }
">=" { count(); RETURN(GE); }
"(" { count(); RETURN(OPENPAR); }
")" { count(); RETURN(CLOSEPAR); }
("["|"<:") { count(); RETURN(OPENBRACKET); }
("]"|":>") { count(); RETURN(CLOSEBRACKET); }
";" { count(); RETURN(SEMICOLON); }
"," { count(); RETURN(COMMA); }
":" { count(); RETURN(COLON); }
"=" { count(); RETURN(EQUAL); }
{LETTER}({LETTER}|{DIGIT})* { count(); RETURN(IDENTIFIER); }
(#[0-9]+)+ { count(); RETURN(STRING_CONST); }
({NQUOTE}|)+{ count(); RETURN(STRING_CONST); }
\(\\.|[^\\])*\{ count(); RETURN(STRING_CONST); }
{DIGIT}+\.\.{DIGIT}+ { count(); RETURN(ARRAY_RANGE); }
0[xX]{HEX}+ { count(); RETURN(UNSIGNED_INTEGER); }
0{DIGIT}+ { count(); RETURN(UNSIGNED_INTEGER); }
{DIGIT}+ { count(); RETURN(UNSIGNED_INTEGER); }
{DIGIT}+{EXP} { count(); RETURN(UNSIGNED_REAL); }
{DIGIT}*"."{DIGIT}+({EXP})? { count(); RETURN(UNSIGNED_REAL); }
{DIGIT}+"."{DIGIT}*({EXP})? { count(); RETURN(UNSIGNED_REAL); }
[\n] { count(); }
[ \t\v\f] { count(); }
. { }
%%
static int column = 0;
#define DEBUG
#include "Debug.h"
void count()
{
int i;
if(yytext != NULL)
{
for (i = 0; yytext[i] != \0; i++)
{
if (yytext[i] == \n)
{
column = 0;
}
else if (yytext[i] == \t)

131

Apendice B - Gram
atica do Delphi (delphi.l)
{
column += 8 - (column % 8);
}
else
{
column++;
}
}
}
}

132

133

Ap
endice C - Descri
ca
o do Delphi
na IDeL (delphi.idel)
###############################################
##

delphi.idel

##

##
##

##
Instrumentador para Delphi/ObjectPascal

##
##
##

##
##
##

Giovanni Buranello

##

##

##

##

AGOSTO/2006

##

###############################################
## Especifica
c~
ao IDeL de um instrumentador para as linguagens
## Delphi e Object Pascal.
instrumenter delphi
###############################################
#### Secao 1) Identificacao da Unidade

####

###############################################
## Cada fun
c~
ao
e uma unidade.
unit
var
:head as

[name_impl]

:name as

[func_or_proc_or_method_name]

:type as

[proc_or_func_fptype]

:pars as

[fp_list]

:decl as
:ss as

[impl_decl_sect_list]
[stmt_list]

named by
:name
match
[main_impl< :head :name :pars :type ; :decl begin :ss end ; >]
end unit
###############################################
#### Secao 2) Processamento da Unidade

####

###############################################
## Este passo encontra cada fun
c~
ao e criar um n
o chamado init
## e um n
o chamado exit para cada uma, que s~
ao respectivamente
## os n
os inicial e final.

Apendice C - Descric
ao do Delphi na IDeL (delphi.idel)
step FindFunction
pattern Function
var
:head as

[name_impl]

:name as

[func_or_proc_or_method_name]

:type as

[proc_or_func_fptype]

:pars as

[fp_list]

:decl as
:ss as

[impl_decl_sect_list]
[stmt_list]

match
[main_impl< :head :name :pars :type ; :decl begin :ss end ; >]
declare node $init
declare node $exit
assignment
assign $parameterdefinition:pars to $init
end pattern
## Este passo cria um n
o chamado begin e um n
o chamado end para
## cada statement encontrado dentro da unidade.
step MarkStatements
pattern FooStatement
var
:s as

[unlabelled_stmt]

match
[stmt< :s >]
declare node $begin
declare node $end
end pattern
## Este passo determina o n
o final e inicial de cada lista de statements
## a partir dos n
o final e inicial das sub
arvores individuais.
step LinkStatementList BT
pattern Statement
var
:s as

[stmt]

match
[stmt_list< :s >]
assignment
assign $begin to
assign $end to

$begin:s
$end:s

end pattern
pattern List
var
:s as
:ss as

[stmt]
[stmt_list]

match
[stmt_list< :ss ; :s >]
graph
$end:ss ->
assignment

$begin:s

134

Apendice C - Descric
ao do Delphi na IDeL (delphi.idel)
assign $begin to
assign $end to

$begin:ss
$end:s

end pattern
## Este passo conecta o n
o final do statement anterior com o n
o
## inicial do pr
oximo statement.
step JoinStatement
pattern Join
var
:ss as

[stmt_list]

match
[stmt< begin :ss end >]
graph
$begin ->

$begin:ss

$end:ss ->

$end

end pattern
## Este passo conecta o n
o inicial de uma fun
c~
ao (init) com o
## primeiro n
o da statement list, e tamb
em o
ultimo n
o da statement
## list com o n
o final da fun
c~
ao (exit).
step JoinToFunction
pattern Function1
var
:head as

[name_impl]

:name as

[func_or_proc_or_method_name]

:type as

[proc_or_func_fptype]

:pars as

[fp_list]

:decl as
:ss as

[impl_decl_sect_list]
[stmt_list]

match
[main_impl< :head :name :pars :type ; :decl begin :ss end ; >]
graph
$init ->

$begin:ss

$end:ss ->

$exit

instrument
add init $init before self
add exit $exit after self
end pattern
## Este passo processa cada statement de acordo com sua sem^
antica
## e gerar os respectivos grafos e tabelas de implementa
c~
oes.
step MakeGraph
## Comando Raise, serve para lancar uma excessao.
pattern Raise
var
:r as

[raise_stmt]

match
[stmt< :r >]
graph
$begin ->
end pattern

$raise

135

Apendice C - Descric
ao do Delphi na IDeL (delphi.idel)

## Tratamento de excessao!
pattern ExceptionBlock1
var
:ss as

[stmt_list]

match
[exception_block< :ss >]
graph
$begin ->

$begin:ss

$end:ss ->

$end

end pattern
pattern ExceptionBlock2
var
:el as

[exception_handler_list]

match
[exception_block< :el >]
graph
$begin ->

$begin:el

$end:el ->

$end

end pattern
pattern ExceptionBlock3
var
:el as

[exception_handler_list]

:ss as

[stmt_list]

match
[exception_block< :el else :ss >]
graph
$begin ->

$begin:el

$begin ->

$begin:ss

$end:el ->

$end

$end:ss ->

$end

end pattern
pattern ExceptionBlock4
var
:el as

[exception_handler_list]

:ss as

[stmt_list]

match
[exception_block< :el ; else :ss >]
graph
$begin ->

$begin:el

$begin ->

$begin:ss

$end:el ->

$end

$end:ss ->

$end

end pattern
## Quando ocorre um raise dentro do try, vai direto
## para o n
o de tratamento de excessao.
pattern Try1
var
:s as

[stmt_list]

136

Apendice C - Descric
ao do Delphi na IDeL (delphi.idel)
:eb as

[exception_block]

match
[stmt< try :s except :eb end >]
graph
$begin ->

$begin:s

$begin ->

$begin:eb

$end:s ->

$end

$end:eb ->

$end

assignment
assign

$raise:s to

$begin:eb

end pattern
## Try com finally, que sempre eh executado.
pattern Try2
var
:s1 as

[stmt_list]

:s2 as

[stmt_list]

match
[stmt< try :s1 finally :s2 end >]
graph
$begin ->

$begin:s1

$end:s1 ->

$begin:s2

$end:s2 ->

$end

assignment
assign

$raise:s1 to

$begin:s2

end pattern
## Comando exit, sai de um la
co.
pattern Exit
var
:e as

[exit_stmt]

match
[stmt< :e >]
graph
$begin ->

$exit

end pattern
## Comando halt, sai da funcao.
pattern Halt
var
:h as

[halt_stmt]

match
[stmt< :h >]
graph
$begin ->

$exit

assignment
assign $begin to $exit
instrument
add halt $begin before self
add checkpoint $begin before self
end pattern
## Chamada de procedimento ou fun
c~
ao.
pattern ProcCall

137

Apendice C - Descric
ao do Delphi na IDeL (delphi.idel)
var
:p as

[proc_call]

match
[stmt< :p >]
graph
$begin ->

$end

end pattern
## Comando asm, permite usar c
odigo assembler.
pattern Asm
var
:a as

[asm_stmt]

match
[stmt< :a >]
graph
$begin ->

$end

end pattern
## Comando Inline, permite usar c
odigo assembler.
pattern InlineDirectr
var
:i as

[inline_directr]

match
[stmt< :i >]
graph
$begin ->

$end

end pattern
## Comando Inherited
pattern Inherited
var
:i as

[inherited_stmt]

match
[stmt< :i >]
graph
$begin ->

$end

end pattern
## Comando If...Then
pattern IfThen
var
:e as

[expr]

:s as

[stmt]

match
[stmt< if :e then :s >]
declare node $foo
graph
$begin ->

$end

$begin ->

$begin:s

$end:s ->

$end

assignment
assign $raise:s to

$exit

assign $definition:e to
assign $pusage:e to

$begin

$begin

138

Apendice C - Descric
ao do Delphi na IDeL (delphi.idel)
instrument
add checkpoint $begin before :e
add checkpoint $begin before self
add checkpoint $begin:s before :s
add checkpoint $end after self
end pattern
## Comando If...Then...Else
pattern IfThenElse
var
:e as

[expr]

:s1 as

[stmt]

:s2 as

[stmt]

match
[stmt< if :e then :s1 else :s2 >]
graph
$begin ->

$begin:s1

$begin ->

$begin:s2

$end:s1 ->

$end

$end:s2 ->

$end

assignment
assign $raise:s1 to

$exit

assign $raise:s2 to

$exit

assign $definition:e to
assign $pusage:e to

$begin

$begin

instrument
add checkpoint $begin before :e
add checkpoint $begin before self
add checkpoint $begin:s1 before :s1
add checkpoint $begin:s2 before :s2
add checkpoint $end after self
end pattern
## Comando While...Do
pattern While
var
:e as

[expr]

:s as

[stmt]

match
[stmt< while :e do :s >]
declare node $control
graph
$begin ->
$control ->
$end:s ->
$control ->

$control
$begin:s
$control
$end

assignment
assign $raise:s to

$exit

assign $break:s to

$end

assign $definition:e to
assign $pusage:e to

$control

$control

instrument
add checkpoint $begin before self
add checkpoint $begin:s before :s

139

Apendice C - Descric
ao do Delphi na IDeL (delphi.idel)
add checkpoint $end after self
add checkpoint $control before :e
end pattern
## Comando Repeat...Until
pattern RepeatUntil
var
:e as
:ss as

[expr]
[stmt_list]

match
[stmt< repeat :ss until :e >]
declare node $control
graph
$begin ->

$begin:ss

$end:ss ->

$control

$control ->

$begin:ss

$control ->

$end

assignment
assign $raise:ss to

$exit

assign $break:ss to

$end

assign $definition:e to
assign $pusage:e to

$control

$control

instrument
add checkpoint $begin before self
add checkpoint $begin:ss before :ss
add checkpoint $end after self
add checkpoint $control before :e
end pattern
## Comando For...To
pattern ForTo
var
:v as
:at as

[variable_reference]
[attrib_sign]

:einit as

[expr]

:e as

[expr]

:s as

[stmt]

match
[stmt< for :v :at :einit to :e do :s >]
declare node $control
declare node $initialization
declare node $increment
graph
$begin ->

$initialization

$initialization ->
$control ->
$control ->
$end:s ->

$control

$begin:s
$end
$increment

$increment ->

$control

assignment
assign $raise:s to

$exit

assign $definition:v to

$initialization

assign $cusage:einit to

$initialization

assign $cusage:e to

$increment

140

Apendice C - Descric
ao do Delphi na IDeL (delphi.idel)
assign $definition:v to
assign $pusage:v to
assign $break:s to

$increment

$control
$end

instrument
add checkpointfor $control before :e
add checkpoint $begin before self
add checkpoint $begin:s before :s
add checkpoint $end after self
end pattern
## Comando For...Downto
pattern ForDownto
var
:v as
:at as

[variable_reference]
[attrib_sign]

:einit as

[expr]

:e as

[expr]

:s as

[stmt]

match
[stmt< for :v :at :einit downto :e do :s >]
declare node $control
declare node $initialization
declare node $increment
graph
$begin ->

$initialization

$initialization ->

$control

$control ->

$begin:s

$control ->

$end

$end:s ->

$increment

$increment ->

$control

assignment
assign $raise:s to

$exit

assign $definition:v to

$initialization

assign $cusage:einit to

$initialization

assign $cusage:e to

$increment

assign $definition:v to
assign $pusage:v to
assign $break:s to

$increment

$control
$end

instrument
add checkpointfor $control before :e
add checkpoint $begin before self
add checkpoint $begin:s before :s
add checkpoint $end after self
end pattern
## Comando With sem par^
enteses
pattern With1
var
:vl as
:s as

[variable_list]
[stmt]

match
[stmt< with :vl do :s >]
graph
$begin ->

$begin:s

141

Apendice C - Descric
ao do Delphi na IDeL (delphi.idel)
$end:s ->

$end

assignment
assign $raise:s to

$exit

instrument
add checkpoint $begin before self
add checkpoint $end after self
end pattern
## Comando With com par^
enteses
pattern With2
var
:vl as
:s as

[variable_list]
[stmt]

match
[stmt< with ( :vl ) do :s >]
graph
$begin ->

$begin:s

$end:s ->

$end

assignment
assign $raise:s to

$exit

instrument
add checkpoint $begin before self
add checkpoint $end after self
end pattern
## Comando Case
pattern CaseStatement
var
:e as
:cl as
:s as

[expr]
[case_list]
[stmt_list]

match
[stmt< case :e of :cl else :s end >]
graph
$begin ->

$begin:cl

$begin ->

$begin:s

$end:cl ->
$end:s ->

$end
$end

assignment
assign $raise:s to
assign $pusage:e to

$exit
$begin

instrument
add checkpoint $begin before self
add checkpoint $begin:s before :s
add checkpoint $end after self
end pattern
## Lista de casos dentro do comando Case.
pattern CaseList
var
:cl as

[case_list]

match
[case_list< :cl >]
graph

142

Apendice C - Descric
ao do Delphi na IDeL (delphi.idel)
$begin ->

$begin:cl

$end:cl ->

$end

end pattern
## Cada caso dentro da lista de casos do comando Case.
pattern Case
var
:s as

[stmt]

:la as

[case_label_list]

match
[case< :la : :s >]
graph
$begin ->

$begin:s

$end:s ->

$end

assignment
assign $raise:s to

$exit

instrument
add checkpoint $begin:s before :s
end pattern
## Este passo encontra express~
oes que nao s~
ao usadas de forma
## predicativa e conecta os seus n
os begin e end.
step Expressions
## As express~
oes utilizadas nas atribuic~
oes n~
ao s~
ao usadas
## de forma predicativa, apenas uso computacional.
pattern Expression1
var
:v as

[variable_reference]

:at as
:e as

[attrib_sign]
[expr]

match
[stmt< :v :at :e >]
graph
$begin ->

$end

assignment
assign $definition:v to
assign $cusage:e to

$begin

$control

end pattern
## Este passo marca o uso e defini
co
~es de vari
aveis.
step Marks TB
## Ignora os identificadores que s~
ao utilizados como nome
## de fun
c~
oes ou procedimentos
pattern SkipFunction
var
:v as

[variable]

:args as

[expr_list]

match
[proc_call< :v ( :args ) >]
assignment
assign $cusage:v to

$null

assign $pusage:v to

$null

143

Apendice C - Descric
ao do Delphi na IDeL (delphi.idel)
end pattern
## Marca a defini
c~
ao de uma vari
avel em uma express~
ao de
## atribui
c~
ao.
pattern MarkExpression
var
:v as
:at as
:e as

[variable_reference]
[attrib_sign]
[expr]

match
[attribution< :v :at :e >]
graph
mark definition of :v at $definition
assignment
assign $cusage:v to

$null

assign $pusage:v to

$null

end pattern
## Marca a dereferencia
c~
ao de uma vari
avel.
pattern MarkDeref
var
:v as

[variable]

match
[variable< :v ^ >]
graph
mark definition of :v at $derefdefinition
assignment
assign $cusage:v to

$null

assign $pusage:v to

$null

end pattern
## Marca o uso de uma vari
avel.
pattern MarkUsage
var
:v as

[variable]

match
[variable_reference< :v >]
graph
mark cusage of :v at

$cusage

mark pusage of :v at

$pusage

mark definition of :v at

$parameterdefinition

end pattern
###############################################
#### Secao 3) Implementacao

####

###############################################
implementation
## Insere um checkpoint antes de uma expressao
implement
var
:e as [expr]
:n as

[constant]

checkpoint $node before

144

Apendice C - Descric
ao do Delphi na IDeL (delphi.idel)
[expr< :e >]
binding :n to node $node
as
[expr< check( :n ) and ( :e ) >]
end implement

implement
var
:e as [expr]
:n as

[constant]

checkpointfor $node before


[expr< :e >]
binding :n to node $node
as
[expr< checkfor( :n ) + ( :e ) >]
end implement

## Insere um checkpoint depois de um statement


implement
var
:s as

[stmt]

:n as

[constant]

checkpoint $node after


[stmt< :s >]
binding :n to node $node
as
[stmt< begin :s ; writeln ( TraceFile , :n ) end >]
end implement
## Insere um checkpoint antes de um statement
implement
var
:s as

[stmt]

:n as

[constant]

checkpoint $node before


[stmt< :s >]
binding :n to node $node
as
[stmt< begin writeln(TraceFile, :n); :s end >]
end implement
## Insere um checkpoint depois de uma lista de statements
implement
var
:s as

[stmt_list]

:n as

[constant]

checkpoint $node after


[stmt_list< :s >]
binding :n to node $node

145

Apendice C - Descric
ao do Delphi na IDeL (delphi.idel)
as
[stmt< begin :s; begin writeln(TraceFile, :n) end end >]
end implement
## Insere um checkpoint antes de uma lista de statements
implement
var
:s as

[stmt_list]

:n as

[constant]

checkpoint $node before


[stmt_list< :s >]
binding :n to node $node
as
[stmt< begin writeln(TraceFile , :n ); begin :s end end >]
end implement
## Fecha o arquivo antes de um halt.
implement
var
:h as

[halt_stmt]

halt $node before


[stmt< :h >]
as
[stmt< begin closefile(TraceFile) ; :h end>]
end implement
## Abre um arquivo de trace assim que comeca uma funcao e
## define a fun
c~
ao check, que serve para gravar no arquivo
## de trace.
implement
var
:head as

[name_impl]

:name as

[func_or_proc_or_method_name]

:type as

[proc_or_func_fptype]

:pars as

[fp_list]

:decl as
:ss as
:file as
:n as

[impl_decl_sect_list]
[stmt_list]
[string]

[constant]

init $init before


[main_impl< :head :name :pars :type ; :decl begin :ss end ; >]
binding :n to node $init
binding :file to literal [string< [:name].trace.tc >]
as
[main_impl<:head :name :pars :type ; :decl
var TraceFile : TextFile;
function check(n : integer) : boolean;
begin
writeln(TraceFile, n);
check := true;
end;
function checkfor(n : integer) : integer;

146

Apendice C - Descric
ao do Delphi na IDeL (delphi.idel)
begin
writeln(TraceFile, n);
checkfor := 0;
end;
begin
assignfile(TraceFile, :file);
if fileexists( :file ) then
reset ( TraceFile )
else
rewrite ( TraceFile );
append(TraceFile);
begin
:ss
end
end ;>]
end implement
## Fecha o arquivo assim que termina a funcao
implement
var
:head as

[name_impl]

:name as

[func_or_proc_or_method_name]

:type as

[proc_or_func_fptype]

:pars as

[fp_list]

:decl as
:ss as
:file as
:n as

[impl_decl_sect_list]
[stmt_list]
[string]

[constant]

exit $exit after


[main_impl< :head :name :pars :type ; :decl
var TraceFile : TextFile;
function check(n : integer) : boolean;
begin
writeln(TraceFile, n);
check := true;
end;
function checkfor(n : integer) : integer;
begin
writeln(TraceFile, n);
checkfor := 0;
end;
begin
assignfile(TraceFile, :file);
if fileexists( :file ) then
reset ( TraceFile )
else
rewrite ( TraceFile );
append(TraceFile);
begin
:ss

147

Apendice C - Descric
ao do Delphi na IDeL (delphi.idel)
end
end ; >]
binding :n to node $exit
binding :file to literal [string< [:name].trace.tc >]
as
[main_impl< :head :name :pars :type ; :decl
var TraceFile : TextFile;
function check(n : integer) : boolean;
begin
writeln(TraceFile, n);
check := true;
end;
function checkfor(n : integer) : integer;
begin
writeln(TraceFile, n);
checkfor := 0;
end;
begin
assignfile(TraceFile, :file);
if fileexists( :file ) then
reset ( TraceFile )
else
rewrite ( TraceFile );
append(TraceFile);
begin
:ss ;
writeln(TraceFile, ----------------);
closefile(TraceFile)
end
end ;>]
end implement
end instrumenter

148