5

我有一组遗留的 C 代码,我正在重构这些代码以将 C 计算代码从 GUI 中分离出来。这由于高度递归的数学核心代码是 K&R 风格的声明而变得复杂。由于函数参数的嵌套使用,我已经放弃了将这些转换为 ANSI 声明的尝试(只是无法消除最后 4 个编译器错误)。

我需要将一些文件移动到纯 DLL 中并确定要公开的最小接口,这将需要编写包装函数来发布类型化接口。

我已经使用 Doxygen @callergraph 标记标记了关键源文件,以便为各个函数生成信息图。除此之外,我想做的是合并这些图表,这样我就可以确定暴露给外界的函数的最窄边界。

原始头文件没有用——它们将所有内容都暴露为无类型的 C 函数。

有数百个函数,所以对生成的调用者图的简单检查是痛苦的。

我正在考虑编写某种 DOT 合并工具 - 设置 DOT_CLEANUP=NO 使 Doxygen 将中间 DOT 文件留在那里,而不是只保留它们生成的 png 文件。

我并不沉迷于这是一个图形解决方案——如果有人可以建议一种替代分析工具(免费或相对便宜)或使用 Doxygen 的 XML 输出来实现相同目标的技术,我会非常高兴。

在文件级别合并的调用者图表确实对客户文档而不是普通列表具有一定的吸引力:-)

4

3 回答 3

6

在你的 Doxyfile 中,设置

GENERATE_XML = YES

然后您可以在 XML 文件中找到您的调用图。对于标有调用者图的每个函数,您会<referencedby>在输出中找到可以使用的元素。这是我的一个 C 文件的示例:

  <memberdef kind="function" id="spfs_8c_1a3"
             prot="public" static="yes" const="no" explicit="no"
             inline="no" virt="non-virtual">
    <type>svn_error_t *</type>
    <definition>svn_error_t * init_apr</definition>
    <argsstring>(apr_pool_t **ppool, int *argc, char const *const **argv)</argsstring>
    <name>init_apr</name>
    <!-- param and description elements clipped for brevity ... -->
    <location file="src/spfs.c" line="26" bodystart="101" bodyend="120"/>
    <referencedby refid="spfs_8c_1a13" compoundref="spfs_8c"
                  startline="45" endline="94">main</referencedby>
  </memberdef>

因此,对于每个 memberdef/referencedby 对,您都有一个调用者-被调用者关系,您可以通过 XSLT 获取它:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text"/>

    <xsl:template match="/">
        <xsl:apply-templates select="//memberdef[@kind eq 'function']"/>
    </xsl:template>

    <xsl:template match="memberdef">
        <xsl:variable name="function-name"
                      select="concat(definition, argsstring)"/>
        <xsl:for-each select="referencedby">
            <xsl:value-of select="concat(./text(), ' calls ', $function-name, '&#xA;')"/>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

它为每个调用者-被调用者提供了一条线,如下所示:

main calls svn_error_t * init_apr(apr_pool_t **ppool, int *argc, char const *const **argv)

您需要调整该 XSLT,然后以跨越最少边的方式对该有向图进行分区。呜呼,一个NP完全问题!幸运的是,有很多关于这个主题的论文,其中一些在这里: http: //www.sandia.gov/~bahendr/partitioning.html

于 2009-08-28T21:08:53.980 回答
1

我有类似的要求。编写了一个 perl 脚本,将一组点文件合并为一个点文件。

https://github.com/bharanis/scripts/blob/master/doxygen_dot_merge.pl

合并多个 doxygen 生成的点文件。这对于为一个文件或一堆文件生成调用映射很有用。

1) 该命令将从 doxygen 放置所有 html、dot 和 map 文件的 html 目录外部运行。

2) 此命令假定 doxygen CREATE_SUBDIRS = NO 中使用的平面目录结构

3) doxygen 将源文件名作为输出点文件名的前缀。每个函数生成一个点文件

4)提供要合并的doxygen生成的点文件列表。例如:

./doxydotmerge.pl  `ls html/ssd_*_8c*_cgraph.dot  | grep -v test | grep -v buf`
于 2013-02-19T23:38:50.930 回答
0

您可以使用 Scientific Toolworks 查看系统范围的调用图。

如果您想自动化分析和切割,您可以考虑使用 DMS 软件再造工具包。它可以计算 C 的完整调用图(完成对函数指针的指向分析),并已在 3500 万行代码的系统中得到证明。它将生成完整的系统 DOT 文件以进行检查;它们非常大,但您可以挑选出要查看的子集。请参阅流分析和调用图

于 2009-08-16T19:23:40.350 回答