//--------------------------------------------------------------------------------------
// サポート関数群
//--------------------------------------------------------------------------------------

#ifndef	__XB_SUPPORT__
#define __XB_SUPPORT__	1

#include "XBdefines.h"
#include "fdef.h"
#include <stdio.h>	// FILE *
#include <string.h>	// memcpy()
#include <stddef.h>	// offsetof() ; GCCではビルトインマクロだが、Xcodeではstddef.h内で定義される普通のマクロのようである

//--------------------------------------------------------------------------------------
// プロトタイプ宣言
//--------------------------------------------------------------------------------------

int		getRGBColorFromFac(FAC fac[],int i,int *r,int *g,int *b,int *alpha);
UByte	*strWithUTF8no(UByte *str,int no);
#define	bstrWithUTF8no(str,no)	((char *)strWithUTF8no(str,no))
#define	strWithUTF8(str)	strWithUTF8no(str,0)
#define	bstrWithUTF8(str)	bstrWithUTF8no(str,0)
void	*pointerAdd(void *p,size_t size);
uwCODE *writeOfstAdrs(uwCODE *wp,uwCODE *adrs);
UWord	rolw(UWord w,int cnt);
int		fgets2(UByte *buff,int max,FILE *fp);
void	returnOnly(void);
int		makeNormalFloatString(UByte *tmp,double d);
int		makeFloatString(double d,int seisuu,int shousuu,UByte *tmp,UByte *tmp2,UWord formatFlag);

#if defined(INTERNAL_TRACE)||defined(DEBUG)
void	openFputCode(char *mes);
void	closeFputCode(void);
void	fputCodeW(uwCODE wp);
void	fputCodeL(ULong  lp);
void	fputFileLine(char *file,int line);
void	fnslog(char *str);	// ファイル出力+nslog
void	fnslog2(char *str);	// ファイル出力のみ
FILE 	*getinfp();
#else
#define	openFputCode(mes)
#define	closeFputCode()
#define	fputCodeW(wp)
#define	fputCodeL(lp)
#define	fputFileLine(file,line)
#define	fnslog(str)
#define	fnslog2(str)
#define	getinfp()	NULL
#endif

psize_t	calcAdrsOffset(void *adrs1,void *adrs2);

void	storeInternalCode(uwCODE code);
void	storeInternalCodeWithOffsetN(uwCODE code,int ofst);
void	storeInternalCodeL(ULong ldata);
void	storeInternalCodeB(UByte c);
void	storeInternalCodeP(void *p);

uwCODE	_readInternalCodeN(void);
uwCODE	_readInternalCode(void);
ULong	_readInternalCodeLN(void);
ULong	_readInternalCodeL(void);
psize_t	_readInternalCodePN(void);
void 	readInternalAbsoluteAdrs(void);

#ifdef INTERNAL_TRACE	// 中間コード出力付き
#define	readInternalCodeN()		(fputFileLine(__FILE__,__LINE__),_readInternalCodeN())
#define	readInternalCode()		(fputFileLine(__FILE__,__LINE__),_readInternalCode())
#define	readInternalCodeLN()	(fputFileLine(__FILE__,__LINE__),_readInternalCodeLN())
#define	readInternalCodeL()		(fputFileLine(__FILE__,__LINE__),_readInternalCodeL())
#define	readInternalCodePN()	(fputFileLine(__FILE__,__LINE__),_readInternalCodePN())
#else	// 本番
#define	readInternalCodeN()		_readInternalCodeN()
#define	readInternalCode()		_readInternalCode()
#define	readInternalCodeLN()	_readInternalCodeLN()
#define	readInternalCodeL()		_readInternalCodeL()
#define	readInternalCodePN()	_readInternalCodePN()
#endif

//--------------------------------------------------------------------------------------
// define関数
//--------------------------------------------------------------------------------------

#define	selectMessageJE(mesE,mesJ)	(operationStatus.fenglish? (mesE):(mesJ))	// 日英メッセージ選択
#define	c2basicYESNO(flag)			((flag)==NO? BASIC_NO:BASIC_YES)	// Cの真偽値をBASICのそれに変換する
#define	basic2cYESNO(flag)			((flag)!=BASIC_NO)					// BASICの真偽値をCのそれに変換する

#ifdef CORE_DEBUG
	#ifdef DOS
		#define	prints(tmp)	fputs((const char *)(tmp),stdout),fputs((const char *)(tmp),stderr),fflush(stdout),fflush(stderr)	// fflush()がないと表示が出ないので注意
	#else
		UByte	*input(int keyType);	// どこかで実装する
		BOOL 	printus(UByte *str);	// どこかで実装する
		#define prints(s)	printus((UByte *)s)
	#endif
	#define	free(mem)	printf("free(%p)\n",mem),fflush(stdout),free(mem)
#else	// 式の二重評価をしないように気をつけること
	#ifdef DOS
		#define	prints(tmp)	fputs((const char *)(tmp),stdout),fflush(stdout)	// fflush()がないと表示が出ないので注意
	#else
		UByte	*input(int keyType);	// どこかで実装する
		BOOL	printus(UByte *str);	// どこかで実装する
		#define prints(s)	printus((UByte *)s)
	#endif

	// free()は本番時はオリジナルに任せる
#endif

// MATH型＋次元から次元数だけを取り出す
#define	_getJigen(prm)		(prm&0x0f)
// MATH型＋次元からMATH型だけを取り出す
#define	getMathType(prm)	(prm&0xff00)

// .wpにofstを.wサイズで計算する
#define	withWord(ofst)		((ofst)/SZ_WORD)

// .lpにofstを.lサイズで計算する
#define	withLong(ofst)		((ofst)/SZ_LONG)

// 4バイト境界化
#define	quadBoundary(size)	((((size)+SZ_LONG-1)/SZ_LONG)*SZ_LONG)

// 64bitでも8バイト境界化する必要はなさそう
//#define	quadBoundary(size)	((((size)+SZ_LLONG-1)/SZ_LLONG)*SZ_LLONG)

//---------------------------------------------
// 型違いによる警告を回避するための定義

#define	bstrlen(str)	strlen((char *)str)

//--------------------------------------------------------------------------------------
// デバッグ専用関数定義
//--------------------------------------------------------------------------------------
// 2つのデバッグモードを実装するため、2種類ある
// 式を二重評価する物は関数にて実装すること

#if defined(CORE_DEBUG)||defined(CORE_DEBUG2)
#define	_f()	fflush(stdout)
#endif
#if !defined(CORE_DEBUG) && !defined(CORE_DEBUG2)
#define	_f()
#endif

// これはデバッグ用printfと本番用printfを識別するための物。
// CORE_DEBUGでくくられた中もこれを使うこと。
// 逆に言えば、CORE_DEBUGでくくらないと消えないので注意。
#define	DBG_printf	printf

#if COMPILE_MODE!=2 // Distributionの時は外す
void DBGprintName(UByte *name,swStrLEN len);
#else
#define	DBGprintName(name,len)	// 本番時は消す
#endif

#ifdef CORE_DEBUG
void DBG_printCode(uwCODE code);
void DBG_printName(UByte *name,swStrLEN len);
void DBG_dump2(char *fname,void *top,int size,char *mode);
void DBG_dumpNames(void);
void DBG_dumpNest(void);
// 表示系は、即表示させるためfflush()している
#define	DBG_printsn(s)				printf(s "\n"),fflush(stdout)
#define	DBG_prints(s)				printf(s),fflush(stdout)
#define	DBG_printf1(s,p1)			printf(s,(p1)),fflush(stdout)
#define	DBG_printf2(s,p1,p2)		printf(s,(p1),(p2)),fflush(stdout)
#define	DBG_printf3(s,p1,p2,p3)		printf(s,(p1),(p2),(p3)),fflush(stdout)
#define	DBG_printf4(s,p1,p2,p3,p4)	printf(s,(p1),(p2),(p3),(p4)),fflush(stdout)
#define	DBG_Func()					DBG_printf1("%s\n",__FUNCTION__)
#define	DBG_Func2(mes)				DBG_printf1("%s" mes "\n",__FUNCTION__)
#else	// 本番時はすべて消す
#define	DBG_printsn(s)
#define	DBG_prints(s)
#define	DBG_printf1(s,p1)
#define	DBG_printf2(s,p1,p2)
#define	DBG_printf3(s,p1,p2,p3)
#define	DBG_printf4(s,p1,p2,p3,p4)
#define	DBG_printCode(code)
#define	DBG_printName(name,len)
#define	DBG_dump2(fname,top,size,mode)
#define	DBG_dumpNames()
#define	DBG_dumpNest()
#define	DBG_Func()
#define	DBG_Func2(mes)
#endif
#define DBG_dump(fname,top,size)	DBG_dump2(fname,top,size,"w")


#ifdef CORE_DEBUG2
#define	DBG2_printsn(s)				printf(s "\n"),fflush(stdout)
#define	DBG2_prints(s)				printf(s),fflush(stdout)
#define	DBG2_printf1(s,p1)			printf(s,(p1)),fflush(stdout)
#define	DBG2_printf2(s,p1,p2)		printf(s,(p1),(p2)),fflush(stdout)
#define	DBG2_printf3(s,p1,p2,p3)	printf(s,(p1),(p2),(p3)),fflush(stdout)
#define	DBG2_printf4(s,p1,p2,p3,p4)	printf(s,(p1),(p2),(p3),(p4)),fflush(stdout)
#define	DBG2_printName(name,len)	DBG_printName(name,len)
#define	DBG2_dump2(fname,top,size,mode)	DBG_dump2(fname,top,size,mode)
#define	DBG2_dumpNames()			DBG_dumpNames()
#define	DBG2_dumpNest()				DBG_dumpNest()
#define	DBG2_Func()					DBG_printf1("%s\n",__FUNCTION__)
#define	DBG2_Func2(mes)				DBG_printf1("%s" mes "\n",__FUNCTION__)
#else
#define	DBG2_printsn(s)
#define	DBG2_prints(s)
#define	DBG2_printf1(s,p1)
#define	DBG2_printf2(s,p1,p2)
#define	DBG2_printf3(s,p1,p2,p3)
#define	DBG2_printf4(s,p1,p2,p3,p4)
#define	DBG2_printCode(code)
#define	DBG2_printName(name,len)
#define	DBG2_dump2(fname,top,size,mode)
#define	DBG2_dumpNames()
#define	DBG2_dumpNest()
#define	DBG2_Func()
#define	DBG2_Func2()
//
#define	DBG2_printChainListWconnected(chain,title)
#define	DBG2_printChainListW(chain,title)
#define	DBG2_printChainListL(chain,title)
#endif
#define DBG2_dump(fname,top,size)	DBG_dump2(fname,top,size,"w")

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

#endif
