diff options
author | Roman Zippel <zippel@linux-m68k.org> | 2003-06-02 03:25:03 -0700 |
---|---|---|
committer | Ben Collins <bcollins@debian.org> | 2003-06-02 03:25:03 -0700 |
commit | f3b837df9e2bb0225b26cd295225fd133207654e (patch) | |
tree | 77109c0d34a84fcb4319841b6303d4e46271f566 /scripts | |
parent | 386ebbf28c019d16a08090df495de797ed4a499a (diff) | |
download | history-f3b837df9e2bb0225b26cd295225fd133207654e.tar.gz |
[PATCH] reverse dependency support
The 'select' keyword defines a lower limit for symbols and allows to
select other symbols when a symbol is selected, e.g.:
config JOLIET
bool "Microsoft Joliet CDROM extensions"
select NLS
This means when JOLIET is selected, NLS will be selected as well.
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/kconfig/expr.c | 28 | ||||
-rw-r--r-- | scripts/kconfig/expr.h | 4 | ||||
-rw-r--r-- | scripts/kconfig/menu.c | 51 | ||||
-rw-r--r-- | scripts/kconfig/symbol.c | 96 | ||||
-rw-r--r-- | scripts/kconfig/zconf.tab.c_shipped | 1 | ||||
-rw-r--r-- | scripts/kconfig/zconf.y | 1 |
6 files changed, 113 insertions, 68 deletions
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c index 451b8dce0b3d0..33a9e0819f87c 100644 --- a/scripts/kconfig/expr.c +++ b/scripts/kconfig/expr.c @@ -55,6 +55,13 @@ struct expr *expr_alloc_and(struct expr *e1, struct expr *e2) return e2 ? expr_alloc_two(E_AND, e1, e2) : e1; } +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2) +{ + if (!e1) + return e2; + return e2 ? expr_alloc_two(E_OR, e1, e2) : e1; +} + struct expr *expr_copy(struct expr *org) { struct expr *e; @@ -158,9 +165,22 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) { - if (!e1 || !e2 || e1->type != e2->type) + if (!e1 || !e2) return; - __expr_eliminate_eq(e1->type, ep1, ep2); + switch (e1->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e1->type, ep1, ep2); + default: + ; + } + if (e1->type != e2->type) switch (e2->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e2->type, ep1, ep2); + default: + ; + } e1 = expr_eliminate_yn(e1); e2 = expr_eliminate_yn(e2); } @@ -1017,11 +1037,11 @@ void expr_print(struct expr *e, void (*fn)(void *, const char *), void *data, in expr_print(e->right.expr, fn, data, E_AND); break; case E_CHOICE: + fn(data, e->right.sym->name); if (e->left.expr) { - expr_print(e->left.expr, fn, data, E_CHOICE); fn(data, " ^ "); + expr_print(e->left.expr, fn, data, E_CHOICE); } - fn(data, e->right.sym->name); break; default: { diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h index 47d65ea2562a5..f1fa5d83956b2 100644 --- a/scripts/kconfig/expr.h +++ b/scripts/kconfig/expr.h @@ -73,6 +73,7 @@ struct symbol { int flags; struct property *prop; struct expr *dep, *dep2; + struct expr_value rev_dep; }; #define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) @@ -97,7 +98,7 @@ struct symbol { #define SYMBOL_HASHMASK 0xff enum prop_type { - P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE + P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE, P_SELECT }; struct property { @@ -152,6 +153,7 @@ struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2); struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); struct expr *expr_copy(struct expr *org); void expr_free(struct expr *e); int expr_eq(struct expr *e1, struct expr *e2); diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index a1e14d7510d57..53075dc5371f2 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -138,7 +138,7 @@ void menu_finalize(struct menu *parent) struct menu *menu, *last_menu; struct symbol *sym; struct property *prop; - struct expr *parentdep, *basedep, *dep, *dep2; + struct expr *parentdep, *basedep, *dep, *dep2, **ep; sym = parent->sym; if (parent->list) { @@ -177,6 +177,11 @@ void menu_finalize(struct menu *parent) 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) @@ -216,12 +221,20 @@ void menu_finalize(struct menu *parent) for (menu = parent->list; menu; menu = menu->next) { if (sym && sym_is_choice(sym) && menu->sym) { menu->sym->flags |= SYMBOL_CHOICEVAL; + for (prop = menu->sym->prop; prop; prop = prop->next) { + if (prop->type != P_DEFAULT) + continue; + fprintf(stderr, "%s:%d:warning: defaults for choice values not supported\n", + prop->file->name, prop->lineno); + } current_entry = menu; menu_set_type(sym->type); menu_add_symbol(P_CHOICE, sym, NULL); prop = sym_get_choice_prop(sym); - prop->expr = expr_alloc_one(E_CHOICE, prop->expr); - prop->expr->right.sym = menu->sym; + for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) + ; + *ep = expr_alloc_one(E_CHOICE, NULL); + (*ep)->right.sym = menu->sym; } if (menu->list && (!menu->prompt || !menu->prompt->text)) { for (last_menu = menu->list; ; last_menu = last_menu->next) { @@ -234,20 +247,46 @@ void menu_finalize(struct menu *parent) menu->list = NULL; } } + + 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))); + } } bool menu_is_visible(struct menu *menu) { + struct menu *child; + struct symbol *sym; tristate visible; if (!menu->prompt) return false; - if (menu->sym) { - sym_calc_value(menu->sym); + sym = menu->sym; + if (sym) { + sym_calc_value(sym); visible = menu->prompt->visible.tri; } else visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr); - return visible != no; + + if (sym && sym_is_choice(sym)) { + for (child = menu->list; child; child = child->next) + if (menu_is_visible(child)) + break; + if (!child) + return false; + } + + if (visible != no) + return true; + if (!sym || sym_get_tristate_value(menu->sym) == no) + return false; + + for (child = menu->list; child; child = child->next) + if (menu_is_visible(child)) + return true; + return false; } const char *menu_get_prompt(struct menu *menu) diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 0aa5d29679278..59e8143759b29 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -133,17 +133,25 @@ struct property *sym_get_default_prop(struct symbol *sym) static void sym_calc_visibility(struct symbol *sym) { struct property *prop; - tristate visible, oldvisible; + tristate tri; /* any prompt visible? */ - oldvisible = sym->visible; - visible = no; + tri = no; for_all_prompts(sym, prop) { prop->visible.tri = expr_calc_value(prop->visible.expr); - visible = E_OR(visible, prop->visible.tri); + tri = E_OR(tri, prop->visible.tri); } - if (oldvisible != visible) { - sym->visible = visible; + if (sym->visible != tri) { + sym->visible = tri; + sym_set_changed(sym); + } + if (sym_is_choice_value(sym)) + return; + tri = no; + if (sym->rev_dep.expr) + tri = expr_calc_value(sym->rev_dep.expr); + if (sym->rev_dep.tri != tri) { + sym->rev_dep.tri = tri; sym_set_changed(sym); } } @@ -195,6 +203,7 @@ void sym_calc_value(struct symbol *sym) if (sym->flags & SYMBOL_VALID) return; + sym->flags |= SYMBOL_VALID; oldval = sym->curr; @@ -209,11 +218,10 @@ void sym_calc_value(struct symbol *sym) newval = symbol_no.curr; break; default: - newval.val = sym->name; - newval.tri = no; - goto out; + sym->curr.val = sym->name; + sym->curr.tri = no; + return; } - sym->flags |= SYMBOL_VALID; if (!sym_is_choice_value(sym)) sym->flags &= ~SYMBOL_WRITE; @@ -228,7 +236,7 @@ void sym_calc_value(struct symbol *sym) if (sym_is_choice_value(sym) && sym->visible == yes) { prop = sym_get_choice_prop(sym); newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; - } else if (sym->visible != no) { + } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) { sym->flags |= SYMBOL_WRITE; if (sym_has_value(sym)) newval.tri = sym->user.tri; @@ -237,11 +245,7 @@ void sym_calc_value(struct symbol *sym) if (prop) newval.tri = expr_calc_value(prop->expr); } - newval.tri = E_AND(newval.tri, sym->visible); - /* if the symbol is visible and not optionial, - * possibly ignore old user choice. */ - if (!sym_is_optional(sym) && newval.tri == no) - newval.tri = sym->visible; + newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri); } else if (!sym_is_choice(sym)) { prop = sym_get_default_prop(sym); if (prop) { @@ -249,6 +253,12 @@ void sym_calc_value(struct symbol *sym) newval.tri = expr_calc_value(prop->expr); } } + if (sym_get_type(sym) == S_BOOLEAN) { + if (newval.tri == mod) + newval.tri = yes; + if (sym->rev_dep.tri == mod) + sym->rev_dep.tri = yes; + } break; case S_STRING: case S_HEX: @@ -274,23 +284,6 @@ void sym_calc_value(struct symbol *sym) ; } - switch (sym_get_type(sym)) { - case S_TRISTATE: - if (newval.tri != mod) - break; - sym_calc_value(modules_sym); - if (modules_sym->curr.tri == no) - newval.tri = yes; - break; - case S_BOOLEAN: - if (newval.tri == mod) - newval.tri = yes; - break; - default: - break; - } - -out: sym->curr = newval; if (sym_is_choice(sym) && newval.tri == yes) sym->curr.val = sym_calc_choice(sym); @@ -349,19 +342,13 @@ bool sym_tristate_within_range(struct symbol *sym, tristate val) if (type != S_BOOLEAN && type != S_TRISTATE) return false; - switch (val) { - case no: - if (sym_is_choice_value(sym) && sym->visible == yes) - return false; - return sym_is_optional(sym); - case mod: - if (sym_is_choice_value(sym) && sym->visible == yes) - return false; - return type == S_TRISTATE; - case yes: - return type == S_BOOLEAN || sym->visible == yes; - } - return false; + if (type == S_BOOLEAN && val == mod) + return false; + if (sym->visible <= sym->rev_dep.tri) + return false; + if (sym_is_choice_value(sym) && sym->visible == yes) + return val == yes; + return val >= sym->rev_dep.tri && val <= sym->visible; } bool sym_set_tristate_value(struct symbol *sym, tristate val) @@ -534,15 +521,7 @@ const char *sym_get_string_value(struct symbol *sym) bool sym_is_changable(struct symbol *sym) { - if (sym->visible == no) - return false; - /* at least 'n' and 'y'/'m' is selectable */ - if (sym_is_optional(sym)) - return true; - /* no 'n', so 'y' and 'm' must be selectable */ - if (sym_get_type(sym) == S_TRISTATE && sym->visible == yes) - return true; - return false; + return sym->visible > sym->rev_dep.tri; } struct symbol *sym_lookup(const char *name, int isconst) @@ -663,7 +642,10 @@ const char *prop_get_type_name(enum prop_type type) return "default"; case P_CHOICE: return "choice"; - default: - return "unknown"; + case P_SELECT: + return "select"; + case P_UNKNOWN: + break; } + return "unknown"; } diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped index f5cdb44e1e12a..36ee30543d1ee 100644 --- a/scripts/kconfig/zconf.tab.c_shipped +++ b/scripts/kconfig/zconf.tab.c_shipped @@ -1406,6 +1406,7 @@ yyreduce: case 36: { + menu_add_symbol(P_SELECT, sym_lookup(yyvsp[-2].string, 0), yyvsp[-1].expr); printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); ;} break; diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y index 342dd688ebd45..7b730cea92f3d 100644 --- a/scripts/kconfig/zconf.y +++ b/scripts/kconfig/zconf.y @@ -215,6 +215,7 @@ config_option: T_DEFAULT expr if_expr T_EOL config_option: T_SELECT T_WORD if_expr T_EOL { + menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3); printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); }; |