// File: /workspace/github_cpp_makefile_star2_O3/exrd[P]neteruhsp/neteruhsp/main.cc
// Function: main
int main( int argc, const char* argv[] )
{
	using namespace neteruhsp;

	// オプション
	bool has_error = false;
	const char* filename = nullptr;
	bool show_script = false;
	bool show_preprocessed_script = false;
	bool show_ast = false;
	bool show_execute_code = false;
	bool show_help = false;

	// オプション解析
	for( int i=1/* 0飛ばし */; i<argc; ++i )
	{
		const auto arg = argv[i];
		if ( arg[0] == '-' )
		{
			switch( arg[1] )
			{
				case 'f':
					if ( i+1 < argc )
					{
						++i;
						filename = argv[i];
					}
					else
					{
						fprintf( stderr, "ERROR : cannot read script file path\n" );
						has_error = true;
					}
					break;
				case 's':
					show_script = true;
					break;
				case 'p':
					show_preprocessed_script = true;
					break;
				case 'a':
					show_ast = true;
					break;
				case 'e':
					show_execute_code = true;
					break;
				case 'h':
					show_help = true;
					break;
				default:
					fprintf( stderr, "ERROR : unknown argument :%s\n", arg );
					has_error = true;
					break;
			}
		}
		else
		{
			fprintf( stderr, "ERROR : cannot parse argument :%s\n", arg );
			has_error = true;
			break;
		}
	}

	if ( filename == nullptr )
	{
		fprintf( stderr, "ERROR : have to specify script file\n" );
		has_error = true;
	}

	if ( show_help || has_error )
	{
		printf(
			"neteruhsp : commandline tool options\n"
			"  <bin> [<options>...] -f <SCRIPT_FILE>\n"
			"    -f : specify file path to execute\n"
			"\n"
			"  options are followings\n"
			"    -s : show loaded script file contents\n"
			"    -p : show preprocessed script contents\n"
			"    -a : show abstract-syntax-tree constructed from loaded script\n"
			"    -e : show instruction code for execution\n"
			"    -h : show (this) help\n"
		);
		fflush( stdout );
		fflush( stderr );
		return ( has_error ? -1 : 0 );
	}

	// システムここから
	initialize_system();

	// ファイル読み込み
	size_t script_size = 0;
	char* script = nullptr;
	{
		FILE* file = fopen( filename, "r" );
		if ( file == nullptr )
		{
			printf( "ERROR : cannot read such file %s\n", filename );
			return -1;
		}

		fseek( file, 0, SEEK_END );
		const size_t initial_size = ftell( file );

		size_t buffer_size = initial_size +4;// 初期バッファ
		script = reinterpret_cast<char*>( xmalloc( buffer_size +1 ) );

		fseek( file, 0, SEEK_SET );

		for( ; ; )
		{
			const auto c = fgetc(file);
			if ( c == EOF )
			{ break; }

			const auto ch = static_cast<char>( c );
			if ( buffer_size <= script_size )
			{
				buffer_size *= 2;
				script = reinterpret_cast<char*>( xrealloc( script, buffer_size ) );
			}
			script[script_size++] = ch;
		}
		script[script_size] = '\0';

		fclose( file );
	}
	assert( script != nullptr );

	if ( show_script )
	{
		printf( "====LOADED SCRIPT FILE(%d bytes)\n----begin----\n%s\n----end----\n", static_cast<int>( script_size ), script );
	}

	// 実行
	{
		{
			auto env =create_execute_environment();

			load_arg_t la;
			la.dump_preprocessed_ = show_preprocessed_script;
			la.dump_ast_ = show_ast;
			load_script( env, script, &la );

			if ( show_execute_code )
			{
				printf( "====Instruction Code for execution\n" );
				dump_code( env->execute_code_ );
			}

			execute( env );
			destroy_execute_environment( env );
		}

		printf(
			"====\n"
			">>Execution finished, press ENTER key to exit\n"
		);
		fflush( stdout );
		getchar();
	}

	xfree( script );
	uninitialize_system();

	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
cmpl $0x2, %edi
jl 0x2795
movq %rsi, %r14
movl %edi, %ebp
movl $0x1, %r13d
xorl %r8d, %r8d
movq 0x13b08(%rip), %r11     # 0x15fe0
leaq 0x9b25(%rip), %r12      # 0xc004
xorl %r15d, %r15d
xorl %r9d, %r9d
xorl %edi, %edi
xorl %ebx, %ebx
xorl %r10d, %r10d
xorl %esi, %esi
movslq %r13d, %rax
movq (%r14,%rax,8), %rdx
cmpb $0x2d, (%rdx)
jne 0x25e6
movzbl 0x1(%rdx), %eax
leal -0x61(%rax), %ecx
cmpl $0x7, %ecx
ja 0x2517
movslq (%r12,%rcx,4), %rax
addq %r12, %rax
jmpq *%rax
movb $0x1, %bl
jmp 0x2547
cmpl $0x70, %eax
je 0x2544
cmpl $0x73, %eax
jne 0x2554
movb $0x1, %r8b
jmp 0x2547
movb $0x1, %r10b
jmp 0x2547
leal 0x1(%r13), %eax
cmpl %ebp, %eax
jge 0x259b
movslq %eax, %rcx
movq (%r14,%rcx,8), %r9
movl %eax, %r13d
jmp 0x2547
movb $0x1, %sil
jmp 0x2547
movb $0x1, %dil
incl %r13d
cmpl %ebp, %r13d
jl 0x24ee
jmp 0x2618
movq %rdi, 0x8(%rsp)
movq (%r11), %rdi
movq %rbx, 0x10(%rsp)
movq %rsi, 0x18(%rsp)
leaq 0x9add(%rip), %rsi      # 0xc04a
xorl %eax, %eax
movq %r8, 0x28(%rsp)
movq %r9, %r15
movq %r10, 0x20(%rsp)
movq %r11, %rbx
callq 0x2230
movq %rbx, %r11
movq 0x20(%rsp), %r10
movq %r15, %r9
movq 0x28(%rsp), %r8
movq 0x8(%rsp), %rdi
jmp 0x25d4
movq %rbx, 0x10(%rsp)
movq %rsi, 0x18(%rsp)
movq %rdi, %rbx
movq %r8, 0x28(%rsp)
movq %r9, 0x8(%rsp)
movq %r10, 0x20(%rsp)
movq %r11, %r15
callq 0x22e0
movq %r15, %r11
movq 0x20(%rsp), %r10
movq 0x8(%rsp), %r9
movq 0x28(%rsp), %r8
movq %rbx, %rdi
movq 0x18(%rsp), %rsi
movq 0x10(%rsp), %rbx
movb $0x1, %r15b
jmp 0x2547
movq %rdi, %r12
movq (%r11), %rdi
movq %rsi, %r14
leaq 0x9a72(%rip), %rsi      # 0xc068
xorl %eax, %eax
movq %r8, %r13
movq %r9, %r15
movq %r10, %rbp
callq 0x2230
movq %rbp, %r10
movq %r15, %r9
movq %r13, %r8
movq %r12, %rdi
movq %r14, %rsi
movb $0x1, %r15b
testq %r9, %r9
je 0x2795
testb $0x1, %r10b
jne 0x279d
testb $0x1, %r15b
jne 0x279d
movq %r8, %r13
movq %rdi, 0x8(%rsp)
movq %rsi, 0x18(%rsp)
movq %r9, %r14
callq 0x27fc
leaq 0xa4e2(%rip), %rsi      # 0xcb33
movq %r14, %rdi
callq 0x2190
testq %rax, %rax
je 0x27e2
movq %rax, %r15
movq %rbx, 0x10(%rsp)
xorl %r14d, %r14d
movq %rax, %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0x2170
movq %r15, %rdi
callq 0x2030
movq %rax, %r12
leaq 0x5(%rax), %rdi
callq 0x287d
movq %rax, %rbx
movq %r15, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2170
movq %r15, %rdi
callq 0x2260
cmpl $-0x1, %eax
je 0x26e1
movl %eax, %ebp
addq $0x4, %r12
xorl %r14d, %r14d
cmpq %r14, %r12
ja 0x26cb
addq %r12, %r12
movq %rbx, %rdi
movq %r12, %rsi
callq 0x2920
movq %rax, %rbx
movb %bpl, (%rbx,%r14)
incq %r14
movq %r15, %rdi
callq 0x2260
movl %eax, %ebp
cmpl $-0x1, %eax
jne 0x26b5
movb $0x0, (%rbx,%r14)
movq %r15, %rdi
callq 0x2160
testb $0x1, %r13b
je 0x2708
leaq 0x99d7(%rip), %rdi      # 0xc0d2
movl %r14d, %esi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x2050
callq 0x7bd7
movq %rax, %r14
movq 0x8(%rsp), %r13
andb $0x1, %r13b
leaq 0x36(%rsp), %rdx
movb %r13b, (%rdx)
movq 0x10(%rsp), %rax
andb $0x1, %al
movb %al, 0x1(%rdx)
movq %r14, %rdi
movq %rbx, %rsi
callq 0x7dc2
testb $0x1, 0x18(%rsp)
je 0x2752
leaq 0x99cd(%rip), %rdi      # 0xc111
callq 0x2240
movq 0x20(%r14), %rdi
callq 0xba02
xorl %ebp, %ebp
movq %r14, %rdi
xorl %esi, %esi
callq 0x8ad0
movq %r14, %rdi
callq 0x7c48
leaq 0x99c7(%rip), %rdi      # 0xc134
callq 0x2240
movq 0x13847(%rip), %rax     # 0x15fc0
movq (%rax), %rdi
callq 0x2180
callq 0x2200
movq %rbx, %rdi
callq 0x291b
callq 0x2882
jmp 0x27d1
callq 0x22fc
movb $0x1, %r15b
leaq 0x99c3(%rip), %rdi      # 0xc167
callq 0x2240
movq 0x13810(%rip), %rax     # 0x15fc0
movq (%rax), %rdi
callq 0x2180
movq 0x13821(%rip), %rax     # 0x15fe0
movq (%rax), %rdi
callq 0x2180
andb $0x1, %r15b
movzbl %r15b, %ebp
negl %ebp
movl %ebp, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x98c7(%rip), %rdi      # 0xc0b0
movq %r14, %rsi
xorl %eax, %eax
callq 0x2050
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
jmp 0x27d1
nop