diff options
Diffstat (limited to 'scripts/config/menu.c')
-rw-r--r-- | scripts/config/menu.c | 451 |
1 files changed, 125 insertions, 326 deletions
diff --git a/scripts/config/menu.c b/scripts/config/menu.c index 1df87dd3a5..3d89dc178d 100644 --- a/scripts/config/menu.c +++ b/scripts/config/menu.c @@ -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 = ¤t_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 = ¤t_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); } |