kconfig: remove string expansion for mainmenu after yyparse()
[carl9170fw.git] / config / zconf.y
index bd2c500d8a7b4c27b7a27f26dfbe2cfad174383e..228a14b24faee961505cb3e473fbcac0d4c5c80b 100644 (file)
 
 int cdebug = PRINTD;
 
-extern int zconflex(void);
+int yylex(void);
+static void yyerror(const char *err);
 static void zconfprint(const char *err, ...);
 static void zconf_error(const char *err, ...);
-static void zconferror(const char *err);
 static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
 
 struct symbol *symbol_hash[SYMBOL_HASHSIZE];
@@ -31,7 +31,7 @@ struct symbol *symbol_hash[SYMBOL_HASHSIZE];
 static struct menu *current_menu, *current_entry;
 
 %}
-%expect 30
+%expect 32
 
 %union
 {
@@ -62,6 +62,7 @@ static struct menu *current_menu, *current_entry;
 %token <id>T_TYPE
 %token <id>T_DEFAULT
 %token <id>T_SELECT
+%token <id>T_IMPLY
 %token <id>T_RANGE
 %token <id>T_VISIBLE
 %token <id>T_OPTION
@@ -69,6 +70,10 @@ static struct menu *current_menu, *current_entry;
 %token <string> T_WORD
 %token <string> T_WORD_QUOTE
 %token T_UNEQUAL
+%token T_LESS
+%token T_LESS_EQUAL
+%token T_GREATER
+%token T_GREATER_EQUAL
 %token T_CLOSE_PAREN
 %token T_OPEN_PAREN
 %token T_EOL
@@ -76,9 +81,11 @@ static struct menu *current_menu, *current_entry;
 %left T_OR
 %left T_AND
 %left T_EQUAL T_UNEQUAL
+%left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL
 %nonassoc T_NOT
 
 %type <string> prompt
+%type <symbol> nonconst_symbol
 %type <symbol> symbol
 %type <expr> expr
 %type <expr> if_expr
@@ -95,8 +102,8 @@ static struct menu *current_menu, *current_entry;
 } if_entry menu_entry choice_entry
 
 %{
-/* Include zconf.hash.c here so it can see the token constants. */
-#include "zconf.hash.c"
+/* Include kconf_id.c here so it can see the token constants. */
+#include "kconf_id.c"
 %}
 
 %%
@@ -104,6 +111,13 @@ input: nl start | start;
 
 start: mainmenu_stmt stmt_list | stmt_list;
 
+/* mainmenu entry */
+
+mainmenu_stmt: T_MAINMENU prompt nl
+{
+       menu_add_prompt(P_MENU, $2, NULL);
+};
+
 stmt_list:
          /* empty */
        | stmt_list common_stmt
@@ -113,13 +127,13 @@ stmt_list:
        | stmt_list T_WORD error T_EOL  { zconf_error("unknown statement \"%s\"", $2); }
        | stmt_list option_name error T_EOL
 {
-       zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name);
+       zconf_error("unexpected option \"%s\"", $2->name);
 }
        | stmt_list error T_EOL         { zconf_error("invalid statement"); }
 ;
 
 option_name:
-       T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
+       T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_IMPLY | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
 ;
 
 common_stmt:
@@ -139,26 +153,23 @@ option_error:
 
 /* config/menuconfig entry */
 
-config_entry_start: T_CONFIG T_WORD T_EOL
+config_entry_start: T_CONFIG nonconst_symbol T_EOL
 {
-       struct symbol *sym = sym_lookup($2, 0);
-       sym->flags |= SYMBOL_OPTIONAL;
-       menu_add_entry(sym);
-       printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
+       $2->flags |= SYMBOL_OPTIONAL;
+       menu_add_entry($2);
+       printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2->name);
 };
 
 config_stmt: config_entry_start config_option_list
 {
-       menu_end_entry();
        printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
 };
 
-menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
+menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL
 {
-       struct symbol *sym = sym_lookup($2, 0);
-       sym->flags |= SYMBOL_OPTIONAL;
-       menu_add_entry(sym);
-       printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
+       $2->flags |= SYMBOL_OPTIONAL;
+       menu_add_entry($2);
+       printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2->name);
 };
 
 menuconfig_stmt: menuconfig_entry_start config_option_list
@@ -167,7 +178,6 @@ menuconfig_stmt: menuconfig_entry_start config_option_list
                current_entry->prompt->type = P_MENU;
        else
                zconfprint("warning: menuconfig statement without prompt");
-       menu_end_entry();
        printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
 };
 
@@ -205,12 +215,18 @@ config_option: T_DEFAULT expr if_expr T_EOL
                $1->stype);
 };
 
-config_option: T_SELECT T_WORD if_expr T_EOL
+config_option: T_SELECT nonconst_symbol if_expr T_EOL
 {
-       menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
+       menu_add_symbol(P_SELECT, $2, $3);
        printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
 };
 
+config_option: T_IMPLY nonconst_symbol if_expr T_EOL
+{
+       menu_add_symbol(P_IMPLY, $2, $3);
+       printd(DEBUG_PARSE, "%s:%d:imply\n", zconf_curname(), zconf_lineno());
+};
+
 config_option: T_RANGE symbol symbol if_expr T_EOL
 {
        menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
@@ -225,8 +241,10 @@ symbol_option_list:
        | symbol_option_list T_WORD symbol_option_arg
 {
        const struct kconf_id *id = kconf_id_lookup($2, strlen($2));
-       if (id && id->flags & TF_OPTION)
+       if (id && id->flags & TF_OPTION) {
                menu_add_option(id->token, $3);
+               free($3);
+       }
        else
                zconfprint("warning: ignoring unknown option %s", $2);
        free($2);
@@ -245,6 +263,7 @@ choice: T_CHOICE word_opt T_EOL
        sym->flags |= SYMBOL_AUTO;
        menu_add_entry(sym);
        menu_add_expr(P_CHOICE, NULL, NULL);
+       free($2);
        printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
 };
 
@@ -296,10 +315,10 @@ choice_option: T_OPTIONAL T_EOL
        printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
 };
 
-choice_option: T_DEFAULT T_WORD if_expr T_EOL
+choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
 {
        if ($1->stype == S_UNKNOWN) {
-               menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
+               menu_add_symbol(P_DEFAULT, $2, $3);
                printd(DEBUG_PARSE, "%s:%d:default\n",
                        zconf_curname(), zconf_lineno());
        } else
@@ -339,13 +358,6 @@ if_block:
        | if_block choice_stmt
 ;
 
-/* mainmenu entry */
-
-mainmenu_stmt: T_MAINMENU prompt nl
-{
-       menu_add_prompt(P_MENU, $2, NULL);
-};
-
 /* menu entry */
 
 menu: T_MENU prompt T_EOL
@@ -382,6 +394,7 @@ source_stmt: T_SOURCE prompt T_EOL
 {
        printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
        zconf_nextfile($2);
+       free($2);
 };
 
 /* comment entry */
@@ -394,9 +407,7 @@ comment: T_COMMENT prompt T_EOL
 };
 
 comment_stmt: comment depends_list
-{
-       menu_end_entry();
-};
+;
 
 /* help option */
 
@@ -408,6 +419,17 @@ help_start: T_HELP T_EOL
 
 help: help_start T_HELPTEXT
 {
+       if (current_entry->help) {
+               free(current_entry->help);
+               zconfprint("warning: '%s' defined with more than one help text -- only the last one will be used",
+                          current_entry->sym->name ?: "<choice>");
+       }
+
+       /* Is the help text empty or all whitespace? */
+       if ($2[strspn($2, " \f\n\r\t\v")] == '\0')
+               zconfprint("warning: '%s' defined with blank help text",
+                          current_entry->sym->name ?: "<choice>");
+
        current_entry->help = $2;
 };
 
@@ -467,6 +489,10 @@ if_expr:  /* empty */                      { $$ = NULL; }
 ;
 
 expr:    symbol                                { $$ = expr_alloc_symbol($1); }
+       | symbol T_LESS symbol                  { $$ = expr_alloc_comp(E_LTH, $1, $3); }
+       | symbol T_LESS_EQUAL symbol            { $$ = expr_alloc_comp(E_LEQ, $1, $3); }
+       | symbol T_GREATER symbol               { $$ = expr_alloc_comp(E_GTH, $1, $3); }
+       | symbol T_GREATER_EQUAL symbol         { $$ = expr_alloc_comp(E_GEQ, $1, $3); }
        | symbol T_EQUAL symbol                 { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
        | symbol T_UNEQUAL symbol               { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
        | T_OPEN_PAREN expr T_CLOSE_PAREN       { $$ = $2; }
@@ -475,7 +501,10 @@ expr:        symbol                                { $$ = expr_alloc_symbol($1); }
        | expr T_AND expr                       { $$ = expr_alloc_two(E_AND, $1, $3); }
 ;
 
-symbol:          T_WORD        { $$ = sym_lookup($1, 0); free($1); }
+/* For symbol definitions, selects, etc., where quotes are not accepted */
+nonconst_symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); };
+
+symbol:          nonconst_symbol
        | T_WORD_QUOTE  { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
 ;
 
@@ -491,27 +520,28 @@ void conf_parse(const char *name)
 
        zconf_initscan(name);
 
-       sym_init();
        _menu_init();
        rootmenu.prompt = menu_add_prompt(P_MENU, "CARL9170 Firmware Configuration", NULL);
 
        if (getenv("ZCONF_DEBUG"))
-               zconfdebug = 1;
-       zconfparse();
-       if (zconfnerrs)
+               yydebug = 1;
+       yyparse();
+       if (yynerrs)
                exit(1);
        if (!modules_sym)
                modules_sym = sym_find( "n" );
 
-       rootmenu.prompt->text = _(rootmenu.prompt->text);
-       rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
+       if (!menu_has_prompt(&rootmenu)) {
+               current_entry = &rootmenu;
+               menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
+       }
 
        menu_finalize(&rootmenu);
        for_all_symbols(i, sym) {
                if (sym_check_deps(sym))
-                       zconfnerrs++;
+                       yynerrs++;
        }
-       if (zconfnerrs)
+       if (yynerrs)
                exit(1);
        sym_set_change_count(1);
 }
@@ -535,17 +565,17 @@ static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtok
 {
        if (id->token != endtoken) {
                zconf_error("unexpected '%s' within %s block",
-                       kconf_id_strings + id->name, zconf_tokenname(starttoken));
-               zconfnerrs++;
+                       id->name, zconf_tokenname(starttoken));
+               yynerrs++;
                return false;
        }
        if (current_menu->file != current_file) {
                zconf_error("'%s' in different file than '%s'",
-                       kconf_id_strings + id->name, zconf_tokenname(starttoken));
+                       id->name, zconf_tokenname(starttoken));
                fprintf(stderr, "%s:%d: location of the '%s'\n",
                        current_menu->file->name, current_menu->lineno,
                        zconf_tokenname(starttoken));
-               zconfnerrs++;
+               yynerrs++;
                return false;
        }
        return true;
@@ -566,7 +596,7 @@ static void zconf_error(const char *err, ...)
 {
        va_list ap;
 
-       zconfnerrs++;
+       yynerrs++;
        fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
        va_start(ap, err);
        vfprintf(stderr, err, ap);
@@ -574,7 +604,7 @@ static void zconf_error(const char *err, ...)
        fprintf(stderr, "\n");
 }
 
-static void zconferror(const char *err)
+static void yyerror(const char *err)
 {
        fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
 }
@@ -607,7 +637,7 @@ static void print_symbol(FILE *out, struct menu *menu)
                fprintf(out, "\nconfig %s\n", sym->name);
        switch (sym->type) {
        case S_BOOLEAN:
-               fputs("  boolean\n", out);
+               fputs("  bool\n", out);
                break;
        case S_TRISTATE:
                fputs("  tristate\n", out);
@@ -655,6 +685,11 @@ static void print_symbol(FILE *out, struct menu *menu)
                        expr_fprint(prop->expr, out);
                        fputc('\n', out);
                        break;
+               case P_IMPLY:
+                       fputs( "  imply ", out);
+                       expr_fprint(prop->expr, out);
+                       fputc('\n', out);
+                       break;
                case P_RANGE:
                        fputs( "  range ", out);
                        expr_fprint(prop->expr, out);
@@ -731,3 +766,4 @@ void zconfdump(FILE *out)
 #include "expr.c"
 #include "symbol.c"
 #include "menu.c"
+#include "preprocess.c"