免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2494 | 回复: 1
打印 上一主题 下一主题

利用预处理程序CPP解读复杂的宏 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-03-05 23:34 |只看该作者 |倒序浏览
本帖最后由 baozhao 于 2011-03-05 23:36 编辑

http://blog.chinaunix.net/space.php?uid=1858380&do=blog&id=156282

      大型C项目可能有包含佶屈聱牙的宏,令人大为头痛,如何看到宏替换后的结果,自然会极大地帮助理解。而这本来就是预处理程序cpp的工作,只是我们习惯了gcc一杆到底,反而忘了cpp的好处,即只是替换,没有编译链接,只需要把所有相关宏聚到一起就可以看到结果。

     下面的示例文件macro.c 前面部分来自linux-2.6.38-rc6/include/trace/ftrace.h 的stage 4部分(以及该部分要用到的来自其他文件宏,注意不能用错,因为里面包含大量的重名宏),ftrace.h是一个非常复杂的文件。为了展开,我们在macro.c尾部添加一个宏的引用,来自 include/trace/events/syscalls.h。

#define PARAMS(args...) args
#define TP_PROTO(args...)       args
#define TP_ARGS(args...)        args

#define TP_STRUCT__entry(args...) args

#define TRACE_EVENT_FN(name, proto, args, tstruct,                      \
               assign, print, reg, unreg)                              \
       TRACE_EVENT(name, PARAMS(proto), PARAMS(args),                  \
               PARAMS(tstruct), PARAMS(assign), PARAMS(print))         \


#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \
       DECLARE_EVENT_CLASS(name,                              \
                            PARAMS(proto),                    \
                            PARAMS(args),                     \
                            PARAMS(tstruct),                  \
                            PARAMS(assign),                   \
                            PARAMS(print));                  


#undef __entry
#define __entry entry

#undef __field
#define __field(type, item)


#undef __array
#define __array(type, item, len)

#undef __dynamic_array
#define __dynamic_array(type, item, len)                                \
TRUCT__entry(args...) args


#undef __string
#define __string(item, src) __dynamic_array(char, item, -1)             \

#undef __assign_str
#define __assign_str(dst, src)                                          \
       strcpy(__get_str(dst), src);

#undef TP_fast_assign
#define TP_fast_assign(args...) args

#undef TP_perf_assign
#define TP_perf_assign(args...)

#undef DECLARE_EVENT_CLASS
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print)  \
                                                                       \
static notrace void                                                     \
ftrace_raw_event_##call(void *__data, proto)                            \
{                                                                       \
       struct ftrace_event_call *event_call = __data;                  \
       struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
       struct ring_buffer_event *event;                                \
       struct ftrace_raw_##call *entry;                                \
       struct ring_buffer *buffer;                                     \
       unsigned long irq_flags;                                        \
       int __data_size;                                                \
       int pc;                                                         \
                                                                       \
       local_save_flags(irq_flags);                                    \
       pc = preempt_count();                                           \
                                                                       \
       __data_size = ftrace_get_offsets_##call(&__data_offsets, args); \
                                                                       \
       event = trace_current_buffer_lock_reserve(&buffer,              \
                             event_call->event.type,                \
                                sizeof(*entry) + __data_size,          \
                                irq_flags, pc);                        \
       if (!event)                                                     \
               return;                                                 \
       entry   = ring_buffer_event_data(event);                        \
                                                                       \
       tstruct                                                         \
                                                                       \
       { assign; }                                                     \
                                                                       \
       if (!filter_current_check_discard(buffer, event_call, entry, event)) \
               trace_nowake_buffer_unlock_commit(buffer,               \
                                                 event, irq_flags, pc); \
}


TRACE_EVENT_FN(sys_enter,

       TP_PROTO(struct pt_regs *regs, long id),

       TP_ARGS(regs, id),
      
       TP_STRUCT__entry(
               __field(        long,           id              )
               __array(        unsigned long,  args,   6       )
       ),

       TP_fast_assign(
               __entry->id     = id;
               syscall_get_arguments(current, regs, 0, 6, __entry->args);
       ),

       TP_printk("NR %ld (%lx, %lx, %lx, %lx, %lx, %lx)",
                 __entry->id,
                 __entry->args[0], __entry->args[1], __entry->args[2],
                 __entry->args[3], __entry->args[4], __entry->args[5]),

       syscall_regfunc, syscall_unregfunc
);

下面利用cpp来展开,用indent修整输出文件后,赏心悦目的C代码出现了。
[user@localhost ~]$ cpp -P macro.c out.c
[user@localhost ~]$ indent out.c
[user@localhost ~]$ cat out.c
  1. static notrace void
  2. ftrace_raw_event_sys_enter (void *__data, struct pt_regs *regs, long id)
  3. {
  4.   struct ftrace_event_call *event_call = __data;
  5.   struct ftrace_data_offsets_sys_enter __maybe_unused __data_offsets;
  6.   struct ring_buffer_event *event;
  7.   struct ftrace_raw_sys_enter *entry;
  8.   struct ring_buffer *buffer;
  9.   unsigned long irq_flags;
  10.   int __data_size;
  11.   int pc;
  12.   local_save_flags (irq_flags);
  13.   pc = preempt_count ();
  14.   __data_size = ftrace_get_offsets_sys_enter (&__data_offsets, regs, id);
  15.   event =
  16.     trace_current_buffer_lock_reserve (&buffer, event_call->event.type,
  17.                                        sizeof (*entry) + __data_size,
  18.                                        irq_flags, pc);
  19.   if (!event)
  20.     return;
  21.   entry = ring_buffer_event_data (event);
  22.   {
  23.     entry->id = id;
  24.     syscall_get_arguments (current, regs, 0, 6, entry->args);;
  25.   }
  26.   if (!filter_current_check_discard (buffer, event_call, entry, event))
  27.     trace_nowake_buffer_unlock_commit (buffer, event, irq_flags, pc);
  28. };;
复制代码

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2011-03-05 23:57 |只看该作者
没想到还有这种cpp工具。一直不知道,因为从来没有接触过楼主所说的这么复杂的宏。

收藏一个。

评分

参与人数 1可用积分 +2 收起 理由
OwnWaterloo + 2 gcc -P的后端

查看全部评分

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP