首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Pycparser不能处理预处理代码

Pycparser不能处理预处理代码
EN

Stack Overflow用户
提问于 2015-03-11 18:11:31
回答 2查看 1.8K关注 0票数 2

我需要在预处理的C代码上使用pycparser (这是'gcc -E‘产生的结果)。然而,我现在遇到了一些我无法理解或解决的问题。

我使用的是提供的示例year2.c和func_defs.py,我对它们进行了修改,使用了各种预处理器和伪库,但都没有用。也许你们中的一些人可以研究一下这个问题,看看是否可以重现/解决这个问题。我会追加所有必要的代码。

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

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

Error & Sample Repo

耽误您时间,实在对不起。

EN

回答 2

Stack Overflow用户

发布于 2015-03-12 00:33:50

你得到的错误是:

代码语言:javascript
复制
pycparser.plyparser.ParseError: /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h:40:27: before: __gnuc_va_list

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

代码语言:javascript
复制
typedef __builtin_va_list __gnuc_va_list;

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

对于C编译器来说,使用基于符号表的技术来解析类型名是很常见的,因为如果您不能区分一个typename和另一个标识符,那么语法中就存在许多歧义。这样的解析器将假定未声明的标识符不是typename,且如果__builtin_va_list不是typename,则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输出的要求,您可以通过包含__builtin_va_list的定义来解决这个问题,例如:

代码语言:javascript
复制
typedef struct __builtin_va_list { } __builtin_va_list;

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

票数 5
EN

Stack Overflow用户

发布于 2016-01-28 13:16:48

因为@rici已经解释了错误的原因。我会更专注于如何解决它。我的答案来自pycparser作者的博客-- http://eli.thegreenplace.net/2015/on-parsing-c-type-declarations-and-fake-headers

这个想法是pycparser需要知道anyheader.h包含什么,这样它才能正确地解析代码。由于实际解析anyheader.h和它传递包含的所有其他头文件可能非常耗时,并且可能不是任务所必需的,因此可以使用fakeheaders。伪造的anyheader.h将只包含解析所需的原始文件部分--#定义和typedefs。

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

上面的命令使用pycparser包提供的伪头对包含<stdio.h>的test.c进行预处理。-nostdinc标志用于屏蔽一些预先设置好的系统头目录,这些目录是gcc自动包含的。现在,解析预处理后的文件,例如使用以下代码

代码语言:javascript
复制
import pycparser
pycparser.parse_file('testPP.c')

在大多数情况下都应该有效。如果没有,请确保您提供了预处理所需的所有依赖项。如果有些headers没有提供伪造,你可以使用#defining来伪造导致类型定义的错误,例如,为了解决__builtin_va_list导致的错误,你可以尝试如下所示:

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28983726

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档