INCLUDES


  Quando o programa que criamos se torna grande demais, fica incoveniente deixar todo o código no mesmo arquivo. Isto porque, passa a ficar difícil de entender o programa, bem como localizar e reaproveitar trechos de código.
  Dessa forma, é desejável que façamos algumas funções ou procedures em arquivos separados, agrupados por assunto, tornando-se mais fácil de se compreender e modificar. Além do mais, podemos usar as sub-rotinas que foram separadas em outros programas, sem ter a necessidade de localizar, recortar e colar trechos de um programa em outro programa. Para isso, basta incorporar rotinas já existentes ao novo projeto.
  O Pascal nos fornece esse recurso, chamado de "including files". Vamos adotar aqui, para este recurso, o nome de "include" da linguagem C.
  O objetivo de um include é de juntar dois ou mais arquivos em um só, em tempo de compilação. Esse recurso assemelha-se com o comando merge do Basic do MSX.

  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}
  O exemplo a seguir, ilustra o procedimento de "including files" do Pascal.

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: main.pas
{$i calcula.inc}

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

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

  O formato de arquivo de inclusão é do mesmo tipo de um arquivo fonte Pascal, ou seja, o formato texto. A extensão do arquivo poderá ser qualquer uma, inclusive ".pas". A extensão ".inc" foi adotada aqui para seguir o padrão do Lammassaari.

  O mesmo arquivo não poderá ser chamado pela directiva de inclusão {$i}, em um mesmo projeto, mais de uma vez. Senão, resulta em código duplicado e gera erro em tempo de compilação. Veja o exemplo abaixo:

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 includes do Lammassaari

  O programador de MSX Kari Lammassaari desenvolveu uma biblioteca de arquivos em Pascal, que contém códigos em assembly para funções específicas do MSX, como recursos gráficos, som, sistema etc.
  O repositório mais completo com os includes do Lammassaari é encontrado na Funet (atual msxarchive), na seção programming/pascal. Além disso, o Manuel Bilderbeek possui uma sessão sobre os includes do pascal. O ambiente de desenvolvimento em Pascal MSX Pad da Icongames, também possui diversos arquivos de includes do Lammassaari.
  Vamos pegar um desses arquivos de includes como exemplo. Escolhi 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.
  Vejamos a seguir, o conteúdo deste arquivo:
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 }
  Este arquivo contém uma procedure chamada "box", na qual inclui um código em assembly para desenhar uma "caixa" na tela gráfica do MSX. Ela faz uso do recurso "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). Esse código é executado imediatamente, quando a procedure inline() é invocada.

  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, o arquivo "box.inc" é incorporado, trazendo a procedure do Lammassaari que desenha retângulos na tela.
{$i box.inc}

begin
  Box(0,0,100,100,0);
end.
  No arquivo "box.inc", o Lammassaari "quebrou" a inline em linhas, para melhor visualizar o código em assembly. Isso pode ser feito para qualquer função ou procedure, desde que a sintaxe da declaração ou chamada da sub-rotina seja respeitada. Veja o exemplo para a procedure box() acima, que foi reescrita 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 include (.inc) e analisar as funções ou procedimentos existentes, seus nomes e parâmetros necessários para chamá-las.
  No caso exposto, a procedure 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 que eu apenas chamei a rotina do Lammassaari para desenhar o retângulo através da procedure box(). Não precisei saber qualquer coisa de assembly ou como desenhar um retângulo, pois ele já fez isso para mim.


/MARMSX/CURSOS/PASCAL