static void check_conf(struct menu *menu) { struct symbol *sym; struct menu *child; if (!menu_is_visible(menu)) return; sym = menu->sym; if (sym && !sym_has_value(sym)) { if (sym_is_changable(sym) || (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { if (input_mode == listnewconfig) { if (sym->name && !sym_is_choice_value(sym)) { printf("%s%s\n", CONFIG_, sym->name); } } else if (input_mode != oldnoconfig) { if (!conf_cnt++) printf(_("*\n* Restart config...\n*\n")); rootEntry = menu_get_parent_menu(menu); conf(rootEntry); } } } for (child = menu->list; child; child = child->next) check_conf(child); }
static void check_conf(struct menu *menu) { struct symbol *sym; struct menu *child; if (!menu_is_visible(menu)) return; sym = menu->sym; if (sym && !sym_has_value(sym)) { if (sym_is_changable(sym) || (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { if (input_mode == dont_ask || input_mode == dont_ask_dont_tell) { if (input_mode == dont_ask && sym->name && !sym_is_choice_value(sym)) { fprintf(stderr,"CONFIG_%s\n",sym->name); ++return_value; } } else { if (!conf_cnt++) printf(_("*\n* Restart config...\n*\n")); rootEntry = menu_get_parent_menu(menu); conf(rootEntry); } } } for (child = menu->list; child; child = child->next) check_conf(child); }
enum symbol_type sym_get_type(struct symbol *sym) { enum symbol_type type = sym->type; if (type == S_TRISTATE) { if (sym_is_choice_value(sym) && sym->visible == yes) type = S_BOOLEAN; else if (modules_val == no) type = S_BOOLEAN; } return type; }
enum symbol_type sym_get_type(struct symbol *sym) { enum symbol_type type = sym->type; if (type == S_TRISTATE) { if (sym_is_choice_value(sym) && sym->visible == yes) type = S_BOOLEAN; /* tristate always enabled */ #if 0 else if (modules_val == no) type = S_BOOLEAN; #endif } return type; }
static void report_conf(struct menu *menu, bool verbose) { struct symbol *sym; struct menu *child; if (!menu_is_visible(menu)) return; if (verbose && menu == &rootmenu) { printf("\n#\n" "# Changes:\n" "#\n"); } sym = menu->sym; if (sym && (sym->flags & SYMBOL_NEW) && sym_is_changable(sym) && sym->name && !sym_is_choice_value(sym)) { conf_write_new_symbol(stdout, sym, verbose); } for (child = menu->list; child; child = child->next) report_conf(child, verbose); }
void menu_finalize(struct menu *parent) { struct menu *menu, *last_menu; struct symbol *sym; struct property *prop; struct expr *parentdep, *basedep, *dep, *dep2, **ep; sym = parent->sym; if (parent->list) { if (sym && sym_is_choice(sym)) { if (sym->type == S_UNKNOWN) { /* find the first choice value to find out choice type */ current_entry = parent; for (menu = parent->list; menu; menu = menu->next) { if (menu->sym && menu->sym->type != S_UNKNOWN) { menu_set_type(menu->sym->type); break; } } } if (parent->prompt && !expr_is_yes(parent->prompt->visible.expr)) { parent->visibility = expr_alloc_and (parent->visibility, parent->prompt->visible.expr); } /* set the type of the remaining choice values */ for (menu = parent->list; menu; menu = menu->next) { current_entry = menu; if (menu->sym && menu->sym->type == S_UNKNOWN) menu_set_type(sym->type); } parentdep = expr_alloc_symbol(sym); } else if (parent->prompt) parentdep = parent->prompt->visible.expr; else parentdep = parent->dep; for (menu = parent->list; menu; menu = menu->next) { basedep = expr_transform(menu->dep); basedep = expr_alloc_and(expr_copy(parentdep), basedep); basedep = expr_eliminate_dups(basedep); menu->dep = basedep; if (menu->sym) prop = menu->sym->prop; else prop = menu->prompt; for (; prop; prop = prop->next) { if (prop->menu != menu) continue; 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; 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))); } } } for (menu = parent->list; menu; menu = menu->next) menu_finalize(menu); } else if (sym) { basedep = parent->prompt ? parent->prompt->visible.expr : NULL; basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); basedep = expr_eliminate_dups(expr_transform(basedep)); 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)) break; if (expr_depends_symbol(dep, sym)) goto next; 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)) { expr_free(dep2); break; } expr_free(dep2); next: menu_finalize(menu); menu->parent = parent; last_menu = menu; } if (last_menu) { parent->list = parent->next; parent->next = last_menu->next; last_menu->next = NULL; } sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep); } for (menu = parent->list; menu; menu = menu->next) { if (sym && sym_is_choice(sym) && menu->sym && !sym_is_choice_value(menu->sym)) { current_entry = menu; menu->sym->flags |= SYMBOL_CHOICEVAL; if (!menu->prompt) menu_warn(menu, "choice value must have a prompt"); for (prop = menu->sym->prop; prop; prop = prop->next) { if (prop->type == P_DEFAULT) prop_warn(prop, "defaults for choice " "values not supported"); if (prop->menu == menu) continue; if (prop->type == P_PROMPT && prop->menu->parent->sym != sym) prop_warn(prop, "choice value used outside its choice group"); } /* Non-tristate choice values of tristate choices must * depend on the choice being set to Y. The choice * values' dependencies were propagated to their * properties above, so the change here must be re- * propagated. */ if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); menu->dep = expr_alloc_and(basedep, menu->dep); for (prop = menu->sym->prop; prop; prop = prop->next) { if (prop->menu != menu) continue; prop->visible.expr = expr_alloc_and(expr_copy(basedep), prop->visible.expr); } } menu_add_symbol(P_CHOICE, sym, NULL); prop = sym_get_choice_prop(sym); for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) ; *ep = expr_alloc_one(E_LIST, NULL); (*ep)->right.sym = menu->sym; } if (menu->list && (!menu->prompt || !menu->prompt->text)) { for (last_menu = menu->list; ; last_menu = last_menu->next) { last_menu->parent = parent; if (!last_menu->next) break; } last_menu->next = menu->next; menu->next = menu->list; menu->list = NULL; } } if (sym && !(sym->flags & SYMBOL_WARNED)) { if (sym->type == S_UNKNOWN) menu_warn(parent, "config symbol defined without type"); if (sym_is_choice(sym) && !parent->prompt) menu_warn(parent, "choice must have a prompt"); /* Check properties connected to this symbol */ sym_check_prop(sym); sym->flags |= SYMBOL_WARNED; } 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, expr_alloc_symbol(&symbol_mod))); } }
static void build_conf(struct menu *menu) { struct symbol *sym; struct property *prop; struct menu *child; int type, tmp, doint = 2; tristate val; char ch; if (!menu_is_visible(menu)) return; sym = menu->sym; prop = menu->prompt; if (!sym) { if (prop && menu != current_menu) { const char *prompt = menu_get_prompt(menu); switch (prop->type) { case P_MENU: child_count++; prompt = _(prompt); if (single_menu_mode) { item_make("%s%*c%s", menu->data ? "-->" : "++>", indent + 1, ' ', prompt); } else item_make(" %*c%s --->", indent + 1, ' ', prompt); item_set_tag('m'); item_set_data(menu); if (single_menu_mode && menu->data) goto conf_childs; return; case P_COMMENT: if (prompt) { child_count++; item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt)); item_set_tag(':'); item_set_data(menu); } break; default: if (prompt) { child_count++; item_make("---%*c%s", indent + 1, ' ', _(prompt)); item_set_tag(':'); item_set_data(menu); } } } else doint = 0; goto conf_childs; } type = sym_get_type(sym); if (sym_is_choice(sym)) { struct symbol *def_sym = sym_get_choice_value(sym); struct menu *def_menu = NULL; child_count++; for (child = menu->list; child; child = child->next) { if (menu_is_visible(child) && child->sym == def_sym) def_menu = child; } val = sym_get_tristate_value(sym); if (sym_is_changable(sym)) { switch (type) { case S_BOOLEAN: item_make("[%c]", val == no ? ' ' : '*'); break; case S_TRISTATE: switch (val) { case yes: ch = '*'; break; case mod: ch = 'M'; break; default: ch = ' '; break; } item_make("<%c>", ch); break; } item_set_tag('t'); item_set_data(menu); } else { item_make(" "); item_set_tag(def_menu ? 't' : ':'); item_set_data(menu); } item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); if (val == yes) { if (def_menu) { item_add_str(" (%s)", _(menu_get_prompt(def_menu))); item_add_str(" --->"); if (def_menu->list) { indent += 2; build_conf(def_menu); indent -= 2; } } return; } } else { if (menu == current_menu) { item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); item_set_tag(':'); item_set_data(menu); goto conf_childs; } child_count++; val = sym_get_tristate_value(sym); if (sym_is_choice_value(sym) && val == yes) { item_make(" "); item_set_tag(':'); item_set_data(menu); } else { switch (type) { case S_BOOLEAN: if (sym_is_changable(sym)) item_make("[%c]", val == no ? ' ' : '*'); else item_make("-%c-", val == no ? ' ' : '*'); item_set_tag('t'); item_set_data(menu); break; case S_TRISTATE: switch (val) { case yes: ch = '*'; break; case mod: ch = 'M'; break; default: ch = ' '; break; } if (sym_is_changable(sym)) { if (sym->rev_dep.tri == mod) item_make("{%c}", ch); else item_make("<%c>", ch); } else item_make("-%c-", ch); item_set_tag('t'); item_set_data(menu); break; default: tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */ item_make("(%s)", sym_get_string_value(sym)); tmp = indent - tmp + 4; if (tmp < 0) tmp = 0; item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)), (sym_has_value(sym) || !sym_is_changable(sym)) ? "" : _(" (NEW)")); item_set_tag('s'); item_set_data(menu); goto conf_childs; } } item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)), (sym_has_value(sym) || !sym_is_changable(sym)) ? "" : _(" (NEW)")); if (menu->prompt->type == P_MENU) { item_add_str(" --->"); return; } } conf_childs: indent += doint; for (child = menu->list; child; child = child->next) build_conf(child); indent -= doint; }
static void build_conf(struct menu *menu) { struct symbol *sym; struct property *prop; struct menu *child; int type, tmp, doint = 2; tristate val; char ch; if (!menu_is_visible(menu)) return; sym = menu->sym; prop = menu->prompt; if (!sym) { if (prop && menu != current_menu) { const char *prompt = menu_get_prompt(menu); switch (prop->type) { case P_MENU: child_count++; cmake(); cprint_tag("m%p", menu); if (single_menu_mode) { cprint_name("%s%*c%s", menu->data ? "-->" : "++>", indent + 1, ' ', prompt); } else { cprint_name(" %*c%s --->", indent + 1, ' ', prompt); } if (single_menu_mode && menu->data) goto conf_childs; return; default: if (prompt) { child_count++; cmake(); cprint_tag(":%p", menu); cprint_name("---%*c%s", indent + 1, ' ', prompt); } } } else doint = 0; goto conf_childs; } cmake(); type = sym_get_type(sym); if (sym_is_choice(sym)) { struct symbol *def_sym = sym_get_choice_value(sym); struct menu *def_menu = NULL; child_count++; for (child = menu->list; child; child = child->next) { if (menu_is_visible(child) && child->sym == def_sym) def_menu = child; } val = sym_get_tristate_value(sym); if (sym_is_changable(sym)) { cprint_tag("t%p", menu); switch (type) { case S_BOOLEAN: cprint_name("[%c]", val == no ? ' ' : '*'); break; case S_TRISTATE: switch (val) { case yes: ch = '*'; break; case mod: ch = 'M'; break; default: ch = ' '; break; } cprint_name("<%c>", ch); break; } } else { cprint_tag("%c%p", def_menu ? 't' : ':', menu); cprint_name(" "); } cprint_name("%*c%s", indent + 1, ' ', menu_get_prompt(menu)); if (val == yes) { if (def_menu) { cprint_name(" (%s)", menu_get_prompt(def_menu)); cprint_name(" --->"); if (def_menu->list) { indent += 2; build_conf(def_menu); indent -= 2; } } return; } } else { if (menu == current_menu) { cprint_tag(":%p", menu); cprint_name("---%*c%s", indent + 1, ' ', menu_get_prompt(menu)); goto conf_childs; } child_count++; val = sym_get_tristate_value(sym); if (sym_is_choice_value(sym) && val == yes) { cprint_tag(":%p", menu); cprint_name(" "); } else { switch (type) { case S_BOOLEAN: cprint_tag("t%p", menu); if (sym_is_changable(sym)) cprint_name("[%c]", val == no ? ' ' : '*'); else cprint_name("---"); break; case S_TRISTATE: cprint_tag("t%p", menu); switch (val) { case yes: ch = '*'; break; case mod: ch = 'M'; break; default: ch = ' '; break; } if (sym_is_changable(sym)) cprint_name("<%c>", ch); else cprint_name("---"); break; default: cprint_tag("s%p", menu); tmp = cprint_name("(%s)", sym_get_string_value(sym)); tmp = indent - tmp + 4; if (tmp < 0) tmp = 0; cprint_name("%*c%s%s", tmp, ' ', menu_get_prompt(menu), (sym_has_value(sym) || !sym_is_changable(sym)) ? "" : " (NEW)"); goto conf_childs; } } cprint_name("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu), (sym_has_value(sym) || !sym_is_changable(sym)) ? "" : " (NEW)"); if (menu->prompt->type == P_MENU) { cprint_name(" --->"); return; } } conf_childs: indent += doint; for (child = menu->list; child; child = child->next) build_conf(child); indent -= doint; }
void menu_finalize(struct menu *parent) { struct menu *menu, *last_menu; struct symbol *sym; struct property *prop; struct expr *parentdep, *basedep, *dep, *dep2, **ep; 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 */ current_entry = parent; for (menu = parent->list; menu; menu = menu->next) { if (menu->sym && menu->sym->type != S_UNKNOWN) { menu_set_type(menu->sym->type); break; } } } /* set the type of the remaining choice values */ for (menu = parent->list; menu; menu = menu->next) { current_entry = menu; 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 if (parent->prompt) /* Menu node for 'menu' */ parentdep = parent->prompt->visible.expr; else /* Menu node for 'if' */ 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_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_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; last_menu->next = NULL; } sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep); } for (menu = parent->list; menu; menu = menu->next) { if (sym && sym_is_choice(sym) && menu->sym && !sym_is_choice_value(menu->sym)) { current_entry = menu; menu->sym->flags |= SYMBOL_CHOICEVAL; if (!menu->prompt) menu_warn(menu, "choice value must have a prompt"); for (prop = menu->sym->prop; prop; prop = prop->next) { if (prop->type == P_DEFAULT) prop_warn(prop, "defaults for choice " "values not supported"); if (prop->menu == menu) continue; if (prop->type == P_PROMPT && prop->menu->parent->sym != sym) prop_warn(prop, "choice value used outside its choice group"); } /* Non-tristate choice values of tristate choices must * depend on the choice being set to Y. The choice * values' dependencies were propagated to their * properties above, so the change here must be re- * propagated. */ if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); menu->dep = expr_alloc_and(basedep, menu->dep); for (prop = menu->sym->prop; prop; prop = prop->next) { if (prop->menu != menu) continue; prop->visible.expr = expr_alloc_and(expr_copy(basedep), prop->visible.expr); } } menu_add_symbol(P_CHOICE, sym, NULL); prop = sym_get_choice_prop(sym); for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) ; *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; if (!last_menu->next) break; } last_menu->next = menu->next; menu->next = menu->list; menu->list = NULL; } } if (sym && !(sym->flags & SYMBOL_WARNED)) { if (sym->type == S_UNKNOWN) menu_warn(parent, "config symbol defined without type"); if (sym_is_choice(sym) && !parent->prompt) menu_warn(parent, "choice must have a prompt"); /* Check properties connected to this symbol */ sym_check_prop(sym); 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, expr_alloc_symbol(&symbol_mod))); } }