aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorRoman Zippel <zippel@linux-m68k.org>2003-06-02 03:25:03 -0700
committerBen Collins <bcollins@debian.org>2003-06-02 03:25:03 -0700
commitf3b837df9e2bb0225b26cd295225fd133207654e (patch)
tree77109c0d34a84fcb4319841b6303d4e46271f566 /scripts
parent386ebbf28c019d16a08090df495de797ed4a499a (diff)
downloadhistory-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.c28
-rw-r--r--scripts/kconfig/expr.h4
-rw-r--r--scripts/kconfig/menu.c51
-rw-r--r--scripts/kconfig/symbol.c96
-rw-r--r--scripts/kconfig/zconf.tab.c_shipped1
-rw-r--r--scripts/kconfig/zconf.y1
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());
};