/*
 * CESHELL : シェルアプリケーション：バッチ関連ルーチン
 * Copyright(C) 1997-1999 Eiichiro Ito
 *
 * 1997/08/12:Eiichiro Ito
 *  (1) 作成開始
 * 修正履歴
 *
 */
#include	"conslib.h"
#include	"kctrl.h"
#include	"compat.h"
#include	"batch.h"

#define		MAX_ARG			10

TCHAR	RcPath[] = TEXT("\\autoexec.ce") ;
TCHAR	CurrentDir[ MAX_PATH ] = TEXT("\\") ;
TCHAR	Env_Path[ MAX_PATH ] = TEXT("\\") ;
TCHAR	Env_Param[ MAX_ARG ][ MAX_PATH ] ;

TCHAR	UnicodeStr[ 256 ] ;
char	SjisStr[ 256 ] ;
TCHAR	ArgRest[ 256 ] ;
TCHAR	FilePath[ 256 ] ;

extern	TCHAR	MessageBuf[] ;
extern	DWORD	command_main( LPTSTR restarg, BOOL f_batch ) ;

static	void	chop_crlf( char *buf ) ;
static	BOOL	goto_main( FILE *fp, LPCTSTR tag ) ;
static	BOOL	if_main( FILE *fp ) ;

BOOL
init_batch( void )
{
	if ( !InitKanjiControls() ) {
		wsprintf( UnicodeStr,
				  TEXT("KCTRL.DLL Initialize error\r\nError=%x"),
				  GetLastError() ) ;
		Cputs( UnicodeStr ) ;
		return FALSE ;
	}
	init_compat() ;
	batch_main( RcPath, TEXT("") ) ;
	return TRUE ;
}

void
release_batch( void )
{
	release_compat() ;
	ReleaseKanjiControls() ;
}

BOOL
check_real_path( LPCTSTR fn, LPCTSTR dir, LPTSTR path )
{
	DWORD	len ;
	LPCTSTR	ptr1, ptr2 ;

	if ( fexist_fileW( fn ) ) {
		wcscpy( path, fn ) ;
		return TRUE ;
	} else if ( *fn == TEXT('\\') ) {
		return FALSE ;
	}
	wcscpy( path, CurrentDir ) ;
	catdir( path, fn, NULL ) ;
	if ( fexist_fileW( path ) ) {
		return TRUE ;
	}
	ptr1 = dir ;
	while ( 1 ) {
		ptr2 = wcschr( ptr1, TEXT(';') ) ;
		if ( ptr2 ) {
			len = ptr2 - ptr1 ;
			wcsncpy( path, ptr1, len ) ;
			path[ len ] = 0 ;
			catdir( path, fn, NULL ) ;
			if ( fexist_fileW( path ) ) {
				return TRUE ;
			}
			ptr1 = ptr2 + 1 ;
		} else {
			wcscpy( path, ptr1 ) ;
			catdir( path, fn, NULL ) ;
			return fexist_fileW( path ) ;
		}
	}
}

void
init_var( LPCTSTR buf )
{
	DWORD	numarg, i ;

	wcscpy( UnicodeStr, buf ) ;
	cmdline2args( UnicodeStr, &Argc, Argv, Quote, NULL ) ;
	wcscpy( Env_Param[ 0 ], FilePath ) ;
	numarg = Argc > MAX_ARG ? MAX_ARG : Argc ;
	for ( i = 1 ; i < numarg ; i ++ ) {
		wcscpy( Env_Param[ i ], Argv[ i ] ) ;
	}
	for ( ; i < MAX_ARG ; i ++ ) {
		*Env_Param[ i ] = 0 ;
	}
}

void
ExpandParam( LPTSTR buf )
{
	DWORD	i ;
	TCHAR	var[ 10 ] ;

	for ( i = 0 ; i < MAX_ARG ; i ++ ) {
		wsprintf( var, TEXT("%%%d"), i ) ;
		ExpandVar( buf, var, Env_Param[ i ] ) ;
	}
}

BOOL
batch_main( LPCTSTR path, LPCTSTR args )
{
	FILE	*fp ;
	DWORD	ret ;

start:
	if ( !check_real_path( path, Env_Path, FilePath ) ) {
		return FALSE ;
	}
	init_var( args ) ;
	fp = fopenW( FilePath, TEXT("r") ) ;
	if ( fp == NULL ) {
		return FALSE ;
	}
	ResetBreak() ;
	while ( fgets( SjisStr, sizeof SjisStr, fp ) != 0 ) {
		if ( SleepWithBreak( 0 ) ) {
			break ;
		}
		chop_crlf( SjisStr ) ;
		switch ( *SjisStr ) {
		case ':':
		case '#':
		case 0:
			continue ;
		}
		sjis2unicode( SjisStr, UnicodeStr, sizeof UnicodeStr ) ;
		ExpandParam( UnicodeStr ) ;
		ExpandEnvVar( UnicodeStr ) ;
		cmdline2args( UnicodeStr, &Argc, Argv, Quote, ArgRest ) ;
		if ( !_wcsicmp( Argv[ 1 ], TEXT("goto") ) ) {
			if ( goto_main( fp, Argv[ 2 ] ) ) {
				continue ;
			} else {
				return TRUE ;
			}
		} else if ( !_wcsicmp( Argv[ 1 ], TEXT("if") ) ) {
			if ( if_main( fp ) ) {
				continue ;
			} else {
				return TRUE ;
			}
		}
		ret = command_main( ArgRest, TRUE ) ;
		if ( ret == 1 ) {
			break ;
		} else if ( ret == 2 ) {
			fclose( fp ) ;
			path = Argv[ 1 ] ;
			args = ArgRest ;
			goto start ;
		}
	}
	fclose( fp ) ;
	return TRUE ;
}

void
exec( LPCTSTR args )
{
	TCHAR			c ;
	DWORD			len, i ;
	LPTSTR			ptr ;
	LPCTSTR			pExecCmd, pExecParam ;
	static TCHAR	arg[ MAX_PATH ], tmp[ MAX_PATH ], tmp2[ MAX_PATH ] ;
	static TCHAR	tmp3[ MAX_PATH ] ;

	if ( !_wcsicmp( Argv[1], TEXT("start") ) ) {
#ifdef	_WIN32_WCE
		SHELLEXECUTEINFO		sei ;

		if ( !*args ) {
			wsprintf( MessageBuf,
					  TEXT("start document\n") ) ;
			Cputs( MessageBuf ) ;
			return ;
		}
		if ( *args == TEXT('"') ) {
			pExecCmd = arg ;
			pExecParam = NULL ;
			wcscpy( arg, &args[1] ) ;
			ptr = wcschr( arg, TEXT('"') ) ;
			if ( ptr ) {
				*ptr++ = TEXT('\0') ;
				while ( (c = *ptr) && (c == TEXT(' ')) ) {
					ptr ++ ;
				}
				pExecParam = ptr ;
			}
		} else {
			pExecCmd = args ;
			pExecParam = NULL ;
		}
		if ( *pExecCmd != TEXT('\\') ) {
			wcscpy( tmp, CurrentDir ) ;
			catdir( tmp, pExecCmd, NULL ) ;
			pExecCmd = tmp ;
		}
		memset( &sei, 0, sizeof sei ) ;
		sei.cbSize = sizeof sei ;
		sei.fMask = 0 ;
		sei.hwnd = NULL ;
		sei.lpVerb = TEXT("Open") ;
		sei.lpFile = pExecCmd ;
		sei.lpParameters = pExecParam ;
		sei.lpDirectory = NULL ;
		sei.nShow = SW_SHOW ;
		if ( !ShellExecuteEx( &sei ) ) {
			wsprintf( MessageBuf, TEXT("cannot start(%d)\n"),
					  GetLastError() ) ;
			Cputs( MessageBuf ) ;
		}
#endif	/* _WIN32_WCE */
	} else {
		wcscpy( tmp3, Argv[1] ) ;
		len = wcslen( tmp3 ) ;
		if ( len <= 4 || _wcsicmp( &tmp3[len-4], TEXT(".EXE") ) ) {
			wcscat( tmp3, TEXT(".EXE") ) ;
		}
		if ( !check_real_path( tmp3, Env_Path, FilePath ) ) {
			Cputs( tmp3 ) ;
			Cputs( TEXT(": not found\n") ) ;
			return ;
		}
		ptr = arg ;
		for ( i = 2 ; i < Argc ; i ++ ) {
			BOOL	fQuote = Quote[ i ] ;

			if ( i != 2 ) {
				*ptr++ = TEXT(' ') ;
			}
			wcscpy( tmp, Argv[ i ] ) ;
			ExpandEnvVar( tmp ) ;
			if ( tmp[0] == TEXT('.') && tmp[1] == TEXT('\\') ) {
				wcscpy( tmp2, CurrentDir ) ;
				catdir( tmp2, &tmp[2], NULL ) ;
				wcscpy( tmp, tmp2 ) ;
			}
			if ( fQuote ) {
				*ptr++ = TEXT('"') ;
			}
			wcscpy( ptr, tmp ) ;
			ptr += wcslen( ptr ) ;
			if ( fQuote ) {
				*ptr++ = TEXT('"') ;
			}
		}
		*ptr = 0 ;
		ResetBreak() ;
		if ( !ExecuteProcess( FilePath, arg ) ) {
			wsprintf( MessageBuf, TEXT("%s: cannot exec(%d)\n"),
					  FilePath, GetLastError() ) ;
			Cputs( MessageBuf ) ;
		}
	}
	GetCurDir( sizeof CurrentDir / sizeof (TCHAR), CurrentDir ) ;
}

static	void
chop_crlf( char *buf )
{
	char	*ptr ;

	ptr = strchr( buf, '\r' ) ;
	if ( ptr ) {
		*ptr = 0 ;
	}
	ptr = strchr( buf, '\n' ) ;
	if ( ptr ) {
		*ptr = 0 ;
	}
}

void
setenv_main( LPCTSTR args )
{
	DWORD	len ;
	LPCTSTR	ptr ;

	ptr = wcschr( args, TEXT('=') ) ;
	if ( !ptr ) {
		PrintEnvVar( Argc > 2 ? Argv[ 2 ] : NULL ) ;
		return ;
	}
	len = ptr - args ;
	wcsncpy( UnicodeStr, args, len ) ;
	UnicodeStr[ len ] = 0 ;
	SetEnvVar( UnicodeStr, ptr + 1 ) ;
	if ( !_wcsicmp( UnicodeStr, TEXT("PATH") ) ) {
		GetEnvVar( TEXT("PATH"), Env_Path, sizeof Env_Path / sizeof (TCHAR) ) ;
	} else if ( !_wcsicmp( UnicodeStr, TEXT("CD") ) ) {
		GetEnvVar( TEXT("CD"), CurrentDir, sizeof CurrentDir / sizeof (TCHAR) ) ;
	}
}

static	BOOL
goto_main( FILE *fp, LPCTSTR tag )
{
	fseek( fp, 0, 0 ) ;
	while ( fgets( SjisStr, sizeof SjisStr, fp ) != 0 ) {
		chop_crlf( SjisStr ) ;
		if ( *SjisStr != ':' ) {
			continue ;
		}
		sjis2unicode( &SjisStr[1], UnicodeStr, sizeof UnicodeStr ) ;
		if ( !_wcsicmp( UnicodeStr, tag ) ) {
			return TRUE ;
		}
	}
	Cputs( tag ) ;
	Cputs( TEXT(": invalid label\n") ) ;
	fclose( fp ) ;
	return FALSE ;
}

static	BOOL
if_main( FILE *fp )
{
	DWORD	idx = 2 ;
	BOOL	f_not = FALSE ;

	if ( !_wcsicmp( Argv[ idx ], TEXT("not") ) ) {
		f_not = TRUE ;
		idx ++ ;
	}
	if ( (Argc > idx + 2) && !_wcsicmp( Argv[ idx ], TEXT("exist") ) ) {
		if ( f_not ^ fexistW( Argv[ idx + 1 ] ) ) {
			idx += 2 ;
			goto exec_goto ;
		}
	} else if ( (Argc > idx + 3) && !_wcsicmp( Argv[ idx + 1 ], TEXT("==") ) ) {
		if ( f_not ^ !_wcsicmp( Argv[ idx ], Argv[ idx + 2 ] ) ) {
			idx += 3 ;
			goto exec_goto ;
		}
	} else {
		goto error ;
	}
	return TRUE ;

exec_goto:
	if ( _wcsicmp( Argv[ idx ], TEXT("goto") ) ) {
		fclose( fp ) ;
		Cputs( Argv[ idx ] ) ;
		Cputs( TEXT(": only GOTO allowed\n") ) ;
		return FALSE ;
	} else if ( Argc <= idx + 1 ) {
		goto error ;
	}
	return goto_main( fp, Argv[ idx + 1 ] ) ;

error:
	Cputs( TEXT("parameter error\n") ) ;
	fclose( fp ) ;
	return FALSE ;
}
