背景
Gtags
是 GNU global 的一个组件, 可以支持多个语言的符号生成, 索引等, 号称为最快的, 支持语言最多的符号索引工作, 可以在多个平台集成使用. Gtags 同时也支持源码变动的增量更新, 大大缩短了符号生成的时间. 目前最近的版本是 6.6.8
, 版本变更相关的信息可以查看 https://www.gnu.org/software/global/whatsnew.html
Gtags 可以使用通过 --gtagslabel
配置不同的源码解析器以便支持不同的语言及格式 , 主要的解析器有:
default
不配置时默认使用的内置 parser,只支持 asm, c/c++, java, php, yacc 语言.
ctags
使用 exuberant-ctags 作为语言 parser,支持 40+ 种语言,只能生成定义索引不能生成引用索引。
new-ctags
使用universal-ctags作为语言parser,支持 100+ 种语言,只能生成定义索引不能生成引用索引。虽然貌似universal-ctags已经支持生成引用tags,但是依然不能配合gtags工作(见这里),我也试了各种操作都没成功,也许是因为这个PR没有被merge。
pygments
使用pygments作为语言parser,号称支持300+种语言。
native-pygments
对于原生支持的6种语言使用内置parser,其他语言使用pygments作为parser。
当我们使用默认解析器或 pygments 解析器时, 在有些情况下解析会报错终止, 导致符号生成失败, 错误如下.
<pre>
Traceback (most recent call last):
File "/usr/local/Cellar/global/6.6.8/share/gtags/script/pygments_parser.py", line 264, in <module>main()
File "/usr/local/Cellar/global/6.6.8/share/gtags/script/pygments_parser.py", line 261, in main
handle_requests(langmap, parser_options)
File "/usr/local/Cellar/global/6.6.8/share/gtags/script/pygments_parser.py", line 228, in handle_requests
print(typ, tag, lnum, path, image)
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 8-15: ordinal not in range(256)
gtags: unexpected EOF.
</pre>
解决
通过上述的堆栈信息找到 pygments_parser.py
文件中的 228 行, 发现报错的地方是一个打印语句.
def handle_requests(langmap, options):
# Update ctags's path from the configuration file
global EXUBERANT_CTAGS
path = load_ctags_path()
...
...
...
while True:
path = sys.stdin.readline()
if not path:
break
path = path.rstrip()
tags = parser.parse(path)
for (isdef, tag, lnum),image in tags.items():
if isdef:
typ = 'D'
else:
typ = 'R'
print(typ, tag, lnum, path, image) # 执行到这句报错了
print(TERMINATOR, end='')
sys.stdout.flush()
如果正常打印到控制台应该是不会错误, 应该是 gtags 中读取控制台的输出的数据解析出错了. 通过在上方增加一个调试代码, 把输出控制台的数据输出到文件中看看.
print(typ, tag, lnum, path, image, file=open('/tmp/aa.txt', 'w')) # 新增调试语句
print(typ, tag, lnum, path, image)
通过输出的临时文件分析, 可以确定的是如果源码的路径参数(path 字段)存在非 ascii 字符时, 解析就会报错停止. 于是把原来的打印语句中的 path
参数进行 utf-8 编码.
print(typ, tag, lnum, path.encode('utf-8'), image)
进行以上修改后, 路径中存在非 ascii 字符时解析也能成功了.
本来还想着提交一个 pr 到 global , 但是看了下 global 的源码并不在 github 上管理. 如果要提交修改需要发邮件申请 contributor, 先作罢吧.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。