Curso de Pascal
Include


  Conforme o programa que estamos desenvolvendo se torna grande demais, o código começa a ficar difícil de se entender e gerenciar. Além disso, se não tomarmos o cuidado de organizar o código por assuntos, a situação piora mais ainda. Dessa forma, se pudermos separar e organizar trechos do nosso programa em arquivos distintos, melhoraria muito a legibilidade e organização do código do programa.
  O Pascal possui o recurso de incluir outros arquivos de código ao arquivo de código corrente, tornando possível essa solução. Esses arquivos são chamados de "including files" (arquivos de inclusão) e o recurso de inclusão é chamado de "include". O objetivo de um include é de juntar dois ou mais arquivos em um só em tempo de compilação, da mesma forma que o comando MERGE faz a junção de arquivos no Basic do MSX.

  Vejamos como funciona esse mecanismo. Seja o seguinte programa em Pascal.

Arquivo: main.pas
function calcula_produto(a, b : real) : real;
begin
  calcula_produto := a * b;
end;

begin
  writeln(calcula_produto(5,4));
end.

  A função "calcula_produto" poderia ser separada em outro arquivo com o nome de "calcula.inc" e depois ser incluída pelo programa principal "main.pas".

  Para se incluir um arquivo ao arquivo corrente, deve-se utilizar a directiva $i, seguida do nome do arquivo e dentro de chaves (nesse caso, não é comentário). Ex:
{$i arquivo.inc}

  Uma vez separados os arquivos, os códigos ficariam assim:

Arquivo: calcula.inc
function calcula_produto(a, b : real) : real;
begin
  calcula_produto := a * b;
end;

Arquivo: main.pas
{$i calcula.inc}

begin
  writeln(calcula_produto(5,4));
end.

  Ao compilar o programa "main.pas", o arquivo "calcula.inc" seria anexado e compilado como se fosse um código apenas. O código resultante é o mesmo do primeiro código apresentado.

  O formato do arquivo de inclusão também é texto como o arquivo fonte ".pas". A extensão do arquivo poderá ser qualquer uma inclusive o ".pas". A extensão ".inc" é utilizada para indicar que aquele código é um arquivo de inclusão e não um código principal.

  A vantagem de se utilizar arquivos de inclusão é o reuso de código, uma vez que outros programas também poderão incluir e utilizar as funções e procedimentos contidos nesse arquivo. É o caso das bibliotecas de MSX do Lammassaari.

  Obs: aconselha-se o uso de arquivos de inclusão quando tivermos programas mais complexos e desejarmos separar o código por assunto, ou quando criarmos rotinas que poderão ser aproveitadas por outros programas. No caso de programas simples e pequenos, o uso desse resurso é desnecessário.


  No próximo exemplo, iremos ver que o mesmo arquivo não poderá ser chamado pela directiva de inclusão {$i} no mesmo programa mais de uma vez, senão resultará em um código duplicado e gerará erro em tempo de compilação.

Códigos em separado Código unificado equivalente
Arquivo: calcula.inc
function calcula_produto(a, b : real) : real;
begin
  calcula_produto := a * b;
end;


Arquivo: formula.inc
{$i calcula.inc}

function formula(a, b, c : real) : real;
begin
  formula := calcula_produto(a,b) + c;
end;


Arquivo: main.pas
{$i calcula.inc}
{$i formula.inc}

begin
  writeln('Produto entre 5 e 4: ', calcula_produto(5, 4):2:1);
  writeln('O resultado da formula: ', formula(5, 4, 3):2:1);
end.
Arquivo: main.pas
function calcula_produto(a, b : real) : real;
begin
  calcula_produto := a * b;
end;

function calcula_produto(a, b : real) : real;
begin
  calcula_produto := a * b;
end;

function formula(a, b, c : real) : real;
begin
  formula := calcula_produto(a,b) + c;
end;

begin
  writeln('Produto entre 5 e 4: ', calcula_produto(5, 4):2:1);
  writeln('O resultado da formula: ', formula(5, 4, 3):2:1);
end.


  Para contornar esse problema, basta declarar os includes no arquivo principal, pois ele é o arquivo de mais alto nível do projeto (contém o corpo principal).

Códigos em separado Código unificado equivalente
Arquivo: calcula.inc
function calcula_produto(a, b : real) : real;
begin
  calcula_produto := a * b;
end;


Arquivo: formula.inc
function formula(a, b, c : real) : real;
begin
  formula := calcula_produto(a,b) + c;
end;


Arquivo: main.pas
{$i calcula.inc}
{$i formula.inc}

begin
  writeln('Produto entre 5 e 4: ', calcula_produto(5, 4):2:1);
  writeln('O resultado da formula: ', formula(5, 4, 3):2:1);
end.
Arquivo: main.pas
function calcula_produto(a, b : real) : real;
begin
  calcula_produto := a * b;
end;

function formula(a, b, c : real) : real;
begin
  formula := calcula_produto(a,b) + c;
end;

begin
  writeln('Produto entre 5 e 4: ', calcula_produto(5, 4):2:1);
  writeln('O resultado da formula: ', formula(5, 4, 3):2:1);
end.



  Biblioteca de MSX do Lammassaari

  O programador Kari Lammassaari desenvolveu e disponibilizou uma biblioteca de arquivos de inclusão em Pascal, contendo códigos em Assembly para funções específicas do MSX como recursos gráficos, sonoros, Joystick, E/S etc.
  Essa biblioteca pode ser encontrada nos seguintes locais:   A seguir será selecionado um arquivo de inclusão dessa biblioteca para ilustrar o seu uso. O arquivo escolhido foi o "box.inc", que desenha um retângulo na tela gráfica do MSX. O formato deste arquivo é texto, assim como um programa em Pascal.
  Ao editar o arquivo "box.inc", observamos o seguinte conteúdo:
Procedure Box(StartX,StartY,EndX,EndY:Integer;LogOp:Byte);
Var LOGOPER :Byte ABsolute $f570;
Begin
     LOGOPER := LogOp;
     Inline (
            $f3/
            $2a/EndX/           { LD HL,(STARTX) }
            $22/$B3/$FC/        { LD ($FCB3),HL }
            $2a/EndY/
            $22/$b5/$fc/
            $ed/$4b/StartX/     { LD BC,(ENDX) }
            $ed/$5b/StartY      { LD DE,(ENDY) }

            /$fd/$2a/$f7/$fa    { LD IY,(EXbrsa - 1 }
            /$DD/$21/$c9/$00    { LD IX,dobox }
            /$CD/$1c/00         { CALL CALSLT }
            /$fb
             );
      LOGOPER := 0;
End; { Box }
  Ele contém um procedimento chamado "Box", no qual inclui um código em Assembly para desenhar uma "caixa" na tela gráfica do MSX. Ela faz uso do comando "inline" para introduzir códigos em Assembly (código de máquina e não mnemônicos, como aqueles que aparecem ao lado das instruções só como comentário).

  Obs importante: A varável do tipo byte é declarada juntamente com a palavra reservada "absolute", seguido de um endereço em hexadecimal. O objetivo do "absolute" é declar explicitamente a localização em memória da variável criada, em vez disso ser feito automaticamente. Assim, a variável LOGOPER irá residir no endereço de memória $f570.

  No programa a seguir, os arquivos "box.inc" e "screen.inc" são incorporados, trazendo dois procedimentos do Lammassaari: um que desenha retângulos na tela e outro que modifica o modo de tela.
{$i screen.inc}
{$i box.inc}

begin
  Screen(5);
  Box(0,0,100,100,0);

  repeat until Keypressed;
  Screen(0);
end.

  No procedimento "Box" do arquivo de inclusão, o código em Assembly foi quebrado em linhas para ficar mais legível. Isso pode ser feito para qualquer função ou procedimento, desde que a sintaxe da declaração ou chamada da sub-rotina seja respeitada. Veja o exemplo para o procedimento "Box", que foi reescrito em linhas:
Box(
    0,    { Coordenada X inicial }
    0,    { Coordenada Y inicial }
    100,  { Coordenada X final }
    100,  { Coordenada Y final }
    0);   { Operação lógica }

  Uma vez que não há uma documentação completa para essas sub-rotinas do Lammassaari, a melhor solução para o programador descobrir qual é a rotina mais indicada para resolver seu problema, é abrir os arquivos de inclusão ".inc" e analisar as funções ou procedimentos existentes, seus nomes e parâmetros necessários para chamá-los.
  No caso exposto, o procedimento chama-se "Box" e nome nos indica o que ele faz, ou seja, desenhar um retângulo.
  Analisando-se os parâmetros da procedure box, temos:   Os valores dos parâmetros utilizados no chamamento da procedure foram: 0 para X inicial, 0 para Y inicial, 100 para X final, 100 para Y final, e 0 para a operação lógica.

  Obs 1: Conforme dito na primeira aula, o include junta dois arquivos e não tem a capacidade de isolar os módulos. Assim, se eu resolvesse fazer outra procedure de desenho de retângulo e também a chamasse de "Box", um erro aconteceria. Isso porque passariam a existir duas procedures chamadas "Box". A sugestão seria chamar a nova procedure de "Box2", para diferenciar da primeira.
  Obs 2: Note foi apenas foi chamada a rotina do Lammassaari para desenhar o retângulo através do procedimento "Box". Não foi necessário qualquer conhecimento em Assembly ou saber como desenhar um retângulo, pois o procedimento já faz isso para a gente. A isso chamamos de transparência.


<< Anterior Pascal Próxima >>


/MARMSX/CURSOS/PASCAL