代码结构://以init.rc 的第一个有效命令为例分析—>import /init.environ.rc
init_parse_config_file("/init.rc");
parse_config(path, data);
next_token(&state);
lookup_keyword //将传入的参数添加K_前缀
parse_new_section(&state, kw, nargs, args);/*section:import,service,on*/
kw_is(kw, type) (keyword_info[kw].flags & (type))
//K_import情况下
parse_import(state, nargs, args);
参考代码:
kw_is(K_import, SECTION)分析:
第一次包含keyword.h的文件内容:
#ifndef KEYWORD
int do_bootchart_init(int nargs, char **args);
...
#define __MAKE_KEYWORD_ENUM__
#define KEYWORD(symbol, flags, nargs, func) K_##symbol,
enum {
K_UNKNOWN,
#endif
KEYWORD(bootchart_init, COMMAND, 0, do_bootchart_init)
…
#ifdef __MAKE_KEYWORD_ENUM__
KEYWORD_COUNT,
};
#undef __MAKE_KEYWORD_ENUM__
#undef KEYWORD
#endif
① 首次包含肯定没定义KEYWORD,等几个宏,so,相当于添加几个函数声明,以及一个K_大头的枚举.
② #define KEYWORD(symbol, flags, nargs, func) K_##symbol,
KEYWORD(bootchart_init, COMMAND, 0, do_bootchart_init)
展开:
K_##symbol—>K_ bootchart_init
综上,第一次包含想当于添加几个函数声明和一个枚举。
第二次包含在结构体中:
第一次包含的最后又用undef关键字去除KEYWORD关键字定义(其他几个宏也一样只不过没有二次再定义所以其中间的内容也不被包含),紧接着就在此定义KEYWORD,但是已经今非昔比了。
再次包含keywords.h时就全然不同了:
再看上述通过宏定义精简的keyword.h代码:
#ifndef KEYWORD
int do_bootchart_init(int nargs, char **args);
…
enum {
K_UNKNOWN,
#endif
…
KEYWORD(writepid, OPTION, 0, 0)
#ifdef __MAKE_KEYWORD_ENUM__
KEYWORD_COUNT,
};
#undef __MAKE_KEYWORD_ENUM__
#undef KEYWORD
#endif
函数以及杂七杂八的都不被包含仅仅剩下等KEYWORD:
…
KEYWORD(bootchart_init, COMMAND, 0, do_bootchart_init)
KEYWORD(chmod, COMMAND, 2, do_chmod)
…
展开:
#define KEYWORD(symbol, flags, nargs, func) [ K_##symbol ] = { #symbol, func, nargs + 1, flags, },
KEYWORD(bootchart_init,COMMAND, 0, do_bootchart_init)
[ K_ bootchart ] = { bootchart, do_bootchart_init, 0 + 1, COMMAND, },
//熟悉的结构体成员定义是不是回来了?
//带入结构体:
static struct {
const char *name;
int (*func)(int nargs, char **args);
unsigned char nargs;
unsigned char flags;
} keyword_info[KEYWORD_COUNT] = {
[ K_UNKNOWN ] = { "unknown", 0, 0, 0 },
[ K_ bootchart ] = { bootchart, do_bootchart_init, 0 + 1, COMMAND, },
…
};
看到这应该能感受到代码的巧妙了吧。
现在来好好看下为什么能判断是否为SECTION,COMMAND等关键字了,走了这么一大段路也只不过是为了定义一个结构体罢了:
#define kw_is(kw, type) (keyword_info[kw].flags & (type))