有没有命令行工具可以从C或C++文件中提取typedef、结构体、枚举、变量、函数?

12
我需要一个命令行工具来从C或C++源文件中提取定义或声明(typedef、结构、枚举、变量或函数)。同时,一个替换现有定义/声明的方法也很方便(在通过用户提交的脚本转换提取的定义之后)。是否有这样通用的工具可用,或者是否有某个合理接近这样的工具?
脚本化和与用户创建的脚本或程序连接的能力在这里很重要,尽管我也对GUI程序抱有学术兴趣。Unix/Linux阵营的开源解决方案是首选(尽管我也对Windows和OS X工具很好奇)。主要语言兴趣是C和C++,但更通用的解决方案会更好(我认为我们不需要超精确的解析能力来查找、提取和替换程序源文件中的定义)。
示例用例(额外 - 对于好奇的人):
- 给定嵌套的struct和这些类型的变量(数组)初始化,假设需要通过添加或重新排序字段或以更易读的格式重写变量/数组定义来更改struct定义,而不引入手动劳动导致的错误。这将通过提取旧的初始化,然后使用脚本/程序编写新的初始化来替换旧的初始化来工作。 - 用于实现代码浏览工具 - 提取定义。 - 装饰性代码生成(例如日志功能条目/返回)。 - 脚本代码结构化(例如提取这个和那个东西并将其放在不同的地方而不改变 - 版本控制提交注释可以记录执行此操作的命令,以使显然且可验证没有更改)。
备选问题:如果有一个工具告诉定义的位置(开始和结束行就足够了 - 我们甚至可以假设我们感兴趣的所有定义/声明都在它们自己的行中),那么编写程序来提取定义、替换定义甚至是一个简单的手指灵活性练习。
  • 提取定义,运行由命令行选项(或编辑器)指定的程序以

    • stdin(或临时文件)接收所需的提取定义,
    • 执行变换(编辑),并且
    • 将新的定义输出到stdout(或保存到给定的临时文件)

    以被执行的程序替换。

  • 因此,主要且更具挑战性的问题是找到定义的起始和结束行。

    关于标签的注释:code-generation这个标签比code-transformation更准确,但它不存在。


    2
    我所说的C/C++指的是C或C++。我主要关注C(我正在积极使用和处理遗留代码),但C++也很有趣(如果可以选择,我更喜欢用于清晰的项目)。对于所描述的任务,您不需要非常精细地理解语言语法,因此C和C++之间的差异似乎并不那么重要。 - FooF
    1
    可能应该删除[tag:automation]--我期望它与装配线系统有关,尽管当前标记几乎没有用处。这将为您提供一个额外的选择.. [tag:tools] 也可以被替换为更具体的内容。如果没有合适的标签,请随意创建一个新的标签... :) - sarnold
    1
    希望有用:http://gcc-melt.org/ 和 https://sparse.wiki.kernel.org/index.php/Main_Page。我认为这两个系统都无法让你重新编写源代码,但它们可能对理解和知识能力有用。 - sarnold
    1
    你想要的标签不是"code-transformation",而是"program-transformation"。请参考http://en.wikipedia.org/wiki/Program_transformation。 - Ira Baxter
    1
    我认为DMS在以下四个方面与Clang不同:a)已经证明能够处理混合任意语言[你今天可能不关心C/C++,但明天你会关心],b)源到源的转换[Clang的转换必须通过爬行ASTs进行过程化编写],c)转换的可组合性[完成一个转换后,您可以执行另一个转换;Clang的发出源文本补丁作为xform禁用了这一点],d)并行计算基础[这对于处理大型程序很重要]。如果您今天可以使用Clang做您想要的事情,那么它是一个完全可以胜任的工具。 - Ira Baxter
    显示剩余12条评论
    3个回答

    4
    我们的 DMS软件重构工具包 试图成为您所期望的工具。但它正在推动技术的发展,不是一种完美的工具。它足以完成真正有趣的工作。
    DMS提供了解析、分析和转换源代码的通用工具。
    它使用显式语法来定义语言(如C和C ++); 语法驱动解析器构建抽象语法树(AST)。各种分析原语提供a)用于沿着类似树形信息流路径收集信息的设施[“属性语法”ATG],这些路径与AST的形状很好地匹配,b)构建符号使用到符号定义映射[“符号表”],c) 控制和数据流分析使用由ATG提取的事实,d)范围分析,e)本地和全局指针分析。这些原始分析器可以用于从AST中组合事实,从而得出有关AST所代表的代码的结论(例如,“此语句修改这些变量”)。语言前端将语法和特定于语言的分析器打包在一起,以便重复使用。DMS具有各种深度和成熟度的语言前端,适用于各种语言。 < p > 【6/27更新:C和C++前端支持特定的C和C++方言:ANSIC、C99、GCC3/4 C、MS Visual C、ANSI C++98、ANSI C++11、GCC3/4 C++、MS Visual C++ 2005/2008/2010。如果您想要准确分析代码,应该使用“正确”的方言来处理您的代码。】 < p >但是,“分析”并不是重点。分析的目的是推动变革。DMS提供了额外的支持,以程序方式修改AST,通过使用语言表面语法编写的源到源重写规则(在某些选择的分析结果的条件下),或将一组过程和源到源重写组合在一起,以进行复合、复杂的重写,可以进行大规模的代码更改,如重新架构等。在AST被转换后,它们可以用于重新生成(“漂亮打印”)相应前端语言/方言的语法正确的代码。【通过逐步修改一个语言的AST,直到你有另一个语言的AST,你可以建立翻译器,但这并不像这个句子暗示的那么容易。】 这一切在相当程度上都能够正常工作,但仍然受到某些语言复杂性的限制。对于C和C++来说,一个著名的复杂性是预处理器;通过任意编辑程序文本,预处理条件可以使源代码无法被任何类似标准解析技术的东西解析。DMS的C和C++前端在一定程度上改善了这种情况,并且可以解析具有良好结构的预处理指令的代码,包括一些大多数人不会称之为结构化但通常会出现的奇怪情况。
       #IF  cond
            if (abc)  {
       #ELSE
            if (def)  {
       #ENDIF
    

    我们正在解析具有任意预处理条件放置的代码方面取得有趣的进展。但一旦这样做,现在所有的分析器突然都必须考虑预处理条件,并且我们都突然陷入了编译器人员尚未真正访问的领域。
    DMS已被用于在大型C++程序中进行重大架构转变,将非CORBA风格转换为CORBA风格,并进行了大量的代码重组,从而提取出沿任意控制流路径的代码,为现有的C代码生成SOW风格的API,并在大型C程序中插入工具以检测指针错误等。[它已经应用于其他语言的许多其他任务]。
    根据我们自己的经验,它仍然很难使用。在我们看来,这是因为它与民主制度是最糟糕的政治制度之一,除了其他所有制度; YMMV。该网站有许多基于DMS的工具和讨论。
    事实上,它已经被用于提取函数(SOW练习比这更普遍),并插入函数(这是插装的广义情况)。
    像GCC-XML这样的工具只是DMS功能的影子。GCC-XML解析、构建符号表并转储数据声明(而不是代码),但它无法进行任何代码更改。Clang更好一些;它将C和C++解析为AST,可以在LLVM中间表示上进行分析,并具有某种机制,可以根据所需的树形更改来生成稍后应用的补丁源文本。我不知道Clang是否能够执行大规模的代码转换,特别是那些一个转换结果再次被转换的情况(如何修改延迟文本补丁的树形?)。DMS可以全天候进行此操作,并且可以对许多其他语言以及其中任意混合的语言进行操作。
    在条件预处理器问题得到解决之前,分析/转换C和C++代码将不容易。我们只能凭借意志力和使用我们能够构建的最强大的工具来完成这些语言的任务。(Java没有这些问题,因此DMS在分析/转换Java方面表现得更好)。

    虽然存在傲慢的风险,但我认为DMS是最好的通用分析和转换工具。作为它的架构师,我将其视为我的长期任务,使其在这个任务上更加强大。


    听起来非常雄心勃勃、强大、有趣和有用。即使我主要关注开源解决方案,而且目前没有钱可花,我肯定打算了解更多关于你们的产品(如果不是出于学术好奇心,那就是为了别的什么)。感谢您也评论了一些困难,并没有让一切听起来太美好。我也经历过C预处理器层使一些工具在C代码上产生糟糕结果的情况(GNU indent 很快就会浮现在我的脑海中)。 - FooF

    3
    你可以考虑使用GCC-XML作为开发类似工具的基础。我曾经结合pygccxml使用它来自动提取深度嵌套的结构成员。这不会让你的工作变得轻松,但肯定比没有使用好。我也听说clang可以作为编写这种工具的基础,但我自己还没有机会深入研究它。

    我也尝试使用gccxml作为显而易见的选择,但是在我的测试中除了错误之外,很快就没有任何结果。(我手头有糟糕的遗留代码,该代码实际上针对不同的架构(ARM和MIPS),而且最重要的是gccxml将代码视为C++(http://www.gccxml.org/HTML/FAQ.html问题1)。 - FooF
    @FooF:关于“将代码视为C ++”的那一点表明,您实际上需要针对正在处理的语言的特定方言进行语言精确解析。对语法位的含义的微小差异可能会导致后续过程中提取/转换的重大差异。(当遇到包含不同编译器的代码的预处理器条件时,这个问题变得棘手。) - Ira Baxter

    2
    你可以看看Clang。他们有非平凡的源代码处理库。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接