//--------------------------------------------------------------------------------------
//
// X-BASIC'
//	外部関数：拡張関数
//
//--------------------------------------------------------------------------------------
// 外部関数の構造を持っている

#include "fdef.h"
#include "XB.h"
#include "support.h"
#include "code2code.h"
#include <time.h>
#include <sys/types.h>
#include <regex.h>
#import "malloc2.h"
#import "sjisZentohan.h"
#import "XBfunc.h"
#include "atoi3b.h"

//---------------------------------------------------------------------------------------------
// 共通ワーク

static UByte *tempBuff;	// 文字列作成領域

//---------------------------------------------------------------------------------------------
// 関数実体
//---------------------------------------------------------------------------------------------

static RET_FUNC _F_version(SWord numFAC,FAC fac[])
// この外部関数のバージョンを返す
{
	printFunc();
	fac[0].dl.cp[LL]=VERSION_XBFUNC2;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// エラーの時はリターン値を!=0
//---------------------------------------------------------------------------------------------
// 文字コード判定
//---------------------------------------------------------------------------------------------

static RET_FUNC _F_iskanji1Sjis(SWord numFAC,FAC fac[])
{
	printFunc();
	int c=(int)fac[0].dl.l[LL];
	fac[0].dl.l[LL]=(SLong)(iskanji1Sjis(c)? BASIC_YES:BASIC_NO);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_iskanji2Sjis(SWord numFAC,FAC fac[])
{
	printFunc();
	int c=(int)fac[0].dl.l[LL];
	fac[0].dl.l[LL]=(SLong)(iskanji2Sjis(c)? BASIC_YES:BASIC_NO);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// 文字コード変換(1コード)
//---------------------------------------------------------------------------------------------

// あり得ないコードでのリターン値は不定
static RET_FUNC _F_utf16ToSjis(SWord numFAC,FAC fac[])
{
	printFunc();
	int c=(int)fac[0].dl.l[LL];
	fac[0].dl.l[LL]=(SLong)u16Sjis((UWord)c,U2STable,U2STableSize);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

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

static RET_FUNC _F_sjisToUtf16(SWord numFAC,FAC fac[])
// あり得ないコードでのリターン値は不定
{
	printFunc();
	int c=(int)fac[0].dl.l[LL];
	switch (c>>8) {
		case 0x80: // 1/2角
		case 0xf0: // 上付き1/4角（片仮名）
		case 0xf1: // 上付き1/4角（平仮名）
		case 0xf2: // 下付き1/4角（片仮名）
		case 0xf3: // 下付き1/4角（平仮名）
			// 1/2,1/4角文字は普通のASCIIに変換
			c=b8(c);
			break;
		default:
			c=u16Sjis((UWord)c,S2UTable,S2UTableSize);
			break;
	}
	fac[0].dl.l[LL]=c;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

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

// あり得ないコードでのリターン値は不定
static RET_FUNC _F_utf16ToUtf8(SWord numFAC,FAC fac[])
{	printFunc();
	SLong c=fac[0].dl.l[LL];
	fac[0].dl.l[LL]=(SLong)Utf16ToUtf8(c); // 本来ULongだが、実在するのはint範囲のみなので
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

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

// あり得ないコードでのリターン値は不定
static RET_FUNC _F_utf8ToUtf16(SWord numFAC,FAC fac[])
{
	printFunc();
	SLong c=fac[0].dl.l[LL];
	fac[0].dl.l[LL]=(SLong)Utf8ToUtf16(c); // 本来ULongだが、実在するのはint範囲のみなので
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

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

// あり得ないコードでのリターン値は不定
static RET_FUNC _F_sjisToUtf8(SWord numFAC,FAC fac[])
{	printFunc();
	ULong c=fac[0].dl.l[LL];
	fac[0].dl.l[LL]=(ULong)sjisToUtf8(c);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// あり得ないコードでのリターン値は不定
static RET_FUNC _F_utf8ToSjis(SWord numFAC,FAC fac[])
{	printFunc();
	ULong c=fac[0].dl.l[LL];
	fac[0].dl.l[LL]=(ULong)utf8ToSjis(c);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

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

// あり得ないコードでのリターン値は不定
static RET_FUNC _F_chars2Sjis(SWord numFAC,FAC fac[])
{	printFunc();
	int c=(int)fac[0].dl.l[LL];
	fac[0].dl.l[LL]=(ULong)chars2Sjis(c);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// あり得ないコードでのリターン値は不定
static RET_FUNC _F_chars2Utf8(SWord numFAC,FAC fac[])
{	printFunc();
	int c=(int)fac[0].dl.l[LL];
	fac[0].dl.l[LL]=(ULong)chars2Utf8(c);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// 文字コード変換(文字列)
//---------------------------------------------------------------------------------------------

// UTF8 → SJIS
static RET_FUNC _F_utf8ToSjisS(SWord numFAC,FAC fac[])
{
	printFunc();
	
	UByte *src=fac[0].dl.bp[LL];
	UByte *des=fac[1].dl.bp[LL];
	UByte *des0=des;
	ULong c;
	int len=0;
	// サイズ制限があるので、utf8ToSjisS()は使わない
	while ((c=getUtf8(&src))!=EOS) { // UTF8文字列として1文字分の文字コードを得る
		c=utf8ToSjis(c); // UTF8 → SHIFT-JIS
		int sz1=calcLongSize(c);
		if (len+sz1>=operationStatus.sz_str-1) break; // 文字列最大長を超えるとき
		des=storeSjis(des,c);
	}
	*des=EOS;
	//
	fac[0].dl.l[LL]=(int)des0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

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

static RET_FUNC _F_sjisToUtf8S(SWord numFAC,FAC fac[])
// SJIS → UTF8
{
	printFunc();
	
	UByte *src=fac[0].dl.bp[LL];
	UByte *des=fac[1].dl.bp[LL];
	UByte *des0=des;
	ULong c;
	int len=0;
	// サイズ制限があるので、sjisToUtf8S()は使わない
	while ((c=getSjisNoX68(&src))!=EOS) {
		c=sjisToUtf8(c); // SHIFT-JIS → UTF8
		int sz1=calcLongSize(c);
		if (len+sz1>=operationStatus.sz_str-1) break; // 文字列最大長を超えるとき
		des=storeUtf8(des,c);
	}
	*des=EOS;
	fac[0].dl.l[LL]=(int)des0;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// 文字列長を返す
//---------------------------------------------------------------------------------------------

// UTF8での文字数を数える
static RET_FUNC _F_utf8Len(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *str=fac[0].dl.bp[LL];
	fac[0].dl.l[LL]=utf8Len(str);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// SJISでの文字数を数える
static RET_FUNC _F_sjisLen(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *str=fac[0].dl.bp[LL];
	fac[0].dl.l[LL]=sjisLen(str);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// 先頭の1文字のコードを返す
//---------------------------------------------------------------------------------------------

static RET_FUNC _F_utf8(SWord numFAC,FAC fac[])
// UTF8文字列の先頭1文字のコードを返す
{
	UByte *str=fac[0].dl.bp[LL];
	fac[0].dl.l[LL]=getUtf8(&str);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sjis(SWord numFAC,FAC fac[])
// SJIS文字列の先頭1文字のコードを返す
{
	UByte *str=fac[0].dl.bp[LL];
	fac[0].dl.l[LL]=getSjis(&str);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// string$/mirror$
//---------------------------------------------------------------------------------------------

// utf8文字列sの先頭1文字を指定個数並べた文字列を作る
static RET_FUNC _F_utf8StringS(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *des=tempBuff;
	int i=(int)fac[0].dl.l[LL]; // i<=0のときはNULLになる
	if (i>0) {
		UByte *src=fac[1].dl.bp[LL];
		// 1文字目のコードを得る
		ULong c=getUtf8(&src);
		// それを指定文字数分書き込む
		int sz1=calcLongSize(c); // string$では途中で文字サイズは変わらないから
		int len=0;
		while (i-->0) {
			if (len+sz1>=operationStatus.sz_str-1) break; // 文字列最大長を超えるとき
			des=storeUtf8(des,c);
		}
	}
	*des=EOS;
	if (bstrlen(tempBuff)>=operationStatus.sz_str) {
		setExternalFuncErrmes("変換結果の文字列が最大長を超えます","The conversion result string exceeds the maximum length.");
		return (RET_FUNC_ERR);
	}
	//
	fac[0].dl.bp[LL]=tempBuff;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// SJIS文字列sの先頭1文字を指定個数並べた文字列を作る
static RET_FUNC _F_sjisStringS(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *des=tempBuff;
	int i=(int)fac[0].dl.l[LL]; // i<=0のときはNULLになる
	if (i>0) {
		UByte *src=fac[1].dl.bp[LL];
		// 1文字目のコードを得る
		ULong c=getSjis(&src);
		// それを指定文字数分書き込む
		int sz1=calcLongSize(c); // string$では途中で文字サイズは変わらないから
		int len=0;
		while (i-->0) {
			if (len+sz1>=operationStatus.sz_str-1) break; // 文字列最大長を超えるとき
			des=storeSjis(des,c);
		}
	}
	*des=EOS;
	if (bstrlen(tempBuff)>=operationStatus.sz_str) {
		setExternalFuncErrmes("変換結果の文字列が最大長を超えます","The conversion result string exceeds the maximum length.");
		return (RET_FUNC_ERR);
	}
	//
	fac[0].dl.bp[LL]=tempBuff;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

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

// utf8左右反転文字列を作る
static RET_FUNC _F_utf8MirrorS(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *str=fac[0].dl.bp[LL];
	UByte *bp =tempBuff;
	//
	int i,len=utf8Len(str)-1;
	for (i=0;i<=len;i++) {
		int pos=utf8Position(str,len-i); // 後ろからの文字数目で文字コードを取得
		// このあたりの処理が無駄が多い
		// バイト列からコード化してまたバイト列化している
		UByte *bp2=&str[pos];
		ULong c=getUtf8(&bp2);
		bp=storeUtf8(bp,c);
	}
	*bp=EOS;
	// 左右反転なので文字数は変わらない＝文字列長チェックは不要
	fac[0].dl.bp[LL]=tempBuff;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// SJIS左右反転文字列を作る
static RET_FUNC _F_sjisMirrorS(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *str=fac[0].dl.bp[LL];
	UByte *bp =tempBuff;
	//
	int i,len=sjisLen(str)-1;
	for (i=0;i<=len;i++) {
		int pos=sjisPosition(str,len-i); // 後ろからの文字数目で文字コードを取得
		// このあたりの処理が無駄が多い
		// バイト列からコード化してまたバイト列化している
		UByte *bp2=&str[pos];
		ULong c=getSjis(&bp2);
		bp=storeSjis(bp,c);
	}
	*bp=EOS;
	// 左右反転なので文字数は変わらない＝文字列長チェックは不要
	fac[0].dl.bp[LL]=tempBuff;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// mid$/left$/right$
//---------------------------------------------------------------------------------------------
// これらは部分文字列なので文字列長は元以下にしかならないのでチェックなし

// UTF8専用
// pos=0～utf8Len(str)-1 : BASICの引数とは違うので注意
UByte *utf8Mid(UByte *str,int pos,int ln)
{
	DBG_printf3("str=%s,pos=%d,ln=%d\n",str,pos,ln);
	UByte *bp=tempBuff;
	if (pos>=0) {
		int len=utf8Len(str);
		if (pos<len) {
			while (ln-->0) {
				int p=utf8Position(str,pos++);
				UByte *bp2=&str[p];
				ULong c=getUtf8(&bp2);
				bp=storeUtf8(bp,c);
			}
		} // pos>=lenのときはNULL
	} // pos<=0の時はNULLを返す
	*bp=EOS;
	return (tempBuff);
}

static RET_FUNC _F_utf8MidS(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *str=fac[0].dl.bp[LL];
	int i1=(int)fac[1].dl.l[LL];
	int i2=(int)fac[2].dl.l[LL];
	//
	fac[0].dl.bp[LL]=utf8Mid(str,i1-1,i2);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_utf8LeftS(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *str=fac[0].dl.bp[LL];
	int i1=(int)fac[1].dl.l[LL];
	//
	fac[0].dl.bp[LL]=utf8Mid(str,0,i1);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_utf8RightS(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *str=fac[0].dl.bp[LL];
	int i1=(int)fac[1].dl.l[LL];
	//
	fac[0].dl.bp[LL]=utf8Mid(str,utf8Len(str)-i1,i1);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

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

// SJIS専用
// pos=0～sjisLen(str)-1 : BASICの引数とは違うので注意
UByte *sjisMid(UByte *str,int pos,int ln)
{
	DBG_printf3("str=%s,pos=%d,ln=%d\n",str,pos,ln);
	UByte *bp=tempBuff;
	if (pos>=0) {
		int len=sjisLen(str);
		if (pos<len) {
			while (ln-->0) {
				int p=sjisPosition(str,pos++);
				UByte *bp2=&str[p];
				ULong c=getSjis(&bp2);
				bp=storeSjis(bp,c);
			}
		} // pos>=lenのときはNULL
	} // pos<=0の時はNULLを返す
	*bp=EOS;
	return (tempBuff);
}

static RET_FUNC _F_sjisMidS(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *str=fac[0].dl.bp[LL];
	int i1=(int)fac[1].dl.l[LL];
	int i2=(int)fac[2].dl.l[LL];
	//
	fac[0].dl.bp[LL]=sjisMid(str,i1-1,i2);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sjisLeftS(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *str=fac[0].dl.bp[LL];
	int i1=(int)fac[1].dl.l[LL];
	//
	fac[0].dl.bp[LL]=sjisMid(str,0,i1);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sjisRightS(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *str=fac[0].dl.bp[LL];
	int i1=(int)fac[1].dl.l[LL];
	//
	fac[0].dl.bp[LL]=sjisMid(str,sjisLen(str)-i1,i1);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// 文字列→配列変換関数
//---------------------------------------------------------------------------------------------

// strToArray(str;str,array;1次元配列)
// 配列はchar/int(拡張配列は来ない)
// INT_RET ; 使った要素数；入りきらないときは最大数
// ASCII用
static RET_FUNC _F_strToArray(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *bp=fac[0].dl.bp[LL];
	
	REGISTER p;
	SWord size1;
	uwYouso youso;
	p.bp=(UByte *)getDim1FromFAC(fac,1,&size1,&youso);
	if (p.bp==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	
	uwYouso i=0;
	UByte c;
	do {
		c=*bp++;
		// 配列の型別に要素として入れる
		switch (size1) {
			case SZ_CHAR: // char
				*p.bp++=c;
				break;
			case SZ_LONG: // int
				p.lp=storeLong(p.lp, (ULong)c); // *p.lp++=(ULong)c;
				break;
		}
		if (++i>=youso) break; // 要素数が足りなくなったら終了
	} while (c!=EOS); // EOSまで
	// fac[]に入れて返す
	fac[0].dl.l[LL]=i; // 使った要素数を返す(EOSを含む)
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// utf8ToArray(str;str,array;1次元配列)
// 配列はint(拡張配列は来ない)
// INT_RET ; 使った要素数；入りきらないときは最大数
// UTF8用
static RET_FUNC _F_utf8ToArray(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *bp=fac[0].dl.bp[LL];
	
	SWord size1;
	uwYouso youso;
	ULong *lp=(ULong *)getDim1FromFAC(fac,1,&size1,&youso);
	if (lp==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	
	uwYouso i=0;
	ULong c;
	do {
		c=getUtf8(&bp);
		// 配列に要素として入れる
		lp=storeLong(lp,c);
		if (++i>=youso) break; // 要素数が足りなくなったら終了
	} while (c!=EOS);
	// fac[]に入れて返す
	fac[0].dl.l[LL]=i; // 使った要素数を返す(EOSを含む)
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// sjisToArray(str;str,array;1次元配列)
// 配列はint(拡張配列は来ない)
// INT_RET ; 使った要素数；入りきらないときは最大数
// SJIS用
static RET_FUNC _F_sjisToArray(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *bp=fac[0].dl.bp[LL];
	
	SWord size1;
	uwYouso youso;
	ULong *lp=(ULong *)getDim1FromFAC(fac,1,&size1,&youso);
	if (lp==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	
	uwYouso i=0;
	ULong c;
	do {
		c=getSjis(&bp);
		// 配列に要素として入れる
		lp=storeLong(lp,c);
		if (++i>=youso) break; // 要素数が足りなくなったら終了
	} while (c!=EOS);
	// fac[]に入れて返す
	fac[0].dl.l[LL]=i; // 使った要素数を返す(EOSを含む)
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// 配列→文字列変換関数
//---------------------------------------------------------------------------------------------

// arrayToStr(array;1次元配列,str;str)
// 配列はchar/int(拡張配列は来ない)
// numFAC=1 : fac[0]=配列(0～0x00の要素まで) , fac[1]=STR_VP
// INT_RET ; strlen()；入りきらないときは最大数
// ASCII用
static RET_FUNC _F_arrayToStr(SWord numFAC,FAC fac[])
{
	REGISTER p;
	SWord size1;
	uwYouso youso;
	p.bp=(UByte *)getDim1FromFAC(fac,0,&size1,&youso);
	if (p.bp==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	
	UByte *bp=fac[1].dl.bp[LL];
	//
	uwYouso i=0;
	ULong c=0; // =0は警告回避のため
	
	while (i<youso) {
		// 配列の型別に読み取る
		switch (size1) {
			case SZ_CHAR: // char
				c=*p.bp++;
				break;
			case SZ_LONG: // int
				c=readLong(p.lp++); // c=*p.lp++;
				break;
		}
		if (c==EOS) break;
		*bp++=(UByte)c;
		i++;
		if (i>=operationStatus.sz_str-1) break; // 最大文字数を超える
	}
	*bp=EOS;
	
	// fac[]に入れて返す
	fac[0].dl.l[LL]=i; // バイト数を返す
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// arrayToUtf8(array;1次元配列,str;str)
// 配列はint(拡張配列は来ない)
// numFAC=1 : fac[0]=配列(0～0x00の要素まで) , fac[1]=STR_VP
// INT_RET ; utf8Len()；入りきらないときは最大数
// UTF8用
static RET_FUNC _F_arrayToUtf8(SWord numFAC,FAC fac[])
{
	SWord size1;
	uwYouso youso;
	ULong *lp=(ULong *)getDim1FromFAC(fac,0,&size1,&youso);
	if (lp==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	
	UByte *bp=fac[1].dl.bp[LL];
	UByte *bp0=bp;
	//
	uwYouso i=0;
	ULong c;
	while ((c=readLong(lp++))!=EOS) {
		if (i>=youso) break;
		int sz=calcLongSize(c);
		if ((int)(bp-bp0)+sz>=operationStatus.sz_str-1) break; // 最大文字数を超える
		//
		bp=storeUtf8(bp,c);
		i++;
	}
	*bp=EOS;
	
	// fac[]に入れて返す
	fac[0].dl.l[LL]=i; // 文字数を返す
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// arrayToSjis(array;1次元配列,str;str)
// 配列はint(拡張配列は来ない)
// numFAC=1 : fac[0]=配列(0～0x00の要素まで) , fac[1]=STR_VP
// INT_RET ; sjisLen()；入りきらないときは最大数
// SJIS用
static RET_FUNC _F_arrayToSjis(SWord numFAC,FAC fac[])
{
	SWord size1;
	uwYouso youso;
	ULong *lp=(ULong *)getDim1FromFAC(fac,0,&size1,&youso);
	if (lp==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	
	UByte *bp=fac[1].dl.bp[LL];
	UByte *bp0=bp;
	//
	uwYouso i=0;
	ULong c;
	while ((c=readLong(lp++))!=EOS) {
		if (i>=youso) break;
		int sz=calcLongSize(c);
		if ((int)(bp-bp0)+sz>=operationStatus.sz_str-1) break; // 最大文字数を超える
		//
		bp=storeSjis(bp,c);
		i++;
	}
	*bp=EOS;
	
	// fac[]に入れて返す
	fac[0].dl.l[LL]=i; // 文字数を返す
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// 16進文字列変換関数
//---------------------------------------------------------------------------------------------

//	str hexchr$(str)
// ｢例｣ "3041"("00"は入れてはいけない) → "0A"
static RET_FUNC _F_hexchrS(SWord numFAC,FAC fac[])
{
	UByte *bp=fac[0].dl.bp[LL];
	UByte *bp2=tempBuff;
	int c;
	while ((c=*bp)!=EOS) {
		if (c==' '||c==','||c=='/'||c=='_'||c=='\t') { // セパレーターは飛ばす(出現しやすい順)
			bp++;
			continue;
		}
		if (*(bp+1)==EOS) break; // hex2桁分ないときは終了
		c=hex2(bp);
		if (c<0) break; // 変換できない文字があった
		bp+=2;
		if (c!=0x00) {
			*bp2++=(UByte)c;
		} // 0x00は入れられない
	}
	*bp2=EOS;
	// 結果は必ず元より短くなるので長さチェックはしない
	// fac[]に入れて返す
	fac[0].dl.l[LL]=(SLong)tempBuff;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//	str chrhex$(str)
// ASCIIコード列を16進桁数値文字列に変換する
// ｢例｣ "0A"(文字列なので&h00は入らない) → "3041"
static RET_FUNC _F_chrhexS(SWord numFAC,FAC fac[])
{
	UByte *bp=fac[0].dl.bp[LL];
	UByte *bp2=tempBuff;
	UByte c;
	while ((c=*bp++)!=EOS) {
		sprintf((char *)bp2,"%02X",c);
		bp2+=2;
	}
	*bp2=EOS;
	if (bstrlen(tempBuff)>=operationStatus.sz_str) {
		setExternalFuncErrmes("変換結果の文字列が最大長を超えます","The conversion result string exceeds the maximum length.");
		return (RET_FUNC_ERR);
	}	// fac[]に入れて返す
	fac[0].dl.l[LL]=(SLong)tempBuff;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}
	
// hexstrToArray(str;str,array;1次元配列)
// 16進文字列を2桁ずつコード化して配列に格納する
// 配列はchar/int(拡張配列は来ない)
// INT_RET ; 使った要素数；入りきらないときは最大数
static RET_FUNC _F_hexstrToArray(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *bp=fac[0].dl.bp[LL];
	
	REGISTER p;
	SWord size1;
	uwYouso youso;
	p.bp=(UByte *)getDim1FromFAC(fac,1,&size1,&youso);
	if (p.bp==NULL) { // 1次元でない
		return (RET_FUNC_ERR);
	}
	
	uwYouso i=0;
	int c;
	while ((c=*bp)!=EOS) {
		if (c==' '||c==','||c=='/'||c=='_'||c=='\t') { // セパレーターは飛ばす(出現しやすい順)
			bp++;
			continue;
		}
		if (*(bp+1)==EOS) break; // hex2桁分ないときは無視
		c=hex2(bp);
		if (c<0) break; // 変換できない文字があった
		bp+=2;
		// 配列の型別に要素として入れる
		switch (size1) {
			case SZ_CHAR: // char
				*p.bp++=c;
				break;
			case SZ_LONG: // int
				p.lp=storeLong(p.lp, (ULong)c); // *p.lp++=(ULong)c;
				break;
		}
		if (++i>=youso) break; // 要素数が足りなくなったら終了
	}
	// fac[]に入れて返す
	fac[0].dl.l[LL]=i; // 使った要素数を返す(EOSを含む)
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// strchr()
//---------------------------------------------------------------------------------------------

// strの中にて最初に指定文字の見つかった位置(文字数目)を返す。
// 先頭=0,見つからなかった=-1
// Cの同名関数とはリターン値が違う
// UTF8
static RET_FUNC _F_utf8Chr(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *str=fac[0].dl.bp[LL];
	ULong ch  =(ULong)fac[1].dl.l[LL];
	int len=0;
	ULong c;
	while ((c=getUtf8(&str))!=EOS) {
		len++; // 先に+1、後で-1する
		if (c==ch) break;
	}
	if (c==EOS) len=0; // 見つからなかったとき；後で-1される
	// fac[]に入れて返す
	fac[0].dl.l[LL]=len-1; // 見つからなかった時は-1を返す
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// strの中にて最初に指定文字の見つかった位置(文字数目)を返す。
// 先頭=0,見つからなかった=-1
// Cの同名関数とはリターン値が違う
// SJIS
static RET_FUNC _F_sjisChr(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *str=fac[0].dl.bp[LL];
	ULong ch  =(ULong)fac[1].dl.l[LL];
	int len=0;
	ULong c;
	while ((c=getSjis(&str))!=EOS) {
		len++; // 先に+1、後で-1する
		if (c==ch) break;
	}
	if (c==EOS) len=0; // 見つからなかったとき；後で-1される
	// fac[]に入れて返す
	fac[0].dl.l[LL]=len-1; // 見つからなかった時は-1を返す
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// chr$()
//---------------------------------------------------------------------------------------------

// SJIS
static RET_FUNC _F_sjisChrS(SWord numFAC,FAC fac[])
{
	printFunc();
	ULong c=fac[0].dl.l[LL];
	DBG_printf1("c=$%04x\n",(int)c);
	UByte *bp=storeSjis(tempBuff,c);
	*bp=EOS;
	// 1文字分なので長さチェックなし
	fac[0].dl.bp[LL]=tempBuff;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// UTF8
static RET_FUNC _F_utf8ChrS(SWord numFAC,FAC fac[])
{
	printFunc();
	ULong c=fac[0].dl.l[LL];
	DBG_printf1("c=$%04x\n",(int)c);
	UByte *bp=storeUtf8(tempBuff,c);
	*bp=EOS;
	// 1文字分なので長さチェックなし
	fac[0].dl.bp[LL]=tempBuff;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

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

static RET_FUNC _F_sjisHantozen(SWord numFAC,FAC fac[])
{
	printFunc();
	ULong  c=fac[0].dl.l[LL];
	int mode=(int)fac[1].dl.l[LL];
	fac[0].dl.l[LL]=sjisHantozen(c,mode);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_utf8Hantozen(SWord numFAC,FAC fac[])
{
	printFunc();
	ULong  c=fac[0].dl.l[LL];
	fac[0].dl.l[LL]=utf8Hantozen(c);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sjisZentohan(SWord numFAC,FAC fac[])
{
	printFunc();
	ULong  c=fac[0].dl.l[LL];
	fac[0].dl.l[LL]=sjisZentohan(c);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_utf8Zentohan(SWord numFAC,FAC fac[])
{
	printFunc();
	ULong  c=fac[0].dl.l[LL];
	fac[0].dl.l[LL]=utf8Zentohan(c);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_isSjisHandaku(SWord numFAC,FAC fac[])
{
	printFunc();
	ULong  c=fac[0].dl.l[LL];
	fac[0].dl.l[LL]=isSjisHandaku(c);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_isUtf8Handaku(SWord numFAC,FAC fac[])
{
	printFunc();
	ULong  c=fac[0].dl.l[LL];
	fac[0].dl.l[LL]=isUtf8Handaku(c);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_sjisHantozens(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *bp=fac[0].dl.bp[LL];
	int  mode=(int)fac[1].dl.l[LL];
	sjisHantozens(bp,tempBuff,mode);
	if (bstrlen(tempBuff)>=operationStatus.sz_str) {
		setExternalFuncErrmes("変換結果の文字列が最大長を超えます","The conversion result string exceeds the maximum length.");
		return (RET_FUNC_ERR);
	}
	fac[0].dl.bp[LL]=tempBuff;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_utf8Hantozens(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *bp=fac[0].dl.bp[LL];
	utf8Hantozens(bp,tempBuff);
	if (bstrlen(tempBuff)>=operationStatus.sz_str) {
		setExternalFuncErrmes("変換結果の文字列が最大長を超えます","The conversion result string exceeds the maximum length.");
		return (RET_FUNC_ERR);
	}
	fac[0].dl.bp[LL]=tempBuff;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}


static RET_FUNC _F_sjisZentohans(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *bp=fac[0].dl.bp[LL];
	sjisZentohans(bp,tempBuff);
	if (bstrlen(tempBuff)>=operationStatus.sz_str) {
		setExternalFuncErrmes("変換結果の文字列が最大長を超えます","The conversion result string exceeds the maximum length.");
		return (RET_FUNC_ERR);
	}	fac[0].dl.bp[LL]=tempBuff;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_utf8Zentohans(SWord numFAC,FAC fac[])
{
	printFunc();
	UByte *bp=fac[0].dl.bp[LL];
	utf8Zentohans(bp,tempBuff);
	if (bstrlen(tempBuff)>=operationStatus.sz_str) {
		setExternalFuncErrmes("変換結果の文字列が最大長を超えます","The conversion result string exceeds the maximum length.");
		return (RET_FUNC_ERR);
	}	fac[0].dl.bp[LL]=tempBuff;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// *StrWidth();V3.00
//---------------------------------------------------------------------------------------------

// 全角半角を判別して文字幅を得る
// UTF8
static RET_FUNC _F_utf8StrWidth(SWord numFAC,FAC fac[])
{
	printFunc();

	/*
	 for i=1 to utf8Len(mes)
		s=utf8Mid$(mes,i,1)
		l=l+1
		if strlen(s)>1 then {:// このstrlen()は1文字のバイト数を数えている
	 // 2バイト以上文字
	 l=l+1:// 全角幅
	 // でも半角カナは1バイト換算しなければならない
	 if instr(1,kanas,s)>0 then {
	 // 半角カナであった
	 l=l-1:// 幅1に戻すため
	 }
		}
	 next
	 */
	UByte *mes=fac[0].dl.bp[LL];
	int l=0;
#define	kanas	"ｱｲｳｴｵｶｷｸｹｺｻｼｽｾｿﾀﾁﾂﾃﾄﾅﾆﾇﾈﾉﾊﾋﾌﾍﾎﾏﾐﾑﾒﾓﾔﾕﾖﾗﾘﾙﾚﾛﾜﾝｦｧｨｩｪｫｬｭｮｯｰ｡｢｣､･ﾞﾟ"	// 半角カナ文字群;UTF8ではコードが連続しないのでテーブルとして持つ
	int len=utf8Len(mes);
	nslog(@"utf8での文字数=%d",len);
	for (int i=0;i<len;i++) {
		UByte *s=utf8Mid(mes,i,1);
		l++;
		if (strlen((char *)s)>1) { // このstrlen()は1文字のバイト数を数えている
			// 2バイト以上文字
			l++; // 全角幅
			// でも半角カナは1バイト換算しなければならない
			FAC fac2[3];
			int j=0;
			fac2[j].facType=INT_PARAM;	fac2[j++].dl.l[LL] =1;
			fac2[j].facType=STR_PARAM;	fac2[j++].dl.cp[LL]=kanas;
			fac2[j].facType=STR_PARAM;	fac2[j++].dl.bp[LL]=s;
			_F_instr(j,fac2); // この中ではエラーは発生しないのでエラーチェック省略(V3.20)
			if (fac2[0].dl.l[LL]>0) {
				// 半角カナであった
				l--; // 幅1に戻すため
			}
		}
	}
	fac[0].dl.l[LL]=l;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}
	
// 全角半角を判別して文字幅を得る
// SJIS
static RET_FUNC _F_sjisStrWidth(SWord numFAC,FAC fac[])
{
	printFunc();

	UByte *mes=fac[0].dl.bp[LL];
	UByte c;
	int l=0;
	while ((c=*mes++)!=0) {
		if (iskanji1Sjis(c)) {
			// 全角,1/2角,1/4角文字である
			switch (c) {
				case 0x80:
				case 0xf0:
				case 0xf1:
				case 0xf2:
				case 0xf3:
					// 1/2角,1/4角なので幅１
					break;
					
				default:
					// 全角なので幅２
					l++;
					break;
			}
			mes++; // ２バイト目はチェックしない
		}
		l++;
	}
	fac[0].dl.l[LL]=l;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// 正規表現関数
//---------------------------------------------------------------------------------------------

// 正規表現比較
static RET_FUNC _F_regcomp(SWord numFAC,FAC fac[])
{
	printFunc();
	
	UByte  *src=fac[0].dl.bp[LL];
	char *regex=fac[1].dl.cp[LL]; // 正規表現式
	
	int cflags=0;
	if (fac[2].facType!=VOID_PARAM) { // 引数が省略されていない時
		cflags=(int)fac[2].dl.l[ LL];
		// この関数は1文字列に対する比較なので、改行/行頭/行末一致フラグは使わない
		// regcomp(cflags)
		// REG_ICASE   =大文字小文字を区別しない	<- cflagsで設定するのはこれだけ
		// REG_NEWLINE =改行はマッチさせない
		// REG_EXTENDED=POSIX 拡張正規表現を使用する
		// REG_NOSUB   = nmatch/pmatchを使わない
		// regexec(eflags) ; cflagsと重複するので同一時に設定できない
		// REG_NOTBOL  = 行頭では一致しない
		// REG_NOTEOL  = 行末では一致しない
		// 参照
		// http://blog.majide.com/2009/03/c-regex-sample-code/
		// http://linuxjm.sourceforge.jp/html/LDP_man-pages/man3/regcomp.3.html
	}
	if (cflags!=0) cflags=REG_ICASE; else cflags=REG_BASIC;
	// 正規表現のコンパイル
	regex_t preg;
	int ret=regcomp( &preg, regex, cflags|REG_EXTENDED); // REG_NOSUB
	if (ret!=0) {
		// エラー処理
	//	size_t regerror(ret, (const regex_t *)&preg, char *errbuf,size_t errbuf_size);
		sprintf((char *)tempBuff
			,selectMessageJE(
				"Regular expression error(Err=%d)",
				"正規表現に誤りがあります(Err=%d)")
			,ret);
		setExternalFuncErrmes((char *)tempBuff,(char *)tempBuff);
		return (RET_FUNC_ERR);
	}
	DBG_printf2("src=%s , regex=%s\n",src,regex);
	// 正規表現での比較
	size_t nmatch = 10; 		// 一致条件を得る個数(最大数)
	regmatch_t pmatch[nmatch];	// 一致結果を入れる構造体
	ret=regexec((const regex_t *)&preg, (const char *)src, nmatch, pmatch, 0);
	#ifdef CORE_DEBUG
	if (ret==0) { // 一致項目があるとき
		prints("一致あり\n");
		int i;
		for (i=0;i<nmatch;i++) {
			int j =(int)pmatch[i].rm_so; // 一致位置
			if (j<0) break; // -1=未使用→終了
			int je=(int)pmatch[i].rm_eo; // 一致最後+1
			fprintf(stderr,"一致位置=%d,%d : ",j,je);
			for (;j<je;j++) fputc(src[j],stderr);
			fputs("\n",stderr);
		}
		fputs("\n",stderr);
	} else {
		prints("一致なし\n");
	}
	#endif
	
	if (fac[3].facType!=VOID_PARAM) { // 引数が省略されていない時
		#if 0
		// 最初にマッチした位置の文字列を返す
		char *bp=fac[3].dl.cp[LL];
		memcpy(bp,&src[pmatch[0].rm_so],pmatch[0].rm_eo-pmatch[0].rm_so);
		bp[pmatch[0].rm_eo]=EOS;
		DBG_printf1(">%s\n",bp);
		#else
		// 最初にマッチした位置を返す
		int *ip=fac[3].dl.ip[LL];
		DBG_printf1("*ip=%p\n",ip);
		*ip=(int)pmatch[0].rm_so;
		DBG_printf2("一致範囲=%d～%d-1\n",(int)pmatch[0].rm_so,(int)pmatch[0].rm_eo);
		#endif
	}
	#ifdef CORE_DEBUG
	else {
		printf("第4引数は省略されている\n");
	}
	#endif
	
	if (fac[4].facType!=VOID_PARAM) { // 引数が省略されていない時
		// 最初にマッチした位置を返す
		int *ip=fac[4].dl.ip[LL];
		DBG_printf1("*ip=%p\n",ip);
		*ip=(int)pmatch[0].rm_eo;
	}
	#ifdef CORE_DEBUG
	else {
		printf("第5引数は省略されている\n");
	}
	#endif
	
	// ワークエリアの解放
	regfree(&preg);
	//
	fac[0].dl.l[LL]=(ret==0? BASIC_YES:BASIC_NO); // 比較結果;YES=一致 , NO=不一致
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// その他
//---------------------------------------------------------------------------------------------

// int sizeofArray(配列)
// 配列はchar/int/float/str(拡張配列は来ない)
// fac[0]=配列 , fac[1]=INT_VP
static RET_FUNC _F_sizeofArray(SWord numFAC,FAC fac[])
{
	printFunc();

	int *ip=fac[1].dl.ip[LL];
	ULong sizeAll=sizeofArray((DIM1_EXEC *)fac[0].dl.bp[LL],ip);
	DBG_printf2("1要素サイズ=%d,総要素数=%d\n",*ip,(int)sizeAll);
	// fac[]に入れて返す
	fac[0].dl.l[LL]=sizeAll; // 総要素数を返す
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_time(SWord numFAC,FAC fac[])
// int time()
{
	printFunc();
	time_t tm;		// time_t = long
	time(&tm);
	// fac[]に入れて返す
	fac[0].dl.l[LL]=(ULong)tm; // 1970-01-01 00:00:00 (UTC) からの秒数で返す
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// int clock()
static RET_FUNC _F_clock(SWord numFAC,FAC fac[])
{
	printFunc();
	// fac[]に入れて返す
	fac[0].dl.l[LL]=(ULong)clock(); // プロセッサ時間の近似値を返す	clock_t=unsigned long
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}
	
static RET_FUNC _F_bit(SWord numFAC,FAC fac[])
{
	printFunc();
	ULong bit=fac[0].dl.l[LL];
	fac[0].dl.l[LL]=(ULong)(1<<bit);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// インフォメーションテーブル (5.2.1章)
//---------------------------------------------------------------------------------------------

// 関数名テーブル(トークンテーブル)
static const char *extendTokens[]={
	//
	"sizeofArray",
	"time",
	"clock",	// v2.4
	"bit",
	"regcomp",
	//
	"utf16ToUtf8",
	"utf8ToUtf16",
	"utf16ToSjis",
	"sjisToUtf16",
	"utf8ToSjis$",
	"sjisToUtf8$",
	"utf8ToSjis",
	"sjisToUtf8",
	
	"chars2Sjis",
	"chars2Utf8",
	
	"iskanji1Sjis",
	"iskanji2Sjis",
	"utf8Len",
	"sjisLen",
	"utf8",
	"sjis",
	"sjisChr$",
	"utf8Chr$",
	"utf8String$",
	"sjisString$",
	"utf8Mirror$",
	"sjisMirror$",
	"utf8Mid$",
	"utf8Left$",
	"utf8Right$",
	"sjisMid$",
	"sjisLeft$",
	"sjisRight$",
	"strToArray",
	"utf8ToArray",
	"sjisToArray",
	"arrayToStr",
	"arrayToUtf8",
	"arrayToSjis",
	"hexchr$",
	"chrhex$",
	"utf8Chr",
	"sjisChr",
	"hexstrToArray",	// v2.2
	"utf8StrWidth",		// v3.00
	"sjisStrWidth",		// v3.00
	//
	// v2.6
	"sjisHantozen",
	"utf8Hantozen",
	"sjisZentohan",
	"utf8Zentohan",
	"sjisHantozens",
	"utf8Hantozens",
	"sjisZentohans",
	"utf8Zentohans",
	"isSjisHandaku",
	"isUtf8Handaku",
	//
	// バージョン
	"versionXBfunc2$",
	// end of table
	NULL,
};

// 実行アドレステーブル
static FUNC_EXEC extendFuncExec[]={
	{_F_sizeofArray},
	{_F_time},
	{_F_clock},
	{_F_bit},
	{_F_regcomp},
	//
	{_F_utf16ToUtf8},
	{_F_utf8ToUtf16},
	{_F_utf16ToSjis},
	{_F_sjisToUtf16},
	{_F_utf8ToSjisS},
	{_F_sjisToUtf8S},
	{_F_utf8ToSjis},
	{_F_sjisToUtf8},
	
	{_F_chars2Sjis},
	{_F_chars2Utf8},
	
	{_F_iskanji1Sjis},
	{_F_iskanji2Sjis},
	{_F_utf8Len},
	{_F_sjisLen},
	{_F_utf8},
	{_F_sjis},
	{_F_sjisChrS},
	{_F_utf8ChrS},
	{_F_utf8StringS},
	{_F_sjisStringS},
	{_F_utf8MirrorS},
	{_F_sjisMirrorS},
	{_F_utf8MidS},
	{_F_utf8LeftS},
	{_F_utf8RightS},
	{_F_sjisMidS},
	{_F_sjisLeftS},
	{_F_sjisRightS},
	{_F_strToArray},
	{_F_utf8ToArray},
	{_F_sjisToArray},
	{_F_arrayToStr},
	{_F_arrayToUtf8},
	{_F_arrayToSjis},
	{_F_hexchrS},
	{_F_chrhexS},
	{_F_utf8Chr},
	{_F_sjisChr},
	{_F_hexstrToArray},	// v2.2
	{_F_utf8StrWidth},	// v3.00
	{_F_sjisStrWidth},	// v3.00
	// v2.6
	{_F_sjisHantozen},
	{_F_utf8Hantozen},
	{_F_sjisZentohan},
	{_F_utf8Zentohan},
	{_F_sjisHantozens},
	{_F_utf8Hantozens},
	{_F_sjisZentohans},
	{_F_utf8Zentohans},
	{_F_isSjisHandaku},
	{_F_isUtf8Handaku},
	//
	// バージョン
	{_F_version},
	// end of table
	{NULL},
};

//------------------------------
// パラメーターテーブル
// (1)種類別定義
// 1関数の引数は最大MAX_PARAM個
//------------------------------

static const uwPARAMTYPE p_time[]={
	INT_RET,
};
#define p_clock	p_time
	
static const uwPARAMTYPE p_regcomp[]={
	STR_VAL,
	STR_VAL,
	INT_OMT,
	INT_VP|PARAM_OMIT,	//INT_OMT|PARAM_POINTER,	// 値を返すのでポインタ
	INT_VP|PARAM_OMIT,	//INT_OMT|PARAM_POINTER,	// 値を返すのでポインタ
	INT_RET,
};

static const uwPARAMTYPE p_sizeofArray[]={
	ARRAY1|PARAM_ARRAY2,
	INT_VP,
	INT_RET,
};

static const uwPARAMTYPE p_strToArray[]={
	STR_VAL,
	(PARAM_ARRAY1|PARAM_POINTER|PARAM_CHAR|PARAM_INT),	// 1次元のcharまたはint配列
	INT_RET,
};
#define p_hexstrToArray	p_strToArray	// v2.2

static const uwPARAMTYPE p_utf8ToArray[]={
	STR_VAL,
	(PARAM_ARRAY1|PARAM_POINTER|PARAM_INT),	// 1次元のint配列
	INT_RET,
};
#define	p_sjisToArray	p_utf8ToArray

static const uwPARAMTYPE p_arrayToStr[]={
	(PARAM_ARRAY1|PARAM_POINTER|PARAM_CHAR|PARAM_INT),	// 1次元のcharまたはint配列
	STR_VP,
	INT_RET,
};

static const uwPARAMTYPE p_arrayToUtf8[]={
	(PARAM_ARRAY1|PARAM_POINTER|PARAM_INT),	// 1次元のint配列
	STR_VP,
	INT_RET,
};
#define p_arrayToSjis	p_arrayToUtf8


static const uwPARAMTYPE p_utf16ToUtf8[]={
	INT_VAL,
	INT_RET,
};
#define	p_utf8ToUtf16	p_utf16ToUtf8
#define	p_sjisToUtf16	p_utf16ToUtf8
#define	p_utf16ToSjis	p_utf16ToUtf8
#define	p_iskanji1Sjis	p_utf16ToUtf8
#define	p_iskanji2Sjis	p_utf16ToUtf8
#define	p_sjisToUtf8	p_utf16ToUtf8
#define	p_utf8ToSjis	p_utf16ToUtf8
#define p_chars2Sjis	p_utf16ToUtf8
#define p_chars2Utf8	p_utf16ToUtf8

static const uwPARAMTYPE p_utf8ToSjisS[]={
	STR_VAL,
	STR_VP,
	STR_RET,
};
#define	p_sjisToUtf8S	p_utf8ToSjisS

static const uwPARAMTYPE p_utf8Len[]={
	STR_VAL,
	INT_RET,
};
#define	p_sjisLen	p_utf8Len
#define	p_utf8		p_utf8Len
#define	p_sjis		p_utf8Len

static const uwPARAMTYPE p_utf8StringS[]={
	INT_VAL,
	STR_VAL,
	STR_RET,
};
#define	p_sjisStringS	p_utf8StringS

static const uwPARAMTYPE p_utf8MirrorS[]={
	STR_VAL,
	STR_RET,
};
#define	p_sjisMirrorS	p_utf8MirrorS
#define	p_hexchrS		p_utf8MirrorS
#define	p_chrhexS		p_utf8MirrorS

static const uwPARAMTYPE p_utf8LeftS[]={
	STR_VAL,
	INT_VAL,
	STR_RET,
};
#define	p_utf8RightS	p_utf8LeftS
#define	p_sjisRightS	p_utf8LeftS
#define	p_sjisLeftS		p_utf8LeftS

static const uwPARAMTYPE p_utf8MidS[]={
	STR_VAL,
	INT_VAL,
	INT_VAL,
	STR_RET,
};
#define	p_sjisMidS	p_utf8MidS

static const uwPARAMTYPE p_utf8Chr[]={
	STR_VAL,
	INT_VAL,
	INT_RET,
};
#define	p_sjisChr	p_utf8Chr

static const uwPARAMTYPE p_version[]={
	STR_RET,
};

static const uwPARAMTYPE p_sjisChrS[]={
	INT_VAL,
	STR_RET,
};
#define	p_utf8ChrS	p_sjisChrS

static const uwPARAMTYPE p_bit[]={
	INT_VAL,
	INT_RET,
};

static const uwPARAMTYPE p_utf8StrWidth[]={
	STR_VAL,
	INT_RET,
};
#define p_sjisStrWidth	p_utf8StrWidth

// v2.6
static const uwPARAMTYPE p_sjisHantozen[]={
	INT_VAL,
	INT_VAL,
	INT_RET,
};
static const uwPARAMTYPE p_utf8Hantozen[]={
	INT_VAL,
	INT_RET,
};
#define	p_sjisZentohan	p_utf8Hantozen
#define	p_utf8Zentohan	p_utf8Hantozen
#define p_isSjisHandaku	p_utf8Hantozen
#define p_isUtf8Handaku	p_utf8Hantozen

static const uwPARAMTYPE p_sjisHantozens[]={
	STR_VAL,
	INT_VAL,
	STR_RET,
};
static const uwPARAMTYPE p_utf8Hantozens[]={
	STR_VAL,
	STR_RET,
};
#define	p_sjisZentohans	p_utf8Hantozens
#define	p_utf8Zentohans	p_utf8Hantozens

//------------------------------
// パラメーターテーブル
// (2)関数別定義

static const
uwPARAMTYPE *extendParams[]={
	p_sizeofArray,
	p_time,
	p_clock,
	p_bit,
	p_regcomp,
	//
	p_utf16ToUtf8,
	p_utf8ToUtf16,
	p_sjisToUtf16,
	p_utf16ToSjis,
	p_utf8ToSjisS,
	p_sjisToUtf8S,
	p_utf8ToSjis,
	p_sjisToUtf8,
	
	p_chars2Sjis,
	p_chars2Utf8,
	
	p_iskanji1Sjis,
	p_iskanji2Sjis,
	p_utf8Len,
	p_sjisLen,
	p_utf8,
	p_sjis,
	p_sjisChrS,
	p_utf8ChrS,
	p_utf8StringS,
	p_sjisStringS,
	p_utf8MirrorS,
	p_sjisMirrorS,
	p_utf8MidS,
	p_utf8LeftS,
	p_utf8RightS,
	p_sjisMidS,
	p_sjisLeftS,
	p_sjisRightS,
	p_strToArray,
	p_utf8ToArray,
	p_sjisToArray,
	p_arrayToStr,
	p_arrayToUtf8,
	p_arrayToSjis,
	p_hexchrS,
	p_chrhexS,
	p_utf8Chr,
	p_sjisChr,
	p_hexstrToArray,	// v2.2
	p_utf8StrWidth,		// v3.00
	p_sjisStrWidth,		// v3.00
	// v2.6
	p_sjisHantozen,
	p_utf8Hantozen,
	p_sjisZentohan,
	p_utf8Zentohan,
	p_sjisHantozens,
	p_utf8Hantozens,
	p_sjisZentohans,
	p_utf8Zentohans,
	p_isSjisHandaku,
	p_isUtf8Handaku,
	//
	// バージョン
	p_version	,
	// end of table
	NULL,
};

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

// この中の関数の初期化処理
static void _Finit(void)
{
	printFunc();
	AllTableSize();
	// 文字列ワーク確保
	// 本来operationStatus.sz_strだけ確保すれば良さそうに思えるが、
	// 文字列変換の途中には最大3倍になる可能性があるため、*3確保する。
	// (ASC->UTF8変換で、UTF8は１文字３バイトがありえるから)
	// 変換結果のバイト数がoperationStatus.sz_strを超えるときは、改めてエラーを出す
	int sz=operationStatus.sz_str*3;
	if (sz<256) sz=256; // エラーメッセージバッファーとしても使うので、一定サイズ以下にはしない。
	nslog(@"%@:%s",@(__FILE__),__FUNCTION__);
	tempBuff=malloc2(sz);
	if (tempBuff==NULL) {
		// エラーが発生したときはerrorNoにエラーコードを入れて返す
		// 規定コードに該当する物がないときはERR_IN_EXTERNAL_FUNCTIONにする
		errorNo=ERR_NO_WORKAREA; // メモリー不足
	}
}

// この中の関数の終了処理
static void _Fexit(void)
{
	printFunc();
	free2(tempBuff);
}

// インフォメーションテーブル
const
INFORMATION_TABLE	InfoExtendFuncs={
	#ifdef FUNC_DEBUG
	"Extend functions",	//"拡張関数群",
	#endif
	_Finit,		// Finit
	returnOnly,	// Frun
	returnOnly,	// Fend
	_Fexit,		// Fexit
	returnOnly,	// Fbreak
	NULL,		// FctrlD;未使用
	NULL,		// 予約1
	NULL,		// 予約2
	//
	extendTokens,
	extendParams,
	extendFuncExec
};

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