#include "app.h"
/****************************************************************************
 *	
 ****************************************************************************/
__declspec(noreturn) static void usage();
/****************************************************************************
 *	
 ****************************************************************************/
#define MAX_FILE 99999			//連結するファイルの数の最大数(調整可)
static char* TBL_File[MAX_FILE];	//連結するファイルのファイル名
static int nFile;			//連結するファイルの数
//{{進捗表示用
static int newMsgLen, oldMsgLen = 0;
//}}進捗表示用
/*--------------------------------------------------------------------------*/
int main(int argc, char* argv[]) {
	FILE* fp;
	char* glbuf = NULL;	//┬getline()用
	int   glcap = 0;	//┘
	int   opt, i;
	char* sTtlFmt = NULL;	//'-l'オプションが指定されたらタイトル書式文字列を設定する。
	//コマンドラインオプションを処理する。
	opterr = 0; //オプションエラーは当プログラム内で処理するので、getopt()内でのエラー表示は不要。
	while((opt = getopt(argc, argv, "f:l::h")) != -1) {
		switch(opt) {
		case 'f':
			{
				//リストファイルを開く。
				fp = fopen(optarg, "r");
				if(!fp) { die("%s が開けません。", optarg); }
				//リストファイルの各行を読み込んで…
				while(getline(&glbuf, &glcap, fp) != EOF) {
					//前後の空白文字を取り除く。
					strstrip(glbuf);
					//空行でなければ…
					if(glbuf[0]) {
						//リストファイルで指定されたファイル名を、連結するファイルに追加する。
						if(nFile >= MAX_FILE) { die("連結するファイル数が制限を超えました。"); }
						TBL_File[nFile++] = strdup(glbuf);	//呼び出し元のバッファは次のgetline()で破壊されるのでstrdup()必要。
					}
				}
				//リストファイルを閉じる。
				fclose(fp);
			}
			break;
		case 'l':
			{
				//タイトル書式文字列を設定する。
				// - オプション引数が有れば、それをタイトル書式文字列とする。
				//   オプション引数が無ければ、"#//%s"とする。
				sTtlFmt = optarg ? optarg : "#//%s";
			}
			break;
		case 'h':
		default:
			usage();
		}
	}
	//コマンドラインで指定されたファイル名を、連結するファイルに追加する。
	for(i = optind; i < argc; i++) {
		if(nFile >= MAX_FILE) { die("連結するファイル数が制限を超えました。"); }
		TBL_File[nFile++] = strdup(argv[i]);					//こちらはstrdup()しなくても構わないが、一応しておくことにした。
	}
	//連結するファイルが指定されていたら、各ファイルを読み込む。
	if(nFile) {
		for(i = 0; i < nFile; i++) {
		    //{{進捗表示用
			newMsgLen = fprintf(stderr, "\r%d/%d %s", (i+1), nFile, TBL_File[i]);
			if(oldMsgLen > newMsgLen) { fprintf(stderr, "%*s", oldMsgLen - newMsgLen, ""); } oldMsgLen = newMsgLen;
		    //}}進捗表示用
			//ファイルを開く。
			fp = fopen(TBL_File[i], "r");
			if(!fp) { die("%s が開けません。", TBL_File[i]); }
			//タイトル書式文字列が設定されていたら、タイトル行を出力する。
			if(sTtlFmt) {
				fprintf(stdout, sTtlFmt, TBL_File[i]);
				fputc('\n', stdout);
			}
			//ファイルの内容を出力する。
			while(getline(&glbuf, &glcap, fp) != EOF) {
				fputs(glbuf, stdout);
			}
			//ファイルを閉じる。
			fclose(fp);
		}
	    //{{進捗表示用
		newMsgLen = fprintf(stderr, "\r%d個のファイルを連結しました。", nFile);
		if(oldMsgLen > newMsgLen) { fprintf(stderr, "%*s", oldMsgLen - newMsgLen, ""); } putc('\n', stderr); oldMsgLen = 0;
	    //}}進捗表示用
	//連結するファイルが指定されていなければ、標準入力から読み込む。
	} else {
		while(getline(&glbuf, &glcap, stdin) != EOF) {
			fputs(glbuf, stdout);
		}
	}
	return EXIT_SUCCESS;
}
/*---------------------------------------------------------------------------*/
__declspec(noreturn) static void usage() {
	fprintf(stderr, "dpcat - テキスト連結ツール(リストファイル対応) (%s)\n", VERSION);
	fprintf(stderr, "Copyright (C) 2015-2016 Naoyuki Sawa\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "USAGE:\n");
	fprintf(stderr, "  dpcat [option] [filename ...]\n");
	fprintf(stderr, "  ・filenameも-fオプションも指定しなければ、標準入力から読み込みます。\n");
	fprintf(stderr, "  ・filenameは、ワイルドカードによる複数指定も可能です。\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "OPTIONS:\n");
	fprintf(stderr, "  -f listfile    リストファイルを指定します。\n");
	fprintf(stderr, "                 リストファイルに、1行に1個づつ、連結するファイル名を記述してください。\n");
	fprintf(stderr, "                 リストファイルに記述したファイル名の、ワイルドカードは展開されません。\n");
	fprintf(stderr, "                 リストファイルに、空行が含まれていても構いません。\n");
	fprintf(stderr, "                 -fオプションは、複数指定できます。\n");
	fprintf(stderr, "                 -fオプションと、コマンドラインでのファイル指定を、併用できます。\n");
	fprintf(stderr, "  -l[書式文字列] タイトル行を出力します。\n");
	fprintf(stderr, "                 書式文字列を指定すると、その書式文字列を使ってファイル名を出力します。\n");
	fprintf(stderr, "                 書式文字列を省略すると、'#//%s' の書式を使ってファイル名を出力します。\n");
	fprintf(stderr, "                 このオプションを指定しなければ、タイトル行を出力しません。\n");
	fprintf(stderr, "  -h             使い方を表示します。\n");
	exit(EXIT_FAILURE);
}
