Linux-使用 - yanbin's Blog
vim 中使用 cscope 的方法。
0. cscope 依赖 $EDITOR, $CSCOPE_DB 环境变量。
使用 vim 打开 cscope 的搜索结果,需要设置 $EDITOR 环境变量为 vim.
$ vim ~/.bashrc
# add: export EDITOR=vim
$ source ~/.bashrc
NOTE: 很多工具都依赖 EDITOR 这个环境变量,修改这个环境变量的值时需考虑其影响范围。
vim 启动时默认加载当前工作目录下的 cscope database 文件,并且与 database 建立连接。
在 ~/.bashrc 或者类似的文件中设置 $CSCOPE_DB 环境变量,vim 启动时也会自动加载 $CSCOPE_DB
指定路径的 database 文件,并与 database 建立连接。
$ vim ~/.basrch
# add: export CSCOPE_DB=/path/to/cscope_db_file
$ source ~/.bashrc
如果这个 database 文件用在系统中的所有工作目录,其中存储的文件路径应该是绝对路径,
不然只能用在特定的工作目录了。
如何做到这一点呢?下面 1.2 给出方法。
1. cscope 的一些用法与 ctags 相同。
1.0 cscope 也支持 -R 参数,在不加 -b 参数时,cscope 运行一个curses-based GUI.
CTRL-d 退出该 GUI, 实际上也退出了 cscope.
Find this C symbol:
Find this global definition:
Find functions called by this function:
Find functions calling this function:
Find this text string:
Change this text string:
Find this egrep pattern:
Find this file:
Find files #including this file:
Find assignments to this symbol:
Find this global definition:
Find functions called by this function:
Find functions calling this function:
Find this text string:
Change this text string:
Find this egrep pattern:
Find this file:
Find files #including this file:
Find assignments to this symbol:
debug 一些问题时,经常出现(a)找到某个 error message 是在哪里打印的;
(b)某个打印 error message 并且退出程序的函数是如何实现/定义的;
(c)某个宏定义的值是什么; (d) 包含某个头文件的其他文件;
(e)函数的定义以及调用的地方; 诸如此类的需求,却无需关注全部代码,用这个工具非常方便。
cscope 还支持: (f) 使用 egrep 格式搜索字符串; (g) 根据文件名 find 文件; 实在方便。
1.1 cscope -R -b 直接搜索/遍历整个源码树,生成 cscope.out 数据库文件并退出程序。
cscope.out 类似 ctags -R 生成的 tags 文件。
内置 cscope support 的 vim 程序自动加载当前目录下的 cscope.out 文件。
FIXME: 不支持功能的 vim 又该如何设置才能自动化的加载 cscope.out 文件?
可以考在 .vimrc 中添加如下代码:
" add any cscope database in current directory
if filereadable("cscope.out")
cs add cscope.out
elseif $CSCOPE_DB != ""
cs add $CSCOPE_DB
endif
if filereadable("cscope.out")
cs add cscope.out
elseif $CSCOPE_DB != ""
cs add $CSCOPE_DB
endif
1.2 根据多个目录中文件的绝对路径生成 database 文件。
获得所有需要的文件的绝对路径,存放在一个文件中。
$ find /path/to/myproject -name "*.c" -o -name "*.h" > /path/to/foo/cscope.files
$ cd /path/to/foo # 保证 foo 中没有其他文件
$ cscope -b
# 在 ~/.bashrc 中添加: export CSCOPE_DB=/path/to/foo/cscope.out
2. vim 中使用 cscope 的方法。 vim 支持短命令 :cs; cs 即 cscope 的缩写。
2.0 :cs 命令基础用法。
0) cscope find 操作, 支持如下选项:
USAGE :cs find {querytype} {name}
0 or s: Find this C symbol
1 or g: Find this definition
2 or d: Find functions called by this function
3 or c: Find functions calling this function
4 or t: Find this text string
6 or e: Find this egrep pattern
7 or f: Find this file
8 or i: Find files #including this file
1 or g: Find this definition
2 or d: Find functions called by this function
3 or c: Find functions calling this function
4 or t: Find this text string
6 or e: Find this egrep pattern
7 or f: Find this file
8 or i: Find files #including this file
这些选项对应不同的搜索方式。
数字用来代替字母,作为一种记忆方式,方便不同的个人习惯选择。
1) find 选项使用举例。
:cs find c vim_free
:cs find 3 vim_free
:cs find 3 vim_free
这两个例子都执行 Find functions calling this function;
NOTE: 'vim_free' 和 '3' 之间有个'空格', 这种搜索方式会乎略此类‘空格’。
:cscope find t initOnce
:cscope find 4 initOnce
:cscope find 4 initOnce
这两个例子都执行: Find this text string;
NOTE: 与其他搜索方式不同, t or 4 以及 e or 6 方式会处理字符串的前后'空格'。
FIXEME: find t or find 4 是如何对待 ' 和 " 这两个字符的?
其他搜索方式又是如何对待这两个字符呢?
所有的搜索方式都将 ' or " 视为 name(字符串) 的一部分,
无论 ' or " 在字符串的开始、结尾或中间。
NOTE: since Cscope by default parses all C header files it finds in /usr/include,
you can open up most standard include files with this
:cscope find s oping_receive_one
结果如下:
Cscope tag: ping_receive_one
# line filename / context / line
1 445 src/liboping.c <<ping_receive_one>>
static int ping_receive_one (pingobj_t *obj, const pinghost_t *ph,
2 706 src/liboping.c <<ping_receive_all>>
if (ping_receive_one (obj, ptr, &nowtime) == 0)
# line filename / context / line
1 445 src/liboping.c <<ping_receive_one>>
static int ping_receive_one (pingobj_t *obj, const pinghost_t *ph,
2 706 src/liboping.c <<ping_receive_all>>
if (ping_receive_one (obj, ptr, &nowtime) == 0)
Type number and <Enter> (empty cancels):
从左至右依次为:
(a)搜索结果编号;(b)结果所在文件行号;(c)结果所在文件名;(d)搜索内容;(e)结果所在行文本;
输入「结果编号」后「回车」,vim 跳转到至一行;使用 CTRL-t 回退。
什么也不输入直接按「回车」可退出本次搜索。
如果只搜索到一个结果,会直接跳转过去。
2) vim 中使用 cscope 需要注意的一点。
保证 ~/.vimrc 或者 /etc/vim/vimrc 以及其他 plugin 里没有这一行:
set cscopequickfix=s-,c-,d-,i-,t-,e-
这样会导致使用 scscope quick window 功能,这个功能实在难用。
执行完 :cs find s token 之类的操作,不显示结果列表窗口,而是只有一行,既不能选中,
也不能翻页,叫人着急的想骂娘。
3) 进阶用法:
a) 更加简略的命令格式
:cs f s foo
b) 水平分割当前 vim 窗口显示某个搜索结果
:scs f s foo # 前面的 s 即为 split
c) 垂直分割当前 vim 窗口显示某个搜索结果
:vert scs f s foo # vert 是 vim 命令
2.1 使用插件, 映射 find 操作的快捷键。
cscope 官方教程提供了 cscope_maps.vim 插件。
将这个插件放到 /etc/viim/plugin 目录或者 ~/.vim/plugin 目录。
0) cscope_maps.vim 提供了如下快捷方式, 直接搜索光标(cursor)所在位置的 token or text.
<CTRL-\>s # symbol: find all references to the token under cursor
<CTRL-\>g # global: find global definition(s) of the token under cursor
<CTRL-\>c # calls: find all calls to the function name under cursor
<CTRL-\>t # text: find all instances of the text under cursor
<CTRL-\>e # egrep: egrep search for the word under cursor
<CTRL-\>f # file: open the filename under cursor
<CTRL-\>i # includes: find files that include the filename under cursor
<CRTL-\>d # called: find functions that function under cursor calls
<CTRL-\>g # global: find global definition(s) of the token under cursor
<CTRL-\>c # calls: find all calls to the function name under cursor
<CTRL-\>t # text: find all instances of the text under cursor
<CTRL-\>e # egrep: egrep search for the word under cursor
<CTRL-\>f # file: open the filename under cursor
<CTRL-\>i # includes: find files that include the filename under cursor
<CRTL-\>d # called: find functions that function under cursor calls
1) 使用举例:
(a) 光标移动到要搜索的 token or text;
(b) 同时按下 CTRL 和 \ 「反斜线」键,松开后立即按下 s 键,即执行 :cs find s token 操作;
(c) 搜索结果如同 :cs find;
2) 高级用法,显示某个搜索结果而又不影响当前窗口:
vim 提过了 split 功能,支持水平和垂直分割窗口,可以在一个新的分割窗口中显示结果。
使用 cscope_maps.vim plugin 中提供的快捷键可以方便的做到这一点。
(a) 使用 <CTRL-@> 代替 <CTRL-\>, 搜索方式相同而打开结果时会从一个水平窗口打开,
<CTRL-@> 在 vim 中用 <CTRL-spacebar>代替;
(b) 光标移动要搜索的 token or text;
(c) 同时按下 CTRL 和「空格」键,松开后立即按下 s 键,即执行 :cs find s token 操作;
(d) 搜索结果等同于 :cs find, 显示某个结果时水平分割当前窗口,显示在新窗口中。
(e) 同样是 :cs find s token, 垂直显示结果,则是 <CTRL-@><CTRL-@>s。
在 vim 中需要连续两次键入 CTRL-空格,然后再按下 s 键。
3) 使用 cscope_maps.vim plugin 需要注意的地方:
cscope_maps.vim plugin 多次一举的包含了如下代码:
" add any cscope database in current directory
if filereadable("cscope.out")
cs add cscope.out
elseif $CSCOPE_DB != ""
cs add $CSCOPE_DB
endif
if filereadable("cscope.out")
cs add cscope.out
elseif $CSCOPE_DB != ""
cs add $CSCOPE_DB
endif
这些代码可能与 vimrc 中代码相冲突,或者与 vim 内置功能相冲突,因为它们都执行了
加载当前目录下 cscope.out 数据库操作。vim 会启动时会提示如下错误:
Error detected while processing /home/username/.vim/plugin/cscope_maps.vim:
line 45: E568: duplicate cscope database not added
Hit ENTER or type command to continue
line 45: E568: duplicate cscope database not added
Hit ENTER or type command to continue
私以为直接注释掉 scsope_maps.vim plugin 中的这几行代码就好了。
也有人说在 ~/.vimrc 里加上: set nocscopeversbose 之类的,这完全不治本嘛。
shell 管道两端的程序,并不是左边的程序先启动
$ ps aux | grep "demo"
这条命令中的 ps 先启动,会导致程序异常退出。
因为写一个没有读端的管道,引发 SIGPIPE 信号,SIGPIPE 信号默认行为是终止程序的执行。
管道的创建者(shell) 先创建管道,启动 read 管道的程序 (grep), 再启动 write 管道的程序(ps aux).
读一个没有写端的管道会阻塞,grep 可以接受阻塞。
$ ps aux | grep "demo" | grep -v "grep"
这样的命令相当于: (ps aux | grep "demo") | grep -v "grep".