Tivoli Service Desk 6.0 Developer's Toolkit - Guide de programmation TSD Script

Chapitre 4 : Composants de bases de connaissances

Retour à la table des matières


Introduction

La boîte à outils du développeur vous permet de grouper des instructions dans des routines et de les intégrer dans des bases de connaissances ou modules réutilisables. Cette caractéristique de modularité facilite la gestion fastidieuse de quantités importantes de codes source.

Ce chapitre présente les notions de base que vous devez connaître pour comprendre et créer des applications composées de plusieurs bases de connaissances.

Section ROUTINES

Le mot clé ROUTINES permet d'introduire toute section d'une base de connaissances comportant des sous-routines ou des procédures.

Emplacement de ROUTINES dans la section publique

Dans la section publique, la sections ROUTINES, située entre l'en-tête KNOWLEDGEBASE et le mot clé PRIVATE, comporte des procédures et des fonctions qui sont implémentées dans la section privée.

Utilisation de ROUTINES dans la section privée

Dans la section privée, le mot clé ROUTINES est suivi des implémentations complètes de procédures et de fonctions.
Exemple :

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;

Section USES

Tous les fichiers de bases de connaissances de la boîte à outils du développeur présentent deux sections principales.

Exemple

L'exemple suivant illustre une base de connaissances nommée Statistics (figurant dans le fichier statisti.kb) utilisée par une autre base de connaissances nommée Application (figurant dans le fichier (applicat.kb) :

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

La déclaration de Statistics dans sa section USES permet aux routines figurant dans Application d'appeler les trois procédures définies par Statistics.

Introduction de la section USES

La section USES est introduite par le mot clé USES et doit figurer au moins à l'un des emplacements suivants :

Utilisation de plusieurs bases de connaissances

Une base de connaissances peut utiliser autant de bases de connaissances que nécessaire. Chacune des bases de connaissances doit être répertoriée dans la section USES et être suivie d'un point-virgule (;) :

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

Utilisation d'une base de connaissances à titre privé

Une base de connaissances est utilisée à titre privé lorsqu'elle figure dans l'instruction USES de la section privée d'une base de connaissances.

Lorsqu'une base de connaissances est utilisée à titre privé, ses procédures et variables publiques sont disponibles dans l'ensemble de la section privée afin de permettre l'implémentation des routines déclarées dans la section publique. En d'autres termes, l'implémentation privée de la base de connaissances peut être composée des routines publiques d'une autre base de connaissances.

Deux bases de connaissances peuvent s'utiliser l'une l'autre à titre privé et sans restriction, tant que leur identification mutuelle figure dans leur section privée respective. Knowledgebase A peut utiliser Knowledgebase B et vice versa.

Utilisation publique d'une base de connaissances

Une base de connaissances est utilisée publiquement lorsqu'elle figure dans l'instruction USES de la section publique d'une base de connaissances.

Lorsqu'une base de connaissances est utilisée publiquement, les symboles de cette base de connaissances sont disponibles dans l'ensemble de la base de connaissances.

Il est conseillé d'utiliser une base de connaissances publiquement lorsque les symboles de cette base sont requis pour effectuer des déclarations publiques dans la base de connaissances utilisée.
Exemple : Lorsqu'un type d'enregistrement défini dans une base de connaissances est utilisé dans une déclaration de type d'enregistrement d'une autre base de connaissances.

Utilisation cyclique de bases de connaissances

Une utilisation cyclique se produit lorsque la base de connaissances A utilise la base de connaissances B et vice versa. Des bases de connaissances ne peuvent pas s'utiliser l'une l'autre cycliquement dans la section PUBLIC.

Un moyen d'éviter cette restriction consiste à déplacer les déclarations requises pour les deux bases de connaissances vers une base de connaissances séparée qui n'utilise aucune information publique. Cette solution ne peut pas toujours être mise en pratique car il peut être illogique de combiner des déclarations relatives à des fonctions différentes dans une seule base de connaissances. Parfois, cependant, cette solution peut être efficace.

Exemple : Vous créez un programme qui permet de suivre les informations relatives aux employés et aux services auxquels ils sont affectés. Vous voulez encapsuler la plupart des informations relatives aux employés dans une base de connaissances nommée "Employee" et celles relatives aux services dans une base de connaissances nommée "Department."

Or, les routines publiques manipulant des enregistrements relatifs aux employés nécessitent parfois l'utilisation d'enregistrements relatifs aux services en tant que paramètres et vice versa. Aussi, les deux bases de connaissances doivent-elles s'utiliser l'une l'autre publiquement. Etant donné que cette utilisation réciproque est impossible, les bases de connaissances doivent être organisées de la manière suivante :

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;

Procédures

Une procédure correspond à un ensemble d'instructions de la boîte à outils du développeur, qui sont désignées par un nom et ne renvoient pas de valeur au programme appelant.

Une procédure est un bloc imbriqué dans une base de connaissances. Une procédure, comme une base de connaissances, peut contenir des sections relatives à des constantes, des types, des variables et des routines. Les identificateurs de ces sessions sont propres à la procédure et ne sont pas visibles en dehors d'elle.

Toutes les procédures présentent une section ACTIONS qui correspond à l'emplacement des instructions exécutables de la boîte à outils du développeur et qui détermine la nature de la procédure.

Exemples

Une procédure se présente sous la forme suivante :

PROCEDURE <nom-procédure>(<liste-paramètre-formel>) IS
CONSTANTS
  <déclarations-constantes>
TYPES 
  <déclarations-types>
  VARIABLES 
  <déclarations-variables>
ROUTINES
  <implémentations-sous-routines>
  ACTIONS 
  <liste-instructions KML>
END;

L'exemple suivant illustre une procédure simple avec une section ACTIONS comportant deux instructions de la boîte à outils du développeur. A l'appel de cette procédure, les deux instructions de cette section sont exécutées :

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

Utilisation de variables locales avec des variables imbriquées

Il est souvent utile qu'une procédure comporte des variables locales dans une section de variables imbriquées. Les variables locales correspondent à des variables de programme dont la portée est limitée à un bloc de code donné. Les variables locales figurent généralement dans une sous-routine.

L'exemple suivant illustre la création d'une procédure nommée WriteTenLines. Cette procédure utilise une variable locale nommée i destinée à être répétée via la boucle FOR et à afficher 10 chaînes dans une fenêtre :

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

Cet exemple est amélioré avec l'ajout d'une constante locale :

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

Création de routines locales

Il est souvent préférable de créer des routines locales, surtout si la variable que vous souhaitez utiliser apparaît uniquement dans une seule partie d'un programme. Les routines locales correspondent à des procédures ou à des fonctions déclarées dans une autre procédure ou une autre fonction. Elles peuvent être appelées uniquement par la procédure ou la fonction dans lesquelles elles figurent ou par d'autres routines locales y figurant également. Exemple :

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;

Portée

L'un des concepts essentiels portant sur les langages utilisant des structures en blocs est celui de portée. Dans un bloc donné, seuls certains identificateurs existent ou figurent dans une portée. Généralement, les blocs imbriqués sont capables de "repérer" des identificateurs déclarés dans une portée qui les englobe. Un objet ou un identificateur figurant dans une portée est considéré comme local uniquement pour ces blocs.

Exemple de portée

Soit l'exemple suivant :

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; 

Explication de l'exemple de portée

Les identificateurs MAX_EMPLOYEES, EmployeeRecord et employeeList sont visibles dans l'ensemble de la base de connaissances car ils sont déclarés dans le bloc supérieur. Ces éléments apparaissent dans la section publique de la base de connaissances, ils sont donc également visibles pour d'autres bases de connaissances utilisant cette base de connaissances.

De même, étant donné que les identificateurs ARRAY_SIZE et employeeArray sont déclarés dans la section privée du bloc supérieur, ils sont visibles dans l'ensemble de la section privée. Les procédures ProcTwo et ProcOne peuvent toutes deux se référer à ces identificateurs. Toutefois, comme ces identificateurs figurent dans la section privée, leur accès par une autre base de connaissances est impossible.

La variable i dans ProcTwo est visible uniquement dans ProcTwo. Les variables i et j dans ProcOne sont visibles uniquement dans ProcOne. La variable i dans ProcOne is complètement indépendante de la variable i dans ProcTwo.

Les valeurs des variables apparaissent uniquement lors de l'exécution du bloc dans lequel elles figurent. Par exemple, les variables i et j présentent des valeurs uniquement lors de l'exécution de ProcOne.

Transmission de paramètre

Transmission d'informations à une procédure

Lorsqu'une procédure est appelée, il est souvent nécessaire que des informations lui soient transmises.
Cette transmission d'informations s'effectue en accomplissant les étapes suivantes :

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

Lors de l'appel de la procédure, le nombre d'expressions transmises est égal au nombre de paramètres déclarés pour la procédure. Les expressions transmises doivent présenter le même type de données et le même type de paramètre que les paramètres indiqués.

      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;

Transmission par REF ou par VAL

Dans l'exemple suivant, notez que certains paramètres sont transmis par la valeur (VAL) et d'autres par la référence (REF).

Dans un paramètre VAL, une valeur est copiée de l'appelant vers la routine appelée et aucune action effectuée par la routine appelée ne modifie la valeur dont l'appelant est toujours propriétaire.

Un paramètre REF transmet les mêmes données que celles détenues par l'appelant. Ainsi, les changements effectués sur la valeur du paramètre lors de l'exécution de la routine appelée se répercutent immédiatement sur la valeur de l'appelant.

Exemple

Soit l'exemple suivant :

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; 

Explication de cet exemple

Dans l'exemple précédent, une procédure nommée DistanceFormula a été déclarée.

Cette procédure comporte cinq arguments formels :

Lors de l'appel de la procédure, des copies des valeurs des quatre premiers nombres entiers sont transmises à la procédure. Dans le cas du cinquième paramètre, c'est la variable en cours envoyée par l'appelant qui se trouve transmise à la procédure.

Si la procédure attend un paramètre transmis par valeur, l'appelant peut renvoyer une :

Cependant, si la procédure attend un paramètre transmis par référence, l'appelant peut uniquement renvoyer une variable.

Traitement des paramètres en tant que variables

Une procédure peut traiter tous les paramètres qui lui ont été transmis en tant que variables. Elle peut :

Les changements apportés à des paramètres transmis par valeur ne sont pas transmis à leur tour à l'appelant.

Dans l'exemple précédent, ComputeDistances envoie des valeurs littérales pour les quatre arguments entiers à DistanceFormula car les paramètres correspondant avaient été déclarés avec le mot clé VAL. Toutefois, ComputeDistances n'a transmis qu'une variable pour le cinquième argument car le cinquième paramètre avait été déclaré avec le mot clé REF.

Remarque : Il n'existe pas de type de paramètre par défaut. Dans une déclaration de procédure, vous devez indiquer VAL ou REF pour chaque paramètre.

Fonctions

Les fonctions sont identiques aux procédures à ceci près qu'elles renvoient une valeur à l'appelant. Ainsi, les fonctions peuvent être utilisées uniquement dans des affectations ou des expressions. Elles ne sont pas utilisables en tant qu'instructions.

Les fonctions peuvent renvoyer aussi bien des types de données simples (tels que des chaînes, des nombres entiers, des nombres décimaux, des valeurs booléennes, des dates et des heures) que des types de données structurés ou définis par l'utilisateur.

Vous pouvez également élaborer une fonction qui renvoie une liste d'enregistrements.

Présentation de la fonction

Les fonctions se présentent sous la forme suivante :

FUNCTION <nom-fonction>(<liste-paramètres-formels>): <Type> IS
CONSTANTS
  <déclarations-constantes>
TYPES 
  <déclarations-types>
  VARIABLES 
  <déclarations-variables>
ROUTINES
  <implémentations-sous-routines>
  ACTIONS 
  <liste-instructions KML>
END; 

Exemple de fonction

L'exemple suivant illustre comment modifier DistanceFormula afin d'obtenir une fonction plutôt qu'une procédure :

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; 

Remarque : Toutes les fonctions doivent comporter un type de renvoi explicite situé à la suite de la liste de paramètres. Ces deux éléments sont séparés par deux points (:).

Utilisation de $Result

$Result peut être utilisé dans le corps d'une fonction pour accéder à la valeur renvoyée pour cette fonction. $Result peut être défini ou testé dans le corps de la fonction.

Examinez les changements apportés à DistanceFormula:

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

Dans cet exemple, la valeur renvoyée pour la fonction est définie par $Result.

$Result peut être affecté plusieurs fois dans le corps d'une fonction. $Result présente automatiquement le type de données déclaré pour la valeur renvoyée pour la fonction.

Utilisation de l'instruction Exit avec des fonctions

L'utilisation de l'instruction Exit sur une fonction provoque :

Lorsque vous utilisez une instruction Exit dans une fonction, vous pouvez lui attribuer un paramètre indiquant la valeur à renvoyer.

Exit (42); 

correspond à :

$Result := 42;
Exit;

Si une fonction se termine sans utiliser d'instruction Exit, une valeur de $Unknown est renvoyée.

Exit combine les tâches qui :

Appel de fonctions et de procédures de bibliothèques

Le mécanisme de routine externe de la boîte à outils du développeur fournit l'accès aux routines écrites en C ou C++ d'un programme créé dans la boîte à outils du développeur.

Une routine externe est constituée de deux éléments :

Syntaxe des déclarations de la boîte à outils du développeur

Avec Developer's Toolkit 4.2, la syntaxe déclarative de la boîte à outils du développeur supporte la plupart des besoins en interface, sans nécessiter une compréhension complète des structures de données de la boîte à outils du développeur sous-jacente.

Pour appeler une routine externe, l'interpréteur de la boîte à outils du développeur doit présenter une déclaration de la routine qui indique :

Syntaxe des routines externes

L'exemple suivant illustre la syntaxe d'une déclaration de routine externe. Comme pour toutes les implémentations de routine de la boîte à outils du développeur, ces déclarations apparaissent uniquement dans la section privée d'une base de connaissances de la boîte à outils du développeur.

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];

L'argument dll_name correspond à une expression de chaîne constante qui indique la bibliothèque dans laquelle se situe la routine externe. L'extension identifiant la DLL diffère d'une plateforme à l'autre et est généralement omise.

Points d'entrée

Les points d'entrée correspondent aux emplacements d'un programme ou d'une routine au niveau desquels l'exécution peut commencer. Une routine ne possède généralement qu'un seul point d'entrée. Il peut s'agir :

Une chaîne représente le nom d'un point d'entrée, tandis qu'un nombre entier correspond à sa référence numérique dans la bibliothèque.

Création d'un nom de fonction

Les compilateurs C++ utilisent généralement une technique de raccourcissement de nom qui permet d'obtenir une lien sûr entre des modules d'objet compilés différents.
Généralement, les fonctions externes écrites dans le langage C++ doivent généralement être déclarées en tant que fonctions externes "C" externe dans le code source C++, ou bien être chargées suivant leur référence numérique.

Spécifications de liaison

La spécification de liaison dans une déclaration de routine externe doit correspondre à l'un des symboles suivants :

Remarque : La fonction d'appel de DLL de la boîte à outils du développeur échouera pour des arguments "transmis par référence" si la DLL appelée n'a pas été compilée à l'aide de Microsoft Visual C++.

Pour IBM C++ sur OS/2, le protocole est _Optlink._

Sous OS/2, le protocole est _System.

Si la spécification de liaison n'est pas mentionnée dans une déclaration de routine externe, la liaison correspondra par défaut à $STANDARD.

Pour tous les systèmes d'exploitation UNIX, la convention est spécifique à la compilation. Si votre bibliothèque a été écrite dans le langage C ou C++, utilisez $C. Sinon, utilisez $System.

Types de paramètres simples pour des routines externes

Pour faciliter l'utilisation de bibliothèques tierces, TSD Script fournit un certain nombre de noms de types prédéfinis effectuant des mappages directs vers des types 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); 

Les types SHORT, USHORT, LONG, ULONG, PSZ, FLOAT et DOUBLE figurent dans la base de connaissances système située dans le fichier TSD Script.KB.

Mappage de types DLL externes

Les types DLL externes sont mappés par TSD Script vers les types de données de bas niveau les plus couramment utilisés dans C et C++. La syntaxe de déclaration supplémentaire indique à l'interpréteur TSD Script comment mapper les données.

Par exemple, la déclaration pour SHORT indique que la valeur doit être comprimée en un nombre entier codé sur deux octets. La déclaration Default indique que $Unknown provoque une erreur d'exécution si l'on tente de le transmettre vers une routine externe via un paramètre SHORT.

La déclaration pour PSZ indique que la valeur doit être comprimée en un pointeur et que $Unknown doit être transmis en tant que pointeur zéro (NULL).

L'exemple suivant illustre comment déclarer la fonction ExitWindows fournie par Microsoft Windows :

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

Remarque : Un "nombre entier" TSD Script correspond à une valeur longue (32 bits) et "int" ne fonctionne pas toujours dans C.

Transmission de paramètres pour des routines externes

Tout comme les paramètres de routines TSD Script classiques, les paramètres de routines externes sont transmis sous forme de paramètres :

Paramètres VAL

Les paramètres VAL des routines externes se comportent de manière identique aux paramètres VAL de routines non externes.

La valeur est copiée de l'appelant vers la routine appelée et aucune action effectuée par la routine appelée ne modifie la valeur dont l'appelant est toujours propriétaire.

Une chaîne transmise en tant que VAL est également reçue par la routine externe sous la forme d'un pointeur indiquant l'emplacement de stockage provisoire dans lequel la chaîne TSD Script a été copiée.

Paramètres REF

Pour les routines externes, les paramètres REF diffèrent légèrement des paramètres VAL.

Lorsqu'une routine non externe reçoit un paramètre REF, celui-ci transmet les même données que celles détenues par l'appelant. Toute modification apportée à la valeur du paramètre lors de l'appel de la routine se répercute immédiatement sur la valeur de l'appelant.

La transmission à une routine externe de paramètres en tant que paramètres REF est implémentée sous la forme de copie en entrée/copie en sortie. La différence est subtile mais dans un certain contexte, ce comportement est détectable. La diffusion d'un message à partir d'une routine externe constitue un exemple de ce comportement.

Le type de données STRING (et des alias tels que PSZ) constitue une exception. Il est transmis en tant que pointeur à la valeur de la chaîne TSD Script en cours lorsque que celle-ci est transmise en tant que paramètre REF.

Tous les paramètres REF sont transmis aux routines externes C ou C++ en tant que pointeurs. TSD Script n'essaye pas de supporter la notion C++ de références. Si vous devez appeler une routine C++ dans laquelle figurent des paramètres référence, vous pouvez écrire une petite fonction de bouclage. Cette fonction sélectionne un pointeur de TSD Script, annule son référencement et le transmet à la fonction C++ requise.

Comme TSD Script ne supporte pas directement la notion ANSI C et C++ de const, les programmeurs TSD Script déclarent un paramètre en tant que paramètre REF lorsqu'une fonction C/C++ sélectionne un argument de pointeur const.

Conversion de données

La transmission de données entre TSD Script et une routine externe nécessite souvent que les données soient converties dans un format de remplacement. Avant que la routine externe ne soit appelée, la valeur de l'appelant est :

Si le paramètre correspond à un paramètre REF, la zone temporaire est décomprimée vers l'espace de stockage de l'appelant après renvoi de l'appelant.

Structures des données et compression binaire

Bien que vous puissiez créer des interfaces d'un niveau plus ou moins élaboré à l'aide de types simples, il vous sera éventuellement nécessaire de transmettre des structures de données à une routine externe.
Developer's Toolkit 4.2 présente une nouvelle syntaxe de TSD Script qui permet de donner des informations détaillées sur le mappage de données TSD Script vers des structures de données C ou C++. Ce type de mappage est désigné par le terme de compression binaire.

Les informations relatives à la compression binaire se présentent sous la forme d'une annotation de spécification de type. Cette annotation correspond à une déclaration de type nommée ou à une spécification de zone dans une déclaration d'enregistrement. La syntaxe brute de ces deux éléments est illustrée ci-dessous :

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

Format de l'annotation de données

Les annotation suivantes indiquent le format selon lequel les données TSD Script sont comprimées. Elles s'excluent toutes mutuellement.

Annotation Description
INT(width) L'annotation INT indique que la zone est comprimée dans le format d'origine de nombres entiers avec la largeur indiquée. Les valeurs admises pour la largeur sont 1, 2 et 4. Tous les types de données TSD Script pouvant être explicitement convertis en INTEGER peuvent être comprimés en tant que INT.
UINT(width) L'annotation UINT indique que la zone est comprimée dans le format d'origine de nombres entiers en tant que valeur sans signe avec la largeur indiquée. Lors de la transmission d'une valeur de TSD Script à une routine externe, la différence entre INT et UINT est minime, car la même combinaison de bits est transmis dans les deux cas. Cependant, lorsqu'une valeur codée sur 1 ou 2 octets est retransmise de la routine externe vers TSD Script, la distinction INT/UINT permet de déterminer le signe de la valeur. Les valeurs admises pour la largeur sont également 1, 2 et 4.
NUMERIC(width) Les zones comportant l'annotation NUMERIC sont comprimées en une séquence de caractères complétée par des espaces avec la largeur indiquée. Les nombres entiers et les nombres réels TSD Script, ainsi que tout type de données convertible en nombre entier, peuvent être comprimés en une zone NUMERIC.
FLOAT(width) Les zones comportant l'annotation FLOAT sont comprimées en un nombre avec virgule flottante IEEE avec la largeur définie. Les largeurs admises sont 4 et 8. Tous les types TSD Script convertibles en REAL peuvent être comprimés en FLOAT.
BCD(width) Les zones comportant l'annotation BCD sont comprimées en format Binary Coded Decimal. Tous les types TSD Script convertibles en REAL peuvent être comprimés en BCD.
CHAR(width) Les zones comportant l'annotation CHAR sont comprimées en un tableau de caractères simple avec la largeur indiquée. Tous les types TSD Script convertibles en STRING peuvent être comprimés en CHAR.
ZSTRING(width) Les zones comportant l'annotation ZSTRING sont comprimées en une chaîne complétée par des zéros (type C) avec la largeur indiquée. Tous les types TSD Script convertibles en STRING peuvent être comprimés en ZSTRING.
LSTRING(width) Les zones comportant l'annotation LSTRING sont comprimées en une chaîne de type Pascal dont le premier octet contient la longueur de la chaîne. Tous les types TSD Script convertibles en STRING peuvent être comprimés en LSTRING.
ASE_DATE Les zones comportant l'annotation ASE_DATE sont comprimées en une structure DATEREC. Tous les types de données convertibles en DATE peuvent être comprimés en ASE_DATE.
BTRV_DATE Les zones comportant l'annotation BTRV_DATE sont comprimées en une date de type Btrieve. Tous les types de données convertibles en DATE peuvent être comprimés en BTRV_DATE.
CCYYMMDD Les zones comportant l'annotation CCYYMMDD sont comprimées en une chaîne de caractères contenant le siècle, l'année, le mois et l'année ; chacun de ces éléments étant comprimé sur deux octets. Tous les types de données convertibles en DATE peuvent être comprimés en CCYYMMDD.
ASE_TIME Les zones comportant l'annotation ASE_TIME sont comprimées en un TIMEREC. Tous les types de données convertibles en TIME peuvent être comprimés en un ASE_TIME.
BTRV_TIME Les zones comportant l'annotation BTRV_TIME sont comprimées en une heure de type Btrieve. Tous les types de données convertissables en TIME peuvent être comprimés en un BTRV_TIME.
HHMMSS Les zones comportant l'annotation HHMMSS sont comprimées en une chaîne de caractères contenant les heures, les minutes et les secondes ; chacun de ces éléments étant comprimé sur deux octets. Tous les types de données convertibles en TIME peuvent être comprimés en un HHMMSS.
POINTER Les zones comportant l'annotation POINTER sont comprimées en un pointeur 32 bits des données TSD Script en cours. Tous les types de données non consolidées dans TSD Script peuvent être comprimés en tant que POINTER.
NOEXPORT L'annotation NOEXPORT indique une zone qui ne figure pas dans la représentation binaire externe. Tous les types de zones peuvent porter l'annotation NOEXPORT

Annotation de valeur par défaut

Outre l'annotation de format, une annotation de valeur par défaut peut être indiquée. Cette annotation indique à l'interpréteur TSD Script comment remplir la zone dans la structure binaire lorsque la valeur de TSD Script est inconnue. La syntaxe de l'annotation de valeur par défaut est :

DEFAULT( $ERROR|expression ) 

Lorsque $ERROR est indiqué et que la compression d'une valeur est effectuée, l'interpréteur TSD Script affiche une message d'erreur et met fin à la routine externe.

Il s'agit de la valeur par défaut lorsqu'aucune annotation de valeur n'est définie.

Lorsqu'une expression est indiquée, elle est évaluée et sa valeur comprimée en fonction de l'annotation de format si la valeur TSD Script est inconnue. Cette fonction permet de mapper des chaînes inconnues vers NULL.

Annotations de compression

Dans une séquence de spécifications de zones, vous pouvez fournir des annotations de compression sans indiquer le nom de zone ou le type de données correspondant. Ces annotations indiquent les zones de la structure binaire qui ne figurent pas dans l'enregistrement. En effet, ces zones n'apparaissent pas elles-mêmes dans l'enregistrement TSD Script. Vous devez ajouter une annotation supplémentaire comportant la valeur de cette zone.

La syntaxe de cette annotation particulière est :

A chaque compression de la zone, l'expression donnée est évaluée, puis comprimée conformément à l'annotation du format correspondant.

Annotations FILL

Enfin, pour que les zones soient alignées, l'annotation FILL peut être utilisée afin de placer un nombre d'octets de remplissage arbitraire entre les différentes zones de la structure binaire.

Syntaxe de l'annotation FILL :

FILL( width [ , valeur ] ) 

Le nombre d'octets indiqué par la largeur, et ceux contenant la valeur donnée, sont comprimés dans la structure binaire. Bien qu'il soit possible d'indiquer n'importe quel nombre entier constant pour l'annotation FILL, les octets comprimés en cours comportent uniquement les 8 bits les moins significatifs - la plage comprise entre 128 et 255 correspond à une plage de valeurs utile. Zéro correspond à la valeur par défaut.

Les zones et les types nommés sans annotations de compression explicites sont comprimés en fonction de la valeur par défaut de leurs types sous-jacents.
Le tableau ci-après indique les valeurs par défaut des types de données TSD Script intrinsèques et non consolidées.

Type Informations de compression par défaut Résultats par défaut
Booléen INT(1) DEFAULT($ERROR)
Nombre entier INT(4) DEFAULT($ERROR)
Nombre décimal FLOAT(8) DEFAULT($ERROR)
Chaîne POINTER DEFAULT(0)
Heure ASE_TIME DEFAULT($ERROR)
Date ASE_DATE DEFAULT($ERROR)
Fenêtre, fichier (types de descripteurs) UINT(4) DEFAULT($ERROR)

Tivoli Service Desk 6.0 Developer's Toolkit - Guide de programmation TSD Script

Retour à la table des matières

Copyright