Merge/rework config system per the latest from linux-2.6.0-test2.
Fix the config bugs revealed by the updated config system. -Erik
This commit is contained in:
@@ -54,9 +54,34 @@ void menu_end_menu(void)
|
||||
current_menu = current_menu->parent;
|
||||
}
|
||||
|
||||
struct expr *menu_check_dep(struct expr *e)
|
||||
{
|
||||
if (!e)
|
||||
return e;
|
||||
|
||||
switch (e->type) {
|
||||
case E_NOT:
|
||||
e->left.expr = menu_check_dep(e->left.expr);
|
||||
break;
|
||||
case E_OR:
|
||||
case E_AND:
|
||||
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 */
|
||||
if (e->left.sym == &symbol_mod)
|
||||
return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 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)
|
||||
@@ -69,56 +94,43 @@ void menu_set_type(int type)
|
||||
sym->type = type;
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "%s:%d: type of '%s' redefined from '%s' to '%s'\n",
|
||||
fprintf(stderr, "%s:%d:warning: type of '%s' redefined from '%s' to '%s'\n",
|
||||
current_entry->file->name, current_entry->lineno,
|
||||
sym->name ? sym->name : "<choice>", sym_type_name(sym->type), sym_type_name(type));
|
||||
}
|
||||
|
||||
struct property *create_prop(enum prop_type type)
|
||||
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 = malloc(sizeof(*prop));
|
||||
memset(prop, 0, sizeof(*prop));
|
||||
prop->type = type;
|
||||
prop->file = current_file;
|
||||
prop->lineno = zconf_lineno();
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
struct property *menu_add_prop(int token, char *prompt, struct symbol *def, struct expr *dep)
|
||||
{
|
||||
struct property *prop = create_prop(token);
|
||||
struct property **propp;
|
||||
|
||||
prop->sym = current_entry->sym;
|
||||
prop->menu = current_entry;
|
||||
prop->text = prompt;
|
||||
prop->def = def;
|
||||
E_EXPR(prop->visible) = dep;
|
||||
prop->expr = expr;
|
||||
prop->visible.expr = menu_check_dep(dep);
|
||||
|
||||
if (prompt)
|
||||
if (prompt) {
|
||||
if (current_entry->prompt)
|
||||
fprintf(stderr, "%s:%d: prompt redefined\n",
|
||||
current_entry->file->name, current_entry->lineno);
|
||||
current_entry->prompt = prop;
|
||||
|
||||
/* append property to the prop list of symbol */
|
||||
if (prop->sym) {
|
||||
for (propp = &prop->sym->prop; *propp; propp = &(*propp)->next)
|
||||
;
|
||||
*propp = prop;
|
||||
}
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
void menu_add_prompt(int token, char *prompt, struct expr *dep)
|
||||
void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
|
||||
{
|
||||
current_entry->prompt = menu_add_prop(token, prompt, NULL, dep);
|
||||
menu_add_prop(type, prompt, NULL, dep);
|
||||
}
|
||||
|
||||
void menu_add_default(int token, struct symbol *def, struct expr *dep)
|
||||
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
|
||||
{
|
||||
current_entry->prompt = menu_add_prop(token, NULL, def, 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, NULL, expr_alloc_symbol(sym), dep);
|
||||
}
|
||||
|
||||
void menu_finalize(struct menu *parent)
|
||||
@@ -126,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) {
|
||||
@@ -143,7 +155,7 @@ void menu_finalize(struct menu *parent)
|
||||
}
|
||||
parentdep = expr_alloc_symbol(sym);
|
||||
} else if (parent->prompt)
|
||||
parentdep = E_EXPR(parent->prompt->visible);
|
||||
parentdep = parent->prompt->visible.expr;
|
||||
else
|
||||
parentdep = parent->dep;
|
||||
|
||||
@@ -159,23 +171,28 @@ void menu_finalize(struct menu *parent)
|
||||
for (; prop; prop = prop->next) {
|
||||
if (prop->menu != menu)
|
||||
continue;
|
||||
dep = expr_transform(E_EXPR(prop->visible));
|
||||
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);
|
||||
E_EXPR(prop->visible) = 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 && parent->prompt) {
|
||||
basedep = E_EXPR(parent->prompt->visible);
|
||||
} 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 ? E_EXPR(menu->prompt->visible) : menu->dep;
|
||||
dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
|
||||
if (!expr_contains_symbol(dep, sym))
|
||||
break;
|
||||
if (expr_depends_symbol(dep, sym))
|
||||
@@ -204,14 +221,27 @@ 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;
|
||||
if (!menu->prompt)
|
||||
fprintf(stderr, "%s:%d:warning: choice value must have a prompt\n",
|
||||
menu->file->name, menu->lineno);
|
||||
for (prop = menu->sym->prop; prop; prop = prop->next) {
|
||||
if (prop->type == P_PROMPT && prop->menu != menu) {
|
||||
fprintf(stderr, "%s:%d:warning: choice values currently only support a single prompt\n",
|
||||
prop->file->name, prop->lineno);
|
||||
|
||||
}
|
||||
if (prop->type == P_DEFAULT)
|
||||
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_prop(P_CHOICE, NULL, parent->sym, NULL);
|
||||
prop = sym_get_choice_prop(parent->sym);
|
||||
//dep = expr_alloc_one(E_CHOICE, dep);
|
||||
//dep->right.sym = menu->sym;
|
||||
prop->dep = expr_alloc_one(E_CHOICE, prop->dep);
|
||||
prop->dep->right.sym = menu->sym;
|
||||
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_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) {
|
||||
@@ -224,20 +254,79 @@ void menu_finalize(struct menu *parent)
|
||||
menu->list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (sym && !(sym->flags & SYMBOL_WARNED)) {
|
||||
struct symbol *sym2;
|
||||
if (sym->type == S_UNKNOWN)
|
||||
fprintf(stderr, "%s:%d:warning: config symbol defined without type\n",
|
||||
parent->file->name, parent->lineno);
|
||||
|
||||
if (sym_is_choice(sym) && !parent->prompt)
|
||||
fprintf(stderr, "%s:%d:warning: choice must have a prompt\n",
|
||||
parent->file->name, parent->lineno);
|
||||
|
||||
for (prop = sym->prop; prop; prop = prop->next) {
|
||||
switch (prop->type) {
|
||||
case P_DEFAULT:
|
||||
if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
|
||||
prop->expr->type != E_SYMBOL)
|
||||
fprintf(stderr, "%s:%d:warning: default must be a single symbol\n",
|
||||
prop->file->name, prop->lineno);
|
||||
break;
|
||||
case P_SELECT:
|
||||
sym2 = prop_get_symbol(prop);
|
||||
if ((sym->type != S_BOOLEAN && sym->type != S_TRISTATE) ||
|
||||
(sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE))
|
||||
fprintf(stderr, "%s:%d:warning: enable is only allowed with boolean and tristate symbols\n",
|
||||
prop->file->name, prop->lineno);
|
||||
break;
|
||||
case P_RANGE:
|
||||
if (sym->type != S_INT && sym->type != S_HEX)
|
||||
fprintf(stderr, "%s:%d:warning: range is only allowed for int or hex symbols\n",
|
||||
prop->file->name, prop->lineno);
|
||||
if (!sym_string_valid(sym, prop->expr->left.sym->name) ||
|
||||
!sym_string_valid(sym, prop->expr->right.sym->name))
|
||||
fprintf(stderr, "%s:%d:warning: range is invalid\n",
|
||||
prop->file->name, prop->lineno);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
visible = E_TRI(menu->prompt->visible);
|
||||
sym = menu->sym;
|
||||
if (sym) {
|
||||
sym_calc_value(sym);
|
||||
visible = menu->prompt->visible.tri;
|
||||
} else
|
||||
visible = E_CALC(menu->prompt->visible);
|
||||
return visible != no;
|
||||
visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
|
||||
|
||||
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)
|
||||
@@ -258,10 +347,9 @@ struct menu *menu_get_parent_menu(struct menu *menu)
|
||||
{
|
||||
enum prop_type type;
|
||||
|
||||
while (menu != &rootmenu) {
|
||||
menu = menu->parent;
|
||||
for (; menu != &rootmenu; menu = menu->parent) {
|
||||
type = menu->prompt ? menu->prompt->type : 0;
|
||||
if (type == P_MENU || type == P_ROOTMENU)
|
||||
if (type == P_MENU)
|
||||
break;
|
||||
}
|
||||
return menu;
|
||||
|
Reference in New Issue
Block a user