TECS CDLによるコンポーネント記述
コンポーネント記述言語TECS CDLでは、概ね以下の順序で記述していきます。
- 型定義、構造体定義、定数定義
- シグニチャ定義
- セルタイプ定義
- セル定義(組上げ記述)
さて、それではこのsample1をコンポーネント記述言語で表していきます。小さな例ではありますが、すべてを示すにはページが足りませんので、それぞれの要素を抜き出して説明します。
C言語定義の取り込み
以下の記述で、kernelの型定義(C言語記述)を取込みます。
import_C( "kernel.h" );
取込まれるのはtypedefで定義された型だけです。
定数定義
定数を定義します。ここで定義した定数は、セルの属性の初期値に使います。
const PRI MAIN_PRIORITY = 5; /* メインタスクの優先度 */ const PRI HIGH_PRIORITY = 9; /* 並列に実行されるタスクの優先度 */
シグニチャsMainの定義
シグニチャは、関数頭部の集合で、提供するまたは必要とする機能を定義します。以下は、TOPPERS/JSPのタスクを制御するためのシグニチャの例です。
signature sTask {
/* タスク管理機能 */
ER act_tsk(void);
ER_UINT can_act(void);
ER ter_tsk(void);
ER chg_pri([in] PRI tskpri);
ER get_pri([out]PRI *p_tskpri);
... タスク付属同期機能など省略
};
シグニチャの定義は、キーワードsignatureに続いてシグニチャ名を記述します。
[ ]で囲んだ内側に、関数頭部を列挙します。
関数頭部の文法はC言語に似ていますが、[ ]で囲んだ中に、引数の特性(指定子)を記述する必要があります。逆にこの[ ]で囲んだ部分を取り除けば、C言語の関数頭部となるようになっています。
この形式は、OSFのDCE RPCのインタフェース定義言語(IDL)を参考にして取り入れました。マイクロソフト社のCOMはDCE RPCをオブジェクト指向拡張したものですので、類似性があります。しかしTECSでは[ ]に記述する指定子は、組込みの特性を考慮したものになっていて、DCE RPCやCOMのものとは異なりますので注意が必要です。
表1の4つは基本指定子で、引数の入出力方向と格納領域を指定します。これらのうち、どれか1つだけ必ず指定します。
| in | 入力引数です。引数は、非ポインタ型か配列の場合はconstへのポインタ型になります |
| out | 出力引数です。引数の型はポインタ型で、格納領域は呼び元が確保します |
| inout | 入出力引数です。outと同じ型の制限があります |
| send(allocator) | 入力引数ですが、記憶領域はアロケータによって確保されており、呼び先は受け取った後、解放する必要があります。sendはアロケータを引数にとります。引数の型はポインタ型になります |
| receive(allocator) | 出力引数ですが、記憶領域はアロケータにより確保されており、呼び元は受け取った後、解放する必要があります。receiveはアロケータを引数に取ります。引数は二重ポインタ型になります |
引数が配列の場合、表2のいずれかにより、引数または転送するデータの大きさを指定します。
| size_is(size) | 引数はsizeの大きさの配列です。sizeは式で、他のパラメータを含めることができます |
| count_is(count) | 引数の配列はcountの大きさが有効な値を持ちます。size_isが指定されずcount_isのみ指定されている場合には、sizeはcountと同じであるとみなされます。countは式で、他のパラメータを含めることができます |
| string | 引数はNULL終端された配列です。この場合、最大長が指定されませんので、バッファオーバーランを起こさないことの保証がなく、使用は推奨されません |
| string(length) | 引数はNULL終端されているか、長さlengthの配列です。長さがlengthに一致する場合、NULL終端されているとは限りません。lengthは式で、他のパラメータを含めることができます |
なお上記の説明は、文字列配列の場合の説明を省略するなど、実際の定義に比べやや簡略化したものになっています。戻り値の型として、ERまたはER_UINT型が推奨されます。これは、ITRONの標準的な戻り値の型です。
引数が構造体の場合、配列へのポインタのメンバについては、やはりsize_is指定子により配列の大きさを指定する必要があります。また、voidの使用は推奨されません。
指定子により、引数にポインタや構造体が指定された場合のデータ構造が明確化され、関数の呼び元と呼び先で設計者の思惑がずれていたというようなことを防ぐことができます。
さらに、リモート呼出しの際に渡すべき値や、トレース機能で表示すべき引数の内容が明確になりますので、機械的にこれらのコードを生成することができます。
