/*****************************************************************************
 * 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.h======================================================*/
/*---------------------------------------------------------------------------*/
/* 構造体定義 */
//keyBody
typedef struct _ST_KeyBody {
	struct _ST_KeyBody*	redir;				//optimize2()で設定する。	NULLでなければ最適化により別のキーボディに統合された事を示す。二段階以上に辿る可能性も有ることに注意せよ。
	union {
		int		index;				//optimize2()で設定する。	走査順で前方(インデクスが小さい方)のキーボディにのみ一致させ、後方(インデクスが大きい方)には一致させないために、連番を振る。
		int		addr;				//setKeyBodyAddr()で設定する。
	};
	int			nKey;
	struct _ST_Key**	TBL_Key/*[nKey]*/;
	int			nValueRow;
	struct _ST_ValueRow**	TBL_ValueRow/*[nValueRow]*/;
	int			nStringRow;
	struct _ST_StringRow**	TBL_StringRow/*[nStringRow]*/;
} ST_KeyBody;
//key
typedef struct _ST_Key {
	struct _ST_NameRow*	nameRow;
	struct _ST_KeyBody*	keyBody;
} ST_Key;
//nameRow
typedef struct _ST_NameRow {
	int	line;	//行番号。エラーメッセージのためだけに使用する。
	int	name;	//(0～UINT16_MAX)=数値,それ以外=文字列アドレス。(Windowsのメモリマップに依存)
} ST_NameRow;
//valueRow
typedef struct _ST_ValueRow {
	int	line;	//行番号。エラーメッセージのためだけに使用する。
	int	name;	//(0～UINT16_MAX)=数値,それ以外=文字列アドレス。(Windowsのメモリマップに依存)
	int	data;	//(0～UINT16_MAX)=数値,それ以外=文字列アドレス。(Windowsのメモリマップに依存)
} ST_ValueRow;
//stringRow
typedef struct _ST_StringRow {
	int	line;	//行番号。エラーメッセージのためだけに使用する。
	int	name;	//(0～UINT16_MAX)=数値,それ以外=文字列アドレス。(Windowsのメモリマップに依存)
	char*	s;	//文字列データ。インターン済みで、TBL_String[]内の文字列を指す。
} ST_StringRow;
/*---------------------------------------------------------------------------*/
/* グローバル関数宣言 */
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_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);
int Name_newExpr(int expr);
int Name_newLabel(char* label);
int Data_newExpr(int expr);
int Data_newLabel(char* label);
char* String_intern(char* s);
/*---------------------------------------------------------------------------*/
/*--- 変更履歴 ---*/
// * 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
// - 文字列のデータタイプを追加し、大幅な変更を行いました。
//   変更前のコードを参照するには、前回のアーカイブを参照してください。
/* バージョン定義 */
#define VERSION "20150411"
/*---------------------------------------------------------------------------*/
#endif/*__WINAPP_H__*/
