关于嵌套头文件的处理

Vim、Emacs配置和使用
回复
kevinlei
帖子: 40
注册时间: 2007-01-13 14:45

关于嵌套头文件的处理

#1

帖子 kevinlei » 2011-09-17 16:01

fanhe 写了: 基于ctags的自动完成基本完工了, 只是暂时纠结与头文件嵌套包含处理问题.
有没有 python 写的头文件扫描程序, 即扫描出本源文件包含的所有头文件, 要求速度尽量快且必须支持缓存结果, 我现在仅有一个 vim 版本的, 用了 vimgrep, 残留了一大堆卸载 buffer, 看着不舒服
stl 的处理方法也知道了, 暂时还没搞, 所以没放出来
现在正忙着和项目管理模块的集成.
今天在坛子上瞎逛,看见fanhe兄提出了这个问题,不由得会心一笑,因为在写ctags_cache的时候,我也碰见这个问题了,这是个很有趣的问题。

看看发贴时间,已经过去3个月了,想必fanhe兄已经解决这个问题了。我在这儿也提出我自己的解法,博方家一笑耳。

首先,我们知道,从某个.c文件开始,一直向上寻找其include的.h文件,假如把每个.c或者.h文件看作一个节点的话,最终我们会得到一个有向图:

代码: 全选

      /b.h---e.h----\
     /      /        \
    /      /          \
a.c\---c.h/--f.h------h.h
    \                /
     \              /
      \d.h---g.h---/
而当出现循环依赖时,则意味着图里面出现了环路。

判断是否存在环路,可以采用标记法:

每个节点上都增加一个标志字段。当我们发起遍历的时候,把开始节点上的标志置为1,然后逐个节点看过去,当发现节点上的标志已置位,就说明我们回到了起点。这个时候就可以采取措施打破环路了。

归结到c语言自动补全这个具体的问题上,打破环路的措施还得看具体程序架构。

我是采用如下做法:

当打开一个.c或.h文件的时候,先去节点池里查找是否已存在相应节点,有则引用记数加1,无则创建新节点,并把新节点的check_loop标志置1。创建新节点的时候,会查找其头文件的节点,若已有,则引用记数加1,无则创建新节点。如此递归下去。当发现某个节点已有,并且check_loop为1,就说明碰上环路了,这个时候既不增加引用记数也不干别的,直接返回。

而关闭一个.c或.h文件的时候,只是递减相应节点的引用记数,如果引用记数为0,才真正从节点池删除这个节点。而真正删除的时候,才会去递减其依赖的头文件的引用记数。这也是个递归的过程。这个过程中,因为头文件有可能存在循环依赖,就需要避免多次删除同一个节点。我的办法是删除前查看节点池里是否还有这个节点。

我的解法就是这样了,抛块窑砖,静候美玉。 :em06

P.S. ctags_cache里的头文件扫描那一段,还是比较独立的,fanhe兄如果需要可以试试。不过现在fanhe兄大概用不着了吧。
头像
fanhe
帖子: 2357
注册时间: 2007-03-24 23:45

Re: 关于嵌套头文件的处理

#2

帖子 fanhe » 2011-09-17 20:08

我是直接用 cache 的方法的,好像用的是字典还是集合,忘了,python 的
有了 cache 也就第一次扫描的时候慢点,其他时候还是满快的
只是,我现在的 VimLite 都是单线程的,保存文件的时候会感觉有一点延时。多线程的会慢慢做出来的。
回复