我正在尝试编写一个程序来检查某些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中获取信息的方法也是完美的。
任何人都可以提供任何帮助,我们将不胜感激。
谢谢,
的Al
答案 0 :(得分:5)
有许多Python解析器包可用于描述语法,然后它将生成Python代码来解析该语法。
Ned Batchelder写了 very nice summary
其中,Ply用于解析C源代码的名为 pycparser 的项目中。我建议从这开始。
其他一些解析器项目也可能有样本C解析器。
编辑:只是注意到pycparser甚至有一个示例Python脚本,就像旧的cdecl程序一样parse C type declarations。
答案 1 :(得分:3)
如何完全从另一侧接近它。您已经拥有一个完全理解C类型系统所有细微差别的解析器:编译器本身。因此,使用完全调试支持编译项目,并在调试数据中进行探索。
对于基于binutils支持的格式的系统,您可以使用BFD库学习所需的大部分详细信息。
微软的调试格式在某种程度上得到了MSDN上的图书馆和文档的支持,但我的谷歌今天很弱,而且我没有把我知道存在的文章放到这里链接。
Keil 8051编译器(我这里没有使用他们的ARM编译器)使用Intel OMF或OMF2格式,并且调试符号用于调试器或“任何与Intel兼容的仿真器”的文档。 Keil C51使用的OMF规格可从Keil获得,因此我认为类似的规格也可用于其他编译器。
对Keil网站的快速扫描似乎表明他们放弃了他们专有的ARM编译器,转而使用ARM的RealView编译器,后者似乎使用带有DWARF格式调试信息的ELF对象。 BFD应该支持Dwarf,并且应该为您提供验证类型和名称是否匹配所需的一切。
答案 2 :(得分:2)
查看ANTLR。它是一个解析器生成器,带有python绑定。 ANTLR站点为包含C的常用语言提供了大量语法。您可以下载C语法并在适当的位置添加操作以收集您感兴趣的信息。甚至还有一个用于创建和调试语法的简洁图形工具。 (我知道这似乎很好,但它实际上非常方便而且不讨厌)
我只是做了类似的事情,除了获取我的符号信息,我实际上是从GDB中提取它。
答案 3 :(得分:2)
您要做的是轻量级的静态分析。您可能会看到Wikipedia指向的工具。
自己解析C代码对我来说听起来是错误的方向:其中就是疯狂。如果你坚持,那么[f] lex和yacc(bison)是编译器编写者可能使用的工具。
或者,如果ctags或cscope获得80%的通道,两者的源代码都可以广泛使用。最后20%是一个简单的编程问题。 :)
答案 4 :(得分:0)
我为几年前工作的项目做过类似的事情。我最后编写了C编译器的前半部分。不要被这种前景吓到。它实际上比听起来容易得多,特别是如果你只是寻找某些令牌(在这种情况下是变量定义)。
在线查找有关如何扫描C源代码,检测感兴趣的令牌以及解析结果的文档。一个好的开始是Wikipedia's artricle on lexical analysis。