diff options
Diffstat (limited to 'scripts/kconfig/menu.c')
-rw-r--r-- | scripts/kconfig/menu.c | 70 |
1 files changed, 61 insertions, 9 deletions
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index 203632cc30bd..5fdf10dc1d8a 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c | |||
@@ -10,7 +10,7 @@ | |||
10 | #include "lkc.h" | 10 | #include "lkc.h" |
11 | 11 | ||
12 | static const char nohelp_text[] = N_( | 12 | static const char nohelp_text[] = N_( |
13 | "There is no help available for this kernel option.\n"); | 13 | "There is no help available for this option.\n"); |
14 | 14 | ||
15 | struct menu rootmenu; | 15 | struct menu rootmenu; |
16 | static struct menu **last_entry_ptr; | 16 | static struct menu **last_entry_ptr; |
@@ -58,6 +58,8 @@ void menu_add_entry(struct symbol *sym) | |||
58 | *last_entry_ptr = menu; | 58 | *last_entry_ptr = menu; |
59 | last_entry_ptr = &menu->next; | 59 | last_entry_ptr = &menu->next; |
60 | current_entry = menu; | 60 | current_entry = menu; |
61 | if (sym) | ||
62 | menu_add_symbol(P_SYMBOL, sym, NULL); | ||
61 | } | 63 | } |
62 | 64 | ||
63 | void menu_end_entry(void) | 65 | void menu_end_entry(void) |
@@ -136,8 +138,22 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e | |||
136 | while (isspace(*prompt)) | 138 | while (isspace(*prompt)) |
137 | prompt++; | 139 | prompt++; |
138 | } | 140 | } |
139 | if (current_entry->prompt) | 141 | if (current_entry->prompt && current_entry != &rootmenu) |
140 | prop_warn(prop, "prompt redefined"); | 142 | prop_warn(prop, "prompt redefined"); |
143 | |||
144 | /* Apply all upper menus' visibilities to actual prompts. */ | ||
145 | if(type == P_PROMPT) { | ||
146 | struct menu *menu = current_entry; | ||
147 | |||
148 | while ((menu = menu->parent) != NULL) { | ||
149 | if (!menu->visibility) | ||
150 | continue; | ||
151 | prop->visible.expr | ||
152 | = expr_alloc_and(prop->visible.expr, | ||
153 | menu->visibility); | ||
154 | } | ||
155 | } | ||
156 | |||
141 | current_entry->prompt = prop; | 157 | current_entry->prompt = prop; |
142 | } | 158 | } |
143 | prop->text = prompt; | 159 | prop->text = prompt; |
@@ -150,6 +166,12 @@ struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr | |||
150 | return menu_add_prop(type, prompt, NULL, dep); | 166 | return menu_add_prop(type, prompt, NULL, dep); |
151 | } | 167 | } |
152 | 168 | ||
169 | void menu_add_visibility(struct expr *expr) | ||
170 | { | ||
171 | current_entry->visibility = expr_alloc_and(current_entry->visibility, | ||
172 | expr); | ||
173 | } | ||
174 | |||
153 | void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) | 175 | void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) |
154 | { | 176 | { |
155 | menu_add_prop(type, NULL, expr, dep); | 177 | menu_add_prop(type, NULL, expr, dep); |
@@ -181,7 +203,7 @@ void menu_add_option(int token, char *arg) | |||
181 | } | 203 | } |
182 | } | 204 | } |
183 | 205 | ||
184 | static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2) | 206 | static int menu_validate_number(struct symbol *sym, struct symbol *sym2) |
185 | { | 207 | { |
186 | return sym2->type == S_INT || sym2->type == S_HEX || | 208 | return sym2->type == S_INT || sym2->type == S_HEX || |
187 | (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); | 209 | (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); |
@@ -199,6 +221,15 @@ static void sym_check_prop(struct symbol *sym) | |||
199 | prop_warn(prop, | 221 | prop_warn(prop, |
200 | "default for config symbol '%s'" | 222 | "default for config symbol '%s'" |
201 | " must be a single symbol", sym->name); | 223 | " must be a single symbol", sym->name); |
224 | if (prop->expr->type != E_SYMBOL) | ||
225 | break; | ||
226 | sym2 = prop_get_symbol(prop); | ||
227 | if (sym->type == S_HEX || sym->type == S_INT) { | ||
228 | if (!menu_validate_number(sym, sym2)) | ||
229 | prop_warn(prop, | ||
230 | "'%s': number is invalid", | ||
231 | sym->name); | ||
232 | } | ||
202 | break; | 233 | break; |
203 | case P_SELECT: | 234 | case P_SELECT: |
204 | sym2 = prop_get_symbol(prop); | 235 | sym2 = prop_get_symbol(prop); |
@@ -218,8 +249,8 @@ static void sym_check_prop(struct symbol *sym) | |||
218 | if (sym->type != S_INT && sym->type != S_HEX) | 249 | if (sym->type != S_INT && sym->type != S_HEX) |
219 | prop_warn(prop, "range is only allowed " | 250 | prop_warn(prop, "range is only allowed " |
220 | "for int or hex symbols"); | 251 | "for int or hex symbols"); |
221 | if (!menu_range_valid_sym(sym, prop->expr->left.sym) || | 252 | if (!menu_validate_number(sym, prop->expr->left.sym) || |
222 | !menu_range_valid_sym(sym, prop->expr->right.sym)) | 253 | !menu_validate_number(sym, prop->expr->right.sym)) |
223 | prop_warn(prop, "range is invalid"); | 254 | prop_warn(prop, "range is invalid"); |
224 | break; | 255 | break; |
225 | default: | 256 | default: |
@@ -318,6 +349,8 @@ void menu_finalize(struct menu *parent) | |||
318 | parent->next = last_menu->next; | 349 | parent->next = last_menu->next; |
319 | last_menu->next = NULL; | 350 | last_menu->next = NULL; |
320 | } | 351 | } |
352 | |||
353 | sym->dir_dep.expr = parent->dep; | ||
321 | } | 354 | } |
322 | for (menu = parent->list; menu; menu = menu->next) { | 355 | for (menu = parent->list; menu; menu = menu->next) { |
323 | if (sym && sym_is_choice(sym) && | 356 | if (sym && sym_is_choice(sym) && |
@@ -406,6 +439,11 @@ bool menu_is_visible(struct menu *menu) | |||
406 | if (!menu->prompt) | 439 | if (!menu->prompt) |
407 | return false; | 440 | return false; |
408 | 441 | ||
442 | if (menu->visibility) { | ||
443 | if (expr_calc_value(menu->visibility) == no) | ||
444 | return no; | ||
445 | } | ||
446 | |||
409 | sym = menu->sym; | 447 | sym = menu->sym; |
410 | if (sym) { | 448 | if (sym) { |
411 | sym_calc_value(sym); | 449 | sym_calc_value(sym); |
@@ -419,9 +457,13 @@ bool menu_is_visible(struct menu *menu) | |||
419 | if (!sym || sym_get_tristate_value(menu->sym) == no) | 457 | if (!sym || sym_get_tristate_value(menu->sym) == no) |
420 | return false; | 458 | return false; |
421 | 459 | ||
422 | for (child = menu->list; child; child = child->next) | 460 | for (child = menu->list; child; child = child->next) { |
423 | if (menu_is_visible(child)) | 461 | if (menu_is_visible(child)) { |
462 | if (sym) | ||
463 | sym->flags |= SYMBOL_DEF_USER; | ||
424 | return true; | 464 | return true; |
465 | } | ||
466 | } | ||
425 | 467 | ||
426 | return false; | 468 | return false; |
427 | } | 469 | } |
@@ -501,9 +543,19 @@ void get_symbol_str(struct gstr *r, struct symbol *sym) | |||
501 | bool hit; | 543 | bool hit; |
502 | struct property *prop; | 544 | struct property *prop; |
503 | 545 | ||
504 | if (sym && sym->name) | 546 | if (sym && sym->name) { |
505 | str_printf(r, "Symbol: %s [=%s]\n", sym->name, | 547 | str_printf(r, "Symbol: %s [=%s]\n", sym->name, |
506 | sym_get_string_value(sym)); | 548 | sym_get_string_value(sym)); |
549 | str_printf(r, "Type : %s\n", sym_type_name(sym->type)); | ||
550 | if (sym->type == S_INT || sym->type == S_HEX) { | ||
551 | prop = sym_get_range_prop(sym); | ||
552 | if (prop) { | ||
553 | str_printf(r, "Range : "); | ||
554 | expr_gstr_print(prop->expr, r); | ||
555 | str_append(r, "\n"); | ||
556 | } | ||
557 | } | ||
558 | } | ||
507 | for_all_prompts(sym, prop) | 559 | for_all_prompts(sym, prop) |
508 | get_prompt_str(r, prop); | 560 | get_prompt_str(r, prop); |
509 | hit = false; | 561 | hit = false; |
@@ -545,7 +597,7 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help) | |||
545 | 597 | ||
546 | if (menu_has_help(menu)) { | 598 | if (menu_has_help(menu)) { |
547 | if (sym->name) { | 599 | if (sym->name) { |
548 | str_printf(help, "CONFIG_%s:\n\n", sym->name); | 600 | str_printf(help, "%s%s:\n\n", CONFIG_, sym->name); |
549 | str_append(help, _(menu_get_help(menu))); | 601 | str_append(help, _(menu_get_help(menu))); |
550 | str_append(help, "\n"); | 602 | str_append(help, "\n"); |
551 | } | 603 | } |