Manuale per la programmazione Tivoli Service Desk 6.0 Developer's Toolkit Script

Capitolo 4: Componenti del file .kb

Ritorna all'indice analitico


Introduzione

Developer's Toolkit consente di raggruppare le istruzioni nelle routine e di impacchettarle in file .kb o moduli riutilizzabili. Questa caratteristica del modulo facilita la conservazione di grandi quantità di codice di risorsa.

Questo capitolo contiene le informazioni di base necessarie per comprendere e creare applicazioni a più file .kb.


Sezione ROUTINES

La parola chiave ROUTINES viene utilizzata per introdurre ogni sezione di un file .kb che contiene sottoroutine e procedure.

Ubicazione di ROUTINES nella sezione pubblica

Nella sezione pubblica tra l'intestazione KNOWLEDGEBASE e la parola chiave PRIVATE, la sezione delle routine contiene dichiarazioni delle procedure e delle funzioni implementate nella sezione privata.

Utilizzo di ROUTINES nella sezione privata

Nella sezione privata, la parola chiave ROUTINES è seguita dalle implementazioni della procedura completa e della funzione.
Un esempio viene riportato di seguito:

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;

Sezione USES

Ogni file .kb Developer's Toolkit è costituito da due sezioni principali.

Esempio

L'esempio seguente presenta un file .kb denominato Statistics (contenuto nel file statisti.kb) utilizzato da un altro file .kb denominato Application (nel file applicat.kb):

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

Dichiarando Statistics nella relativa sezione Uses, le routine in Application possono chiamare le tre procedure definite da Statistics.

Introduzione alla sezione USES

La sezione degli utilizzi viene introdotta dalla parola chiave USES e deve trovarsi in una di queste posizioni (o entrambe):

Utilizzo di più file .kb

Un file .kb può utilizzare un qualsiasi numero di altri file .kb. Ogni file .kb deve essere elencato nella sezione uses e deve essere seguito da un punto e virgola:

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

Utilizzo privato di un file .kb

Un file .kb viene utilizzato privatamente quando è contenuto nell'istruzione USES nella sezione privata di un file .kb.

Quando un file .kb viene utilizzato privatamente, le variabili e le procedure pubbliche a esso relative sono disponibili in tutta la sezione privata per implementare le routine dichiarate nella sezione pubblica. In altre parole, l'implementazione privata del file .kb può essere composta dalle routine pubbliche di un altro file .kb.

Due file .kb possono utilizzarsi reciprocamente e privatamente senza limitazioni, finché essi si denominano reciprocamente nella sezione privata. Cioè, un file .kb A può utilizzare un file .kb B e viceversa.

Utilizzo pubblico di un file .kb

Un file .kb viene utilizzato pubblicamente quando è contenuto nell'istruzione USES nella sezione pubblica di un file .kb.

Quando un file .kb viene utilizzato pubblicamente, i simboli del file .kb utilizzato sono disponibili in tutti i file .kb.

E' possibile utilizzare un file .kb pubblicamente quando i simboli a esso relativi sono necessari per alcune dichiarazioni pubbliche nel file .kb utilizzato.
Un esempio di ciò viene fornito quando un tipo di record definito in un file .kb viene utilizzato in una dichiarazione del tipo di record di un altro file .kb.

Utilizzo ciclico di file .kb pubblici

L'utilizzo ciclico si verifica quando un file .kb A utilizza un file .kb B e viceversa. I file .kb non possono utilizzarsi reciprocamente e ciclicamente nella sezione PUBLIC.

Un modo per evitare questa limitazione è quello di spostare le dichiarazioni comuni necessarie per entrambi i file .kb in un file .kb separato che non utilizza nulla in modo pubblico. Ciò non è sempre fattibile perché potrebbe non avere senso combinare dichiarazioni per funzioni molto diverse in un file .kb. Talvolta, tuttavia, questa soluzione risulta adeguata.

Ad esempio, supporre di creare un programma che traccia informazioni relative a impiegati e al reparto in cui lavorano. Si desidera concentrare tutte le informazioni sugli impiegati in un file .kb denominato "Employee" e le informazioni sui reparti in un file .kb denominato "Department."

Tuttavia, le routine pubbliche che gestiscono i record employee richiedono talvolta i record department come parametri e viceversa. Quindi, è necessario che i file .kb si utilizzino reciprocamente e pubblicamente. Se ciò non funziona, i file .kb devono essere organizzati come mostrato nell'esempio seguente:

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;

Procedure

Una procedura è una raccolta di istruzioni Developer's Toolkit a cui è possibile fare riferimento tramite un nome che non restituisce un valore a colui che ha effettuato la chiamata.

Una procedura è un blocco nidificato all'interno del file .kb. Come lo stesso file .kb, una procedura può disporre di sezioni per costanti, tipi, variabili e routine. Gli identificativi in queste sezioni sono locali per la procedura e non sono visibili all'esterno di essa.

Ogni procedura dispone di una sezione di azioni che indica la posizione per le istruzioni eseguibili Developer's Toolkit che stabiliscono ciò che fa la procedura.

Esempi

La forma generale di una procedura è mostrata di seguito:

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

Quella di seguito riportata è una procedura semplice con una sezione di azioni che contiene due istruzioni Developer's Toolkit. Quando questa procedura viene chiamata, le due istruzioni nella sezione delle azioni vengono eseguite:

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

Utilizzo di variabili locali con variabili nidificate

Spesso è utile che una procedura contenga variabili locali in una sezione di variabili nidificate. Le variabili locali sono variabili di programma il cui ambito è limitato a un blocco di codice specifico. Di regola, le variabili locali sono confinate a una sottoroutine.

L'esempio seguente crea una procedura definita WriteTenLines. La procedura utilizza una variabile locale denominata i; questa variabile deve essere ripetuta per tutto il loop FOR e per scrivere 10 stringhe su una finestra:

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

Questo esempio viene migliorato ulteriormente per includere una costante locale:

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

Creazione di routine locali

Spesso risulta utile creare delle routine locali, in particolare se la variabile che si desidera utilizzare si presenta solo in una parte di un programma. Le routine locali sono procedure o funzioni dichiarate all'interno di un'altra funzione o procedura. Una routine locale può essere richiamata solo dalla procedura o dalla funzione che la contiene o da altre routine locali contenute in essa. Consultare l'esempio:

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;

Determinazione degli ambiti

Uno dei problemi concettuali più importanti nelle lingue strutturate in blocchi è l'ambito. All'interno di ogni blocco dato, esistono solo determinati identificativi oppure sono nell'ambito. In generale, i blocchi nidificati sono in grado di "visualizzare" gli identificativi dichiarati in un ambito limitato. Un oggetto o identificativo è in un ambito limitato è locale solo per quel blocco.

Esempio di determinazione degli ambiti

Considerare il seguente esempio:

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; 

Spiegazione dell'esempio di determinazione degli ambiti

MAX_EMPLOYEES, EmployeeRecord e employeeList sono visibili in tutto il file .kb poiché sono dichiarati nel blocco più esterno. Questi elementi appaiono nella sezione pubblica del file .kb, in modo da poter essere visibili anche dagli altri file .kb che utilizzano questo file .kb.

In modo analogo, poiché ARRAY_SIZE e employeeArray sono dichiarati nella sezione privata del blocco più esterno, sono visibili nell'intera sezione privata. Sia ProcTwo che ProcOne possono riferirsi a questi identificativi, ma poiché si trovano nella sezione privata, nessun altro file .kb può accedere a essi.

La variabile i in ProcTwo è visibile solo in ProcTwo. Le variabili i e j in ProcOne sono visibili solo in ProcOne. La variabile i in ProcOne non è correlata alla variabile i in ProcTwo.

I valori della variabile esistono solo quando è in esecuzione il blocco in cui esse sono contenute. Ad esempio, le variabili i e j dispongono di valori solo durante l'esecuzione di ProcOne.

Inoltro dei parametri

Inoltro di informazioni a una procedura

Quando si chiamano delle procedure, spesso è necessario inoltrare a esse delle informazioni.
Per inoltrare delle informazioni seguire questi passi:

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

Quando si richiama la procedura, il numero di espressioni passate eguaglia il numero di parametri dichiarati per la procedura. Le espressioni passate devono avere lo stesso tipo di parametro e lo stesso tipo di dati dei parametri specificati.

        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;

Inoltro per REF oppure VAL

Nell'esempio successivo, alcuni parametri vengono inoltrati per valore (VAL) altri per riferimento (REF).

In un parametro VAL, un valore viene copiato dal chiamante sulla routine richiamata e nulla di quanto la routine chiamata esegue influenza il valore ancora in possesso del chiamante.

Un parametro REF indirizza la stessa memoria posseduta dal richiedente. Perciò, le modifiche al valore del parametro che si apportano nel corso della routine richiamata diventano effettive immediatamente sul valore del richiedente.

Esempio

Considerare il seguente esempio:

    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; 

Spiegazione dell'esempio

Nell'esempio precedente, è stata dichiarata una procedura denominata DistanceFormula.

La procedura comprende cinque argomenti formali:

Quando viene chiamata una procedura, vengono inviate a essa le copie dei primi quattro valori interi passati. Tuttavia, nel caso del quinto parametro, la variabile attuale inviata dal richiedente viene passata alla procedura.

Se una procedura prevede che un parametro sia passato per valore, il richiedente può inviare una:

Tuttavia, se una procedura prevede di passare un parametro per riferimento, il chiamante può inviare solo una variabile.

Trattamento dei parametri come variabili

Una procedura può trattare come variabili tutti i parametri che le vengono passati. Essa può:

Le modifiche apportate ai parametri passati per valore non sono restituite al chiamante.

Nell'esempio precedente, ComputeDistances invia valori literal per i quattro argomenti interi a DistanceFormula, perché i parametri corrispondenti sono stati dichiarati con la parola chiave VAL. Tuttavia, ComputeDistances inoltra solo una variabile per il quinto argomento poiché il quinto parametro è stato dichiarato con la parola chiave REF.

Nota: Non esiste un tipo di parametro di default. In una dichiarazione di procedura è necessario specificare il valore VAL o il valore REF per ogni parametro.

Funzioni

Le funzioni sono identiche alle procedure, ma restituiscono un valore al chiamante. Per questo motivo, le funzioni possono essere utilizzate solo in assegnazioni o in espressioni. Non possono essere utilizzate come istruzioni.

Le funzioni possono restituire tipi semplici (come stringhe, numeri interi, numeri reali, valori booleani, data e ora), tipi strutturati e definiti dall'utente.

E' possibile, inoltre, scrivere una funzione che restituisce un elenco di record.

Formato funzioni

Le funzioni hanno il seguente formato generale:

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; 

Esempio di funzione

L'esempio seguente modifica DistanceFormula in modo che essa sia una funzione e non una procedura:

    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: Ogni funzione deve disporre di un tipo di restituzione esplicito che segue l'elenco dei parametri ed è separato da esso da un segno d'interpunzione due punti (:).

Utilizzo di $Result

$Result può essere utilizzato nel corpo di una funzione per accedere al valore di restituzione corrente per quella funzione. E' possibile impostarlo o testarlo nel corpo della funzione.

Prendere in considerazione la seguente modifica per DistanceFormula:

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

In questo esempio, il valore di restituzione della funzione è impostato con $Result.

$Result può essere assegnato più volte nel corpo di una funzione. $Result dispone automaticamente del tipo di dati dichiarato per il valore di restituzione della funzione.

Utilizzo di Exit con le funzioni

Exit, se utilizzato con una funzione, causa:

Quando si utilizza un'istruzione Exit in una funzione, è possibile assegnare a essa un parametro che indica il valore che si desidera restituire.

Exit (42); 

è lo stesso di:

$Result := 42;
      Exit;

Se un'istruzione termina senza utilizzare un'istruzione Exit, viene restituito un valore $Unknown.

Exit combina le attività che:

Chiamata di funzioni e di procedure libreria

L'accesso alle routine scritte in C o C++ da un programma scritto in Developer's Toolkit è fornito dal meccanismo di routine esterno del Developer's Toolkit.

Una routine esterna è composta da due parti:

Sintassi di dichiarazione Developer's Toolkit

A partire da Developer's Toolkit 4.2, la sintassi dichiarativa del Developer's Toolkit supporta la maggior parte dei requisiti d'interfaccia senza una conoscenza approfondita delle strutture di dati sottostanti di Developer's Toolkit.

Per chiamare una routine esterna, Developer's Toolkit Interpreter deve disporre di una dichiarazione della routine che indica:

Sintassi di routine esterna

La sintassi di una dichiarazione di routine esterna viene mostrata nell'esempio seguente. Come ogni implementazione di routine Developer's Toolkit, queste dichiarazioni possono apparire solo nella sezione privata di un file .kb 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];

Il nome DLL è un'espressione costante di stringa costante che identifica la libreria in cui è ubicata la routine esterna. L'estensione .dll è solitamente diversa su una base per piattaforma e viene generalmente omessa dal nome dato.

Punti d'immissione

I punti d'immissione sono dei punti all'interno di un programma o di una routine in cui può cominciare l'esecuzione. Generalmente, una routine ha un solo punto d'immissione. Il punto d'immissione può essere:

Una stringa rappresenta il nome di un punto d'immissione e un numero intero rappresenta il relativo numero ordinale nella libreria.

Costruzione di un nome di funzione

I compilatori C++ utilizzano, generalmente, una tecnica nota come estensione del nome che assicura il corretto collegamento tra i moduli degli oggetti compilati separati.
Le funzioni esterne scritte in C++ possono essere dichiarate come esterne "C" nel codice di risorsa C++ oppure possono essere caricate in base al numero ordinale a esse relativo.

Specifiche di collegamento

La specifica di collegamento in una dichiarazione di routine esterna deve essere uno dei simboli seguenti:

Nota: La funzione callout DLL di Developer's Toolkit riporta esito negativo per gli argomenti "passati per riferimento" se la DLL non è richiamata con Microsoft Visual C++.

Per IBM C++ su OS/2, il protocollo è _Optlink._

Per OS/2, il protocollo è _System.

Se la specifica di collegamento viene omessa completamente da una dichiarazione di routine esterna, il collegamento è impostato per default su $STANDARD.

Per tutti i sistemi operativi UNIX, la convenzione è di compilazione specifica. Se la libreria è stata scritta in C o C++, utilizzare $C. Altrimenti, utilizzare $System.

Tipi di parametri semplici per routine esterne

Per facilitare l'utilizzo di librerie di terza parte, TSD Script fornisce una serie di nomi del tipo predefinito che definiscono direttamente i tipi C/C++.

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

I tipi SHORT, USHORT, LONG, ULONG, PSZ, FLOAT e DOUBLE vengono forniti nel file .kb del sistema trovato nel file TSD Script.KB.

Definizione dei tipi di DLL esterni

I tipi di DLL esterni vengono definiti da TSD Script per i tipi di dati di bassa qualità più comuni utilizzati in C e C++. La sintassi extra dichiarativa indica a TSD Script Interpreter come definire i dati.

Ad esempio, la dichiarazione per SHORT dice che il valore deve essere compresso in un numero intero a due byte. La dichiarazione Default indica che $Unknown provoca un errore nel tempo di esecuzione se si tenta di passare a una routine esterna tramite un parametro SHORT.

La dichiarazione per PSZ dice che il valore deve essere compresso come un puntatore e che $Unknown deve essere passato come un puntatore zero (NULL).

Segue un esempio di come dichiarare la funzione ExitWindows fornita da Microsoft Windows:

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

Nota: Un "numero intero" è un valore a 32 bit e "int" non sempre opera in C.

Inoltro dei parametri per le routine esterne

Come i parametri per le routine TSD Script, i parametri per le routine esterne vengono specificati in base al modo in cui vengono passati:

Parametri VAL

Il parametri VAL per le routine esterne si comportano in modo molto simile ai parametri VAL per le routine non esterne.

Il valore viene copiato dal chiamante sulla routine chiamata e nulla di quanto la routine chiamata esegue influenza il valore ancora in possesso del chiamante.

Una stringa passata per VAL viene ricevuta anche dalla routine esterna come un puntatore che indirizza una ubicazione di memoria temporanea in cui è stata copiata la stringa TSD Script.

Parametri REF

I parametri REF differiscono leggermente dai parametri VAL per le routine esterne.

Quando una routine non esterna riceve un parametro REF, essa indirizza la stessa memoria posseduta dal chiamante. Ogni modifica apportata al valore del parametro durante il richiamo della routine diventa effettiva immediatamente sul valore del chiamante.

Il passaggio per riferimento a una routine esterna è implementato realmente come copy-in/copy-out. La differenza è sottile, ma in alcune circostanze, è possibile distinguerne la funzionalità. La distribuzione di un messaggio da una routine esterna costituisce un esempio di tale funzionalità.

La STRINGA tipo di dati (e gli alias come PSZ) rappresenta un'eccezione e viene passata tramite un puntatore al valore di stringa TSD Script reale, se inoltrata per REF.

Tutti i parametri REF vengono passati a routine esterne C o C++ come puntatori. TSD Script non tenta di supportare la nozione C++ dei riferimenti. Se è necessario chiamare una routine C++ contenente parametri di riferimento, è possibile scrivere una funzione wrapper piccola. Il wrapper prende un puntatore da TSD Script, lo priva dei riferimenti e lo passa alla funzione C++ richiesta.

Poiché TSD Script non supporta direttamente le nozioni C e C++ di const, generalmente i programmatori TSD Script dichiarano un parametro REF se la funzione C/C++ comprende un argomento del puntatore const.

Conversione dei dati

Spesso, il passaggio di dati tra TSD Script e una routine esterna richiede la conversione dei dati in un formato alternativo. Prima di chiamare una routine esterna, il valore del chiamante è:

Se il parametro è REF, dopo la restituzione del chiamante, l'area temporanea è impacchettata nuovamente nella memoria del chiamante.

Strutture di dati e pacchetto binario

Nonostante sia possibile costruire interfacce piuttosto elaborate utilizzando tipi semplici, potrebbe comunque essere necessario passare strutture di dati aggregate a una routine esterna.
Developer's Toolkit 4.2 aggiunge una nuova sintassi a TSD Script che consente la specifica esplicita che spiega nei dettagli come vengono definiti i dati TSD Script su strutture di dati C o C++. A questa definizione si farà riferimento con un pacchetto binario.

Le informazioni di pacchetto binario vengono fornite come un'annotazione alla specifica del tipo in una dichiarazione di tipo denominata o in una specifica del campo, in una dichiarazione di record. La sintassi generica per entrambi è riportata di seguito:

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

Formato di annotazione dei dati

Le seguenti annotazioni specificano il formato in cui vengono impacchettati i dati del TSD Script. Esse si escludono reciprocamente.

Annotazione Descrizione
INT(width) L'annotazione INT specifica che il campo viene impacchettato nel formato intero di origine con la larghezza specificata. I valori consentiti per la larghezza sono 1, 2 e 4. Ogni tipo di dati TSD Script che può essere convertito esplicitamente in INTEGER può essere impacchettato come INT.
UINT(width) L'annotazione UINT specifica che il campo viene compresso nel formato intero di origine come un valore non definito nella larghezza specificata. Quando un valore viene passato da TSD Script a una routine esterna, non esiste una differenza significativa tra INT e UINT, perché , in entrambi i casi, viene passato lo stesso modello bit. Comunque, quando un valore a 1 o 2 byte viene restituito a TSD Script dalla routine esterna, la distinzione tra INT e UINT stabilisce qual è il valore con segno. Ancora, i valori legal per la larghezza sono 1, 2 e 4.
NUMERIC(width) I campi con l'annotazione NUMERIC vengono compressi come una sequenza di caratteri vuoti con la larghezza data. I numeri interi e i numeri reali e qualsiasi tipo di dati TSD Script che possono essere convertiti in Numeri interi possono essere anche compressi come un campo NUMERIC.
FLOAT(width) I campi con l'annotazione FLOAT vengono compressi come un numero a virgola mobile IEEE con la larghezza specificata. Le larghezze valide sono 4 e 8. Ogni tipo di TSD Script che può essere esplicitamente convertito in REAL può essere compresso come FLOAT.
BCD(width) I campi con l'annotazione BCD vengono compressi come BCD (Binary Coded Decimal). Ogni tipo di dati TSD Script che può essere convertito esplicitamente in REAL può essere compresso come BCD.
CHAR(width) I campi con l'annotazione CHAR vengono compressi come una schiera di caratteri semplici con la larghezza data. Ogni tipo di dati TSD Script che possono essere convertiti in STRING possono essere compressi come CHAR.
ZSTRING(width) I campi con l'annotazione ZSTRING vengono compressi come una stringa a terminazione null (stile C) con la larghezza data. Ogni tipo di dati TSD Script che può essere convertito in STRING può essere compresso come ZSTRING.
LSTRING(width) I campi con l'annotazione LSTRING vengono compressi come una stringa stile Pascal, con un byte iniziale contenente la lunghezza della stringa. Ogni tipo TSD Script che può essere convertito in STRING può essere compresso come LSTRING.
ASE_DATE I campi con l'annotazione ASE_DATE vengono compressi come una struttura DATEREC. Ogni tipo di dati che può essere convertito esplicitamente in DATE può essere compresso come un ASE_DATE.
BTRV_DATE I campi con l'annotazione BTRV_DATE vengono compressi come una data in stile Btrieve. Ogni tipo di dati che può essere convertito esplicitamente in DATE può essere compresso come un BTRV_DATE.
CCYYMMDD I campi con l'annotazione CCYYMMDD vengono compressi come una stringa di carattere contenente il secolo, l'anno, il mese e il giorno, ognuno compresso in due byte. Ogni tipo che può essere esplicitamente convertito in DATE può essere compresso come un CCYYMMDD.
ASE_TIME I campi con l'annotazione ASE_TIME vengono compressi come un TIMEREC. Ogni tipo di dati che può essere esplicitamente convertito in TIME può essere compresso come un ASE_TIME.
BTRV_TIME I campi con l'annotazione BTRV_TIME vengono compressi come un'ora stile Btrieve. Ogni tipo di dati che può essere esplicitamente convertito in TIME può essere compresso come BTRV_TIME.
HHMMSS I campi con l'annotazione HHMMSS vengono compressi come una stringa di caratteri contenente l'ora, i minuti e i secondi, ognuno compresso in due byte. Ogni tipo di dati che può essere esplicitamente convertito in TIME può essere compresso come HHMMSS.
POINTER I campi con l'annotazione POINTER vengono compressi come un puntatore a 32 bit nei dati reali TSD Script a essi relativi. Ognuno dei dati non aggregati in TSD Script può essere compresso come POINTER.
NOEXPORT L'annotazione NOEXPORT contrassegna un campo non incluso nella rappresentazione binaria esterna. Tutti i tipi di campo possono essere contrassegnati con NOEXPORT

Annotazione del valore di default

In aggiunta a un'annotazione del formato, può essere specificata un'annotazione di valore di default. L'annotazione del valore di default indica al TSD Script interpreter come riempire un campo nella struttura binaria quando il valore TSD Script è sconosciuto. La sintassi per l'annotazione del valore di default è:

DEFAULT( $ERROR|expression ) 

Quando viene specificato $ERROR, la compressione di un valore sconosciuto provoca la visualizzazione di un messaggio di errore e l'interruzione della routine esterna da parte del TSD Script Interpreter.

Questo è il valore di default quando non viene specificata nessuna annotazione di valore.

Se viene specificata un'espressione, essa viene valutata e i valori a essa relativi vengono compressi secondo l'annotazione del formato, quando il valore TSD Script non è sconosciuto. Questa caratteristica viene utilizzata per definire stringhe sconosciute per NULL.

Annotazioni pacchetto

In una sequenza di specifiche di campo, è possibile fornire annotazioni di pacchetto senza un nome campo o un tipo di dati corrispondente. Queste annotazioni specificano i campi nella struttura binaria che non appaiono nel record TSD Script. Ciò si verifica perché gli stessi campi non appaiono nel record TSD Script. E' necessario fornire un'annotazione ulteriore con il valore per quel campo.

La sintassi per questa annotazione speciale è

Ogni volta che viene compresso un campo, l'espressione fornita viene valutata e compressa secondo l'annotazione del formato corrispondente.

Annotazioni FILL

Infine, per l'allineamento del campo, l'annotazione FILL può essere utilizzata per ubicare un numero arbitrario di byte di riempimento tra i campi nella struttura binaria.

La sintassi dell'annotazione FILL è

FILL( width [ , value ] ) 

Il numero di byte specificato per larghezza e quello dei dati contenente il valore fornito viene compresso nella struttura binaria. Sebbene un qualsiasi valore intero di costante possa essere specificato per l'annotazione FILL, i byte realmente compressi contengono solo gli ultimi 8 bit, così da -128 a 255 rappresenta un intervallo utile di valori. Il valore di default è zero.

I tipi e i campi denominati senza annotazioni di pacchetto specifiche vengono compressi per default per i tipi sottostanti.
La tabella seguente indica i valori di default per i tipi di dati TSD Script non aggregati intrinseci.

Tipo Informazioni sul pacchetto di default Risultato di default
Booleano INT(1) DEFAULT($ERROR)
Numero intero INT(4) DEFAULT($ERROR)
Numero reale FLOAT(8) DEFAULT($ERROR)
Stringa POINTER DEFAULT(0)
Ora ASE_TIME DEFAULT($ERROR)
Data ASE_DATE DEFAULT($ERROR)
Finestra, File (Tipi handle) UINT(4) DEFAULT($ERROR)

Manuale per la programmazione Tivoli Service Desk 6.0 Developer's Toolkit Script

Ritorna all'indice analitico

Copyright