/*****************************************************************************/
/* ＳＴＫ外部コマンド：ファイル */
/*****************************************************************************/

#include <stdio.h>
#include <io.h>
#include "defines.h"
#include "stk.h"

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

static int Sfile(NSTACK nstk[],int mode)
/* ファイル系処理 */
{
static int (*funcs[])()={
	/* int func(fp) */
	fclose,fgetc,feof,ferror,rewind
	/* rewind()は本来はvoidなのでここではWarningが出る */
};
FILE *fp; // fpはNNUM扱いされている
unchar *buff;
long ret,size;
	fp=(FILE *)NN0;
	switch (mode) {
	    case 0:// fp(0) FCLOSE → ret(0)  : 0=正常 , EOF=エラー
	    case 1:// fp(0) FGETC  → char(0) : 読み出した文字/EOF=ｴﾗｰ/ﾌｧｲﾙｴﾝﾄﾞ
	    case 2:// fp(0) FEOF   → stat(0) : 0=ファイル途中 , <>0=feof
	    case 3:// fp(0) FERROR → stat(0) : 0=エラー無し , <>0=エラー
	    case 4:// fp(0) FREWIND→ なし
		ret=(long)funcs[mode](fp);
		break;
	
	    // ftell/filelengthはlongを返すので上にまとめない
	    case 5:// fp(0) FTELL  → point(0): 0>=:正常 , EOF:エラー
		ret=ftell(fp);
		break;
	    case 6:// fp(0) FLENGTH→ len(0)
		ret=filelength(fileno(fp));
		break;
	
	    case 7:// size(2) point(1) fp(0) FSEEK → ret(0): 0:正常 , EOF:ｴﾗｰ
		ret=(long)(fseek(fp,NN2,(int)NN1)? EOF:0);
		break;
	    case 8:// char(1) fp(0) FPUTC → ret(0) : 0:正常 , EOF:エラー
		ret=(long)(fputc((int)NN1,fp)==EOF? EOF:0);
		break;
	
	    default:
	    { unchar *buff; long size;
		if (mode>=11) SwapStack(nstk,2,1); // buff(2) size(1) -> size(2) buff(1)
		if ((buff=Cadrs(NN1))==NULL) return(NULLERR);
		if (mode>=11) {
		    size=ARYSTRLen(&NS2,&NS1); // <=0なら元サイズ分
		    // 読み込むだけのワークエリアがあるか
		    // 実はFWRITEの元データサイズチェックもしている
		    if (ARYSTRChkSize(&NS1,size)) return(ARSZOVER);
		}
		switch (mode) {
		    case 9:// fp VAR fname(NADRS/NSTR1:1) mode(NADRS/NSTR1:0) FOPEN =
			{ unchar *md;
			if ((md=Cadrs(NN0))==NULL) return(NULLERR);
			fp=fopen(buff,md);
			ret=(fp==NULL? EOF:(long)fp); // >=0:正常 , EOF:エラー
			}
			break;
		
		    case 10:// buff(NADRS/NSTR1:1) fp(0) FPUTS → ret(0): 0:正常 , EOF:ｴﾗｰ
			ret=(long)(fputs(buff,fp)? EOF:0);
			break;
		
		    case 11:// buff(NADRS/NSTR1:2) size(1) fp(0) FWRITE → ret(0)
			/* =size:正常 , <size:エラー */
			ret=(long)fwrite(buff,1,(int)size,fp);
			break;
		
		    case 12:// buff(NADRS:2) size(1) fp(0) FREAD → ret(0)
			/* =size:正常 , <size:エラー */
			ret=(long)fread(buff,1,(int)size,fp);
			break;
		
		    case 13:// buff(NADRS:2) size(1) fp(0) FGETS → ret(0)
			/* 0:正常 , EOF:エラー */
			ret=(long)(fgets(buff,(int)size,fp)==NULL? EOF:0);
			break;
		}
	    }
	}
	NN0=ret;
	return(NOK);
}

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

static int Sfconst(NSTACK nstk[],int mode)
/* ファイル系定数 */
{
static int fconst[]={
	 EOF,SEEK_CUR,SEEK_END,SEEK_SET
};
	NN0=(long)fconst[mode];
	return(NOK);
}

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

static int Sfend()
/* 終了時処理 */
{
	fcloseall();
	return(OK);
}

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

STKCOM filtbl[]={
	 {NULL		,NULL	,TNONE,0,0}
	,{"FCLOSE"	,Sfile	,TNUM ,1,0}
	,{"FGETC"	,Sfile	,TNUM ,1,1}
	,{"FEOF"	,Sfile	,TNUM ,1,2}
	,{"FERROR"	,Sfile	,TNUM ,1,3}
	,{"FREWIND"	,Sfile	,TNUM ,0,4}
	//
	,{"FTELL"	,Sfile	,TNUM ,1,5}
	,{"FLENGTH"	,Sfile	,TNUM ,1,6}
	,{"FSEEK"	,Sfile	,TNUM TNUM TNUM,1,7}
	,{"FPUTC"	,Sfile	,TNUM TNUM,1,8}
	,{"FOPEN"	,Sfile	,TSTR1 TSTR1,1,9}
	,{"FPUTS"	,Sfile	,TNUM TSTR1,1,10}
	,{"FWRITE"	,Sfile	,TNUM TNUM TSTR1,1,11}
	,{"FREAD"	,Sfile	,TNUM TNUM TADRS,1,12}
	,{"FGETS"	,Sfile	,TNUM TNUM TADRS,1,13}
	/* 定数 */
	,{"EOF"		,Sfconst,TNONE,1,0}
	,{"SEEK_CUR"	,Sfconst,TNONE,1,1}
	,{"SEEK_END"	,Sfconst,TNONE,1,2}
	,{"SEEK_SET"	,Sfconst,TNONE,1,3}
	,{NULL		,Sfend	,TNONE,0,0}	/* 終了時処理が必要 */
};

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