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语言真是难懂啊