/* ==================
     import options
   ================== */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "MThdINFO.h"
#include "config.h"
#include "68lib.h"
#include "etc.h"
#include "structs.h"
#include "tempo.h"

#ifdef UNIXY_OS
	#define inpEXT ".zmd"
#else
	#define inpEXT ".ZMD"
#endif

extern void help(int exitcode);

FILEINFO option(int,char *argv[]);
FILEINFO supplement(FILEINFO);
int getnum(char **ptr);
void swerr(void);


/* ====================
     get command line
   ==================== */

FILEINFO option(int argc,char *argv[])
{
	int x;
	FILEINFO f;

	f.fadedelay = 0;	/* [do]-[loop] delay */
	f.fadespeed = 10;	/* [do]-[loop] fadeout speed */
	f.trkbuf = 16;		/* トラックバッファのサイズを初期化 */
	/* f.debug=0; */	/* デバッグスイッチは無効 */
	f.init = -1;		/* 「初期化コードを埋め込まない」よう初期化 */
	f.ABspc = 1;		/* オートベンドは１クロックごとに */
	f.run_status = 1;	/* ランニングステータスを使用する */
	f.looptime = 2;		/* [do]〜[loop]は２回ループに */

	f.timer = 0;		/* 使用タイマー＝TIMER B で初期化 */
	f.R = 0;			/* キーオフ処理は必ず行う */
	f.MDDdelta = 0;		/* no delta time for MDD */
	f.opmtrk = 0;		/* OPMトラックは変換しない */
	f.doloop = 0;		/* [do]〜[loop]の自動調整はしない */
	f.round = 0;		/* テンポ値補正(四捨五入)はしない */

	f.inpfile[0] = f.outfile[0] = f.sigfile[0] = '\0';

	if (argc == 1) {
#ifdef UNIXY_OS
		strcpy(f.inpfile,"-");
		strcpy(f.outfile,"-");
#else
		help(0);					/* boot program without any switch/sourcefile */
#endif
	} else {
		for (x = 1; x < argc; x++) {
//			char opt[65]; 
//			if ( strlen(argv[x]) > 64 ) { //deleted by Kobarin
			char opt[2048]; // added by Kobarin 
			if ( strlen(argv[x]) > sizeof(opt)-1 ) {//added by Kobarin
#ifndef ENGLISH
				ZTOMFormatMessage( stderr,"option:オプション文字列が長すぎます。\n");
#else
				ZTOMFormatMessage( stderr,"option:too long the switch-strings is!\n");
#endif
			}
			strcpy( opt,argv[x] );
#ifdef UNIXY_OS
			if ( opt[0] == '-') {	/* スイッチがあったら */
#else
			if ( opt[0] == '-' || opt[0] == '/' ) {	/* スイッチがあったら */
#endif
				char *ptr = strlwr(opt);
				ptr++;
				if (!*ptr) {						/* use standard input */
					if (!(f.inpfile[0])) {
						f.inpfile[0] = '-';
						f.inpfile[1] = '\0';
					} else {
#ifdef _0
						f.outfile[0] = '-';
						f.outfile[1] = '\0';
#endif
#ifndef ENGLISH
						fatal(1,"Error: 入力ファイルが多すぎます。\n");
#else
						fatal(1,"Error: too many sources are specified.\n");
#endif
					}
				}
				while (*ptr) {

					switch ( *ptr++ ) {
						case 'h':
						case '?':		/* 使用法表示 */
							help(0);
							break;
						case 'c':		/* 標準出力利用 */
							f.outfile[0] = '-';
							f.outfile[1] = '\0';
							break;
						case 'e':		/* エラー出力リダイレクト */
							if (*ptr) {
								freopen(ptr,"w",stderr);
								while (*ptr) ptr++;
							} else if (x + 1 < argc) {
								/* strcpy(f.outfile,argv[++x]); */
								freopen(argv[++x],"w",stderr);
							} else {
#ifndef ENGLISH
								ZTOMFormatMessage(stderr,"-e:ファイル名が指定されていません。\n");
#else
								ZTOMFormatMessage(stderr,"-e:no filename is specified.\n");
#endif
								help(1);
							}
							break;
						case 'g':		/* signatureファイル名指定 */
							if (*ptr) {
								strcpy(f.sigfile, ptr);
								while (*ptr) ptr++;
							} else if (x + 1 < argc) {
								strcpy(f.sigfile,argv[++x]);
							} else {
#ifndef ENGLISH
								ZTOMFormatMessage(stderr,"-g:ファイル名が指定されていません。\n");
#else
								ZTOMFormatMessage(stderr,"-g:no filename is specified.\n");
#endif
								help(1);
							}
							break;
						case 'o':		/* 出力ファイル名指定 */
							if (*ptr) {
								strcpy(f.outfile,ptr);
								while (*ptr) ptr++;
							} else if (x + 1 < argc) {
								strcpy(f.outfile,argv[++x]);
							} else {
#ifndef ENGLISH
								ZTOMFormatMessage(stderr,"-o:ファイル名が指定されていません。\n");
#else
								ZTOMFormatMessage(stderr,"-o:no filename is specified.\n");
#endif
								help(1);
							}
							break;
						case 't':		/* trkバッファ */
						case 'l':		/* loop回数 */
						case 'd':		/* delay */
							do {
								DWORD *var;

								if (*(ptr - 1) == 't') {
									var = &f.trkbuf;
								} else if (*(ptr - 1) == 'l') {
									var = &f.looptime;
								} else {
									var = &f.fadedelay;
								}

								if ( isdigit((int)*ptr) ) {
									*var = getnum(&ptr);
								} else {
#ifndef ENGLISH
									ZTOMFormatMessage(stderr,"%s:無効な数字を指定しました。\n",(ptr-2));
#else
									ZTOMFormatMessage(stderr,"%s:invalid number.\n",(ptr-2));
#endif
									help(1);
								}
							} while (0);
							break;
						case 'f':	/*char */
							if ( isdigit((int)*ptr) ) {
								f.fadespeed = getnum(&ptr);
							} else {
#ifndef ENGLISH
									ZTOMFormatMessage(stderr,"%s:無効な数字を指定しました。\n",(ptr-2));
#else
									ZTOMFormatMessage(stderr,"%s:invalid number.\n",(ptr-2));
#endif
								help(1);
							}
							if (f.fadespeed < 0) {
#ifndef ENGLISH
									ZTOMFormatMessage(stderr,"%s:数字が大きすぎます。\n",opt);
#else
									ZTOMFormatMessage(stderr,"%s:Too large the number is.\n",opt);
#endif
								help(1);
							}
							break;
						case 'b':
							if ( isdigit((int)*ptr) ) {
								f.ABspc = getnum(&ptr);
								if (f.ABspc == 0) {
#ifndef ENGLISH
									ZTOMFormatMessage(stderr,"%s:無効な数字を指定しました。\n",(ptr-2));
#else
									ZTOMFormatMessage(stderr,"%s:invalid number.\n",(ptr-2));
#endif
									help(1);
								}
							} else {
#ifndef ENGLISH
									ZTOMFormatMessage(stderr,"%s:無効な数字を指定しました。\n",(ptr-2));
#else
									ZTOMFormatMessage(stderr,"%s:invalid number.\n",(ptr-2));
#endif
								help(1);
							}
							if (f.ABspc < 0) {
#ifndef ENGLISH
								ZTOMFormatMessage(stderr,"%s:数字が大きすぎます。\n",opt);
#else
								ZTOMFormatMessage(stderr,"%s:Too large the number is.\n",opt);
#endif
								help(1);
							}
							break;

						case 'a':
							f.timer = 1;
							break;
						case 'u':
							f.round = 1;
							setTempoRoundMode(1);
							break;
						case 'j':
							f.doloop = 1;
							break;
						case 'm':
							f.opmtrk = 1;
							break;
						case 'i':		/* 初期化code */
							if ( isdigit((int)*ptr) ) {
								f.init = getnum(&ptr);
							} else {
								f.init = 0;
							}
							if (f.init < 0) {
#ifndef ENGLISH
								ZTOMFormatMessage(stderr,"%s:数字が大きすぎます。\n",opt);
#else
								ZTOMFormatMessage(stderr,"%s:Too large the number is.\n",opt);
#endif
								help(1);
							}
							break;
						case 'r':		/* @r on/off */
							if ( isdigit((int)*ptr) ) {
								f.R = getnum(&ptr);
								if (f.R < 0) {
#ifndef ENGLISH
								ZTOMFormatMessage(stderr,"%s:数字が大きすぎます。\n",opt);
#else
								ZTOMFormatMessage(stderr,"%s:Too large the number is.\n",opt);
#endif
									help(1);
								}
							} else {
								f.R = -1;
							}
							break;
						case 's':		/* running status off */
							f.run_status = 0;
							break;
						case 'x':
							if ( isdigit((int)*ptr) ) {
								f.MDDdelta = getnum(&ptr);
							} else {
#ifndef ENGLISH
								ZTOMFormatMessage(stderr,"%s:無効な数字を指定しました。\n",(ptr-2));
#else
								ZTOMFormatMessage(stderr,"%s:invalid number.\n",(ptr-2));
#endif
								help(1);
							}
							if (f.MDDdelta < 0) {
#ifndef ENGLISH
								ZTOMFormatMessage(stderr,"%s:数字が大きすぎます。\n",opt);
#else
								ZTOMFormatMessage(stderr,"%s:Too large the number is.\n",opt);
#endif
								help(1);
							}
							break;
						default:
#ifndef ENGLISH
							ZTOMFormatMessage(stderr,"%s:無効なスイッチを指定しました。\n",(ptr-1));
#else
							ZTOMFormatMessage(stderr,"%s:invalid option.\n",(ptr-1));
#endif
							help(1);
							break;
					}
				}
			} else {
				if (!f.inpfile[0]) {
					strcpy(f.inpfile,opt);
#ifdef _0
				} else if (!f.outfile[0]) {
					strcpy(f.outfile,opt);
#endif
				} else {
#ifndef ENGLISH
					ZTOMFormatMessage(stderr,"入力ファイルが３つ以上存在します。\n" );
#else
					ZTOMFormatMessage(stderr,"Too many source files are.\n");
#endif
				}
			}
		}
	}
	return f;
}


/* ========================
     ファイルネームの補間
   ======================== */

FILEINFO supplement(FILEINFO f)
{
	int x,y,z=0;
#ifdef UNIXY_OS
	char outEXT[5]={ '.','m','i','d',0 };
#else
	char outEXT[5]={ '.','M','I','D',0 };
#endif

	if ( !f.inpfile[0] ) 	{						/* ZMDファイルが無指定 */
#ifndef ENGLISH
		ZTOMFormatMessage( stderr,"入力ファイルを指定して下さい。\n" );
#else
		ZTOMFormatMessage(stderr,"Specify source file.\n");
#endif
		help(1);
	}
	if ( !f.outfile[0] ) {							/* MIDファイルが無指定 */
		strcpy(f.outfile,f.inpfile);				/* 取り敢えず入力file=出力fileにしておく */
		z = 1;										/* 出力ファイルが省略されていた旨のフラグ */
	}

	if ( f.outfile[0] > 'Z' ) {						/* ファイル名が小文字なら */
		strcpy(&outEXT[0],".mid");					/* 補間する拡張子も小文字 */
	}

	if ( f.outfile[strlen(f.outfile) - 1] == ':' ) {	/* 出力ドライブ名のみ指定 */
		for (x = 0; x <= (int)strlen(f.inpfile); x++) {
			if (f.inpfile[x] == ':') break;
		}
		if (x == (int)strlen(f.inpfile) + 1) {
			x = 0 - 1;
		}
		strcat(f.outfile,&f.inpfile[x + 1]);		/* 出力file名=出力drive名+filename */
	}

	for (x = strlen(f.inpfile)-1; x > 0; x--) {
		if (f.inpfile[x] == '.') break;
	}
	if (stricmp(&f.inpfile[x],inpEXT)) {			/* 入力側.zmdが省略されていたら */
		strcat(f.inpfile,inpEXT);					/* 拡張子の補間 (.zmdを補う) */
	}

	for (x = strlen(f.outfile) - 1; x > 0; x--) {
		if (f.outfile[x] == '.') break;
	}
	if (!stricmp(&f.outfile[x],inpEXT)) {			/* 出力側の拡張子もZMDだったら */
		strcpy(&f.outfile[x],outEXT);				/* 拡張子の置換 (.MIDにする) */
	} else if (z == 1) {							/* 出力ファイルを省略していたら */
		strcat(f.outfile,outEXT);					/* 拡張子の補間 (.MIDを補う) */
	}

	for (x = 0; x <= (int)strlen(f.inpfile); x++) {
		if (f.inpfile[x] == ':') break;
	}
	if (x == (int)strlen(f.inpfile) + 1) {
		x = -1;
	}

	for (y = 0; y <= (int)strlen(f.outfile); y++) {
		if (f.outfile[y] == ':') break;
	}
	if (y == (int)strlen(f.outfile) + 1) {
		y = -1;
	}

	if (!strcmp(&f.inpfile[x + 1],&f.outfile[y + 1])) {	/* ２つのファイルネームが同じだったら */
		for (x = strlen(f.outfile) - 1; x > 0; x--) {
			if (f.outfile[x] == '.') break;
		}
		strcpy(f.outfile,outEXT);					/* 出力の拡張子をMIDに変更する */
	}												/* よってソース側ではMIDという拡張子は
													/* 使わない方がよい */
	return f;										/* 手抜きと言われればそれまでですが…… */
}



/* ==============================
     スイッチから数字を取り出す
   ============================== */

int getnum(char **ptr)
{
	int n = 0;

	if ( (**ptr) == 0 ) swerr();
	while ( isdigit((int)**ptr) && (**ptr) != ',' ) {
		n = n * 10 + (**ptr) - 48;
		(*ptr)++;
	}
	if ( n < 0 ) swerr();
	return n;
}


/* ==================================
     正しくない数字指定のエラー処理
   ================================== */

void swerr(void)
{
#ifndef ENGLISH
	ZTOMFormatMessage( stderr,"無効な数字を指定しました。\n" );
#else
	ZTOMFormatMessage( stderr,"invalid numver.\n");
#endif
	help(1);
}
