是否可以将代码转换的结果写回原始源文件?

Is it possible to write the result of code transformations back to the original source files?

我想对 多个 文件执行代码转换,并将这些转换产生的更改写回原文件,最好是原始文件。例如,我想向源自文件 fileA.c 的函数 funcA 和文件 fileB.c 中定义的函数 funcB 添加一个 if 语句。在 funcAfuncB 上执行转换后,我想用生成的源代码覆盖文件 fileA.cfileB.c。我不一定需要宏扩展之前的源代码(我怀疑这是不可能的)。

是否有使用 Frama-C 执行此操作的明智方法?

目前,您可以通过简单地将输出写入文件(使用选项 -print-ocode <file>)对单个文件执行此操作,如在:

frama-c file.c [add your transformation options here] -print -ocode file.c

这会起作用,因为 Frama-C 读取输入源文件以解析它们并在实际写入输出之前构建其 AST。因此,当它截断原始文件以开始覆盖它时,文件已经被完全读取。

请注意,严格来说,此行为将来可能会改变(换句话说,这 不是 推荐的使用方式 Frama-C,尽管它应该在实践中工作)。

但是,对于多个文件,目前这是不可能的:Frama-C总是将它们全部合并为一个,统一的 AST,在进一步处理之前。虽然 AST 元素确实保留了有关它们来自哪个源文件的位置信息,但目前没有任何内容告诉 pretty-printer 将每个部分输出到不同的文件。

请注意,一般来说,这有点复杂:C 允许多次声明全局变量,因此您可以有一个文件 a.c 声明一个 struct st; 而不指定其字段,然后另一个文件 b.c 实际上声明了它的字段;当 pretty-printing 这些文件时,您需要记住所有原始声明。根据所执行的语法更改的类型,这些可能会影响某些声明,但不会影响全部。

总的来说,我认为理论上 可能 以某种方式告诉 Frama-C 记住所有这些细节并尝试使用位置信息来 pretty-print 它的AST 到多个文件(如果我们包括逻辑预处理,带有 ACSL 注释等,我什至不确定这是否可行),但它需要对内核进行 deep 更改。

因此,目前我认为没有明智的方法告诉 Frama-C 去做,至少在一般情况下是这样。对于一些与之相关的特定子任务(例如,pretty-printing 一些 select 全局变量),可以创建一个 AST 访问者,当访问这些元素时,pretty-print 将它们保存到一个文件中其名称与原始名称相关(例如,对于位置为 f.c 的 AST 节点,将其打印为 f-out.c)。但是确保这些文件在 all 情况下在语法上是有效的 C 会使它变得更加复杂。并且至少需要为脚本编写相当数量的 OCaml 代码。