Schi Heil と叫ぶために

hiroakiuno's blog

改行コードと TeraTerm の関係を整理してみよう

改行コード (newline) はテキストの行末を表す文字コードの一つで、一般に1個または2個の制御文字 (Control Character) で表現される。一般的なテキストエディタ上で Enter を押したときのいわゆる改行は、厳密には復帰 (CR:Carriage Return) + 改行 (LF:Line Feed) という振る舞いになるが、実際の改行コードは ASCII ベースのシステムでは CR、LF、CR+LF のいずれかで表現され処理系によって異なる。

プログラミングにおける改行コードの取り扱いはこれを踏まえてややこしくなるが wikipedia に詳しい。

ポータブルなプログラムを記述するために、プログラミング言語は異なる改行コードを扱うためにある程度の抽象性を提供している。
C言語は'\n'(改行)、'\r'(復帰)の二つのエスケープシーケンスを提供している。しかし一般的な認識に反して、これらのエスケープシーケンスは一般的にはLFやCRと等価ではない。C言語は次の二つの事柄のみを保証している。

  1. これらのエスケープシーケンスはそれぞれ異なった環境依存のchar型に収まる範囲の数字に変換される。
  2. テキストモードでファイルに書き込むとき、'\n'はシステムで使用されている改行コードに変換される。この改行コードは1文字に収まるとは限らない。逆にテキストモードで読み込む時、改行コードのシーケンスは'\n'に変換される。バイナリモードにおいてはいかなる変換も行われない。

改行コード - Wikipedia

最近のブラウザやエディタは全ての改行コードを自動で判別するので実は面倒なケースであっても問題が明るみに出ることは少ないが、クロスコンパイル環境や異なる処理系でテキスト情報を通信するケースでは非常にデリケートな問題となる。例えば組み込み系で vprintf を使って文字列を処理し、それを PC に転送して端末ウィンドウに表示するというケースでは送り側と受け側の改行コードを対応させる必要が出てくる。vprintf に渡された "\n" がどの改行コードに落とされるかは処理系(コンパイラ)依存であるため、それを受ける端末、例えば TeraTerm では「設定」→ 「端末」→「改行コード」→「受信」で細かく設定できるようになっている。

設定を CR、CR+LF にしたときの動作はこちらが参考になる。

ちなみに上記の投稿の時点では LF というモードは無かったようなので、

個人的には、LFコード受信時にLFかCR+LFを選択できると、HTTPとかで改行コー
ドをLFのまま送ってくるお茶目なサーバを覗くのに便利なのですが…。

とあるが、最新の UTF-8 TeraTerm Pro with TTSSH2 (これを書いている時点での最新版は4.53) では実装されていて、それが設定の LF になる。ソース管理のログにその仕様も記載されていた。

Terminal setupダイアログの New-line の Receive に "LF" を追加した。
受信時の改行コードが LF の場合は、サーバから LF のみが送られてくると
仮定し、CR+LFとして扱うようにする。

http://cvs.sourceforge.jp/cgi-bin/viewcvs.cgi/ttssh2/teraterm/source/teraterm/vtterm.c

ということで手元の Tera Term で、上記3つの受信設定それぞれに対して、

  • 送信データの改行コードを CR とした場合
  • 送信データの改行コードを LF とした場合
  • 送信データの改行コードを CR+LF とした場合

を送って実際の見た目を確かめてみた。結果は次の通り。

送信側:CR 送信側:LF 送信側:CR+LF
受信設定:CR NG (改行のみで復帰せず) NG (復帰のみで改行せず) OK
受信設定:CR + LF OK NG (復帰のみで改行せず) NG (二重に改行される)
受信設定:LF NG (改行のみで復帰せず) OK OK

OK は見た目に問題ないという意味だが、見た目だけなら CR+CR+CR+LF と CR が繰り返しても問題ない。それを踏まえて上記を噛み砕くと、実際の動作としては、

送信側:CR 送信側:LF 送信側:CR+LF
受信設定:CR NG (CRのみ) NG (LFのみ) OK (CR+LF)
受信設定:CR + LF OK (CR+LF) NG (LFのみ) NG (CR+LF+LF)
受信設定:LF NG (CRのみ) OK (CR+LF) OK (CR+CR+LF だけど OK)

ということになる。