7

我正在尝试编写一个程序来检查某些 C 源代码是否符合变量命名约定。为此,我需要分析源代码并识别所有局部和全局变量的类型。

最终结果几乎肯定会是一个 python 程序,但分析代码的工具可以是 python 模块,也可以是生成易于解析的报告的应用程序。或者(在下面详细介绍)它可能是从编译器中提取信息的一种方式(通过报告或类似方式)。如果这很有帮助,很可能是Keil ARM 编译器。

我一直在尝试使用ctags,这对于查找所有 typedef 和宏定义等非常有用,但它没有提供查找变量类型的直接方法,尤其是当定义分布在多行时(其中我希望不会!)。

示例可能包括:

static volatile u8 var1; // should be flagged as static and volatile and a u8 (typedef of unsigned 8-bit integer)
volatile   /* comments */   
    static /* inserted just to make life */
        u8 /* difficult! */   var2 =
        (u8) 72
           ; // likewise (nasty syntax, but technically valid C)
const uint_16t *pointer1;  // flagged as a pointer to a constant uint_16t
int * const pointer2; // flagged as a constant pointer to an int
const char * const pointer3; // flagged as a constant pointer to a constant char
static MyTypedefTYPE var3; // flagged as a MyTypedefTYPE variable
u8 var4, var5, var6 = 72;
int *array1[SOME_LENGTH]; // flagged as an array of pointers to integers
char array2[FIRST_DIM][72]; // flagged as an array of arrays of type char

等等等等

它还需要确定它们是本地变量还是全局/文件范围变量(ctags 可以这样做),如果它们是本地变量,我最好是在其中声明它们的函数的名称。

另外,我想对函数做类似的事情:识别返回类型,它们是否是静态的以及它们所有参数的类型和名称。

不幸的是,这对于 C 语法来说是相当困难的,因为参数顺序有一定的灵活性,并且参数之间允许的空白数量有很大的灵活性。我曾尝试过使用一些花哨的正则表达式来完成这项工作,但这远非理想,因为可以应用的情况太多了,因此正则表达式很快变得难以管理。我不禁认为编译器必须能够做到这一点(为了工作!),所以我想知道是否可以提取这些信息。Keil 编译器似乎为每个编译的源文件生成一个“.crf”文件,这似乎包含该文件中声明的所有变量,但它是二进制格式,我不能 找不到有关如何解析此文件的任何信息。或者,从 ctags 中获取信息的方法将是完美的。

任何人都可以为此提供任何帮助,我们将不胜感激。

谢谢,

4

5 回答 5

5

有许多 Python 解析器包可用于描述语法,然后它将生成 Python 代码来解析该语法。

Ned Batchelder 写了一个很好的总结

其中,Ply 用于解析 C 源代码的名为pycparser的项目中。我建议从这个开始。

其中一些其他解析器项目可能也有示例 C 解析器。

编辑:刚刚注意到 pycparser 甚至有一个示例 Python 脚本来解析 C 类型声明,就像旧的 cdecl 程序一样。

于 2009-04-22T18:17:02.200 回答
3

从另一边完全接近它怎么样。您已经拥有一个完全理解 C 类型系统所有细微差别的解析器:编译器本身。因此,使用完整的调试支持编译项目,并深入了解调试数据。

对于基于binutils支持的格式的系统,您需要的大部分细节都可以通过BFD库学习。

MSDN 上的库和文档(在某种程度上)支持 Microsoft 的调试格式,但我的 Google-fu 今天很弱,我不会将我知道存在链接到此处的文章放在手上。

Keil 8051 编译器(我在这里没有使用过他们的 ARM 编译器)使用 Intel OMF 或 OMF2 格式,并记录了调试符号适用于他们的调试器或“任何与 Intel 兼容的仿真器”。Keil C51 使用的OMF规范可从Keil获得,所以我想类似的规范也可用于他们的其他编译器。

快速浏览 Keil 的网站似乎表明他们放弃了专有的 ARM 编译器,转而使用 ARM 的 RealView 编译器,它似乎使用带有 DWARF 格式调试信息的 ELF 对象。BFD 应该支持 Dwarf,并且应该为您提供验证类型和名称是否匹配所需的一切。

于 2009-04-22T22:20:22.380 回答
2

查看 ANTLR。它是一个解析器生成器,带有 python 绑定。ANTLR 站点为常用语言提供了一大堆语法,包括 C。您可以下载 C 的语法并在适当的位置添加操作以收集您感兴趣的信息。甚至还有一个用于创建和调试语法的简洁图形工具。(我知道这看起来很古怪,但实际上很方便而且不讨厌)

我只是做了一些类似的事情,除了获取我的符号信息,我实际上是从 GDB 中提取它。

于 2009-04-22T18:22:03.000 回答
2

您正在尝试做的是一种轻量级的静态分析形式。查看Wikipedia指出的工具,您可能会走运一些。

自己解析 C 代码对我来说听起来像是错误的方向:其中存在疯狂。如果您坚持,那么 [f]lex 和 yacc (bison) 可能是您的编译器编写者使用的工具。

或者,如果 ctags 或 cscope 可以帮助您完成 80% 的工作,那么两者的源代码都可以广泛使用。最后 20% 是简单的编程问题。:)

于 2009-04-22T18:41:45.760 回答
0

我为几年前从事的一个项目做了类似的事情。我最终编写了 C 编译器的前半部分。不要对这种前景感到惊慌。它实际上比听起来要容易得多,特别是如果您只寻找某些标记(在这种情况下是变量定义)。

在线查找有关如何扫描 C 源代码、检测感兴趣的标记和解析结果的文档。一个很好的起点是维基百科关于词法分析的文章

于 2009-04-22T18:21:51.003 回答