gcc研究笔记(三)libcpp中的宏扩展机制

 
1、libcpp中和宏相关的基础知识
libcpp是gcc的C/C++语言预处理器,gcc将C/C++语言预处理器cpp以库的形式独立出来,故取名曰libcpp。libcpp的输出为预处理标记cpp_token序列,为了实现回退机制、预处理指令处理和宏扩展,libcpp分三层输出预处理标记cpp_token序列:
a)_cpp_lex_direct:这是预处理标记序列输出的第一层,它直接对程序文件进行词法分析,不处理任何预处理指令,也不提供回退功能,它反映的是真实的程序文本;
b)cpp_lex_token:第二层在第一层的基础上实现了回退和预处理指令处理功能,调用这一层的用户看不到符合C/C++标准的预处理指令行;
c)cpp_get_token:这是最外一层,调用这个函数看到的将是C/C++标准中的翻译单元。这一层相对上一层主要是实现了宏扩展和##操作符处理功能。
2、预处理指令的处理
预处理指令的处理流程起始于cpp_lex_token函数,不考虑回退机制(回退机制将在后续文章中单独讨论),cpp_lex_token调用第一层分析函数_cpp_lex_direct,如果得到标记#,且其为当前行的第一个标记,转入_cpp_handle_directive。_cpp_handle_directive继续调用_cpp_lex_direct读取下一个标记,如果其为标识符(dname->type == CPP_NAME),并且为有效的预处理指令名字,转入相应的预处理指令处理函数。
为了提高效率,libcpp使用了两个小技巧。首先,为了快速判别出一个标识符是否为预处理指令名字,libcpp在标识符的存储结构cpp_hashnode中提供了一个is_directive标记,用于标识该标识符是否为预处理指令名字。另外,为了快速定位相应预处理指令的处理函数,libcpp将所有的预处理指令处理函数按顺序保存在一个数组当中,并且在cpp_hashnode中额外提供了一个directive_index成员,用于对处理函数数组索引。
处理函数数组的定义代码如下:
#define DIRECTIVE_TABLE                                                                 /
D(define,     T_DEFINE = 0, KANDR,     IN_I)      /* 270554 */ /
D(include,   T_INCLUDE,     KANDR,     INCL | EXPAND) /* 52262 */ /
D(endif,       T_ENDIF, KANDR,     COND)           /* 45855 */ /
D(ifdef,       T_IFDEF, KANDR,     COND | IF_COND) /* 22000 */ /
D(if,            T_IF,                   KANDR, COND | IF_COND | EXPAND) /* 18162 */ /
D(else,                  T_ELSE,             KANDR,     COND)           /*   9863 */ /
D(ifndef,     T_IFNDEF,        KANDR,     COND | IF_COND) /*   9675 */ /
D(undef,      T_UNDEF,         KANDR,     IN_I)      /*   4837 */ /
D(line,                  T_LINE,             KANDR,     EXPAND)      /*   2465 */ /
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值