Revert "build: scripts/config - update to kconfig-v5.6"
[oweals/openwrt.git] / scripts / config / menu.c
index 1df87dd3a5b2986168b9b0e3e2c8e8f7d02eb199..3d89dc178d7cb15f32ca0b953ec163ed3fc76f67 100644 (file)
@@ -1,6 +1,6 @@
-// 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.
  */
 
 #include <ctype.h>
@@ -62,8 +62,13 @@ void menu_add_entry(struct symbol *sym)
                menu_add_symbol(P_SYMBOL, sym, NULL);
 }
 
+void menu_end_entry(void)
+{
+}
+
 struct menu *menu_add_menu(void)
 {
+       menu_end_entry();
        last_entry_ptr = &current_entry->list;
        return current_menu = current_entry;
 }
@@ -74,23 +79,19 @@ void menu_end_menu(void)
        current_menu = current_menu->parent;
 }
 
-/*
- * Rewrites 'm' to 'm' && MODULES, so that it evaluates to 'n' when running
- * without modules
- */
-static struct expr *rewrite_m(struct expr *e)
+static struct expr *menu_check_dep(struct expr *e)
 {
        if (!e)
                return e;
 
        switch (e->type) {
        case E_NOT:
-               e->left.expr = rewrite_m(e->left.expr);
+               e->left.expr = menu_check_dep(e->left.expr);
                break;
        case E_OR:
        case E_AND:
-               e->left.expr = rewrite_m(e->left.expr);
-               e->right.expr = rewrite_m(e->right.expr);
+               e->left.expr = menu_check_dep(e->left.expr);
+               e->right.expr = menu_check_dep(e->right.expr);
                break;
        case E_SYMBOL:
                /* change 'm' into 'm' && MODULES */
@@ -105,7 +106,7 @@ static struct expr *rewrite_m(struct expr *e)
 
 void menu_add_dep(struct expr *dep)
 {
-       current_entry->dep = expr_alloc_and(current_entry->dep, dep);
+       current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
 }
 
 void menu_set_type(int type)
@@ -124,76 +125,61 @@ void menu_set_type(int type)
                sym_type_name(sym->type), sym_type_name(type));
 }
 
-struct property *menu_add_prop(enum prop_type type, struct expr *expr,
-                              struct expr *dep)
+struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
 {
-       struct property *prop;
+       struct property *prop = prop_alloc(type, current_entry->sym);
 
-       prop = xmalloc(sizeof(*prop));
-       memset(prop, 0, sizeof(*prop));
-       prop->type = type;
-       prop->file = current_file;
-       prop->lineno = zconf_lineno();
        prop->menu = current_entry;
        prop->expr = expr;
-       prop->visible.expr = dep;
-
-       /* append property to the prop list of symbol */
-       if (current_entry->sym) {
-               struct property **propp;
-
-               for (propp = &current_entry->sym->prop;
-                    *propp;
-                    propp = &(*propp)->next)
-                       ;
-               *propp = prop;
-       }
-
-       return prop;
-}
-
-struct property *menu_add_prompt(enum prop_type type, char *prompt,
-                                struct expr *dep)
-{
-       struct property *prop = menu_add_prop(type, NULL, dep);
+       prop->visible.expr = menu_check_dep(dep);
 
-       if (isspace(*prompt)) {
-               prop_warn(prop, "leading whitespace ignored");
-               while (isspace(*prompt))
-                       prompt++;
-       }
-       if (current_entry->prompt)
-               prop_warn(prop, "prompt redefined");
+       if (prompt) {
+               if (isspace(*prompt)) {
+                       prop_warn(prop, "leading whitespace ignored");
+                       while (isspace(*prompt))
+                               prompt++;
+               }
+               if (current_entry->prompt && current_entry != &rootmenu)
+                       prop_warn(prop, "prompt redefined");
 
-       /* Apply all upper menus' visibilities to actual prompts. */
-       if (type == P_PROMPT) {
-               struct menu *menu = current_entry;
+               /* Apply all upper menus' visibilities to actual prompts. */
+               if(type == P_PROMPT) {
+                       struct menu *menu = current_entry;
 
-               while ((menu = menu->parent) != NULL) {
-                       struct expr *dup_expr;
+                       while ((menu = menu->parent) != NULL) {
+                               struct expr *dup_expr;
 
-                       if (!menu->visibility)
-                               continue;
-                       /*
-                        * Do not add a reference to the menu's visibility
-                        * expression but use a copy of it. Otherwise the
-                        * expression reduction functions will modify
-                        * expressions that have multiple references which
-                        * can cause unwanted side effects.
-                        */
-                       dup_expr = expr_copy(menu->visibility);
+                               if (!menu->visibility)
+                                       continue;
+                               /*
+                                * Do not add a reference to the
+                                * menu's visibility expression but
+                                * use a copy of it.  Otherwise the
+                                * expression reduction functions
+                                * will modify expressions that have
+                                * multiple references which can
+                                * cause unwanted side effects.
+                                */
+                               dup_expr = expr_copy(menu->visibility);
 
-                       prop->visible.expr = expr_alloc_and(prop->visible.expr,
-                                                           dup_expr);
+                               prop->visible.expr
+                                       = expr_alloc_and(prop->visible.expr,
+                                                        dup_expr);
+                       }
                }
-       }
 
-       current_entry->prompt = prop;
+               current_entry->prompt = prop;
+       }
        prop->text = prompt;
 
        return prop;
 }
 
+struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
+{
+       return menu_add_prop(type, prompt, NULL, dep);
+}
+
 void menu_add_visibility(struct expr *expr)
 {
        current_entry->visibility = expr_alloc_and(current_entry->visibility,
@@ -202,34 +188,39 @@ void menu_add_visibility(struct expr *expr)
 
 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
 {
-       menu_add_prop(type, expr, dep);
+       menu_add_prop(type, NULL, expr, dep);
 }
 
 void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
 {
-       menu_add_prop(type, expr_alloc_symbol(sym), dep);
+       menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
 }
 
-void menu_add_option_modules(void)
+void menu_add_option(int token, char *arg)
 {
-       if (modules_sym)
-               zconf_error("symbol '%s' redefines option 'modules' already defined by symbol '%s'",
-                           current_entry->sym->name, modules_sym->name);
-       modules_sym = current_entry->sym;
-}
-
-void menu_add_option_defconfig_list(void)
-{
-       if (!sym_defconfig_list)
-               sym_defconfig_list = current_entry->sym;
-       else if (sym_defconfig_list != current_entry->sym)
-               zconf_error("trying to redefine defconfig symbol");
-       sym_defconfig_list->flags |= SYMBOL_NO_WRITE;
-}
-
-void menu_add_option_allnoconfig_y(void)
-{
-       current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
+       switch (token) {
+       case T_OPT_MODULES:
+               if (modules_sym)
+                       zconf_error("symbol '%s' redefines option 'modules'"
+                                   " already defined by symbol '%s'",
+                                   current_entry->sym->name,
+                                   modules_sym->name
+                                   );
+               modules_sym = current_entry->sym;
+               break;
+       case T_OPT_DEFCONFIG_LIST:
+               if (!sym_defconfig_list)
+                       sym_defconfig_list = current_entry->sym;
+               else if (sym_defconfig_list != current_entry->sym)
+                       zconf_error("trying to redefine defconfig symbol");
+               break;
+       case T_OPT_ENV:
+               prop_add_env(arg);
+               break;
+       case T_OPT_ALLNOCONFIG_Y:
+               current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
+               break;
+       }
 }
 
 static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
@@ -242,8 +233,6 @@ static void sym_check_prop(struct symbol *sym)
 {
        struct property *prop;
        struct symbol *sym2;
-       char *use;
-
        for (prop = sym->prop; prop; prop = prop->next) {
                switch (prop->type) {
                case P_DEFAULT:
@@ -261,32 +250,20 @@ static void sym_check_prop(struct symbol *sym)
                                            "'%s': number is invalid",
                                            sym->name);
                        }
-                       if (sym_is_choice(sym)) {
-                               struct property *choice_prop =
-                                       sym_get_choice_prop(sym2);
-
-                               if (!choice_prop ||
-                                   prop_get_symbol(choice_prop) != sym)
-                                       prop_warn(prop,
-                                                 "choice default symbol '%s' is not contained in the choice",
-                                                 sym2->name);
-                       }
                        break;
                case P_SELECT:
-               case P_IMPLY:
-                       use = prop->type == P_SELECT ? "select" : "imply";
                        sym2 = prop_get_symbol(prop);
                        if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
                                prop_warn(prop,
-                                   "config symbol '%s' uses %s, but is "
-                                   "not bool or tristate", sym->name, use);
+                                   "config symbol '%s' uses select, but is "
+                                   "not boolean or tristate", sym->name);
                        else if (sym2->type != S_UNKNOWN &&
                                 sym2->type != S_BOOLEAN &&
                                 sym2->type != S_TRISTATE)
                                prop_warn(prop,
-                                   "'%s' has wrong type. '%s' only "
-                                   "accept arguments of bool and "
-                                   "tristate type", sym2->name, use);
+                                   "'%s' has wrong type. 'select' only "
+                                   "accept arguments of boolean and "
+                                   "tristate type", sym2->name);
                        break;
                case P_RANGE:
                        if (sym->type != S_INT && sym->type != S_HEX)
@@ -311,11 +288,6 @@ void menu_finalize(struct menu *parent)
 
        sym = parent->sym;
        if (parent->list) {
-               /*
-                * This menu node has children. We (recursively) process them
-                * and propagate parent dependencies before moving on.
-                */
-
                if (sym && sym_is_choice(sym)) {
                        if (sym->type == S_UNKNOWN) {
                                /* find the first choice value to find out choice type */
@@ -333,167 +305,65 @@ void menu_finalize(struct menu *parent)
                                if (menu->sym && menu->sym->type == S_UNKNOWN)
                                        menu_set_type(sym->type);
                        }
-
-                       /*
-                        * Use the choice itself as the parent dependency of
-                        * the contained items. This turns the mode of the
-                        * choice into an upper bound on the visibility of the
-                        * choice value symbols.
-                        */
                        parentdep = expr_alloc_symbol(sym);
-               } else {
-                       /* Menu node for 'menu', 'if' */
+               } else if (parent->prompt)
+                       parentdep = parent->prompt->visible.expr;
+               else
                        parentdep = parent->dep;
-               }
 
-               /* For each child menu node... */
                for (menu = parent->list; menu; menu = menu->next) {
-                       /*
-                        * Propagate parent dependencies to the child menu
-                        * node, also rewriting and simplifying expressions
-                        */
-                       basedep = rewrite_m(menu->dep);
-                       basedep = expr_transform(basedep);
+                       basedep = expr_transform(menu->dep);
                        basedep = expr_alloc_and(expr_copy(parentdep), basedep);
                        basedep = expr_eliminate_dups(basedep);
                        menu->dep = basedep;
-
                        if (menu->sym)
-                               /*
-                                * Note: For symbols, all prompts are included
-                                * too in the symbol's own property list
-                                */
                                prop = menu->sym->prop;
                        else
-                               /*
-                                * For non-symbol menu nodes, we just need to
-                                * handle the prompt
-                                */
                                prop = menu->prompt;
-
-                       /* For each property... */
                        for (; prop; prop = prop->next) {
                                if (prop->menu != menu)
-                                       /*
-                                        * Two possibilities:
-                                        *
-                                        * 1. The property lacks dependencies
-                                        *    and so isn't location-specific,
-                                        *    e.g. an 'option'
-                                        *
-                                        * 2. The property belongs to a symbol
-                                        *    defined in multiple locations and
-                                        *    is from some other location. It
-                                        *    will be handled there in that
-                                        *    case.
-                                        *
-                                        * Skip the property.
-                                        */
                                        continue;
-
-                               /*
-                                * Propagate parent dependencies to the
-                                * property's condition, rewriting and
-                                * simplifying expressions at the same time
-                                */
-                               dep = rewrite_m(prop->visible.expr);
-                               dep = expr_transform(dep);
+                               dep = expr_transform(prop->visible.expr);
                                dep = expr_alloc_and(expr_copy(basedep), dep);
                                dep = expr_eliminate_dups(dep);
                                if (menu->sym && menu->sym->type != S_TRISTATE)
                                        dep = expr_trans_bool(dep);
                                prop->visible.expr = dep;
-
-                               /*
-                                * Handle selects and implies, which modify the
-                                * dependencies of the selected/implied symbol
-                                */
                                if (prop->type == P_SELECT) {
                                        struct symbol *es = prop_get_symbol(prop);
                                        es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
                                                        expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
-                               } else if (prop->type == P_IMPLY) {
-                                       struct symbol *es = prop_get_symbol(prop);
-                                       es->implied.expr = expr_alloc_or(es->implied.expr,
-                                                       expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
                                }
                        }
                }
-
-               if (sym && sym_is_choice(sym))
-                       expr_free(parentdep);
-
-               /*
-                * Recursively process children in the same fashion before
-                * moving on
-                */
                for (menu = parent->list; menu; menu = menu->next)
                        menu_finalize(menu);
        } else if (sym) {
-               /*
-                * Automatic submenu creation. If sym is a symbol and A, B, C,
-                * ... are consecutive items (symbols, menus, ifs, etc.) that
-                * all depend on sym, then the following menu structure is
-                * created:
-                *
-                *      sym
-                *       +-A
-                *       +-B
-                *       +-C
-                *       ...
-                *
-                * This also works recursively, giving the following structure
-                * if A is a symbol and B depends on A:
-                *
-                *      sym
-                *       +-A
-                *       | +-B
-                *       +-C
-                *       ...
-                */
-
                basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
                basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
                basedep = expr_eliminate_dups(expr_transform(basedep));
-
-               /* Examine consecutive elements after sym */
                last_menu = NULL;
                for (menu = parent->next; menu; menu = menu->next) {
                        dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
                        if (!expr_contains_symbol(dep, sym))
-                               /* No dependency, quit */
                                break;
                        if (expr_depends_symbol(dep, sym))
-                               /* Absolute dependency, put in submenu */
                                goto next;
-
-                       /*
-                        * Also consider it a dependency on sym if our
-                        * dependencies contain sym and are a "superset" of
-                        * sym's dependencies, e.g. '(sym || Q) && R' when sym
-                        * depends on R.
-                        *
-                        * Note that 'R' might be from an enclosing menu or if,
-                        * making this a more common case than it might seem.
-                        */
                        dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
                        dep = expr_eliminate_dups(expr_transform(dep));
                        dep2 = expr_copy(basedep);
                        expr_eliminate_eq(&dep, &dep2);
                        expr_free(dep);
                        if (!expr_is_yes(dep2)) {
-                               /* Not superset, quit */
                                expr_free(dep2);
                                break;
                        }
-                       /* Superset, put in submenu */
                        expr_free(dep2);
                next:
                        menu_finalize(menu);
                        menu->parent = parent;
                        last_menu = menu;
                }
-               expr_free(basedep);
                if (last_menu) {
                        parent->list = parent->next;
                        parent->next = last_menu->next;
@@ -542,35 +412,6 @@ void menu_finalize(struct menu *parent)
                        *ep = expr_alloc_one(E_LIST, NULL);
                        (*ep)->right.sym = menu->sym;
                }
-
-               /*
-                * This code serves two purposes:
-                *
-                * (1) Flattening 'if' blocks, which do not specify a submenu
-                *     and only add dependencies.
-                *
-                *     (Automatic submenu creation might still create a submenu
-                *     from an 'if' before this code runs.)
-                *
-                * (2) "Undoing" any automatic submenus created earlier below
-                *     promptless symbols.
-                *
-                * Before:
-                *
-                *      A
-                *      if ... (or promptless symbol)
-                *       +-B
-                *       +-C
-                *      D
-                *
-                * After:
-                *
-                *      A
-                *      if ... (or promptless symbol)
-                *      B
-                *      C
-                *      D
-                */
                if (menu->list && (!menu->prompt || !menu->prompt->text)) {
                        for (last_menu = menu->list; ; last_menu = last_menu->next) {
                                last_menu->parent = parent;
@@ -595,15 +436,6 @@ void menu_finalize(struct menu *parent)
                sym->flags |= SYMBOL_WARNED;
        }
 
-       /*
-        * For non-optional choices, add a reverse dependency (corresponding to
-        * a select) of '<visibility> && m'. This prevents the user from
-        * setting the choice mode to 'n' when the choice is visible.
-        *
-        * This would also work for non-choice symbols, but only non-optional
-        * choices clear SYMBOL_OPTIONAL as of writing. Choices are implemented
-        * as a type of symbol.
-        */
        if (sym && !sym_is_optional(sym) && parent->prompt) {
                sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
                                expr_alloc_and(parent->prompt->visible.expr,
@@ -711,21 +543,6 @@ const char *menu_get_help(struct menu *menu)
                return "";
 }
 
-static void get_def_str(struct gstr *r, struct menu *menu)
-{
-       str_printf(r, "Defined at %s:%d\n",
-                  menu->file->name, menu->lineno);
-}
-
-static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix)
-{
-       if (!expr_is_yes(expr)) {
-               str_append(r, prefix);
-               expr_gstr_print(expr, r);
-               str_append(r, "\n");
-       }
-}
-
 static void get_prompt_str(struct gstr *r, struct property *prop,
                           struct list_head *head)
 {
@@ -733,20 +550,7 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
        struct menu *submenu[8], *menu, *location = NULL;
        struct jump_key *jump = NULL;
 
-       str_printf(r, "  Prompt: %s\n", prop->text);
-
-       get_dep_str(r, prop->menu->dep, "  Depends on: ");
-       /*
-        * Most prompts in Linux have visibility that exactly matches their
-        * dependencies. For these, we print only the dependencies to improve
-        * readability. However, prompts with inline "if" expressions and
-        * prompts with a parent that has a "visible if" expression have
-        * differing dependencies and visibility. In these rare cases, we
-        * print both.
-        */
-       if (!expr_eq(prop->menu->dep, prop->visible.expr))
-               get_dep_str(r, prop->visible.expr, "  Visible if: ");
-
+       str_printf(r, _("Prompt: %s\n"), _(prop->text));
        menu = prop->menu->parent;
        for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
                bool accessible = menu_is_visible(menu);
@@ -779,16 +583,16 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
        }
 
        if (i > 0) {
-               str_printf(r, "  Location:\n");
+               str_printf(r, _("  Location:\n"));
                for (j = 4; --i >= 0; j += 2) {
                        menu = submenu[i];
                        if (jump && menu == location)
                                jump->offset = strlen(r->s);
                        str_printf(r, "%*c-> %s", j, ' ',
-                                  menu_get_prompt(menu));
+                                  _(menu_get_prompt(menu)));
                        if (menu->sym) {
                                str_printf(r, " (%s [=%s])", menu->sym->name ?
-                                       menu->sym->name : "<choice>",
+                                       menu->sym->name : _("<choice>"),
                                        sym_get_string_value(menu->sym));
                        }
                        str_append(r, "\n");
@@ -796,22 +600,16 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
        }
 }
 
-static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
-                                enum prop_type tok, const char *prefix)
+/*
+ * get property of type P_SYMBOL
+ */
+static struct property *get_symbol_prop(struct symbol *sym)
 {
-       bool hit = false;
-       struct property *prop;
+       struct property *prop = NULL;
 
-       for_all_properties(sym, prop, tok) {
-               if (!hit) {
-                       str_append(r, prefix);
-                       hit = true;
-               } else
-                       str_printf(r, " && ");
-               expr_gstr_print(prop->expr, r);
-       }
-       if (hit)
-               str_append(r, "\n");
+       for_all_properties(sym, prop, P_SYMBOL)
+               break;
+       return prop;
 }
 
 /*
@@ -820,6 +618,7 @@ static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
 static void get_symbol_str(struct gstr *r, struct symbol *sym,
                    struct list_head *head)
 {
+       bool hit;
        struct property *prop;
 
        if (sym && sym->name) {
@@ -835,36 +634,36 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
                        }
                }
        }
-
-       /* Print the definitions with prompts before the ones without */
-       for_all_properties(sym, prop, P_SYMBOL) {
-               if (prop->menu->prompt) {
-                       get_def_str(r, prop->menu);
-                       get_prompt_str(r, prop->menu->prompt, head);
+       for_all_prompts(sym, prop)
+               get_prompt_str(r, prop, head);
+
+       prop = get_symbol_prop(sym);
+       if (prop) {
+               str_printf(r, _("  Defined at %s:%d\n"), prop->menu->file->name,
+                       prop->menu->lineno);
+               if (!expr_is_yes(prop->visible.expr)) {
+                       str_append(r, _("  Depends on: "));
+                       expr_gstr_print(prop->visible.expr, r);
+                       str_append(r, "\n");
                }
        }
 
-       for_all_properties(sym, prop, P_SYMBOL) {
-               if (!prop->menu->prompt) {
-                       get_def_str(r, prop->menu);
-                       get_dep_str(r, prop->menu->dep, "  Depends on: ");
-               }
+       hit = false;
+       for_all_properties(sym, prop, P_SELECT) {
+               if (!hit) {
+                       str_append(r, "  Selects: ");
+                       hit = true;
+               } else
+                       str_printf(r, " && ");
+               expr_gstr_print(prop->expr, r);
        }
-
-       get_symbol_props_str(r, sym, P_SELECT, "Selects: ");
+       if (hit)
+               str_append(r, "\n");
        if (sym->rev_dep.expr) {
-               expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, "Selected by [y]:\n");
-               expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, "Selected by [m]:\n");
-               expr_gstr_print_revdep(sym->rev_dep.expr, r, no, "Selected by [n]:\n");
-       }
-
-       get_symbol_props_str(r, sym, P_IMPLY, "Implies: ");
-       if (sym->implied.expr) {
-               expr_gstr_print_revdep(sym->implied.expr, r, yes, "Implied by [y]:\n");
-               expr_gstr_print_revdep(sym->implied.expr, r, mod, "Implied by [m]:\n");
-               expr_gstr_print_revdep(sym->implied.expr, r, no, "Implied by [n]:\n");
+               str_append(r, _("  Selected by: "));
+               expr_gstr_print(sym->rev_dep.expr, r);
+               str_append(r, "\n");
        }
-
        str_append(r, "\n\n");
 }
 
@@ -877,7 +676,7 @@ struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
        for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
                get_symbol_str(&res, sym, head);
        if (!i)
-               str_append(&res, "No matches found.\n");
+               str_append(&res, _("No matches found.\n"));
        return res;
 }
 
@@ -892,7 +691,7 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
                        str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
                help_text = menu_get_help(menu);
        }
-       str_printf(help, "%s\n", help_text);
+       str_printf(help, "%s\n", _(help_text));
        if (sym)
                get_symbol_str(help, sym, NULL);
 }