我需要分析一些C文件并打印出找到的所有#define。 使用正则表达式(例如)
并不难def with_regexp(fname):
print("{0}:".format(fname))
for line in open(fname):
match = macro_regexp.match(line)
if match is not None:
print(match.groups())
但是例如它不处理多行定义。
有一种很好的方法可以在C中执行此操作,例如使用
gcc -E -dM file.c
问题是它返回所有#defines,而不仅仅是给定文件中的#defines,而且我找不到任何只使用给定文件的选项..
任何提示? 感谢
编辑: 这是过滤掉不需要的定义的第一个解决方案,只需检查定义的名称实际上是原始文件的一部分,不完美但似乎很好用..
def with_gcc(fname):
cmd = "gcc -dM -E {0}".format(fname)
proc = Popen(cmd, shell=True, stdout=PIPE)
out, err = proc.communicate()
source = open(fname).read()
res = set()
for define in out.splitlines():
name = define.split(' ')[1]
if re.search(name, source):
res.add(define)
return res
答案 0 :(得分:2)
听起来像是一个单一的贝壳工作!
我想要做的是从C文件中删除所有#include
(因此我们不会从其他文件中获取垃圾),将其传递给gcc -E -dM
,然后删除所有构建的在#define
s中 - 以_
开头,显然是linux
和unix
。
如果您的#define
以下划线开头,则无法完全按照承诺行事。
它是这样的:
sed -e '/#include/d' foo.c | gcc -E -dM - | sed -e '/#define \(linux\|unix\|_\)/d'
你也可以在几行Python中完成它。
答案 1 :(得分:1)
在PowerShell中,您可以执行以下操作:
function Get-Defines {
param([string] $Path)
"$Path`:"
switch -regex -file $Path {
'\\$' {
if ($multiline) { $_ }
}
'^\s*#define(.*)$' {
$multiline = $_.EndsWith('\');
$_
}
default {
if ($multiline) { $_ }
$multiline = $false
}
}
}
使用以下示例文件
#define foo "bar"
blah
#define FOO \
do { \
do_stuff_here \
do_more_stuff \
} while (0)
blah
blah
#define X
打印
\x.c:
#define foo "bar"
#define FOO \
do { \
do_stuff_here \
do_more_stuff \
} while (0)
#define X
不理想,至少PowerShell函数应该如何工作,但应该能够很好地满足您的需求。
答案 2 :(得分:1)
在纯python中执行此操作我将使用一个小型状态机:
def getdefines(fname):
""" return a list of all define statements in the file """
lines = open(fname).read().split("\n") #read in the file as a list of lines
result = [] #the result list
current = []#a temp list that holds all lines belonging to a define
lineContinuation = False #was the last line break escaped with a '\'?
for line in lines:
#is the current line the start or continuation of a define statement?
isdefine = line.startswith("#define") or lineContinuation
if isdefine:
current.append(line) #append to current result
lineContinuation = line.endswith("\\") #is the line break escaped?
if not lineContinuation:
#we reached the define statements end - append it to result list
result.append('\n'.join(current))
current = [] #empty the temp list
return result