Quagga里面的宏定义

本文详细介绍了在Quagga中遇到的宏定义问题,特别是DEFUN宏的使用。通过逐步展开宏,解析了DEFUN CMD_FUNC_DECL、DEFUN_CMD_ELEMENT和DEFUN_CMD_FUNC_TEXT的作用,分别对应函数声明、命令数据结构定义和命令动作函数的定义,揭示了C语言宏定义的层次结构,帮助读者理解C语言的复杂性。
摘要由CSDN通过智能技术生成

Quagga宏定义

以前在看Quagga源码的时候,被里面的宏定义搞残了,根本看不懂啊,今天再回头看了2小时多,还是不懂啊,就在要放弃的时候,我按照C语言宏的定义开始将这个宏一步步展开,发现居然被我搞定了,不容易。。。


DEFUN宏定义

Quagga的命令是以宏来定义的,如zebra的“link-detect”命令,是在“zebra/interface.c”中声明实现的:

DEFUN (linkdetect,
       linkdetect_cmd,
       "link-detect",
       "Enable link detection on interface\n")
{
  struct interface *ifp;
  int if_was_operative;
  
  ifp = (struct interface *) vty->index;
  if_was_operative = if_is_operative(ifp);
  SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);

  /* When linkdetection is enabled, if might come down */
  if (!if_is_operative(ifp) && if_was_operative) if_down(ifp);

  /* FIXME: Will defer status change forwarding if interface
     does not come down! */

  return CMD_SUCCESS;
}

DEFUN是一个宏,定义在“lib/command.h”,见:

#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
  DEFUN_CMD_FUNC_DECL(funcname) \
  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \
  DEFUN_CMD_FUNC_TEXT(funcname)

接着递归,DEFUN展开还是三个宏定义:

#define DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attrs, dnum) \
  struct cmd_element cmdname = \
  { \
    .string = cmdstr, \
    .func = funcname, \
    .doc = helpstr, \
    .attr = attrs, \
    .daemon = dnum, \
  };

#define DEFUN_CMD_FUNC_DECL(funcname) \
  static int funcname (struct cmd_element *, struct vty *, int, const char *[]);

#define DEFUN_CMD_FUNC_TEXT(funcname) \
  static int funcname \
    (struct cmd_element *self __attribute__ ((unused)), \
     struct vty *vty __attribute__ ((unused)), \
     int argc __attribute__ ((unused)), \
     const char *argv[] __attribute__ ((unused)) )

展开一次宏

到此就结束了,之前不管怎么看都看不懂,不得不承认笔者智商平平,就在山穷水尽之际,柳暗花明,笔者尝试先把宏展开看看是什么样的,第一次展开得到如下结果:

DEFUN_CMD_FUNC_DECL(vtysh_end_all) \
DEFUN_CMD_ELEMENT(vtysh_end_all, vtysh_end_all_cmd, "end", "End current mode and change to enable mode\n", 0, VTYSH_ALL) \
DEFUN_CMD_FUNC_TEXT(vtysh_end_all)
{
  return vtysh_end ();
}

再展开

一回生,二回熟,既然接着递归把这三个宏也展开:

static int vtysh_end_all (struct cmd_element *, struct vty *, int, const char *[]); \
struct cmd_element vtysh_end_all_cmd = \
  { \
    .string = "end", \
    .func = vtysh_end_all, \
    .doc = "End current mode and change to enable mode\n", \
    .attr = 0, \
    .daemon = VTYSH_ALL, \
  }; \
static int vtysh_end_all \
    (struct cmd_element *self __attribute__ ((unused)), \
     struct vty *vty __attribute__ ((unused)), \
     int argc __attribute__ ((unused)), \
     const char *argv[] __attribute__ ((unused)) )
{
  return vtysh_end ();
}

结果

可以看出,

1、DEFUN_CMD_FUNC_DECL展开的结果是对函数“vtysh_end_all”进行声明;

2、DEFUN_CMD_ELEMENT是定义该命令相应的数据结构;

3、DEFUN_CMD_FUNC_TEXT则是函数该命令相应动作函数的定义;


至此就看懂了,不容易啊,C语言真是难懂啊


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值