summaryrefslogtreecommitdiff
path: root/misc/tools/kconfig-frontends/libs/parser/menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc/tools/kconfig-frontends/libs/parser/menu.c')
-rw-r--r--misc/tools/kconfig-frontends/libs/parser/menu.c77
1 files changed, 63 insertions, 14 deletions
diff --git a/misc/tools/kconfig-frontends/libs/parser/menu.c b/misc/tools/kconfig-frontends/libs/parser/menu.c
index e98a05c8e..c1d53200c 100644
--- a/misc/tools/kconfig-frontends/libs/parser/menu.c
+++ b/misc/tools/kconfig-frontends/libs/parser/menu.c
@@ -48,7 +48,7 @@ void menu_add_entry(struct symbol *sym)
{
struct menu *menu;
- menu = malloc(sizeof(*menu));
+ menu = xmalloc(sizeof(*menu));
memset(menu, 0, sizeof(*menu));
menu->sym = sym;
menu->parent = current_menu;
@@ -146,11 +146,24 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e
struct menu *menu = current_entry;
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);
+
prop->visible.expr
= expr_alloc_and(prop->visible.expr,
- menu->visibility);
+ dup_expr);
}
}
@@ -184,12 +197,15 @@ void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
void menu_add_option(int token, char *arg)
{
- struct property *prop;
-
switch (token) {
case T_OPT_MODULES:
- prop = prop_alloc(P_DEFAULT, modules_sym);
- prop->expr = expr_alloc_symbol(current_entry->sym);
+ 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)
@@ -430,6 +446,22 @@ bool menu_has_prompt(struct menu *menu)
return true;
}
+/*
+ * Determine if a menu is empty.
+ * A menu is considered empty if it contains no or only
+ * invisible entries.
+ */
+bool menu_is_empty(struct menu *menu)
+{
+ struct menu *child;
+
+ for (child = menu->list; child; child = child->next) {
+ if (menu_is_visible(child))
+ return(false);
+ }
+ return(true);
+}
+
bool menu_is_visible(struct menu *menu)
{
struct menu *child;
@@ -515,13 +547,6 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
struct jump_key *jump;
str_printf(r, _("Prompt: %s\n"), _(prop->text));
- 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");
- }
menu = prop->menu->parent;
for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
bool accessible = menu_is_visible(menu);
@@ -531,7 +556,7 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
location = menu;
}
if (head && location) {
- jump = malloc(sizeof(struct jump_key));
+ jump = xmalloc(sizeof(struct jump_key));
if (menu_is_visible(prop->menu)) {
/*
@@ -572,6 +597,18 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
}
/*
+ * get peoperty of type P_SYMBOL
+ */
+static struct property *get_symbol_prop(struct symbol *sym)
+{
+ struct property *prop = NULL;
+
+ for_all_properties(sym, prop, P_SYMBOL)
+ break;
+ return prop;
+}
+
+/*
* head is optional and may be NULL
*/
void get_symbol_str(struct gstr *r, struct symbol *sym,
@@ -595,6 +632,18 @@ void get_symbol_str(struct gstr *r, struct symbol *sym,
}
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");
+ }
+ }
+
hit = false;
for_all_properties(sym, prop, P_SELECT) {
if (!hit) {