0

我需要分析一些 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,而不仅仅是给定文件中的那个,而且我没有找到任何仅使用给定文件的选项..

有什么提示吗?谢谢

编辑:这是过滤掉不需要的定义的第一个解决方案,只需检查定义的名称实际上是原始文件的一部分,不完美但似乎工作得很好..

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
4

3 回答 3

2

听起来像是壳单线的工作!

我想做的是#include从 C 文件中删除所有 s (这样我们就不会从其他文件中得到垃圾),将其传递给gcc -E -dM,然后删除所有内置的#defines - 那些以_, 显然linuxunix.

如果您有#define以下划线开头的 s,这将无法完全按照承诺工作。

它是这样的:

sed -e '/#include/d' foo.c | gcc -E -dM - | sed -e '/#define \(linux\|unix\|_\)/d'

你也可以用几行 Python 来完成。

于 2012-06-15T11:57:56.877 回答
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 函数应该如何工作,但应该足以满足您的需求。

于 2012-06-15T10:31:04.440 回答
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
于 2012-06-15T20:14:42.733 回答