doxygen 日本語文字化け対策

観測気球

収集物の記録書庫 a data archive of collection -- collectible toys

[要旨] doxygen を使ってソースコードからドキュメントを生成するとき、日本語(Shift_JIS)を使うと文字化けが発生することがあります。doxygen のソースに手を入れて、文字化け対策を実現してみました。
[キーワード] ソースコード,プログラム,ドキュメント,文字化け

« Pinky:st. 「フルーツバスケット」本田透(BlogPet) | トップページ | メイド喫茶に関する本 »

2005.08.29

doxygen 日本語文字化け対策

現在、doxygen の 1.4.4 (2005年7月21日版)を使って、自作のライブラリのドキュメントを整備しようとしています。

doxygen というのは、ソースプログラムの中に一定の規則にしたがってコメントを書いておくと、そのコメントを元にドキュメント(html や LaTeX など、いろんな形式をサポートしています)を自動生成してくれるツールです。

問題の概要

で、doxygen は日本語を含む多国語サポートが売りなんですが、実際に使ってみると、一部の漢字・カタカナが化けてしまうんですね。Shift_JIS の場合、2バイト目が 0x5c (つまり '\') になる漢字やカタカナがあるんですが、そういう類の文字が化けてしまうんですね。doxygen は '\' という文字に特別な意味を持たせているので、2バイト目に '\' を含む文字が来ると誤動作してしまう。誤動作を防ぐ対策として、Shift_JIS を使うのをやめて EUC-JP にする、という逃げ道はあるんですが、Windows 環境で開発しているプログラムに関しては、Shift_JIS のまま行きたいところ。

原因追求

最初は doxygen の設定をいじれば何とかなるのかと思っていろいろ試行錯誤してみましたが、設定ではどうにもならないことがわかってきました。結局、doxygen のソースに手を入れるしか方法はなさそう。1.3.9 版までは、日本語関係の処理を有志の人が手伝ってアップデートしていたそうなんですが、現在は日本語関連のアップデートは止まっているとのこと。私がどの程度手伝えるのか不明ですが、とりあえず、いじれるところまでいじってみようと、挑戦してみました。

まず、どこで文字化けが発生するのか、特定する必要があります。想定される状況としては、

  • ドキュメント生成対象のソースコードを読み込む処理で、すでに2バイト目の '\' が失われてしまっている
  • ソースコードを読み込んだ後、doxygen コマンドを解析する段階で、2バイト目の '\' が捨てられてしまう
  • 最終段階で(ドキュメントを吐き出すときに)、2バイト目の '\' が失われる

というようなものが考えられます。

ソースをぱっと見ただけではすぐにはわからないので、デバッガを使って doxygen の処理を追いかけてみました。すると、ソースファイルを読み込んだ直後はまだ化けていない、ドキュメントを吐き出すときはすでに化けていることがわかりました。少しづつ探索範囲を狭めていって、結局、ソースファイルからコメントを切り出し、doxygen コマンドを抽出する処理で、2バイト目の '\' が失われていることを突き止めました。

この「ソースファイルからコメントを切り出し、doxygen コマンドを抽出する処理」は lexical analyzer、通称 lex と呼ばれるプログラムで処理するための専用言語で記述されている部分で、lex またはその互換プログラム flex により、C ソースプログラムに変換されます。要するに、doxygen コマンドの一覧表がその専用言語で記述されている訳です。

修正方針

ということで、doxygen の日本語文字化け問題を解決するには、

  • doxygen コマンド一覧表を Shift_JIS を意識した形で書き直す
  • doxygen コマンド一覧表自体は改変せず、lex (あるいは flex) に Shift_JIS を意識したコードを吐き出させるように lex (あるいは flex) を改造する
  • lex (あるいは flex) の吐き出したコードに手を入れ、Shift_JIS 対応を実現する

というような方法が考えられます。

結局、最小限の手間暇で対応できる、いちばん最後の方法を採用しました。flex の吐き出したソース(C で記述されている)に手を入れ、それを使うことにしました。

修正結果

実際に、この対策を施した doxygen を作って動かしてみたところ、期待通り文字化けは解消。問題は、こういう解決方法を、開発元に送っても取り込んでもらえるかどうか、不明なこと。却下されても不思議じゃないですし。とはいっても、日本語(それも Shift_JIS)のためだけに、「doxygen コマンド一覧表」を書き換えるのも何か違う気がするし。というか、書き換え量が半端じゃないし、「一覧表」が複雑で見通しの悪いものになり、可読性(というか保守容易性)が極めて低下するのは目に見えています。もっとも、日本語以外にも、何らかの問題を抱かえている言語が存在する可能性もあります。結局、実際問題としては、lex の吐き出したコードに手を入れる方法がいちばん無難。

修正内容 (パッチ)

ということで、どういう風に手を入れたか、context diff を示しておきます。手を入れたのは commentscan.l を flex にかけたときの出力 commentscan.cpp です。手を入れる前のファイルを commentscan.cpp.orig として保存し、 手を入れた後のファイル commentscan.cpp との context diff を取りました。

(2005年9月8日 追記: 以下のパッチは、すでに obsolete です。最新のパッチは「doxygen 日本語文字化け対策 その3」から入手してください)

*** commentscan.cpp.orig	Thu Jul 21 00:00:30 2005
--- commentscan.cpp	Mon Aug 29 18:49:06 2005
***************
*** 3649,3654 ****
--- 3649,3669 ----
  	register yy_state_type yy_current_state;
  	register char *yy_cp = NULL, *yy_bp = NULL;
  	register int yy_act;
+ #if defined(_WIN32)
+ 	static bool isJapanese  = theTranslator->idLanguage()=="japanese" || 
+                               theTranslator->idLanguage()=="japanese-en";
+ 	bool  isKanji = false;
+ 	bool  kanji5C = false;
+ 
+ #ifndef	iskanji1
+ #define	iskanji1(s)	((((unsigned char)(s)>=0x81) && ((unsigned char)(s)<=0x9f)) || \
+ 			         (((unsigned char)(s)>=0xe0) && ((unsigned char)(s)<=0xfc))   )
+ #endif
+ #ifndef	iskanji2
+ #define	iskanji2(s)	((((unsigned char)(s)>=0x40) && ((unsigned char)(s)<=0x7e)) || \
+ 			         (((unsigned char)(s)>=0x80) && ((unsigned char)(s)<=0xfc))   )
+ #endif
+ #endif  /* _WIN32 */
  
  #line 779 "commentscan.l"
  
***************
*** 3715,3720 ****
--- 3730,3750 ----
  		do
  			{
  			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ 
+ #if defined(_WIN32)
+ 			if ( isJapanese ) {
+ 				if ( !isKanji && iskanji1(*yy_cp) )
+ 			 		isKanji = true;
+ 				else if ( isKanji /* && iskanji2(*yy_cp) */ ) {
+ 					isKanji = false;
+ 					if ( *yy_cp == '\\' )
+ 						kanji5C = true; // 漢字の2バイト目が 0x5c のとき特別扱いが必要
+ 				}
+ 			}
+ 			if ( kanji5C )
+ 				kanji5C = false;
+ 			else {
+ #endif  /* _WIN32 */
  			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
  				{
  				yy_current_state = (int) yy_def[yy_current_state];
***************
*** 3722,3727 ****
--- 3752,3760 ----
  					yy_c = yy_meta[(unsigned int) yy_c];
  				}
  			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ #if defined(_WIN32)
+ 			}
+ #endif  /* _WIN32 */
  			*yy_state_ptr++ = yy_current_state;
  			++yy_cp;
  			}

参考資料

どういう具合の文字化けが発生するのか、参考までに書いておきます。

例1
/** \defgroup software ソフトウェア
 *  \ingroup nodeID

のように、\defgroup の第2引数に日本語を使う場合、2バイト目に 0x5c があると化ける(上記の例では「ソ」の2バイト目が 0x5c)。具体的には、「ソフトウェア」が「ャtトウェア」に化ける。

例2
/**
 *  \defgroup amazonSearch 検索結果格納用構造体
 */

構造体」が「国「体」に化ける。

例3

ただし、以下のように、単なるコメントの場合は化けない

#define AMAZON_NODE_M_SOUL        569318  /**< ソウル・リズム&ブルース      */

期待通り「ソウル・リズム&ブルース」と出力される。


関連記事

投稿者: tsupo 2005.08.29 午後 08:49 | 固定リンク | このエントリーをはてなブックマークに追加 | このエントリを del.icio.us に登録 このエントリの del.icio.us での登録状況 | このエントリを Buzzurl に追加このエントリの Buzzurl での登録状況 | このエントリをlivedoorクリップに登録 このエントリのlivedoorクリップでの登録状況 このエントリをlivedoorクリップに登録している人の数 | 酢鶏巡回中

楽天市場


品揃え豊富で安い!NTT-X Store


アマゾンわくわく探検隊

トラックバック

この記事のトラックバックURL:

この記事へのトラックバック一覧です: doxygen 日本語文字化け対策:

» doxygen graphviz で日本語を使った絵をドキュメントに埋め込む from 観測気球
doxygen と graphviz を組み合わせて使うと、クラス図やコラボレーション図などの絵を組み込むことができます。ただし、モジュールの名前が日本語の場合、文字化けしてしまって、実用になりません。その解決方法がわかりましたので、解説します。... 続きを読む

受信: 2005.08.30 午後 07:45

» doxygen 日本語文字化け対策 その2 from 観測気球
先日の対策を施しても、まだ文字化けが発生するパターンが残っていました。暫定対処法(運用でカバーする方法)を提示します。 続きを読む

受信: 2005.09.02 午後 11:12

» doxygen 日本語文字化け対策 その3 from 観測気球
ようやく Shift_JIS 使用時に発生する doxygen の文字化けを完全に退治することができました。 続きを読む

受信: 2005.09.07 午後 08:49

コメント


Σ(゜Д゜)文字化けメール、たまに来ますね。たぶん、UTF-8で送ろうとして失敗してるぞ^^;

投稿者: 酢鶏@人工無能 (2005.09.26 午前 07:26)

ワード

ニッセン

fujisan.co.jp

楽天市場