Blame view

scripts/kconfig/menu.c 17.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
  /*
   * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
   * Released under the terms of the GNU GPL v2.0.
   */
dd003306a   Arnaud Lacombe   kconfig: add miss...
5
  #include <ctype.h>
10a4b2772   Arnaud Lacombe   kconfig: add miss...
6
  #include <stdarg.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
  #include <stdlib.h>
  #include <string.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
  #include "lkc.h"
57e6292da   Arnaud Lacombe   kconfig: factor c...
10
  static const char nohelp_text[] = "There is no help available for this option.";
6bd5999d1   Cheng Renquan   kconfig: add menu...
11

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
  struct menu rootmenu;
  static struct menu **last_entry_ptr;
  
  struct file *file_list;
  struct file *current_file;
93449082e   Roman Zippel   kconfig: environm...
17
  void menu_warn(struct menu *menu, const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  {
  	va_list ap;
  	va_start(ap, fmt);
  	fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
  	vfprintf(stderr, fmt, ap);
  	fprintf(stderr, "
  ");
  	va_end(ap);
  }
  
  static void prop_warn(struct property *prop, const char *fmt, ...)
  {
  	va_list ap;
  	va_start(ap, fmt);
  	fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
  	vfprintf(stderr, fmt, ap);
  	fprintf(stderr, "
  ");
  	va_end(ap);
  }
692d97c38   nir.tzachar@gmail.com   kconfig: new conf...
38
  void _menu_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
41
42
43
44
45
46
  {
  	current_entry = current_menu = &rootmenu;
  	last_entry_ptr = &rootmenu.list;
  }
  
  void menu_add_entry(struct symbol *sym)
  {
  	struct menu *menu;
177acf784   Alan Cox   kconfig: Fix mall...
47
  	menu = xmalloc(sizeof(*menu));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
51
52
53
54
55
56
  	memset(menu, 0, sizeof(*menu));
  	menu->sym = sym;
  	menu->parent = current_menu;
  	menu->file = current_file;
  	menu->lineno = zconf_lineno();
  
  	*last_entry_ptr = menu;
  	last_entry_ptr = &menu->next;
  	current_entry = menu;
59e89e3dd   Sam Ravnborg   kconfig: save loc...
57
58
  	if (sym)
  		menu_add_symbol(P_SYMBOL, sym, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
62
63
  }
  
  void menu_end_entry(void)
  {
  }
a02f0570a   Roman Zippel   [PATCH] kconfig: ...
64
  struct menu *menu_add_menu(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  {
a02f0570a   Roman Zippel   [PATCH] kconfig: ...
66
  	menu_end_entry();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  	last_entry_ptr = &current_entry->list;
a02f0570a   Roman Zippel   [PATCH] kconfig: ...
68
  	return current_menu = current_entry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
72
73
74
75
  }
  
  void menu_end_menu(void)
  {
  	last_entry_ptr = &current_menu->next;
  	current_menu = current_menu->parent;
  }
4356f4890   Trevor Keith   kbuild: add stati...
76
  static struct expr *menu_check_dep(struct expr *e)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  {
  	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, menu_check_dep(dep));
  }
  
  void menu_set_type(int type)
  {
  	struct symbol *sym = current_entry->sym;
  
  	if (sym->type == type)
  		return;
  	if (sym->type == S_UNKNOWN) {
  		sym->type = type;
  		return;
  	}
57540f1de   Martin Walch   kconfig: adjust w...
116
117
118
119
  	menu_warn(current_entry,
  		"ignoring type redefinition of '%s' from '%s' to '%s'",
  		sym->name ? sym->name : "<choice>",
  		sym_type_name(sym->type), sym_type_name(type));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
  }
ad8d40cda   Michal Marek   kconfig: Remove u...
121
  static struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
  {
  	struct property *prop = prop_alloc(type, current_entry->sym);
  
  	prop->menu = current_entry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
129
  	prop->expr = expr;
  	prop->visible.expr = menu_check_dep(dep);
  
  	if (prompt) {
f001f7f89   Roman Zippel   kconfig: warn abo...
130
131
132
133
134
  		if (isspace(*prompt)) {
  			prop_warn(prop, "leading whitespace ignored");
  			while (isspace(*prompt))
  				prompt++;
  		}
ba6ff60d5   Arnaud Lacombe   kconfig: don't em...
135
  		if (current_entry->prompt && current_entry != &rootmenu)
f001f7f89   Roman Zippel   kconfig: warn abo...
136
  			prop_warn(prop, "prompt redefined");
7ad122781   Jan Beulich   kconfig: fix unde...
137
138
139
140
141
142
  
  		/* Apply all upper menus' visibilities to actual prompts. */
  		if(type == P_PROMPT) {
  			struct menu *menu = current_entry;
  
  			while ((menu = menu->parent) != NULL) {
e983b7b17   Dirk Gouders   kconfig/menu.c: f...
143
  				struct expr *dup_expr;
7ad122781   Jan Beulich   kconfig: fix unde...
144
145
  				if (!menu->visibility)
  					continue;
e983b7b17   Dirk Gouders   kconfig/menu.c: f...
146
147
148
149
150
151
152
153
154
155
  				/*
  				 * Do not add a reference to the
  				 * menu's visibility expression but
  				 * use a copy of it.  Otherwise the
  				 * expression reduction functions
  				 * will modify expressions that have
  				 * multiple references which can
  				 * cause unwanted side effects.
  				 */
  				dup_expr = expr_copy(menu->visibility);
7ad122781   Jan Beulich   kconfig: fix unde...
156
157
  				prop->visible.expr
  					= expr_alloc_and(prop->visible.expr,
e983b7b17   Dirk Gouders   kconfig/menu.c: f...
158
  							 dup_expr);
7ad122781   Jan Beulich   kconfig: fix unde...
159
160
  			}
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
  		current_entry->prompt = prop;
  	}
f001f7f89   Roman Zippel   kconfig: warn abo...
163
  	prop->text = prompt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
  
  	return prop;
  }
fb7f6ff61   Paolo 'Blaisorblade' Giarrusso   [PATCH] kconfig: ...
167
  struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
  {
fb7f6ff61   Paolo 'Blaisorblade' Giarrusso   [PATCH] kconfig: ...
169
  	return menu_add_prop(type, prompt, NULL, dep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  }
86e187ff9   Arnaud Lacombe   kconfig: add an o...
171
172
173
174
175
  void menu_add_visibility(struct expr *expr)
  {
  	current_entry->visibility = expr_alloc_and(current_entry->visibility,
  	    expr);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
179
180
181
182
183
184
  void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *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);
  }
f6a88aa86   Roman Zippel   kconfig: add symb...
185
186
  void menu_add_option(int token, char *arg)
  {
face4374e   Roman Zippel   kconfig: add defc...
187
188
  	switch (token) {
  	case T_OPT_MODULES:
e06278139   Yann E. MORIN   kconfig: do not a...
189
190
191
192
193
194
  		if (modules_sym)
  			zconf_error("symbol '%s' redefines option 'modules'"
  				    " already defined by symbol '%s'",
  				    current_entry->sym->name,
  				    modules_sym->name
  				    );
6902dccfd   Yann E. MORIN   kconfig: do not s...
195
  		modules_sym = current_entry->sym;
face4374e   Roman Zippel   kconfig: add defc...
196
197
198
199
200
201
202
  		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;
93449082e   Roman Zippel   kconfig: environm...
203
204
205
  	case T_OPT_ENV:
  		prop_add_env(arg);
  		break;
5d2acfc7b   Josh Triplett   kconfig: make all...
206
207
208
  	case T_OPT_ALLNOCONFIG_Y:
  		current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
  		break;
face4374e   Roman Zippel   kconfig: add defc...
209
  	}
f6a88aa86   Roman Zippel   kconfig: add symb...
210
  }
ab60bd0b9   Arnaud Lacombe   kconfig: add more...
211
  static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
4cf3cbe2a   Roman Zippel   [PATCH] kconfig: ...
212
213
214
215
  {
  	return sym2->type == S_INT || sym2->type == S_HEX ||
  	       (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
  }
4356f4890   Trevor Keith   kbuild: add stati...
216
  static void sym_check_prop(struct symbol *sym)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
219
  {
  	struct property *prop;
  	struct symbol *sym2;
237e3ad0f   Nicolas Pitre   Kconfig: Introduc...
220
  	char *use;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
223
224
225
226
  	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)
  				prop_warn(prop,
4280eae09   Li Zefan   kconfig: some sma...
227
  				    "default for config symbol '%s'"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
  				    " must be a single symbol", sym->name);
ab60bd0b9   Arnaud Lacombe   kconfig: add more...
229
230
231
232
233
234
235
236
237
  			if (prop->expr->type != E_SYMBOL)
  				break;
  			sym2 = prop_get_symbol(prop);
  			if (sym->type == S_HEX || sym->type == S_INT) {
  				if (!menu_validate_number(sym, sym2))
  					prop_warn(prop,
  					    "'%s': number is invalid",
  					    sym->name);
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
  			break;
  		case P_SELECT:
237e3ad0f   Nicolas Pitre   Kconfig: Introduc...
240
241
  		case P_IMPLY:
  			use = prop->type == P_SELECT ? "select" : "imply";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
244
  			sym2 = prop_get_symbol(prop);
  			if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
  				prop_warn(prop,
237e3ad0f   Nicolas Pitre   Kconfig: Introduc...
245
246
  				    "config symbol '%s' uses %s, but is "
  				    "not boolean or tristate", sym->name, use);
603d49885   Sam Ravnborg   kconfig: ignore s...
247
  			else if (sym2->type != S_UNKNOWN &&
bb66fc671   Masahiro Yamada   kbuild: trivial -...
248
249
  				 sym2->type != S_BOOLEAN &&
  				 sym2->type != S_TRISTATE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  				prop_warn(prop,
237e3ad0f   Nicolas Pitre   Kconfig: Introduc...
251
  				    "'%s' has wrong type. '%s' only "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
  				    "accept arguments of boolean and "
237e3ad0f   Nicolas Pitre   Kconfig: Introduc...
253
  				    "tristate type", sym2->name, use);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
255
256
257
  			break;
  		case P_RANGE:
  			if (sym->type != S_INT && sym->type != S_HEX)
  				prop_warn(prop, "range is only allowed "
bb66fc671   Masahiro Yamada   kbuild: trivial -...
258
  						"for int or hex symbols");
ab60bd0b9   Arnaud Lacombe   kconfig: add more...
259
260
  			if (!menu_validate_number(sym, prop->expr->left.sym) ||
  			    !menu_validate_number(sym, prop->expr->right.sym))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
  				prop_warn(prop, "range is invalid");
  			break;
  		default:
  			;
  		}
  	}
  }
  
  void menu_finalize(struct menu *parent)
  {
  	struct menu *menu, *last_menu;
  	struct symbol *sym;
  	struct property *prop;
  	struct expr *parentdep, *basedep, *dep, *dep2, **ep;
  
  	sym = parent->sym;
  	if (parent->list) {
  		if (sym && sym_is_choice(sym)) {
5a1aa8a1a   Roman Zippel   kconfig: add name...
279
280
281
282
283
  			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) {
f5eaa323e   Jan Beulich   kconfig: tristate...
284
  						menu_set_type(menu->sym->type);
5a1aa8a1a   Roman Zippel   kconfig: add name...
285
286
  						break;
  					}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
288
  				}
  			}
5a1aa8a1a   Roman Zippel   kconfig: add name...
289
290
291
292
293
294
  			/* set the type of the remaining choice values */
  			for (menu = parent->list; menu; menu = menu->next) {
  				current_entry = menu;
  				if (menu->sym && menu->sym->type == S_UNKNOWN)
  					menu_set_type(sym->type);
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
296
297
298
299
300
301
302
  			parentdep = expr_alloc_symbol(sym);
  		} else if (parent->prompt)
  			parentdep = parent->prompt->visible.expr;
  		else
  			parentdep = parent->dep;
  
  		for (menu = parent->list; menu; menu = menu->next) {
  			basedep = expr_transform(menu->dep);
e8b8c9777   Linus Torvalds   Revert "kconfig: ...
303
  			basedep = expr_alloc_and(expr_copy(parentdep), basedep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  			basedep = expr_eliminate_dups(basedep);
  			menu->dep = basedep;
  			if (menu->sym)
  				prop = menu->sym->prop;
  			else
  				prop = menu->prompt;
  			for (; prop; prop = prop->next) {
  				if (prop->menu != menu)
  					continue;
  				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);
  				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)));
237e3ad0f   Nicolas Pitre   Kconfig: Introduc...
323
324
325
326
  				} else if (prop->type == P_IMPLY) {
  					struct symbol *es = prop_get_symbol(prop);
  					es->implied.expr = expr_alloc_or(es->implied.expr,
  							expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
  				}
  			}
  		}
  		for (menu = parent->list; menu; menu = menu->next)
  			menu_finalize(menu);
  	} 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 ? menu->prompt->visible.expr : menu->dep;
  			if (!expr_contains_symbol(dep, sym))
  				break;
  			if (expr_depends_symbol(dep, sym))
  				goto next;
  			dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
  			dep = expr_eliminate_dups(expr_transform(dep));
  			dep2 = expr_copy(basedep);
  			expr_eliminate_eq(&dep, &dep2);
  			expr_free(dep);
  			if (!expr_is_yes(dep2)) {
  				expr_free(dep2);
  				break;
  			}
  			expr_free(dep2);
  		next:
  			menu_finalize(menu);
  			menu->parent = parent;
  			last_menu = menu;
  		}
0f511f3dd   Ulf Magnusson   kconfig: Fix auto...
358
  		expr_free(basedep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
360
361
362
363
  		if (last_menu) {
  			parent->list = parent->next;
  			parent->next = last_menu->next;
  			last_menu->next = NULL;
  		}
ff5ff6060   Arnaud Lacombe   kconfig: delay sy...
364

ec6452a5e   Arnaud Lacombe   kconfig: do not o...
365
  		sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
367
  	}
  	for (menu = parent->list; menu; menu = menu->next) {
5a1aa8a1a   Roman Zippel   kconfig: add name...
368
369
370
  		if (sym && sym_is_choice(sym) &&
  		    menu->sym && !sym_is_choice_value(menu->sym)) {
  			current_entry = menu;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
373
374
  			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) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
  				if (prop->type == P_DEFAULT)
  					prop_warn(prop, "defaults for choice "
5a1aa8a1a   Roman Zippel   kconfig: add name...
377
378
379
380
381
382
  						  "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");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
  			}
f5eaa323e   Jan Beulich   kconfig: tristate...
384
385
386
387
  			/* 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-
5a1aa8a1a   Roman Zippel   kconfig: add name...
388
389
  			 * propagated.
  			 */
f5eaa323e   Jan Beulich   kconfig: tristate...
390
391
  			if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {
  				basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);
5a1aa8a1a   Roman Zippel   kconfig: add name...
392
  				menu->dep = expr_alloc_and(basedep, menu->dep);
f5eaa323e   Jan Beulich   kconfig: tristate...
393
394
395
  				for (prop = menu->sym->prop; prop; prop = prop->next) {
  					if (prop->menu != menu)
  						continue;
5a1aa8a1a   Roman Zippel   kconfig: add name...
396
397
  					prop->visible.expr = expr_alloc_and(expr_copy(basedep),
  									    prop->visible.expr);
f5eaa323e   Jan Beulich   kconfig: tristate...
398
399
  				}
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
401
402
403
  			menu_add_symbol(P_CHOICE, sym, NULL);
  			prop = sym_get_choice_prop(sym);
  			for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
  				;
7a9629233   Roman Zippel   kconfig: explicit...
404
  			*ep = expr_alloc_one(E_LIST, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
  			(*ep)->right.sym = menu->sym;
  		}
  		if (menu->list && (!menu->prompt || !menu->prompt->text)) {
  			for (last_menu = menu->list; ; last_menu = last_menu->next) {
  				last_menu->parent = parent;
  				if (!last_menu->next)
  					break;
  			}
  			last_menu->next = menu->next;
  			menu->next = menu->list;
  			menu->list = NULL;
  		}
  	}
  
  	if (sym && !(sym->flags & SYMBOL_WARNED)) {
  		if (sym->type == S_UNKNOWN)
f001f7f89   Roman Zippel   kconfig: warn abo...
421
  			menu_warn(parent, "config symbol defined without type");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
423
  
  		if (sym_is_choice(sym) && !parent->prompt)
f001f7f89   Roman Zippel   kconfig: warn abo...
424
  			menu_warn(parent, "choice must have a prompt");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
426
427
428
429
430
431
432
433
434
435
436
  
  		/* Check properties connected to this symbol */
  		sym_check_prop(sym);
  		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)));
  	}
  }
22c7eca61   Li Zefan   menuconfig: add s...
437
438
439
440
441
442
  bool menu_has_prompt(struct menu *menu)
  {
  	if (!menu->prompt)
  		return false;
  	return true;
  }
1278ebdbc   Dirk Gouders   mconf/nconf: mark...
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
  /*
   * Determine if a menu is empty.
   * A menu is considered empty if it contains no or only
   * invisible entries.
   */
  bool menu_is_empty(struct menu *menu)
  {
  	struct menu *child;
  
  	for (child = menu->list; child; child = child->next) {
  		if (menu_is_visible(child))
  			return(false);
  	}
  	return(true);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
460
461
462
463
464
465
  bool menu_is_visible(struct menu *menu)
  {
  	struct menu *child;
  	struct symbol *sym;
  	tristate visible;
  
  	if (!menu->prompt)
  		return false;
22c7eca61   Li Zefan   menuconfig: add s...
466

86e187ff9   Arnaud Lacombe   kconfig: add an o...
467
468
  	if (menu->visibility) {
  		if (expr_calc_value(menu->visibility) == no)
aab24a897   Vegard Nossum   kconfig: return '...
469
  			return false;
86e187ff9   Arnaud Lacombe   kconfig: add an o...
470
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
471
472
473
474
475
476
477
478
479
  	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);
  
  	if (visible != no)
  		return true;
22c7eca61   Li Zefan   menuconfig: add s...
480

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
  	if (!sym || sym_get_tristate_value(menu->sym) == no)
  		return false;
3fb9acb32   Li Zefan   kconfig: fix to t...
483
484
485
486
  	for (child = menu->list; child; child = child->next) {
  		if (menu_is_visible(child)) {
  			if (sym)
  				sym->flags |= SYMBOL_DEF_USER;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
  			return true;
3fb9acb32   Li Zefan   kconfig: fix to t...
488
489
  		}
  	}
22c7eca61   Li Zefan   menuconfig: add s...
490

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
492
493
494
495
496
  	return false;
  }
  
  const char *menu_get_prompt(struct menu *menu)
  {
  	if (menu->prompt)
01771b0fe   EGRY Gabor   kconfig: macro fi...
497
  		return menu->prompt->text;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
  	else if (menu->sym)
01771b0fe   EGRY Gabor   kconfig: macro fi...
499
  		return menu->sym->name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
  	return NULL;
  }
  
  struct menu *menu_get_root_menu(struct menu *menu)
  {
  	return &rootmenu;
  }
  
  struct menu *menu_get_parent_menu(struct menu *menu)
  {
  	enum prop_type type;
  
  	for (; menu != &rootmenu; menu = menu->parent) {
  		type = menu->prompt ? menu->prompt->type : 0;
  		if (type == P_MENU)
  			break;
  	}
  	return menu;
  }
03d291227   Sam Ravnborg   kconfig: attach h...
519
520
521
522
523
524
525
526
527
528
529
530
  bool menu_has_help(struct menu *menu)
  {
  	return menu->help != NULL;
  }
  
  const char *menu_get_help(struct menu *menu)
  {
  	if (menu->help)
  		return menu->help;
  	else
  		return "";
  }
6bd5999d1   Cheng Renquan   kconfig: add menu...
531

95ac9b3b5   Benjamin Poirier   menuconfig: Assig...
532
  static void get_prompt_str(struct gstr *r, struct property *prop,
bad9955db   Benjamin Poirier   menuconfig: Repla...
533
  			   struct list_head *head)
6bd5999d1   Cheng Renquan   kconfig: add menu...
534
535
  {
  	int i, j;
5e609addb   Benjamin Poirier   menuconfig: Add j...
536
  	struct menu *submenu[8], *menu, *location = NULL;
2d5603060   Peter Kümmel   kconfig: Fix warn...
537
  	struct jump_key *jump = NULL;
6bd5999d1   Cheng Renquan   kconfig: add menu...
538
539
540
  
  	str_printf(r, _("Prompt: %s
  "), _(prop->text));
6bd5999d1   Cheng Renquan   kconfig: add menu...
541
  	menu = prop->menu->parent;
5e609addb   Benjamin Poirier   menuconfig: Add j...
542
543
  	for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
  		bool accessible = menu_is_visible(menu);
6bd5999d1   Cheng Renquan   kconfig: add menu...
544
  		submenu[i++] = menu;
5e609addb   Benjamin Poirier   menuconfig: Add j...
545
546
547
  		if (location == NULL && accessible)
  			location = menu;
  	}
95ac9b3b5   Benjamin Poirier   menuconfig: Assig...
548
  	if (head && location) {
177acf784   Alan Cox   kconfig: Fix mall...
549
  		jump = xmalloc(sizeof(struct jump_key));
95ac9b3b5   Benjamin Poirier   menuconfig: Assig...
550

5e609addb   Benjamin Poirier   menuconfig: Add j...
551
552
553
554
555
556
557
  		if (menu_is_visible(prop->menu)) {
  			/*
  			 * There is not enough room to put the hint at the
  			 * beginning of the "Prompt" line. Put the hint on the
  			 * last "Location" line even when it would belong on
  			 * the former.
  			 */
95ac9b3b5   Benjamin Poirier   menuconfig: Assig...
558
  			jump->target = prop->menu;
5e609addb   Benjamin Poirier   menuconfig: Add j...
559
  		} else
95ac9b3b5   Benjamin Poirier   menuconfig: Assig...
560
  			jump->target = location;
bad9955db   Benjamin Poirier   menuconfig: Repla...
561
  		if (list_empty(head))
95ac9b3b5   Benjamin Poirier   menuconfig: Assig...
562
563
  			jump->index = 0;
  		else
bad9955db   Benjamin Poirier   menuconfig: Repla...
564
565
  			jump->index = list_entry(head->prev, struct jump_key,
  						 entries)->index + 1;
95ac9b3b5   Benjamin Poirier   menuconfig: Assig...
566

bad9955db   Benjamin Poirier   menuconfig: Repla...
567
  		list_add_tail(&jump->entries, head);
95ac9b3b5   Benjamin Poirier   menuconfig: Assig...
568
  	}
5e609addb   Benjamin Poirier   menuconfig: Add j...
569

6bd5999d1   Cheng Renquan   kconfig: add menu...
570
571
572
  	if (i > 0) {
  		str_printf(r, _("  Location:
  "));
95ac9b3b5   Benjamin Poirier   menuconfig: Assig...
573
  		for (j = 4; --i >= 0; j += 2) {
6bd5999d1   Cheng Renquan   kconfig: add menu...
574
  			menu = submenu[i];
2d5603060   Peter Kümmel   kconfig: Fix warn...
575
  			if (jump && menu == location)
503c82304   Martin Walch   kconfig: fix bug ...
576
  				jump->offset = strlen(r->s);
95ac9b3b5   Benjamin Poirier   menuconfig: Assig...
577
578
  			str_printf(r, "%*c-> %s", j, ' ',
  				   _(menu_get_prompt(menu)));
6bd5999d1   Cheng Renquan   kconfig: add menu...
579
580
581
582
583
584
585
586
587
588
  			if (menu->sym) {
  				str_printf(r, " (%s [=%s])", menu->sym->name ?
  					menu->sym->name : _("<choice>"),
  					sym_get_string_value(menu->sym));
  			}
  			str_append(r, "
  ");
  		}
  	}
  }
5e609addb   Benjamin Poirier   menuconfig: Add j...
589
  /*
8d9dfe827   Martin Walch   kconfig: fix triv...
590
   * get property of type P_SYMBOL
bcdedcc1a   Wengmeiling   menuconfig: print...
591
592
593
594
595
596
597
598
599
   */
  static struct property *get_symbol_prop(struct symbol *sym)
  {
  	struct property *prop = NULL;
  
  	for_all_properties(sym, prop, P_SYMBOL)
  		break;
  	return prop;
  }
237e3ad0f   Nicolas Pitre   Kconfig: Introduc...
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
  static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
  				 enum prop_type tok, const char *prefix)
  {
  	bool hit = false;
  	struct property *prop;
  
  	for_all_properties(sym, prop, tok) {
  		if (!hit) {
  			str_append(r, prefix);
  			hit = true;
  		} else
  			str_printf(r, " && ");
  		expr_gstr_print(prop->expr, r);
  	}
  	if (hit)
  		str_append(r, "
  ");
  }
bcdedcc1a   Wengmeiling   menuconfig: print...
618
  /*
95ac9b3b5   Benjamin Poirier   menuconfig: Assig...
619
   * head is optional and may be NULL
5e609addb   Benjamin Poirier   menuconfig: Add j...
620
   */
ad8d40cda   Michal Marek   kconfig: Remove u...
621
  static void get_symbol_str(struct gstr *r, struct symbol *sym,
bad9955db   Benjamin Poirier   menuconfig: Repla...
622
  		    struct list_head *head)
6bd5999d1   Cheng Renquan   kconfig: add menu...
623
  {
6bd5999d1   Cheng Renquan   kconfig: add menu...
624
  	struct property *prop;
b040b44c3   Li Zefan   kconfig: print sy...
625
  	if (sym && sym->name) {
6bd5999d1   Cheng Renquan   kconfig: add menu...
626
627
628
  		str_printf(r, "Symbol: %s [=%s]
  ", sym->name,
  			   sym_get_string_value(sym));
b040b44c3   Li Zefan   kconfig: print sy...
629
630
  		str_printf(r, "Type  : %s
  ", sym_type_name(sym->type));
70ed07471   Li Zefan   kconfig: print th...
631
632
633
634
635
636
637
638
639
  		if (sym->type == S_INT || sym->type == S_HEX) {
  			prop = sym_get_range_prop(sym);
  			if (prop) {
  				str_printf(r, "Range : ");
  				expr_gstr_print(prop->expr, r);
  				str_append(r, "
  ");
  			}
  		}
b040b44c3   Li Zefan   kconfig: print sy...
640
  	}
6bd5999d1   Cheng Renquan   kconfig: add menu...
641
  	for_all_prompts(sym, prop)
95ac9b3b5   Benjamin Poirier   menuconfig: Assig...
642
  		get_prompt_str(r, prop, head);
383da76f5   Li Zefan   menuconfig: fix N...
643

bcdedcc1a   Wengmeiling   menuconfig: print...
644
  	prop = get_symbol_prop(sym);
383da76f5   Li Zefan   menuconfig: fix N...
645
646
647
648
649
650
651
652
653
654
  	if (prop) {
  		str_printf(r, _("  Defined at %s:%d
  "), prop->menu->file->name,
  			prop->menu->lineno);
  		if (!expr_is_yes(prop->visible.expr)) {
  			str_append(r, _("  Depends on: "));
  			expr_gstr_print(prop->visible.expr, r);
  			str_append(r, "
  ");
  		}
bcdedcc1a   Wengmeiling   menuconfig: print...
655
  	}
383da76f5   Li Zefan   menuconfig: fix N...
656

237e3ad0f   Nicolas Pitre   Kconfig: Introduc...
657
  	get_symbol_props_str(r, sym, P_SELECT, _("  Selects: "));
6bd5999d1   Cheng Renquan   kconfig: add menu...
658
659
660
661
662
663
  	if (sym->rev_dep.expr) {
  		str_append(r, _("  Selected by: "));
  		expr_gstr_print(sym->rev_dep.expr, r);
  		str_append(r, "
  ");
  	}
237e3ad0f   Nicolas Pitre   Kconfig: Introduc...
664
665
666
667
668
669
670
671
  
  	get_symbol_props_str(r, sym, P_IMPLY, _("  Implies: "));
  	if (sym->implied.expr) {
  		str_append(r, _("  Implied by: "));
  		expr_gstr_print(sym->implied.expr, r);
  		str_append(r, "
  ");
  	}
6bd5999d1   Cheng Renquan   kconfig: add menu...
672
673
674
675
  	str_append(r, "
  
  ");
  }
bad9955db   Benjamin Poirier   menuconfig: Repla...
676
  struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
692d97c38   nir.tzachar@gmail.com   kconfig: new conf...
677
678
679
  {
  	struct symbol *sym;
  	struct gstr res = str_new();
95ac9b3b5   Benjamin Poirier   menuconfig: Assig...
680
  	int i;
692d97c38   nir.tzachar@gmail.com   kconfig: new conf...
681
682
  
  	for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
95ac9b3b5   Benjamin Poirier   menuconfig: Assig...
683
  		get_symbol_str(&res, sym, head);
692d97c38   nir.tzachar@gmail.com   kconfig: new conf...
684
685
686
687
688
  	if (!i)
  		str_append(&res, _("No matches found.
  "));
  	return res;
  }
6bd5999d1   Cheng Renquan   kconfig: add menu...
689
690
691
  void menu_get_ext_help(struct menu *menu, struct gstr *help)
  {
  	struct symbol *sym = menu->sym;
57e6292da   Arnaud Lacombe   kconfig: factor c...
692
  	const char *help_text = nohelp_text;
6bd5999d1   Cheng Renquan   kconfig: add menu...
693
694
  
  	if (menu_has_help(menu)) {
3f198dfee   Srinivas Kandagatla   kbuild: Fix help ...
695
  		if (sym->name)
ffb5957bc   Arnaud Lacombe   kconfig: allow bu...
696
697
698
  			str_printf(help, "%s%s:
  
  ", CONFIG_, sym->name);
57e6292da   Arnaud Lacombe   kconfig: factor c...
699
  		help_text = menu_get_help(menu);
6bd5999d1   Cheng Renquan   kconfig: add menu...
700
  	}
57e6292da   Arnaud Lacombe   kconfig: factor c...
701
702
  	str_printf(help, "%s
  ", _(help_text));
4779105e0   Cheng Renquan   kconfig: make use...
703
  	if (sym)
95ac9b3b5   Benjamin Poirier   menuconfig: Assig...
704
  		get_symbol_str(help, sym, NULL);
6bd5999d1   Cheng Renquan   kconfig: add menu...
705
  }