diff options
Diffstat (limited to 'config/menu.c')
-rw-r--r-- | config/menu.c | 171 |
1 files changed, 94 insertions, 77 deletions
diff --git a/config/menu.c b/config/menu.c index f6e6200ce..07ff8d105 100644 --- a/config/menu.c +++ b/config/menu.c @@ -10,13 +10,12 @@ #include "lkc.h" struct menu rootmenu; -struct menu *current_menu, *current_entry; static struct menu **last_entry_ptr; struct file *file_list; struct file *current_file; -static void menu_warn(struct menu *menu, const char *fmt, ...) +void menu_warn(struct menu *menu, const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -62,10 +61,11 @@ void menu_end_entry(void) { } -void menu_add_menu(void) +struct menu *menu_add_menu(void) { - current_menu = current_entry; + menu_end_entry(); last_entry_ptr = ¤t_entry->list; + return current_menu = current_entry; } void menu_end_menu(void) @@ -114,7 +114,7 @@ void menu_set_type(int type) sym->type = type; return; } - menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'\n", + menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'", sym->name ? sym->name : "<choice>", sym_type_name(sym->type), sym_type_name(type)); } @@ -124,22 +124,27 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e struct property *prop = prop_alloc(type, current_entry->sym); prop->menu = current_entry; - prop->text = prompt; prop->expr = expr; prop->visible.expr = menu_check_dep(dep); if (prompt) { + if (isspace(*prompt)) { + prop_warn(prop, "leading whitespace ignored"); + while (isspace(*prompt)) + prompt++; + } if (current_entry->prompt) - menu_warn(current_entry, "prompt redefined\n"); + prop_warn(prop, "prompt redefined"); current_entry->prompt = prop; } + prop->text = prompt; return prop; } -void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) { - menu_add_prop(type, prompt, NULL, dep); + return menu_add_prop(type, prompt, NULL, dep); } void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) @@ -152,6 +157,33 @@ 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_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); + break; + case T_OPT_DEFCONFIG_LIST: + if (!sym_defconfig_list) + sym_defconfig_list = current_entry->sym; + else if (sym_defconfig_list != current_entry->sym) + zconf_error("trying to redefine defconfig symbol"); + break; + case T_OPT_ENV: + prop_add_env(arg); + break; + } +} + +static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2) +{ + return sym2->type == S_INT || sym2->type == S_HEX || + (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); +} + void sym_check_prop(struct symbol *sym) { struct property *prop; @@ -166,18 +198,14 @@ void sym_check_prop(struct symbol *sym) " must be a single symbol", sym->name); break; case P_SELECT: - case P_SELECTNOT: sym2 = prop_get_symbol(prop); if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) prop_warn(prop, "config symbol '%s' uses select, but is " "not boolean or tristate", sym->name); - else if (sym2->type == S_UNKNOWN) - prop_warn(prop, - "'select' used by config symbol '%s' " - "refer to undefined symbol '%s'", - sym->name, sym2->name); - else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE) + else if (sym2->type != S_UNKNOWN && + sym2->type != S_BOOLEAN && + sym2->type != S_TRISTATE) prop_warn(prop, "'%s' has wrong type. 'select' only " "accept arguments of boolean and " @@ -187,8 +215,8 @@ void sym_check_prop(struct symbol *sym) if (sym->type != S_INT && sym->type != S_HEX) prop_warn(prop, "range is only allowed " "for int or hex symbols"); - if (!sym_string_valid(sym, prop->expr->left.sym->name) || - !sym_string_valid(sym, prop->expr->right.sym->name)) + if (!menu_range_valid_sym(sym, prop->expr->left.sym) || + !menu_range_valid_sym(sym, prop->expr->right.sym)) prop_warn(prop, "range is invalid"); break; default: @@ -207,15 +235,21 @@ void menu_finalize(struct menu *parent) sym = parent->sym; if (parent->list) { if (sym && sym_is_choice(sym)) { - /* find the first choice value and find out choice type */ + 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) { - if (menu->sym) { - current_entry = parent; - menu_set_type(menu->sym->type); - current_entry = menu; + current_entry = menu; + if (menu->sym && menu->sym->type == S_UNKNOWN) menu_set_type(sym->type); - break; - } } parentdep = expr_alloc_symbol(sym); } else if (parent->prompt) @@ -245,10 +279,6 @@ void menu_finalize(struct menu *parent) 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_SELECTNOT) { - struct symbol *es = prop_get_symbol(prop); - es->rev_dep_inv.expr = expr_alloc_or(es->rev_dep_inv.expr, - expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); } } } @@ -287,27 +317,43 @@ void menu_finalize(struct menu *parent) } } for (menu = parent->list; menu; menu = menu->next) { - if (sym && sym_is_choice(sym) && menu->sym) { + 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_PROMPT && prop->menu != menu) { - prop_warn(prop, "choice values " - "currently only support a " - "single prompt"); - } if (prop->type == P_DEFAULT) prop_warn(prop, "defaults for choice " - "values not supported"); + "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); + } } - current_entry = menu; - menu_set_type(sym->type); 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 = expr_alloc_one(E_LIST, NULL); (*ep)->right.sym = menu->sym; } if (menu->list && (!menu->prompt || !menu->prompt->text)) { @@ -324,11 +370,10 @@ void menu_finalize(struct menu *parent) if (sym && !(sym->flags & SYMBOL_WARNED)) { if (sym->type == S_UNKNOWN) - menu_warn(parent, "config symbol defined " - "without type\n"); + menu_warn(parent, "config symbol defined without type"); if (sym_is_choice(sym) && !parent->prompt) - menu_warn(parent, "choice must have a prompt\n"); + menu_warn(parent, "choice must have a prompt"); /* Check properties connected to this symbol */ sym_check_prop(sym); @@ -394,43 +439,15 @@ struct menu *menu_get_parent_menu(struct menu *menu) return menu; } -struct file *file_lookup(const char *name) +bool menu_has_help(struct menu *menu) { - struct file *file; - - for (file = file_list; file; file = file->next) { - if (!strcmp(name, file->name)) - return file; - } - - file = malloc(sizeof(*file)); - memset(file, 0, sizeof(*file)); - file->name = strdup(name); - file->next = file_list; - file_list = file; - return file; + return menu->help != NULL; } -int file_write_dep(const char *name) +const char *menu_get_help(struct menu *menu) { - struct file *file; - FILE *out; - - if (!name) - name = ".config.cmd"; - out = fopen(".config.tmp", "w"); - if (!out) - return 1; - fprintf(out, "deps_config := \\\n"); - for (file = file_list; file; file = file->next) { - if (file->next) - fprintf(out, "\t%s \\\n", file->name); - else - fprintf(out, "\t%s\n", file->name); - } - fprintf(out, "\n.config include/config.h: $(deps_config)\n\n$(deps_config):\n"); - fclose(out); - rename(".config.tmp", name); - return 0; + if (menu->help) + return menu->help; + else + return ""; } - |