//--------------------------------------------------------------------------------------
//
// X-BASIC'
//	コンパイラ：式評価サブルーチンとか一部処理
//
//--------------------------------------------------------------------------------------

#include "fdef.h"
#include "XB.h"
#include <ctype.h>
#include "atod3.h"
#include "atoi3b.h"

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

// 変数番号のみ取り出す
// システム変数は渡さないこと
swVarNO getVarNo(swVarNO no)
{
	if (_isLocal(no)) {
		no=_getVarNo(no);
		// ローカル変数は<0にするため-1されているから
		return (no);
	}
	// グローバル変数
	return (no);
}

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

// 定義の型指定と、実際の型が一致するかどうか調べる
void checkParamType(uwPARAMTYPE prm,uwMATHTYPE msType)
{	// 引き数型check	2204
	if (prm&PARAM_FLOAT) {
		if (msType==MATH_FLOAT)	return;
	}
	if (prm&PARAM_INT) {
		if (msType==MATH_INT)	return;
	}
	if (prm&PARAM_CHAR) {
		if (msType==MATH_CHAR)	return;
	}
	if (prm&PARAM_STR) {
		if (msType==MATH_STR)	return;
	}
	// 一致しないならエラー
	Error(ERR_PARAM_ILLEGAL_IN_FUNCTION);
}

//-----------------------------------------------
// 値取得関数
//-----------------------------------------------

// intの定数を得る
SLong getIntConstant(void)
{	// int定数get()	546
	DBG_Func();
//	nslog(@"tmp=%p",tmp);
	UWord *wp=(UWord *)tmp; // 展開結果はtmpに入れる
	interpretMath(MATH_INT,&wp,NULL); // interpretMathの最適化を利用

	nslog(@"次の1文字:source=%c",*source);

	wp=(UWord *)tmp;
	if (*wp++!=(_CONSTANT|T_INT)) {
		nslog(@"intの定数ではない"); // enum内で整数演算子を2つ以上使った時にエラーが出るのはここ
		Error(ERR_SYNTAX_FORMULA);
	}
	return (*(SLong *)wp);
}

// floatの定数を得る
double getFloatConstant(void)
{
	DBG_Func();
//	nslog(@"tmp=%p",tmp);
	UWord *wp=(UWord *)tmp; // 展開結果はtmpに入れる
	interpretMath(MATH_FLOAT,&wp,NULL); // interpretMathの最適化を利用
	
	nslog(@"次の1文字:source=%c",*source);
	
	wp=(UWord *)tmp;
	if (*wp++!=(_CONSTANT|T_FLOAT)) {
		nslog(@"floatの定数ではない");
		Error(ERR_SYNTAX_FORMULA);
	}
#if AARM>=2
	return (readDouble(wp));
#else
	return (*(double *)wp);
#endif
}

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

// (source)～に '.'(小数点)/'#'/'e'/'E' があれば T_FLOAT、でなければ T_INTを返す
uwTYPE checkImmidiate(void)
{	// Imm判断	1836
	DBG_Func();
	DBG2_printName(source,10);
	UByte c;
	UByte *text=source;
	do {
		c=*text++;
		if (c==EOS) break; // intと判定
		switch (c) {
			case '.':
			case '#':
			case 'e':
			case 'E':
				DBG2_prints("float");
				return (T_FLOAT);
		}
	} while (isdigit(c)); // 数字が並んでいる間回る
	DBG2_prints("int");
	return (T_INT);
}

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

// 数値定数取得
// dlの境界整合に注意
SLong getNumConstant(uwTYPE type,DOUBLE_LONG *dl)
{	// 1784 定数get
	DBG_Func();
	if (type==T_FLOAT) {
		// floatの時
		DBG_printsn("float");
		BOOL ferr;
		DOUBLE_LONG dl1;
		dl1.d=atod3(source,&source,&ferr); // source=endアドレス
		if (ferr) {
			// 数値として異常
			nslog(@"数値として異常");
			Error(ERR_ILLEGAL_NUM);
		}
		*dl=dl1;
		return (dl1.l[LW]);  // 念のため
	}
	// 整数系の時
	SLong num;
	int base=10;
	if (*source=='&') {
		switch (*(source+1)) {
			case 'H':
			case 'h':
				// 16進数
				base=16;
				break;
			case 'B':
			case 'b':
				// 2進数
				base=2;
				break;
			case 'O':
			case 'o':
				// 8進数
				base=8;
				break;
			default:
				nslog(@"進数指定子がおかしい");
				Error(ERR_SYNTAX_FORMULA);
		}
	}
	if (base!=10) source+=2; // &?を飛ばす
	DBG_printf1("int:%d進数\n",base);
	num=atoi3b(source,base,&source);
	DBG2_printf1("*source=%c\n",*source);
	
	return (num);
}

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

// source="～"文字列をdesへコピーする
// リターン値:WORD単位文字列長
int sourceStringCopy(UByte *des)
{
	int len=0;
	UByte c;
	// 最初の'"'を飛ばしてから開始
	while (c=*++source,c!='"' && c!=EOS && c!=LF) {
		if (c==CR) {
			if (*(source+1)==LF) {
				// CR+LFならLFも飛ばす
				source++;
				break;
			}
		}
		//
		*des++=c;
		len++;
	}
	// 文字列終端処置
	// この位置でのsource=終端文字の位置
	if (c=='"') source++; // 文字列終端を飛ばす
	*des++=EOS;
	len++;
	if ((ULong)des&1) {
		// 偶数サイズ化
		*des++=0;
		len++;
	}
	// 返すのはWORD単位の文字列長
	return (withWord(len));
}

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

// systemVariable[]を構築する
void makeSystemVariableTable(void)
{	// 331	system変数table作成
	DBG_Func();
	uwMATHTYPE msType;
	swVarNO intNo=0,strNo=0; // 型別変数番号
	UByte *token;
	int i=0;
	while ((token=(UByte *)NameOfSystemVariable[i])!=NULL) {
		DBG2_printf2("token(%d)=%s\n",i,token);
		if (*token=='$') {
			msType=MATH_STR;
			token++; // 先頭の$は飛ばす
			// 実行時はstat情報がないため、変数番号そのものに細工する
			systemVariable[i].no=_setSystemVarStr(strNo++); // 型別変数番号
			DBG_printf2("str型:%d.%s\n",strNo,token);
		} else {
			msType=MATH_INT;
			// 実行時はstat情報がないため、変数番号そのものに細工する
			systemVariable[i].no=_setSystemVarInt(intNo++); // 型別変数番号
			DBG_printf2("int型:%d.%s\n",intNo,token);
		}
		systemVariable[i].msType =msType;	// 型
		systemVariable[i].token	 =token;	// 名前
		calcHash(token,&systemVariable[i].len,&systemVariable[i].hash,NULL); // hash値と長さ
		// ここはlen=0はあり得ない(あったらプログラムの記述ミス)
		i++;
	}
}

//--------------------------------------------------------------------------------------
// 演算子チェック
//--------------------------------------------------------------------------------------

// name と source からの文字列を比べる	500	one_check
// 一致
//		かつ、後ろが英数字$_以外	CMP_EQUAL
//		かつ、後ろが英数字$_
//				記号演算子		CMP_LARGE
//				非記号演算子		CMP_NOT_EQUAL
// 不一致							CMP_NOT_EQUAL
// fsourceSet : sourceは移動する
CMP_RESULT compareNameToSource(UByte *name,int fsourceSet)
{
	DBG2_Func();
	UByte c,c0;
	UByte *p=source;
	c0=*name; // 演算子の1文字目；これで記号型かどうかを区別する
	do {
		if ((c=*name++)==EOS) {
			// 文字列は一致した
			c=*p; // 直後の文字を見る
			DBG2_printf1("[end:%c]",c);
			if (c=='_' || c=='$' || isalnum(c)) {
				// 後ろは英数字または$_だった
				// 記号演算子　：演算子として一致
				// 非記号演算子：演算子として不一致
				if (c0>='a') {
					DBG_printsn("非記号型演算子：不一致");
					break;
				}
				DBG2_printsn("記号型演算子：一致");
				if (fsourceSet) source=p; // 直後の位置に合わせる;演算子の時は必ず後に何かしらの式が続くので必要
				return (CMP_LARGE);
			}
			// 後ろはそうではなかった＝条件クリア
			DBG2_printsn("CMP_EQUAL");
			source=p; // 直後の位置に合わせる
			DBG2_printf1("%s(end;一致)\n",__FUNCTION__);
			return(CMP_EQUAL);
		}
	} while (c==*p++);
	DBG2_printf1("%s(end;不一致)\n",__FUNCTION__);
	// 文字列が不一致だった
	return (CMP_NOT_EQUAL);
}

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

// 演算子チェック
// リターン値
//	演算子だったら		演算子番号＋優先順位(CODE_*>=0x0100)
//	違ったら			CODE_NONE(=0)
//	改行/プログラム	CODE_PROGRAMEND
uwCODE operatorCheck(void)
{	// 	391	cal_check
	DBG_Func(); // 演算子チェック
	// まず、空白を飛ばして、先頭の文字を見る。
	if (firstCheckSouceInLine()==EOL) {
		// 演算子があるべき部分で改行またはプログラム終了
		// 代入だけで終わっている場合にもここに来るので、エラーではない
		nslog(@"演算子があるべき部分で改行(プログラム終了)");
		return (CODE_PROGRAMEND);
	}
	// その他文字であった
	//
	// 記号演算子のチェック
	uwCODE code;
	int i=0;
	while (OperatorName[i].name!=NULL) {
		nslog(@"%s",OperatorName[i].name);
		if (compareNameToSource((UByte *)OperatorName[i].name,YES)!=CMP_NOT_EQUAL) {
			// sourceは演算子の直後
			code=OperatorName[i].code;
			UByte c=*source; // 次の1文字
			switch (code) {
				case CODE_DIV:
					nslog(@"DIV");
					if (c=='*'||c=='/') {
						// 実は /*,//で注釈であった
						nslog(@"実は注釈であった");
						source--; // 注釈の先頭に戻しておく
						return(CODE_NONE);
					}
					break;
				//
				// <>の時は>=,<=,<>があり得る
				case CODE_SMALL: // <
					DBG_printf1("\nCODE_SMALL:[%c]",c);
					if (c=='>') {
						// <>
						DBG_prints(" → CODE_NOTEQU");
						code=CODE_NOTEQU;
					} else {
						if (c!='=') break; // <のみ
						// <=
						DBG_prints(" → CODE_SMALLEQU");
						code=CODE_SMALLEQU;
					}
					source++; // =または>も飛ばす
					break;
				case CODE_LARGE: // >
					DBG_printf1("\nCODE_LARGE:[%c]",c);
					if (c!='=') break; // >のみ
					// >=
					DBG_prints(" → CODE_LARGEEQU");
					code=CODE_LARGEEQU;
					source++; // =も飛ばす
					break;
			}
			DBG_prints("\n");
			nslog(@"%s:code=$%04x",OperatorName[i].name,code);
			DBG_printCode(code);
			DBG_Func2("(end)");
			return (code);
		}
		i++;
	}
	DBG2_printf1("%s(end);NONE\n",__FUNCTION__);
	return (CODE_NONE);
}

//--------------------------------------------------------------------------------------
// 変数チェック
//--------------------------------------------------------------------------------------

#ifdef CORE_DEBUG2
int fglobal;
#endif

// 変数が指定変数領域内に存在するかどうか調べる
// name		変数名
// varCtrl	変数管理ワーク（グローバル/ローカル）
// size1	1変数管理ワークのサイズ
// リターン値
//		1変数管理構造体のアドレス
//		NULL=見つからない(未宣言変数)
//	no=変数番号(ローカル変数への変換は呼び出し側で行うこと)
VARIABLE1 *varCheck(UByte *name,uwHash hash,swStrLEN len,VAR_CTRL *varCtrl,int size1,swVarNO *no)
{	// 185 _check
	DBG_Func();
	
	VARIABLE1 *var1=varCtrl->var1Top;	// 変数チェインバッファー内に記録されている
	swVarCNT cnt=varCtrl->cnt;			// 登録されている変数の個数
	DBG2_printf2("登録されている変数の数=%d/size1=%d\n",cnt,size1);
	//if (size1==32 && cnt>0) DBG2_dump("LocalArray.dat",var1,256);
	if (cnt>0) { // 変数が登録されている
		#ifdef CORE_DEBUG2
		if (fglobal) {
			DBG_printf("登録済み変数数=%d/var1=%p\n",cnt,var1);
			DBG_printf("検索変数:hash=$%04x/len=%d : ",hash,len);
			DBG2_printName(name,len);
		}
		#endif
		int cnt1InLink=CNT_VAR_IN_1_BLOCK; // 1ブロック内の変数格納可能数
		swVarCNT i;
		for (i=0;i<cnt;i++) {
			DBG2_printf2("---\n%d.比較変数名:hash=$%04x : ",i,var1->hash);
			DBG2_printName(var1->token,var1->len);
			if (var1->hash==hash
			 && var1->len ==len) {
				// ハッシュ値と長さが一致する時
				nslog(@"ハッシュ値と長さが一致");
				if (memcmp(var1->token,name,len)==0) {
					// 全一致
					*no=i;
					return (var1);
				}
			}
			// 次の変数へ
			DBG2_printf2("次の変数へ;var1=%p+%d=",var1,size1);
			var1=(VARIABLE1 *)pointerAdd(var1,size1);
			DBG2_printf2("next var1=%p/cnt1InLink=%d\n",var1,cnt1InLink);
			if (--cnt1InLink==0) {
				var1=*(VARIABLE1 **)var1; // 次のリンクへ;一番後ろにリンクポインタが入っている
				cnt1InLink=CNT_VAR_IN_1_BLOCK; // 1ブロック内の変数格納可能数
			}
		}
	} // 変数は登録されてない
	// 見つからなかった;noは不変
	return (NULL);
}

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

// 変数名がすでに存在するかどうかを調べる
// hash/len	hash/文字数
// name		名前
// no		変数番号(この番号にはグローバル・ローカルの区別はない) ; >=SystemVar???TopNo:システム変数
// operationStatus.flocal : YES=ローカル変数モード , NO=グローバル変数モード
// リターン値：変数の型または重複状態
// 		存在しない		MATH_NONE
//		存在する		MATH_INT/STR/CHAR/FLOAT
//						no=変数番号
// stat:変数形態	VARIABLE_*
//	VARIABLE_DIMがあるときはdimInfo=その配列情報のポインタ
//	以下ローカル変数または存在しない時は<0になる(グローバル/ローカルの区別はこちら)
//  -1 : 存在しない(retType=MATH_NONE)
uwMATHTYPE variableCheck(UByte *name,uwHash hash,UWord len,sbVarSTAT *stat,DIM1 *(*dimInfo),swVarNO *no)
{
	DBG_Func();
	DBGprintName(name,len);
	nslog(@"hash=$%04x,len=%d\n",hash,len);
	DBG2_dumpNames();
	#ifdef CORE_DEBUG2
	fglobal=NO;
	#endif

	// (1)system変数との比較(最優先)
	int j=0;
	while ( systemVariable[j].token!=NULL) {
		if (systemVariable[j].hash==hash
		 && systemVariable[j].len ==len) {
			// ハッシュ値と長さが一致する時
			if (memcmp((char *)systemVariable[j].token,(char *)name,len)==0) {
				// 全一致
				nslog(@"システム変数:%s\n",systemVariable[j].token);
				*stat=VARIABLE_GLOBAL_VAR|VARIABLE_SYSTEM;	// グローバル変数扱いにする
				*no=systemVariable[j].no;
				return (systemVariable[j].msType);
			}
		}
		j++;
	}
	// system変数とは一致しなかった
	
	nslog(@"ローカル変数チェック");
	VARIABLE1 *var1;
	VAR_TYPES i;
	if (operationStatus.flocal) { // ローカル変数モード
		*stat=VARIABLE_LOCAL_VAR;	// ローカル変数
		for (i=VAR_INT;i<=VAR_FLOAT;i++) {
			nslog(@"---%s型\n",name_type[i].name);
			if (varCheck(name,hash,len,&localVarCtrl[i],SZ_VARIABLE1,no)!=NULL)	{
			//	*no=_setLocal(*no); // ローカル変数番号に変換する
				DBG2_printName(name,len);
				nslog(@"=ローカル変数:番号=%d;msType=$%04x\n",*no,MathTypeOfParameters[i]);
				return(MathTypeOfParameters[i]);
			}
		}
		//
		nslog(@"ローカル配列");
		var1=varCheck(name,hash,len,&LocalArray,SZ_VARIABLE_DIM1,no);
		if (var1!=NULL) {
			*stat=VARIABLE_LOCAL_DIM;	// local 配列
		//	*no=_setLocal(*no); // ローカル変数番号に変換する
			*dimInfo=(DIM1 *)var1->dims;
			DBG_printName(name,len);
			nslog(@"=ローカル配列:番号=%d\n",*no);
			return ((*dimInfo)->msType);
		}
	}
	
	// 133 global_var_check
	nslog(@"グローバル変数チェック");
	
	// グローバル変数は常にチェックされる
	*stat=VARIABLE_GLOBAL_VAR;	// グローバル変数
	for (i=VAR_INT;i<=VAR_FLOAT;i++) {
		nslog(@"---%s型\n",name_type[i].name);
		if (varCheck(name,hash,len,&globalVarCtrl[i],SZ_VARIABLE1,no)!=NULL) {
			// noはそのまま
			DBGprintName(name,len);
			nslog(@"=グローバル変数:番号=%d;msType=$%04x\n",*no,MathTypeOfParameters[i]);
			return(MathTypeOfParameters[i]);
		}
	}
	//
	nslog(@"グローバル配列");
	var1=varCheck(name,hash,len,&GlobalArray,SZ_VARIABLE_DIM1,no);
	if (var1!=NULL) {
		*stat=VARIABLE_GLOBAL_DIM;	// 配列
		*dimInfo=(DIM1 *)var1->dims;
		DBGprintName(name,len);
		nslog(@"=グローバル配列:番号=%d\n",*no);
		return ((*dimInfo)->msType);
	}
	
	DBG2_Func();
	
	// 一致変数なし
	nslog(@"一致変数なし");
	*stat=VARIABLE_NONE;
	return (MATH_NONE);
}

//--------------------------------------------------------------------------------------
// 関数チェック
//--------------------------------------------------------------------------------------

// token=関数名
// hash=ハッシュ値 , len=文字数
// リターン値：=0:見つからない , !=0:リターン値の型(*_ret)
// 見つかった時
//	paramCnt  	: パラメーターの個数そのもの		NULLもあり
//	paramTable	: パラメーターテーブルのアドレス	NULLもあり
//	fno0		: 関数番号を返す；ここでは内部関数かどうかのフラグは設定しない	NULLもあり
uwPARAMTYPE funcCheckLoop(FUNCTION1 *func1,UByte *token,uwHash hash,UWord len,swVarCNT *paramCnt0,uwCODE *(*paramTable0),swFuncNO *fno0)
{	// 278
	DBG_Func();
	swVarCNT	paramCnt; //	=*paramCnt0;
	uwCODE		*paramTable; // =*paramTable0;	// iOS
	DBG_printf2("関数:%p(%d)=",token,len); // 調べる関数名
	DBG_printName(token,len);
	//
	swFuncNO fno=0;
	while (func1->token!=NULL) {
#ifdef CORE_DEBUG
		printf("(%d)token=%s\n",fno,func1->token);
#endif
		if (func1->hash ==hash
		 && func1->len  ==len) {
			// ハッシュと文字列長が一致
			if (memcmp((char *)token,(char *)func1->token,len)==0) {
				// 名前も一致	292
				uwPARAMTYPE *p=func1->param; // パラメーターテーブル	293
				paramTable=p; // パラメーターテーブルのアドレスを返すため
				DBG_printf1("すべて一致:パラメーターテーブル=%p\n",p);
				// パラメーター数の算出とリターン値の取得
				paramCnt=0; // 引数の個数	295相当
				uwPARAMTYPE prm;
				while (1) {
					prm=*p++;
					DBG_printf1("[$%04x]",prm);
					if (prm&PARAM_RETURN) {
						// リターン値(オリジナルとはPARAM_ARRAYextの値が違うので、異なる判定式になっている)
						DBG_printsn("リターン値");
						break;
					}
					// 拡張配列指定時には、配列の要素数として定数(_CONSTANT=0x8000)もあるので識別が必要
					if (prm==PARAM_ARRAYext) { // 配列拡張	300
						// なので、この先しばらくは特別処理しなくてはならない
						prm=*p++;	// 次のパラメーター
						swJigen jigen=_getJigen(prm);	// 次元
						#ifdef CORE_DEBUG
						uwTYPE type=_getType(prm);		// T_*型
						DBG_printf3("型|次元=$%04x/次元=%d/型=$%04x\n",prm,jigen,type);
						#endif
						//									  拡張配列
						//									  ↓ 型|次元(-1;オリジナル)
						//									  ↓   ↓ 要素数フラグ=p
						//									  ↓   ↓   ↓  要素数
						//									  ↓   ↓   ↓   ↓   リターン値
						// ｢例｣testFunc(n;int,s(5);str)→	0002 8080 0100 8000 0005 8001	オリジナル
						//								0002 4000 0101 8000 0005 8001	iOS
						jigen++;	// 要素数フラグ分を加えておく
						p+=jigen;	// 要素数フラグ分＋次元数分要素数情報を飛ばす
					// 不要だった
					//	paramCnt+=(1+jigen);	// パラメーター数も加えておく
					//	// 次元数分も次でカウントする
					}
					paramCnt++;	// 引数の個数	(297だけど順番が違う)
				}
				DBG_printsn("リターン値発見直後");
				if (fno0     !=NULL) *fno0		=fno;
				if (paramCnt0!=NULL) *paramCnt0	=paramCnt;
				DBG_printf3("fno0=%p,paramCnt0=%p,paramTable=%p\n",fno0,paramCnt0,paramTable0);
				if (paramTable0!=NULL) *paramTable0=paramTable;
				#ifdef CORE_DEBUG
				DBG_printf("\n見つかった:番号=%d,引数(%d)=",fno,paramCnt); _f();
				int i;
				for (i=0;i<paramCnt;i++) {
					DBG_printf("$%04x,",*(paramTable+i)); _f();
				}
				DBG_printf("/リターン値=$%04x\n",prm);
				_f();
				#endif
				// リターン値の型を返す
				return (prm);
			}
			// 名前が不一致
		}
		func1++;
		fno++;
	} // while
	// 関数が見つからない
	// リターン値はPARAM_RETURNが立っているので=0にはならない
	// ＝0のときは関数が見つからない
	DBG_printsn("見つからない");
	return (FuncNotFound);
}

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

// 関数名チェック
// token=関数名 , hash=ハッシュ値 , len=文字数
// リターン値
//		 =0:見つからない
//		!=0:リターン値の型(*_ret) ; bit15=1なので<0になっている
// 見つかった時(NULLなら格納しない)
//	paramCnt  	: パラメーターの個数そのもの(リターン値は含まない)		NULLもあり
//	paramTable	: パラメーターテーブルのアドレス						NULLもあり
//	fno			: 関数番号(0～) ; <0ならinternalFunction(-fno-1なので0->-1,1=-2...になる)	NULLもあり
uwPARAMTYPE functionCheck(UByte *token,uwHash hash,UWord len,swVarCNT *paramCnt,uwCODE *(*paramTable),swFuncNO *fno)
{	// 235
	DBG_Func();
	uwPARAMTYPE retType;
	if (InternalFunctionCount>0) {
		// 内部関数がある時はそれが優先
		DBG_printsn("内部関数チェック");
		DBG_printName(token,len);
		DBG_printf2("*paramCnt=%p/*paramTable=%p\n",paramCnt,paramTable);
		//
		retType=funcCheckLoop(InternalFunctionBuffer,token,hash,len,paramCnt,paramTable,fno);
		if (retType!=FuncNotFound) {
			// 内部関数にあった
			DBG_printsn("内部関数にあった");
			if (fno!=NULL) {
				*fno=_setInternalFuncNo(*fno); // 内部関数番号にする
			}
			return (retType);
		}
		// 内部関数にはなかった
	}
	// 外部関数検索
	DBG_printsn("外部関数チェック");
	// まずはハッシュ値で関数の存在の可能性を調べる
	if (ExternalFuncsionTable[hash&0xff].cnt==0) { // 同ハッシュ値を持つ関数はない
		// 外部関数にもない
		DBG_printsn("外部関数にもない(ハッシュで判断)");
		return (FuncNotFound);
	}
	DBG_printf1("外部関数検索:cnt=%d\n",ExternalFuncsionTable[hash&0xff].cnt);
	retType=funcCheckLoop(&FunctionBuffer[ExternalFuncsionTable[hash&0xff].offset],token,hash,len,paramCnt,paramTable,fno);
	DBG_printsn("functionCheck(end)");
	// paramTableには関数の持つ引数テーブルのアドレスが入る
	// 内部関数の時はInternalFunctionParam、外部関数の時は外部関数ファイル内にある引数テーブル
	return (retType);
}

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