ソースコード生成
- ソースコード生成の概要
- 1. コード生成を行うJava プログラムの呼び出し
- 2. 実行パラメタの解析
- 3. 作業用ディレクトリの作成
- 4. mapping definition の妥当性検証
- 5. mapping definition にファイル名・行番号埋め込み
- 6. UMS の単純化
- 7. define/ref の展開
- 8. UMS の単純化、define / ref 展開後の妥当性検証
- 9. mapping definition に対応した XSLT の生成・マージ
- 10. mapping definition のチェック処理
- 11. mapping definition を Language syntax へ変換
- 12. ソースコード生成
- [拡張機能] デバッグ情報の出力
- [拡張機能] 生成ソースコードの最適化
ソースコード生成の概要
umsCodeGenerator は、シェル、Java、XSLT で実装されています。 各実装の処理内容は以下の通りです。
実装 | 処理内容 | 備考 |
---|---|---|
シェル | コード生成処理全体を実行する Java プログラムを呼び出す | Bourne シェルを使用。C シェルは使用しない。 |
Java |
コード生成処理全体を実行(バリデータの実行、XSLT 変換など) ファイル出力 XSLT を生成 変数定義 XSLT を生成 |
|
XSLT |
mapping definition のチェック mapping definition の編集 mapping definition からソースコードへ変換 |
XSLT プロセッサは Xalan-Java を使用する。 実装 XSLT 一覧 |
ソースコードの生成は、以下のステップで行います。
- コード生成を行うJava プログラムの呼び出し
- 実行パラメタの解析
- 作業用ディレクトリの作成
- mapping definition の妥当性検証
- mapping definition にファイル名・行番号埋め込み
- UMS の単純化
- define/ref の展開
- UMS の単純化、define/ref 展開後の妥当性検証
- mapping definition に対応した XSLT の生成・マージ
- mapping definition のチェック処理
- mapping definition を Language syntax へ変換
- ソースコード生成
設計メモ:build〜コード生成までの流れ
1. コード生成を行うJava プログラムの呼び出し
コード生成時に使用する各種ライブラリをパスに設定し、コマンドラインオプションを引数にして コード生成を行う Java プログラムを呼び出します。
[参照ファイル]
src/txt2clng.tmpl
src/txt2java.tmpl
2. 実行パラメタの解析
"txt2lang" の実行オプションの解析を行います。 実行オプションの指定が不適切な場合は、USAGE を表示します。
パラメタの解析には、Jakarta-Commons プロジェクトで提供されている、コマンドラインオプション 解析ライブラリである CLI を使用しています。
[参照ファイル]
src/java/jp/jaxa/isas/ums/codeGenerator/GeneratorMain.java
3. 作業用ディレクトリの作成
コード生成時に作成される一時ファイルを格納する一時ディレクトリを作成します。 作成するディレクトリ名は以下になります。
"$TABLETOOLS_TEMP/yyyyMMddHHmmssSSS乱数(0.0 以上 1.0 未満の double 値)"
[参照ファイル]
src/java/jp/jaxa/isas/ums/codeGenerator/WorkDirectory.java
4. mapping definition の妥当性検証
MSV と Jing を使用して、mapping definition がスキーマ通り記述されているかどうか の妥当性を検証します。 コマンドラインオプションに指定された組み合わせに応じて、妥当性検証を かけるスキーマを選択します。 各 mapping definition に対応するスキーマの組み合わせは以下の通りです。
mapping definition | スキーマ |
---|---|
XML syntax(C 言語) | dat_xml-clng.rng |
XML syntax(Java) | dat_xml-java.rng |
Language syntax(C 言語) | dat_lang.rng |
Language syntax(Java) | dat_lang.rng |
この時、value 要素の type 属性に指定された値に応じた 制約 facet についても妥当性を検証します。 現在サポートしているデータ型については、 encodengLibrary を参照してください。
[参照ファイル]
src/java/jp/jaxa/isas/ums/codeGenerator/XmlValidator.java
設計メモ:value 要素の制約 facet
5. mapping definition にファイル名・行番号埋め込み
mapping definition の記述ミスチェック時や、エラー情報の出力時に mapping definition ファイルの以下の情報を出力します。
- ファイル名
- 行番号
- 列番号
mapping definition の記述ミスのチェックや、エラー情報を出力するコードの 生成は XSLT で行います。 そのため、XSLT でこれらの情報を取得できるよう、要素の属性値として mapping definition に埋め込みます。
[参照ファイル]
src/java/jp/jaxa/isas/ums/codeGenerator/XmlEditor.java
6. UMS の単純化
ここでは、UMS 仕様書の「4.3. datatypeLibrary 属性」と「4.4. value 要素の type 属性」 についての単純化を実施します。 それぞれの項目に対して、以下の処理を行います。
項目 | 処理 |
---|---|
4.3. datatypeLibrary 属性 |
datatypeLibrary 属性を持たない data 要素、value 要素に対して、 datatypeLibrary 属性を持つ直近の祖先要素の datatypeLibrary 属性の値を付与する。 data 要素、value 要素以外に付属している datatypeLibrary 属性を取り除く。 |
4.4. value 要素の type 属性 |
type 属性を持たない value 要素に対して、値が token である type 属性を付与し、 datatypeLibrary 属性の値を空文字に置き換える。 |
[参照ファイル]
src/xslt/raw/simplify.xsl
7. define/ref の展開
umsCodeGenerator での処理を簡略化するため、mapping definition で定義されている define 要素と ref 要素の展開を行います。
[参照ファイル]
src/xslt/raw/resolveRef.xsl
設計メモ:XML ファイルの再帰的なコピー
8. UMS の単純化、define / ref 展開後の妥当性検証
UMS の単純化、define /ref の展開を行った後も、スキーマに対して妥当性であるかを 検証します。 各 mapping definition に対応するスキーマの組み合わせは以下の通りです。
mapping definition | スキーマ |
---|---|
XML syntax(C 言語) | simple_dat_xml-clng.rng |
XML syntax(Java) | simple_dat_xml-java.rng |
Language syntax(C 言語) | simple_dat_lang.rng |
Language syntax(Java) | simple_dat_lang.rng |
[参照ファイル]
src/java/jp/jaxa/isas/ums/codeGenerator/XmlValidator.java
9. mapping definition に対応した XSLT の生成・マージ
9.1 ファイル出力テーブル XSLT の生成
生成されるソースコードのファイル名は、*.ums の拡張子を変更したものになります。 しかし、file タグを用い、特定の部分を指定したファイルに出力することも可能です。
ファイル名の定義は mapping definition 内に記述されるため、mapping definition に 応じたファイルの切り分け処理を行う XSLT を生成します。 ファイルの切り分け処理は、Xalan-Java の拡張機能を使用します。
[参照ファイル]
src/java/jp/jaxa/isas/ums/codeGenerator/FileOutputTableCreator.java
設計メモ:出力ファイルの振り分け
9.2 変数変換テーブル XSLT template の生成
マッピングの定義は、mapping definition の defineMapping 要素内に記述されます。 defineMapping 要素内には、変数名のみが記述されますが、変数の型定義は defineMapping 要素の外部で定義されます。 そのため、XSLT 変換を行う際に defineMapping 要素内に現れる変数がどのような型 であるかを、処理系が知っている必要があります。
そこで、defineMapping 内で使用される変数名と型との対応情報を取得可能な XSLT の template を生成します。
[参照ファイル]
src/java/jp/jaxa/isas/ums/codeGenerator/VarTypeTableCreatorForClng.java
src/java/jp/jaxa/isas/ums/codeGenerator/VarTypeTableCreatorForJava.java
設計メモ:変数変換テーブル
9.3 XSLT template のマージ
XSLT 形式に変換した変数変換テーブルを基本のスタイルシートにマージし、 今回処理用のスタイルシートを作成します。 これは、単純に、基本スタイルシート内に、XSLT の template を挿入する処理です。
"pre_txt2lang.xsl" 中の <xsl:template name="varTypeDefinition"/> という部分を、 9.2 で生成した template に置き換えます。
[参照ファイル]
src/java/jp/jaxa/isas/ums/codeGenerator/Generator.java
10. mapping definition のチェック処理
mapping definition の制約と、 UMS 仕様書の制限のチェックを行います。チェックする項目は、以下の通りです。
- define 要素の子孫に、optional 、oneOrMore、zeroOrMore が記述されていないか。
- loop のネストが 32 を超えていないか?
- byte 要素、list 要素の祖先に bit 要素が記述されていないか?
- bit 要素の encode 属性の値に "txt" が指定されていないか?
- method の値として、"2"、"3"、"4" 以外が指定されていないか?
- umsCodeGenerator がサポートしているタグ以外のタグが記述されていないか?
- 環境変数 UMS_THREAD に "true" 以外の値が設定されている際に、制御構造のタグが指定されていないか?
- UMS 仕様書「7.1.5. start 要素」に記述された、禁止されているパスを含んでいないか?
[参照ファイル]
src/xslt/raw/check_mappingdef.xsl
src/xslt/raw/check.xsl
11. mapping definition を Language syntax へ変換
9.3 でマージされた XSLT を使用し、 XML syntax の mapping definition を、Language syntax へ変換します。 入力 mapping definition が Language syntax だった場合は、mapping definition の内容は 変化しません。
[参照ファイル]
src/xslt/raw/pre_txt2clng.xsl
src/xslt/raw/pre_txt2java.xsl
12. ソースコード生成
以下のステップでソースコードを生成します。
- <post:* /> と file 要素を含んだソースコードへ変換
- <post:* /> を展開し file 要素を含んだソースコードへ変換
- file 要素に応じて出力ファイルを振り分け
設計メモ:XSLT デザインパターン(preタグの展開)
設計メモ:スタイルシートの整理
設計メモ:ソースコードに mapping definition をコメントとして出力
設計メモ:tableTools と umsCodeGenerator を切り分ける XSLT template
12.1 <post:* /> と file 要素を含んだソースコードへ変換
ソースコードへ変換するスタイルシートは、言語ごとに用意されています。 トップのスタイルシートは言語ごとに別物が用意されており 以下のようになっています。
ファイル名 | 役割 |
---|---|
txt2clng.xsl | テキスト/バイナリデータとC 言語のマッピング用 |
txt2chdr.xsl | テキスト/バイナリデータとC 言語のマッピング用(ヘッダファイル生成) |
txt2java.xsl | テキスト/バイナリデータとJAVAのマッピング用 |
"txt2lang.xsl" は処理が多岐にわたります。 そのため、mapping definition に記述する要素ごとに、それぞれの処理を行う XSLT を作成しています(ファイル名の多くは "要素名.xsl")。
これらの XSLT は "txt2clng.xsl"、"txt2java" の両方から呼び出されるため、 C言語とJAVAの共通部分にどちらか固有なコードを記述してはいけません。 言語毎に異なる処理が必要な場合は、それぞれ専用のテンプレートを用意するか、 後述する post 処理で内容を選択するかのいずれかの方法を用います。 "txt2lang.xsl" では、それぞれの XSLT を xsl:include で含めます。
[参照ファイル]
src/xslt/raw/txt2clng.xsl
src/xslt/raw/txt2chdr.xsl
src/xslt/raw/txt2java.xsl
12.2 <post:* /> を展開し file 要素を含んだソースコードへ変換
C 言語と Java の文法の記述を吸収し、XSLT を共通化するために、マクロを使用します。 しかし、XSLT には標準でマクロの機能がないため、"post" 名前空間の要素を定義し、 マクロの機能を実現します。
post マクロで定義するものは、以下になります。
- 例外処理
- 構造体/クラス変数のアクセス
- 関数/メソッドのインターフェース
この他、強力な以下の2つのマクロがあります。 しかし、使用する頻度は必要最低限にしてください。
マクロ | 役割 |
---|---|
<post:clng/> | 子ノードに任意の C言語 のみのソースコードを記述する |
<post:java/> | 子ノードに任意の JAVA のみのソースコードを記述する |
[参照ファイル]
src/xslt/m2/secondTransform_clng.xsl
src/xslt/m2/secondTransform_java.xsl
src/xslt/m3/secondTransform_java.xsl
src/xslt/m4/secondTransform_clng.xsl
src/xslt/raw/post_clng.xsl
src/xslt/raw/post_java.xsl
設計メモ:post 処理による XSLT 変換
12.3 file 要素に応じて出力ファイルを振り分け
9.1 で生成された XSLT を使用し、最終的に出力ファイルを振り分けます。
以上でソースコードの生成は終了です。
[拡張機能] デバッグ情報の出力
umsCodeGenerator 実行時に "-d" オプションを付与することにより、デコード/エンコード 処理時に以下の情報を出力するコードを生成する。
- mapping definition の処理位置(行番号、要素名)
- 稼動中のスレッド数
- 稼動中のスレッド番号
- タスク制御関数の実行状況
設計メモ:デバッグ情報の出力
[拡張機能] 生成ソースコードの最適化
「最適化しないオプション」を、umsCodeGenerator 実行時に指定できるようにする案が 出たが、オプションを追加するかどうかは 2006/10/27 現在保留中。 2006/10/27 現在の実装としては、最適化しないオプションを "false" の状態で保持 し、コード生成処理を行っている。
[参照ファイル]
src/java/jp/jaxa/isas/ums/codeGenerator/GeneratorMain.java
設計メモ:生成コードの最適化