ログデフォルトファイル名に strftime が正しく置換されない
LANG, LC_ALL, LC_TIME の環境変数を設定してから起動しましたが、いずれもロケールの切り替えは出来ませんでした。
なお、私のところでビルドすると、Teraterm4 で以下が現象を確認できたので、ビルド環境によりロケールが正しく扱われていないようでした。
端末設定のロケールを american の Equivalent Locale Name (en-US)で指定。
※ビルドした場合でも en-US.utf8 まで指定すればハングアップしないので cランタイムが適切でないのかもしれない。
Tera Term 4 はプログラム内で
setlocale(LC_ALL, ts.Locale)とやっているので環境変数の影響は受けないのではないかと思います。
ハングアップするのは腑に落ちないですね。
Tera Term 5 は setlocale()を行っていません。
起動時に setlocale(LC_ALL, "C") と同等な処理が行われるようです。
https://learn.microsoft.com/ja-jp/cpp/c-runtime-library/reference/setlocale-wsetlocale?view=msvc-170
ロケールクリアすれば正しく置換される。
Tera Term 5 の起動最初の方で
setlocale(LC_ALL, "")を実行しておいた方がよさそうですね。
入れようと思いますが、 特に問題なさそうですか?
プログラムの最初に setlocale(LC_ALL, "") を追加しました。r10738です。
LANG, LC_ALL, LC_TIME の環境変数を設定してから起動しましたが、いずれ もロケールの切り替えは出来ませんでした。
setlocale() のドキュメントには環境変数を参照する、とないですね。
コントロールパネル「地域」-「形式」タブにはしたがうようです。
そういう仕様(VS2022のCランタイムの仕様)なのかなと思います。
書式指定 %C などは、今のところ isInvalidStrftimeCharW() で不正と判定、 deleteInvalidStrftimeCharW() で削除されてます。
使用可能な書式指定はVSのバージョンで変化すると思います。 ハードコードじゃない方法でチェックしたいですがどうしたものでしょうか。
r10739 で VS2022 で使える "%C" などが使えるよう修正しました。
strftime() は使用できない書式を与えるとパラメータ不正で内部でassert()します。
起動時に自動的にログ取得を開始するようになっている状態で、 誤って使用できない書式のファイル名を指定してしまうと 困ったことになるので厳密にチェックしているんだと思います。
_set_invalid_parameter_handler() (Debugビルドなら _CrtSetReportMode()も) を使えばstrftime()内部で止まらず、呼び出し側に戻るようにできそうでした。 とりあえず今のところはリリースで使用する予定のVS2022でうまく動けば良いかなと思い、 パラメータチェックはハードコードで実装しています。
こちらでもテストしてみました。
"%a, %A, %b, %B, %c, %p, %r, %x, %X, %Z.log"
火, 火曜日, 6, 6月, 20230606 224932, 午後, , 20230606, 224932, 東京 (標準時).log
火, 火曜日, 6, 6月, 2023_06_06 23_01_44, 午後, 23_01_44, 2023_06_06, 23_01_44, 東京 (標準時).log
%a ロケールでの曜日の省略名 %A ロケールでの完全な曜日名 %b ロケールでの月の省略名 %B ロケールでの月の完全な名前 %c ロケールに合った日付と時刻の表記 %p ロケールでの 12 時間形式の午前/午後の標識 %r ロケールでの 12 時間制時刻 %x ロケールの日付表現 %X ロケールの時刻表現 %Z レジストリ設定に応じて、ロケールのタイム ゾーンの名前またはタイム ゾーンの略称のいずれか。タイム ゾーンが不明の場合は文字なし
%a 曜日の省略形。 %A 曜日の正式名。 %b 月の省略形。 %B 月の正式名。 %c ロケールに対応する日付と時刻の表現。 %p 現在のロケールの午前/午後。 %x 現在のロケールの日付表現。 %X 現在のロケールの時刻表現。 %z, %Z レジストリの設定に応じて、タイム ゾーンの名前または省略形を指定します。 タイム ゾーンが不明な場合は指定しません。
書式指定 %C などは、今のところ
isInvalidStrftimeCharW() で不正と判定、
deleteInvalidStrftimeCharW() で削除されてます。
一番最初に「Tera Term 4 は VIsual Studio 2005 を使うのであるから、その範囲内でしかサポートし得ない」がありました。
次に「Visual Studio 2005 のマニュアルを Microsoft がオンライン上から消してしまった」がありました。これが次の項目の確認を困難にしています。
「Visual Studio 2005 のサポートするフォーマットをすべてサポートしていたが、%Cはその中に含まれていなかった」か、「含まれていたがあまり使わなそうだと思ったか、長い文字列に展開されそうで固定長で確保しているバッファがあふれそうな気がすると思ったのでサポート外とした」ような気もします。前者は古い MSDN Library を引っ張り出さないと確認できませんし、後者は私のおぼろげな記憶なのでソースのコメントになかったら確認できません。とにかく現在サポートされているのはドキュメントに書いてあるとおり、これだけということになります。
使用可能な書式指定はVSのバージョンで変化すると思います。
ハードコードじゃない方法でチェックしたいですがどうしたものでしょうか。
「Tera Term 側でサポートする書式を、コンパイラのサポートしている書式に対応して動的に変化させる」をしたら、マニュアルもそうしなければなりません。こういう場合は「コンパイルをサポートする最も低い VS バージョンにあわせる。その場合には新しい VS のみ使える書式は導入できない」でよいと考えます。
こちらでもテストしてみました。
ありがとうございます。
「Tera Term 側でサポートする書式を、コンパイラのサポートしている書式 に対応して動的に変化させる」をしたら、マニュアルもそうしなければなり ません。
「strftime の書式が使用できます」とマニュアルにあると「"%C"が使えない?」 と思ってしまいますね(思ってしまいました)。内部の実装はstrftimeですが、 マニュアルではstrftimeを削除して「次の書式が使用できます」としたほうが よいかも、とおもいました。
でもstrftime()を知っている人なら、strftime とあるほうがわかりやすいですね。 「strftimeと同様の次の書式が使用できます」のほうがよさそうでしょうか?
ついさっきVS2022で使える書式を使えるようにした修正を入れましたが、 従来と同等に戻そうと思います。
それとマニュアルの"%a"などの説明に「現在のロケールの」を追加したほうがよさそうですね。
環境変数で動作(フォーマット)を変更する件ですが、Visual Studio 2022で作っ たプログラムはできないように思います。
また手もと(r10739相当+VS2022)で LANG=en-US としてハングアップすることなく起動し ています。気になります。
環境変数で変更できなくても、日本語環境以外のときに"%B"なら"%#m月"とするなどで表現可能ものもあります。 以前よりは制限が減ったのではないかと思います。
でも"%A" ("日曜日"など)は日本語環境以外では再現できないですね。
環境変数 TZ は参照されるようです。
https://learn.microsoft.com/ja-jp/cpp/c-runtime-library/reference/tzset?view=msvc-170
ttermpro.exe では _tzset() はコールしていないのですがうまく設定されているようです。
setlocale() でセットされているのかもしれません。
「strftime の書式が使用できます」とマニュアルにあると
直下に書式を列挙しているのでそこを見るだろうと思っていました。strftime の書式を暗記していて覚えている書式をそのまま書くと、Tera Term に限らず、VS バージョンによって/もしかしたらプラットフォームによってもサポート状況が違う、という罠があるわけですね。
「strftimeと同様の次の書式が使用できます」
こう書くと、よりわかりやすくなると思います。
マニュアルの"%a"などの説明に「現在のロケールの」を追加したほうがよさそうですね。
今列挙している書式は、Visual Studio 2005 のときの MSDN の説明のコピペです。現在の MSDN では変わっているんですね。
つかえる書式チェックを従来と同等に戻して、マニュアルを修正しました。r10744です。
直下に書式を列挙しているのでそこを見るだろうと思っていました。
確かにそうですよね。
そちらよりダイアログの「標準ログファイル名(strftimeフォーマット可) (&F)」 に引っ張られたのかなと思います。
思い切って省略して「標準ログファイル名(&F)」でもよいかなと思いますが いかがでしょうか?
(ちょっと省略しすぎかな・・strfime以外の書式もありますし・・悩ましい)
ドロップダウンで書式指定の例を見ることができるので、 調べたくなったユーザーはヘルプ参照、となるのかなと思います。
思い切って省略して「標準ログファイル名(&F)」でもよいかなと思いますが いかがでしょうか?
変更せずに現在のままにしましょう。
クローズします。
ログデフォルトファイル名に strftime 文字列で指定した場合、置換は行われるが、地域に合った文字列に置換されない。
teraterm/teraterm/terater.cpp の WinMain() でロケールクリアすれば正しく置換される。(コントロールパネル「言語と地域設定」の設定が使われる)
setlocale(LC_ALL, "");
以下の環境で行っています。(win11 でビルドしているけど vs2022 にあげてないからかも)
実行環境:Windows 11 Home 22H2 22621.963
ビルド環境:Visual Studio 2019 Community/Windows SDK version 10.0.17763.0/cmake version 3.25.0-rc1