//--------------------------------------------------------------------------------------
//
// X-BASIC'
//	インタープリター(実行)
//
//--------------------------------------------------------------------------------------

#include "fdef.h"
#include "XB.h"
#include "code2code.h"
#include <ctype.h>
#import "libs.h"
#include "atod3.h"
#include "atoi3b.h"
#import "myString.h"

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

// リターン値を格納するFAC
// リターンするのは１ブロック１回だけなので共通ワークでかまわない（ただし、リターン直前に代入・確定する）
FAC	retFromFunctions;

//--------------------------------------------------------------------------------------
// 各ステートメントごとの処理
//--------------------------------------------------------------------------------------
// 実行時には呼ばれるはずのないステートメント

STATE E_Gosub(void)
{
	DBG_Func();
	nslog(@"Gosubが使われている");
	IError(ERR_SYSTEM/*ERR_NON_SUPPORT_STATEMENT*/);
	return(STATE_ERROR);
}

STATE E_NonExecute(void)
{
	nslog(@"実行時には出てこないはずのステートメント");
	IError(ERR_SYSTEM);
	return(STATE_ERROR);
}

#define	E_Case		E_NonExecute
#define	E_Func		E_NonExecute
#define	E_Default	E_NonExecute

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

// iOSではアプリからの時計への代入はしない方が良いはずなので、サポートしない
STATE E_SysVar(void)
{
	DBG_Func();
	IError(ERR_DISABLE_ASSIGN_SYSTEMVAR);
	return (STATE_ERROR);
}

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

STATE E_Error(void)
{
	DBG_Func();
	switch (readInternalCode()) {
		case ERR_OFF: // OFF
			nslog(@"error off");
			operationStatus.ferror=ERR_OFF;
			break;
		case ERR_ON: // ON
			nslog(@"error on");
			operationStatus.ferror=ERR_ON;
			break;
		case ERR_ON2: // ON2 v2.6
			nslog(@"error on2");
			operationStatus.ferror=ERR_ON2;
			break;
	}
	return (STATE_OK);
}

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

// 文字内容更新式
// 文字列変数中の1文字を書き換える
STATE E_Str(void)
{	// 1941
	DBG_Func();
	SLong num1=intGetValue();		// 代入ポインタ=変数番号
	SLong num2=intGetValue();		// 文字コード
	swVarNO no=readInternalCode();	// str変数番号=いくつ目の文字列変数か
	VAR_CTRL_EXEC *var_ctrl_exec=getVarCtrlExecWithVarNo(VAR_STR,&no);
	UByte *p=var_ctrl_exec->varArea;
	p=&p[no*operationStatus.sz_str]; // その文字列変数の格納開始位置
	if (num1>=bstrlen(p)) {
		// 変更対象文字列長を超えている
		IError(ERR_STRING_OFFSET_OUTOF_LENGTH);
	}
	p[num1]=(UByte)num2;
	return (STATE_OK);
}

//------------------------------------------------------
// 配列

STATE E_Dim(void)
{	// 1972
	DBG_Func();
	// CODE_dimは2つの処理に使われている
	uwTYPE wType=readInternalCode();	// 型
	uwTYPE  type=_getType(wType);
	swVarNO	  no=readInternalCode();	// 配列番号
	DBG_printf3("型=$%04x/%04x,配列番号=%d(変換前)\n",wType,type,no);
	
	if (_isNotConstant(wType)) {
		// 可変長配列定義:	2027
		DBG_printsn("可変長配列定義");
		// ローカルの配列宣言時、要素数指定に変数が使える(ぺけ-BASICでの拡張)
		// グローバルは定数でのみ宣言可能
		
		// 拡張配列はvariableInit()では要素数未定のため、DIM_EXEC領域が確保されていない。
		// (dim1_exec_adrs[]は確保されている)
		// そのため、ここでその確保が必要となる。
		no=getVarNo(no);
		swJigen jigen=readInternalCode();	// 次元
		DBG_printf2("配列番号=%d(変換後)/次元数=%d\n",no,jigen);
		
		// 変数エリアを確保するため、先に全要素数を読んでしまう
		SWord sz1=Var1Size[_getSerialType(type)];	// T_*型別 1要素サイズ
		DBG_printf1("1要素サイズ=%d\n",sz1);
		ULong sizeL=1;
		uwYouso youso[MAX_DIM_JIGEN];
		int i;
		for (i=0;i<jigen;i++) {
			SLong num=intGetValue();
			num++; // BASICでは指定要素数+1まで使える;a(10)ならa(0)～a(10)の11個
			if (num>=MAX_DIM) { // 要素数が多すぎる
				nslog(@"1次元の要素数が多すぎる");
				IError(ERR_ILLEGAL_DEFINE_ARRAY);
			}
			youso[i]=num; // 要素数の大きさ
			DBG_printf2("次元%d : 大きさ=%d\n",i+1,(int)num);
			sizeL*=((ULong)sz1*num); // 総サイズ
		}
		DBG_printf1("要素分総サイズ=%d\n",(int)sizeL);
		
		// 配列情報領域のサイズも加える
		sizeL+=dimInfoAreaSize(jigen);
		DBG_printf1("＋配列情報領域=%d\n",(int)sizeL);
		
		// 其の分をvariableAreaから確保(その先頭アドレスを返す)
		UByte *varArea=getVariableArea(sizeL);
		//
		DIM1_EXEC **dim1_exec_adrs=(DIM1_EXEC **)LocalArrayExec.varArea; // 読み替えのため
		DBG_printf1("dim1_exec_adrs[]=%p\n",dim1_exec_adrs);
		dim1_exec_adrs[no]=(DIM1_EXEC *)varArea; // 指定配列番号分のDIM1_EXEC実体位置をここで確定する
		DBG_printf3("＞dim1_exec_adrs[%d]=%p → 実体:%p\n",no,&dim1_exec_adrs[no],varArea);
		//
		dimSetYousoAndOffset(jigen,sz1,youso,varArea); // 実体からに情報を書き込む(連続確保はないのでリターン値は不要)
		DBG2_printsn("dimSetYousoAndOffset後");
		#ifdef CORE_DEBUG
		{
		DBG_printf("VAR_CTRL_EXEC[DIM]全表示(E_Dim)\n");
		SWord cnt=LocalArrayExec.cnt;
		DBG_printf(".varArea=%p(=dim1_exec_adrs[])\n",dim1_exec_adrs);
		DBG_printf(".cnt=%d\n",cnt);
		_f();
		int j;
		for (j=0;j<cnt;j++) {
			DIM1_EXEC *dim1_exec=(DIM1_EXEC *)dim1_exec_adrs[j];
			DBG_printf("%d : DIM1_EXECアドレス=%p\n",j,dim1_exec); _f();
			if (dim1_exec!=NULL) {
				DBG_printf("  dim1_exec.offset=%d/jigen1=%d/size1=%d\n",(int)dim1_exec->offset,dim1_exec->jigen1,dim1_exec->size1);
				_f();
				int k;
				for (k=0;k<=dim1_exec->jigen1;k++) {
					DBG_printf("    %d次元目:要素数=%d\n",k+1,dim1_exec->youso[k]);
					_f();
				}
			} else { // dim宣言前はNULLだから飛ばしておく
				DBG_printf("    dim未宣言\n");
			}
		}
		}
		#endif
		variableArea+=sizeL;	// 次の確保エリアへ
	} else { // 固定長配列への書き込み
		// 1975
		DBG_printsn("固定長配列への(初期)書き込み");
		VAR_CTRL_EXEC *var_ctrl_exec=getVarCtrlExecWithVarNo(VAR_DIM,&no);
		DIM1_EXEC **dim1_exec_adrs=(DIM1_EXEC **)var_ctrl_exec->varArea;	// 読み替えのため
		DIM1_EXEC *dim1_exec=dim1_exec_adrs[no];	// 指定配列番号分のDIM1_EXEC実体
		swJigen jigen = dim1_exec->jigen1+1;		// 次元数
		DBG_printf1("次元数=%d\n",jigen);
		ULong *offset=(ULong *)&dim1_exec->youso[jigen];	// オフセットテーブル位置(jigen1分);普通配列は4バイト境界化なし(これは型変換)
		UByte *bp    =(UByte *)&offset[jigen-1];			// データ実体(これは型変換)
		//
		swVarCNT cnt=readInternalCode(); // 総データ数
		DBG_printf1("総データ数=%d\n",cnt);
		switch (type) {
			case T_FLOAT:	// float_dim_init:
				{
				// ↓これは型変換
				DOUBLE_LONG *dp =(DOUBLE_LONG *)bp;
				DOUBLE_LONG *dp5=internalCode.dp;
			#if AARM>=1
				mmemcpyL(dp, dp5, SZ_DOUBLE_LONG*cnt);
				dp5+=cnt;
			#else
				while (cnt-->0) {
					*dp++=*dp5++;
				}
			#endif
				internalCode.bp=(UByte *)dp5;
				}
				break;
			case T_INT:	// int_dim_init:
				{
				SLong *lp=(SLong *)bp;
			#if AARM>=2
				mmemcpyL(lp,internalCode.lp,SZ_LONG*cnt);
				internalCode.lp+=cnt;
			#else
				while (cnt-->0) {
					ULong num;
					num=readInternalCodeL();
					*lp++=num;
				}
			#endif
				}
				break;
			case T_STR:		// str_dim_init:
				while (cnt-->0) {
					UByte *p=bp;
					while ((*p++=*internalCode.bp++)!=EOS);
					bp+=operationStatus.sz_str;
				}
				break;
			case T_CHAR:	// char_dim_init:
				while (cnt-->0) {
					*bp++=*internalCode.bp++;
				}
				break;
		}
		// strとcharのみ、偶数境界化	2008
		if (internalCode.l&1) *internalCode.bp++=EOS; // 念のためEOSを入れておく
	}
	DBG_printsn("設定完了");
	return (STATE_OK);
}

//-----------------------------------------------
// 制御構文とコマンド
//-----------------------------------------------

// T_INT型switch
STATE E_Switch(void)
{	// 2085
	DBG_Func();
	
	SLong num1=intGetValue();				// case値
	DBG_printf1("case値=%d\n",(int)num1);
	
	readInternalAbsoluteAdrs();	// case table : 相対アドレスを絶対アドレスに変換する
	DBG_printf1("case tableアドレス=%p\n",internalCode.wp);

	swCaseCNT cnt=readInternalCode();		// case の個数(defaultは含まない)
	DBG_printf1("case 個数=%d\n",cnt);
	/* case テーブルの構造
		.l	case値
		.p	飛び先オフセットアドレス
	*/
	while (cnt-->0) {
		SLong num=readInternalCodeL();
		if (num1==num) { // case値に一致した
			break;
		}
		internalCode.vp++; // case処理アドレスを飛ばす
	}
	// cntだけ回ってここまで来た時は、internalCodeはcase tabelの次を差している=default
	
	readInternalAbsoluteAdrs();	// その処理へ飛ばす
	return (STATE_OK);
}

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

// T_STR型switch
STATE E_Switch2(void)
{	// 2103
	DBG_Func();

	DOUBLE_LONG dl=getValue(T_STR);	// 値１
	UByte  *bp=dl.bp[LL];
	swStrLEN len=bstrlen(bp);		// 文字列長さ
	DBG_prints("case文字列:");
	DBG_printName(bp,len);

	readInternalAbsoluteAdrs();	// case table
	DBG_printf1("case tableアドレス=%p\n",internalCode.wp);

	swCaseCNT cnt=readInternalCode();		// case の個数
	DBG_printf1("case 個数=%d\n",cnt);
	while (cnt-->0) {
		swStrLEN len0=readInternalCode();	// 文字列長さ
		DBG_printf1("case 文字列長=%d\n",len0);
		int f=NO;
		if (len0==len) { // 文字列長は一致
			// 文字列本体を比較
			if (strcmp((char *)bp,(char *)internalCode.bp)==0) {
				// 文字列も一致
				DBG_printsn("文字列も一致");
				f=YES;
			}
		} // 文字列長不一致＝文字列不一致
		// case処理アドレスと文字列を飛ばす
		len0++;		// EOS分
		if (len0&1) len0++; // 偶数バイト化
		internalCode.bp+=len0;
		if (f) break; // 文字列一致時
		internalCode.vp++;	// case処理アドレスを飛ばす
	}
	// cntだけ回ってここまで来た時は、internalCodeはcase tabelの次を差している=default
	
	readInternalAbsoluteAdrs();	// その処理へ飛ばす
	return (STATE_OK);
}

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

#define	E_Break		E_Goto
#define	E_Else		E_Goto
#define	E_Continue	E_Goto

STATE E_Goto(void)
{	// 2169
	DBG_Func();

	readInternalAbsoluteAdrs();	// 飛ばす(gotoは飛び先へのオフセットが格納されている)
	return (STATE_OK);
}

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

// fnonJump : 飛ばない条件
static STATE ifNotJump(int fnonJump)
{
	DBG_printf3("%s:(%d)internalCode.wp=%p\n",__FUNCTION__,fnonJump,internalCode.wp);
	
	if (fnonJump) {	// 飛ばないとき
		DBG_printsn("飛ばない\n----------------------------------------");
		internalCode.vp++;	// ジャンプ先.vpの次の命令へ
	} else {
		readInternalAbsoluteAdrs();	// 飛ばす
		DBG_printf1("飛ぶ → %p\n",internalCode.wp);
	}
	return (STATE_OK);
}

STATE E_For(void)
{	// 2147
	DBG_Func();
	
	SLong num1=intGetValue();	// 値１
	//
	swVarNO no=readInternalCode();// 変数番号
	VAR_CTRL_EXEC *var_ctrl_exec=getVarCtrlExecWithVarNo(VAR_INT,&no);
	SLong *lp=(SLong *)var_ctrl_exec->varArea;
	lp[no]=num1;
	DBG_printf2("変数アドレス=%p<-%d\n",&lp[no],(int)num1);
	//
	SLong num2=intGetValue();	// 値２
	nslog(@"For i=%d to %d",(int)num1,(int)num2);
	
	// for (i=num1 to num2)でループに入るのはnum1<=num2のとき
	return (ifNotJump(num1<=num2));
	// いったんループに入ったら、終値判定はnext側で行われる
}

static STATE nextSub(int fend2)
{
	swVarNO no=readInternalCode();	// 変数番号
	DBG_printf2("%s:変数番号=%d\n",__FUNCTION__,no);
	
	// ループカウンター変数
	VAR_CTRL_EXEC *var_ctrl_exec=getVarCtrlExecWithVarNo(VAR_INT,&no);
	SLong *lp=(SLong *)var_ctrl_exec->varArea;
	DBG_printf1("変数アドレス=%p\n",&lp[no]);
	SLong num1=lp[no];
	DBG_printf1("num=%d++\n",(int)num1);
	lp[no]=num1+1;	// ++した値を保存
	
	// 終了値
	SLong num2;
	if (fend2) {// next2
		num2=readInternalCodeL();	// 定数
	} else {	// next
		num2=intGetValue();			// 変数
	}
	DBG_printf1("終了値:%d\n",(int)num2);

	// for i=num1 to num2 : nextでnum1>=num2で終了
	// 今回の比較値はnum1=今回のループ値
	DBG_printf3("num=%d:num2=%d;比較結果(>=)=%d\n",(int)num1,(int)num2,(num1>=num2));
	return (ifNotJump(num1>=num2));
}

STATE E_Next2(void)
{
	DBG_Func();
	// [NEXT2][変数番号.w][終値.l][FORの次のアドレスまでのオフセット.vp]
	return (nextSub(YES));
}

STATE E_Next(void)
{
	DBG_Func();
	// [NEXT][変数番号.w][FORの次のアドレスまでのオフセット.vp]
	return (nextSub(NO));
}

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

#define	E_While	E_If
#define	E_Until	E_If

STATE E_If(void)
{	// 2178
	// [if.w][式群.w*n][ジャンプ先.l]
	DBG_Func();
	SLong num1=intGetValue();	// 値1(式)
	return (ifNotJump(num1!=0));
}

STATE E_Endwhile(void)
{	// 2244
	// [Endwhile.w][式群.w*n][ジャンプ先.l]
	DBG_Func();
	SLong num1=intGetValue();		// 値1
	// while ～ endwhile
	return (ifNotJump(num1==0));	// 抜けるのはfalse(trueの時に飛ぶ)
}

STATE E_Ifeq(void)
{
	DBG_Func();
	SLong num1=intGetValue();	// 値1
	SLong num2=intGetValue();	// 値2
	return (ifNotJump(num1==num2));
}

STATE E_Ifne(void)
{
	DBG_Func();
	SLong num1=intGetValue();	// 値1
	SLong num2=intGetValue();	// 値2
	return (ifNotJump(num1!=num2));
}

STATE E_Ifgt(void)
{
	DBG_Func();
	SLong num1=intGetValue();	// 値1
	SLong num2=intGetValue();	// 値2
	return (ifNotJump(num1>num2));
}

STATE E_Ifge(void)
{
	DBG_Func();
	SLong num1=intGetValue();	// 値1
	SLong num2=intGetValue();	// 値2
	return (ifNotJump(num1>=num2));
}

STATE E_Iflt(void)
{
	DBG_Func();
	SLong num1=intGetValue();	// 値1
	SLong num2=intGetValue();	// 値2
	return (ifNotJump(num1<num2));
}

STATE E_Ifle(void)
{
	DBG_Func();
	SLong num1=intGetValue();	// 値1
	SLong num2=intGetValue();	// 値2
	return (ifNotJump(num1<=num2));
}

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

void skipInputMessage(void)
{	// inp_sub	2554
	while (*internalCode.bp++!=EOS);
	if (internalCode.l&1) *internalCode.bp++=EOS; // 偶数境界化;念のためEOSを入れておく
}

// 進数判断付き数値入力
SLong inputNumberWithShinsu(UByte *(*bp00))
{
	UByte *bp0=*bp00;
	int base=10;
	switch (*bp0) {
		case '&': // 進数指定
			switch (*++bp0) {
				case 'h': // 定数HEX
					base=16;
					bp0++;
					break;
				case 'b': // 定数BIN
					base=2;
					bp0++;
					break;
				case 'o':
					base=8;
					bp0++;
					break;
				default:
					Warn(WARN_ILLEGAL_NUMBER_FORMAT); // "数値指定が間違っています"
					// bp0不変
					return(0);	// 一応0を返す
			}
			break;
		case '\'': // \'1文字
			{
			bp0++; // 'を飛ばす
			ULong c=getSjisOrUtf8(&bp0,fsjisInRun);
			if (*bp0=='\'') bp0++; // 閉じ\'があるときはそれも飛ばす
			*bp00=bp0;
			return (c);
			}
	}
	return (atoi3b(bp0,base,bp00));
}

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

STATE E_Input(void)
{
	DBG_Func();
	uwMATHTYPE msType=MATH_INT; // 入力が全くない時に再入力させるため
	REGISTER internalCode0=internalCode; // 保存;リトライ時のため
	//
	// input "message=";a,b,c
	do { // 入力を最初からやり直す	Inp_retry:
		internalCode=internalCode0;
		
		// internalCode.bp～にはその入力タイトル文字列が入っている
		// 入力催促文字列の表示
		UByte *p1=tmp;
#if DOS
		fputs((char *)internalCode.bp,stderr);
#else	// iOS
		printus(internalCode.bp);
#endif
		//
		skipInputMessage(); // 中間コード内の入力タイトル文字列を飛ばす
		//
#if DOS
		// 入力
		scanf("%s",p1);
		// 完全未入力はここで処理すること
#else
		// iOS
		// 本当は代入する変数別に変更したいが、入力後にしか型がわからないので仕方なくreturn付き数値型(デフォルトキーボードは文字列用であるが、inputでは数値入力のほうが確率が高いから)
		strcpy((char *)p1,(char *)input(UIKeyboardTypeNumbersAndPunctuation)); // UIKeyboardTypeDefault
		// input後に入力内容の表示と改行が必要
		printus(p1);
		prints("\n");
#endif
		DBG_printf1("input=%s<<\n",p1);
		
		// p1内を分割解釈
		UByte *p0;
		while (*p1!=EOS) { // Inp_loop: 2590
			// 入力内容を整形しながらtmp1(p1) → tmp2(p2)へ転送する
			DBG_printsn("入力内容を整形しながらtmp1(p1) → tmp2(p2)へ転送する");
			p0=tmp2;
			UByte c;
			while ((c=*p1)!=EOS) {
				p1++;
				if (c==',')	break;
				*p0++=c;
			}
			// EOS(全体)または , で区切られた1つ分
			// 行末のスペースを取り除く 2604
			while (*(p0-1)==' ') p0--;
			*p0=EOS; // 2609
			
			DBG_printf1("実体=%s<<\n",tmp2);
			
			// 転送された内容を解釈	2610
			msType=readInternalCode();
			if (msType==MATH_VOID) break; // 必要引数列(変数番号列)が終了したので解釈も終了
			swVarNO		   no=readInternalCode();
			DBG_printf2("型=$%04x,変数番号=%d\n",msType,no);
			
			p0=tmp2;
			DBG_printf1("1入力=%s\n",p0);
			VAR_CTRL_EXEC *var_ctrl_exec;
			switch (msType) { // 型別代入処理
				#ifdef CORE_DEBUG
				default:
					DBG_printf1("その他:$%04x\n",msType);
					break;
				#endif
				
				case MATH_STR:	// Inp_str: 2625
					{
					DBG_printsn("MATH_STR");
					var_ctrl_exec=getVarCtrlExecWithVarNo(VAR_STR,&no);
					UByte *bp=(UByte *)var_ctrl_exec->varArea;
					bp=&bp[no*operationStatus.sz_str];
					DBG_printf1("元inp=%s\n",bp);
					if (*p0==EOS) continue; // 入力がない時は変数内容無変更
					//DBG_printf1("*p0=%c\n",*p0);
					//
					while ((*bp++=*p0++)!=EOS); // 実内容転送
					p0--; // EOSの位置に合わせておく（後の処理を共通化するため）
					//DBG_printf1("*p0=%c\n",*p0);
					}
					// 文字列入力には型違いはない
					break;
				
				case MATH_INT:	// Inp_int: 2645
					{
					DBG_printsn("MATH_INT");
					var_ctrl_exec=getVarCtrlExecWithVarNo(VAR_INT,&no);
					SLong *lp=(SLong *)var_ctrl_exec->varArea;
					lp=&lp[no];
					DBG_printf1("元inp=%d\n",(int)*lp);
					if (*p0==EOS)	continue; // 入力がない時は変数内容無変更
					//
					*lp=inputNumberWithShinsu(&p0);
					DBG_printf1("新inp=%d\n",(int)*lp);
					}
					break;
				
				case MATH_CHAR:	// Inp_char: 2665
					{
					DBG_printsn("MATH_CHAR");
					var_ctrl_exec=getVarCtrlExecWithVarNo(VAR_CHAR,&no);
					UByte *bp=(UByte *)var_ctrl_exec->varArea;
					bp=&bp[no];
					DBG_printf1(*bp<' '? "元inp=$%02x\n":"元inp=%c\n",*bp);
					if (*p0==EOS)	continue; // 入力がない時は変数内容無変更
					//
					*bp=(UByte)inputNumberWithShinsu(&p0);
					DBG_printf1(*bp<' '? "新inp=$%02x\n":"新inp=%c\n",*bp);
					}
					break;
				
				case MATH_FLOAT:	// Inp_float 2684
					{
					DBG_printsn("MATH_FLOAT");
					var_ctrl_exec=getVarCtrlExecWithVarNo(VAR_FLOAT,&no);
					DOUBLE_LONG *dp=(DOUBLE_LONG *)var_ctrl_exec->varArea;
					dp=&dp[no];
					DBG_printf1("元inp=%f\n",dp->d);
					if (*p0==EOS) continue; // 入力がない時は変数内容無変更
					//
					DOUBLE_LONG dl;
					dl.d=atod3(p0,&p0,NULL);
					// ここでは入力エラーチェックしない（インタープリター側だから。正しくなければ正しくない値のまま先に進めば良い）
					*dp=dl;
					DBG_printf1("新inp=%f\n",dp->d);
					}
					break;
			}
			// 1回のループで1入力分が処理されるので、すべての文字が解析に使われたときは*p0==EOSのはずである
			if (*p0!=EOS) {
				Warn(WARN_INPUT_TYPE_ILLEGAL); // "入力型違い"
				msType=MATH_INT; // 全部再入力
				break;
			}
			DBG_printf3("tmp=%p/tmp2=%p/*p0=$%02x\n",tmp,tmp2,*p0);
			msType=readInternalCodeN();
		}
		DBG_printsn("解釈終了");
	} while (msType!=MATH_VOID); // 足りなかったら入力し直し
	internalCode.wp++;	// MATH_VOIDを読み飛ばす
	//
	return (STATE_OK);
}

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

// 文字列専用入力
// 1回1入力
// ただし、,"'も入力可能
STATE E_Linput(void)
{
	DBG_Func();

	UByte *p1=tmp;
#if DOS
	fputs((char *)internalCode.bp,stderr);
#else
	printus(internalCode.bp);
#endif
	//
	skipInputMessage(); // 中間コード内の入力タイトル文字列を飛ばす
	//
#if DOS
	// 入力
	scanf("%s",p1);
	// 完全未入力はここで処理すること
#else
	// iOS
	strcpy((char *)p1,(char *)input(UIKeyboardTypeDefault)); // linputは文字列入力しかないのでこのキーボードタイプで良い
	// input後には改行が必要
	printus(p1);
	prints("\n");
#endif
	DBG_printf1("input=%s<<\n",p1);

	// 2782
	swVarNO no=readInternalCode();
	VAR_CTRL_EXEC *var_ctrl_exec=getVarCtrlExecWithVarNo(VAR_STR,&no);
	UByte *bp=(UByte *)var_ctrl_exec->varArea;
	bp=&bp[no*operationStatus.sz_str];
	//
	while ((*bp++=*p1++)!=EOS); // 実内容転送
	return (STATE_OK);
}

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

static
void printInt(SLong num
#ifdef CORE_DEBUG
						,NSString *type
#endif
			  )
{
#ifdef ARM32
	#define LONG_FORMAT	"%c%ld "
#else	// 64bit
	#define LONG_FORMAT	"%c%d "
#endif
	char c=' '; // >=0のときは符号は表示しない
	if (num<0) {
		c='-';
		num=-num;
	}
	sprintf((char *)tmp,LONG_FORMAT,c,num);
#ifdef CORE_DEBUG
	nslog(@"%@:%s",type,tmp);
#endif
	printus(tmp);
}

STATE E_Print(void)
{	// 2824
	printFunc();
	while (1) { // Print:
		operationStatus.fdimSizeVar=NO; // 配列要素数指定に変数はないにしておく
		// 2827
		uwCODE prcode;
		DBG_printsn("\n--------------------");
		prcode=readInternalCode();
		DBG_printf1("print用中間コード=$%04x\n",prcode);
		if (!(prcode&_PARAM)) {
			// print_ctrl 2955
			switch (prcode) { // using用中間コード
				case CrLfEnd: // crlf_end:
					prints("\n");
					DBG_printsn("改行終了");
					return(STATE_OK);
				
				case NoCrLfEnd: // print_end:
					DBG_printsn("非改行終了");
					return(STATE_OK);

				case TabJump: // tab:
					prints("\t");
					break;

				case UsingNum: // using_num: 2983
					{ // 変数宣言用
					nslog(@"UsingNum");
					DOUBLE_LONG dl1=getValue(T_FLOAT);	// 前半処理用
					//
					SWord seisuu 	=readInternalCode(); // 整数桁
					SWord shousuu	=readInternalCode(); // 小数桁
					UWord formatFlag=readInternalCode(); // フォーマット指定
					//
					// 表示数字の作成
					makeFloatString(dl1.d,seisuu,shousuu,tmp2,tmp,formatFlag);
					nslog(@"フォーマット文字列(途中):%s\n",tmp);
					
					if (formatFlag&USING_COMMA) {
						nslog(@"整数部分を3桁ごとに,で区切る");
						// 整数部分を３桁ごとに","で区切る
						
						// (1)先頭から文字を調べ、数字以外が出てくる部分の直前を得る
						UByte c,*p=tmp,*pp=tmp2;
						UByte *ps,*pf=(UByte *)"";
						ps=p; // 警告回避のため
						int f=NO,cnt=0;
						do {
							c=*p;
							if (isdigit(c)) { // 数字
								if (!f) ps=p; // 数字開始位置（必ず来る）
								f=YES;
								cnt++; // 整数部桁数
							} else { // 非数字
								if (f) {
									// 数字の後（来ない場合もある）
									pf=p; // 位置を記録
									break; // ループ終了
								} else { // 数字の前なら転送
									*pp++=c;
								}
							}
							p++;
						} while (c!=EOS);
						// pp=tmp2〜に数字前の文字群が転送されている
						nslog(@"数字開始位置ps=%s,pf=%s,整数部桁数cnt=%d\n",ps,pf,cnt);
						
						// f=NOのままここに来ることはない（はず）
						// 数字部分を3桁毎に,で区切っていく
						// 上位から処理する場合、最初はcnt%3で以降3毎となる
						// ただし、cnt%3==0のときは最初には入れない
						if (cnt>3) { // 入れるのは3桁より多い時
							int top=cnt%3;
							nslog(@"top=%d\n",top);
							if (top!=0) { // 最初の余り桁分
								#ifdef CORE_DEBUG
								int i=top;
								#endif
								cnt-=top;
								while (top-->0) *pp++=*ps++;
								*pp++=',';
								DBG_printName(tmp2,i+1); // ,も含む
							}
							while (cnt>0) {
								// 3桁転送
								*pp++=*ps++;
								*pp++=*ps++;
								*pp++=*ps++;
								cnt-=3;
								if (cnt>0) *pp++=',';
							}
//							*pp=0; // EOS(V2.5で修正);↓をstrcat()にするならこれが必要になる
							strcpy((char *)pp,(char *)pf); // 残り部分を結合する（残りは実体がない場合もある）;v2.5で修正strcatではない
							// 表示
							prints((char *)tmp2);
						} else {
							// 数字が3桁以下の時は処理なしで即表示(V2.5で修正)
							nslog(@"3桁以下");
							prints((char *)tmp);
						}
					} else { // ,による区切りなし
						nslog(@",による区切りなし表示");
						// 表示
						prints((char *)tmp);
					}
					} // 変数宣言用
					break;
				
				case UsingStr: // using_str: 2966
					{
					DBG_printsn("UsingStr");
					DOUBLE_LONG dl=getValue(T_STR);
					UByte *bp=dl.bp[LL];
					swStrLEN len=readInternalCode(); // 文字列長
					DBG_printf2("文字列=%p:長さ指定=%d:",bp,len);
					DBG_printName(bp,len);
					UByte *bp2=tmp;
					while (1) { // 文字コード変換をしながら格納する
						ULong c=getSjisOrUtf8(&bp,fsjisInRun);
						if (fsjisInRun) {
							// SJIS → UTF8変換して格納
							c=sjisToUtf8(c);
						}
						bp2=storeUtf8(bp2,c);
						if (c==EOS) break;
						if (--len==0) break;
					}
					if (len>0) {
						bp2--; // EOSを消す
						// 指定文字列長に足りない時は、後ろにスペースを表示して合わせる
						while (len-->0) {
							*bp2++=' '; // UTF8/SJIS/ASCでスペースは同じ
						}
					}
					*bp2=EOS;
					//
					// printf()を使わないのは、文字列中に'%'が入っていたときに異常表示するから
					printus(tmp);
					}
					break;
			} // switch (prcode)
		} else {
			// 2829
			uwTYPE type=_getType(prcode);
			nslog(@"フォーマット指定なし表示:type=%d",type);
			DOUBLE_LONG dl=getValue(type);
			// 数値は後に空白を入れるのが仕様
			// 前は符号分で+の場合は空白になる(%の後の空白はその指定)

			// usingでのSLongのsprintf()での表示フォーマット
			switch (type) { // 型別
				case T_FLOAT:	// float_print:
					{
					nslog(@"T_FLOAT:%f\n",dl.d);
					int len=makeNormalFloatString(tmp,dl.d);
					tmp[len++]=' '; // 後ろスペース
					tmp[len]=EOS;
					}
#ifdef CORE_DEBUG
					nslog(@"%s",tmp);
#endif
					printus(tmp);
					break;
				case T_CHAR:	// char_print:
					printInt((SLong)((UByte)dl.l[LL])
#ifdef CORE_DEBUG
													,@"T_CHAR"
#endif
					 );
					break;
				case T_INT:		// int_print:
					printInt((SLong)(dl.l[LL])
#ifdef CORE_DEBUG
							 ,@"T_INT"
#endif
							 );
					break;
				
				case T_STR:
					// printf()を使わないのは、文字列中に'%'が入っていたときに異常表示するから
					if (fsjisInRun) { // SHIFT-JIS
						sjisToUtf8S(tmp,dl.bp[LL]); // → UTF8変換
#ifdef CORE_DEBUG
						nslog(@"T_STR(SJIS):%s",tmp);
#endif
						printus(tmp);
					//	printWithCtrlCode(tmp);
					} else { // UTF8/ASCII
#ifdef CORE_DEBUG
						nslog(@"T_STR(UTF):%s",dl.cp[LL]);
#endif
						prints(dl.cp[LL]);
					//	printWithCtrlCode(dl.bp[LL]);
					}
					break;
			} // switch (type)
#ifdef CORE_DEBUG
			printf("\n");
#endif
		} // if
	} // while
	return (STATE_OK);
}

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

STATE E_End(void)
{
	DBG_Func();
	exitCode=0;
	return (STATE_END);
}

STATE E_Exit(void)
{
	DBG_Func();
	exitCode=(UWord)intGetValue();
	return (STATE_END);
}

STATE E_Stop(void)
{
	// contによる再開はできない;今はその機能自体がないけど
	DBG_Func();
	exitCode=1;
	return (STATE_STOP);
}

//--------------------------------------------------------------------------------------
// 関数処理
//--------------------------------------------------------------------------------------

// 関数呼び出し
STATE E_FunctionCall(void)
{
	DBG_Func();	// 関数呼び出し
	functionCall(T_INT);
	return (operationStatus.fend);
}

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

// func=内部関数に対するreturn
// xbasicMain()からリターンさせる
STATE E_Return(void)
{
	DBG_Func();
	uwCODE code=readInternalCode();
	uwTYPE type=_getType(code);
	DOUBLE_LONG dl=getValue(type);
	retFromFunctions.dl=dl; // リターン値代入
	return (STATE_RETURN); // xbasicMain()終了してリターン
}

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

// リターン値のないreturn相当
// xbasicMain()からリターンさせる
STATE E_Endfunc(void)
{
	DBG_Func();
	// ここに来るときはリターン値はなしだけど念のため
	retFromFunctions.dl.l[HL]=0;
	retFromFunctions.dl.l[LL]=0;
	return (STATE_RETURN); // xbasicMain()終了してリターン
}

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

// 関数呼び出し
// type = 型
DOUBLE_LONG functionCall(uwTYPE type)
{
	DBG_Func();
	fnslog2((char *)__FUNCTION__);
	// 3148
	FAC fac[MAX_PARAM];	// 面倒なので、常にMAX_PARAM分確保する
	UWord numFAC=readInternalCode(); // 引数の個数
	nslog(@"関数呼び出し:引数個数=%d\n",numFAC);
	if (numFAC>MAX_PARAM) { // 念のため
		IError(ERR_ILLEGAL_PARAM_IN_EXTERNAL_FUNCTION);
	}
	//
	DBG_printsn("引数解釈");
	uwCODE code;
	SLong num;
	DOUBLE_LONG dl;
	int i=0;
	UWord numFAC1=numFAC;
	while (numFAC1-->0) { // 引数がある時
		nslog(@">>引数 fac[%d](%p)\n",i,&fac[i]);
		// 引数をFACに設定する
		// fnc_call_loop: 3162
		code=readInternalCode();	// 3163
		fac[i].dl.l[HL]=0;
		if (_isDainyu(code)) {	// 3164
			// 引数は式 3256
			DBG_prints("引数は式の");
			switch (_getType(code)) {
				case T_INT:		// intP		3284
					fnslog("int");
					fac[i].facType=INT_PARAM;
					num=intGetValue();
					fac[i].dl.l[LL]=num;
					break;
				case T_CHAR:	// charP	3273
					fnslog("char");
					fac[i].facType=CHAR_PARAM;
					num=intGetValue();
					fac[i].dl.l[LL]=(UByte)num;
					break;
				case T_FLOAT:	// floatP	3276
					fnslog("float");
					dl=getValue(T_FLOAT);
					fac[i].facType=FLOAT_PARAM;
					fac[i].dl=dl;
					break;
				case T_STR:		// strP:	3262
					//nslog(@"外部関数へ渡す文字列:code=$%x",code);
					fnslog("str");
					dl=getValue(T_STR);
					fac[i].facType=STR_PARAM;
					fac[i].dl=dl;
					break;
			}
		} else {
			if (code&CODE_ATRB_VARIABLE) { // 3165
				// 引数は配列かポインター 3179
				fnslog("引数は配列かポインター");
				VAR_CTRL_EXEC *var_ctrl_exec;
				SWord sz1;
				SLong no=(ULong)readInternalCode();
				if (code&CODE_ATRB_POINTER) { // 3180
					//	引数はポインタ 3200
					VAR_TYPES typeNo=type2VarTypes(_getType(code));
					nslog(@"引数はポインター:番号=%d/型=$%04x\n",(int)no,typeNo);
					if (typeNo==VAR_VOID) {
						// 引数は省略 3172
						IError(ERR_PARAM_ILLEGAL_IN_FUNCTION);
					}
					var_ctrl_exec=getVarCtrlExec(typeNo, code);
					sz1=Var1Size[typeNo]; // 1要素サイズ
					UByte *varAdrs=var_ctrl_exec->varArea;
					// 3246
					fac[i].facType=POINTER_PARAM;
					fac[i].dl.bp[LL]=&varAdrs[no*sz1];
				} else {
					// 3183
					nslog(@"引数は配列:番号=%d\n",(int)no);
					var_ctrl_exec=getVarCtrlExec(VAR_DIM, code);
					DIM1_EXEC **dim1_exec_adrs=(DIM1_EXEC **)var_ctrl_exec->varArea;
					fac[i].facType=POINTER_PARAM;
					fac[i].dl.bp[LL]=(UByte *)dim1_exec_adrs[no]; // 配列の実体(=DIM1_EXEC)のアドレスを渡す
				}
			} else {
				nslog(@"引数はなし");
				// 3167
				if (code!=CODE_ATRB_NONE) {
					IError(ERR_PARAM_ILLEGAL_IN_FUNCTION);
				}
				// 引数は省略 3172
				fac[i].facType=VOID_PARAM;
				fac[i].dl.l[LL]=0;
			}
		}
		i++; // 次のFACへ
	} // while (numFAC1)
	//
	#ifdef CORE_DEBUG
//	#ifdef DEBUG
	// 引数リスト表示
	nslog(@"渡す引数群");
	for (i=0;i<numFAC;i++) {
		nslog(@"%d.PARAM(%p)=$%04x:$%08x:%08x"
			  				,i
			  				,&fac[i]
							,(int)fac[i].facType
							,(int)fac[i].dl.l[HL]
							,(int)fac[i].dl.l[LL]
		);
	}
	#endif
	// fnc_call_loop_end 3297
	//
	swFuncNO fno=readInternalCode();	// 関数番号
	if (_isInternalFunc(fno)) {
		// 内部関数呼出 3333
		fno=_getFuncNo(fno);
		DBG_printf1("内部関数呼出:番号=%d\n",fno);
		
		// エラー位置を特定するため、呼び出し前にエラーチェックしなければならない
		extern int recursiveCnt; // xb.mにて定義
#ifdef PRT_STACKED
		nslog1(@"xbasicMain()前:cnt=%d+1",recursiveCnt);
#endif
		if (++recursiveCnt>=MAX_RECURSIVE) { // 再帰呼び出し段数によるエラー判定;++により1〜なので>=で判定する
			nslog1(@"再帰呼び出し段数オーバー");
			IError(ERR_RECURSIVE_CALL_OVER);
		}
		
		// 状態保存
		UByte *variableArea0=variableArea;		// 変数領域
		DBG_printf1("変数領域待避:%p\n",variableArea);
		REGISTER internalCode0=internalCode;	// 現在の実行アドレス；下で実行アドレスを変更する前に退避が必要
		DBG_printf1("実行アドレス退避:%p\n",internalCode.wp);
		OPERATION_STATUS pushOperationStatus=operationStatus;	// 動作状態
		
		// 関数実行アドレス=飛び先の中間コード位置
		internalCode.vp=(void **)(InternalFunctionBuffer[fno].exec.func);
		if (internalCode.vp==NULL) {
			// 内部関数のアドレスなし
			nslog(@"内部関数のアドレスなし");
			IError(ERR_SYSTEM);
		}
		//
		// 関数呼び出し(ローカルモード)	3348
		DOUBLE_LONG dl=xbasicMain(internalCode.wp,YES,numFAC,fac);
		// ここはmain.xbasicMain()→functionCall()[→xbasicMain()]→で帰ってきたところ
		//						  ~~~~~~~~~~~~~~いるのはこの中
		--recursiveCnt; // 再帰呼び出し段数
#ifdef PRT_STACKED
		nslog1(@"xbasicMain()後:cnt=%d",recursiveCnt);
#endif
		//
		nslog(@"内部関数.xbasicMainから返ってきた:fend=%d",operationStatus.fend);
		DBG_printf2("\n--------------------------------\n"
					"ローカル関数からの復帰\nリターン値:$%08x:%08x\n",(int)dl.l[HL],(int)dl.l[LL]);
		if (operationStatus.fend==STATE_OK) {
			// 状態復帰	3350
			nslog1(@"状態復帰");
			operationStatus=pushOperationStatus;	// 動作状態
			internalCode=internalCode0;				// 実行アドレス
			DBG_printf1("実行アドレス復帰:%p\n",internalCode.wp);
			variableArea=variableArea0;				// 変数領域
			DBG_printf1("変数領域復帰:%p\n",variableArea);
		} // STATE_OK以外で帰ってきたときは戻さない
#ifdef DEBUG
		else {
			//
			nslog1(@"operationStatus.fend!=STATE_OK:%d",operationStatus.fend);
		}
#endif
		//
		return (dl);
	} // if (内部関数)
	
	// 外部関数	3300
	DBG_printf3("外部関数呼び出し:%s(%d,%p)\n",FunctionBuffer[fno].token,numFAC,&fac[0]);
	nslog(@"外部関数呼び出し:%s(%d,%p)",FunctionBuffer[fno].token,numFAC,&fac[0]);
	//
	extraFunctionErrmes=NULL;					// 外部関数内エラーメッセージをクリア(発生したら設定されてくる)
	RET_FUNC (*func)(SWord numFAC,FAC fac[]);	// これは変数宣言
	func=FunctionBuffer[fno].exec.func;			// 関数実行アドレス
	RET_FUNC ret=func(numFAC,fac);				// 関数呼び出し;レジスタは全て保存すること
	// X-BASICの規定に従ったチェック
	if (ret==RET_FUNC_OK) {
		if (fac[0].facType!=FACTYPE_RETURN) {
			// fac[0]の構造がリターン時のそれとして正しくない
			IError(ERR_PARAM_IN_EXTERNAL_FUNCTION);
		}
	} // エラーで返ってきているときにはこのチェックは不要。↓でエラーメッセージを表示するから。
	//
	errorNo=ret;
	nslog(@"errorNo=%d",errorNo);
	if (ret!=RET_FUNC_OK) {
		nslog(@"ret!=RET_FUNC_OK:%d/operationStatus.ferror=%d",ret,operationStatus.ferror);
		if (operationStatus.ferror!=ERR_OFF) {
			sprintf((char *)tmp,selectMessageJE("External function error:%s\n","外部関数エラー:%s\n"),extraFunctionErrmes); // %sがあるが、printus()内で@()されるので問題ない
			printus(tmp); // テキスト画面に出力する
			if (operationStatus.debugPrintFunc!=NULL) {
				// ダンプ画面にも出力する
				operationStatus.debugPrintFunc(@((char *)tmp));
			}
			IError(ERR_IN_EXTERNAL_FUNCTION);
		} else {
			nslog(@"error offのときは、エラーを無視して次の行へ");
		}
		if (numFAC==0) {
			// 引数がないときはFACもないので、仮のFACを作りそれを返す
			static FAC void_error_fac;
			void_error_fac.facType=FACTYPE_RETURN;
			void_error_fac.dl.sl[HL]=-1;
			void_error_fac.dl.sl[LL]=-1;
			return (void_error_fac.dl);
		} // FACがあるときはそのまま返す
	}
//	nslog(@"functionCall:ret=%f/%d",fac[0].dl.d,(int)fac[0].dl.l[LL]);
	return (fac[0].dl); // 外部関数からのリターン値はここに格納されている
}

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

typedef struct {
	STATE (*exec)(void);
} STATEMENT_TABLE_EXEC;

// 中間コード別処理アドレス表
static 	STATEMENT_TABLE_EXEC statTable[]={
// xbstat.mのS_*とほぼ同じだが、一部実行時に中間コードの意味の差し替えがある
// CODE_*順
	{E_FunctionCall},	// 0
	{E_Print},
	{E_Break},
	{E_Case},
	{E_Continue},
	{E_Default},
	{E_Endfunc},
	{E_Switch2},	// <<差し替え
	{E_Error},
	{E_Return},
	{E_Switch},		// 10
	{E_End},
	{E_Endwhile},
	{E_Exit},
	{E_For},
	{E_Gosub},
	{E_Goto},
	{E_If},			// 17
	{E_Input},
	{E_Linput},
	{E_Next},		// 20
	{E_Next2},		// <<差し替え
	{E_Stop},
	{E_Until},
	{E_While},		// 24=$18
	{E_Dim},
	{E_Str},
	{E_Func},
	{E_Else},
	{E_SysVar},
	{E_Ifeq},		// 30
	{E_Ifne},
	{E_Iflt},
	{E_Ifgt},
	{E_Ifle},
	{E_Ifge},
};

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

// デバッグ画面への情報出力
void debugOperation(int enableBit,NSString *atMes,NSString *lineMes,NSString *lineMesInStartup)
{
	printFunc();
	nslog(@"lineMes=%@/enableBit=$%x/operationStatus.debugMode=$%x",lineMes,enableBit,operationStatus.debugMode);
	
	if (operationStatus.debugMode&enableBit) {
		nslog(@"ダンプ出力対象:operationStatus.dumpCnt=%d",operationStatus.dumpCnt);
		if (operationStatus.dumpCnt==0) {
			// 行番号を表示する
			// break中間コード実行前に検出されるので-1不要
			// stopは・・・これで良い
			uwLineNO lno;
			pinpointExecuteLine(internalCode.wp,&lno);	// 中間コードアドレスから行を特定する;0〜
			NSString *mes;
			if (lno<startupLines) {
				nslog(@"startup内");
				mes=[NSString stringWithFormat:NSLocalStr(lineMesInStartup),lno];
			} else {
				nslog(@"ユーザーソース内");
				lno-=startupLines;
				mes=[NSString stringWithFormat:NSLocalStr(lineMes),lno+1];
			}
			nslog(@"mes=%@/operationStatus.debugPrintFunc=%p",mes,operationStatus.debugPrintFunc);
			if (operationStatus.debugPrintFunc!=NULL) {
				operationStatus.debugPrintFunc(mes);
			}
			// ダンプ
			varDump2(operationStatus.debugDumpMode,NSLocalStr(atMes),operationStatus.debugPrintFunc);
			// 出力回数
			operationStatus.dumpCnt++;
		}
	}
}

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

// 内部関数またはグローバル処理の実行
// 入出力は外部関数実行とほぼ同じにする
// internalCode0の初期値の保存は、必要なら呼び出し側でしておくこと
DOUBLE_LONG xbasicMain(uwCODE *internalCode0,int flocal0,SWord numFAC,FAC *fac)
{
	DBG_Func();
	nslog1(@"%s:flocal=%d",__FUNCTION__,flocal0);
	
	operationStatus.flocal=flocal0;
	//
	VAR_CTRL_EXEC _localVarCtrlExec[MAX_VAR_TYPES]; 	// 実行時ローカル用変数管理構造体
	VAR_CTRL_EXEC *localVarCtrlExec0=localVarCtrlExec; 	// 現在のlocalVarCtrlExecを保存
	localVarCtrlExec=_localVarCtrlExec; 				// ローカル変数用VAR_CTRLをBASIC内部でグローバルにアクセスするため
	
	// 変数領域を確保する
	INTERNAL_CODE_INFO *internalCodesInfo=(INTERNAL_CODE_INFO *)internalCode0;	// 読み替えのため
	
	// 今回使う変数リスト位置から情報を読み出す
	// バッファー内のVARLIST_CHAINは境界整合できてない可能性があるので、一旦変数にコピー(64bit対応)・・・したいが、ここは可変サイズなので出来ない。
	// 故にアドレスを直接返す。アドレスによっては落ちるかも。
//	VARLIST_CHAIN varList;
//	getValueFromBufferByCopy(&variableBuffCtrl,internalCodesInfo->varChainListNo,&varList,sizeof(varList));

	VARLIST_CHAIN *varList=getValueAdrs(&variableBuffCtrl,internalCodesInfo->varChainListNo);
	DBG_printf1("varList=%p",varList);
	DBG_printf1(";sizeVarArea=%d\n",(int)varList->sizeVarArea);
//	printf("variableBuffCtrl内ダンプ\n");
//	dumpBuffer(&variableBuffCtrl, YES);
	
	getVariableArea(varList->sizeVarArea);	// 必要サイズ分確保要求(ワークエリアの確保はここで行われる);拡張配列の分は含まない(というか容量が未確定なので確保できない)
	
	// このブロックで使う変数領域先頭アドレスをオフセットで保存しておく
	// オフセットにするのは、以下の処理内で再びgetVariableArea()が呼び出されてrealloc()で実アドレスが移動するかもしれないから
	psize_t offset=calcAdrsOffset(variableArea,variableAreaTop);
#ifdef CORE_DEBUG2
	DBG_printf("variableArea=%p,variableAreaTop=%p,offset=%zu\n",variableArea,variableAreaTop,offset);
	//
	VAR_CTRL_EXEC *globalVarCtrlExec=(VAR_CTRL_EXEC *)globalVarCtrl;
	DBG_printf("globalVarCtr     =%p,globalVarCtrlExec=%p\n",&    globalVarCtrl[0],&globalVarCtrlExec[0]);
	DBG_printf("_localVarCtrlExec=%p, localVarCtrlExec=%p\n",&_localVarCtrlExec[0],& localVarCtrlExec[0]);
	//
	VAR_TYPES typeNo;
	for (typeNo=VAR_INT;typeNo<=VAR_FLOAT;typeNo++) {
		DBG_printf("globalVarCtr[%d]=%p/%p\n",typeNo,&globalVarCtrl[typeNo]    ,&globalVarCtrlExec[typeNo]);
	}
	for (typeNo=VAR_INT;typeNo<=VAR_FLOAT;typeNo++) {
		DBG_printf( "localVarCtr[%d]=%p/%p\n",typeNo,&_localVarCtrlExec[typeNo],& localVarCtrlExec[typeNo]);
	}
#endif
#ifdef CORE_DEBUG
	// 引数リスト表示
	DBG_printf("引数数:%d\n",numFAC);
	for (int i=0;i<numFAC;i++) {
		DBG_printf("引数%d:型(*_PARAM)=$%04x:$%08x:%08x\n",i,fac[i].facType,(int)fac[i].dl.l[HL],(int)fac[i].dl.l[LL]);
	}
#endif
	//
	// 変数領域確定 & 引数セット(初期化)
#ifdef CORE_DEBUG
	UByte *bp;
#endif
	if (operationStatus.flocal) {
		// ローカル時
		nslog(@"ローカル:%p",localVarCtrlExec);
		#ifdef CORE_DEBUG
		bp=
		#endif
		variableInit(variableArea,varList,internalCodesInfo,localVarCtrlExec	,numFAC,fac);
	} else {
		// グローバル時;現在はb_argv[]をサポートしてないのでないはずだけど念のため
		nslog(@"グローバル:%p",globalVarCtrl);
		VAR_CTRL_EXEC	*globalVarCtrlExec=(VAR_CTRL_EXEC *)globalVarCtrl;
		#ifdef CORE_DEBUG
		bp=
		#endif
		variableInit(variableArea,varList,internalCodesInfo,globalVarCtrlExec	,numFAC,fac);
	}
	variableArea+=varList->sizeVarArea;	// 次の確保エリアへ(ここから先に拡張配列分または次ブロック分の確保が行われる)
#ifdef CORE_DEBUG
	nslog(@"実確保上の次アドレス=%p",bp);
	nslog(@"計算上　の次アドレス=%p",variableArea);
	if (bp!=variableArea) {
		nslog(@"プログラム異常終了");
		exit(100); // 不一致ならおかしいので止める
	}
#endif
	
	internalCode.wp=internalCodesInfo->codes;	// 実中間コード格納領域へ
	//
	DBG_Func2(";メインループ");
	STATE ret;
	DOUBLE_LONG dl;
	dl.l[HL]=0;
	#ifdef CORE_DEBUG
	int	codesNo=0;
	#endif
	while (1) {
		if (checkBreak()==STATE_BREAK) {
			nslog(@"Break:%s",__FUNCTION__);
			ret=STATE_BREAK;
			//longjmp(jmpEnv,JMP_BREAK);
			break;
		}
		DBG_printf1("\n--読み出しループ(%d)--\n",codesNo++);
		fnslog("read loop");
		//
		strbuf=strAddWork;	// ブロックに入るごとに文字列定数用ワークは先頭から使う
		// 109
		uwCODE code=readInternalCode();	// 中間コード読みだし	109
//		nslog(@"%p->$%04x",internalCode.wp-1,code);
		DBG_printCode(code);
		if (_isDainyu(code)) {
			fnslog("代入式だった");
			// 代入式だった 175
			uwTYPE type=_getType(code);	// 代入の場合；type = 代入先の型
			DBG_printf1("代入先型:$%04x\n",type);
			if (_isVariable(code)) {
				// 配列への代入 181
				//fnslog("配列への代入");
				nslog(@"配列への代入");
				dl=getValue(type); // 値を得る
				//
				swVarNO hno=readInternalCode(); // 配列番号
				nslog(@"配列への代入:配列番号=%d",hno);
				VAR_CTRL_EXEC *var_ctrl_exec=getVarCtrlExecWithVarNo(VAR_DIM,&hno);
				slAryNO thno; // 指定された要素番号を全次元での通し番号に直したものが返る
				UByte *bp=dimSetSub(&thno,hno,var_ctrl_exec);
				// 指定要素内容は((型*)リターン値)[thno]から読み出せばよい
				nslog(@"代入先:%p[%d]",bp,(int)thno);
				//
				switch (type) {
					case T_INT:		// int_setD: 215
						fnslog("T_INT");
						{
						SLong *lp=(SLong *)bp;
						lp+=thno;
						storeLong(lp,dl.l[LL]);	// *lp=dl.l[LL];
						DBG_printf1("%p\n",lp);
						}
						break;
					case T_FLOAT:	// float_setD: 206
//						fnslog("T_FLOAT");
						nslog(@"T_FLOAT");
						{
						DOUBLE_LONG *dp=(DOUBLE_LONG *)bp;
						dp+=thno;
						readDOUBLE_LONG(dp,&dl); // *dp=dl;
						DBG_printf1("%p\n",dp);
						}
						break;
					case T_STR:		// str_setD: 198
						fnslog("T_STR");
						bp+=thno*operationStatus.sz_str;
						strcpy((char *)bp,dl.cp[LL]);
						DBG_printf1("%p\n",bp);
						break;
					case T_CHAR:	// char_setD: 194
						fnslog("T_CHAR");
						bp[thno]=(UByte)dl.l[LL];
						DBG_printf1("%p\n",&bp[thno]);
						break;
				}
			} else {
				// 普通変数への代入 228
				fnslog("普通変数への代入");
				dl=getValue(type);	// 値を得る
				swVarNO no=readInternalCode();	// 代入先の変数番号
				DBG_printf1("代入先変数番号=%d\n",no);
				VAR_CTRL_EXEC *var_ctrl_exec;
				switch (type) { // 代入先の型
					case T_INT:
						fnslog("T_INT");
						{
						var_ctrl_exec=getVarCtrlExecWithVarNo(VAR_INT,&no);
						SLong *lp=var_ctrl_exec->varArea;
						storeLong(&lp[no], dl.l[LL]); // lp[no]=dl.l[LL]
						}
						break;
					case T_FLOAT:
						fnslog("T_FLOAT");
						{
						var_ctrl_exec=getVarCtrlExecWithVarNo(VAR_FLOAT,&no);
						DOUBLE_LONG *dp=(DOUBLE_LONG *)var_ctrl_exec->varArea;
						readDOUBLE_LONG(&dp[no], &dl); // dp[no]=dl;
						}
						break;
					case T_STR:
						fnslog("T_STR");
						{
						var_ctrl_exec=getVarCtrlExecWithVarNo(VAR_STR,&no);
						UByte *bp=var_ctrl_exec->varArea;
						bp+=(no*operationStatus.sz_str);
						strcpy((char *)bp,dl.cp[LL]);
						}
						break;
					case T_CHAR:
						fnslog("T_CHAR");
						{
						var_ctrl_exec=getVarCtrlExecWithVarNo(VAR_CHAR,&no);
						UByte *bp=var_ctrl_exec->varArea;
						bp[no]=(UByte)dl.l[LL];
						}
						break;
				}
			}
		} else { // 112
			if (code==CODE_FUNC) {
				// 関数呼び出し
				fnslog("関数呼び出し");
				nslog1(@"関数呼び出し");
				ret=E_FunctionCall();
				nslog1(@"関数呼び出し後:ret=%d",ret);
			} else {
				// 構文だった 112
				fnslog("構文だった");
				@autoreleasepool {
					ret=statTable[code].exec();
				}
			}
			// 関数のリターン値による判定
			if (ret!=STATE_OK) {
				nslog1(@"停止系:%d",ret);
				// return(1)/error(2)/end(-1)/stop(-2)が呼び出された,Breakが押された
				break;
			}
		}
	} // while (checkBreak)
	nslog(@"ブロック終了処理:ret=%d",ret);
	fnslog2("ブロック終了");
	//
	retFromFunctions.facType=FACTYPE_RETURN; // ここで入れるので、個別の処理では代入不要
	
	// 以下の処理の中で、retrurn以外のダンプは1回しか行わない
	// なぜなら、return以外はその場でプログラムを終了するものであるが、
	// 発生した最初でのみその時点のローカル変数が有効である。
	// return以外は以降の実行を止めて一番上まで戻るが、その間もここを通るが、その時はダンプしてはいけない。
	switch ((int)ret) { // enumの警告を回避するため
		case STATE_BREAK:
			// breakが押された
			nslog1(@"%s.STATE_BREAK",__FUNCTION__);
			operationStatus.fend=STATE_BREAK;
			externalFunctionsRoutine(noFbreak); // Break時処理を実行
			debugOperation(DEBUG_MODE_BREAK,@"AT_BREAK",@"BREAK_LINE",@"BREAK_LINE_IN_STARTUP");
			break;
		case STATE_STOP:
			// stopが実行された
			nslog1(@"%s.STATE_STOP",__FUNCTION__);
			operationStatus.fend=STATE_STOP;
			debugOperation(DEBUG_MODE_STOP,@"AT_STOP",@"STOP_LINE",@"STOP_LINE_IN_STARTUP");
			break;
		case STATE_END:
			// Endが実行された
			nslog1(@"%s.STATE_END",__FUNCTION__);
			operationStatus.fend=STATE_END;
			if (operationStatus.debugMode&DEBUG_MODE_END) {
				if (operationStatus.dumpCnt==0) {
					varDump2(operationStatus.debugDumpMode,NSLocalStr(@"AT_END"),operationStatus.debugPrintFunc);
					operationStatus.dumpCnt++;
					// endはプログラム中基本的には1つだけだから停止位置を表示しない
				}
			}
			break;
		case STATE_ERROR:
			// エラーが発生している
			// エラー処理は別途なされているのでここには来ない
#if 0
			nslog1(@"%s.STATE_ERROR",__FUNCTION__);
			operationStatus.fend=STATE_ERROR;
			if (operationStatus.debugMode&DEBUG_MODE_ERROR) {
				if (operationStatus.dumpCnt==0) {
					varDump2(operationStatus.debugDumpMode,NSLocalStr(@"AT_ERROR"),operationStatus.debugPrintFunc);
					operationStatus.dumpCnt++;
				}
			}
#endif
			break;
		case STATE_RETURN:
			// XB.mからの呼び出し時はここには来ない
			// return/endfuncが実行された
			// retFromFunctionsはそれらの処理の中で格納されている
			//nslog(@"%s.STATE_RETURN",__FUNCTION__);
			if (operationStatus.debugMode&DEBUG_MODE_RETURN) {
				varDump2(operationStatus.debugDumpMode,NSLocalStr(@"AT_RETURN"),operationStatus.debugPrintFunc);
			}
			break;
	}
	// このブロックで使った変数領域を解放(相当)；ただし、realloc()で拡大した分はそのまま
	variableArea=variableAreaTop+offset;
	DBG_printf3("variableArea:%p=variableAreaTop:%p+offset:%zu\n",variableArea,variableAreaTop,offset);
	strbuf=strAddWork;	// 一応戻しておく
	//
	localVarCtrlExec=localVarCtrlExec0; // localVarCtrlExecを復帰

	DBG_Func2("(end)");
	if (operationStatus.fend==STATE_BREAK) {
		nslog1(@"longjmp");
		longjmp(jmpEnv,JMP_BREAK);
	}
	return (retFromFunctions.dl);
}

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

// debugPrintFunc()は出力関数
void varDumpSub(int dumpMode,VAR_CTRL_EXEC *varCtrlExec,BOOL fglobal,void (*debugPrintFunc)(NSString *text))
{
	printFunc();
	nslog1(@"実行時変数ダンプ:varCtrlExec=%p:fglobal=%d",varCtrlExec,fglobal);

	if (debugPrintFunc==NULL) return; // 出力関数の指定がないときは処理しない
	
	int    *ip;
	UByte  *bp;
	double *dp;
	int cnt;
	
	// 変数タイプ別
	VAR_TYPES typeNo;
	for (typeNo=VAR_INT;typeNo<=VAR_FLOAT;typeNo++) {
		
		cnt=varCtrlExec[typeNo].cnt;
		nslog1(@"%s変数:%d個",name_type[typeNo].name,cnt);
		if (cnt<=0) continue; // １つもないので飛ばす;<0は念のため
		
		// 表示限定
		switch (typeNo) {
			default: // コンパイラの警告回避のため
			case VAR_INT: // int
				if (!(dumpMode&DUMP_VAR_INT)) continue;
				break;
			case VAR_STR: // str
				if (!(dumpMode&DUMP_VAR_STR)) continue;
				break;
			case VAR_CHAR: // char
				if (!(dumpMode&DUMP_VAR_CHAR)) continue;
				break;
			case VAR_FLOAT: // float
				if (!(dumpMode&DUMP_VAR_FLOAT)) continue;
				break;
		}

//		fprintf(stdout,nsStringTocString(NSLocalStr(@"MES_VARDUMP_VAR_CNT")),name_type[typeNo].name,cnt); // "%s変数:%d個\n"
		debugPrintFunc([NSString stringWithFormat:NSLocalStr(@"MES_VARDUMP_VAR_CNT"),name_type[typeNo].name,cnt]);	// name_typeは英字のみなので%sで良い

		VARIABLE1 *var1Array=varCtrlExec[typeNo].var1Top; // ローカルでは使えない
		if (fglobal) {
			nslog1(@"var1Array=%p",var1Array);
		}
		void *varArea=varCtrlExec[typeNo].varArea;
		nslog1(@"varArea=%p",varArea);
		
		ip=(int    *)varArea;
		bp=(UByte  *)varArea;
		dp=(double *)varArea;
		for (int i=0;i<cnt;i++) {
			if (fglobal) {
//				fprintf(stdout,"%s=",var1Array[i].token);
				debugPrintFunc([NSString stringWithFormat:@"%s=",var1Array[i].token]); // 変数名は英数字のみなので%sで良い
			}
			switch (typeNo) {
				default: // コンパイラの警告回避のため
				case VAR_INT: // int
//					fprintf(stdout,"%d",*ip++);
					debugPrintFunc([NSString stringWithFormat:@"%d",*ip++]);
					break;
				case VAR_STR: // str
				{
					char *cp=(char *)bp;
//					fprintf(stdout,"\x22%@\x22",@(cb));
					debugPrintFunc([NSString stringWithFormat:@"\x22%@\x22",@(cp)]);
				}
					bp+=operationStatus.sz_str;
					break;
				case VAR_CHAR: // char
//					fprintf(stdout,"%d",*bp++);
					debugPrintFunc([NSString stringWithFormat:@"%d",*bp++]);
					break;
				case VAR_FLOAT: // float
				{
					double d;
#if AARM>=2
					d=readDoubleFromDoublePointer(dp);
#else
					d=*dp;
#endif
//					fprintf(stdout,"%f",d);
					debugPrintFunc([NSString stringWithFormat:@"%f",d]);
					dp++;
				}
					break;
			}
//			fprintf(stdout,"\n");
			debugPrintFunc([NSString stringWithFormat:@"\n"]);
		}
	}
	
	// 配列
	// ここではtypeNo=VAR_DIM
	cnt=varCtrlExec[typeNo].cnt;
	if (cnt>0) {
//		fprintf(stdout,nsStringTocString(NSLocalStr(@"MES_VARDUMP_DIMENSION_CNT")),cnt); // "配列:%d個\n"
		debugPrintFunc([NSString stringWithFormat:NSLocalStr(@"MES_VARDUMP_DIMENSION_CNT"),cnt]);

		void *vp=varCtrlExec[typeNo].var1Top; 	// 名称取得のため(グローバル時のみ有効)
		void *varArea=varCtrlExec[typeNo].varArea;	// 実行時配列本体
		DIM1_EXEC **dim1execArray=(DIM1_EXEC **)varArea;

		for (int i=0;i<cnt;i++) {
			VARIABLE1 *var1=(VARIABLE1 *)vp;
	//		nslog(@"hash=$%04x/len=%d/token=%s",var1->hash,var1->len,var1->token);
			vp+=sizeof(VARIABLE1);
			
	//		DIM1 *dim1=(DIM1 *)vp;
	//		nslog(@"+mstype=%d/jigen=%d",dim1->msType,dim1->jigen);
	//		for (int j=0;j<dim1->jigen;j++) {
	//			nslog(@"+-%d:%d",j+1,dim1->youso[j]);
	//		}
			vp+=sizeof(DIM1);

			// 拡張配列の場合、実行時にしか要素情報が決定されない可能性があるのでdim1execで取る
			
			DIM1_EXEC *dim1exec=dim1execArray[i];
			char *type;
			switch (dim1exec->size1) {
				case SZ_INT:
					if (!(dumpMode&DUMP_DIM_INT)) continue;
					type="int";
					break;
				case SZ_CHAR:
					if (!(dumpMode&DUMP_DIM_CHAR)) continue;
					type="char";
					break;
				case SZ_FLOAT:
					if (!(dumpMode&DUMP_DIM_FLOAT)) continue;
					type="float";
					break;
				default: // SZ_str=operationStatus.sz_str
					if (!(dumpMode&DUMP_DIM_STR)) continue;
					type="str";
					break;
			}
			
//			fprintf(stdout,"(%d)dim %s ",i+1,type);
			debugPrintFunc([NSString stringWithFormat:@"(%d)dim %s ",i+1,type]); // typeは英字のみなので%sで良い
			if (fglobal) {
//				fprintf(stdout,"%s",var1->token);
				debugPrintFunc([NSString stringWithFormat:@"%s",var1->token]); // 変数名は英数字のみなので%sで良い
			}
//			fprintf(stdout,"(");
			debugPrintFunc([NSString stringWithFormat:@"("]);
			//
			swJigen jigen1=dim1exec->jigen1;
	//		nslog(@"jigen1=%d",jigen1);
			
			// 各次元の要素数を読み取る
			uwYouso yousos[MAX_DIM_JIGEN];
			for (int j=0;j<MAX_DIM_JIGEN;j++) yousos[j]=0;
			uwYouso *youso=dim1exec->youso;
			for (int j=0;j<jigen1+1;j++) {
				yousos[j]=*youso++; // この次元の要素数
//				fprintf(stdout,"%d%c",yousos[j]-1,j==jigen1+1-1? ')':',');
				debugPrintFunc([NSString stringWithFormat:@"%d%c",yousos[j]-1,j==jigen1+1-1? ')':',']);
			}
//			fprintf(stdout,nsStringTocString(NSLocalStr(@"MES_VARDUMP_DIMENSION")),jigen1+1); // " // %d次元\n"
			debugPrintFunc([NSString stringWithFormat:NSLocalStr(@"MES_VARDUMP_DIMENSION"),jigen1+1]);
			
			// 2次元以上の時はオフセットテーブルが存在する
			ULong *offset=(ULong *)youso;
			ULong offsets[MAX_DIM_JIGEN];
			for (int j=1;j<jigen1+1;j++) {
				offsets[j]=*offset++; // この次元の
				if (dumpMode&DUMP_OFFSET) {
//					fprintf(stdout,nsStringTocString(NSLocalStr(@"MES_VARDUMP_OFFSET")),j+1,(int)offsets[j]); // "--%d次元目：オフセット=%d\n"
					debugPrintFunc([NSString stringWithFormat:NSLocalStr(@"MES_VARDUMP_OFFSET"),j+1,(int)offsets[j]]);
				}
			}
			youso=(uwYouso *)offset;
			
			if (!(dumpMode&DUMP_DIM_WITH_ELEMENTS)) continue; // 要素はダンプしない時

			// 各要素		(1次元,2次元)				2次元
			// dim a(5,3)={	0, 1, 2, 3, 4, 5	0
			//			,	6, 7, 8, 9,10,11	1
			//			,  12,13,14,15,16,17	2
			//			,  18,19,20,21,22,23	3
			// 全要素は
			ip=(int    *)youso;
			bp=(UByte  *)youso;
			dp=(double *)youso;
			
			// プログラムの簡素化のため即値記述しているので注意
			// MAX_DIM_JIGEN=10
			int k[MAX_DIM_JIGEN];
			int add=(yousos[9]==0); // 0,1=要素数が0でも表示のためループを回すため
			for (k[9]=0;k[9]<yousos[9]+add;k[9]++) {
				add=(yousos[8]==0); // 0,1
				for (k[8]=0;k[8]<yousos[8]+add;k[8]++) {
					add=(yousos[7]==0); // 0,1
					for (k[7]=0;k[7]<yousos[7]+add;k[7]++) {
						add=(yousos[6]==0); // 0,1
						for (k[6]=0;k[6]<yousos[6]+add;k[6]++) {
							add=(yousos[5]==0); // 0,1
							for (k[5]=0;k[5]<yousos[5]+add;k[5]++) {
								add=(yousos[4]==0); // 0,1
								for (k[4]=0;k[4]<yousos[4]+add;k[4]++) {
									add=(yousos[4]==0); // 0,1
									for (k[3]=0;k[3]<yousos[3]+add;k[3]++) {
										add=(yousos[2]==0); // 0,1
										for (k[2]=0;k[2]<yousos[2]+add;k[2]++) {
											add=(yousos[1]==0); // 0,1
											for (k[1]=0;k[1]<yousos[1]+add;k[1]++) {
												if (jigen1>0) {
//													fprintf(stdout, "(x");
													debugPrintFunc([NSString stringWithFormat:@"(x"]);
													int m;
													for (m=1;m<=9;m++) {
														if (yousos[m]>0) {
//															fprintf(stdout,",%d",k[m]);
															debugPrintFunc([NSString stringWithFormat:@",%d",k[m]]);
														} else {
															m=9;
//															fprintf(stdout,")=");
															debugPrintFunc([NSString stringWithFormat:@")="]);
															break;
														}
														//
													}
													if (m>9) {
//														fprintf(stdout,")=");
														debugPrintFunc([NSString stringWithFormat:@")="]);
													}
												}
												// 1次元目は必ず存在する
												for (int l=0;l<yousos[0];l++) {
													switch (dim1exec->size1) {
														case SZ_INT:
//															fprintf(stdout,"%d",*ip++);
															debugPrintFunc([NSString stringWithFormat:@"%d",*ip++]);
															break;
														case SZ_CHAR:
//															fprintf(stdout,"%d",*bp++);
															debugPrintFunc([NSString stringWithFormat:@"%d",*bp++]);
															break;
														case SZ_FLOAT:
														{
															double d;
#if AARM>=2
															d=readDoubleFromDoublePointer(dp);
#else
															d=*dp;
#endif
//															fprintf(stdout,"%f",*dp++);
															debugPrintFunc([NSString stringWithFormat:@"%f",d]);
															dp++;
														}
															break;
														default: // SZ_str=operationStatus.sz_str
														{
															char *cp=(char *)bp;
//															fprintf(stdout,"\x22%@\x22",@(cb));
															debugPrintFunc([NSString stringWithFormat:@"\x22%@\x22",@(cp)]);
														}
															bp+=operationStatus.sz_str;
															break;
													}
//													fprintf(stdout,"%c",l==yousos[0]-1? '\n':',');
													debugPrintFunc([NSString stringWithFormat:@"%c",l==yousos[0]-1? '\n':',']);
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		} // for cnt
	} // if (cnt>0)
}

// 変数ダンプ関数(NSString *型)
void varDump2(int dumpMode,NSString *mes,void (*debugPrintFunc)(NSString *text))
{
	if (debugPrintFunc==NULL) return; // 出力関数の指定がないときは処理しない
	
	if (!(dumpMode&DUMP_ONLY_LOCAL)) {
		// グローバル
//		fprintf(stdout,"-----%s(%s)-----\n",mes,nsStringTocString(NSLocalStr(@"MES_VARDUMP_GLOBAL")));
		debugPrintFunc([NSString stringWithFormat:@"-----%@(%@)-----\n",mes,NSLocalStr(@"MES_VARDUMP_GLOBAL")]);
		varDumpSub(dumpMode,(VAR_CTRL_EXEC *)globalVarCtrl,YES,debugPrintFunc); // グローバルは実行時は読み替えだけ
	}
	
	if (operationStatus.flocal) { // ローカル中
		if (!(dumpMode&DUMP_ONLY_GLOBAL)) {
			// ローカル
	//		fprintf(stdout,"-----%s(%s)-----\n",mes,nsStringTocString(NSLocalStr(@"MES_VARDUMP_LOCAL")));
			debugPrintFunc([NSString stringWithFormat:@"-----%@(%@)-----\n",mes,NSLocalStr(@"MES_VARDUMP_LOCAL")]);
			varDumpSub(dumpMode,localVarCtrlExec,NO,debugPrintFunc); // ローカルは実行時は別領域
		}
	}
}

// 変数ダンプ関数(char *型)
void varDump(int dumpMode,char *cmes,void (*debugPrintFunc)(NSString *text))
{
	// mesは直接表示されるので、日本語対応できてない%sを使わないため
	varDump2(dumpMode,CstringToNSString(cmes),debugPrintFunc);
}

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