//==============================================================================================================================
//	スクリプトリストアップ
//
//
//==============================================================================================================================
#define	SW_MODULE_LISTUPSCR

#define		MAXSTRING		256
#define		SCR_ENTRYMAX		1024
#define		FLG_ENTRYMAX		1024
#define		LAB_ENTRYMAX		16384
#define		ETC_ENTRYMAX		32768	//10240

//------------------------------------------------------------------
//		スクリプトコマンドクラス
//------------------------------------------------------------------
class LISTUPSCR
{
	BOOL		m_bInitialized;
	BOOL		m_bImplemented;
	BOOL		m_FullInit;
	
	TCHAR		*m_pScripts;
	TCHAR		*m_pFlags;
	TCHAR		*m_pLabels;
	TCHAR		*m_pEtcs;
	
	int			m_iEntryScripts;
	int			m_iEntryFlags;
	int			m_iEntryLabels;
	int			m_iEntryEtcs;
	
	void		Initialize();
	int			entry_string( LPTSTR _buff, const int entry, const int emax, LPCTSTR str );
	void		entry_sort( LPTSTR _buff, const int entry );
	
public:
	int			Func( LPCTSTR _sParamString );
//	int			Func(char *path,char *outname);
	void		Quit( BOOL _bExit );
	
	LISTUPSCR();
	~LISTUPSCR();
	
};

//	アプリケーション起動時
LISTUPSCR::LISTUPSCR()
	: m_FullInit( FALSE )
	, m_bInitialized( FALSE )
	, m_bImplemented( FALSE )
	, m_pScripts( NULL )
	, m_pFlags( NULL )
	, m_pLabels( NULL )
	, m_pEtcs( NULL )
	, m_iEntryScripts( 0 )
	, m_iEntryFlags( 0 )
	, m_iEntryLabels( 0 )
	, m_iEntryEtcs( 0 )
{
}
//	アプリケーション終了時
LISTUPSCR::~LISTUPSCR()
{
}


//==============================================================================================================================================
//	初期化と開放
//		1ファイルに1つの処理でコンプリートするような場合は修正する必要ありません
//		注釈となっている Message_printf を有効にして sample.swb を実行すると動きがよく分かると思います。
//==============================================================================================================================================

//------------------------------------------------------------------
//		スクリプトコマンドの初期化
//			(特に必要ないなら変更の必要なし)
//------------------------------------------------------------------
void	LISTUPSCR::Initialize()
{
	if(m_bInitialized == TRUE)	return;
	m_bInitialized = TRUE;	//	初期済みフラグ
	
	if(m_FullInit == FALSE){
		m_FullInit = TRUE;
		//	全体を通して一度しか行わない初期化
		
		//Message_printf(TEXT("全体の初期化"));
		
		
	}
	
	//	初期化処理
	//	１つのバッチに同じスクリプトが２度指定されていたならここには２度来る
	//Message_printf(TEXT("初期化"));
	
	mem_alloc( TCHAR, m_pScripts,	MAXSTRING * SCR_ENTRYMAX );
	mem_alloc( TCHAR, m_pFlags,		MAXSTRING * FLG_ENTRYMAX );
	mem_alloc( TCHAR, m_pLabels,	MAXSTRING * LAB_ENTRYMAX );
	mem_alloc( TCHAR, m_pEtcs,		MAXSTRING * ETC_ENTRYMAX );
	
	m_iEntryScripts = 
	m_iEntryFlags = 
	m_iEntryLabels = 
	m_iEntryEtcs = 0;
	
}

//------------------------------------------------------------------
//		スクリプトコマンドの終了
//			(特に必要ないなら変更の必要なし)
//------------------------------------------------------------------
void	LISTUPSCR::Quit( BOOL _bExit )
{
	int		ii;
	
	//	ここにはスクリプトを使っていなくても来るので注意
	
	if(m_bImplemented == FALSE)	return;		//	変換処理が実行されていないなら帰還
	m_bImplemented = FALSE;
	m_bInitialized = FALSE;
	
	//	終了処理
	//Message_printf(TEXT("完了"));
	
	entry_sort( m_pScripts,	m_iEntryScripts);
	entry_sort( m_pFlags,	m_iEntryFlags);
	entry_sort( m_pLabels,	m_iEntryLabels);
	entry_sort( m_pEtcs,	m_iEntryEtcs);
	
	
	Message_printf( TEXT("●script(s) %d entry"),  m_iEntryScripts );
	for(ii=0 ; ii<m_iEntryScripts ; ii++){
		Message_printf( m_pScripts + ii*MAXSTRING );
	}
	Message_printf( TEXT("\n\n●flag(s) %d entry"), m_iEntryFlags );
	for(ii=0 ; ii<m_iEntryFlags ; ii++){
		Message_printf( m_pFlags + ii*MAXSTRING );
	}
	Message_printf( TEXT("\n\n●label(s) %d entry"), m_iEntryLabels );
	for(ii=0 ; ii<m_iEntryLabels ; ii++){
		Message_printf( m_pLabels + ii*MAXSTRING );
	}
	Message_printf( TEXT("\n\n●etc(s) %d entry"), m_iEntryEtcs );
	for(ii=0 ; ii<m_iEntryEtcs ; ii++){
		Message_printf( m_pEtcs + ii*MAXSTRING );
	}
	
	mem_del( m_pScripts );
	mem_del( m_pFlags );
	mem_del( m_pLabels );
	mem_del( m_pEtcs );
	
	if( _bExit == TRUE )
	{
		//	次のスクリプトは存在しない、完全な終了
		//	１つのバッチに同じスクリプトに別パラメータを渡しての処理で
		//	逐一結果を出さず、全体で統合して結果を出したい場合などはここで
		
		//Message_printf(TEXT("終了"));
		
	}
	
}


//		
void	LISTUPSCR::entry_sort( LPTSTR _buff, const int entry )
{
	int			ii, jj;
	
	for( ii=0 ; ii<entry-1 ; ii++ )
		for( jj=ii ; jj<entry ; jj++ )
		{
			if( STRING_cmp( _buff+ii*MAXSTRING, _buff+jj*MAXSTRING ) > 0 )	_swap( _buff+ii*MAXSTRING, _buff+jj*MAXSTRING );
		}
	
}


//		
int		LISTUPSCR::entry_string( LPTSTR _buff, const int _entry, const int emax, LPCTSTR  _pStr )
{
	int			ii;
	int			entry = _entry;
	
	
	if(entry >= emax){
		Message_error( TEXT("Entry over.%s"), _pStr );
	}else{
		
		if( STRING_len(_pStr) > MAXSTRING){
			Message_error( TEXT("string over.%d"), STRING_len(_pStr) );
		}else{
			ii = 0;
			while(ii<entry){
				if( STRING_cmp( _buff + ii*MAXSTRING, _pStr) == 0 )	return entry;
				ii++;
			}
			
			STRING_cpy( _buff + entry*MAXSTRING, _pStr );
			entry++;
		}
	}
	
	return entry;
}


//		
int		chkword( LPCTSTR ptr, int off )
{
	TCHAR	stchk[] = TEXT(" \t\r\n()[]+-*/;:@,.!#$%&'=~|^\"{}?<>\\");
	int		ii;
	
	
	if(off == 0)	return TRUE;	//	先頭なら当然単語(タブなどはスキップされている事が前提)
	
	
	if(_ismbbtrail(*(ptr+off-1))!=0)	return FALSE;
	
	for(ii=0 ; ii<STRING_len(stchk) ; ii++)
		if(*(ptr+off-1) == stchk[ii])	return TRUE;
	
	return FALSE;
}


//		
int		getword( LPCTSTR ptr, LPTSTR temp )
{
	TCHAR	endchk[] = TEXT(" \t\r\n()[]+-*/;:,!#$%&'=~|^\"{}?<>");	//	chkword のものから .@\ を除去(ファイル名、アドレスに対応させるため)
	int		ii, jj, ff;
	
	
	for(jj=0 ; jj<STRING_len(ptr) ; jj++){
		ff = 0;
		for(ii=0 ; ii<STRING_len(endchk) ; ii++){
			if(ptr[jj] == endchk[ii]){	ff = 1;	break;}
		}
		if(ff==1)	break;
		
#ifndef	_UNICODE
		if( _ismbblead(ptr[jj]) != 0 ){		//	全角文字だ
			temp[jj] = ptr[jj];
			jj++;
		}
#endif
		temp[jj] = ptr[jj];
	}
	temp[jj] = 0;
	
	return jj;
}


//==============================================================================================================================================
//	変換処理部分
//==============================================================================================================================================

#define	LISTUPSCR_RANGE				//	このdefineを有効にすると範囲限定機能が有効になる

//------------------------------------------------------------------
//	変換フィルターサンプル　機能:無変換(ファイルコピー)
//			変換せず調査だけなら out に関する部分は不要
//------------------------------------------------------------------
int		LISTUPSCR::Func( LPCTSTR _sParamString ){
	CSwbParam	cParam( _sParamString );							///< パラメータ処理.
	
	TCHAR	temp[ 1024 ];
	TCHAR	*mem = NULL;
	int		ii,len,off;
	LPCTSTR	pPath;
//	LPCTSTR	pOutName;
	
	pPath    = cParam.GetPath();		///< ターゲットファイル (GetFilePath(0)としても同じ).
//	pOutName = cParam.GetString( 1 );
	
	
	Initialize();
	
	len = MEM_TextRead(&mem, pPath );
	if(len == 0)	return FALSE;		//	ファイルがない
	
	m_bImplemented = TRUE;	//	実行済みフラグ
	
	
	ii = 0;
	#ifdef	LISTUPSCR_RANGE
	cRange.Init(mem,len);						//範囲限定機能を有効にするにはこの初期化と
	while(cRange.Is(mem,ii,len))	ii++;		//　初回スキップ、下の[スキップ判定]が必要。スキップが必要な間trueが返りループしている
	#endif
	
	while(ii < len){
		#ifdef	LISTUPSCR_RANGE
		while(cRange.Is(mem,ii,len))	ii++;	//	スキップ判定
		#endif
		
		//	注釈をスキップ　// ; に対応
		if(	(*(mem+ii) == '/' && *(mem+ii+1) == '/') || *(mem+ii) == ';'){
			while( ii<len && *(mem+ii) != '\n')	ii++;
			ii++;
			continue;
		}
		
		//	範囲注釈
		if(*(mem+ii) == '/' && *(mem+ii+1) == '*'){
			while( ii<len && *(mem+ii) != '*' || *(mem+ii+1) != '/')	ii++;
			ii+=2;
			continue;
		}
#ifndef	_UNICODE
		if(	_ismbblead(*(mem+ii)) != 0 && _ismbbtrail(*(mem+ii+1)) != 0 ){
			while(_ismbblead(*(mem+ii)) != 0 && _ismbbtrail(*(mem+ii+1)) != 0 )	ii+=2;
			continue;
		}
#else
		if( STRING_IsMultiByte( *(mem+ii) ) ){
			while( ii<len && STRING_IsMultiByte( *(mem+ii) ) )	ii++;
			continue;
		}
#endif
		if(*(mem+ii) == '\t'){
			while( ii<len && *(mem+ii) == '\t')	ii++;
			continue;
		}
		if(*(mem+ii) == '\r'){
			while(ii<len &&  *(mem+ii) == '\r' && *(mem+ii+1) == '\n')	ii+=2;
			continue;
		}
		if(*(mem+ii) == '\n'){
			while(ii<len &&  *(mem+ii) == '\n')	ii++;
			continue;
		}
		
		
		if( chkword( mem, ii ) )
		{
			off = getword( mem+ii, temp );
			ii += off;
	//		_str(temp);
			
			if(off != 0){
				switch(*(mem+ii)){
					case '(':
						ii++;
						m_iEntryScripts = entry_string( m_pScripts, m_iEntryScripts, SCR_ENTRYMAX, temp );
						break;
					case '[':
						ii++;
						m_iEntryFlags   = entry_string( m_pFlags, m_iEntryFlags, FLG_ENTRYMAX, temp );
						break;
					case ':':
						ii++;
						m_iEntryLabels  = entry_string( m_pLabels, m_iEntryLabels, LAB_ENTRYMAX, temp );
						break;
					default:
						m_iEntryEtcs    = entry_string( m_pEtcs, m_iEntryEtcs, ETC_ENTRYMAX, temp );
						break;
				}
			}else
				ii++;
			
		}
		else
			ii++;
		
	}
	
	//	メモリを開放
	mem_del(mem);
	
	return TRUE;
}


LISTUPSCR	*pC_listupscr = NULL;

