gpt4 book ai didi

gcc - 如何在源代码中的特定行检查 GCC 预处理器定义

转载 作者:行者123 更新时间:2023-12-04 09:59:21 31 4
gpt4 key购买 nike

有没有办法在源文件中的某个点转储所有当前的预处理器定义? 或者另一种检查源文件中两点之间预处理器指令更改的方法?

我没有找到任何东西 here .这是一个给出这个想法的例子:

#define FOO

#pragma message "defines before whatever.h"
#pragma please_dump_all_defines
#include <whatever.h>
#pragma message "defines after whatever.h"
#pragma please_dump_all_defines

// rest of the file

另一种获取信息的方式也可以使用,例如使用 gcc -E不知何故,只要考虑到 FOO以上可能会影响包含文件的确切定义,并且可以跟踪多个 #define/ #undef , 等等。

最佳答案

当然,GCC 预处理器不能完全按照您的要求做,但它确实可以
有一个 -dCHARS选项,用于标志组合 CHARS , 那
您可以利用一些脚本来提取
翻译单元中两点之间的预处理器定义。

我将用包含这两个文件的翻译单元进行说明:

foo.c

#define B 1
#define C 2
#pragma message Begin
#include "bar.h"
#pragma message End
#undef B
#undef C
#define B 4
#define C 5

bar.h
#ifndef BAR_H
#define BAR_H

#undef B
#undef C
#ifdef A
#define B 2
#define C 3
#endif

#endif

调用:
cpp -dD foo.c
-dD选项保留 #define|#undef否则的指令
预处理输出。该输出有 > 500 行,所以我只是
引用有趣的尾部:
# 1 "<command-line>" 2
# 1 "foo.c"
#define B 1
#define C 2

# 3 "foo.c"
#pragma message Begin
# 3 "foo.c"

# 1 "bar.h" 1

#define BAR_H

#undef B
#undef C
# 5 "foo.c" 2

# 5 "foo.c"
#pragma message End
# 5 "foo.c"

#undef B
#undef C
#define B 4
#define C 5

或者,调用:
cpp -dD -DA foo.c

相应的尾部(带有我的评论)是:
# 1 "<command-line>" 2
# 1 "foo.c"
#define B 1
#define C 2

# 3 "foo.c"
#pragma message Begin
# 3 "foo.c"

# 1 "bar.h" 1

#define BAR_H

#undef B
#undef C

#define B 2 //<- New with -DA
#define C 3 //<- New with -DA
# 5 "foo.c" 2

# 5 "foo.c"
#pragma message End
# 5 "foo.c"

#undef B
#undef C
#define B 4
#define C 5

与此相关的脚本是:
  • 1) 提取 #define|#undef在起点之前的指令
    标记,#pragma message Begin ,仅保留每个宏名称的最新滚动。
  • 2) 从起点到终点标记#pragma message End重复1) .
  • 3) 按宏名称匹配两组并报告前后差异。

  • 就像你的运气一样,碰巧我需要吹掉我的蜘蛛网(从不
    非常有光泽的)python 用于面试,所以这里有一个脚本(只是粗略地
    调试):

    macrodiff.py
    #!/usr/bin/python

    import sys, argparse, os, string, re, subprocess, shlex
    from subprocess import call, CalledProcessError

    class macro_directive:
    def __init__(self,directive = None,name = None,definition = None):
    self.__directive = directive
    self.__name = name
    self.__definition = definition
    def __eq__(self,other):
    return self.__name == other.__name and \
    self.__directive == other.__directive and \
    self.__definition == other.__definition
    def __neq__(self,other):
    return not __eq__(self,other)
    @property
    def empty(self):
    return not self.__directive
    @property
    def directive(self):
    return self.__directive
    @property
    def name(self):
    return self.__name
    @property
    def definition(self):
    return self.__definition

    @property
    def desc(self):
    desc = self.__directive + ' ' + self.__name
    if self.__definition:
    desc += ' '
    desc += self.__definition
    return desc

    @staticmethod
    def read(line):
    match = re.match('^\s*#\s*(define|undef)\s+(\w+) \s*(.*)$',line)
    if match:
    directive = match.group(1)
    name = match.group(2)
    if directive == 'define':
    return macro_directive(directive,name,match.group(3))
    else:
    return macro_directive(directive,name)
    else:
    return macro_directive()
    @staticmethod
    def make_dict(lines):
    d = {}
    for line in lines:
    md = macro_directive.read(line);
    if not md.empty:
    d[md.name] = md
    return d


    def find_marker(lines,marker):
    for i, line in enumerate(lines):
    if line.find(marker) == 0:
    return i;
    return -1

    def split_by_marker(lines,marker):
    mark_i = find_marker(lines,marker)
    if mark_i != -1:
    return [lines[:mark_i],lines[mark_i:]]
    return [[],lines]

    parser = argparse.ArgumentParser(
    prog="macrodiff",
    formatter_class=argparse.RawDescriptionHelpFormatter,
    description='Extract changes in simple preprocessor macro values between' +
    ' two marked points in a C/C++ translation unit. ' +
    'Function-like macros are not supported')
    parser.add_argument('-s', '--start', metavar='STARTSTR',required=True,
    help='The initial macro values will be those in effect when the' +
    ' first line commencing with STARTSTR is read')
    parser.add_argument('-e', '--end', metavar='ENDSTR',
    help='The final macro values will be those in effect when the first line' +
    ' commencing with ENDSTR is read, or if --end is not given then those' +
    ' in effect at end-of-file ')
    parser.add_argument('--pp', default='cpp -dD',metavar='PP',
    help='PP is the preprocessor command to invoke. Default \'cpp -dD\'')
    parser.add_argument('--ppflags',default='',metavar='PPFLAGS',
    help='PPFLAGS are additional options to be passed to PP')
    parser.add_argument('infile',metavar='FILE',nargs=1,
    help='FILE is a C/C++ source file to be processed')

    args = vars(parser.parse_args())
    startstr = args['start'];
    endstr = args['end'];
    stdout = ''
    command = args['pp'] + ' ' + args['ppflags'] + ' ' + args['infile'][0]

    try:
    stdout = subprocess.check_output(shlex.split(command))
    except CalledProcessError, e:
    sys.stderr.write( '***Error: Command \"' + command + '\" failed: \"' + \
    e.output + '\": ' + 'syscode = ' + str(e.returncode) + '\n')
    sys.exit(e.returncode)
    lines = stdout.splitlines();
    lines_before,lines_after = split_by_marker(lines,startstr);
    if not lines_before:
    sys.stderr.write( '***Error: STARTSTR \"' + startstr + '\" not found\n')
    sys.exit(1)
    if endstr:
    lines_after, ignore = split_by_marker(lines_after,endstr);
    if not lines_after:
    sys.stderr.write( '***Error: ENDSTR \"' + endstr + '\" not found\n')
    sys.exit(1)

    directives_dict_before = macro_directive.make_dict(lines_before)
    directives_dict_after = macro_directive.make_dict(lines_after)
    intersection = \
    directives_dict_before.viewkeys() & directives_dict_after.viewkeys()

    for key in intersection:
    before = directives_dict_before[key]
    after = directives_dict_after[key]
    if before != after:
    print 'BEFORE[' + before.desc + '] AFTER[' + after.desc +']'

    sys.exit(0)

    用法
    $ ./macrodiff.py -h
    usage: macrodiff [-h] -s STARTSTR [-e ENDSTR] [--pp PP] [--ppflags PPFLAGS]
    FILE

    Extract changes in simple preprocessor macro values between two marked points in a C/C++ translation unit. Function-like macros are not supported

    positional arguments:
    FILE FILE is a C/C++ source file to be processed

    optional arguments:
    -h, --help show this help message and exit
    -s STARTSTR, --start STARTSTR
    The initial macro values will be those in effect when
    the first line commencing with STARTSTR is read
    -e ENDSTR, --end ENDSTR
    The final macro values will be those in effect when
    the first line commencing with ENDSTR is read, or if
    --end is not given then those in effect at end-of-file
    --pp PP PP is the preprocessor command to invoke. Default 'cpp
    -dD'
    --ppflags PPFLAGS PPFLAGS are additional options to be passed to PP

    试试这个:
    $ ./macrodiff.py -s='#pragma message Begin' -e='#pragma message End' foo.c

    输出:
    BEFORE[define C 2] AFTER[undef C]
    BEFORE[define B 1] AFTER[undef B]

    或者:
    $ ./macrodiff.py -s='#pragma message Begin' -e='#pragma message End' --ppflags='-DA' foo.c

    输出:
    BEFORE[define C 2] AFTER[define C 3]
    BEFORE[define B 1] AFTER[define B 2]

    或者:
    $ ./macrodiff.py -s='#pragma message Begin' --ppflags='-DA' foo.c

    这次的差异取自 #pragma message Begin
    文件结尾。输出:
    BEFORE[define C 2] AFTER[define C 5]
    BEFORE[define B 1] AFTER[define B 4]

    如果您更愿意使用独特的注释而不是编译指示作为
    开始和结束标记,然后添加 -CPPFLAGS .这将保留评论
    预处理的输出,指令中的输出除外。

    对类似函数的宏的支持留作练习。

    关于gcc - 如何在源代码中的特定行检查 GCC 预处理器定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23239090/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com