#include "app.h"
/****************************************************************************
 *	
 ****************************************************************************/
__declspec(noreturn) static void usage();
static void dumpKeyBody(int indent, const unsigned char* keyBody);
static void printIndent(int indent, const char* fmt, ...);
/****************************************************************************
 *	
 ****************************************************************************/
int main(int argc, char* argv[]) {
	FILE* fp;
	void* buf;
	int opt, len;
	//コマンドラインオプションを処理する。
	opterr = 0; //オプションエラーは当プログラム内で処理するので、getopt()内でのエラー表示は不要。
	while((opt = getopt(argc, argv, "h")) != -1) {
		switch(opt) {
		case 'h':
		default:
			usage();
		}
	}
	//レジストリテーブルのバイナリデータを読み込む。
	if(optind != (argc - 1)) { usage(); }	//引数の数が不正
	fp = fopen(argv[optind], "rb");
	fseek(fp, 0, SEEK_END);
	len = ftell(fp);
	rewind(fp);
	buf = malloc(len);
	if(!buf) { DIE(); }	//メモリ不足
	fread(buf, 1, len, fp);
	fclose(fp);
	//レジストリテーブルをダンプする。
	dumpKeyBody(0, buf);
	return EXIT_SUCCESS;
}
/*---------------------------------------------------------------------------*/
__declspec(noreturn) static void usage() {
	fprintf(stderr, "dRegTblD - レジストリテーブル逆コンパイラ (%s)\n", VERSION);
	fprintf(stderr, "Copyright (C) 2015 Naoyuki Sawa\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "USAGE:\n");
	fprintf(stderr, "  dRegTblD [option] RegTbl.bin\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "OPTIONS:\n");
	fprintf(stderr, "  -h 使い方を表示します。\n");
	exit(EXIT_FAILURE);
}
/*--------------------------------------------------------------------------*/
static void dumpKeyBody(int indent, const unsigned char* keyBody) {
	//--- キー ---
	{
		int nKey, keyName, keyBodyDist;
		nKey      = *keyBody++;				//┐
		nKey    <<= 8;					//├符号無し16ビット,ビッグエンディアン
		nKey     |= *keyBody++;				//┘
		while(--nKey >= 0) {
			keyName       =       *keyBody++;	//┐
			keyName     <<= 8;			//├符号無し16ビット,ビッグエンディアン
			keyName      |=       *keyBody++;	//┘
			keyBodyDist   = (char)*keyBody++;	//┐
			keyBodyDist <<= 8;			//│
			keyBodyDist  |=       *keyBody++;	//├符号有り24ビット,ビッグエンディアン
			keyBodyDist <<= 8;			//│
			keyBodyDist  |=       *keyBody++;	//┘
			printIndent(indent, "%u", keyName);
			dumpKeyBody(indent + 1, keyBody + keyBodyDist);
			printIndent(indent, "end");
		}
	}
	//--- 値 ---
	{
		int nValue, valueName, valueData;
		nValue    = *keyBody++;				//┐
		nValue  <<= 8;					//├符号無し16ビット,ビッグエンディアン
		nValue   |= *keyBody++;				//┘
		while(--nValue >= 0) {
			valueName     =       *keyBody++;	//┐
			valueName   <<= 8;			//├符号無し16ビット,ビッグエンディアン
			valueName    |=       *keyBody++;	//┘
			valueData     =       *keyBody++;	//┐
			valueData   <<= 8;			//├符号無し16ビット,ビッグエンディアン
			valueData    |=       *keyBody++;	//┘
			printIndent(indent, "%u\t=\t%u", valueName, valueData);
		}
	}
	//--- 文字列 ---
	{
		int nString, stringName, stringDist;
		nString   = *keyBody++;				//┐
		nString <<= 8;					//├符号無し16ビット,ビッグエンディアン
		nString  |= *keyBody++;				//┘
		while(--nString >= 0) {
			stringName    =       *keyBody++;	//┐
			stringName  <<= 8;			//├符号無し16ビット,ビッグエンディアン
			stringName   |=       *keyBody++;	//┘
			stringDist    = (char)*keyBody++;	//┐
			stringDist  <<= 8;			//│
			stringDist   |=       *keyBody++;	//├符号有り24ビット,ビッグエンディアン
			stringDist  <<= 8;			//│
			stringDist   |=       *keyBody++;	//┘
			printIndent(indent, "%u\t=\t\"%s\"", stringName, keyBody + stringDist);
		}
	}
}
/*--------------------------------------------------------------------------*/
static void printIndent(int indent, const char* fmt, ...) {
	va_list ap;
	while(--indent >= 0) { putchar('\t'); }
	va_start(ap, fmt);
	vprintf(fmt, ap);
	va_end(ap);
	putchar('\n');
}
