//	
//	dpesc5c.c
//	
//	dpesc5c - 行末シフトJIS 0x5c問題を回避するツール
//	Copyright (C) 2015 Naoyuki Sawa
//	
//	* Tue Mar 03 23:04:12 JST 2015 Naoyuki Sawa
//	- 1st リリース。
//	- マルチバイト文字の第2バイトがバックスラッシュに一致して、Cプリプロセッサコメントの継続と見なされて次の行が削除される問題を、回避するためのツールです。
//	  「\usr\PIECE\tools\pcc33_102\pcc33.c」の、「行末シフトJIS 0x5c問題に対応」の機能のみを切り出したものです。
//	- 当ツールは、Cプリプロセッサコメント内かどうかを、判断していません。
//	  マルチバイト文字の第2バイトがバックスラッシュに一致して直後に改行文字が有れば、その行がCプリプロセッサコメント行かどうかに関係無く、改行文字の前にダミーの空白文字を出力します。
//	  この挙動はC言語ならば問題有りませんが、行末の空白文字に意味の有る言語やテキストに使用する場合は注意して下さい。
//	- とても単純なツールなので、使い方の表示や親切なエラーメッセージの表示は搭載しませんでした。
//	  プログラム名の'dpesc5c'の意味は、'ESCape 0x5C'の略です。
//	- □実行例
//	  │Fifty	⇒	そのまま出力
//	  │Fifty\	⇒	そのまま出力
//	  │十五	⇒	そのまま出力
//	  │五十	⇒	行末に空白文字を追加して出力
//	- □『錬金術の館』(http://homepage2.nifty.com/k_maeda/)さんの「注意すべき全角文字」(http://homepage2.nifty.com/k_maeda/code/perl.html)のページより引用：
//	  │―（81 5C） : Horizontal Bar
//	  │ソ（83 5C） : Katakana Letter So
//	  │Ы（84 5C） : Cyrillic Capital Letter Yeru
//	  │噂（89 5C） : ソン、うわさ
//	  │浬（8A 5C） : リ、かいり、ノット
//	  │欺（8B 5C） : ギ、キ、あざむ・く
//	  │圭（8C 5C） : ケイ、たま
//	  │構（8D 5C） : コウ、かま・える、かま・え、かま・う、かま・い
//	  │蚕（8E 5C） : サン、テン、かいこ
//	  │十（8F 5C） : ジュウ、ジッ、シュウ、とお、と
//	  │申（90 5C） : シン、もう・す、さる
//	  │曾（91 5C） : ソ、ソウ、かつ・て、ひい
//	  │箪（92 5C） : タン
//	  │貼（93 5C） : テン、チョウ、は・る
//	  │能（94 5C） : ノウ、ドウ、あた・う、よ・く、よ・くする
//	  │表（95 5C） : ヒョウ、おもて、あらわ・す、あらわ・れる
//	  │暴（96 5C） : ボウ、バク、あば・く、あば・れる、さら・す
//	  │予（97 5C） : ヨ、あらかじ・め
//	  │禄（98 5C） : ロク
//	  │兔（99 5C） : ト、うさぎ
//	  │喀（9A 5C） : カク、は・く
//	  │媾（9B 5C） : コウ
//	  │彌（9C 5C） : ビ、ミ、や、いよいよ、いや
//	  │拿（9D 5C） : ダ、ナ、ひ・く、つか・む
//	  │杤（9E 5C） : とち
//	  │歃（9F 5C） : ソウ、すす・る
//	  │濬（E0 5C） : シュン
//	  │畚（E1 5C） : ホン、もっこ、ふご
//	  │秉（E2 5C） : ヘイ、と・る
//	  │綵（E3 5C） : サイ、あや
//	  │臀（E4 5C） : デン、しり
//	  │藹（E5 5C） : アイ
//	  │觸（E6 5C） : ショク、ソク、ふ・れる、ふ・れ、さわ・る
//	  │軆（E7 5C） : タイ、テイ、からだ
//	  │鐔（E8 5C） : シン、タン、つば
//	  │饅（E9 5C） : マン、バン
//	  │鷭（EA 5C） : ハン、バン
//	
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <mbctype.h>
//□[NOTE]
//│コマンドライン引数のワイルドカードを展開するために、
//│[プロジェクトの設定]->[リンク]->[オブジェクト/ライブラリモジュール]に
//│「setargv.obj」を追加しました。
//-----------------------------------------------------------------------------
static void process_file(FILE* fp);
//-----------------------------------------------------------------------------
int main(int argc, char* argv[]) {
	if(argc <= 1) {						//ファイルが指定されていなければ、標準入力から読み込む。
		process_file(stdin);
	} else {						//ファイルが指定されていたら、各ファイルを読み込む。
		int i;
		for(i = 1; i < argc; i++) {
			FILE* fp = fopen(argv[i], "r");
			if(!fp) {
				fprintf(stderr, "%s が開けません。\n", argv[i]);
				return EXIT_FAILURE;
			}
			process_file(fp);
			fclose(fp);
		}
	}
	return EXIT_SUCCESS;
}
//-----------------------------------------------------------------------------
static void process_file(FILE* fp) {
	int c, mode = 0;
	while((c = getc(fp)) != EOF) {				//一文字読み込む。
		       if(_ismbblead(c)) {			//マルチバイト文字の第1バイトならば…
			mode = 1;				//モード1(マルチバイト文字の第1バイト)へ遷移する。
		} else if(_ismbbtrail(c)) {			//マルチバイト文字の第2バイトならば…
			if((mode == 1) && (c == '\\')) {	//モード1(マルチバイト文字の第1バイト),かつ,バックスラッシュならば…
				mode = 2;			//モード2(マルチバイト文字の第2バイトがバックスラッシュに一致した)へ遷移する。
			} else {				//モード1(マルチバイト文字の第1バイト),かつ,バックスラッシュでなければ…
				mode = 0;			//モード0(通常状態)へ遷移する。
			}
		} else if(c == '\n') {				//改行文字ならば…
			if(mode == 2) {				//モード2(マルチバイト文字の第2バイトがバックスラッシュに一致した)ならば…
				putchar(' ');			//ダミーの空白文字を出力する。
			}
			mode = 0;				//モード0(通常状態)へ遷移する。
		} else {					//それ以外ならば…
			mode = 0;				//モード0(通常状態)へ遷移する。
		}
		putchar(c);					//読み込んだ文字を出力する。
	}
}
