写点什么

Gtags 解决 UnicodeEncodeError 问题

作者:alps2006
  • 2022-10-27
    上海
  • 本文字数:1582 字

    阅读完需:约 5 分钟

Gtags解决UnicodeEncodeError问题

背景

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 解析器时, 在有些情况下解析会报错终止, 导致符号生成失败, 错误如下.


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.


解决

通过上述的堆栈信息找到 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='')        ss.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, 先作罢吧.

参考

发布于: 刚刚阅读数: 4
用户头像

alps2006

关注

从事音视频即时通信领域开发, 喜欢瞎折腾. 2018-09-18 加入

从事音视频即时通信领域开发, 喜欢瞎折腾.

评论

发布
暂无评论
Gtags解决UnicodeEncodeError问题_alps2006_InfoQ写作社区