1.1 --- a/kconfig/menu.c Thu Nov 13 17:55:16 2008 +0000
1.2 +++ b/kconfig/menu.c Sun May 08 14:14:40 2011 +0200
1.3 @@ -9,6 +9,9 @@
1.4 #define LKC_DIRECT_LINK
1.5 #include "lkc.h"
1.6
1.7 +static const char nohelp_text[] = N_(
1.8 + "There is no help available for this option.\n");
1.9 +
1.10 struct menu rootmenu;
1.11 static struct menu **last_entry_ptr;
1.12
1.13 @@ -35,7 +38,7 @@
1.14 va_end(ap);
1.15 }
1.16
1.17 -void menu_init(void)
1.18 +void _menu_init(void)
1.19 {
1.20 current_entry = current_menu = &rootmenu;
1.21 last_entry_ptr = &rootmenu.list;
1.22 @@ -55,6 +58,8 @@
1.23 *last_entry_ptr = menu;
1.24 last_entry_ptr = &menu->next;
1.25 current_entry = menu;
1.26 + if (sym)
1.27 + menu_add_symbol(P_SYMBOL, sym, NULL);
1.28 }
1.29
1.30 void menu_end_entry(void)
1.31 @@ -74,7 +79,7 @@
1.32 current_menu = current_menu->parent;
1.33 }
1.34
1.35 -struct expr *menu_check_dep(struct expr *e)
1.36 +static struct expr *menu_check_dep(struct expr *e)
1.37 {
1.38 if (!e)
1.39 return e;
1.40 @@ -128,19 +133,27 @@
1.41 prop->visible.expr = menu_check_dep(dep);
1.42
1.43 if (prompt) {
1.44 - /* For crostool-NG, a leading pipe followed with spaces
1.45 - * means that pipe shall be removed, and the spaces should
1.46 - * not be trimmed.
1.47 - */
1.48 - if (*prompt == '|')
1.49 - prompt++;
1.50 - else if (isspace(*prompt)) {
1.51 - /* Silently trim leading spaces */
1.52 + if (isspace(*prompt)) {
1.53 + prop_warn(prop, "leading whitespace ignored");
1.54 while (isspace(*prompt))
1.55 prompt++;
1.56 }
1.57 - if (current_entry->prompt)
1.58 + if (current_entry->prompt && current_entry != &rootmenu)
1.59 prop_warn(prop, "prompt redefined");
1.60 +
1.61 + /* Apply all upper menus' visibilities to actual prompts. */
1.62 + if(type == P_PROMPT) {
1.63 + struct menu *menu = current_entry;
1.64 +
1.65 + while ((menu = menu->parent) != NULL) {
1.66 + if (!menu->visibility)
1.67 + continue;
1.68 + prop->visible.expr
1.69 + = expr_alloc_and(prop->visible.expr,
1.70 + menu->visibility);
1.71 + }
1.72 + }
1.73 +
1.74 current_entry->prompt = prop;
1.75 }
1.76 prop->text = prompt;
1.77 @@ -153,6 +166,12 @@
1.78 return menu_add_prop(type, prompt, NULL, dep);
1.79 }
1.80
1.81 +void menu_add_visibility(struct expr *expr)
1.82 +{
1.83 + current_entry->visibility = expr_alloc_and(current_entry->visibility,
1.84 + expr);
1.85 +}
1.86 +
1.87 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
1.88 {
1.89 menu_add_prop(type, NULL, expr, dep);
1.90 @@ -184,13 +203,13 @@
1.91 }
1.92 }
1.93
1.94 -static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
1.95 +static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
1.96 {
1.97 return sym2->type == S_INT || sym2->type == S_HEX ||
1.98 (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
1.99 }
1.100
1.101 -void sym_check_prop(struct symbol *sym)
1.102 +static void sym_check_prop(struct symbol *sym)
1.103 {
1.104 struct property *prop;
1.105 struct symbol *sym2;
1.106 @@ -200,8 +219,17 @@
1.107 if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
1.108 prop->expr->type != E_SYMBOL)
1.109 prop_warn(prop,
1.110 - "default for config symbol '%'"
1.111 + "default for config symbol '%s'"
1.112 " must be a single symbol", sym->name);
1.113 + if (prop->expr->type != E_SYMBOL)
1.114 + break;
1.115 + sym2 = prop_get_symbol(prop);
1.116 + if (sym->type == S_HEX || sym->type == S_INT) {
1.117 + if (!menu_validate_number(sym, sym2))
1.118 + prop_warn(prop,
1.119 + "'%s': number is invalid",
1.120 + sym->name);
1.121 + }
1.122 break;
1.123 case P_SELECT:
1.124 sym2 = prop_get_symbol(prop);
1.125 @@ -221,8 +249,8 @@
1.126 if (sym->type != S_INT && sym->type != S_HEX)
1.127 prop_warn(prop, "range is only allowed "
1.128 "for int or hex symbols");
1.129 - if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
1.130 - !menu_range_valid_sym(sym, prop->expr->right.sym))
1.131 + if (!menu_validate_number(sym, prop->expr->left.sym) ||
1.132 + !menu_validate_number(sym, prop->expr->right.sym))
1.133 prop_warn(prop, "range is invalid");
1.134 break;
1.135 default:
1.136 @@ -321,6 +349,8 @@
1.137 parent->next = last_menu->next;
1.138 last_menu->next = NULL;
1.139 }
1.140 +
1.141 + sym->dir_dep.expr = parent->dep;
1.142 }
1.143 for (menu = parent->list; menu; menu = menu->next) {
1.144 if (sym && sym_is_choice(sym) &&
1.145 @@ -393,6 +423,13 @@
1.146 }
1.147 }
1.148
1.149 +bool menu_has_prompt(struct menu *menu)
1.150 +{
1.151 + if (!menu->prompt)
1.152 + return false;
1.153 + return true;
1.154 +}
1.155 +
1.156 bool menu_is_visible(struct menu *menu)
1.157 {
1.158 struct menu *child;
1.159 @@ -401,6 +438,12 @@
1.160
1.161 if (!menu->prompt)
1.162 return false;
1.163 +
1.164 + if (menu->visibility) {
1.165 + if (expr_calc_value(menu->visibility) == no)
1.166 + return no;
1.167 + }
1.168 +
1.169 sym = menu->sym;
1.170 if (sym) {
1.171 sym_calc_value(sym);
1.172 @@ -410,12 +453,18 @@
1.173
1.174 if (visible != no)
1.175 return true;
1.176 +
1.177 if (!sym || sym_get_tristate_value(menu->sym) == no)
1.178 return false;
1.179
1.180 - for (child = menu->list; child; child = child->next)
1.181 - if (menu_is_visible(child))
1.182 + for (child = menu->list; child; child = child->next) {
1.183 + if (menu_is_visible(child)) {
1.184 + if (sym)
1.185 + sym->flags |= SYMBOL_DEF_USER;
1.186 return true;
1.187 + }
1.188 + }
1.189 +
1.190 return false;
1.191 }
1.192
1.193 @@ -457,3 +506,104 @@
1.194 else
1.195 return "";
1.196 }
1.197 +
1.198 +static void get_prompt_str(struct gstr *r, struct property *prop)
1.199 +{
1.200 + int i, j;
1.201 + struct menu *submenu[8], *menu;
1.202 +
1.203 + str_printf(r, _("Prompt: %s\n"), _(prop->text));
1.204 + str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name,
1.205 + prop->menu->lineno);
1.206 + if (!expr_is_yes(prop->visible.expr)) {
1.207 + str_append(r, _(" Depends on: "));
1.208 + expr_gstr_print(prop->visible.expr, r);
1.209 + str_append(r, "\n");
1.210 + }
1.211 + menu = prop->menu->parent;
1.212 + for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
1.213 + submenu[i++] = menu;
1.214 + if (i > 0) {
1.215 + str_printf(r, _(" Location:\n"));
1.216 + for (j = 4; --i >= 0; j += 2) {
1.217 + menu = submenu[i];
1.218 + str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu)));
1.219 + if (menu->sym) {
1.220 + str_printf(r, " (%s [=%s])", menu->sym->name ?
1.221 + menu->sym->name : _("<choice>"),
1.222 + sym_get_string_value(menu->sym));
1.223 + }
1.224 + str_append(r, "\n");
1.225 + }
1.226 + }
1.227 +}
1.228 +
1.229 +void get_symbol_str(struct gstr *r, struct symbol *sym)
1.230 +{
1.231 + bool hit;
1.232 + struct property *prop;
1.233 +
1.234 + if (sym && sym->name) {
1.235 + str_printf(r, "Symbol: %s [=%s]\n", sym->name,
1.236 + sym_get_string_value(sym));
1.237 + str_printf(r, "Type : %s\n", sym_type_name(sym->type));
1.238 + if (sym->type == S_INT || sym->type == S_HEX) {
1.239 + prop = sym_get_range_prop(sym);
1.240 + if (prop) {
1.241 + str_printf(r, "Range : ");
1.242 + expr_gstr_print(prop->expr, r);
1.243 + str_append(r, "\n");
1.244 + }
1.245 + }
1.246 + }
1.247 + for_all_prompts(sym, prop)
1.248 + get_prompt_str(r, prop);
1.249 + hit = false;
1.250 + for_all_properties(sym, prop, P_SELECT) {
1.251 + if (!hit) {
1.252 + str_append(r, " Selects: ");
1.253 + hit = true;
1.254 + } else
1.255 + str_printf(r, " && ");
1.256 + expr_gstr_print(prop->expr, r);
1.257 + }
1.258 + if (hit)
1.259 + str_append(r, "\n");
1.260 + if (sym->rev_dep.expr) {
1.261 + str_append(r, _(" Selected by: "));
1.262 + expr_gstr_print(sym->rev_dep.expr, r);
1.263 + str_append(r, "\n");
1.264 + }
1.265 + str_append(r, "\n\n");
1.266 +}
1.267 +
1.268 +struct gstr get_relations_str(struct symbol **sym_arr)
1.269 +{
1.270 + struct symbol *sym;
1.271 + struct gstr res = str_new();
1.272 + int i;
1.273 +
1.274 + for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
1.275 + get_symbol_str(&res, sym);
1.276 + if (!i)
1.277 + str_append(&res, _("No matches found.\n"));
1.278 + return res;
1.279 +}
1.280 +
1.281 +
1.282 +void menu_get_ext_help(struct menu *menu, struct gstr *help)
1.283 +{
1.284 + struct symbol *sym = menu->sym;
1.285 +
1.286 + if (menu_has_help(menu)) {
1.287 + if (sym->name) {
1.288 + str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
1.289 + str_append(help, _(menu_get_help(menu)));
1.290 + str_append(help, "\n");
1.291 + }
1.292 + } else {
1.293 + str_append(help, nohelp_text);
1.294 + }
1.295 + if (sym)
1.296 + get_symbol_str(help, sym);
1.297 +}