Tivoli Service Desk 6.0 Developer's Toolkit Script プログラミングの手引き

第 4 章: 知識ベースのコンポーネント

目次に戻る


概要

Developer's Toolkit によって、ステートメントをルーチンにまとめ、再使用可能知識ベース (またはモジュール) にパッケージすることができます。このモジュラー特性によって、大量のソース・コードを保守することの困難さが解消します。

この章では、マルチ知識ベース・アプリケーションの理解し、ビルドするために必要な基本事項について説明します。

ROUTINES セクション

キーワード ROUTINES は、サブルーチンまたはプロシージャーを含む知識ベースのどのセクションを紹介するためにも使用されます。

公用セクションでの ROUTINES の位置決め

KNOWLEDGEBASE 見出しと PRIVATE キーワードの間の公用セクションでは、ルーチン・セクションに私用セクションで実装されるプロシージャーおよび関数の宣言が含まれています。

私用セクションでの ROUTINES の使用

私用セクションでは、ROUTINES キーワードの後に完全なプロシージャーおよび関数の実装が続きます。
以下に例を示します。

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;

USES セクション

Developer's Toolkit のすべての知識ベース・ファイルは、2 つの基本セクションからなります。

次の例では、Statistics と呼ばれる知識ベース (ファイル statisti.kb に入っています) があり、これは Application (ファイル applicat.kb に入っています) と呼ばれる別の知識ベースによって使用されます。

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

Statistics をその USES セクションで宣言することによって、 Application のルーチンが Statistics によって定義された 3 つのプロシージャーを呼び出すことができるようになります。

USES セクションの紹介

USES セクションは、USES キーワードによって紹介され、次の場所の 1 つ (または両方) に入っていなければなりません。

複数の知識ベースの使用

知識ベースは、必要とする数の他の知識ベースを使用することができます。使用される各知識ベースは、USES セクションにリストし、後にセミコロンを付けなければなりません。

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

知識ベースの私的使用

知識ベースは、知識ベースの私用セクションの USES ステートメントに含まれる時には、私的に使用されます。

知識ベースが私的に使用されると、その公用変数およびプロシージャーは、公用セクションに宣言されたルーチンを実装するために、私用セクションを介して使用可能になります。言い換えると、知識ベースの私用実装は、別の知識ベースの公用ルーチンから構成されます。

2 つの知識ベースは、私用セクションで互いの名前を指定している限り、制約なしに私的に相互使用することができます。すなわち、知識ベース A は、知識ベース B を使用することができます。またその逆も可能です。

知識ベースの公的使用

知識ベースは、知識ベースの公用セクションの USES ステートメントに含まれる時には、公的に使用されます。

知識ベースが公的に使用されると、使用された知識ベースからの記号は、知識ベース全体を通して使用可能になります。

使用中の知識ベース中のある種の公用宣言に知識ベースからの記号が必要な時には、その知識ベースを公的に使用しなければなりません。
この例として、1 つの知識ベースに定義されたレコード・タイプが別の知識ベースのレコード・タイプ宣言で使用される場合があります。

公用知識ベースの循環使用

循環使用は、知識ベース A が知識ベース B を、知識ベース B が知識ベース A を使用する時に起こります。 PUBLIC セクションでは、知識ベースは相互に循環使用することができません。

この制約を避ける 1 つの方法として、両方の知識ベースに必要な共通宣言を自身は何も公的に使用しない別の知識ベースに移動する方法があります。非常に異なる関数の宣言を 1 つの知識ベースに結合することは意味をなさないことがあるので、これが常に実行可能であるとは限りません。しかし、時にはこのソリューションがうまくいきます。

例として、従業員およびその従業員が働く所属部署に関する情報を記録するプログラムを作成する場合を想定してください。必要であれば、従業員に関するほとんどの情報を "Employee" と呼ばれる知識ベースにカプセル化し、所属部署に関する情報を "Department." と呼ばれる知識ベースにカプセル化することができます。

しかし、従業員レコードを扱う公用ルーチンは、時として所属部署レコードをパラメーターとして必要とします。またその逆の場合もあります。したがって、2 つの知識ベースが互いを公的に使用する必要が生じます。 これがうまくいかないので、代わりにこれらの知識ベースを次の例で示しているように編成する必要があります。

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;

プロシージャー

プロシージャーとは、名前によって参照され、呼び出し側に値を戻さない Developer's Toolkit ステートメントのコレクションです。

プロシージャーは、知識ベース内でネストされたブロックです。知識ベースそのものと同様に、プロシージャーは、定数、タイプ、変数、およびルーチンのためのセクションをもつことができます。こうしたセクション中の識別子は、プロシージャーにとってローカルなものであり、その範囲外では見ることができません。

各プロシージャーは、そのプロシージャーが実行するものを決定する実行可能 Developer's Toolkit ステートメントの位置であるアクション・セクションをもちます。

プロシージャーの一般形式は次の通りです。

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

以下は、2 つの Developer's Toolkit ステートメントが含まれているアクション・セクションをもつ簡単なプロシージャーです。このプロシージャーが呼び出されると、アクション・セクション中の 2 つのステートメントが実行されます。

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

ネストされた変数でのローカル変数の使用

プロシージャーがネストされた変数セクションにローカル変数をもつことが有効である場合がよくあります。ローカル変数 とは、その有効範囲がコードの特定ブロックに限定されるプログラム変数です。ルールとして、ローカル変数はサブルーチンに限定されます。

次の例では、WriteTenLines と呼ばれるプロシージャーが作成されます。このプロシージャーは、i と呼ばれるローカル変数を使用して、FOR ループを通して反復し、10 個のストリングをウィンドウに書き込みます。

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

この例はさらに拡張され、ローカル定数を組み込みます。

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

ローカル・ルーチンの作成

ローカル・ルーチンを作成したほうがよい場合がよくあります。特に使用したい変数がプログラムの一部分でしか発生しない場合です。ローカル・ルーチンは、別のプロシージャーまたは関数内で宣言されたプロシージャーまたは関数です。ローカル・ルーチンは、それを含むプロシージャーまたは関数、あるいはそれに含まれる他のローカル・ルーチンによってのみ呼び出すことができます。次の例を調べてください。

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;

有効範囲設定

ブロック構造言語の重要な概念の 1 つは、有効範囲です。一定のブロック内では、一定の識別子だけが存在します (すなわち有効範囲内にあります)。一般的に、ネストされたブロックは、組み込み 有効範囲内で宣言された識別子を「見る」ことができます。 組み込み有効範囲内のオブジェクトまたは識別子は、そのブロックに対してのみローカルなものとなります。

有効範囲設定の例

次の例を考えてください。

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; 

有効範囲設定の例の説明

MAX_EMPLOYEESEmployeeRecord、および employeeList は、一番外側のブロックで宣言されているので、知識ベース全体で見ることができます。これらの要素は、知識ベースの公用セクションに現れるので、それらは、この知識ベースを使用する他の知識ベースも見ることができます。

同様に、ARRAY_SIZE および employeeArray は、一番外側のブロックの私用セクションで宣言されているので、私用セクション全体で見ることができます。 ProcTwoProcOne は、共にこれらの識別子を参照することができますが、私用セクションにあるために、他の知識ベースはそれらにアクセスすることができません。

ProcTwo 中の変数 i は、ProcTwo 内でのみ見ることができます。ProcOne 中の変数 i および j は、ProcOne 内でのみ見ることができます。 ProcOne 中の i 変数は、ProcTwo 中の i 変数とは完全に無関係です。

変数値は、それらを含んでいるブロックが実行している間にのみ存在します。 たとえば、変数 i および j は、ProcOne 実行中の間でだけ値をもちます。

パラメーターの転送

プロシージャーへの情報の転送

プロシージャーを呼び出している時には、そのプロシージャーに情報を渡すことが必要になることがよくあります。
これは、次のステップで行うことができます。

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

プロシージャーが呼び出されると、渡される式の数は、そのプロシージャーに宣言されたパラメーターの数に等しくなります。 渡される式は、指定されたパラメーターと同じデータ・タイプで、同じパラメーター・タイプでなければなりません。

      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;

REF または VAL による転送

次の例では、一部のパラメーターは値 (VAL) で渡され、一部のパラメーターは参照 (REF) で渡されるということに注意してください。

VAL パラメーターでは、値が呼び出し側から呼び出されたルーチンにコピーされ、呼び出されたルーチンが行うことは、呼び出し側がまだ処理している値には影響しません。

REF パラメーターは、呼び出し側が処理するのと同じ記憶域をアドレスします。したがって、呼び出されたルーチンの実行中に生じたパラメーター値に対する変更は、呼び出し側の値で即時に効力をもちます。

次の例を考えてください。

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; 

例の説明

上の例では、DistanceFormula と呼ばれるプロシージャーが宣言されています。

このプロシージャーは、5 つの形式的な引き数をもっています。

プロシージャーが呼び出されると、渡される最初の 4 つの整数値のコピーがプロシージャーに送られます。 しかし、5 番目のパラメーターの場合、呼び出し側によって送られた実際の変数がプロシージャーに渡されます。

プロシージャーが値によって渡されるパラメーターを必要とする場合には、呼び出し側は次のものを送ることができます。

しかし、プロシージャーが参照によって渡されるパラメーターを必要とする場合には、呼び出し側は変数のみを送ることができます。

変数としてのパラメーターの扱い

プロシージャーは、渡されたすべてのパラメーターを変数として扱うことができます。プロシージャーは次のことを行うことができます。

値によって渡されたパラメーターに行われた変更は、呼び出し側に送り返されません。

前の例では、対応するパラメーターが VAL キーワードで宣言されていたので、 ComputeDistances が 4 つの整数引き数のリテラル値を DistanceFormula を送りました。しかし、5 番目のパラメーターは REF キーワードで宣言されているので、ComputeDistances は、5 番目の引き数の変数のみを渡しました。

注: デフォルトのパラメーター・タイプはありません。プロシージャー宣言の各パラメーターには VAL か REF のいずれかを指定しなければなりません。

関数

関数はプロシージャーと同様ですが、値を呼び出し側に戻す点か異なります。この理由のため、関数は、割り当てまたは式でのみ使用することができます。ステートメントとして使用することはできません。

関数は単純なタイプ (ストリング、整数、実数、ブール値、日付、時刻など) を戻す他に、構造化タイプおよびユーザー定義タイプを戻すことができます。

レコードのリストを戻す関数を書くこともできます。

関数の形式

関数は、次の一般形式をもっています。

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; 

関数の例

次の例では、DistanceFormula は、プロシージャーではなく、関数となるように変更されています。

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; 

注: すべての関数は、パラメーター・リストの後に続き、コロンでそのリストと区切られている明示の戻りタイプをもっていなければなりません。

$Result の使用

$Result は、関数の現在の戻り値にアクセスするために、その関数の本体内で使用することができます。 関数本体でそれを設定またはテストすることができます。

DistanceFormula に対する次の変更を考えてください。

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

この例では、関数の戻り値が $Result によって設定されています。

$Result は、関数本体で何度も割り当てることができます。 $Result は、関数の戻り値に宣言されたデータ・タイプを自動的にもちます。

関数での Exit の使用

Exit が関数で使用されると、次のようになります。

関数内で Exit ステートメントを使用する時には、戻したい値を示すパラメーターをそれに与えることができます。

Exit (42); 

is the same as:

$Result := 42;
Exit;

関数が Exit ステートメントを使用せずに終了した場合には、 $Unknown の値が戻されます。

Exit は、次を行うタスクを結合します。

ライブラリー・プロシージャーおよび関数の呼び出し

Developer's Toolkit で書かれたプログラムからの C または C++ で書かれたルーチンへのアクセスは、Developer's Toolkit の外部ルーチンのメカニズムによって提供されます。

外部ルーチンは次の 2 つの部分から構成されます。

Developer's Toolkit の宣言構文

Developer's Toolkit 4.2 からは、Developer's Toolkit の宣言構文は、基礎となる Developer's Toolkit データ構造を広範囲に及んで理解しなくても、ほとんどのインターフェース要件をサポートするようになっています。

外部ルーチンを呼び出すには、Developer's Toolkit のインタープリターが次のことを指示するルーチンの宣言をもっていなければなりません。

外部ルーチンの構文

外部ルーチン宣言の構文は、以下の例に示してあります。 Developer's Toolkit ルーチンのどのような実装についても、こうした宣言は、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];

DLL 名は、外部ルーチンがあるライブラリーを識別する定数ストリング式です。 .dll 拡張子は、通常はプラットフォームごとに異なり、一般的には指定される名前から除外されます。

エントリー・ポイント

エントリー・ポイントは、プログラムまたはルーチン中で実行を開始できる位置です。ルーチンは通常、ただ 1 つのエントリー・ポイントをもちます。エントリー・ポイントは次のいずれかにすることができます。

ストリングはエントリー・ポイントの名前を表し、整数はライブラリー中のその序数を表します。

関数名の組み立て

C++ コンパイラーは一般的に、名前マングリングと呼ばれる手法を使用して、個別にコンパイルされたオブジェクト・モジュール間で正しいリンケージができるようにします。
C++ で書かれた外部関数は通常、C++ ソース・コードで宣言された外部 "C" であるか、あるいはその序数によってロードされなければなりません。

リンケージ仕様

外部ルーチン宣言中のリンケージ仕様は、次の記号の 1 つでなければなりません。

注: 呼び出される DLL が Microsoft Visual C++ によってコンパイルされたものでなかった場合には、「参照による転送」引き数のために、Developer's Toolkit DLL コールアウト機能は失敗します。

OS/2 上の IBM C++ の場合、プロトコルは _Optlink_ です。

OS/2 の場合、プロトコルは _System です。

外部ルーチン宣言からリンケージ仕様がまったく省略されている場合には、リンケージは デフォルトの $STANDARD となります。

すべての UNIX オペレーティング・システムでは、規則はコンパイル固有です。ライブラリーが Cまたは C++ で書かれている場合には、$C を使用します。そうでない場合には、 $System を使用します。

外部ルーチンの単純パラメーター・タイプ

第三者ライブラリーの使用を容易にするために、TSD Script は、単純 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); 

タイプ SHORT、USHORT、LONG、ULONG、PSZ、FLOAT、および DOUBLE は、ファイル TSD Script.KB にあるシステム知識ベース中で提供されます。

外部 DLL タイプのマッピング

外部 DLL タイプは、TSD Script によって、C および C++ で使用されるもっとも一般的な低レベル・データ・タイプにマップされます。 余分な宣言構文は、TSD Script インタープリターにデータのマップ方法を指示します。

たとえば、SHORT の宣言は、値が 2 バイトの整数にパックされることを告げます。 デフォルト宣言は、$Unknown が SHORT パラメーターを介して外部ルーチンに渡されようとした場合に、それによって実行時エラーが起こるということを示します。

PSZ の宣言は、値がポインターとしてパックされなければならないこと、および $Unknown がゼロ (ヌル) ポインターとして渡されなければならないこと告げます。

以下は、Microsoft Windows によって提供された ExitWindows 関数をどのようにして宣言するかの例です。

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

注: TSD Script "integer" は long (32 ビット) 値であり、"int" は、C では常に機能しません。

外部ルーチンのパラメーター転送

通常 TSD Script ルーチンのパラメーターと同様に、外部ルーチンのパラメーターは、次のものによって渡されるものとして指定されます。

VAL パラメーター

外部ルーチンに対する VAL パラメーターは、非外部ルーチンに対する VAL パラメーターと非常によく似た働きをします。

値は呼び出し側から呼び出されたルーチンにコピーされ、呼び出されたルーチンが行うものは、呼び出し側がまだ処理している値には影響しません。

VAL によって渡されたストリングもポインター (コピーされる TSD Script ストリングのコピーが入れられている一時記憶域位置を示すもの) として、外部ルーチンによって受け取られます。

REF パラメーター

外部ルーチンの場合、REF パラメーターは、VAL パラメーターと少し異なります。

非外部ルーチンは、REF パラメーターを受け取ると、呼び出し側が処理するのと同じ記憶域をアドレス指定します。呼び出されたルーチンの実行時のこのパラメーターの値に対する変更は、呼び出し側の値で即時に効力をもちます。

外部ルーチンに対する参照による転送は、実際にはコピー・イン / コピー・アウトとして実装されます。差は微妙ですが、ある種の状況の下では、動作は見極められます。たとえば、外部ルーチンからのメッセージのディスパッチがこの動作の例です。

データ・タイプ STRING (および PSZ などの別名) は例外であり、REF によって渡される時には、実際の TSD Script ストリングを示すポインターによって渡されます。

すべての REF パラメーターは、ポインターとして外部 C または C++ ルーチンに渡されます。 TSD Script は、参照の C++ 概念をサポートしようとしません。参照パラメーターを取る C++ ルーチンを呼び出す必要がある場合には、小さいラッパー関数を書くことができます。ラッパーは、TSD Script からポインターを取り出し、その参照を解除して、必要な C++ 関数と一緒に渡します。

TSD Script は const の ANSI の C および C++ 概念を直接にはサポートしないので、TSD Scriptのプログラマーは、C/C++ 関数が const ポインター引き数を取る時には、一般的にパラメーターを REF として宣言します。

データの変換

TSD Script と外部ルーチンの間でデータを受け渡しするには、データを代替形式に変換しなければならないことがよくあります。外部ルーチンが呼び出される前に、呼び出し側の値は次のようになります。

その結果、パラメーターが REF パラメーターである場合には、呼び出し側に戻った後に、一時域がアンパックされて呼び出し側の記憶域に戻されます。

データ構造および 2 進パッキング

単純なタイプを使用してかなり精密なインターフェースを構成することができますが、結局、集合データ構造を外部ルーチンに渡すことになります。
Developer's Toolkit 4.2 では TSD Script に新しい構文が追加されており、これにより、TSD Script データがどのように C または C++ データ構造にマップされるかを詳しく記述する明示指定が可能になります。これ以降このマッピングを 2 進パッキングと呼びます。

2 進パッキング情報は名前付きタイプ宣言中、あるいはレコード宣言内のフィールド仕様中のタイプ仕様に対する注釈として提供されています。両方の場合の大体の構文を次に示します。

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

データ注釈形式

次の注釈は、TSD Script データがパックされる形式を指定します。 これらは、すべて排他的です。

注釈 説明
INT(width) INT 注釈は、フィールドが指定された幅で固有の整数形式にパックされることを指定します。 幅の正規の値は 1、2、および 4 です。INTEGER に明示的に変換可能などの TSD Script データ・タイプでも、INT としてパックすることができます。
UINT(width) UINT 注釈は、フィールドが指定された幅をもつ符号なしの値として現地国の整数形式にパックされることを指定します。TSD Script から外部ルーチンに値を渡す時には、INT と UINT のいずれの場合にも同じビット・パターンが渡されるので、その間には目立った差はありません。しかし、1 バイトまたは 2 バイトの値が外部ルーチンから TSD Script に送り戻される時には、値がどのように符号拡張されるかは、INT と UINT の差によって決定されます。再び言及しますが、幅の正規の値は 1、2、および 4 です。
NUMERIC(width) NUMERIC 注釈をもつフィールドは、一定の幅になるようにブランクを埋め込まれた文字列としてパックされます。TSD Script の Real、Integer、および Integer に変換できる他のデータ・タイプは NUMERIC フィールドとしてパックされます。
FLOAT(width) FLOAT 注釈をもつフィールドは、指定された幅の IEEE 浮動小数点数としてパックされます。有効な幅は 4 と 8 です。明示的に REAL に変換可能な TSD Script タイプはどれも FLOAT としてパックすることができます。
BCD(width) BCD 注釈をもつフィールドは、2 進化 10 進数としてパックされます。明示的に REAL に変換可能な TSD Script のタイプはどれも BCD としてパックすることができます。
CHAR(width) CHAR 注釈をもつフィールドは、一定の幅の単純文字配列としてパックされます。 STRING に変換可能な TSD Script のタイプはどれも CHAR としてパックすることができます。
ZSTRING(width) ZSTRING 注釈をもつフィールドは、一定の幅のヌル終結 (C スタイル) ストリングとしてパックされます。STRING に変換可能な TSD Script のタイプはどれも ZSTRING としてパックすることができます。
LSTRING(width) LSTRING 注釈をもつフィールドは、ストリングの長さを含む先行バイトをもつ Pascal スタイルのストリングとしてパックされます。STRING に変換可能な TSD Script タイプはどれも LSTRING としてパックすることができます。
ASE_DATE ASE_DATE 注釈をもつフィールドは、DATEREC 構造としてパックされます。明示的に DATE に変換可能なデータ・タイプはどれも ASE_DATE としてパックすることができます。
BTRV_DATE BTRV_DATE 注釈をもつフィールドは、Btrieve スタイルの日付としてパックされます。明示的に DATE に変換可能なデータ・タイプはどれも BTRV_DATE としてパックすることができます。
CCYYMMDD CCYYMMDD 注釈をもつフィールドは、それぞれが 2 バイトにパックされる世紀、年、月、および日を含む文字ストリングとしてパックされます。明示的に DATE に変換可能なデータ・タイプはどれも CCYYMMDD としてパックすることができます。
ASE_TIME ASE_TIME 注釈をもつフィールドは、TIMEREC としてパックされます。明示的に TIME に変換可能なデータ・タイプはどれも ASE_TIME としてパックすることができます。
BTRV_TIME BTRV_TIME 注釈をもつフィールドは、Btrieve スタイルの時刻としてパックされます。明示的に TIME に変換可能なデータ・タイプはどれも BTRV_TIME としてパックすることができます。
HHMMSS HHMMSS 注釈をもつフィールドは、それぞれが 2 バイトにパックされる時、分、および秒を含む文字ストリングとしてパックされます。明示的に TIME に変換可能なデータ・タイプはどれも HHMMSS としてパックすることができます。
POINTER POINTER 注釈をもつフィールドは、その実際の TSD Script データを示す 32 ビットのポインターとしてパックされます。TSD Script 中の非集合データ・タイプはどれも、POINTER としてパックすることができます。
NOEXPORT NOEXPORT 注釈は、外部 2 進表現にまったく組み込まれていないフィールドをマークします。どのタイプのフィールドでも NOEXPORT とマークすることができます。

デフォルト値注釈

形式の注釈に加えて、デフォルト値の注釈を指定することができます。 デフォルト値の注釈は、TSD Script 値が不明である時に、2 進構造中のフィールドを埋め込む方法を TSD Script のインタープリターに指示します。デフォルト値注釈の構文は次の通りです。

DEFAULT( $ERROR|expression ) 

$ERROR が指定された場合、不明の値をパックすると、TSD Script のインタープリターは、エラー・メッセージを表示して、外部ルーチンを打ち切ります。

これは、値注釈が指定されていない時のデフォルトです。

式が指定された時には、その式が評価され、TSD Script 値が不明であると、その値が形式注釈に従ってパックされます。この機能は、不明のストリングをヌルにマップするために使用されます。

パッキング注釈

一連のフィールド仕様では、対応するフィールド名もデータ・タイプもなしで、パッキング注釈を提供することができます。 これらの注釈は、2 進構造中で TSD Script レコードに現れないフィールドを指定します。これは、フィールド自身が TSD Script レコードに現れないために起こります。そのフィールドの値で追加の注釈を提供しなければなりません。

この特殊な注釈の構文は次の通りです。

フィールドがパックされるたびに、与えられた式が評価され、対応する形式注釈に従ってパックされます。

FILL 注釈

最後に、フィールド位置合わせの目的で、FILL 注釈を使用し、2 進構造内のフィールド間に任意の数の埋め込みバイトを配置することができます。

FILL 注釈の構文は次の通りです。

FILL( width [ , value ] ) 

幅で指定された数のバイトおよび一定の値を含むバイトが 2 進構造にパックされます。FILL 注釈にはどのような定数整数値でも指定することができますが、実際にパックされたバイトには、一番有効でない 8 ビットだけが含まれるので、-128 - 255 は値の有効範囲を表します。デフォルト値はゼロです。

明示のパッキング注釈のない名前付きのタイプおよびフィールドは、その基礎となるタイプのデフォルトに従ってパックされます。
次の表は、組み込みの非集合 TSD Script データ・タイプのデフォルトを示したものです。

タイプ デフォルトのパッキング情報 デフォルトの結果
Boolean INT(1) DEFAULT($ERROR)
Integer INT(4) DEFAULT($ERROR)
Real FLOAT(8) DEFAULT($ERROR)
String POINTER DEFAULT(0)
Time ASE_TIME DEFAULT($ERROR)
Date ASE_DATE DEFAULT($ERROR)
ウィンドウ、ファイル (ハンドル・タイプ) UINT(4) DEFAULT($ERROR)

Tivoli Service Desk 6.0 Developer's Toolkit Script プログラミングの手引き

目次に戻る

著作権