Linux Kbuild 的词法分析器问题
Kbuild 的词法分析器,也就是 make config 对配置的词法分析和语法分析,最后通过 Kconfig 文件生产对应的 .config。其源码位于 /srctree/scripts/kconfig/ 目录下。
请问有哪位朋友研究过 zonconf.l 的编译命令?
没仔细分析过这个flex文件,楼主具体的问题是什么?
PS,可以通过info flex查询具体的语法点。 5 Format of the Input File
**************************
The `flex' input file consists of three sections, separated by a line
containing only `%%'.
definitions
%%
rules
%%
user code
简单的例子
int num_lines = 0, num_chars = 0;
%%
\n ++num_lines; ++num_chars;
. ++num_chars;
%%
main()
{
yylex();
printf( "# of lines = %d, # of chars = %d\n",
num_lines, num_chars );
}
回复 3# nswcfd
Kbuild 系统中,当我们使用命令 “make config” 的时候,他就会去调用 scripts/kconfig/zconf.l 的词法分析器分析 KCONFIG。
通过源码分析, Kbuild 同时使用了两个词法分析器,为了分开两个词法分析器, Kbuild 会使用 flex 带上一定的编译参数来生成这两个词法分析器。
我就是想知道 flex 生产这两个词法分析器时候使用的命令是什么?
默认的词法分析器是 yylex() 另外一个是 zconflex() 本帖最后由 nswcfd 于 2016-08-31 17:06 编辑
第一部分声明了一些状态(start conditons)
%x COMMAND HELP STRING PARAM
以及ws(空白)和n(数字或字母)两个“宏”
第二部分
[ \t]*#.*\n |
[ \t]*\n {
current_file->lineno++;
return T_EOL;
}
//匹配行末空白或注释(#开始)
[ \t]*#.*
//忽略注释以及之前的空白
[ \t]+{
BEGIN(COMMAND);
}
//空格进入COMMAND状态
. {
unput(yytext);
BEGIN(COMMAND);
}
//任意字符进入COMMAND状态, unput放回当前字符(重新解析)
<COMMAND>{
//COMMAND状态下的pattern & action
{n}+ {
struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
BEGIN(PARAM);
current_pos.file = current_file;
current_pos.lineno = current_file->lineno;
if (id && id->flags & TF_COMMAND) {
zconflval.id = id;
return id->token;
}
alloc_string(yytext, yyleng);
zconflval.string = text;
return T_WORD;
}
//匹配标识符(可能已经存在),切换到PARAM状态
.
//忽略其它字符
\n {
BEGIN(INITIAL);
current_file->lineno++;
return T_EOL;
}
//换行切换为INIT状态
}
<PARAM>{
//PARAM状态下的pattern & action
"&&" return T_AND;
"||" return T_OR;
"(" return T_OPEN_PAREN;
")" return T_CLOSE_PAREN;
"!" return T_NOT;
"=" return T_EQUAL;
"!=" return T_UNEQUAL;
//字符串常量,各种操作符
\"|\' {
str = yytext;
new_string();
BEGIN(STRING);
}
//单引号或双引号,切换为STRING状态
\n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
//换行切换为INIT状态
--- /* ignore */
//忽略---
({n}|[-/.])+ {
struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
if (id && id->flags & TF_PARAM) {
zconflval.id = id;
return id->token;
}
alloc_string(yytext, yyleng);
zconflval.string = text;
return T_WORD;
}
//匹配标识符
#.* /* comment */
//注释,忽略
\\\n current_file->lineno++;
//line continue,忽略
.
//忽略其它字符
<<EOF>> {
BEGIN(INITIAL);
}
}
<STRING>{
//STRING状态下的pattern & action
[^'"\\\n]+/\n {
append_string(yytext, yyleng);
zconflval.string = text;
return T_WORD_QUOTE;
}
//行末的串,不包括引号和转义
[^'"\\\n]+ {
append_string(yytext, yyleng);
}
//非行未的(部分)串,不包括引号和转义
\\.?/\n {
append_string(yytext + 1, yyleng - 1);
zconflval.string = text;
return T_WORD_QUOTE;
}
//行末的转义,串结束
\\.? {
append_string(yytext + 1, yyleng - 1);
}
//非行末的转义,串未结束
\'|\" {
if (str == yytext) {
BEGIN(PARAM);
zconflval.string = text;
return T_WORD_QUOTE;
//字符串结束
} else
append_string(yytext, 1);
//引号本身作为字符串的一部分
}
\n {
printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
current_file->lineno++;
BEGIN(INITIAL);
return T_EOL;
}
//换行结束STRING状态
<<EOF>> {
BEGIN(INITIAL);
}
}
<HELP>{
//HELP状态下的pattern & acttion
[ \t]+{
ts = 0;
for (i = 0; i < yyleng; i++) {
if (yytext == '\t')
ts = (ts & ~7) + 8;
else
ts++;
}
last_ts = ts;
if (first_ts) {
if (ts < first_ts) {
zconf_endhelp();
return T_HELPTEXT;
}
ts -= first_ts;
while (ts > 8) {
append_string(" ", 8);
ts -= 8;
}
append_string(" ", ts);
}
}
//看起来像是tab展开,基于缩进量判断help是否结束(python风格……)
[ \t]*\n/[^ \t\n] {
current_file->lineno++;
zconf_endhelp();
return T_HELPTEXT;
}
//下一行没有缩进,help结束
[ \t]*\n {
current_file->lineno++;
append_string("\n", 1);
}
//忽略行末空白,help可以包含换行
[^ \t\n].* {
while (yyleng) {
if ((yytext != ' ') && (yytext != '\t'))
break;
yyleng--;
}
append_string(yytext, yyleng);
if (!first_ts)
first_ts = last_ts;
}
//help正文本身(未结束),忽略末尾的空白,并计算第一行的缩进量
<<EOF>> {
zconf_endhelp();
return T_HELPTEXT;
}
}
第三部分是原封不动的代码,不解释。 回复 4# Buddy_Zhang1
看同目录下的makefile
conf-objs := conf.ozconf.tab.o
$(obj)/zconf.tab.o: $(obj)/lex.zconf.c $(obj)/zconf.hash.c
$(obj)/zconf.tab.c: $(src)/zconf.y
$(obj)/lex.zconf.c: $(src)/zconf.l
%.tab.c: %.y
bison -l -b $* -p $(notdir $*) $<
cp $@ $@_shipped
lex.%.c: %.l
flex -L -P$(notdir $*) -o$@ $<
cp $@ $@_shipped
不知道有没有理解错误楼主的问题。
flex:
-P,--prefix=STRING use STRING as prefix instead of "yy"
-L,--noline suppress #line directives in scanner
bison:
-p, --name-prefix=PREFIX prepend PREFIX to the external symbols
-l, --no-lines don't generate `#line' directives
$*代表%匹配的部分,所以,对于匹配lex.%.c的lex.zonf.c而言,%就是zconf
所以yylex就是zconflex
不好意思审题不仔细:-L 回复 8# nswcfd
牛逼,我就是要这样的答案,通过你的答复,我已经找到满意回复了
牛逼
今天论坛回复给力,幸好今天没水逆。
你在微信群里叫什么名字,大神。 回复 7# nswcfd
我就是想要这个东西
%.tab.c: %.y
bison -l -b $* -p $(notdir $*) $<
cp $@ $@_shipped
lex.%.c: %.l
flex -L -P$(notdir $*) -o$@ $<
cp $@ $@_shipped
今天本来这是碰碰运气看能否解决
大神果然牛逼!!!
页:
[1]
2