とりあえず日記

VIM→秀丸エディタ→VIM→秀丸エディタ→VIM→秀丸エディタ→VIM→秀丸エディタ→VIM→秀丸エディタ→VIM→秀丸エディタ(いまここ🍄)

tagsファイル(Exuberant Ctags)を解析してみたのでその覚え書き。

Visual Assist X の Hovering Tooltips っぽい機能を秀丸マクロで実装するために、tagsファイルを解析しています。

Hovering Tooltipsの詳細はこちら

http://www.wholetomato.com/products/features/hover.asp

要するに関数のコメントをTooltipでポップアップ表示する機能ですな。
こんなのを秀丸マクロで作ろうとしています。

さてtagsファイルの中身ですが

tagsファイルの中身はシンボル名でソートされたテキストファイルになっていて、テキストエディタで開くとこんな風になってます。

!_TAG_FILE_FORMAT	2	/extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED	1	/0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR	Darren Hiebert	/dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_JP_AUTHOR	Hirohito Higashi	/h_east@pop11.odn.ne.jp/
!_TAG_PROGRAM_JP_URL	http://hp.vector.co.jp/authors/VA025040/	//
!_TAG_PROGRAM_NAME	Exuberant Ctags	//
!_TAG_PROGRAM_URL	http://ctags.sourceforge.net	/official site/
!_TAG_PROGRAM_VERSION	5.8J1	//
$0	.\test\MC\AsmParser\macro-def-in-instantiation.s	/^$0 $1$/;"	l
$2	.\test\MC\AsmParser\macro-def-in-instantiation.s	/^$2 $3$/;"	l
<<省略>>
~s1	.\tools\clang-3.0.src\test\SemaTemplate\destructor-template.cpp	/^    ~s1() {}$/;"	f	class:s0::s1	file:
~scoped_ptr	.\utils\unittest\googletest\include\gtest\internal\gtest-port.h	/^  ~scoped_ptr() { reset(); }$/;"	f	class:testing::internal::scoped_ptr
~simple_ptr	.\tools\clang-3.0.src\test\SemaCXX\destructor.cpp	/^  ~simple_ptr() { delete _ptr; } \/\/ \\$/;"	f	class:dnvd::simple_ptr
~simple_ptr2	.\tools\clang-3.0.src\test\SemaCXX\destructor.cpp	/^  ~simple_ptr2() { delete _ptr; } \/\/ expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}$/;"	f	class:dnvd::simple_ptr2
~thing	.\tools\clang-3.0.src\test\SemaTemplate\alias-templates.cpp	/^    ~thing() { traits.free(static_cast<inner_ptr&&>(val)); }$/;"	f	struct:X::thing
~unique_ptr	.\tools\clang-3.0.src\test\SemaCXX\rval-references-examples.cpp	/^  ~unique_ptr() { delete ptr; }$/;"	f	class:unique_ptr
~usage_requirements	.\tools\clang-3.0.src\test\SemaTemplate\instantiate-field.cpp	/^    ~usage_requirements()$/;"	f	struct:PR7123::usage_requirements
~xpto	.\tools\clang-3.0.src\test\CodeGenCXX\array-construction.cpp	/^  ~xpto() {$/;"	f	class:xpto

1行が横に長いためブラウザによっては折り返されて見にくいかもしれません。
上記サンプルは、LLVM3.0のソールコードからtagsファイルを作っています。ちなみにファイルサイズは17MBです。

並び方は、

シンボル名 ファイル名 シンボルの定義値を探す正規表現 ・・・

tagsファイルを作った後でテキストを編集し行番号がずれたときでもシンボルを検索出来るように行番号は格納されていません。
その代わりに正規表現で探します。(まさにテキストエディタ向けのフォーマット)

tagsファイルからシンボルを検索する

tagsファイルはシンボル名でソートされています。
ふと思いつくのは二分検索(Binary Search)ですが、ファイルに対しての二分検索はランダムアクセスなので効率が悪いのと、任意の行へアクセスするには別途補助情報(行番号へのオフセットを格納したファイル??)が必要になります、、、面倒です。

「データベースを別途用意すれば・・・」とも思いましたが、管理するものが増えてこれも面倒です。(DBという別の問題にすり替えただけ)

まあ、うだうだと頭の中で考えていても仕方ないので、tagsファイルのシンボルを線形検索で探すプログラムを書いたところ、17MB程度のtagsファイルを一瞬で検索出来ました。
きちんと時間は計っていませんが(すいません)テキストエディタから呼び出して使うぶんには問題なさそうです。

100MB級のtagsファイルを検索して遅ければ、それはその時に考えようかと思います。

作ったプログラム

Githubへアップしました。
https://github.com/ohtorii/hidemaru_hovering_tooltips

使い方

>ctags_search createCXTUResourceUsageEntry ..\sample\tags

createCXTUResourceUsageEntry    .\tools\clang-3.0.src\tools\libclang\CIndex.cpp /^static inline void createCXTUResourceUsageEntry(MemUsageEntries &entries,$/;" f       file:

今後の予定

tagsファイルから「関数名、クラス名・・・」などを検索することができたので、あとは秀丸ディタ側の処理だけです。
ぼちぼち、やっていこうかと思います。