Tivoli Service Desk 6.0 Developer's Toolkit - Guia de Programação do Script

Capítulo 4: Componentes da Base de Informações

Retornar ao Índice


Introdução

O Developer's Toolkit permite agrupar instruções em rotinas e compactá-las nas bases de informações reutilizáveis (ou módulos). Esta característica modular atenua a dificuldade de manter quantidades grandes de código fonte.

Este capítulo abrange os fundamentos necessários para entender e construir aplicativos de multi-base de informações.

A seção ROUTINES

A palavra-chave ROUTINES é utilizada para introduzir qualquer seção de uma base de informações que contém subrotinas ou procedimentos.

Como localizar ROUTINES na seção pública

Na seção pública entre o cabeçalho KNOWLEDGEBASE e a palavra-chave PRIVATE, a seção de rotinas contém as declarações de procedimentos e funções que são implementadas na seção particular.

Como utilizar ROUTINES na seção particular

Na seção particular, a palavra-chave ROUTINES é acompanhada pelas implementações da função e dos procedimentos completos.
Um exemplo é mostrado abaixo:

KNOWLEDGEBASE Print; 
TYPES 
    EmployeeRecord IS RECORD 
       first_name, last_name: String; 
      employee_ID: String; 
      hireDate : Date;
      salary : Real;
END; 
ROUTINES 
    PrintEmployee(REF e: EmployeeRecord); 
PRIVATE 
ROUTINES 
    PROCEDURE PrintString(VAL s: String) IS 
ACTIONS 
      ... 
END; 
PROCEDURE PrintEmployee(REF e: EmployeeRecord) IS 
ACTIONS 
    PrintString(e.first_name); 
    PrintString(e.last_name); 
      ... 
END;

A seção USES

Cada arquivo de base de informações do Developer's Toolkit consiste em duas seções principais.

Exemplo

No exemplo a seguir, há uma base de informações chamada Statistics (contida no arquivo statisti.kb) que é utilizada por outra base de informações chamada Application (no arquivo (applicat.kb)):

KNOWLEDGEBASE Statistics;
ROUTINES
    PROCEDURE Regression;
    PROCEDURE TimeSeries;
    PROCEDURE ChiSquare;
...
KNOWLEDGEBASE Application;
...
PRIVATE
    USES
    Statistics;
...

Declarando Statistics em sua seção Uses, as rotinas em Application serão capazes de chamar os três procedimentos definidos por Statistics.

Como introduzir a seção USES

A seção Uses é apresentada pela palavra-chave USES e deve ser colocada em um (ou ambos) destes locais:

Como utilizar várias bases de informações

Uma base de informações pode utilizar tantas outras bases de informações quantas forem necessárias. Cada base de informações utilizada deve ser listada na seção Uses e deve ser seguida por um ponto e vírgula:

KNOWLEDGEBASE User;
...
PRIVATE
    USES
    Used1;
    Used2;
    ...
    Used99;

Como utilizar uma base de informações privadamente

Uma base de informações é utilizada privadamente quando está contida na instrução USES, na seção particular de uma base de informações.

Quando uma base de informações é utilizada privadamente, suas variáveis e procedimentos públicos estarão disponíveis através da seção particular para a implementação das rotinas declaradas na seção pública. Em outras palavras, a implementação particular da base de informações pode ser composta por rotinas públicas de outra base de informações.

Duas bases de informações podem utilizar uma a outra privadamente sem restrição, visto que elas se nomeiem mutuamente na seção particular. Ou seja, a Base de Informações A pode utilizar a Base de Informações B, e vice-versa.

Como utilizar uma base de informações publicamente

Uma base de informações é utilizada publicamente quando está contida na instrução USES, na seção pública de uma base de informações.

Quando uma base de informações é utilizada publicamente, os símbolos da base de informações utilizados estão disponíveis através de toda a base de informações.

Você deve utilizar uma base de informações publicamente quando símbolos desta base de informações forem necessários para alguma declaração pública na utilização da base de informações.
Um exemplo disso é quando um tipo de registro definido em uma base de informações for utilizado em uma declaração de tipo de registro diferente.

Utilização cíclica de bases de informações públicas

O uso cíclico ocorre quando a Base de Informações A utiliza a Base de Informações B e vice-versa. As bases de informações não podem utilizar uma a outra ciclicamente na seção PUBLIC.

Uma maneira de evitar esta limitação é mover as declarações comuns necessárias para ambas bases de informações para uma base de informações separada que em si não utiliza nada publicamente. Isso nem sempre é viável, pois pode não fazer sentido combinar declarações para funções muito diferentes em uma base de informações. Às vezes, entretanto, esta solução funciona.

Como exemplo, suponha que você crie um programa que rastreia informações referente a empregados e o departamento em que trabalham. Você deseja encapsular a maioria das informações relativas aos empregados em uma base de informações chamada "Employee" e as informações relativas aos departamentos em uma base de informações chamada "Department."

Entretanto, as rotinas públicas que manipulam os registros dos empregados, algumas vezes, requerem os registros de departamento como parâmetros, e vice-versa. Portanto, há uma necessidade das duas bases de informações utilizarem uma a outra publicamente. Pelo fato disso não funcionar, as bases de informações devem ser organizadas conforme mostrado no exemplo a seguir:

KNOWLEDGEBASE EmplType;
TYPES
        Employee IS RECORD
        ...
END;
    ...
END;
KNOWLEDGEBASE DeptType;
TYPES
        Department IS RECORD
        ...
END;
    ...
END;
KNOWLEDGEBASE Employee;
    USES
        EmplType;
        DeptType;
ROUTINES
        PROCEDURE AddEmployee (VAL lst: LIST OF Employee,
                               REF dept: Department);
...
PRIVATE
...
END;
KNOWLEDGEBASE Department;
    USES
        EmplType;
        DeptType;
ROUTINES
    PROCEDURE AssignOffice (REF dept: Department, REF empl:
                   Employee);
...
PRIVATE
END;

Procedimentos

Procedimento é uma coleção de instruções do Developer's Toolkit que são mencionadas pelo nome e que não retornam um valor ao responsável pela chamada.

Procedimento é um bloco que está aninhado dentro da base de informações. Da mesma forma que a própria base de informações, um procedimento pode ter seções de constantes, variáveis e rotinas. Identificadores nestas seções são locais para o procedimento e não são visíveis fora dele.

Cada procedimento possui uma seção de ações que é a localização para as instruções executáveis do Developer's Toolkit, as quais determinam qual procedimento realizar.

Exemplos

O formulário geral para um procedimento é mostrado abaixo:

PROCEDURE <procedure-name>(<formal-parameter-list>) IS 
CONSTANTS 
  <constant-declarations> 
TYPES 
  <type-declarations> 
VARIABLES 
  <variable-declarations>
ROUTINES 
  <subroutine-implementations>
ACTIONS 
  <KML statement-list>
END;

A seguir, há um procedimento simples com uma seção de ações que contém duas instruções do Developer's Toolkit. Quando este procedimento for chamado. as duas instruções na seção de ações serão executadas:

PROCEDURE CopyrightMessage; 
ACTIONS 
  WinWriteLN($DeskTop,'Copyright 1996 by'); 
  WinWriteLN($DeskTop,'Software Artistry, Inc.'); 
END; 

Como utilizar variáveis locais com variáveis aninhadas

Geralmente, é útil a um procedimento conter variáveis locais em uma seção de variáveis aninhadas. As variáveis locais são variáveis de programa cujo escopo é limitado a um bloco de código específico. Como regra, as variáveis locais são confinadas a uma subrotina.

O exemplo seguinte, cria um procedimento chamado WriteTenLines. O procedimento utiliza uma variável local chamada i para se repetir através de um loop FOR e escrever 10 cadeias em uma janela:

PROCEDURE WriteTenLines; 
VARIABLES 
       i: Integer; 
ACTIONS 
  FOR i:=1 TO 10 DO 
    WinWriteLn(myWindow,''); 
END; 
END; 

Este exemplo é mais avançado para incluir uma constante local:

PROCEDURE WriteTenLines; 
CONSTANTS 
  MAX_LINES IS 10; 
VARIABLES 
       i: Integer; 
ACTIONS 
  FOR i:=1 TO MAX_LINES DO 
    WinWriteLn(myWindow,''); 
END; 
END; 

Como criar rotinas locais

Geralmente é desejável criar rotinas locais, particularmente se a variável que se quer utilizar ocorre somente em uma parte de um programa. As rotinas locais procedimentos ou funções declaradas dentro de outro procedimento ou função. Uma rotina local pode ser chamada apenas pelo procedimento ou pela função que a contém ou por outras rotinas locais contidas nela. Veja o exemplo:

PROCEDURE PrintEmployeeInfo(REF e: EmployeeRecord) IS 
ROUTINES 
  PROCEDURE PrintDemographics IS 
ACTIONS 
    PrintString(e.first_name); 
    PrintString(e.last_name); 
    PrintString(e.ssn); 
END; 
  PROCEDURE PrintManages IS 
ACTIONS 
    FOR e.manages DO 
      PrintString(e.manages[$Current]); 
END; 
END; 
ACTIONS 
  PrintDemographics; 
  PrintManages; 
END;

Escopo

Um dos assuntos conceituais importantes em linguagens estruturadas em bloco é o escopo. Dentro de um determinado bloco, existem somente alguns identificadores, ou estão no escopo. Em geral, os blocos aninhados podem "ver" identificadores declarados em um escopo de inclusão. Um objeto ou identificador em um escopo de inclusão é local somente para este bloco.

Exemplo de escopo

Considere o seguinte exemplo:

KNOWLEDGEBASE Scope; 
CONSTANTS 
    MAX_EMPLOYEES IS 500; 
TYPES 
    EmployeeRecord IS RECORD 
       first_name, last_name: String; 
END; 
VARIABLES 
    employeeList: List of EmployeeRecord; 
PRIVATE 
CONSTANTS 
    ARRAY_SIZE IS 1000; 
VARIABLES 
    employeeArray[ARRAY_SIZE]: ARRAY OF EmployeeRecord; 
ROUTINES 
    PROCEDURE ProcTwo IS 
VARIABLES 
       i: Integer; 
ACTIONS 
       ... 
END; 
      PROCEDURE ProcOne IS 
VARIABLES 
        i: String; 
        j: Integer; 
ACTIONS 
        ... 
END; 

Explicação do exemplo de escopo

MAX_EMPLOYEES, EmployeeRecord e employeeList são visíveis em toda base de informações pois são declarados no bloco mais externo. Estes elementos aparecem em uma seção pública da base de informações, dessa forma, são visíveis para outras bases de informações que utilizam esta base de informações.

De forma semelhante, devido ao fato de ARRAY_SIZE e employeeArray serem declarados na seção particular do bloco mais externo, eles são visíveis em toda a seção particular. Tanto ProcTwo quanto ProcOne podem se referir a estes identificadores, mas porque estão na seção particular, nenhuma outra base de informações poderá acessá-los.

A variável i em ProcTwo é visível apenas em ProcTwo. As variáveis i e j em ProcOne são visíveis apenas em ProcOne. A variável i em ProcOne é completamente não relacionada a variável i em ProcTwo.

Os valores de variáveis existirão somente enquanto o bloco no qual estão inclusos for executado. Por exemplo, as variáveis i e j possuem valores somente durante a execução de ProcOne.

Transmissão de Parâmetros

Como transmitir informações para um procedimento

Ao chamar procedimentos, geralmente é necessário passar informações para eles.
Isso pode ser realizado com as seguintes etapas:

    PROCEDURE ComputePercent (VAL Dividend : INTERGER,
                             VAL Divisor : INTEGER,
                             REF Quotient : INTEGER) IS
                (*parameter to PROCEDURE ComputePercent*) 
    ACTIONS
          Quotient := Dividend/Divisor*100;
END;

Quando o procedimento é chamado, o número de expressões passadas iguala-se ao número de parâmetros declarados no procedimento. As expressões passadas devem ter o mesmo tipo de dados e tipo de parâmetro que os parâmetros especificados.

    VARIABLES
    (*Compute the percentage of cars of differing colors
    in a garage*)
         NumBrownCars : INTEGER;
         NumBlackCars : INTEGER;
         NumMixedCars : INTEGER;
         TotalCars : INTEGER;
         PercentBrownCars : INTEGER;
         PercentBlackCars : INTEGER;
         PercentMixedCars : INTEGER;
ACTIONS
    (*Expressions passed to compute the percentage of 
    cars of differing colors in a garage*)
         ComputePercent (NumBrownCars, TotalCars,
                         PercentBrownCars);
         ComputePercent (NumBlackCars, TotalCars,
                         PercentBlackCars);
         ComputePercent (NumMixedCars, TotalCars,
                         PercentMixedCars);
    End;

Como passar por REF ou VAL

No exemplo a seguir, observe que alguns parâmetros são passados pelo valor (VAL) e alguns pela referência (REF).

Em um parâmetro VAL, um valor é copiado do responsável pela chamada para a rotina chamada e nada que a rotina chamada faz afetará o valor que o responsável pela chamada ainda possui.

Um parâmetro REF endereça o mesmo armazenamento que o responsável pela chamada possui. Desse modo, as alterações no valor do parâmetro que ocorrem durante o curso da rotina chamada se efetivarão imediatamente no valor do responsável pela chamada.

Exemplo

Considere o seguinte exemplo:

ROUTINES 
  PROCEDURE DistanceFormula(VAL x1, y1, x2, y2: 
      Integer, REF distance: REAL) IS 
ACTIONS 
    distance:=Sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)); 
END; 
  PROCEDURE ComputeDistances IS 
VARIABLES 
    distance: Real; 
ACTIONS 
    DistanceFormula(1,1,9,9,distance); 
    WinWriteLN(myWindow,'The distance is ' & 
      distance); 
    DistanceFormula(9,9,15,87,distance); 
    WinWriteLN(myWindow,'The distance is ' & 
      distance); 
END; 

Explicação do exemplo

No exemplo anterior, um procedimento chamado DistanceFormula foi declarado.

O procedimento possui cinco argumentos formais:

Quando o procedimento é chamado, cópias dos primeiros quatro valores de inteiro passados são enviados ao procedimento. Entretanto, no caso do quinto parâmetro, a variável real enviada pelo responsável pela chamada é passada ao procedimento.

Se um procedimento esperar um parâmetro passado pelo valor, o responsável pela chamada pode enviar uma:

Entretanto , se o procedimento esperar que um parâmetro seja passado por referência, o responsável pela chamada pode enviar apenas uma variável.

Como tratar parâmetros como variáveis

Um procedimento pode tratar todos os parâmetros passados a ele como variáveis. Ele pode:

As alterações feitas em parâmetros passados por valor não são transmitidas de volta para o responsável pela chamada.

No exemplo anterior, ComputeDistances enviou valores literais dos quatro argumentos inteiros para DistanceFormula porque os parâmetros correspondentes foram declarados com a palavra-chave VAL. Contudo, ComputeDistances passou somente uma variável ao quinto argumento porque o quinto parâmetro foi declarado com a palavra-chave REF.

Nota: Não há nenhum tipo de parâmetro padrão. Você deve especificar VAL ou REF para cada parâmetro em uma declaração de procedimento.

Funções

As funções são idênticas aos procedimentos, exceto que retornam um valor ao responsável pela chamada. Por esta razão, as funções podem ser utilizadas somente em atribuições ou expressões. Elas não podem ser utilizadas como instruções.

As funções podem retornar tipos simples (como cadeias, inteiros, reais, valores Booleanos, datas e horas), bem como tipos estruturados e tipos definidos pelo usuário.

Você também pode escrever uma função que retorna uma lista de registros.

Formato da função

As funções possuem o seguinte formato geral:

FUNCTION <function-name>(<formal-parameter-list>): <Type> IS 
CONSTANTS 
  <constant-declarations> 
TYPES 
  <type-declarations> 
VARIABLES 
  <variable-declarations>
ROUTINES 
  <subroutine-implementations>
ACTIONS 
  <KML statement-list>
END; 

Exemplo de função

O seguinte exemplo altera DistanceFormula para que seja uma função em vez de um procedimento:

ROUTINES 
FUNCTION DistanceFormula(VAL x1, y1, x2, y2: 
    Integer): REAL IS 
ACTIONS 
    Exit Sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)); 
END; 
  PROCEDURE ComputeDistances IS 
VARIABLES 
    distance: Real; 
ACTIONS 
    distance:=DistanceFormula(1,1,9,9); 
    WinWriteLN(myWindow,'The distance is ' & 
      distance); 
    distance:=DistanceFormula(9,9,15,87); 
    WinWriteLN(myWindow,'The distance is ' & 
      distance); 
END; 

Nota: Cada função deve ter um tipo de retorno explícito que segue a lista de parâmetros e seja separado dela por dois pontos.

Como utilizar $Result

$Result pode ser utilizado dentro do corpo de uma função para acessar o valor de retorno atual desta função. Você pode definir ou testá-lo dentro do corpo da função.

Considere a seguinte alteração para DistanceFormula:

FUNCTION DistanceFormula(VAL x1, y1, x2, y2: 
    Integer): REAL IS 
ACTIONS 
  $Result := Sqrt((x2-x1)*(x2-x1) + (y2-y1)*
                 (y2-y1)); 
END; 

Neste exemplo, o valor de retorno da função é definido com $Result.

$Result pode ser atribuído muitas vezes em um corpo da função. $Result automaticamente possui o tipo de dados declarado no valor de retorno da função.

Como utilizar Exit com as funções

Exit, quando utilizado com a função, faz com que:

Quando você utiliza uma instrução Exit dentro de uma função, você pode fornecer-lhe um parâmetro que indica o valor que deseja retornado.

Exit (42); 

é o mesmo que:

$Result := 42;
      Exit;

Se uma função é encerrada sem a utilização da instrução Exit, será retornado um valor $Unknown.

Exit combina as tarefas que:

Como Chamar Procedimentos e Funções da Biblioteca

Acesso às rotinas escritas em C ou C++ a partir de uma programa escrito no Developer's Toolkit é fornecido pelo mecanismo de rotina externa do Developer's Toolkit.

Uma rotina externa consiste em duas partes:

Sintaxe da declaração do Developer's Toolkit

Começando com o Developer's Toolkit 4.2, a sintaxe declarativa do Developer's Toolkit suporta a maioria dos requisitos de interface sem uma compreensão extensiva das estruturas de dados do Developer's Toolkit.

Para chamar uma rotina externa, o Interpretador do Developer's Toolkit deve ter uma declaração da rotina que informe:

Sintaxe da rotina externa

A sintaxe de uma declaração de rotina externa é mostrada no seguinte exemplo. Como em qualquer implementação de rotina do Developer's Toolkit, estas declarações podem aparecer somente na seção particular de uma base de informações do Developer's Toolkit.

FUNCTION name [(VAL|REF parameter : type [, ...])] : type
    IS EXTERNAL dll_name [, entry_point][, linkage];
PROCEDURE name [(VAL|REF parameter : type [, ... ])]
    IS EXTERNAL dll_name [, entry_point][, linkage];

O nome DLL é uma expressão de cadeia de constante que identifica a biblioteca na qual a rotina externa está localizada. A extensão .dll usualmente é diferente em uma base por plataforma e geralmente é omitida do nome fornecido.

Pontos de entrada

Os pontos de entrada são localizações dentro de um programa ou rotina onde pode se iniciar a execução. Normalmente, uma rotina possui apenas um ponto de entrada. O ponto de entrada pode ser uma:

Uma cadeia representa o nome de um ponto de entrada e um inteiro representa seu número ordinal na biblioteca.

Como construir o nome de uma função

Os compiladores C++ comumente utilizam uma técnica conhecida como 'name mangling' que garante a ligação correta entre os módulos de objetos compilados pelo separador.
As funções externas escritas em C++ geralmente devem ser declaradas "C" externo no código fonte C++ ou ser carregadas por seu número ordinal.

Especificações de ligação

A especificação de ligação em uma declaração de rotina externa deve ser um dos seguintes símbolos:

Nota: O recurso de chamada de DLL do Developer's Toolkit irá falhar nos argumentos "passar por referência" se o DLL sendo chamado não foi compilado com o Microsoft Visual C++.

Para IBM C++ no OS/2, o protocolo é _Optlink._

Para OS/2, o protocolo é _System.

Se a especificação de ligação for completamente omitida de uma declaração de rotina externa, a ligação será padronizada como $STANDARD.

Para todos os sistemas operacionais UNIX, a convenção é específica para compilação. Se sua biblioteca foi escrita em C ou C++, utilize $C. Caso contrário, utilize $System.

Tipos de parâmetros simples para rotinas externas

Para facilitar o uso de bibliotecas de terceiros, o TSD Script fornece uma quantidade de nomes de tipos predefinidos que mapeiam diretamente aos tipos C/C++ simples.

TYPES
SHORT    IS INTEGER: INT(2)  DEFAULT($ERROR);
USHORT   IS INTEGER: UINT(2) DEFAULT($ERROR);
LONG     IS INTEGER: INT(4)  DEFAULT($ERROR);
ULONG    IS INTEGER: UINT(4) DEFAULT($ERROR);
PSZ      IS STRING : POINTER DEFAULT(0);
FLOAT    IS REAL   : FLOAT(4) DEFAULT($ERROR);
DOUBLE   IS REAL   : FLOAT(8) DEFAULT($ERROR); 

Os tipos SHORT, USHORT, LONG, ULONG, PSZ, FLOAT e DOUBLE são fornecidos na base de informações do sistema encontrada no arquivo TSD Script.KB.

Como mapear tipos de DLL externo

Os tipos de DLL externos são mapeados pelo TSD Script para os tipos de dados de nível inferior mais comuns utilizados em C e C++. A sintaxe declarativa extra informa ao Interpretador do TSD Script como mapear os dados.

Por exemplo, a declaração de SHORT diz que o valor deve ser compactado em um inteiro de dois bytes. A declaração Default indica que $Unknown provoca um erro no tempo de execução se for feita uma tentativa de passá-lo para uma rotina externa através do parâmetro SHORT.

A declaração de PSZ diz que o valor deve ser compactado como um ponteiro, e que $Unknown deve ser passado como um ponteiro zero (NULL).

Aqui está um exemplo de como você pode declarar a função ExitWindows, fornecida pelo Microsoft Windows:

FUNCTION ExitWindows (VAL reserved: INTEGER,
                      VAL returnCode: INTEGER ): BOOLEAN
IS EXTERNAL `USER.EXE', `ExitWindows', $SYSTEM;

Nota: Um "inteiro" do TSD Script é um valor longo (32-bit) e "int" nem sempre funciona em C.

Transmissão de Parâmetros para Rotinas Externas

Da mesma forma que os parâmetros das rotinas normais do TSD Script, os parâmetros das rotinas externas são especificados conforme são passados pelo:

Parâmetros VAL

Os parâmetros VAL para rotinas externas se comportam muito parecidas com os parâmetros VAL em rotinas não-externas.

O valor é copiado do responsável pela chamada para a rotina chamada e nada que a rotina chamada faz afetará o valor que o responsável pela chamada ainda possui.

Uma cadeia que é passada por VAL também é retida pela rotina externa como um ponteiro que endereça uma localização de memória temporária na qual a cadeia de TSD Script foi copiada.

Parâmetros REF

Os parâmetros REF pouco diferem dos parâmetros VAL para rotinas externas.

Quando uma rotina não-externa retém um parâmetro REF, ele endereça a mesma memória que o responsável pela chamada possui. Quaisquer alterações no valor do parâmetro durante a rotina chamada será efetivada imediatamente no valor do responsável pela chamada.

A passagem por referência em uma rotina externa é realmente implementada como cópia interna/cópia externa. A diferença é sutil, mas sob algumas circunstâncias, o procedimento é detectável. Por exemplo, o envio de uma mensagem a partir de uma rotina externa é um exemplo desse procedimento.

O tipo de dados STRING (e aliases, como PSZ) é uma exceção e é passado por um ponteiro para o valor de cadeia real do TSD Script quando passado pelo REF.

Todos os parâmetros REF são passados para as rotinas externas C ou C++ como ponteiros. O TSD Script não tenta suportar a noção de referências do C++. Se precisar chamar uma rotina C++ que toma parâmetros de referência, você poderá escrever uma função de wrapper pequena. O wrapper obtém um ponteiro do TSD Script, faz referência a ele e passa-o junto à função C++ exigida.

Devido ao TSD Script não suportar diretamente a noção de constante C e C++ do ANSI, os programadores do TSD Script comumente declaram um parâmetro como REF quando a função C/C++ obtém um argumento de ponteiro de constante.

Como converter dados

A passagem de dados entre o TSD Script e uma rotina externa freqüentemente requer que os dados sejam convertidos em um formato alternativo. Antes da rotina externa ser chamada, o valor do responsável pela chamada será:

Se o parâmetro for REF, então, após o responsável pela chamada retornar, a área temporária será descompactada novamente na memória do responsável pela chamada.

Estruturas de dados e compactação de binário

Embora você possa construir interfaces completamente elaboradas utilizando os tipos simples, eventualmente será conveniente você passar estruturas de dados agregados para uma rotina externa.
O Developer's Toolkit 4.2 incluiu nova sintaxe ao TSD Script que permite a especificação explícita que detalha como os dados do TSD Script são mapeados para as estruturas de dados C ou C++. Este mapeamento será referido daqui em diante como compactação binária.

As informações sobre a compactação binária são fornecidas como uma anotação para a especificação do tipo em uma declaração de tipo nomeada ou em uma especificação de campo dentro de uma declaração de registro. A sintaxe total para ambas é mostrada abaixo.

TYPES
type_name IS type : annotation ... ;
type_name IS RECORD
[ field_name : type ] [ : annotation ... ] ; ...
END;

Formato da anotação de dados

As seguintes anotações especificam o formato em que os dados do TSD são compactados. Todos eles são mutuamente exclusivos.

Anotação Descrição
INT(largura) A anotação INT especifica que o campo foi compactado no formato de inteiro nativo com a largura especificada. Os valores legais para a largura são 1, 2 e 4. Qualquer tipo de dados do TSD Script que podem ser explicitamente convertidos para INTEGER podem ser compactados como INT.
UINT(largura) A anotação UINT especifica que o campo foi compactado no formato de inteiro nativo como um valor sem assinatura com a largura especificada. Ao passar um valor do TSD Script para uma rotina externa, não haverá diferença significativa entre INT e UINT, porque nos dois casos é passado o mesmo padrão de bit. Entretanto, quando um valor de 1 ou 2 bytes é passado de volta ao TSD Script a partir de uma rotina externa, a distinção entre INT/UINT determina como o valor será estendido por sinal. Novamente, os valores legais para a largura são 1, 2 e 4.
NUMERIC(largura) Os campos com a anotação NUMERIC são compactados como uma seqüência de caracteres preenchidas em branco com a largura determinada. Os Reais e Inteiros do TSD Script e qualquer outro tipo de dados que possam ser convertidos em Inteiro poderão ser compactados como um campo NUMERIC.
FLOAT(largura) Os campos com a anotação FLOAT são compactados como um número de ponto flutuante IEEE com a largura especificada. As larguras válidas são 4 e 8. Qualquer tipo do TSD Script que possa ser explicitamente convertido em REAL poderá ser compactado como um FLOAT.
BCD(largura) Os campos com a anotação BCD são compactados como Notação Decimal Codificada em Binário. Qualquer tipo do TSD Script que possa ser explicitamente convertido em REAL poderá ser compactado como um BCD.
CHAR (largura) Os campos com a anotação CHAR são compactados como uma matriz de caracteres simples com a largura determinada. Qualquer tipo do TSD Script que possa ser convertido em STRING poderá ser compactado como CHAR.
ZSTRING(largura) Os campos com a anotação ZSTRING são compactados como uma cadeia terminada como nulo (estilo C) com a largura determinada. Qualquer tipo de dados do TSD Script que possa ser convertido em STRING poderá ser compactado como ZSTRING.
LSTRING(largura) Os campos com a anotação LSTRING são compactados como uma cadeia de estilo Pascal, com um byte contendo o comprimento da cadeia. Qualquer tipo do TSD Script que possa ser convertido em STRING poderá ser compactado como LSTRING.
ASE_DATE Os campos com a anotação ASE_DATE são compactados como uma estrutura DATEREC. Qualquer tipo de dados que possa ser explicitamente convertido em DATE poderá ser compactado como um ASE_DATE.
BTRV_DATE Os campos com a anotação BTRV_DATE são compactados como dados de estilo Btrieve. Qualquer tipo de dados que possa ser explicitamente convertido em DATE poderá ser compactado como um BTRV_DATE.
CCYYMMDD Os campos com a anotação CCYYMMDD são compactados como uma cadeia de caracteres contendo o século, ano, mês e dia, cada um compactado em dois bytes. Qualquer tipo que possa ser explicitamente convertido em DATE poderá ser compactado como um CCYYMMDD.
ASE_TIME Os campos com a anotação ASE_TIME são compactados como uma estrutura TIMEREC. Qualquer tipo de dados que possa ser explicitamente convertido em TIME poderá ser compactado como um ASE_TIME.
BTRV_TIME Os campos com a anotação BTRV_TIME são compactados como uma hora em estilo Btrieve. Qualquer tipo de dados que possa ser explicitamente convertido em TIME poderá ser compactado com um BTRV_TIME.
HHMMSS Os campos com a anotação HHMMSS são compactados como uma cadeia de caracteres contendo hora, minuto e segundo, cada um compactado em dois bytes. Qualquer tipo de dados que possa ser explicitamente convertido em TIME poderá ser compactado como um HHMMSS.
POINTER Os campos com a anotação POINTER são compactados como um ponteiro de 32-bit os dados reais do TSD Script. Qualquer um dos tipos de dados não-agregados em TSD Script pode ser compactado como POINTER.
NOEXPORT A anotação NOEXPORT marca um campo que, de modo algum, não está incluído na representação binária externa. Qualquer tipo de campo pode ser marcado NOEXPORT

Anotação do valor padrão

Além de uma anotação de formatação, uma anotação de valor padrão pode ser especificada. A anotação de valor padrão instrui o Interpretador do TSD Script como preencher o campo na estrutura binária quando o valor do TSD Script for desconhecido. A sintaxe da anotação do valor padrão é:

DEFAULT( $ERROR|expression ) 

Quando $ERROR é especificado, a compactação de um valor desconhecido faz com que o Interpretador do TSD Script exiba uma mensagem de erro e aborte a rotina externa.

Este é o padrão quando nenhuma anotação de valor é especificada.

Quando uma expressão é especificada, esta expressão é avaliada e seu valor compactado de acordo com a anotação de formatação, quando o valor do TSD Script é desconhecido. Este recurso é utilizado para mapear cadeias desconhecidas para NULL.

Anotações sobre compactação

Em uma seqüência de especificações de campo, você pode fornecer anotações sobre compactação sem qualquer tipo de dados ou nome de campo correspondente. Estas anotações especificam campos na estrutura binária que não aparecem no registro do TSD Script. Isso ocorre devido aos próprios campos não aparecerem no registro do TSD Script. É necessário que você forneça uma anotação adicional com o valor para este campo.

A sintaxe para esta anotação especial é

Cada vez que o campo é compactado, uma determinada expressão é avaliada e, em seguida, compactada de acordo com a anotação de formatação correspondente.

Anotações FILL

Finalmente, com objetivos de alinhamento do campo, a anotação FILL pode ser utilizada para colocar um número arbitrário de bytes de preenchimento entre os campos na estrutura binária.

A sintaxe da anotação FILL é

FILL( largura [ , valor ] ) 

O número de bytes especificado pela largura, e aqueles contendo o valor determinado, são compactados na estrutura binária. Embora qualquer valor de inteiro de constante possa ser especificado para a anotação FILL, os bytes reais compactados contêm somente 8 bits menos significativos, assim, -128 a 255 representam o intervalo útil de valores. O valor padrão é zero.

Os tipos e campos nomeados sem anotações de compactação explícita são compactados de acordo com o padrão para seus tipos de base.
A tabela a seguir indica os padrões para os tipos de dados intrínsecos não-agregados do TSD Script.

Tipo Informações sobre compactação padrão Resultado Padrão
Booleana INT(1) DEFAULT($ERROR)
Número Inteiro INT(4) DEFAULT($ERROR)
Real FLOAT(8) DEFAULT($ERROR)
Cadeia POINTER DEFAULT(0)
Hora ASE_TIME DEFAULT($ERROR)
Data ASE_DATE DEFAULT($ERROR)
Janela, Arquivo (Tipos de identificadores) UINT(4) DEFAULT($ERROR)

Tivoli Service Desk 6.0 Developer's Toolkit - Guia de Programação do Script

Retornar ao Índice

Copyright