2

我需要在预处理的 C 代码('gcc -E' 产生的结果)上使用 pycparser。但是,我目前遇到了我无法理解或解决的问题。

我正在使用提供的示例 year2.c 和 func_defs.py,我对其进行了修改以使用各种预处理器和假库,但无济于事。也许你们中的一些人可以调查一下,看看是否可以重现/解决问题。我将附加所有必要的代码。

错误是使用 year2.c(常规示例文件)和 year2.i('gcc -E' 输出)生成的。后者没有可用的结果,而前者同时使用预处理器/fakelib 变体。

我创建了一个包含所有相关错误的 bitbucket 存储库、使用的脚本(尽管只是它的最后一个变体)以及 year2.c 和 year2.i 文件。

错误和示例回购

谢谢你的时间。

4

2 回答 2

5

你得到的错误是:

pycparser.plyparser.ParseError: /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h:40:27: before: __gnuc_va_list

指示为导致错误的行 ( stdarg.h:40):

typedef __builtin_va_list __gnuc_va_list;

在 gcc__builtin_va_list中,顾名思义,它内置于编译器中。因此,不需要(或不允许)声明该类型。

C 编译器使用基于符号表的技术来解析类型名是很常见的,因为如果您无法将类型名与另一个标识符区分开来,语法中就会出现许多歧义。这样的解析器将假定未声明的标识符不是类型名,如果__builtin_va_list不是类型名,那typedef就是语法错误。

所以我想你使用的 pyparser 语法不知道 gcc 内置类型(为什么应该知道?)。

您的 fakelib 似乎包含相同的头文件。这并不奇怪,因为它很难伪造stdarg.h;尽管在技术上是一个库头文件,但它是编译器必须提供的一小部分头文件,即使在独立(非标准库)实现中也是如此:<float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h><stdnoreturn.h>(C11 标准,第 4 条,第 6 段)。这些必须由编译器实现,因为外部库无法充分了解已编译代码的性质以正确定义它们。

根据您对 pyparsed 输出的要求,您可以通过包含 的定义来为 pyparser 解决此问题__builtin_va_list,例如:

typedef struct __builtin_va_list { } __builtin_va_list;

__builtin_va_list不是唯一的内置 gcc 数据类型,尽管您可能不会遇到其他数据类型。因此,您可能必须多次迭代此解决方案,直到实现您想要实现的任何目标。

于 2015-03-11T16:33:49.517 回答
2

正如@rici 解释了错误的原因。我会更多地关注如何解决它。我从 pycparser 作者的博客中得到了答案 - http://eli.thegreenplace.net/2015/on-parsing-c-type-declarations-and-fake-headers

这个想法是 pycparser 需要知道 anyheader.h 包含的内容,以便它可以正确解析代码。由于实际解析 anyheader.h 和它传递包含的所有其他标头,可能非常耗时,并且您的任务可能不需要,因此可以使用 fakeheaders。伪造的 anyheader.h 将仅包含解析所需的原始部分 - #defines 和 typedefs。

gcc -nostdinc -E -I/home/rg/pycparser-master/utils/fake_libc_include test.c > testPP.c

上面的命令预处理 test.c,其中包含<stdio.h>使用 pycparser 包提供的假头文件。-nostdincflag 用于阻止 gcc 自动包含的一些预先设置的系统头目录。现在,使用例如下面的代码解析预处理文件

import pycparser
pycparser.parse_file('testPP.c')

应该在大多数情况下工作。如果它不能确保你为预处理提供所有依赖项。如果某些标题没有提供伪造,您可以使用 #defining 伪造导致 typedef 的错误,例如解决由 引起的错误 __builtin_va_list,您可以尝试按如下方式伪造它:

gcc -nostdinc -E -D'__builtin_va_list(x)=' -I/home/rg/pycparser-master/utils/fake_libc_include test.c > testPP.c

于 2016-01-28T05:16:47.933 回答