#author("2022-12-02T23:07:03+09:00","","")
#topicpath

///////////////////////////////////////////////////////////////////////////////
* 目次 [#sec94d40]
#contents();

///////////////////////////////////////////////////////////////////////////////
* TagSystem [#faa5a708]
- ソースコードを静的解析するツール。指定したシンボルの定義を参照したりするのに使われる。

///////////////////////////////////////////////////////////////////////////////
* xcscope.el [#xcscope]
- タグシステムの一つ
- debian では、 cscope は cscope パッケージに入っている
- この他、 emacs で使用するのに xcscope.el を使う。そのために cscope-el パッケージを導入する
- emacs起動時に問題がなくても xcscope.el が正しく動作しない時は、''cscope-minor-mode'' に正しく入れていない可能性がある。その場合には
 (setq c++-mode-hook
       '(lambda ()
 		 (setq cscope-minor-mode t)
 		 ))
のように ${HOME}/.emacs などの適切な初期設定ファイルに記述しておく。 
- xcscope.el では、タグファイルを生成してあっても、リストを表示させるたびに grep が走る。そのため表示は速くない。速度が問題になる場合は、xcscope.el ではなく [[ascope>#ascope]] の使用を検討する余地がある。
* 各種 TagStstem [#y9fbb108]
#ls2(Prog/TagSystem/);

///////////////////////////////////////////////////////////////////////////////
* 各システムでの解析速度 [#y0ec5d99]
- 各タグシステムで同一コードツリーを走査して、 DB を作り終わるまでの時間を計測した。
- 結果(2)
|~[[TagSystem>Prog/TagSystem]] |~command |~elapsed time [sec] |~remark |
|[[cscope>Prog/TagSystem#cscope]]             |cscope-indexer -r |13.65 | |
|[[id-utils>Prog/TagSystem#id-utils]]         |mkid              |16.61 | |
|[[gtags-global>Prog/TagSystem#gtags-global]] |gtags             |14.82 | |
|[[etags>Prog/TagSystem#etags]]               |find -name '*.h' -o -name '*.c' -o -name '*.cc' | xargs -P ${THREAD_NUM} -I {} etags -a {} |8.30 |THREAD_NUM=8 |
|[[ctags-exuberant>Prog/TagSystem#ctags-xuberant]] |ctags-exuberant -e -R <path> |14.00 | |
// |[[Silent Bob>Prog/TagSystem#silent-bob]]  |bob --make-ctags&br;bob --cfiles&br;bob -L cfiles --call-tags|22.79 | |
-- 計測条件
--- 対象:linux-4.0.1
--- CPU:Core i7-7700HQ @ 2.8GHz (8Core)
--- Disk I/O:なし(tmpfs 上で計測)

//==============================================================================
** tag の生成 [#cscope-indexer]
- コンソールから
 $ cscope-indexer -r
- cscope-indexer のオプション
|~option |~description |
|-f <database-file> |出力先データベースのファイル名を指定する(default: cscope.out)|
|-i <list-file> |リストファイル(ファイルのインデックスを記録したファイル)の名前を指定する(default: cscope.files)|
|-l |データベースファイルの生成・更新を抑制する。&br;但し、リストファイルが生成済みであること |
|-r |再帰的にディレクトリを走査する。&br;このオプションがない場合、走査対象はカレントディレクトリに限定される。|
|-v |冗長モード |

- emacs 上の xcscope.el から
 C-c s L
- 結果(1)
|~[[TagSystem>Prog/TagSystem]] |~command      |~elapsed time [sec] |~remark |
|[[cscope>Prog/TagSystem/cscope]]             |cscope-indexer -r   |20.19 | |
|[[id-utils>Prog/TagSystem/id-utils]]         |mkid                |19.23 | |
|[[gtags-global>Prog/TagSystem/gtags]]        |gtags               |25.24 | |
|[[etags>Prog/TagSystem/etags]]               |find &#124; grep -i "\.h$\&#124;\.c$&#124;\.cc$&#124;\.cxx$&#124;\.cpp" &#124; xargs -P ${THREAD_NUM} -I {} etags -a {} |35.69 |THREAD_NUM=4 |
|[[ctags-exuberant>Prog/TagSystem/ctags-exuberant]] |ctags-exuberant -e -R <path> |16.36 | |
|[[Silent Bob>Prog/TagSystem/SilentBob]]     |bob --make-ctags&br;bob --cfiles&br;bob -L cfiles --call-tags|22.79 | |
-- 計測条件
--- 対象:linux-3.16.36
--- CPU:Core i7-3520M @ 2.90GHz (4Core)
--- Disk I/O:あり(HDD 上で計測)


** シンボルを探す [#la257bda]
|~key |~description |~remark |
|C-c s s |シンボルを指定して探す(定義・呼び出し箇所等の一覧をリストアップする)| |
|C-c s C |指定したシンボルの呼び出し箇所をリストアップ | |
|C-c s G |指定したシンボルの定義(宣言ではなく)、またはそれに関する定義をリストアップする | |
|C-c s n |次のシンボルへ Jump | |
|C-c s p |前のシンボルへ Jump | |




** xcscope のキーバインド一覧(xcscope.el ver.1.0) [#b0965a30]
 ;; * Keybindings:
 ;;
 ;; All keybindings use the "C-c s" prefix, but are usable only while
 ;; editing a source file, or in the cscope results buffer:
 ;;
 ;;      C-c s s         Find symbol.
 ;;      C-c s =         Find assignments to this symbol
 ;;      C-c s d         Find global definition.
 ;;      C-c s g         Find global definition (alternate binding).
 ;;      C-c s G         Find global definition without prompting.
 ;;      C-c s c         Find functions calling a function.
 ;;      C-c s C         Find called functions (list functions called
 ;;                      from a function).
 ;;      C-c s t         Find text string.
 ;;      C-c s e         Find egrep pattern.
 ;;      C-c s f         Find a file.
 ;;      C-c s i         Find files #including a file.
 ;;
 ;; These pertain to navigation through the search results:
 ;;
 ;;      C-c s b         Display *cscope* buffer.
 ;;      C-c s B         Auto display *cscope* buffer toggle.
 ;;      C-c s n         Next symbol.
 ;;      C-c s N         Next file.
 ;;      C-c s p         Previous symbol.
 ;;      C-c s P         Previous file.
 ;;      C-c s u         Pop mark.
 ;;
 ;; These pertain to setting and unsetting the variable,
 ;; `cscope-initial-directory', (location searched for the cscope database
 ;;  directory):
 ;;
 ;;      C-c s a         Set initial directory.
 ;;      C-c s A         Unset initial directory.
 ;;
 ;; These pertain to cscope database maintenance:
 ;;
 ;;      C-c s L         Create list of files to index.
 ;;      C-c s I         Create list and index.
 ;;      C-c s E         Edit list of files to index.
 ;;      C-c s W         Locate this buffer's cscope directory
 ;;                      ("W" --> "where").
 ;;      C-c s S         Locate this buffer's cscope directory.
 ;;                      (alternate binding: "S" --> "show").
 ;;      C-c s T         Locate this buffer's cscope directory.
 ;;                      (alternate binding: "T" --> "tell").
 ;;      C-c s D         Dired this buffer's directory.
 ;;

//==============================================================================
** xcscope のキーバインドが正しく動作しない場合 [#pf0b58f2]
- xcscope.el を組み込んだ後、
 C-c s
と打っても
 C-c s is undefined
とメッセージが出て動作しない場合は、xcscope.el が提供するマイナーモードに入れていない可能性がある。~
その場合は、c-mode-hook, c++-mode-hook に引っ掛けて ''cscope-minor-mode'' を呼び出すようにすると良い。
 ; c-mode での設定
 (setq c-mode-hook
       '(lambda ()
          (cscope-minor-mode)
          ))
 
 ; c++-mode でも同様に...
 (setq c++-mode-hook
       '(lambda ()
          (cscope-minor-mode)
          ))

//==============================================================================
** cscope で SymLink になっているファイルが扱えない問題について [#o8adfa9f]
- ソースコード・ヘッダが SymLink になっている場合、cscope では正しく DB 化出来ない。
- これは、cscope が DB 作成処理の際、 SymLink を対象外とするように動作する実装になっているためである。
- SymLink も DB 化の対象にするためには、以下を修正する必要がある:
 $ git diff
 diff --git a/cscope-15.8a/src/dir.c b/cscope-15.8a/src/dir.c
 index cf9330d..e73d86f 100644
 --- a/cscope-15.8a/src/dir.c
 +++ b/cscope-15.8a/src/dir.c
 @@ -651,7 +651,7 @@ accessible_file(char *file)
      if (access(compath(file), READ) == 0) {
  	struct stat stats;
  
 -	if (lstat(file, &stats) == 0
 +	if (stat(file, &stats) == 0
  	    && S_ISREG(stats.st_mode)) {
  	    return YES;
  	}
 

//==============================================================================
** 参考リンク [#xcscope-link]
- [[cscope Home Page>http://cscope.sourceforge.net/]]
- [[Emacsからcscopeソースコードナビゲータを使ってみよう>http://prog.quarklink.org/linux/xcscope/]]
- [[[Emacs] id-utils と cscope 導入してみた>http://d.hatena.ne.jp/khiker/20071018/cscope]]


////////////////////////////////////////////////////////////////////////////////
* acscope.el [#ascope]
- ascope.el は cscope の emacs 用 I/F の一つ。cscope は タグシステムの一つ
- [[xcscope.el>#cscope]] と比べて
-- 機能は少ない
-- xcscope.el と違って毎回検索を行わない分、
--- 結果表示までの時間は早い
--- 対象のソースコードに変更があった場合、検索結果に正しく反映されない場合がある
- debian では、 cscope は cscope パッケージに入っている
- この他、 emacs で使用するのに acscope.el を使う。debian8 にはパッケージはない。

//==============================================================================
** 導入 [#qd41bf62]
- debian8 のようにディストリビューションからパッケージが提供されていない場合は、[[GitHub>https://github.com/ameyp/ascope/blob/master/ascope.el]] または [[EmacsWiki>https://www.emacswiki.org/emacs/ascope.el]] などから Download して組み込む。~
但し [[EmacsWiki>https://www.emacswiki.org/emacs/ascope.el]] に掲載されているものは、 GitHub の最新版より大分古いようなので注意が必要。
-- GitHub から取得する場合
 $ git clone https://github.com/ameyp/ascope
- キーバインドを設定する
-- ascope.el ではキーバインドが設定されてない一方、関数名が xcscope.el と同じなので、xcscope.el から流用して設定する。~
#ただ、xcscope.el にあって ascope.el にないものが多い。
 (setq load-path (cons (expand-file-name "~/.emacs.d/site-lisp/ascope")  load-path))
 (load-library "~/.emacs.d/site-lisp/ascope/ascope.el")
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; Original is from xcscope.el
 (defvar cscope-minor-mode-keymap
   (let ((map (make-sparse-keymap)))
 
     ;; xemacs has various issues with (cscope-mouse-popup-menu-or-search), so I
     ;; don't use that function for xemacs. Its popup menu support won't be as
     ;; good (cscope will still prompt for the search term)
     ;(if cscope-running-in-xemacs
     ;    (progn
     ;      (define-key map [(shift button3)] 'cscope-mouse-search-again))
     ;  (define-key map [mouse-3]   'cscope-mouse-popup-menu-or-search)
     ;  (define-key map [S-mouse-3] 'cscope-mouse-search-again))
 
     ;; The following line corresponds to be beginning of the "Cscope" menu.
     (define-key map "\C-css" 'cscope-find-this-symbol)
     (define-key map "\C-csd" 'cscope-find-global-definition)
     (define-key map "\C-csg" 'cscope-find-global-definition)
     ; (define-key map "\C-csG" 'cscope-find-global-definition-no-prompting)
     ; (define-key map "\C-cs=" 'cscope-find-assignments-to-this-symbol)
     (define-key map "\C-csc" 'cscope-find-functions-calling-this-function)
     (define-key map "\C-csC" 'cscope-find-called-functions)
     (define-key map "\C-cst" 'cscope-find-this-text-string)
     ; (define-key map "\C-cse" 'cscope-find-egrep-pattern)
     (define-key map "\C-csf" 'cscope-find-this-file)
     (define-key map "\C-csi" 'cscope-find-files-including-file)
     ;; --- (The '---' indicates that this line corresponds to a menu separator.)
     ; (define-key map "\C-csb" 'cscope-display-buffer)
     ; (define-key map "\C-csB" 'cscope-display-buffer-toggle)
     ; (define-key map "\C-csn" 'cscope-history-forward-line-current-result)
     ; (define-key map "\C-csN" 'cscope-history-forward-file-current-result)
     ; (define-key map "\C-csp" 'cscope-history-backward-line-current-result)
     ; (define-key map "\C-csP" 'cscope-history-backward-file-current-result)
     ; (define-key map "\C-csu" 'cscope-pop-mark)
     ;; ---
     ; (define-key map "\C-csa" 'cscope-set-initial-directory)
     ; (define-key map "\C-csA" 'cscope-unset-initial-directory)
     ;; ---
     ; (define-key map "\C-csL" 'cscope-create-list-of-files-to-index)
     ; (define-key map "\C-csI" 'cscope-index-files)
     ; (define-key map "\C-csE" 'cscope-edit-list-of-files-to-index)
     ; (define-key map "\C-csW" 'cscope-tell-user-about-directory)
     ; (define-key map "\C-csS" 'cscope-tell-user-about-directory)
     ; (define-key map "\C-csT" 'cscope-tell-user-about-directory)
     ; (define-key map "\C-csD" 'cscope-dired-directory)
     ;; The previous line corresponds to be end of the "Cscope" menu.
 
 
 
     ;; (START Add) --------------------------------------
     ;; ここは xcscope.el にないものを追加
     (define-key map "\C-csa" 'cscope-setup)
     ;; (END   Add) --------------------------------------
 
     map)
   "The global cscope keymap")
 
 (require 'ascope)

//==============================================================================
** tagの生成 [#m97a4239]
- emacs 上のインターフェースが異なるのみで、cscope を使うという意味では [[xcscope.el>Editor/emacsen#xcscope]]と変わりない。&br;
tag の生成については [[tag の生成(xcscope.el)>Editor/emacsen#cscope-indexer]] を参照のこと。

//==============================================================================
** 参考リンク [#ascope-link]
- [[Erlcscope and ascope.el>http://masayuki038.github.io/blog/2013/09/23/erlcscope-and-ascope-el/]]
- [[ascope.el@github>https://github.com/ameyp/ascope/blob/master/ascope.el]]
- [[EmacsWiki>https://www.emacswiki.org/emacs/ascope.el]]


////////////////////////////////////////////////////////////////////////////////
* cscope-indexer の改造 [#cscope-indexer-modify]
- cscope で DB を用意する際に実行する
 $ cscope-indexer -r
だが、ソースやヘッダが SymLink だった場合は検索対象としないようになっている。~
これを敢えて検索対象としたい場合には、 cscope-indexer の改造が必要になる。
- cscope-15.8a 同梱の cscope-indexer への修正
-- find に -L を追加する。それに伴い、-type を -xtype に置き換える必要が出てくる。
 $ diff cscope-indexer.orig cscope-indexer.mod 
  137c137
 < 	find $DIR \( -type f -o -type l \)
 ---
 > 	find -L $DIR \( -xtype f -o -xtype l \)



////////////////////////////////////////////////////////////////////////////////
* id-utils [#id-utils]
//==============================================================================
** 導入 [#ne99dcda]
- debian の場合は、以下のパッケージをインストールする
 id-utils elscreen
- emacs 

//==============================================================================
** emacs の設定 [#h329a827]
- ${HOME}/.emacs.d/init.el に以下を追記
 ; id-utils
 (require 'elscreen)
 (require 'elscreen-gf)

//==============================================================================
** DB の生成 [#wd2fdf42]
- mkid コマンドで DB を生成する
-- コマンドラインから
 $ mkid
-- emacs から
 M-x: elscreen-gf-idutils-mkid

//==============================================================================
* symbol の検索 [#tb78737a]
- 検索
 M-x: elscreen-gf-idutils-gid
で、検索したいパターンを入力する
- 検索結果から Jump
-- カーソルで見たいところを選択し、
 o
または
 O (read-only で Jump 先が開かれる)


////////////////////////////////////////////////////////////////////////////////
* gtags / global の利用 [#gtags-global]
- タグシステムの一つ
- debian では、 global パッケージに入っている

//==============================================================================
** tag の生成 [#g0b7236d]
 $ gtags [options] [path]
 $ gtags -f <files>
 $ gtags -v
- gtags には、etags と違って append mode が存在しないため、xargs でマルチスレッド化して実行するのは不可かもしれない。
- -f <file> を指定しない場合、gtags はカレント以下のディレクトリを走査してタグ情報を生成する。
- tag の生成処理が終わると、実行したディレクトリ配下に、下記4つのファイルが作られる:
 GPATH GTAGS GRTAGS GSYMS

//==============================================================================
** emacs の設定 [#m88404b9]
-- gtags.el を入手する
--- ディストリビューションによっては、下記のようなパスにインストールされる場合もある
 /usr/share/emacs/site-lisp/global/gtags.el
--- もしディストリビューションで用意されていない場合は、手動で取得し、library-path の通っている場所に配置する。
--- 大文字・小文字を区別するように設定する~
→ [[検索時に大文字・小文字を区別するかしないかの設定>#case-fold-search]]
-- キーバインドを設定する
 ; "\M-p" が prefix-command に喰われていて使えないので、全て "\C-\M-" のシリーズにしている
 (global-set-key "\C-\M-t" 'gtags-find-tag)     ;関数の定義元へ
 (global-set-key "\C-\M-r" 'gtags-find-rtag)    ;関数の参照先へ
 (global-set-key "\C-\M-s" 'gtags-find-symbol)  ;変数の定義元/参照先へ
 (global-set-key "\C-\M-p" 'gtags-find-pattern)
 (global-set-key "\C-\M-f" 'gtags-find-file)    ;ファイルにジャンプ
 (global-set-key [?\C-,] 'gtags-pop-stack)      ;前のバッファに戻る

//==============================================================================
** 参考リンク [#a32e22f8]
- [[GNU GLOBAL(gtags)>http://cha.la.coocan.jp/doc/gnu_global.html]]
- [[新機能の御紹介>http://www.tamacom.com/handbook/new.html]]


////////////////////////////////////////////////////////////////////////////////
* etags (ctags for Emacs)の利用 [#etags]

//==============================================================================
** tag の生成 [#u1d75162]
- まずは、 Tag file を生成する。emacs パッケージには etags.emacs** なコマンドが付属している場合があるので、それがあればそちらを使う。
- Tag file は TAGS というファイル名で生成される。
 $ etags.emacs23 `find | grep -i "\.c$\|\.cc\|\.cpp$\|\.cxx$\|\.h$"
- ただ、ファイル数が多い場合にはコマンドラインバッファの上限を超えてしまい、全てのファイルを処理できないことが予想される。この問題は xargs を使って解消することが出来る。~
以下に、そのためのスクリプトを示す。~
下記の例では、 xargs の -P オプションも併用し、マルチスレッドで動作するようにしている。 THREAD_NUM は CPUの数もしくは Core 数に合わせる。
 #!/bin/bash
 TAGS_FILE=TAGS
 CMD_ETAGS=etags.emacs23
 THREAD_NUM=4
 rm -f ${TAGS_FILE};
 find | grep -i "\.c$\|\.cc\|\.cpp$\|\.cxx$\|\.h$" | xargs -P ${THREAD_NUM} -I {} ${CMD_ETAGS} -a {} # 対象となるソース・ヘッダを etags に引数で渡す
-- 全てのファイルを渡すのにコマンドバッファが足りなくなってしまう場合(=ファイル数が多い場合や個々のパス名が長い場合など)でも全てのファイルを渡せるよう、xargs を使って etags にファイル名を渡すようにしている。
-- コマンドバファが足りなくなった場合、 xargs は複数回 etags を呼ぶ。この場合、 etags が append モードで動作しないと etags は呼ばれる度に TAGS ファイルを上書きしてしまうので注意すること(そのため上記では append モードにするため "-a" を付けて etags を呼んでいる)。

//==============================================================================
** emacs に TAGS ファイルを読みこませる [#m5a7e186]
 M-x: tags-reset-tags-tables 一旦リセットする
 M-x: visit-tags-table 明示的に TAGS ファイルを読み込む
- emcs から操作する(下記)
|~Key binding  |~command |~description |
|M-.        |find-tag  |クラスや関数を探す |
|C-u M-.    | |次の検索結果候補を表示する |
|C-u – M-.  | |前の検索結果候補を表示する |
|M-*        |  |元の場所に戻る |
|C-x 4 .    |find-tag-other-window | 	タグ(名前)の定義箇所を探し別ウィンドウに表示 |
|C-x 5 .    |find-tag-other-frame  | 	タグ(名前)の定義箇所を探し別フレームに表示 |


//==============================================================================
** ctags-exuberant [#ctags-exuberant]
- install 後、実行ファイルは /usr/bin/ctags-exuberant に配置される。システムによっては /usr/bin/ctags に symlink されることもある。

//==============================================================================
** TAGS file の生成 [#oca9c6d9]
 $ ctags-exuberant -e -R [path]
- emacs からの使い方は、[[etags>Editor/emacsen#etags]] と基本的に同じ

//==============================================================================
** emacs から TAGS の生成を行えるようにする [#a7b3409c]
- ${HOME}/.emacs に下記の行を追加する:
 (setq path-to-ctags "/usr/bin/ctags-exuberant") ;; <- your ctags path here
 (defun create-tags (dir-name)
   "Create tags file."
   (interactive "DDirectory: ")
   (shell-command
    (format "ctags -f %s -e -R %s" path-to-ctags (directory-file-name dir-name)))
   )
- TAGS の生成を実行
 M-x: create-tags

//==============================================================================
** 参考リンク [#l7a6e3a8]
- [[BuildTags>http://www.emacswiki.org/emacs/BuildTags]]
- [[EmacsTags>http://www.emacswiki.org/emacs/EmacsTags]]


////////////////////////////////////////////////////////////////////////////////
* ebrowse (ebrowse for Emacs)の利用 [#ebrowse]
- etags/ctags 同様、C++ のコードから class のデータベースを作成し、それを emacs で読み込み、class 定義などに Jump 出来るというもの。
- まずは、 BROWSE file を生成する
 $ cd ${PROGRAM_TOP_DIR}
 $ find | grep "C$\|h$" | xargs ebrowse -f  # 対象となるソース・ヘッダを ebrowse に渡す
- emacs に BROWSE ファイルを読みこませる
 C-x C-f: ${PROGRAM_TOP_DIR}/BROWSE
- emacs から操作する
|~Key binding  |~command |~description |
|return        |ebrowse-find-class-declaration| 当該の class 定義に Jump |
|C-x 4 .       |find-tag-other-window  |- |
|C-x 5 .       |find-tag-other-frame   | - |

//==============================================================================
** Links [#scc713f1]
- [[A Class Browser for C++>http://www.sunsite.ualberta.ca/Documentation/Gnu/emacs-21.1/html_chapter/ebrowse.html]]


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS