/*****************************************************************************
 * Bison/Flexプログラム部分をテストするための、Windowsアプリケーションの雛型 *
 * □ビルド・実行方法:                                                       *
 * ┃"C:\Program Files (x86)\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT"  *
 * ┃make -f winapp.mk run                                                   *
 *****************************************************************************/
#ifndef __WINAPP_H__
#define __WINAPP_H__
/*{{定型コード:winapp.h======================================================*/
#include <clip.h>
/* y.tab.y */
extern int yynerrs;
#if     (YYDEBUG!=0)
extern int yydebug;
#endif/*(YYDEBUG!=0)*/
int yyparse();
void yyerror(const char* fmt, ...);
/* lex.yy.l */
extern FILE* yyin;
extern FILE* yyout;
extern int yylineno;
int yylex();
void yylex_init(FILE* input_file);
/* winapp.c */
void push_location(const char* path);
void pop_location();
/*}}定型コード:winapp.h======================================================*/
/*---------------------------------------------------------------------------*/
/* 構造体定義 */
//keyBody
typedef struct _ST_KeyBody {
	struct _ST_KeyBody*	redir;				//optimize2()で設定する。	NULLでなければ最適化により別のキーボディに統合された事を示す。二段階以上に辿る可能性も有ることに注意せよ。
	union {
		int		index;				//optimize2()で設定する。	走査順で前方(インデクスが小さい方)のキーボディにのみ一致させ、後方(インデクスが大きい方)には一致させないために、連番を振る。
		int		addr;				//setKeyBodyAddr()で設定する。
	};
	int			bPreventDeletion;		//(bPreventDeletion==1)ならば、もしキーボディが空でも、最適化によって削除されない。キーボディが空でない場合は、bPreventDeletionは関係無い。	//{{2018/04/12追加:「prevent-deletion」を追加しました。}}
	//キー
	ght_hash_table_t*	ht_Key;
	struct obstack		o_Key;				//高速化のためにo_Keyを使ってTBL_Keyを伸張する事にした。
	int			nKey;
	struct _ST_Key**	TBL_Key/*[nKey]*/;
	//値
	ght_hash_table_t*	ht_ValueRow;
	struct obstack		o_ValueRow;			//高速化のためにo_ValueRowを使ってTBL_ValueRowを伸張する事にした。
	int			nValueRow;
	struct _ST_ValueRow**	TBL_ValueRow/*[nValueRow]*/;
	//文字列
	ght_hash_table_t*	ht_StringRow;
	struct obstack		o_StringRow;			//高速化のためにo_StringRowを使ってTBL_StringRowを伸張する事にした。
	int			nStringRow;
	struct _ST_StringRow**	TBL_StringRow/*[nStringRow]*/;
	//BLOB
	ght_hash_table_t*	ht_BlobRow;
	struct obstack		o_BlobRow;			//高速化のためにo_BlobRowを使ってTBL_BlobRowを伸張する事にした。
	int			nBlobRow;
	struct _ST_BlobRow**	TBL_BlobRow/*[nBlobRow]*/;
} ST_KeyBody;
//key
typedef struct _ST_Key {
	struct _ST_NameRow*	nameRow;
	struct _ST_KeyBody*	keyBody;
} ST_Key;
typedef struct _ST_Blob {
//{{2017/09/30削除:BLOBデータ作成にclipblob.cモジュールの機能を使うように変更しました。
//	struct obstack		o_data;				//高速化のためにo_dataを使ってdataを伸張する事にした。
//}}2017/09/30削除:BLOBデータ作成にclipblob.cモジュールの機能を使うように変更しました。
	int			addr;				//─2パス目で設定する。
//{{2017/09/30変更:BLOBデータ作成にclipblob.cモジュールの機能を使うように変更しました。
//	int			size;				//┬1パス目で設定する。
//	uint8_t*		data/*[size]*/;			//┤
//	int			bitsLeft;			//┘最終バイトの残りビット数。	このフィールドが1～7ならば次のビット格納要求は最終のバイトの(1<<(8-bitsLeft))の位置に格納する。このフィールドが1～7の時にbyte,half,wordの格納を行う場合はバイト境界まで進める(即ち確実にbitsLeft=0とする)。このフィールドが1～7の時もデータ全体として見れば完全なのでどのタイミングでもST_Blobのファイナライズは不要である。
//↓2017/09/30変更:BLOBデータ作成にclipblob.cモジュールの機能を使うように変更しました。
	uint8_t*		data;				//─1パス目で設定する。		'struct blob'構造体のdataフィールドを指すポインタです。(clipblob.cモジュールを参照して下さい。)
//}}2017/09/30変更:BLOBデータ作成にclipblob.cモジュールの機能を使うように変更しました。
} ST_Blob;
//nameRow
typedef struct _ST_NameRow {
	int			line;				//行番号。エラーメッセージのためだけに使用する。
	int			name;				//(0～(1<<24)-1)=数値,それ以外=文字列をstr2num()で変換した値。
} ST_NameRow;
//valueRow
typedef struct _ST_ValueRow {
	int			line;				//行番号。エラーメッセージのためだけに使用する。
	int			name;				//(0～(1<<24)-1)=数値,それ以外=文字列をstr2num()で変換した値。
	int			data;				//(0～(1<<24)-1)=数値,それ以外=文字列をstr2num()で変換した値。
} ST_ValueRow;
//stringRow
typedef struct _ST_StringRow {
	int			line;				//行番号。エラーメッセージのためだけに使用する。
	int			name;				//(0～(1<<24)-1)=数値,それ以外=文字列をstr2num()で変換した値。
	char*			s;				//文字列データ。インターン済みでTBL_String[]内の文字列を指す。
} ST_StringRow;
//blobRow
typedef struct _ST_BlobRow {
	int			line;				//行番号。エラーメッセージのためだけに使用する。
	int			name;				//(0～(1<<24)-1)=数値,それ以外=文字列をstr2num()で変換した値。
	ST_Blob*		blob;				//BLOBデータ。インターン済みでTBL_Blob[]内のデータを指す。
} ST_BlobRow;
//{{2018/04/08追加:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
//ValueType
enum {
	ValueType_bit		= 1,
	ValueType_byte,
	ValueType_half,
	ValueType_exp10,
	ValueType_word,
	ValueType_ber,
	ValueType_fp16,
	ValueType_fp32,
	ValueType_fp64,
	ValueType_str,
	ValueType_file,
};
//typedValue
typedef struct _ST_TypedValue {
	int			type;				//ValueType_*
	union {
		int		i;				//bit,byte,half,exp10,word,ber
		double		d;				//fp16,fp32,fp64
		char*		s;				//str
		GByteArray*	a;				//file
	};
} ST_TypedValue;
//}}2018/04/08追加:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
/*---------------------------------------------------------------------------*/
/* グローバル関数宣言 */
int cast_dbl_to_int(double d);
void add_keyBody(ST_KeyBody* keyBody);
ST_KeyBody* KeyBody_new();
ST_KeyBody* KeyBody_addKey(ST_KeyBody* keyBody, ST_Key* key);
ST_KeyBody* KeyBody_addValueRow(ST_KeyBody* keyBody, ST_ValueRow* valueRow);
ST_KeyBody* KeyBody_addStringRow(ST_KeyBody* keyBody, ST_StringRow* stringRow);
ST_KeyBody* KeyBody_addBlobRow(ST_KeyBody* keyBody, ST_BlobRow* blobRow);
ST_KeyBody* KeyBody_setPreventDeletion(ST_KeyBody* keyBody);	//{{2018/04/12追加:「prevent-deletion」を追加しました。}}
ST_Key* Key_new(ST_NameRow* nameRow, ST_KeyBody* keyBody);
ST_NameRow* NameRow_new(int name);
ST_ValueRow* ValueRow_new(int name, int data);
ST_StringRow* StringRow_new(int name, char* s);
ST_BlobRow* BlobRow_new(int name, ST_Blob* blob);
int Name_newExpr(int expr);
int Name_newLabel(char* label);
int Data_newExpr(int expr);
int Data_newLabel(char* label);
//{{2018/04/08削除:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
//int Bit_new(int expr);
//int Byte_new(int expr);
//int Half_new(int expr);
//int Exp10_new(int expr);	//{{2017/02/16追加:BLOBのデータ定義に'exp10'のプレフィクス指定を追加しました。}}
//}}2018/04/08削除:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
char* String_intern(char* s);
//{{2018/04/08削除:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
//ST_Blob* Blob_newBit(int bit);
//ST_Blob* Blob_addBit(ST_Blob* blob, int bit);
//ST_Blob* Blob_newByte(int byte);
//ST_Blob* Blob_addByte(ST_Blob* blob, int byte);
//ST_Blob* Blob_newHalf(int half);
//ST_Blob* Blob_addHalf(ST_Blob* blob, int half);
//ST_Blob* Blob_newWord(int word);
//ST_Blob* Blob_addWord(ST_Blob* blob, int word);
////{{2018/04/07追加:BLOBにBER圧縮整数も含められるようにしました。
//ST_Blob* Blob_newBer(int ber);
//ST_Blob* Blob_addBer(ST_Blob* blob, int ber);
////}}2018/04/07追加:BLOBにBER圧縮整数も含められるようにしました。
//ST_Blob* Blob_newFp16(double d);
//ST_Blob* Blob_addFp16(ST_Blob* blob, double d);
//ST_Blob* Blob_newFp32(double d);
//ST_Blob* Blob_addFp32(ST_Blob* blob, double d);
//ST_Blob* Blob_newFp64(double d);
//ST_Blob* Blob_addFp64(ST_Blob* blob, double d);
////{{2017/09/23追加:BLOBにヌル終端文字列も含められるようにしました。
//ST_Blob* Blob_newStr(char* s);
//ST_Blob* Blob_addStr(ST_Blob* blob, char* s);
////}}2017/09/23追加:BLOBにヌル終端文字列も含められるようにしました。
//ST_Blob* Blob_newFile(char* file);
//ST_Blob* Blob_addFile(ST_Blob* blob, char* file);
//}}2018/04/08削除:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
ST_Blob* Blob_intern(ST_Blob* blob);
//{{2018/04/08追加:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
ST_Blob* Blob_new(GSList/*<ST_TypedValue*>*/* typedBlock);
ST_TypedValue* TypedValue_newBit(int i);
ST_TypedValue* TypedValue_newByte(int i);
ST_TypedValue* TypedValue_newHalf(int i);
ST_TypedValue* TypedValue_newExp10(int i);
ST_TypedValue* TypedValue_newWord(int i);
ST_TypedValue* TypedValue_newBer(int i);
ST_TypedValue* TypedValue_newFp16(double d);
ST_TypedValue* TypedValue_newFp32(double d);
ST_TypedValue* TypedValue_newFp64(double d);
ST_TypedValue* TypedValue_newStr(char* s);
ST_TypedValue* TypedValue_newFile(char* s);
GSList/*<ST_TypedValue*>*/* TypedBlock_addValue(GSList/*<ST_TypedValue*>*/* typedBlock/*NULL可*/, ST_TypedValue* typedValue);
GSList/*<ST_TypedValue*>*/* TypedBlock_addBlock(GSList/*<ST_TypedValue*>*/* typedBlock1/*NULL可*/, GSList/*<ST_TypedValue*>*/* typedBlock2);
//}}2018/04/08追加:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
/*---------------------------------------------------------------------------*/
/*--- 変更履歴 ---*/
// * Mon Mar 23 21:35:39 JST 2015 Naoyuki Sawa
// - 1st リリース。
// * Tue Mar 24 21:30:13 JST 2015 Naoyuki Sawa
// - 最適化処理1を実装しました。
// * Thu Mar 26 21:28:16 JST 2015 Naoyuki Sawa
// - 出力データ構造を大幅に変更しました。
//   実行処理の速度アップのための変更であり、スクリプトの書式や概念は変えていません。
// - 前回までの出力データ構造では、キーの数が多い時に、検索時間が非常に長くなる問題が有りました。
//   具体的には、約10000のサブキーが有る時、末尾のサブキーを検索するのに0.01秒ぐらい掛かりました。
//   大抵、1フレームで複数回キー検索を行うと思うので、1回に0.01秒は時間が掛かりすぎです。
// - 問題の原因は、キーの配列は一要素のサイズが不定(固定長のキー名+可変長のキーボディ)で、バイナリサーチ出来なかったからです。
//   尚、値の配列は一要素のサイズが固定(固定長の値名+固定長の値データ)でバイナリサーチ出来るので、この問題は有りませんでした。
// - 今回、キーの配列も一要素のサイズを固定(固定長のキー名+固定長のキーボディ距離)にして、バイナリサーチ出来るようにしました。
//   そのために、一要素当り3バイト(キーボディ距離を24ビットで表現したため)の容量増加になりました。
//   容量増加は望ましく有りませんが、この変更を行わないと実用的な速度が出ないので、やむを得ません。
//   少しでも容量増加を抑えるために、実用上充分な24ビット距離としました。
//   16ビット距離では10000個ぐらいキーが有るとオーバーして不足するし、32ビットでは無駄が多いので、24ビットが適切と思いました。
// - 最適化処理2を実装しました。
//   上記の高速化のために容量が増えましたが、最適化処理2により容量が減るので、ある程度容量増加を相殺できたと思います。
//   要検討:最適化処理2は複数回行うようにしてあるが、必要無いかも知れません。
//   dDirSeqC.exeの場合は複数回実行する事によって2回目以降にも最適化できる箇所が出現する事を確認したのですが、
//   当ツール(dRegSeqC.exe)のアルゴリズムでは必ず1回目で全て最適化でき2回目に最適化できる箇所が出現しないような気もします。
//   今までのところ、2回目で最適化出来る箇所が出現するようなサンプルデータを作れていません。
//   複数回実行しても少し時間が掛かるだけで実行結果に悪影響は無いので、とりあえずこのままとしておく事にします。
//   今後、2回目で最適化出来る箇所が出現するようなサンプルデータが得られたら、複数回実行するままにしてください。
//   或いはもし、2回目で最適化出来る箇所が出現しない事を証明出来たら、最適化処理2の複数回実行を削除してください。
// * Fri Mar 27 21:11:31 JST 2015 Naoyuki Sawa
// - 最適化処理1,最適化処理2を複数回行っていたのをやめました。
//   最適化処理1は元から、複数回行う必要が無いのが判っていました。
//   最適化処理2を複数回行う必要が有るかどうか検討したところ、どう考えても2回目に最適化できる箇所が出現しないと思いました。
//   深さ優先で操作して前方に対して同一のキーを探して行くのですから、一回で全て見つかるはずだからです。
//   そんなわけで複数回行っても無駄だったので、一回で終了するようにして、全体の処理時間を短縮しました。
// * Fri Apr 03 00:32:50 JST 2015 Naoyuki Sawa
// - 前バージョンまでは、「optimize2()が走査順で前方のキーボディにのみマッチさせる判断」が不充分で、後方のキーボディにもマッチしまっていたバグがありました。
//   たとえば、下記のような構造で、問題が起きていました。
//   □入力ﾌｧｲﾙ
//   │1
//   │ 3
//   │  4 = 5 #//｢REG_get_value_l(TBL_RegTbl,1,3,4,-1)｣の結果が正しくは6であるべきところ(-1)になってしまうような､間違ったﾃﾞｰﾀが出力されていた｡
//   │ end
//   │end
//   │2
//   │ 3
//   │  4 = 5 #//｢REG_get_value_l(TBL_RegTbl,2,3,4,-1)｣の結果が正しくは6であるべきところ(-1)になってしまうような､間違ったﾃﾞｰﾀが出力されていた｡
//   │ end
//   │end
//   ×出力ﾃﾞｰﾀ[誤]
//   │00 00
//   │00 02
//   │ 00 01  00 00 05
//   │ 00 02  00 00 00
//   │00 00
//   │00 01
//   │ 00 03  FF FF E9 #//本来ここが｢4=5｣の値を持つｷｰﾎﾞﾃﾞｨを指すべきなのだが､｢4=5｣の値を持つｷｰﾎﾞﾃﾞｨが存在せず､ﾙｰﾄｷｰﾎﾞﾃﾞｨへの誤った相対ｱﾄﾞﾚｽになっている｡
// - 具体的には、optimize2()の間違った動作は、以下のような処理の流れで起きていました。
//   ①
//   │1
//   │ 3
//   │  4 = 5
//   │ end
//   │end
//   │2
//   │ 3
//   │  4 = 5
//   │ end
//   │end
//   ②
//   │1
//   │ 3
//   │  ----- ─┐ 最適化されて実体が無くなる !!ここで後方に最適化しているのが間違い!!
//   │ end      │
//   │end       │
//   │2         │
//   │ 3        │
//   │  4 = 5 ←┘
//   │ end
//   │end
//   ③
//   │1
//   │ 3  ←───┐
//   │  ----- ─┐│
//   │ end      ││
//   │end       ││
//   │2         ││
//   │ ------ ─│┘最適化されて実体が無くなる
//   │ ------ ←┘
//   │ ------
//   │end
//   この後、output()が'2'のキーボディを出力しないので、'3'のキーボディの参照先の実体が無く、間違ったアドレス(0)への距離が出力されていました。
// - 今回のバージョンで修正し、必ず前方のキーボディにのみマッチさせるように修正しました。
//   修正後は正しく、以下のような処理の流れになりました。
//   ①
//   │1
//   │ 3
//   │  4 = 5
//   │ end
//   │end
//   │2
//   │ 3
//   │  4 = 5
//   │ end
//   │end
//   ②
//   │1
//   │ 3
//   │  4 = 5 ←┐
//   │ end      │
//   │end       │
//   │2         │
//   │ 3        │
//   │  ----- ─┘
//   │ end
//   │end
//   ③
//   │1
//   │ 3  ←───┐
//   │  4 = 5 ←┐│
//   │ end      ││
//   │end       ││
//   │2         ││
//   │ ------ ─│┘
//   │ ------ ─┘
//   │ ------
//   │end
// - 修正後は正しく、下記のデータが出力されるようになりました。
//   ○出力ﾃﾞｰﾀ[正]
//   │00 00
//   │00 02
//   │ 00 01  00 00 05
//   │ 00 02  00 00 00
//   │00 00
//   │00 01
//   │ 00 03  00 00 00 #//正しく｢4=5｣の値を持つｷｰﾎﾞﾃﾞｨを指すようになった｡
//   │00 01            #//┐
//   │ 00 04  00 05    #//├──｢4=5｣の値を持つｷｰﾎﾞﾃﾞｨ
//   │00 00            #//┘
// * Sat Apr 11 13:20:40 JST 2015 Naoyuki Sawa
// - 文字列のデータタイプを追加し、大幅な変更を行いました。
//   変更前のコードを参照するには、前回のアーカイブを参照してください。
// * Sun Oct 04 21:01:44 JST 2015 Naoyuki Sawa
// - clipreg.cの大幅な変更に伴い、当ツールも大幅な変更を行いました。
//   詳細は、clipreg.cの同日のコメントを参照して下さい。
// - レジストリテーブルのバイナリフォーマットの互換性も無くなりました。
//   変更前のソースとツールを'keep/17_レジストリテーブル形式変更前保存/'に保存しておきました。
// * Tue Oct 06 22:24:46 JST 2015 Naoyuki Sawa
// - 1パス目の処理を高速化しました。主な高速化手段は以下の通りです。
//   ・str2num()で、これまでは同じ文字列も通し番号の異なる数値に変換していましたが、同じ文字列は同じ数値に変換するように変更し、数値比較出来るようにしました。
//   ・KeyBody_addKey(),KeyBody_addValueRow(),KeyBody_addStringRow(),KeyBody_addBlobRow()で、これまでは同じ名前を検索するのにリニアサーチしていましたが、ハッシュテーブルを使うように変更しました。
//   ・KeyBody_addKey(),KeyBody_addValueRow(),KeyBody_addStringRow(),KeyBody_addBlobRow()で、これまでは配列の拡張にrealloc()を使っていましたが、Obstackを使うように変更しました。
// * Wed Oct 07 21:13:47 JST 2015 Naoyuki Sawa
// - String_intern(),Blob_intern()を高速化しました。
// * Thu Oct 08 21:52:46 JST 2015 Naoyuki Sawa
// - BLOBのデータ構造を少し変更しました。
//   これまでは、BLOBのサイズに(データ本体のバイト数)を格納していましたが、今後は、(データ本体のバイト数-1)を格納します。
//   他のフィールドには(要素数-1)を格納しているので、BLOBのサイズもそれらに合わせて統一する方が判り易いと思ったからです。
// - Blob_addByte()で、これまでは配列の拡張にrealloc()を使っていましたが、Obstackを使うように変更しました。
// * Fri Oct 09 21:09:22 JST 2015 Naoyuki Sawa
// - BLOBのデータ定義に'byte','half','word'のプレフィクス指定を追加しました。
//   これまではたとえばBLOBのデータとして0x12345678を含めたい時、
//   {0x78,0x56,0x34,0x12},又は,{0x12345678&255,(0x12345678>>8)&255,(0x12345678>>16)&255,(0x12345678>>24)&255}のように定義する必要が有りましたが、今後は{word 0x12345678}と書けます。
//   一つのBLOBのデータ内で、複数のプレフィクスを混在させる事も可能です。⇒{byte 0x12,half 0x1234,word 0x12345678}
//   プレフィクスを省略すれば、これまでどおり、byteと見なします。⇒{0x12}と{byte 0x12}は同じ意味です。
// - half,wordは、リトルエンディアンで格納する事にしました。
//   理由は、BLOB内のデータを構造体と見なしてアプリケーションが直接参照する時に、リトルエンディアンの方が扱い易いと思ったからです。
//   レジストリ構造の要素数や名前の値などはビッグエンディアンで格納していますが、BLOB内のデータはリトルエンディアンである事に注意してください。
//   尚、BLOB内のデータにビッグエンディアンで格納したい場合は、{0x12,0x34,0x56,0x78}のように明示的にバイト単位で指定してください。
// * Sat Oct 10 21:13:38 JST 2015 Naoyuki Sawa
// - '~'演算子を対応しました。
// * Thu Oct 15 21:01:52 JST 2015 Naoyuki Sawa
// - '-n'オプションを追加しました。
//   詳細は、/clip/tool/dLotTblC/winapp.h の同日のコメントを参照して下さい。
// * Fri Oct 16 21:16:43 JST 2015 Naoyuki Sawa
// - clipstr.hのstrnatcmp(),strnatcasecmp()の動作を変更した事に伴い、当ツールをリビルドしました。
//   上記の関数の動作変更は、当ツールの使用方法では影響無いのですが、念のためにリビルドする事にしました。
// * Thu Oct 29 21:30:16 JST 2015 Naoyuki Sawa
// - clipreg.cモジュールを修正した事に伴い、当ツールもリビルドしました。
//   当ツールのソースは、変更していません。
// * Sun Nov 08 21:48:30 JST 2015 Naoyuki Sawa
// - 「Boehm GC」をマルチスレッド対応にした事,及び,それに伴ってclipbpe.cモジュールを修正した事に伴い、当ツールもプロジェクト設定の変更を行ってリビルドしました。
//   詳細は、/clip/tool/gc/README.TXT と /clip/clipbpe.c の2015/11/03のコメントを参照して下さい。
// - BLOBのデータ定義に'bit'のプレフィクス指定を追加しました。
//   'bit'を1～7ビット格納した後に、'byte','half','word'の格納を行うと、バイト境界までパディングします。(例:x={bit 1,bit 0,bit 1,0xAB})
//   'bit'を1～7ビット格納した状態で、Blobを終端した場合も同様です。(例:x={bit 1,bit 0,bit 1})
//   詳細は、Blob_addBit(),Blob_addByte(),Blob_addHalf(),Blob_addWord()の実装を参照して下さい。
// * Sat Nov 14 21:55:38 JST 2015 Naoyuki Sawa
// - ゼロ除算エラーと、範囲外ビットシフトのハンドリングを追加しました。
//   これまでは前者はCPU例外で終了し、後者は無視してしまっていました。今後はエラーと見なします。
// - '%'演算子を対応しました。
// * Sun Nov 22 21:02:41 JST 2015 Naoyuki Sawa
// - 環境変数'プログラム名_OPTION'で指定されたオプション(有れば)を、コマンドライン引数にマージするようにしました。
//   詳細は、/clip/clipmisc.c の同日のコメントを参照して下さい。
// - GCに'-DLARGE_CONFIG'を付けてリビルドした事に伴い、当アプリケーションもリビルドしました。
//   詳細は、/clip/tool/gc/README.TXT の同日のコメントを参照して下さい。
// * Sun Dec 06 21:06:49 JST 2015 Naoyuki Sawa
// - 文字列式を追加しました。今回対応した文字列式は、以下の二種類のみです。
//   │("文字列")⇒文字列
//   │"文字列"+"文字列"⇒文字列
//   文字列式を追加した目的は、スクリプト上、複数の文字列に分けて記述する方が見た目に判り易い場合が有るからです。
//   文字列式を使わなくても最初から連結して記述すれば結果は同じになのですが、見た目の判り易さのために対応する事にしました。
// - C言語の書式に倣うならば「"文字列" "文字列"」なのですが、二つの文字列トークンの並びと区別出来なくなる事を避けるために、'+'を使う事にしました。
// - 文字列と数値の連結は、今回は、対応しない事にしました。
//   数値を文字列化して連結する場合、数値の書式を指定出来ないと、実用上、使い物にならないと思ったからです。
//   もし今後、文字列と数値の連結にも対応する場合は、その時に、数値の書式の指定方法を検討しようと思います。
// * Sat Jan 02 21:26:28 JST 2016 Naoyuki Sawa
// - '<<','>>'と'<','>'に対して、これまでlex.yy.lがどちらも'<','>'を返していましたが、前者についてはT_SHL,T_SHRを返すようにして区別しました。
//   詳細は、/clip/tool/dPrpTblC/winapp.h の2015/12/27のコメントを参照して下さい。
// * Sun Jan 03 21:17:56 JST 2016 Naoyuki Sawa
// - プレフィクス文字列を固定にしました。
//   これまで使って来てプレフィクス文字列を変更する必要性が無く、毎回'-p'オプションを指定する事が却って手間になる事が判ったからです。
//   この変更に伴い、'-p'オプションを廃止しました。
// * Sun Feb 21 21:02:01 JST 2016 Naoyuki Sawa
// - libclipのライブラリ化の伴い、以下の変更を行いました。
//   ・extclip.hとextclip.cを削除しました。extclip.hとextclip.cはlibclipに含まれるようになったからです。
//   ・"CLiP Files"を削除しました。CLiPライブラリの各モジュールはlibclipに含まれるようになったからです。
//   当ツールの動作には変更有りません。
// * Tue Mar 01 21:34:55 JST 2016 Naoyuki Sawa
// - clipstd.hにてC4131の警告レベルを引き上げましたが、Bison/Flexの生成コードには旧スタイルの宣言が使われているので、Bison/Flexの生成コードのみ警告レベルを元に戻しました。
// * Tue Apr 12 21:05:50 JST 2016 Naoyuki Sawa
// - BLOBのデータ定義に'file'のプレフィクス指定を追加しました。
//   ファイルの内容をそのままBLOBに取り込めるようになりました。
//   <例>
//   │Label1 = { file "Data1.bin" }
//   上記はファイル単体で一つのBLOBとした例ですが、複数のfile要素を並べたり、bit,byte,half,word要素と組み合わせる事も出来ます。
//   │Label1 = { word 0x01234567, file "Data1.bin", word 0x89ABCDEF, file "Data1.bin" }
//   とは言え実際には、file要素を使用する場合は、ファイル単体で一つのBLOBとする事がほとんどだと思います。
// * Sun Apr 24 21:05:43 JST 2016 Naoyuki Sawa
// - 2016/04/23に、/clip/clipstd.hにparsonとLibYAMLのインクルードを追加した事に伴い、当プロジェクトにもparsonとLibYAMLのインクルードパスとライブラリパスの設定を追加しました。
//   当プロジェクトはparsonもLibYAMLも使用していませんが、インクルードパスとライブラリパスの設定を追加しないとビルドエラーになるからです。
// - libclip.lib,gc.lib,pthreadVC2(d).lib,sqlite.lib,pdcurses.libのリンク指定を、/clip/libclip/extclip.hで指定するようにし、個別のアプリケーション設定からは削除しました。
//   parson.lib,yaml.libのリンク指定を、/clip/clipstd.hで指定するようにし、個別のアプリケーション設定からは削除しました。
// * Mon Apr 25 22:45:55 JST 2016 Naoyuki Sawa
// - 実数の計算式に対応しました。
//   暗黙の型変換のルールは、C言語と同じです。
//   キャスト演算子は、'(int)'と'(double)'のみ対応しています。
// - あくまでも途中計算で実数の計算式が使えるだけであり、最終的には整数にキャストする必要が有る事に注意して下さい。
//   例は、/clip/tool/dTexDefC/winapp.hの同日のコメントを参照して下さい。
// * Tue Apr 26 22:39:26 JST 2016 Naoyuki Sawa
// - 実数の計算式から、整数引数への、暗黙の型変換を対応しました。
//   '-w'オプションを指定しなければ、C言語と同様に、警告無しで処理します。
//   '-w'オプション,又は,'-wcast'オプションを指定すると、暗黙の型変換によって誤差が発生した時のみ警告を表示し、最終的にエラー終了します。
//   C言語と違って、誤差が発生しなかった時は警告を表示しない事に注意して下さい。
// - 上記の変更のために、'-w'オプションを処理する仕組みとして、getsubopt()を導入しました。
//   今後、他の種類の警告を追加する時は、この仕組みを使って警告を追加出来ます。
// * Thu Jun 09 21:26:53 JST 2016 Naoyuki Sawa
// - lex.yy.lにて、数値(T_NUM)の解析を、既存の10進数と16進数に加えて、新しく8進数と2進数も解析出来るようにしました。
// * Sat Jul 02 21:34:21 JST 2016 Naoyuki Sawa
// - 2016/06/14に、/clip/clipstd.hに'#pragma comment(lib, "liblua.lib")'を追加した事に伴い、当プロジェクトにもlibluaのライブラリパスの設定を追加しました。
//   現在の所、当プロジェクトはlibluaを使用していませんが、インクルードパスとライブラリパスの設定を追加しないとビルドエラーになるからです。
//   尚、libluaのインクルードパスは以前から設定していたので、今回、追加したのはlibluaのライブラリパスのみです。
// - 2016/07/01に、/clip/libclip/extclip.hに'#include <sqlite3.h>'と'#pragma comment(lib, "sqlite3.lib")'を追加した事に伴い、当プロジェクトにもsqlite3のインクルードパスとライブラリパスの設定を追加しました。
//   現在の所、当プロジェクトはsqlite3を使用していませんが、インクルードパスとライブラリパスの設定を追加しないとビルドエラーになるからです。
// * Sun Jul 10 11:29:13 JST 2016 Naoyuki Sawa
// - y.tab.yのint_argの文法規則の最後に、「;」が抜けていたミスを修正しました。
//   bison.exeはこのような単純なミスを自動的に補ってくれるので、bison.exeのエラーにもならず、生成したプログラムの動作上も問題無く、これまで気付きませんでした。
//   しかし、間違った記述であった事には違い無いので、修正しておく事にしました。
// * Tue Aug 09 21:14:43 JST 2016 Naoyuki Sawa
// - BLOBのデータ定義に'fp16','fp32','fp64'のプレフィクス指定を追加しました。
//   使用方法は、'bit','byte','half','word'のプレフィクス指定と同様です。
//   <例>
//   │{fp16 1.2,fp16 3.4,fp16 5.6}
//   │{fp32 1.2,fp32 3.4,fp32 5.6}
//   │{fp64 1.2,fp64 3.4,fp64 5.6}
//   │{bit 1,byte 2,half 3,word 4,fp16 5.6,fp32 7.8,fp64 9.0,file "Data.bin"}		…他のプレフィクス指定との混在も可能です。ただし、自動的に境界整列は行われないので注意して下さい。(既存の他のプレフィクス指定と同様です。)
//   │{fp16 1,fp32 2,fp64 3}								…整数表現での指定も可能です。左記の例は{fp16 1.0,fp32 2.0,fp64 3.0}と書くのと同じです。尚、左記の例ではfp32,fp64がワード境界に整列していない事に注意して下さい。
// - 当初、プレフィクス名を'fp16','single','double'にしようかと思っていたのですが、最終的に、'fp16','fp32','fp64'とする事にしました。
//   理由の一つは、前者では'fp16'だけ名前が浮いていて判り辛いと思ったからです。
//   もう一つの理由は、既存のキャスト演算子'(double)'とキーワードが被って、(字句解析上は問題無いのですが)紛らわしいと思ったからです。
// * Fri Sep 16 21:30:10 JST 2016 Naoyuki Sawa
// - '-q'オプションを追加しました。
//   /clip/test.win/を元にしたプロジェクトで、VC++6.0のカスタムビルドから呼び出された場合に、'\r'による同じ行の重ね書きが上手く認識されず、VC++6.0の出力ペインに進捗表示が多く出過ぎて、その他の重要なエラーが見づらくなってしまう問題を避けるためです。
//   基本的には、VC++6.0のカスタムビルドから呼び出す場合だけに'-q'オプションを使用し、コマンドラインから呼び出す場合はこれまで通り'-q'オプションは指定しなくて構いません。
// * Wed Sep 21 21:20:16 JST 2016 Naoyuki Sawa
// - die(～)で終了していた箇所を、error(EXIT_FAILURE,～)で終了するように変更しました。
//   変更した理由は、以下の通りです。
// - die()は、標準エラー出力がコンソールでなければ、エラーメッセージをメッセージボックスで表示します。
//   通常はそれが望ましい動作なのですが、VC++6.0やVS2015のカスタムビルドとして当ツールを呼び出した場合に、使い辛い問題が生じます。
//   VC++6.0やVS2015は、カスタムビルドとして呼び出すツールの標準エラー出力をリダイレクトして、アウトプットウインドウに表示します。
//   標準エラー出力がコンソールでないので、当ツールはエラー終了する場合に、メッセージボックスを表示します。
//   結果として、カスタムビルドとして呼び出したツールがエラーになると、いちいちメッセージボックスを表示して停止し、使い辛い問題が生じました。
//   元々、die()が標準エラー出力がコンソールでなければエラーメッセージをメッセージボックスで表示するようにした理由は、コマンドプロンプトを持たないウインドウアプリケーションのためであり、
//   当ツールのようなコンソールアプリケーションの標準エラー出力がリダイレクトされた場合にメッセージボックスを表示する必要はあまり有りません。
//   そこで、当ツールがエラー終了する時にdie()を呼び出すのをやめて、error()で終了するように変更する事にしました。
// * Sun Sep 25 21:05:26 JST 2016 Naoyuki Sawa
// - /clip/test.win/lex.yy.lの'popen'対応処理を、当ツールのlex.yy.lにマージしました。
//   当ツールの'popen'対応は必須ではないのですが、本日dFsmMapC.exeに上記の変更を行ったついでに当ツールも対応しておく事にしました。
// - エラーメッセージに、現在の行番号だけでなく、現在のファイル名も表示するようにしました。
//   エラーメッセージの形式は、VC++6.0に合わせて、「ファイル名(行番号) : エラーメッセージ」としました。
// * Wed Sep 28 21:26:44 JST 2016 Naoyuki Sawa
// - error()の文字列の最後に余計な改行が付いていたのを削除しました。
//   error()は指定された文字列の後に(もし有ればエラー名を挟んで)自動的に改行を出力するので、アプリケーション側で文字列の最後に改行を付けると、文字列とエラー名の間に余計な改行が出力されたり、二回改行してしまう問題が生じていました。
// * Sun Oct 02 21:48:17 JST 2016 Naoyuki Sawa
// - ";"によるマルチステートメントに対応しました。
//   変更箇所は、lex.yy.lの「\n { return T_EOL; }」の上の行に、「";" |」を追加しただけです。
// - マルチステートメント対応が必要になった理由は、主にdDirSeqC.exeのためです。
//   Cプリプロセッサで一つのマクロで複数のact命令を生成する時に、Cプリプロセッサの制限のために複数行に分けられないからです。
//   今回マルチステートメントを対応した事によって、「act ～; act ～; act ～」のように一行で複数のact命令が可能になりました。
//   dDirSeqC.exe以外のツールについては、今すぐにマルチステートメント対応が必要な訳ではないのですが、上述の通り変更箇所は少ないので、他のツールも一緒に変更しておく事にしました。
// * Thu Feb 16 21:10:48 JST 2017 Naoyuki Sawa
// - BLOBのデータ定義に'exp10'のプレフィクス指定を追加しました。
//   使用方法は、'bit','byte','half','word'のプレフィクス指定と同様です。
//   exp10の形式については、cliplot.hの「16ビットで大きな値を表現するための、指数表現」のコメントを参照して下さい。
//   <例>
//   │{exp10 10,exp10 1000,exp10 100000,exp10 10000000,exp10 1000000000}
// * Mon Feb 27 22:08:56 JST 2017 Naoyuki Sawa
// - '-xc','-xcs'オプションを追加しました。
//   ラベル定義と、テキスト形式のデータ出力を、これまでのC言語形式に加えて、C#形式でも出力出来るようになりました。
//   普通はデータ出力はバイナリ形式で行うと思うので、テキスト形式のデータ出力の方のC#形式対応が役に立つ事はあまり無いと思いますが、テスト時にはテキスト形式でデータを出力する方が扱い易い事も有るので、一応、テキスト形式のデータ出力もC#形式に対応しておきました。
// - C#アプリケーションからレジストリデータにアクセスするには、/clip/libclip.net/clipreg.cs を使用して下さい。
// * Sun Mar 05 23:35:48 JST 2017 Naoyuki Sawa
// - dRegTblC.exeの引数にスクリプトファイル名を二個以上指定すると、最後のスクリプトファイルの内容しか出力されていなかった、バグを修正しました。
// - バグの原因は、add_keyBody()の処理が正しくなかった事でした。
//   dRegTblC.exeの引数にスクリプトファイル名を二個以上指定した場合、Bison/Flexは、全てのスクリプトファイルを連結した内容に対してパースを行うのではなく、個々のスクリプトファイルに対してパースを行います。(要するに、<<EOF>>が複数回現れます。)
//   そのため、トップレベルのKeyBodyが複数個生成され、add_keyBody()が複数回呼び出されます。
//   しかしこれまで、add_keyBody()は一回しか呼ばれない事を想定した処理になっていて、g_keyBodyを上書きしていました。
//   そのため、一個目のスクリプトファイルに対するadd_keyBody()の呼び出しによってg_keyBodyが格納された後、二個目のスクリプトファイルに対するadd_keyBody()の呼び出しによってg_keyBodyが上書きされてしまい、一個目のスクリプトファイルの内容が消えてしまっていました。
//   正しくは、二個目以降のスクリプトファイルに対するadd_keyBody()の呼び出しならば(=既にg_keyBodyが格納されていたら)、上書きするのではなく、マージするのが正しい処理でした。
//   今回、そのように修正したので、dRegTblC.exeの引数にスクリプトファイル名を二個以上指定した場合も、正しく動作するようになりました。
// - かなり大きなバグなのですが、これまで気づかなかった理由は以下の通りです。
//   大抵の場合、レジストリスクリプトのコンパイルは、dRegTblC.exeを直接使用せずに、MkRegTbl.batを経由して使用しています。
//   MkRegTbl.batは、cpp.exeを通すして、指定されたファイルを一つのファイルに連結してから、dRegTblC.exeを呼び出しています。
//   そのため、図らずも、dRegTblC.exeに対しては一個のスクリプトファイルしか指定されていなかったので、上記のバグが顕在化していませんでした。
// * Thu Mar 16 23:39:55 JST 2017 Naoyuki Sawa
// - 複数の入力ファイルを指定した時に、最後以外のファイルでエラーが発生した場合、当ツールの終了ステータスが0になっていたバグを修正しました。
//   詳細は、/clip/tool/dEnmDefC/winapp.hの同日のコメントを参照して下さい。
// * Mon May 08 08:35:51 JST 2017 Naoyuki Sawa
// - ライブラリのバグ修正に伴う、ツールのリビルドを行いました。
//   詳細は、clipmisc.cの'Sun May 07 09:13:01 JST 2017 Naoyuki Sawa'のコメントを参照して下さい。
// * Sat Sep 09 23:14:26 JST 2017 Naoyuki Sawa
// - '-l'オプションを追加しました。
//   '-l'オプション指定すると、レジストリテーブルにラベルテーブルを格納します。
//   この機能を追加した理由は、以下の通りです。
// - ラベル名に対するラベルの数値は、レジストリスクリプトのコンパイル時に割り当てられます。
//   レジストリスクリプトの内容によって、ラベル名に割り当てられる数値は変化するので、特定のラベル名に対して特定の数値を想定する事は出来ません。
//   言い換えると、あるレジストリデータにおけるあるラベル名の数値は、そのレジストリデータと共に生成されたヘッダファイルをインクルードしているアプリケーションしか知り得ません。
//   通常はそれで問題無いのですが、ライブラリ関数内で特定のラベル名に対する数値を知りたい時に、アプリケーションからライブラリへラベルの数値を引き渡すインターフェイスが面倒になる問題が有りました。
//   これまでは、例えば、/clip/DxlibHelper.hのST_TexInf構造体のような方法を使って、アプリケーションからライブラリへラベルの数値を引き渡していました。
//   動作上はそれでも問題無かったのですが、今後、もっと簡単に、特定のラベル名に対する数値を取得する方法を用意したいと思いました。
//   そこで、'-l'オプションを指定すると、レジストリデータ内に、ラベル名と数値の対応表(ラベルテーブルと呼ぶ事にします)を格納するようにしました。
//   アプリケーションから明示的にラベルの数値を引き渡さなくても、ライブラリ自身でラベルテーブルを検索する事によって、特定のラベル名に対する数値を求める事が出来るようになりました。
// - ラベルテーブルを利用する上での、注意点は以下の通りです。
//   一点目として、ラベルテーブル自身のラベル(RegKey_LabTbl)はライブラリは知り得ませんので、RegKey_LabTbl(又はラベルテーブルのポインタ)だけは、やはりこれまで通りアプリケーションからライブラリに引き渡す必要が有ります。
//   二点目として、ラベルテーブルはラベルの数値の昇順であり、ラベルの数値がラベル名の昇順であり、ラベル名のソート順はレジストリスクリプトのコンパイル時に'-n'が指定されていたかによって変わるので、ライブラリがラベルテーブルを検索する際にバイナリサーチではなくリニアサーチを使う方が確実です。
//                 尚、ラベルテーブルを検索する処理は今後頻繁に必要になると思うので、ラベルテーブルを検索するユーティリティ関数を、近日中にclipreg.cモジュールに追加する予定です。	⇒{{2017/09/10コメント追記:clipreg.cモジュールに、「ラベルテーブルを検索するユーティリティ関数」を追加しました。}}
//   三点目として、ラベルテーブルを格納するとレジストリデータのサイズは増えてしまうので、容量を抑える必要が有る場合は'-l'を指定しないで下さい。
//                 ただし今後、ライブラリ自身でラベルテーブルを検索して特定のラベル名に対する数値を求めるようにライブラリを変更して行く予定で、ラベルテーブルが必須になると思うので、極力'-l'を指定するようにして下さい。
// * Fri Sep 15 23:29:32 JST 2017 Naoyuki Sawa
// - ラベルテーブルの格納構造を変更しました。
//   詳細は、以下の通りです。
// - 2017/09/09に、ラベルテーブルを格納する機能を新規作成した時点では、ラベルテーブルはレジストリデータのルートに存在する通常のキーであり、格納構造上は特別扱いしていませんでした。
//   アプリケーションが明示的にRegKey_LabTblを使って、レジストリデータのルートからラベルテーブルを取り出す必要が有りました。
//   ラベルテーブルを格納する事による容量の増加を最小限に抑えるには上記の仕様が適切ではあるのですが、しかし、実際にアプリケーションで使おうとすると使い辛いという事に気付きました。
//   ラベルテーブルを使用したい関数に対して、常に、その関数で処理したいキーとは別に、ラベルテーブルも渡さなければいけないからです。
//   なぜなら、ラベルテーブルを使用したい関数はレジストリデータのルートやRegKey_LabTblの値を知っているとは限らず、それらを知り得るのは個々のアプリケーションだけであるからです。
//   しかし、そのために常に二つのキーを渡すというのは関数インターフェイスが複雑で使い辛く、せっかく追加したラベルテーブルを有効に活用出来ない懸念が生じました。
// - そこで今回、ラベルテーブルの格納構造を変更して、レジストリデータのルートだけでなく、どのキーからでもラベルテーブルにアクセス出来るように変更しました。
//   具体的には、各キーのヘッダの後ろに、隠しフィールドとして、ラベルテーブルへの相対距離(符号付き3バイト)を格納するようにしました。
//   この変更により、ラベルテーブルを使用したい関数に対して、その関数で処理したいキーだけを渡せば、関数はそのキーを経由してラベルテーブルにアクセス出来るようになりました。
//   この方法の欠点は、全てのキーが3バイト増加するため、容量が増加する事です。
//   全体でどれぐらい増加するかは、レジストリデータの内容にもよるのですが、/clip/test.win/や/clip/test.pce/の雛形アプリケーションのデータで試した所、約10％強の増加になるようです。
//   無視できる容量増加ではありませんが、とは言え、ラベルテーブルが使い辛くて使わなければせっかく追加したのに意味が無くなるので、容量増加を受容してこの方法を取る事にしました。
//   ちなみに、この方法のもう一つの利点としては、ラベルテーブルを知らない既存のアプリケーションに対しては、何の悪影響も生じない事です。
//   ラベルテーブルへの相対距離は各キーのヘッダの後ろに追加した隠しフィールドですから、ラベルテーブルを知らない既存のアプリケーションがその部分をアクセスする心配は有りません。
// - 余談ですが、隠しフィールドとしてラベルテーブルへの相対距離を格納するのとは別の案として、親キーへの相対距離を格納する方法も考えたのですが、その方法は取りませんでした。
//   もし、各キーが親キーへの相対距離(=リンク)を持ってしまうと、全てのキーの内容が別々となり、どのキーも最適化出来なくなってしまいます。
//   当ツールの利点の一つは、同じ内容のキーを最適化して容量節約出来る事であり、実際に利用してそれが有効に働いている事も検証済みなので、その利点を失うのは良くないと思ったからです。
// * Sat Sep 23 23:49:28 JST 2017 Naoyuki Sawa
// - BLOBにヌル終端文字列も含められるようにしました。
//   特に必要が有ってこの機能を追加した訳では無いのですが、僅かな処理の追加で対応出来るので追加しておく事にしました。
//   ある名前に対して、値と文字列を両方登録したい場合に、普通ならば、その名前のキーを作って、値と文字列を個別に格納するのですが…
//   □普通の方法
//   │name1
//   │ idA  = 0x1234
//   │ strA = "Hoge"
//   │ idB  = 0x5678
//   │ strB = "Fuga"
//   │end
//   │name2
//   │ idA  = 0x9ABC
//   │ strA = "Piyo"
//   │ idB  = 0xDEF0
//   │ strB = "Hogera"
//   │end
//   │---
//   │key = REG_open_key(TBL_RegTbl, RegKey_name1);
//   │idA = REG_get_value(key, RegKey_idA);
//   │strA = REG_get_string(key, RegKey_strA);
//   │idB = REG_get_value(key, RegKey_idB);
//   │strB = REG_get_string(key, RegKey_strB);
//   …今回追加した方法を使うと、値と文字列を一つのBLOBにパックして格納し、容量を節約する事が出来ます。
//   □今回追加した方法
//   │name1 = {half 0x1234,"Hoge",half 0x5678,"Fuga"}
//   │name2 = {half 0x9ABC,"Piyo",half 0xDEF0,"Hogera"}
//   │---
//   │blob = REG_get_blob(TBL_RegTbl, RegKey_name1);
//   │idA = LEHALF(blob); blob += 2;
//   │strA = blob;   blob = strchr(blob, '\0') + 1;
//   │idB = LEHALF(blob); blob += 2;
//   │strB = blob; /*blob = strchr(blob, '\0') + 1;*/
//   とは言え、上記の方法はデータ構造としては明示的でなく、管理しづらくなるおそれがあるので、使い過ぎないように気を付けて下さい。
// * Sat Sep 30 23:55:57 JST 2017 Naoyuki Sawa
// - BLOBデータ作成にclipblob.cモジュールの機能を使うように変更しました。
//   これまでは当ツール内でBLOBデータを作成する処理を実装していましたが、今後はBLOBの仕様を共通化するためにclipblob.cモジュールの機能を使用する事にしました。
//   詳細は、/clip/clipblob.cの'Tue Sep 26 23:05:51 JST 2017 Naoyuki Sawa'のコメントを参照して下さい。
//   尚、clipblob.cモジュールのBLOBデータの仕様は、当ツールの既存のBLOBデータの仕様と同じなので、結果として当ツールの出力データはこれまでと変わりありません。
// * Sun Oct 01 23:07:12 JST 2017 Naoyuki Sawa
// - /clip/clipblob.cにて、BLOB構造体にシグネチャを追加した事に伴い、当ツールもリビルドしました。
//   当ツールのソースコード,及び,当ツールの動作には変更有りません。
// * Sat Apr 07 23:59:59 JST 2018 Naoyuki Sawa
// - BLOBにBER圧縮整数も含められるようにしました。
// * Sun Apr 08 23:59:59 JST 2018 Naoyuki Sawa
// - BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
//   具体的には、以下の通りです。
// - これまでは、BLOB内の型指定の無い数値は全てbyte，BLOB内の型指定の無い文字列は全て文字列と見なしていました。
//   しかしそれでは、byteと文字列以外の型(bit,word,fp64,file等)を多用する時に、個々の値に対して明示的な型指定を付けなければいけないという不都合が有りました。
//   △変更前の例
//   │a = { bit 1, bit 0, bit 1, bit 0 }
//   │b = { 1, 2, 3, word 4, word 5, word 6 }
//   │c = { 1, 2, fp32 3.3, fp32 4.4, fp64 5.5, fp64 6.6, fp32 7.7, fp32 8.8, 9, 10 }
//   │d = { ber 1, ber 2, ber 3, word 4, ber 5, ber 6, ber 7 }
//   │e = { file "a.txt", file "b.txt", file "c.txt" }
//   │f = { "signature", file "a.txt", file "b.txt", file "c.txt" }
// - 今回の変更により、個々の値でなく、ブロックに対してデフォルトの型を指定出来るようになりました。
//   上記の例は、今後は、以下のように書く事が出来ます。
//   ○変更後の例
//   │a = bit { 1, 0, 1, 0 }
//   │b = { 1, 2, 3, word { 4, 5, 6 } }
//   │c = { 1, 2, fp32 { 3.3, fp32 4.4, fp64 { 5.5, 6.6 }, 7.7, 8.8 }, 9, 10 }	//ブロックはこのようにネスト出来ます。
//   │d = ber { 1, 2, 3, word 4, 5, 6, 7 }					//デフォルトの型を指定したブロックの中でも、個々の値に対して別の型を明示する事も出来ます。
//   │e = file { { "signature" }, "a.txt", file "b.txt", file "c.txt" }	//ただし、fileブロックの中で文字列型を明示する事は出来ません(文字列型を明示するためのキーワードが無いので)。その場合はこのようにブロックをネストして下さい。
// - 注意点として、bit位置はブロックをまたいで継続する事に注意して下さい。
//   「a = { bit { 1, 0 }, bit { 0, 1 }」は、「a = bit { 1, 0, 0, 1 }」と等価です。
//   前半のbitブロックと後半のbitブロックの間で、バイト境界まで進んだりはしません。
// - 今回の変更は大幅な変更でしたが、これまでの書式との互換性は保たれています。
//   なぜなら、「{～}」ブロックのデフォルトの型は、これまで通りbyteだからです。
//   従って、既存のスクリプトも、変更せずにそのまま使用出来るはずです。
// * Thu Apr 12 23:59:59 JST 2018 Naoyuki Sawa
// - 「prevent-deletion」を追加しました。
//   具体的には、以下の通りです。
// - これまでは、空のキーを作成する事が出来ませんでした。
//   空のキーは、最適化処理によって削除されるからです。
//   ('-d'オプションを指定して最適化を抑制すれば可能ですが、それでは全体の最適化が抑制されてしまって無駄が多いので、現実的ではありません。)
//   そこで今回、特定のキーが空であっても、最適化によって削除されないように明示的に指定する、「prevent-deletion」キーワードを追加しました。
// - キーの中に「prevent-deletion」を指定すると、そのキーが空でも、最適化によって削除されません。
//   □例
//   │Test1	#//削除される
//   │end
//   │Test2	#//削除されない
//   │  prevent-deletion
//   │end
// - トップレベルのキーだけでなく、子階層のキーに対しても、同様に指定出来ます。
//   □例
//   │Parent
//   │  Test1	#//削除される
//   │  end
//   │  Test2	#//削除されない
//   │    prevent-deletion
//   │  end
//   │end
// - 空でないキーに対して「prevent-deletion」を指定しても無意味ですが、エラーにはなりません。
//   □例
//   │Test1
//   │  prevent-deletion	#//無意味だがエラーにはならない。
//   │  value1 = 12345
//   │end
// - 「prevent-deletion」を複数回指定しても、二回目以降は無意味ですが、エラーにはなりません。
//   □例
//   │Test1
//   │  prevent-deletion
//   │  prevent-deletion	#//無意味だがエラーにはならない。
//   │end
// - 「prevent-deletion」も、その他の値と同様に、マージ対象となります。
//   □例
//   │Test1			#//┐
//   │end			#//│Test1
//   │Test1			#//│  prevent-deletion
//   │  prevent-deletion	#//│end
//   │end			#//┘
// * Thu May 03 23:59:59 JST 2018 Naoyuki Sawa
// - Boehm GCを修正した事に伴い、当ツールもリビルドしました。
//   詳細は、/clip/tool/gc/README.TXTの'Wed May 02 23:59:59 JST 2018 Naoyuki Sawa'のコメントを参照して下さい。
/*---------------------------------------------------------------------------*/
/* バージョン定義 */
#define VERSION "20180503"
/*---------------------------------------------------------------------------*/
#endif/*__WINAPP_H__*/
