diff options
Diffstat (limited to 'scripts/kconfig/zconf.l')
-rw-r--r-- | scripts/kconfig/zconf.l | 235 |
1 files changed, 125 insertions, 110 deletions
diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l index 25bd2b89fe3f..b2d0a3b0bce9 100644 --- a/scripts/kconfig/zconf.l +++ b/scripts/kconfig/zconf.l @@ -1,11 +1,11 @@ -%option nostdinit noyywrap never-interactive full ecs -%option 8bit nodefault yylineno -%x COMMAND HELP STRING PARAM ASSIGN_VAL -%{ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> - * Released under the terms of the GNU GPL v2.0. */ +%option nostdinit noyywrap never-interactive full ecs +%option 8bit nodefault yylineno +%x ASSIGN_VAL HELP STRING +%{ #include <assert.h> #include <limits.h> @@ -15,6 +15,9 @@ #include <unistd.h> #include "lkc.h" +#include "zconf.tab.h" + +#define YY_DECL static int yylex1(void) #define START_STRSIZE 16 @@ -23,6 +26,8 @@ static struct { int lineno; } current_pos; +static int prev_prev_token = T_EOL; +static int prev_token = T_EOL; static char *text; static int text_size, text_asize; @@ -73,7 +78,7 @@ static void warn_ignored_character(char chr) { fprintf(stderr, "%s:%d:warning: ignoring unsupported character '%c'\n", - zconf_curname(), zconf_lineno(), chr); + current_file->name, yylineno, chr); } %} @@ -83,54 +88,73 @@ n [A-Za-z0-9_-] int str = 0; int ts, i; -[ \t]*#.*\n | -[ \t]*\n { - return T_EOL; -} -[ \t]*#.* - - -[ \t]+ { - BEGIN(COMMAND); -} - -. { - unput(yytext[0]); - BEGIN(COMMAND); -} - - -<COMMAND>{ - {n}+ { - const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); - current_pos.file = current_file; - current_pos.lineno = yylineno; - if (id && id->flags & TF_COMMAND) { - BEGIN(PARAM); - yylval.id = id; - return id->token; - } - alloc_string(yytext, yyleng); - yylval.string = text; - return T_VARIABLE; - } - ({n}|$)+ { - /* this token includes at least one '$' */ - yylval.string = expand_token(yytext, yyleng); - if (strlen(yylval.string)) - return T_VARIABLE; - free(yylval.string); - } - "=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_RECURSIVE; return T_ASSIGN; } - ":=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_SIMPLE; return T_ASSIGN; } - "+=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_APPEND; return T_ASSIGN; } - [[:blank:]]+ - . warn_ignored_character(*yytext); - \n { - BEGIN(INITIAL); - return T_EOL; - } -} +#.* /* ignore comment */ +[ \t]* /* whitespaces */ +\\\n /* escaped new line */ +\n return T_EOL; +"allnoconfig_y" return T_ALLNOCONFIG_Y; +"bool" return T_BOOL; +"choice" return T_CHOICE; +"comment" return T_COMMENT; +"config" return T_CONFIG; +"def_bool" return T_DEF_BOOL; +"def_tristate" return T_DEF_TRISTATE; +"default" return T_DEFAULT; +"defconfig_list" return T_DEFCONFIG_LIST; +"depends" return T_DEPENDS; +"endchoice" return T_ENDCHOICE; +"endif" return T_ENDIF; +"endmenu" return T_ENDMENU; +"help"|"---help---" return T_HELP; +"hex" return T_HEX; +"if" return T_IF; +"imply" return T_IMPLY; +"int" return T_INT; +"mainmenu" return T_MAINMENU; +"menu" return T_MENU; +"menuconfig" return T_MENUCONFIG; +"modules" return T_MODULES; +"on" return T_ON; +"option" return T_OPTION; +"optional" return T_OPTIONAL; +"prompt" return T_PROMPT; +"range" return T_RANGE; +"select" return T_SELECT; +"source" return T_SOURCE; +"string" return T_STRING; +"tristate" return T_TRISTATE; +"visible" return T_VISIBLE; +"||" return T_OR; +"&&" return T_AND; +"=" return T_EQUAL; +"!=" return T_UNEQUAL; +"<" return T_LESS; +"<=" return T_LESS_EQUAL; +">" return T_GREATER; +">=" return T_GREATER_EQUAL; +"!" return T_NOT; +"(" return T_OPEN_PAREN; +")" return T_CLOSE_PAREN; +":=" return T_COLON_EQUAL; +"+=" return T_PLUS_EQUAL; +\"|\' { + str = yytext[0]; + new_string(); + BEGIN(STRING); + } +{n}+ { + alloc_string(yytext, yyleng); + yylval.string = text; + return T_WORD; + } +({n}|$)+ { + /* this token includes at least one '$' */ + yylval.string = expand_token(yytext, yyleng); + if (strlen(yylval.string)) + return T_WORD; + free(yylval.string); + } +. warn_ignored_character(*yytext); <ASSIGN_VAL>{ [^[:blank:]\n]+.* { @@ -142,71 +166,17 @@ n [A-Za-z0-9_-] . } -<PARAM>{ - "&&" return T_AND; - "||" return T_OR; - "(" return T_OPEN_PAREN; - ")" return T_CLOSE_PAREN; - "!" return T_NOT; - "=" return T_EQUAL; - "!=" return T_UNEQUAL; - "<=" return T_LESS_EQUAL; - ">=" return T_GREATER_EQUAL; - "<" return T_LESS; - ">" return T_GREATER; - \"|\' { - str = yytext[0]; - new_string(); - BEGIN(STRING); - } - \n BEGIN(INITIAL); return T_EOL; - ({n}|[/.])+ { - const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); - if (id && id->flags & TF_PARAM) { - yylval.id = id; - return id->token; - } - alloc_string(yytext, yyleng); - yylval.string = text; - return T_WORD; - } - ({n}|[/.$])+ { - /* this token includes at least one '$' */ - yylval.string = expand_token(yytext, yyleng); - if (strlen(yylval.string)) - return T_WORD; - free(yylval.string); - } - #.* /* comment */ - \\\n ; - [[:blank:]]+ - . warn_ignored_character(*yytext); - <<EOF>> { - BEGIN(INITIAL); - } -} - <STRING>{ "$".* append_expanded_string(yytext); - [^$'"\\\n]+/\n { - append_string(yytext, yyleng); - yylval.string = text; - return T_WORD_QUOTE; - } [^$'"\\\n]+ { append_string(yytext, yyleng); } - \\.?/\n { - append_string(yytext + 1, yyleng - 1); - yylval.string = text; - return T_WORD_QUOTE; - } \\.? { append_string(yytext + 1, yyleng - 1); } \'|\" { if (str == yytext[0]) { - BEGIN(PARAM); + BEGIN(INITIAL); yylval.string = text; return T_WORD_QUOTE; } else @@ -216,11 +186,15 @@ n [A-Za-z0-9_-] fprintf(stderr, "%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + unput('\n'); BEGIN(INITIAL); - return T_EOL; + yylval.string = text; + return T_WORD_QUOTE; } <<EOF>> { BEGIN(INITIAL); + yylval.string = text; + return T_WORD_QUOTE; } } @@ -271,6 +245,12 @@ n [A-Za-z0-9_-] } <<EOF>> { + BEGIN(INITIAL); + + if (prev_token != T_EOL && prev_token != T_HELPTEXT) + fprintf(stderr, "%s:%d:warning: no new line at end of file\n", + current_file->name, yylineno); + if (current_file) { zconf_endfile(); return T_EOL; @@ -280,6 +260,41 @@ n [A-Za-z0-9_-] } %% + +/* second stage lexer */ +int yylex(void) +{ + int token; + +repeat: + token = yylex1(); + + if (prev_token == T_EOL || prev_token == T_HELPTEXT) { + if (token == T_EOL) { + /* Do not pass unneeded T_EOL to the parser. */ + goto repeat; + } else { + /* + * For the parser, update file/lineno at the first token + * of each statement. Generally, \n is a statement + * terminator in Kconfig, but it is not always true + * because \n could be escaped by a backslash. + */ + current_pos.file = current_file; + current_pos.lineno = yylineno; + } + } + + if (prev_prev_token == T_EOL && prev_token == T_WORD && + (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL)) + BEGIN(ASSIGN_VAL); + + prev_prev_token = prev_token; + prev_token = token; + + return token; +} + static char *expand_token(const char *in, size_t n) { char *out; |