我需要使用pycparser解析我的C和C++代码,但之前需要删除预处理程序指令和注释.
所以,你知道怎么做吗?我找到了CPP预处理器,但我不知道,如果我可以像这样使用它,没有"完整"的预处理.
我也发现了一个unifdef工具,它似乎完全符合我的要求,但仅限于预处理器条件(例如#ifdef).
我不想自己编写这个工具,因为它将用于一个非常大的项目,所以我想使用一些非常复杂的东西.
我试图找到地方,test这个代码中调用的函数在哪里:
#include <stdio.h>
// asdfdsa
/* sadfsd
*
*/
void test() {
printf("asd");
}
int main() {
test();
test();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我用命令预处理了这段代码gcc -E -std=c99 test.c -o testP.c然后我试着用这个Python代码找到函数调用:
#-----------------------------------------------------------------
# pycparser: func_defs.py
#
# Using pycparser for printing out all the calls of some function
# in a C file.
#
# Copyright (C) 2008-2015, Eli Bendersky
# License: BSD
#-----------------------------------------------------------------
from __future__ import print_function
import sys
# This is not required if you've installed pycparser into
# your site-packages/ with setup.py
sys.path.extend(['.', '..'])
from pycparser import c_parser, c_ast, parse_file
# A visitor with some state information (the funcname it's
# looking for)
#
class FuncCallVisitor(c_ast.NodeVisitor):
def __init__(self, funcname):
self.funcname = funcname
def visit_FuncCall(self, node):
if node.name.name == self.funcname:
print('%s called at %s' % (self.funcname, node.name.coord))
def show_func_calls(filename, funcname):
ast = parse_file(filename, use_cpp=True)
v = FuncCallVisitor(funcname)
v.visit(ast)
if __name__ == "__main__":
if len(sys.argv) > 2:
filename = sys.argv[1]
func = sys.argv[2]
else:
filename = 'test.c'
func = 'test'
show_func_calls(filename, func)
Run Code Online (Sandbox Code Playgroud)
但仍然,我收到此错误:
Traceback (most recent call last):
File "func_calls.py", line 46, in <module>
show_func_calls(filename, func)
File "func_calls.py", line 33, in show_func_calls
ast = parse_file(filename, use_cpp=True)
File "/usr/local/lib/python2.7/dist-packages/pycparser/__init__.py", line 93, in parse_file
return parser.parse(text, filename)
File "/usr/local/lib/python2.7/dist-packages/pycparser/c_parser.py", line 146, in parse
debug=debuglevel)
File "/usr/local/lib/python2.7/dist-packages/pycparser/ply/yacc.py", line 265, in parse
return self.parseopt_notrack(input,lexer,debug,tracking,tokenfunc)
File "/usr/local/lib/python2.7/dist-packages/pycparser/ply/yacc.py", line 1047, in parseopt_notrack
tok = self.errorfunc(errtoken)
File "/usr/local/lib/python2.7/dist-packages/pycparser/c_parser.py", line 1691, in p_error
column=self.clex.find_tok_column(p)))
File "/usr/local/lib/python2.7/dist-packages/pycparser/plyparser.py", line 55, in _parse_error
raise ParseError("%s: %s" % (coord, msg))
pycparser.plyparser.ParseError: /usr/lib/gcc/x86_64-linux-gnu/4.9/include/stdarg.h:40:27: before: __gnuc_va_list
Run Code Online (Sandbox Code Playgroud)
pycparser文档明确说明您应该使用cpp或gcc -E准备源代码进行解析.因此,"满"预处理不是问题的cpp,这是你需要为了运行功能,pycparser在你的代码.
如果您只是删除所有预处理程序指令的代码,解析将失败,因为未声明的类型(如int32_t或size_t)和库函数缺少原型.
编辑:pycparser仅支持C99语法.如果gcc出于某种原因需要使用C++代码,请运行预处理器,如下所示:
gcc -E -std=c99
Run Code Online (Sandbox Code Playgroud)
EDIT2:您似乎收到了与编译器特定符号相关的更多错误.尝试使用"假"标题提供pycparser:
gcc -E -std=c99 -I/path/to/pycparser/utils/fake_libc_include
Run Code Online (Sandbox Code Playgroud)