//--------------------------------------------------------------------------------------
//
// X-BASIC'
// 	ワークエリア定義
//		fdef.hから呼び出されることを前提にしているので、これだけを単独で呼ばないこと
//
//--------------------------------------------------------------------------------------
// X-BASIC'では、可変構造ワーク内を持っている
//	internalCode/param/チェインバッファー
// したがって、それに関わる構造体は#pragma pack()の指定が必須となる。
// internalCodeの中では(68なのでword単位で)long/DOUBLE_LONGが混在しているので、ARMのようにlobg/DOUBLE_LONGでの読み取りの際にバイト境界に制約が出るCPUでは
// その読み書き単位で細工を入れる必要がある（入れないとCPUのトラップに引っかかる)。
// メンバー配置を気にしなければならないのはCore内部のみ。他にはメンバー配置に依存している構造体はない。

#ifndef	__XB_VARIABLE__
#define __XB_VARIABLE__	1

#include "XBdefines.h"
#include <setjmp.h>
#include "bufferCtrl.h"

//--------------------------------------------------------------------------------------

#ifdef FROM_C	// Cソース生成時
#define	EXTERN	// EXTERN宣言を消し、実体確保する
#else			// ヘッダー生成時
#define	EXTERN	extern
#endif

//-------------------------------------------------------------------
// 型宣言
//-------------------------------------------------------------------

typedef	SLong	slAryNO;		// 配列の通しの要素番号
typedef SWord	swVarNO;		// 変数(>=0:グローバル,<0:ローカル変数-1,SystemVarTopNo>=システム変数)/配列番号>=0
								// 実行時はstat情報がないため、変数番号そのものに細工する

#define	swVarCNT	swVarNO		// 変数/配列番号=0～登録されている個数-1なので、交互互換性がある
								// または引数の個数

#define	_isLocal(no)			((no)<0)	// ローカル変数かどうか
#define	_getVarNo(no)			(-(no)-1)	// ローカル変数時に番号を得る(復号)	-1→0,-2→1
#define	_setLocal(no)			(-(no)-1)	// ローカル変数番号にする			0→-1,1=-2,... (-1するのは0=先頭の時対策)

#define	SystemVarIntTopNo		0x7fe0		// intシステム変数は>0でこの番号から始める；符号が変わらないようにするため、intシステム変数は最大0x0f個しか設定できない(増えたときはこの番号を小さくする)
#define	SystemVarStrTopNo		0x7ff0		// strシステム変数は>0でこの番号から始める；符号が変わらないようにするため、strシステム変数は最大0x0f個しか設定できない(増えたときはこの番号を小さくする)
#define	_isSystemVarInt(no)		((no)>=SystemVarIntTopNo)	// intシステム変数かどうか
#define	_getSystemVarInt(no)	((no) -SystemVarIntTopNo)	// intシステム変数番号を得る
#define	_setSystemVarInt(no)	((no) +SystemVarIntTopNo)	// intシステム変数番号にする
#define	_isSystemVarStr(no)		((no)>=SystemVarStrTopNo)	// strシステム変数かどうか
#define	_getSystemVarStr(no)	((no) -SystemVarStrTopNo)	// strシステム変数番号を得る
#define	_setSystemVarStr(no)	((no) +SystemVarStrTopNo)	// strシステム変数番号にする


typedef SWord	swFuncNO;		// 関数番号;>=0:外部関数,<0:内部関数
#define	_isInternalFunc(fno)	((fno)<0)	// 内部関数かどうか
#define	_getFuncNo(fno)			(-(fno)-1)	// 内部関数時に番号を得る(復号)	-1→0,-2→1
#define	_setInternalFuncNo(fno)	(-(fno)-1)	// 内部関数番号にする			0→-1,1=-2,... (-1するのは0=先頭の時対策)

typedef SLong 	slLabelNO;		// ラベル番号(チェインバッファー内容)
typedef SWord 	swLabelNO;		// ラベル番号
typedef SWord	swJigen;		// 配列次元数
typedef	UWord	uwYouso;		// 要素数

typedef	UWord	uwLineNO;		// 内部行番号:0～0xfffe/0xffff=LINENO_SPECIALは特別
#define	LINENO_SPECIAL	0xffff	// 特別行番号
typedef	SLong	slLineNO;		// エラー処理用行番号:0～0xfffe/0xffff=LINENO_SPECIALは特別,<0=startup内行

typedef SByte	sbVarSTAT;		// variableCheck()のstat値
typedef	SWord	swCaseCNT;		// case数
typedef	SWord	swStrLEN;		// 文字列長

typedef UWord	uwHash;			// ハッシュ値
#define	_calcHashMain(hash,c)	(rolw(hash,2)^((c)&0x00ff))	// ハッシュ値計算式

//-------------------------------------------------------------------

typedef enum { // 比較の結果
	CMP_EQUAL		=-1,	// basicのtrueは-1なので	BASIC_YESに合わせておくこと
	CMP_NOT_EQUAL	=0,		// 直接には返さない
	CMP_LARGE,
	CMP_SMALL,
} CMP_RESULT;


enum { // setjmp/longjmp()の識別用
	JMP_NONE=0,	// setjmp()を素通り(longjmpからは返り得ない)
	JMP_ERROR,	// Error()からの戻り
	JMP_IERROR,	// IError()からの戻り
	JMP_BREAK,	// breakでの終了
};

//-------------------------------------------------------------------
// グローバル変数

// ソースコードは独立したエリアに読み込む(サイズがあらかじめわかるから)
EXTERN	UByte		*sourceTop;				// ソースコード先頭
EXTERN	UByte		*sourceEnd;				// ソースコード最終＋1
EXTERN	UByte		*source;				// ソースコード；a5(コンパイル時)

EXTERN	uwLineNO	lineNo;					// 行数;先頭=0～/LINENO_SPECIAL=特殊行,<0=startup内行

EXTERN	REGISTER	internalCode;			// 現在の中間コード格納/読み出し位置；a4(コンパイル時),a5(実行時)
EXTERN	uwCODE		*internalCodeTop;		// 中間コード領域先頭
EXTERN	uwCODE		*internalCodePrevLine;	// 1つ前の行の中間コード先頭位置
EXTERN	ULong		internalCodeSize;		// 現在の中間コード領域サイズ(B)

EXTERN	UByte		*variableAreaTop;		// 変数領域先頭アドレス
EXTERN	UByte		*variableArea;			// 現在のブロックの変数領域先頭アドレス
EXTERN	ULong		variableAreaSize;		// 現在の変数領域サイズ(B)

EXTERN	jmp_buf		jmpEnv;					// setjmp/longjmp()の環境保存用

EXTERN	SWord		exitCode;				// exit()値
EXTERN	uwTYPE		returnType;				// リターン値の型
EXTERN	SWord		breakflag;				// BREAKが押されたかどうか

// 汎用ワーク
EXTERN	UByte		*tmp;					// 確保はXB.mにて
EXTERN	UByte		*tmp2;					// 〃
#define	MAX_TMP3	2						// tmp3の本数
EXTERN	UByte		*tmp3s[MAX_TMP3];		// 〃	SHIFT-JIS→UTF8文字列変換用ワーク（外部関数用）

#define	LIMIT_INTERNAL_CODE	(sizeof(uwCODE)*256)	// 中間コード領域オーバーフローチェック用(テキスト1行で此の分の中間コードははき出さないだろう、と言う想定)
#define	SZ_INTERNAL_CODE	(sizeof(uwCODE)*32*K)	// 中間コード領域サイズ(初期値であり、増分)

#define	SZ_VARIABLE_AREA	(64*K)			// 変数領域サイズ(初期値であり、増分)

//-------------------------------------------------------------------
// 中間コードエリア
//-------------------------------------------------------------------

typedef struct {
	UWord	varChainListNo;		// 変数チェインリストから指定ブロックの変数情報を取り込む位置
	UWord	paramChainListNo;	// パラメーターチェインリストから指定ブロックの引数情報を取り込む位置	オリジナルは*2されてる
	uwCODE	codes[0];			// 中間コード実格納領域
} INTERNAL_CODE_INFO;
// グローバル先頭と、ローカル＝func関数内先頭に作成される。
// その全てを通して内部コード領域を示しているのがinternalCode

//-------------------------------------------------------------------
// 名前バッファー
//-------------------------------------------------------------------

EXTERN	UByte	*nameBuffer;	// 名前バッファーのアドレス		名前Buffer
EXTERN	UWord	nameLeftSize;	// 名前バッファーの残りサイズ	名前size
// defineName();XBstat.mで書き込み

#define	ADD_NAME_BUFFER		(16*K)	// nameBufferの増分；足りなくなったら、この単位で追加する	//!!増加単位!!
#define	MAX_NAMEBUFFER		(64*K)	// 最大バッファーサイズ
#define	MAX_NAMEBUFFER_LIST	(MAX_NAMEBUFFER/ADD_NAME_BUFFER)	// 最大バッファーサイズまでADD_NAME_BUFFER単位で増加させるときの回数

EXTERN	UByte	*nameBufferList[MAX_NAMEBUFFER_LIST];	// 確保した各nameBufferの先頭アドレス
EXTERN	SWord	nameBufferCnt;

//-------------------------------------------------------------------
// バッファー制御構造体
//-------------------------------------------------------------------
// コンパイル時のみ書き込まれる

// バッファーを使った制御構造
EXTERN	BUFF_CTRL	variableBuffCtrl;					// 変数
EXTERN	BUFF_CTRL	paramBuffCtrl;						// 引数
EXTERN	BUFF_CTRL	gotoBuffCtrl;						// goto飛先
EXTERN	BUFF_CTRL	labelBuffCtrl;						// ラベル
EXTERN	BUFF_CTRL	internalCodeBytesBy1LineBuffCtrl;	// 1行当たりの中間コードバイト数
EXTERN	BUFF_CTRL	sourceAdrsEachLinesBuffCtrl;		// 各行のソース先頭アドレス

//---------------------------
// バッファー内定義
//---------------------------

typedef enum {
	VAR_INT=0,
	VAR_STR,
	VAR_CHAR,		// X-BASICのcharはunsignedである
	VAR_FLOAT,
	VAR_DIM,
	//
	MAX_VAR_TYPES,	// 種類数
	//
	VAR_VOID,		// これは特別
} VAR_TYPES;		// 変数種類の表；変数名はtypeNoを推奨

#pragma pack(push,2)
typedef struct { // 配列の付属情報
	UWord	jigenType;	// 次元<<8|T_型	←_setJigenAndType(jigen,type) / →_getJignFromJigenAndType()/_getTypeFromJigenAndType()
	uwYouso	youso[];	// 要素数
} DIMLIST_CHAIN;
#pragma pack(pop)

#pragma pack(push,2)
typedef struct { // variableBuffCtrl
	ULong			sizeVarArea;		// 変数領域のサイズ
	swVarCNT		cnt[MAX_VAR_TYPES];	// 型別変数の個数
	DIMLIST_CHAIN	dimList[0];			// 配列の付属情報がここからに入るcnt[VAR_DIM]分;dimList[配列番号]でその配列の情報が得られる
} VARLIST_CHAIN;
#pragma pack(pop)
// コンパイル中はチェインバッファーであるが、インタープリター前に結合処理が入るので、単一バッファーになる。
// グローバル→ソースの先頭から出現順の各func別に、その中で定義される変数の型別数、それに必要な領域サイズなどを記録している


/*	各ブロック(グローバル/ローカル)中の変数個数と配列の情報を記録する

	VARLIST_CHAIN	varListInfo
	+---------------+
0	|sizeVarArea	|.l	← .w単位書き込みのチェインバッファーを使うが、ここだけ例外的にアドレス取得後*(ULong*)で書き込んでいる
	+---------------+				determineVariableList();XBstatSub.mで書き込まれている
4	|cnt[VAR_INT]	|.w				このブロックで使う全変数領域サイズ	varArea[sizeVarArea]だけ必要
	+---------------+
6	|cnt[VAR_STR]	|.w
	+---------------+
8	|cnt[VAR_CHAR]	|.w
	+---------------+
10	|cnt[VAR_FLOAT]	|.w
	+---------------+
12	|cnt[VAR_DIM]	|.w	DIMLIST_CHAIN
	+---------------+---------------+---+
	 dimList		|jigen+Type	.w	|	|
	- - - - - - - - +---------------+  1配列分
					|	youso	.w	|	|
					+---------------+	|
						～				|
					+---------------+	|
					|	youso	.w	|youso[jigen-1]まで
					+---------------+---+
										～*cnt[VAR_DIM]分
*/

//--------------------------------以下は固定内容の配列
// 常に構造単位でアクセスするものはpackする必要なし

typedef struct { // paramBuffCtrl
	uwMATHTYPE	msType;	// |_PARAMあり=引数の型 , なし=配列の次元数 / [cnt+0]のみこのブロックの引数の数;[].msType=0なら[1]以降はなし(グローバルがこの状態)
	swVarNO		no;		// 変数/配列番号
} PARAM_CHAIN;
// グローバル→ソースの先頭から出現順(=関数番号順)の各func別に、その中で定義される引数の型およびその番号を記録している

typedef struct { 	// labelBuffCtrl
	SLong	len;		// ラベル文字数
	UByte	*name;		// 名前へのポインタ
	uwCODE	*lineAdrs;	// 行アドレス
	SLong	flabel;		// ラベルの定義され方	intでいいが、サイズを固定するためSLong
} LABEL_CHAIN;
#define	LABEL_NO_LINE	((uwCODE *)(-1))	// 行数が未登録
enum { // flabel値
	FLABEL_LABEL=0,	// label文または*labelで定義された(定義が先)
	FLABEL_GOTO,	// gotoで定義された(前方参照)
};

typedef struct { // goto飛び先[]
	slLabelNO	no;		// ラベル番号
	uwCODE		*jump;	// 飛び先アドレス
} GOTO_CHAIN;

// internalCodeBytesBy1LineBuffCtrl
typedef UWord CODEBYTES;	// 行ごとの中間コードバイト数

// sourceAdrsEachLinesBuffCtrl
typedef UByte * SOURCEADRS;	// ソース各行の先頭アドレス

//-------------------------------------------------------------------
// 変数・配列管理
//-------------------------------------------------------------------
// 変数・配列実体管理
// オリジナルはチェインバッファーであるが、iOS版は固定バッファーにする。
// （リンク処理が面倒なので）
// 無駄にバッファーを確保することになるが、iOSデバイスのメモリ容量の前では微々だるものである

// 変数実体チェインバッファーの、1ブロック内の変数個数
#define	CNT_VAR_IN_1_BLOCK	(32*K-1)	// これを超えるときはエラーにする;short最大値

// dims[0]に入れる配列情報
#pragma pack(push,2)
typedef struct { // 1配列の管理構造体；コンパイル時	// VARIABLE1からの通し位置
	uwMATHTYPE	msType;							// +8.w	型
	swJigen		jigen;							//+10.w	次元数
	uwYouso		youso[MAX_DIM_JIGEN];			//+12	[SZ_WORD*MAX_DIM_JIGEN]
} DIM1;
#pragma pack(pop)
#define	SZ_DIM1		(sizeof(DIM1))				// 2+2+2*10=24

#pragma pack(push,2)
typedef struct { // 1変数/配列の管理構造体；コンパイル時のみ使われる
						//	32bit	64bit
	uwHash	hash;		// .w-+		.w-+	ハッシュ値
	UWord	len;		// .w |		.w |	文字数
#ifdef __LP64__	// 64bit
	ULong	reserveL2;	// 			.l-q	なし
#endif
	UByte	*token;		// .p-p		q		変数名
	// 以下は配列時のみ使われる
	DIM1	dims[0];	// 配列時、DIM1が格納されるエリアの先頭アドレス
} VARIABLE1;
#pragma pack(pop)
// この構造はシステム変数/関数の管理でも共通で使われる(処理の共通化)
#define	SZ_VARIABLE1		sizeof(VARIABLE1)			// 2+2+4/8=8/12
#define	SZ_VARIABLE_DIM1	(SZ_VARIABLE1+sizeof(DIM1))	// 8/12+24=32/36


// VARIABLE1(普通変数)のみまたはVARIABLE1+DIM1(配列)が変数実体チェインバッファー内に、
// 1ブロックCNT_VAR_IN_1_BLOCK個固定で書き込まれる


// 1配列の管理構造体；実行時にvarArea内に構築される
// この構造はX-BASICでの定義そのものである
#pragma pack(push,2)
typedef struct {
	ULong	offset;		// +0.l	スキップオフセット（使ってない）
	swJigen	jigen1;		// 4.w	次元数-1 ; X-BASICでの定義なので (ユーザー作成外部関数を出来るだけそのまま移植できるように同じにしておく)
	UWord	size1;		// 6.w	1要素サイズ
	uwYouso	youso[0];	// 8.w～	要素数群[jigen]だけある
	// その後にオフセットテーブルが続く
	//		.l*jigen1分		1次元の時は先頭しかないのでオフセットテーブルも作られない
	// この後に配列要素の実体が続く
} DIM1_EXEC;
#pragma pack(pop)
#define	SZ_DIM1_EXEC	sizeof(DIM1_EXEC)
/* yousoまでの最大サイズは、
	SZ_DIM1-SZ_WORD;msType分+SZ_LONG;offset+SZ_WORD;size1+SZ_LONG*(jigen-1)
　なので、コンパイル時の確保領域では足りない
*/

//-------------------------------
// 変数・配列管理構造体
// これが型別にあり、それぞれを管理する
// コンパイル時と実行時で内容が変わる

#pragma pack(push,2)
typedef struct { // 変数/配列全体の管理構造体；コンパイル時用
								// 		32bit	64bit
	VARIABLE1		*var1Top;	// .p	.l-+	.q		先頭の1変数/配列管理構造体アドレス；チェインバッファー
	void			*varArea;	// .p	.l-q	.q		変数実体先頭のアドレス（実内容は型毎に異なる）	実行時に生成される	V3.20
	swVarCNT		cnt;		// .w	.w--+	-+		登録されている変数の数(1～;0=初期値) ; -1すると変数番号になる
	UWord			reserveW;	// .w	.w	|	 |		予約(境界整合.l)
	ULong			reserveL1;	// .l	.l=.q	-q		予約(境界整合.q)
#ifndef __LP64__	// 32bit
	ULong			reserveL2;	// 		.l-+	なし
#endif
	DIMLIST_CHAIN	*dimList;	// .p	.l-q	.q		配列リストのアドレス
	// 64bitでfloatを読み出すため、ここが.q境界になるように調整する
} VAR_CTRL;
#pragma pack(pop)
#define	SZ_VAR_CTRL	sizeof(VAR_CTRL)	// 4/8+2+2=8/12

/*	VAR_CTRL;コンパイル時
	これがグローバル(globalVarCtrl)に１つ、ローカル(localVarCtrl)も１つ存在する
	コンパイル時は、ソースはグローバル部分かローカル部分かの区別しかないため。
	
	INT用				STR用				CHAR				FLOAT				配列用			
 	+---------------+	+---------------+	+---------------+	+---------------+	+---------------+
 	|*var1Top	.p	|+	|*var1Top		|	|*var1Top		|	|*var1Top		|	|*var1Top		|+
 	+---------------+|	+---------------+	+---------------+	+---------------+	+---------------+|
	|*varArea	.p	||	|*varArea		|	|*varArea		|	|*varArea		|	|*varArea		||<-V3.2で追加;実行時に格納されるので、コンパイル時は未定
	+---------------+|	+---------------+	+---------------+	+---------------+	+---------------+|
 	|cnt		.w	||	|cnt			|	|cnt			|	|cnt			|	|cnt			||
 	+---------------+|	+---------------+	+---------------+	+---------------+	+---------------+|
 	|予約		.?	||	|予約			|	|予約			|	|予約			|	|予約			||
 	+---------------+|	+---------------+	+---------------+	+---------------+	+---------------+|
 	|*dimList	.p	||	|*dimList		|	|*dimList		|	|*dimList		|	|*dimList		||
 	+---------------+|	+---------------+	+---------------+	+---------------+	+---------------+|
					 |																				 |
					VARIABLE1；変数チェインバッファー内に記録										VARIABLE1
					+-----------+---+																+-----------+---------------+
					|hash	.w	|	|																|hash		|				|
					+-----------+	|																+-----------+				|
					|len	.w	| 1変数分																|len		|				|
					+-----------+	|																+-----------+				|
		ソース内	   ←|*token	.p	|	|																|*token		|DIM1			|
					+-----------+---+																+-----------+-----------+	|
				   	～	*cnt分=変数個別に存在する															dims	|msType		|	|
																												+-----------+	|
																												|jigen		|	|
																												+-----------+	|
					全変数・配列で共通登録																			|1次元目要素数	|	|
				中間コードには[type][no]の順で書き込まれる															+-----------+	|
				（故にVARIABLE1内にはtype記憶が無い)																|2次元目		| 1配列分
																												+-----------+	|
																												|3次元目		|	|
																												+-----------+	|
																												|4次元目		|	|
																												+-----------+	|
																												|5次元目		|	|
																												+-----------+	|
																												|6次元目		|	|
																												+-----------+	|
																												|7次元目		|	|
																												+-----------+	|
																												|8次元目		|	|
																												+-----------+	|
																												|9次元目		|	|
																												+-----------+	|
																												|10次元目		|	|
																												+-----------+---+
																									～*cnt分存在する
*/

#pragma pack(push,2)
typedef struct { // 変数/配列全体の管理構造体；実行時用
	VARIABLE1		*var1Top;	// 先頭の1変数/配列管理構造体アドレス；チェインバッファー		コンパイル時に決定済み	V3.20
	void			*varArea;	// 変数実体先頭のアドレス（実内容は型毎に異なる）
	swVarCNT		cnt;		// 登録されている変数の数(1～;0=初期値) ; -1すると変数番号になる
	UWord			reserveW;	// .w	.w	|	 |		予約(境界整合.l)
	ULong			reserveL1;	// .l	.l=.q	-q		予約(境界整合.q)
#ifndef __LP64__	// 32bit
	ULong			reserveL2;	// 		.l-+	なし
#endif
	DIMLIST_CHAIN	*dimList;	// 配列リストのアドレス
} VAR_CTRL_EXEC;
#pragma pack(pop)
#define	SZ_VAR_CTRL_EXEC	sizeof(VAR_CTRL_EXEC)	// ==SZ_VAR_CTRLでなければならない（メンバーオフセットは変えない）

// 配列情報領域サイズ計算式
#define	dimInfoAreaSize(jigen)	(SZ_DIM1_EXEC + ((jigen))*SZ_WORD + ((jigen)-1)*SZ_LONG) // jigenは多重評価されるので注意
								// DIM1_EXEC + 要素数テーブル + オフセットテーブル

/*	VAR_CTRL_EXEC;実行時
	これがグローバルは１つ(globalVarCtrl)、ローカル(localVarCtrl)はブロックごとに存在する。
	グローバルはコンパイル時に作成した物をVAR_CTRL_EXECに読み替えて流用する。
	実行時はローカル=関数の中から別の関数を呼び出すことがあるため、その各関数=ブロック毎にローカルの変数領域が必要となる。
	
	INT用				STR/CHAR/FLOAT		配列用
	+---------------+	+---------------+	+---------------+
	|*var1Top	.p	|+	|*var1Top		|	|*var1Top		|	<-V3.2で追加;コンパイル時に決定した情報そのものへのポインタ；ただしローカルでは使えない(ローカルは同じワークを使いまわすから)
	+---------------+	+---------------+	+---------------+
	|*varArea	.p	|+	|*varArea		|	|*varArea		|+	dim1_exec_adrs[]のアドレスを持っている
	+---------------+|	+---------------+	+---------------+|
	|cnt		.w	||	|cnt			|	|cnt			||	=varListInfo->cnt ; 配列は拡張と普通両方を足した数
	+---------------+|	+---------------+	+---------------+|
	|予約		.?	||	|予約			|	|予約			||
	+---------------+|	+---------------+	+---------------+|
	|*dimList	.p	||	|*dimList		|	|*dimList		||→チェインリスト内dimList;型はここから得る
	+---------------+|	+---------------+	+---------------+|
	～～～～～～～～～～|	～～～～～～～～～～	～～～～～～～～～～|～↓～以下の変数実体エリアの総合計サイズがVARLIST_CHAIN varListInfo.sizeVarArea
					 |										 |
					 |										 |	配列の情報は、固定→可変の順に登録される。固定はコンパイル時に確定されるが、可変は実行時だからである。
					 |										 |	従って、宣言順とは異なる場合があるので注意。
					 |										 |
					 |										 |配列ポインタ群(DIM1_EXEC *dim1_exec_adrs[]) ; これの登録順とDIM1_EXEC～の格納順は必ずしも一致しない
					varArea1								+-------------------------------+					(拡張配列では内容は後から確保されるから)
					+-----------+---+						|配列[0]のDIM1_EXECアドレス	.p	|+～拡張配列では実行時まで内容未確定(領域は確保されている)
					|.型別ｻｲｽﾞ	|１変数分						+-------------------------------+|	関数の引数として配列を渡すときは、渡し側のDIM1_EXECのアドレスが入る
					+-----------+---+						|		～*cnt分 				 |
					～*cnt分存在する							|								 |以下variableAreaから確保
															|								 |DIM1_EXEC : size=(l+w+w)+w*(jigen)+l*(jigen-1)+Σ{size1*各次元要素数}
		新たに、variableAreaからに確保される						|								+-----------+-----------------------------------------------+
		各型別にcnt*１要素サイズ分							配列情報							0	|offset	.l	|												|
		charは全体で４バイト境界化する						サイズはdimInfoAreaSize()				+-----------+												|
															で計算						4	|jigen1	.w	|次元数-1										１配列分
															|								+-----------+												|
															|							6	|size1	.w	|<-配列の型はこれから決めなければならない	(将来、異なる型で同じサイズを持つものを作る時は型も記録する必要がある)
															|								+-----------+-----------+ youso[];要素数テーブル				|
		変数へのアクセスは										|				2次元時	8	8				|1次元要素数	|.w									|
			*型アドレス[no]									|											+-----------+									|
															|						10					～*次元数=(jigen1+1)分							|
		文字列変数はUByte *[no*sz_str]に格納する				|											+-----------+-----------+						|
															|						12				オフセットテーブル	|2次元目ｵﾌｾｯﾄ.l=次次元までの要素数		|
		文字列定数の加算時はstrbufから割り付ける					|	↑									1次元時は存在しない	+-----------+						|
		加算結果を変数に代入しない限り				オフセットは、多次元配列を通しで見たときの、								～*次元数								|
		その結果は一時的なものなので、				2次元目以降の先頭位置を示す要素番号である				-------------------	+-----------+-----------+			|
		次のブロックに入るときには消してしまう												16	10							各要素内容	|1要素のサイズは型別		|
		(次回またそこにきたときに作ればよいだけ)	「例」																				+-----------+			|
													dim a(5,3,2)																～*全要素数				|
													通しでは5*3*2=30要素ある														+-----------+-----------+
																						～この構造がcnt分ある
													2次元目オフセット=5					ただし、個々のサイズは異なる
													3次元目		  =5*3						+-----------+
														→1次元								|			|
												↓	0+	[ 0][ 1][ 2][ 3][ 4]				+-----------+-----------+
											2次元	5+	[ 5][ 6][ 7][ 8][ 9]							|			|
														[10][11][12][13][14]							+-----------+-----------+
																	＼	3次元										|			|
															15+	[15][16][17][18][19]								+-----------+-----------+
																[20][21][22][23][24]											|			|
																[25][26][27][28][29]											+-----------+
																														→variableArea=次のブロック分の記録位置
*/

// 変数型別サイズ
EXTERN UWord Var1Size[MAX_VAR_TYPES]
#ifdef FROM_C
									={SZ_INT,0,SZ_CHAR,SZ_FLOAT,0} // 配列は別途計算が必要なので0を入れておく。文字列は=operationStatus.sz_strしておく
#endif
;

// グローバル変数用(型別)
// 各変数領域の中では型の混在はないので、SLong/DOUBLE_LONG/str/charのみである。
// したがって、先頭アドレスさえ必要バイト境界にあれば、後も全てその境界に置かれる
// =境界整合を考える必要はない
EXTERN	VAR_CTRL	globalVarCtrl[MAX_VAR_TYPES+1];		// int,str,char,float,配列の順(連続確保するため配列にする)
// 個別アクセス用名称定義
#define	GlobalInt		globalVarCtrl[VAR_INT]			// 変数int
#define	GlobalStr		globalVarCtrl[VAR_STR]			// 変数str
#define	GlobalChar		globalVarCtrl[VAR_CHAR]			// 変数char
#define	GlobalFloat		globalVarCtrl[VAR_FLOAT]		// 変数float
#define GlobalArray		globalVarCtrl[VAR_DIM]			// 配列
// グローバルは実行時とコンパイル時で構造体を共有するので、実行時は(VAR_CTRL_EXEC *)で型キャストすること

// ローカルのVAR_CTRL構造体はxbasicMain();XBinterpreter.m内で確保する
EXTERN	VAR_CTRL 		localVarCtrl[MAX_VAR_TYPES]; 	// コンパイル時ローカル用変数管理構造体
#define	LocalInt		localVarCtrl[VAR_INT]			// LOCALint
#define	LocalStr		localVarCtrl[VAR_STR]			// LOCALstr
#define	LocalChar		localVarCtrl[VAR_CHAR]			// LOCALchar
#define	LocalFloat		localVarCtrl[VAR_FLOAT]			// LOCALfloat
#define	LocalArray		localVarCtrl[VAR_DIM]			// LOCAL配列

EXTERN	VAR_CTRL_EXEC	*localVarCtrlExec;				// BASIC内部でグローバルにアクセス出来るようにするため
#define	LocalIntExec	localVarCtrlExec[VAR_INT]		// LOCALint
#define	LocalStrExec	localVarCtrlExec[VAR_STR]		// LOCALstr
#define	LocalCharExec	localVarCtrlExec[VAR_CHAR]		// LOCALchar
#define	LocalFloatExec	localVarCtrlExec[VAR_FLOAT]		// LOCALfloat
#define	LocalArrayExec	localVarCtrlExec[VAR_DIM]		// LOCAL配列

// 配列における次元＆型の格納・取得処理
#define	_setJigenAndType(jigen,type)		(((jigen)<<8)|(type))
#define	_getJignFromJigenAndType(jigentype)	((jigenType)>>8)
#define	_getTypeFromJigenAndType(jigentype)	((jigenType)&0x00ff)

EXTERN	UByte	*strbuf;		// 文字列定数加算で一時的に割り付ける文字列ワークの次回利用アドレス
#define	SZ_STRADDWORK	0x2000	// 文字列定数加算用ワークサイズ
EXTERN	UByte	strAddWork[SZ_STRADDWORK];

//-------------------------------------------------------------------
// interpretMath/Optimizer用構造体
//-------------------------------------------------------------------

#pragma pack(push,2)
typedef struct {
	UWord	*adrs;	// paramの書き込み位置
	ULong	lenL;	// その書き込み長さ(.w単位)
} PRM_ADRS;
#pragma pack(pop)

//-------------------------------------------------------------------
// ネスティング
//-------------------------------------------------------------------

// ネスティングする構文の識別子
typedef SWord	swNESTTYPE;
											// ↓この型キャストを外すとGCCがバグを起こす(NESTTYPE_WHILE==nestType(0xffff)が成立しない)
#define	NESTTYPE_FOR						(swNESTTYPE)(0x0000)	// for
#define	NESTTYPE_WHILE						(swNESTTYPE)(0xffff)	// while
#define	NESTTYPE_SWITCH						(swNESTTYPE)(0x0001)	// switch
#define	NESTTYPE_SWITCH_AFTER_DEFAULT		(swNESTTYPE)(0x0011)	// switch (defaultの後)
#define	NESTTYPE_REPEAT 					(swNESTTYPE)(0x0002)	// repeat
#define	NESTTYPE_IF							(swNESTTYPE)(0x0003)	// if
#define	NESTTYPE_SWITCH_STR					(swNESTTYPE)(0x0004)	// switch(str)
#define	NESTTYPE_SWITCH_STR_AFTER_DEFAULT	(swNESTTYPE)(0x0014)	// switch(str) (defaultの後)

// nest_work内の定義
// ここの内容はややこしく、最初の3つ以降はnestType毎に異なる
// 一部はbefore/nestType以降を中間コードアドレス表に使う（＝NEST構造ではない）
#pragma pack(push,2)
struct _NEST_WORK {
	struct _NEST_WORK	*next;		// .p	次のブロックのポインタ>0/中間言語アドレス(<0=continue,>0=break)	初期はNULL
	struct _NEST_WORK	*before;	// .p	前のブロックのポインタ	初期はNULL
	swNESTTYPE			nestType;	// .w	ネスト種類	NESTTYPE_*
	char				work[0];	// 		nestType別内容(可変)へのオフセット；実体は作られない(GCCの拡張機能)
};
typedef struct _NEST_WORK	NEST_WORK;
#pragma pack(pop)

#define	nest_workSIZE	0x2000
EXTERN	UByte		nestWorkHontai[nest_workSIZE];	// ネスティング処理用ワーク；固定ワーク
EXTERN	NEST_WORK	*nest_work;						// 次に書き込む位置を保持する

/* ネストワークの構造;実体はnestWorkHontai内に書き込まれている

	now = nest_work = 現在使っているネスト
	↓
	↓		now.nextは常に最新の一番最後=次に書き込むべきアドレスを保持している
+→	.next	<---------------------------------------------------------------------------------------------------+
|	.before		1つ前はなし=一番ルートのネストならNULL																|
|	.nestType	workに書き込まれるネストの種類																		|
|	.work 		----------ここからに実体が書き込まれる																|
|								NEST_IF		NEST_WHILE_FOR_NEXT		NEST_SWITCH/CASE/DEFAULT/BREAK	NEST_CASE2	|
|									.～			.～						.～								.～		|
|									.next		.sikis[n]				.next							(next)	|
|									  |			NEST_LOOP.loops			 |								 |		|
|									  |			(next)					 |								 |		|	(next)は算出するもの
|									  |			 |						 |								 |		|
|									  +----------+-----------------------+-------------------------------+------+
|							nextの位置	次のNEST_WORK															↑新しいネストをつなげるdefineNest();XBstat
|										.next																	|
+------------1つ前のブロック-----------	.before																	|
										.nextType																|
										.work -------------------------------									|
														.next													|
														--------------------------------------------------------+
*/
//--------------------------------------
// 以下、.workの位置に入るnestType別内容

// if
#pragma pack(push,2)
typedef struct {
	SWord	ifFlag;		// IF_*
	uwCODE	*adrs;		// 飛び先を書き込むアドレス
	char	next[0];	// このアドレスを示すオフセット；実体は作られない(GCCの拡張機能)；次のネストワークはここからに作成する
} NEST_IF;
#pragma pack(pop)
#define	SZ_NEST_IF	sizeof(NEST_IF)

#define	IF_1LINE		0	// {のないif / }で閉じた後の then
#define	IF_BLOCK		bit(0)
#define	IF_ELSE			bit(1)
#define	IF_ELSE_BLOCK	(bit(1)|bit(0))


// while/next/for共通
#pragma pack(push,2)
typedef struct {
	SWord	cnt;		// 式の数
	swVarNO	no;			// int変数番号	<- オリジナルでは終値がint定数の時だけ書き込まれているが、Cでは常に確保する
	// ↑ここまではすべてで同じ
	uwCODE	sikis[0];	// 式(または変数番号)そのもの	; [cnt]だけ続く
//	NEST_LOOP	loops[]
						// cnt=0のときはsikis=loopsとなる
	// これはnextの位置が記述できないので、プログラムで計算する
} NEST_WHILE_FOR_NEXT;
#pragma pack(pop)


// アドレス値種類
enum {
	ADRS_LOOP=0,	// 通常ループ(continueとは意味が違う)
	ADRS_BREAK,		// break(ステートメントも含む)
	// 以下ステートメントによる代入分
	ADRS_CONTINUE,	// continue
	ADRS_CASE,		// case
	ADRS_DEFAULT	// default
};

// &sikis[len]後にこれが続く
#pragma pack(push,2)
typedef struct {
	uwCODE	*adrs;		// 飛び先
	ULong	adrsFlag;	// 飛び先の種類;ADRS_*
} LOOP_ADRS;
#pragma pack(pop)
#define	SZ_LOOP_ADRS	sizeof(LOOP_ADRS)


#pragma pack(push,2)
typedef struct {
	LOOP_ADRS	loops[0];	// このアドレスを示すオフセット；実体は作られない(GCCの拡張機能)
							// ループ種類などによって個数が可変なので、オフセットにしている
	// これはnextの位置が記述できないので、プログラムで計算する
} NEST_LOOP;
#pragma pack(pop)

// loops[LOOPS_*]のどこに何を入れるか
enum {
	LOOPS_LOOP=0,		// ループアドレス;これだけは位置固定
	// 以下はループ自身の持つもの
	LOOPS_BREAK,		// breakアドレス
	LOOPS_CONTINUE,		// continueアドレス;ない場合もある
	// 此の後にステートメントbreak/continueが格納する分が続くことがある
};


// switch→case/default/breakでネストブロックが構築され、endswitchで確定される

// swicthで作成
#pragma pack(push,2)
typedef struct {
	uwCODE	*table;		// case/default飛び先テーブル
	char	next[0];	// このアドレスを示すオフセット；実体は作られない(GCCの拡張機能)；次のネストワークはここからに作成する
} NEST_SWITCH;
#pragma pack(pop)

// caseはNEST_SWITCH.nextに作成
// 以下はjump部分が共通であり、endswitchはその中のフラグによって処理を分ける

#pragma pack(push,2)
typedef struct {
	LOOP_ADRS	jump;	// 飛び先アドレスを書き込むアドレスとフラグ
	// ↑共通
	ULong		caseValue;	// case値
	char		next[0];	// このアドレスを示すオフセット；実体は作られない(GCCの拡張機能)；次のネストワークはここからに作成する
} NEST_CASE; // 数値用case
#pragma pack(pop)

#pragma pack(push,2)
typedef struct {
	LOOP_ADRS	jump;	// 飛び先アドレスを書き込むアドレスとフラグ
	// ↑共通
	swStrLEN	len;	// 文字列長
	UByte	string[0];	// 文字列;このアドレスを示すオフセット；実体は作られない(GCCの拡張機能)
	// これはnextの位置が記述できないので、プログラムで計算する
} NEST_CASE2; // 文字列用case
#pragma pack(pop)

#pragma pack(push,2)
typedef struct {
	LOOP_ADRS	jump;			// 飛び先アドレスを書き込むアドレスとフラグ
	// ↑共通
	uwCODE		*defaultAdrs;	// defaultの処理アドレス
	char		next[0];		// このアドレスを示すオフセット；実体は作られない(GCCの拡張機能)；次のネストワークはここからに作成する
} NEST_DEFAULT;
#pragma pack(pop)

#pragma pack(push,2)
typedef struct {
	LOOP_ADRS	jump;		// 飛び先アドレスを書き込むアドレスとフラグ
	// ↑共通
	char		next[0];	// このアドレスを示すオフセット；実体は作られない(GCCの拡張機能)；次のネストワークはここからに作成する
} NEST_BREAK;
#pragma pack(pop)
#define	NEST_CONTINUE	NEST_BREAK	// continueも同じ構造(ただし、adrsFlag値が異なる)

//-------------------------------------------------------------------
// FACに入れるパラメーターの型の定義
//-------------------------------------------------------------------

// 引数(パラメーター)の型.w ; T_INTとかとは異なるので注意
// PARAM_BIT_*だと思うので、そう定義し直し
#define	FLOAT_PARAM		PARAM_BIT_FLOAT		// float	0x0000
#define	INT_PARAM		PARAM_BIT_INT		// int		0x0001
#define	CHAR_PARAM		PARAM_BIT_CHAR		// char		0x0002
#define	STR_PARAM		PARAM_BIT_STR		// str		0x0003
#define	POINTER_PARAM	PARAM_BIT_POINTER	// ポインタ	0x0004
#define	VOID_PARAM		(-1)				// 省略された引数
#define	FACTYPE_RETURN	(0)					// リターン時のfacType値
typedef SWord	swFACTYPE;

// リターン値定義.w ; これによりFACの読むべきメンバーが決定できる
typedef UWord	uwRETURNTYPE;	// ==usPARAMTYPEでなければならない(パラメーターテーブルの中に入れるから)
#define	FuncNotFound	(0)		// リターン値はPARAM_RETURNが立っているので=0にはならないので
// .bは_param
#define	FLOAT_RET	(PARAM_RETURN|FLOAT_PARAM)	// 返り値はfloat型	0x8000
#define	INT_RET		(PARAM_RETURN|INT_PARAM)	// 返り値は  int型	0x8001
#define	CHAR_RET	(PARAM_RETURN|CHAR_PARAM)	// 返り値は char型	0x8002
#define	STR_RET		(PARAM_RETURN|STR_PARAM)	// 返り値は  str型	0x8003
#define	VOID_RET	(0xffff)					// 返り値はなし(void)	(-1)だと警告が出るので
//

// これはpackしない : スタック上に配置して読み取るので、境界整合させる必要があるから
typedef struct { // Floating ACcumurator
	// X-BASICの定義ではULong h/lの順だが、CPU依存になるので変更
	DOUBLE_LONG	dl;			// 文字列/配列の場合、.bp[LL]にポインタを入れる
							// intは.l[LL]に入れる
							// charの場合.l[LL]に(int)して入れる
	/* X68のFACでは
	 	32bit					64bit
	 float	8byteすべて			←
	 int	[HW]=0,[LW]=値		←
	 char	[LW.LB]=値			←
	 ポインタ	[HW]=0,[LW]=値		8byteすべて
	 */
	// 境界整合に配慮して、dlを1番目のメンバーに変更
	swFACTYPE	facType;	// 引数型 ; *_PARAM , リターン時はFACTYPE_RETURNにしておく
} FAC;
#define	SZ_FAC		sizeof(FAC)

// 関数呼び出し時にはパラメーター数.wとFAC[その数]が与えられる
// int func(SWord numFAC,FAC fac[]);

// X-BASICでの定義上は、外部関数からのリターン値は
//	d0.l	エラーコード(0=正常終了)
//	a0.l	戻り値を格納したエリアへのポインタ=fac[0],ただしfacType=0
//	a1.l	エラーメッセージへのポインタ(エラー時のみ)

// 配列引数の格納仕方はDIM1_EXEC

//-------------------------------------------------------------------
// 外部関数
//-------------------------------------------------------------------

typedef enum {
	RET_FUNC_OK=0,		// 正常終了
	RET_FUNC_ERR,		// エラー発生
} RET_FUNC;

typedef struct {	// 実行アドレスを持つ構造体
	RET_FUNC	(*func)(SWord numFAC,FAC fac[]);
} FUNC_EXEC;
// このメンバーを直接INFORMATION_TABLE/FUNCTION1に入れたいが、どうしてもエラーを回避できなかったので、構造体をかませた。

// インフォメーションテーブル
typedef struct {
	#ifdef FUNC_DEBUG
	char	*funcName;				// 外部関数名（デバッグ用）
	#endif
	// 各種状態時実行処理定義
	void	(*Finit		)(void);
	void	(*Frun		)(void);
	void	(*Fend		)(void);
	void	(*Fexit		)(void);
	void	(*Fbreak	)(void);
	void	(*FctrlD	)(void);	// 未使用
	void	(*Freserve1	)(void);	// 予約1
	void	(*Freserve2	)(void);	// 予約2
	//
	const char			**tokens;	// 関数名テーブル(トークンテーブル)
	const uwPARAMTYPE	**params;	// パラメーターテーブル(引数定義表)
//	RET_FUNC	*((*execs)(...));	// 実行アドレステーブル(アドレスの配列[])
	FUNC_EXEC	*execs;
	// X-BASICではsizeof(INFORMATION_TABLE)=64にするため、ここに予約領域がある
} INFORMATION_TABLE;

// INFORMATION_TABLE内各種状態時実行処理定義番号
enum {
	noFinit=0,
	noFrun,
	noFend,
	noFexit,
	noFbreak,
	noFctrlD,
};

EXTERN	const INFORMATION_TABLE  *functionsList[MAX_FUNC_FILES];	// 外部関数インフォメーションテーブルリスト

//-------------------------------------------------------------------
// 内部関数
//-------------------------------------------------------------------

EXTERN	char *extraFunctionErrmes; 	// 外部関数のエラーメッセージ ; リターン値==RET_FUNC_ERRの時のみ有効
									// 設定はsetExternalFuncErrmes()で行う
EXTERN	UByte *externalSourceLine;	// ソース行を外部から指定してエラー表示させるための指定
									// lineNo==LINENO_SPECIALにする

// １関数テーブル；内部・外部関数共用
typedef struct {
	uwHash		hash;			// ハッシュ値
	swStrLEN	len;			// 文字数
	UByte		*token;			// 関数名(EOSを含む）
	// ↑ここまでは変数と同じ
	uwPARAMTYPE	*param;			// パラメーター(引数定義)←paramBuffCtrlチェインバッファー
//	RET_FUNC	(*exec)(...);	// 実行アドレス	実引数は(SWord numFAC,FAC fac[])
	FUNC_EXEC	exec;
} FUNCTION1;
#define	SZ_FUNCTION1	sizeof(FUNCTION1)

EXTERN	FUNCTION1	*FunctionBuffer;	// 外部関数テーブル；実体はmallocされる	関数buf

// 登録されている内部関数数
EXTERN	SWord		InternalFunctionCount;
// 内部関数テーブル；全関数分
EXTERN	FUNCTION1	InternalFunctionBuffer[MAX_INTERNAL_FUNC];
// 全内部関数のパラメーターリストを作成する領域;+1はリターン値用
EXTERN	uwPARAMTYPE	InternalFunctionParam[(sizeof(uwPARAMTYPE)*(MAX_PARAM+1))*MAX_INTERNAL_FUNC];

// 上記は固定で確保する。
// 内部関数の検索には時間がかかるため2パスに出来ないので。

typedef struct {
	UWord	offset;	// FunctionBuffer内でのオフセット=FunctionBuffer内[要素番号]
	UWord	cnt;	// 同一hash(の下位1バイト)に含まれる関数数
} FUNC_TABLE;
EXTERN	FUNC_TABLE	ExternalFuncsionTable[256];	// ハッシュ値の下位1バイト別だから	外部functable


EXTERN	SWord	AllExternalFuncsionCount;	// 全外部関数の総関数数								全外部関数個数
EXTERN	SWord	ExternalFuncsionFiles;		// 外部関数ファイル数(標準関数があるから0にはならない)	関数file数

//-------------------------------------------------------------------
// システム変数
//-------------------------------------------------------------------

EXTERN const char *NameOfSystemVariable[]	// システム変数
#ifdef FROM_C
={
	// int型
	"errno",
#if 0	// v2.2でenum値に変更
	"YES",
	"NO",
	"true",
	"false",
#endif
	// str型；$で始めている；先頭の$は名前には入らない
	"$basicVersion$",
	"$basicCoreVersion$",
	"$iOSInterfaceVersion$",
	"$date$",
	"$day$",
	"$time$",
	"$NULL$",
	// 他の型のを作る時は考えること(makeSystemVariableTable()の修正も必要)
	// end of table
	NULL
}
#endif
;
#ifdef FROM_C
#define	CNT_SYSTEM_VAR	(sizeof(NameOfSystemVariable)/sizeof(char *))	// .h中では内容が確定しないので使えない
#endif

// makeSystemVariableTable();xbmath.mで代入される
typedef struct {
	uwHash		hash;		// ハッシュ値
	swStrLEN	len;		// 文字数
	UByte		*token;		// 名前へのポインタ
	// ↑ここまでは変数と同じ
	uwMATHTYPE	msType;		// 型
	swVarNO		no;			// 番号；int/str別
} SYSTEM_VARIABLE;
#define	SZ_SYSTEM_VARIABLE	sizeof(SYSTEM_VARIABLE)

EXTERN	SYSTEM_VARIABLE		systemVariable[
#ifdef FROM_C
CNT_SYSTEM_VAR	// NameOfSystemVariable[]は.h中では確定しないからsizeof()も確定しないので
#endif
];	// system変数

//-------------------------------------------------------------------
// ステートメント定義のため
//-------------------------------------------------------------------

typedef struct {
	uwHash		hash;		// ハッシュ値
	swStrLEN	len;		// 文字数
	char		*token;		// 名前へのポインタ;本当はUByte *にしたいが、コンパイラが警告を出しやがるので
	// ↑ここまでは変数と同じ
} STATEMENT_TABLE;

//-------------------------------------------------------------------
// 定数テーブル
//-------------------------------------------------------------------

EXTERN const uwPARAMTYPE	TypeOfParameters[]	// prm引き数の型
#ifdef FROM_C
	={INT_VAL,STR_VAL,CHAR_VAL,FLOAT_VAL}		// 0002,0008,0004,0001
#endif
;
#define	TypeOfParameters_int	0	// int型の位置


// VAR_TYPES → MATH_型への変換にも使う
EXTERN const uwMATHTYPE		MathTypeOfParameters[]	// ms引き数の型
#ifdef FROM_C
	={MATH_INT,MATH_STR,MATH_CHAR,MATH_FLOAT}	// 0000,0100,0200,8000
#endif
;

EXTERN const uwRETURNTYPE	ReturnTypes[]	// ret返り値の型
#ifdef FROM_C
	={INT_RET,STR_RET,CHAR_RET,FLOAT_RET}
#endif
;

// 型の名前とその型の値の表
typedef struct {
	char	*name;	// 文字定数を使うためUByte*に出来ない
	uwTYPE	type;
} NAME_TYPE;

EXTERN const NAME_TYPE name_type[]
#ifdef FROM_C
={	// VAR_TYPES順
	{"int"		,T_INT	},	// 0000
	{"str"		,T_STR	},	// 0001
	{"char"		,T_CHAR	},	// 0002
	{"float"	,T_FLOAT},	// 0080
	// end of table
	{NULL		,0},
}
#endif
;
//#define CNT_NAME_TYPE	(sizeof(name_type)/sizeof(NAME_TYPE)) // ヘッダーでは要素が確定しないためsizeof()が使えない


// 演算子と中間コードの表
typedef struct {
	char		*name;
	uwCODE		code;
} NAME_CODE;

EXTERN const NAME_CODE OperatorName[]	// 演算子の表
#ifdef FROM_C
={	// 記号演算子
	{"*"	,CODE_MUL	},
	{"/"	,CODE_DIV	},	// 別途 /*,// == 注釈の判定が必要
	{"\\"	,CODE_IDIV	},
	{"+"	,CODE_ADD	},
	{"-"	,CODE_SUB	},
	{"="	,CODE_EQU	},	// 比較(代入ではない)
	{"<"	,CODE_SMALL	},	// 別途 <,=<,<>	の場合分けが必要
	{">"	,CODE_LARGE	},	// 別途 >,>=	の場合分けが必要
	// 非記号演算子
	{"or"	,CODE_OR	},
	{"and"	,CODE_AND	},
	{"mod"	,CODE_MOD	},
	{"not"	,CODE_NOT	},
	{"shl"	,CODE_SHL	},
	{"shr"	,CODE_SHR	},
	{"xor"	,CODE_XOR	},
	// end of table
	{NULL	,CODE_NONE	}
}
#endif
;
//#define CNT_ENZANSI_NAME	(sizeof(OperatorName)/sizeof(NAME_CODE))	// .Cコンパイル時以外には確定しないので使えない

// else/thenの文字列
#define	nameELSE	"else"
#define	nameTHEN	"then"
#define	lenELSETHEN	(sizeof(nameELSE)-1)	//上記2つの文字列長(同じにすること;手抜き)

//-------------------------------------------------------------------
// 動作モードフラグ+グローバル制御変数
// ローカル中で変更されるものもあるので、構造体にまとめ、ローカル呼び出し時には待避/復帰する

typedef struct {
	// コンパイラのフラグ
	int		finFunc;		// func中かどうか							YES=中 , NO=func中でない
	int		fenum;			// enum中かどうか		v2.1				ENUM_*
	SLong 	intEnum; 		// int   enum初期値	v2.1
	double	floatEnum;		// float enum初期値	v3.10

	// インタプリタのフラグ
	int		fundefVarInt;	// 未宣言で代入される変数をintとして自動定義するかどうか	YES=する , NO=しない
							// dimなしでの配列宣言を可能にするかどうか
	int		ferror;			// 外部関数エラー発生時にエラーメッセージを表示する＝停止するかどうか 		ERR_ON/ON2=する , ERR_OFF=しない
	int		fbreakoff;		// BREAKを無効にするかどうか				YES=無効にする , NO=しない
	int		fend;			// プログラムが終了するかどうか				STATE_*

	// インタプリタ・コンパイラ共用フラグ・設定
	swStrLEN	sz_str;		// 最大文字列長+1							(1 for EOS ; 16～1024;SZ_WORDの倍数にしておくこと , 標準=256)
							// ソースの長さは関係ない(常にMAX_SOUREC1LINE)
	int		flocal;			// ローカル変数かどうか						YES=ローカル , NO=グローバル
	int		fdimSizeVar;	// 配列の要素数指定に変数があるかどうか		YES=ある , NO=ない
	// 全体動作
	int		fsjisInSetup;	// 強制SHIFT-JISモードにするかどうか			FSJIS_*
	int		fsjis;			// 強制SHIFT-JISモードかどうか				YES/NO
							// 変わるのは、'1文字とusingの文字数の意味のみ(SJISではバイト単位)
	int		ferrSource;		// エラー時にソース行を表示するかどうか		YES=する , NO=しない
	int		fenglish;		// 英語モード								YES=English , NO=日本語；将来的に多国語化するならここを使う
	int		fsprite;		// スプライト関数を有効にするかどうか
	int		fX68;			// X68互換関数を有効にするかどうか
	int		fOlder;			// 表示をv3.00互換にするかどうか
	//
	int		debugMode;		// デバッグモード	DEBUG_MODE_*
	int		debugDumpMode;	// ダンプ設定		DUMP_*	(XB.h)
	void (*debugPrintFunc)(NSString *text);	// ダンプ先関数
	int		dumpCnt;		// ダンプ出力の回数；1回しか出力してはいけないものもあるので
	//
	int		errorCodeFopen;	// fopenのエラーコード		0=旧:0,-1=新		V3.10で変更したが、互換モードも持つので現在値をこれに入れる
	char	*programName;	// 実行中プログラム名		v3.20
} OPERATION_STATUS;

EXTERN	OPERATION_STATUS	operationStatus;

EXTERN	int fsjisInRun;		// 実行中のfsjis	v3.00	YES/NOどちらか	実行開始時は=fsjis
EXTERN	int	errorCodeFopenInRun;	// 実行中のerrorCodeFopen	v3.10

enum {
	FSJIS_NO 	=NO,	// 0	強制SHIFT-JISモードにしない
	FSJIS_YES	=YES,	// 1	強制SHIFT-JISモードにする
	FSJIS_AUTO			// 2	ファイルの文字コードによって決定 -> fsjis
};

enum { // enumの種類と状態
	ENUM_NONE=0,	// enum中でない
	ENUM_INT,		// enum中
	ENUM_FLOAT,		// fenum中
	ENUM_STR,		// senum中
}; // 各enumはネストできないので1つで良い

// ダンプ条件設定
#define	DEBUG_MODE_NORMAL	0		// debugDump()だけ
#define	DEBUG_MODE_RETURN	BIT8	// 関数を抜け出す時
#define	DEBUG_MODE_BREAK	BIT9	// Break時
#define	DEBUG_MODE_END		BIT10	// end時
#define	DEBUG_MODE_STOP		BIT11	// stop時
#define	DEBUG_MODE_ERROR	BIT15	// エラー発生時
#define DEBUG_MODE_ALL		(DEBUG_MODE_RETURN|DEBUG_MODE_BREAK|DEBUG_MODE_END|DEBUG_MODE_ERROR)

//-------------------------------------------------------------------
// インタープリター用
//-------------------------------------------------------------------

typedef enum {
	STATE_BREAK=-3,	// Breakが押された
	STATE_STOP=-2,	// stopされた
	STATE_END=-1,	// end/exitされた
	STATE_OK=0,		// 正常実行中
	STATE_RETURN,	// xbasicMain()を抜ける
	STATE_ERROR,	// エラー
} STATE;

//-------------------------------------------------------------------

#endif
