You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用boost::wave关联C代码中嵌套宏的调用位置与展开文本

用Boost.Wave搞定宏调用位置与展开文本的关联

核心思路:靠context_hooks追踪宏调用上下文

Boost.Wave的advanced_hooks只能捕获展开文本,但要绑定原代码中的调用位置,得结合宏调用的进出钩子和位置栈存储——毕竟嵌套宏调用会层层触发钩子,用栈才能保住外层的位置信息不被覆盖。

具体操作步骤

  1. 自定义钩子类,用栈存储调用位置:
struct MacroTrackingHooks : boost::wave::context_hooks<> {
    std::stack<boost::wave::token_position> call_pos_stack;

    // 宏开始展开时,把当前调用位置压栈
    void macro_expansion_start(
        boost::wave::context_type const&,
        boost::wave::token_type const&,
        boost::wave::token_position const& call_pos,
        bool
    ) override {
        call_pos_stack.push(call_pos);
    }

    // 宏展开结束,弹出栈顶位置(适配嵌套宏场景)
    void macro_expansion_end(
        boost::wave::context_type const&,
        boost::wave::token_type const&,
        bool
    ) override {
        if (!call_pos_stack.empty()) {
            call_pos_stack.pop();
        }
    }

    // 在rescanned_macro中绑定位置与展开文本
    void rescanned_macro(
        boost::wave::context_type const&,
        boost::wave::token_type const&,
        boost::wave::token_sequence_type const& expansion
    ) override {
        if (call_pos_stack.empty()) return;
        
        // 提取原调用的行号、列号
        auto const& pos = call_pos_stack.top();
        int line = pos.get_line();
        int col = pos.get_column();

        // 拼接完整的展开文本
        std::string expanded;
        for (auto const& tok : expansion) {
            expanded += tok.get_value();
        }

        // 这里把位置和展开文本存入自定义映射结构即可
        // 示例:macro_map[{line, col}] = expanded;
    }
};
  1. 注入钩子到Wave上下文:
    编译时必须定义BOOST_WAVE_SUPPORT_CONTEXT_HOOKS宏(比如编译参数加-DBOOST_WAVE_SUPPORT_CONTEXT_HOOKS),否则钩子接口无法启用。创建上下文时带上自定义钩子:
boost::wave::context<
    std::string::iterator,
    boost::wave::cpplexer::lex_iterator<>,
    boost::wave::context_policies::default_policy,
    MacroTrackingHooks
> ctx(input.begin(), input.end(), "your_source.c");

// 启用钩子功能
ctx.get_hooks().enable();
  1. 适配嵌套宏参数:
    函数式宏参数中的嵌套宏会触发递归展开,此时栈结构会自动保留外层宏的位置——内层展开时栈顶始终是原代码中最外层的宏调用位置,直到内层展开结束弹出栈,完美对应原位置。

额外提醒

  • 对象式宏的处理逻辑和函数式一致,macro_expansion_start同样会触发,无需额外修改
  • token_position还支持获取文件名,多文件处理场景下也能直接复用

内容的提问来源于stack exchange,提问作者johnco3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 06:00:02