我们的DMS 软件再造工具包正在努力成为您想要的工具。但它正在推动最先进的技术,并不是一种必杀技工具。做真正有趣的工作就足够了。
DMS 为解析、分析和转换源代码提供了通用工具。
它使用显式语法来定义语言(例如 C 和 C++);语法驱动构建抽象语法树(AST)的解析器。各种分析原语提供 a) 设施 [“属性语法”ATG] 用于沿着树状信息流路径收集信息,这些路径与 AST 的形状很好地匹配,b) 符号定义映射的符号使用构造 [“符号表”] , c)使用 ATG 提取的事实进行控制和数据流分析,d) 范围分析,e) 局部和全局点分析。这些原始分析器可用于组合来自 AST 的事实,以得出关于由 AST 表示的代码的结论(例如,“此语句修改这些变量”)。语言前端将语法和特定于语言的分析器打包在一个可重用的包中。DMS 具有针对各种语言的不同深度和成熟度的语言前端。
[编辑 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。如果你想准确分析代码,你应该使用“正确”的方言来处理你的代码。]
但“分析”不是重点。分析的目的是推动变革。DMS 提供了额外的支持以在程序上修改 AST,通过以语言的表面语法编写的源到源重写规则来修改 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++ 之外的许多语言执行此操作,并且可以针对它所知道的任意混合语言执行此操作。
在条件语句的预处理器问题得到解决之前,分析/转换 C 和 C++ 代码并不容易。我们只有凭借绝对的意志力和使用我们可以构建的最强大的工具才能在这些语言上成功完成这些任务。(Java 不存在这些问题,而 DMS 相应地更擅长分析/转换它)。
冒着狂妄自大的严重风险,我相信 DMS 是用于通用分析和转换的最佳工具。作为它的架构师,我将其视为我的长期工作,以使其更强大地完成这项任务。