/*****************************************************************************/
/* ＳＴＫ外部コマンド：文字列 */
/*****************************************************************************/

#include <string.h>
#include "defines.h"
#include "stk.h"

/*****************************************************************************/

static int Sstrcpy(NSTACK nstk[],int mode)
// 文字列コピー・結合
{
long len;
	switch (mode) {
	    case 1: // EOS結合 : des(1:NADRS) src(0:NADRS/NSTR1) strcat
		// desをEOSまで飛ばして、それがdes領域を越えるならｴﾗｰ
		len=strlen(Cadrs(NN1));
		if (ARYsize(&NS1)<len) return(ARSZOVER);
		NN1+=len; // desをEOSまで飛ばす
		// 後はstrcpyと同じ
	    case 0: // EOSｺﾋﾟｰ : des(1:NADRS) src(0:NADRS/NSTR1) strcpy
		len=strlen(Cadrs(NN0))+1; // +1 for EOS
		break;
	    case 2: // 指定ｻｲｽﾞ: len(2) des(1:NADRS) src(0:NADRS/NSTR1) memcpy
		// len<=0ならsrcサイズになる
		len=ARYSTRLen(&NS2,&NS0);
		break;
	}
	// des,srcの領域チェックはARYStoreAの中で行われる
	return(ARYStoreB(&NS1,Cadrs(NN0),len));
}

/*****************************************************************************/

static int Sstrcmp(NSTACK nstk[],int mode)
// 文字列比較
// return : 0=一致 , >0=desはsrcより大きい , <0=desはsrcより小さい
{
static int (*cmp[])()={ // 比較関数
	memcmp,memcmpi
};
unchar *src;
long len;
int ret=-1L; // ない＝srcの方が大きいの印
	// 領域アドレス
	src=Cadrs(NN0);
	// 比較サイズ
	switch (mode) {
		case 0: // EOS
		case 1: // des(1:NADRS/NSTR1) src(0:NADRS/NSTR1) strcmp? → ret(0)
			len=strlen(src)+1; // src EOS size (with EOS)
			break;
		case 2: // 指定サイズ
		case 3: // len(2) des(1:NADRS/NSTR1) src(0:NADRS/NSTR1) memcmp? → ret(0)
			// len<=0ならsrcサイズになる
			len=ARYSTRLen(&NS2,&NS0);
			// srcにそれだけのデータがあるか
			if (ARYSTRChkSize(&NS0,len)) { // 無ければ即不一致
				ret=1L; // desの方が大きいにする
				goto L1;
			}
	}
	// desにそれだけの領域があるか
	if (!ARYSTRChkSize(&NS1,len)) { // 有る時のみ
		// 比較
		ret=(cmp[mode&1])(Cadrs(NN1),src,len);
	} // ないときはsrcの方が大きいとする
    L1:;
	NN0=(long)ret;
	return(NOK);
}

/*****************************************************************************/

static int Sstring(NSTACK nstk[],int mode)
/* 文字列長・文字列数値化・サーチ */
{
unchar *str;
long ret;
	str=Cadrs(NN0);
	switch (mode) {
		// 文字列長
		case 0:	// EOSｻｲｽﾞ : str(NADRS/NSTR1:0) STRLEN → len(0)
			ret=strlen(str); // EOS
			break;
		case 1:	// 領域サイズ : str(NADRS/NSTR1:0) STRLENS → len(0)
			ret=ARYSTRSize(&NS0);
			break;
		
		// 文字列数値化
		case 2:	// str(NADRS/NSTR1:0) ATOI → num(0)
			{ int n;
			atoi3(str,&n,BIT15);
			ret=(long)n;
			}
			break;
		
		// 文字サーチ
		case 3:	// char(1) str(NADRS/NSTR1:0) KSTRCHAR → ret(0)
			ret=kstrchar(str,(unint)NN1);
			break;
		case 4:	// char(2) str(NADRS/NSTR1:1) len(0) MEMCHAR → ret(0)
			// len<=0ならsrcサイズになる
			{ unchar *des;
			str=Cadrs(NN1);
			des=memchr(str,(int)NN2,ARYSTRLen(&NS0,&NS1));
			ret=(des==NULL? -1:(long)(des-str));
			}
			break;
	}
	NN0=ret;
	return(NOK);
}

/*****************************************************************************/
/* コマンドテーブル */

STKCOM strtbl[]={
	 {NULL		,NULL	,TNONE,0,0}
	// 文字列コピー
	,{"STRCPY"	,Sstrcpy,TSTR1 TADRS ,0,0}	// EOSｺﾋﾟｰ
	,{"STRCAT"	,Sstrcpy,TSTR1 TADRS ,0,1}	// EOS結合
	,{"MEMCPY"	,Sstrcpy,TSTR1 TADRS TNUM,0,2}	// lenｺﾋﾟｰ
	// 文字列比較
	,{"STRCMP"	,Sstrcmp,TSTR1 TSTR1,1,0}	// EOS
	,{"STRCMPI"	,Sstrcmp,TSTR1 TSTR1,1,1}	// EOS:大小区別無し
	,{"MEMCMP"	,Sstrcmp,TSTR1 TSTR1 TNUM,1,2}	// len
	,{"MEMCMPI"	,Sstrcmp,TSTR1 TSTR1 TNUM,1,3}	// len:大小区別無し
	// 文字列長等
	,{"STRLEN"	,Sstring,TSTR1,1,0}		// EOS
	,{"STRLENS"	,Sstring,TSTR1,1,1}		// size
	,{"ATOI"	,Sstring,TSTR1,1,2}		// 文字列数値変換
	// 文字サーチ
	,{"KSTRCHAR"	,Sstring,TSTR1 TNUM,1,3}	// EOS:文字単位
	,{"MEMCHAR"	,Sstring,TNUM TSTR1 TNUM,1,4}	// len:byte単位
	,{NULL		,NULL	,TNONE,0,0}
};

/*****************************************************************************/
