kconfig/menu.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Sun Jul 13 10:32:38 2008 +0000 (2008-07-13)
changeset 645 8e58024f8e37
child 943 1cca90ce0481
permissions -rw-r--r--
Ioannis E. VENETIS <venetis@mail.capsl.udel.edu> pointed out that GMP and MPFR were not used by gcc.
Turned out that none could use GMP and MPFR as the config option changed its name, but the change was not propagated to all users.

/trunk/scripts/build/binutils.sh | 2 1 1 0 +-
/trunk/scripts/build/debug/300-gdb.sh | 2 1 1 0 +-
/trunk/scripts/build/cc_gcc.sh | 6 3 3 0 +++---
3 files changed, 5 insertions(+), 5 deletions(-)
yann@1
     1
/*
yann@1
     2
 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
yann@1
     3
 * Released under the terms of the GNU GPL v2.0.
yann@1
     4
 */
yann@1
     5
yann@1
     6
#include <stdlib.h>
yann@1
     7
#include <string.h>
yann@1
     8
yann@1
     9
#define LKC_DIRECT_LINK
yann@1
    10
#include "lkc.h"
yann@1
    11
yann@1
    12
struct menu rootmenu;
yann@1
    13
static struct menu **last_entry_ptr;
yann@1
    14
yann@1
    15
struct file *file_list;
yann@1
    16
struct file *current_file;
yann@1
    17
yann@1
    18
static void menu_warn(struct menu *menu, const char *fmt, ...)
yann@1
    19
{
yann@1
    20
	va_list ap;
yann@1
    21
	va_start(ap, fmt);
yann@1
    22
	fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
yann@1
    23
	vfprintf(stderr, fmt, ap);
yann@1
    24
	fprintf(stderr, "\n");
yann@1
    25
	va_end(ap);
yann@1
    26
}
yann@1
    27
yann@1
    28
static void prop_warn(struct property *prop, const char *fmt, ...)
yann@1
    29
{
yann@1
    30
	va_list ap;
yann@1
    31
	va_start(ap, fmt);
yann@1
    32
	fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
yann@1
    33
	vfprintf(stderr, fmt, ap);
yann@1
    34
	fprintf(stderr, "\n");
yann@1
    35
	va_end(ap);
yann@1
    36
}
yann@1
    37
yann@1
    38
void menu_init(void)
yann@1
    39
{
yann@1
    40
	current_entry = current_menu = &rootmenu;
yann@1
    41
	last_entry_ptr = &rootmenu.list;
yann@1
    42
}
yann@1
    43
yann@1
    44
void menu_add_entry(struct symbol *sym)
yann@1
    45
{
yann@1
    46
	struct menu *menu;
yann@1
    47
yann@1
    48
	menu = malloc(sizeof(*menu));
yann@1
    49
	memset(menu, 0, sizeof(*menu));
yann@1
    50
	menu->sym = sym;
yann@1
    51
	menu->parent = current_menu;
yann@1
    52
	menu->file = current_file;
yann@1
    53
	menu->lineno = zconf_lineno();
yann@1
    54
yann@1
    55
	*last_entry_ptr = menu;
yann@1
    56
	last_entry_ptr = &menu->next;
yann@1
    57
	current_entry = menu;
yann@1
    58
}
yann@1
    59
yann@1
    60
void menu_end_entry(void)
yann@1
    61
{
yann@1
    62
}
yann@1
    63
yann@1
    64
struct menu *menu_add_menu(void)
yann@1
    65
{
yann@1
    66
	menu_end_entry();
yann@1
    67
	last_entry_ptr = &current_entry->list;
yann@1
    68
	return current_menu = current_entry;
yann@1
    69
}
yann@1
    70
yann@1
    71
void menu_end_menu(void)
yann@1
    72
{
yann@1
    73
	last_entry_ptr = &current_menu->next;
yann@1
    74
	current_menu = current_menu->parent;
yann@1
    75
}
yann@1
    76
yann@1
    77
struct expr *menu_check_dep(struct expr *e)
yann@1
    78
{
yann@1
    79
	if (!e)
yann@1
    80
		return e;
yann@1
    81
yann@1
    82
	switch (e->type) {
yann@1
    83
	case E_NOT:
yann@1
    84
		e->left.expr = menu_check_dep(e->left.expr);
yann@1
    85
		break;
yann@1
    86
	case E_OR:
yann@1
    87
	case E_AND:
yann@1
    88
		e->left.expr = menu_check_dep(e->left.expr);
yann@1
    89
		e->right.expr = menu_check_dep(e->right.expr);
yann@1
    90
		break;
yann@1
    91
	case E_SYMBOL:
yann@1
    92
		/* change 'm' into 'm' && MODULES */
yann@1
    93
		if (e->left.sym == &symbol_mod)
yann@1
    94
			return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
yann@1
    95
		break;
yann@1
    96
	default:
yann@1
    97
		break;
yann@1
    98
	}
yann@1
    99
	return e;
yann@1
   100
}
yann@1
   101
yann@1
   102
void menu_add_dep(struct expr *dep)
yann@1
   103
{
yann@1
   104
	current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
yann@1
   105
}
yann@1
   106
yann@1
   107
void menu_set_type(int type)
yann@1
   108
{
yann@1
   109
	struct symbol *sym = current_entry->sym;
yann@1
   110
yann@1
   111
	if (sym->type == type)
yann@1
   112
		return;
yann@1
   113
	if (sym->type == S_UNKNOWN) {
yann@1
   114
		sym->type = type;
yann@1
   115
		return;
yann@1
   116
	}
yann@1
   117
	menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
yann@1
   118
	    sym->name ? sym->name : "<choice>",
yann@1
   119
	    sym_type_name(sym->type), sym_type_name(type));
yann@1
   120
}
yann@1
   121
yann@1
   122
struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
yann@1
   123
{
yann@1
   124
	struct property *prop = prop_alloc(type, current_entry->sym);
yann@1
   125
yann@1
   126
	prop->menu = current_entry;
yann@1
   127
	prop->expr = expr;
yann@1
   128
	prop->visible.expr = menu_check_dep(dep);
yann@1
   129
yann@1
   130
	if (prompt) {
yann@1
   131
		if (isspace(*prompt)) {
yann@1
   132
			prop_warn(prop, "leading whitespace ignored");
yann@1
   133
			while (isspace(*prompt))
yann@1
   134
				prompt++;
yann@1
   135
		}
yann@1
   136
		if (current_entry->prompt)
yann@1
   137
			prop_warn(prop, "prompt redefined");
yann@1
   138
		current_entry->prompt = prop;
yann@1
   139
	}
yann@1
   140
	prop->text = prompt;
yann@1
   141
yann@1
   142
	return prop;
yann@1
   143
}
yann@1
   144
yann@1
   145
struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
yann@1
   146
{
yann@1
   147
	return menu_add_prop(type, prompt, NULL, dep);
yann@1
   148
}
yann@1
   149
yann@1
   150
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
yann@1
   151
{
yann@1
   152
	menu_add_prop(type, NULL, expr, dep);
yann@1
   153
}
yann@1
   154
yann@1
   155
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
yann@1
   156
{
yann@1
   157
	menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
yann@1
   158
}
yann@1
   159
yann@1
   160
void menu_add_option(int token, char *arg)
yann@1
   161
{
yann@1
   162
	struct property *prop;
yann@1
   163
yann@1
   164
	switch (token) {
yann@1
   165
	case T_OPT_MODULES:
yann@1
   166
		prop = prop_alloc(P_DEFAULT, modules_sym);
yann@1
   167
		prop->expr = expr_alloc_symbol(current_entry->sym);
yann@1
   168
		break;
yann@1
   169
	case T_OPT_DEFCONFIG_LIST:
yann@1
   170
		if (!sym_defconfig_list)
yann@1
   171
			sym_defconfig_list = current_entry->sym;
yann@1
   172
		else if (sym_defconfig_list != current_entry->sym)
yann@1
   173
			zconf_error("trying to redefine defconfig symbol");
yann@1
   174
		break;
yann@1
   175
	}
yann@1
   176
}
yann@1
   177
yann@1
   178
static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
yann@1
   179
{
yann@1
   180
	return sym2->type == S_INT || sym2->type == S_HEX ||
yann@1
   181
	       (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
yann@1
   182
}
yann@1
   183
yann@1
   184
void sym_check_prop(struct symbol *sym)
yann@1
   185
{
yann@1
   186
	struct property *prop;
yann@1
   187
	struct symbol *sym2;
yann@1
   188
	for (prop = sym->prop; prop; prop = prop->next) {
yann@1
   189
		switch (prop->type) {
yann@1
   190
		case P_DEFAULT:
yann@1
   191
			if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
yann@1
   192
			    prop->expr->type != E_SYMBOL)
yann@1
   193
				prop_warn(prop,
yann@1
   194
				    "default for config symbol '%'"
yann@1
   195
				    " must be a single symbol", sym->name);
yann@1
   196
			break;
yann@1
   197
		case P_SELECT:
yann@1
   198
			sym2 = prop_get_symbol(prop);
yann@1
   199
			if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
yann@1
   200
				prop_warn(prop,
yann@1
   201
				    "config symbol '%s' uses select, but is "
yann@1
   202
				    "not boolean or tristate", sym->name);
yann@1
   203
			else if (sym2->type == S_UNKNOWN)
yann@1
   204
				prop_warn(prop,
yann@1
   205
				    "'select' used by config symbol '%s' "
yann@1
   206
				    "refer to undefined symbol '%s'",
yann@1
   207
				    sym->name, sym2->name);
yann@1
   208
			else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
yann@1
   209
				prop_warn(prop,
yann@1
   210
				    "'%s' has wrong type. 'select' only "
yann@1
   211
				    "accept arguments of boolean and "
yann@1
   212
				    "tristate type", sym2->name);
yann@1
   213
			break;
yann@1
   214
		case P_RANGE:
yann@1
   215
			if (sym->type != S_INT && sym->type != S_HEX)
yann@1
   216
				prop_warn(prop, "range is only allowed "
yann@1
   217
				                "for int or hex symbols");
yann@1
   218
			if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
yann@1
   219
			    !menu_range_valid_sym(sym, prop->expr->right.sym))
yann@1
   220
				prop_warn(prop, "range is invalid");
yann@1
   221
			break;
yann@1
   222
		default:
yann@1
   223
			;
yann@1
   224
		}
yann@1
   225
	}
yann@1
   226
}
yann@1
   227
yann@1
   228
void menu_finalize(struct menu *parent)
yann@1
   229
{
yann@1
   230
	struct menu *menu, *last_menu;
yann@1
   231
	struct symbol *sym;
yann@1
   232
	struct property *prop;
yann@1
   233
	struct expr *parentdep, *basedep, *dep, *dep2, **ep;
yann@1
   234
yann@1
   235
	sym = parent->sym;
yann@1
   236
	if (parent->list) {
yann@1
   237
		if (sym && sym_is_choice(sym)) {
yann@1
   238
			/* find the first choice value and find out choice type */
yann@1
   239
			for (menu = parent->list; menu; menu = menu->next) {
yann@1
   240
				if (menu->sym) {
yann@1
   241
					current_entry = parent;
yann@1
   242
					menu_set_type(menu->sym->type);
yann@1
   243
					current_entry = menu;
yann@1
   244
					menu_set_type(sym->type);
yann@1
   245
					break;
yann@1
   246
				}
yann@1
   247
			}
yann@1
   248
			parentdep = expr_alloc_symbol(sym);
yann@1
   249
		} else if (parent->prompt)
yann@1
   250
			parentdep = parent->prompt->visible.expr;
yann@1
   251
		else
yann@1
   252
			parentdep = parent->dep;
yann@1
   253
yann@1
   254
		for (menu = parent->list; menu; menu = menu->next) {
yann@1
   255
			basedep = expr_transform(menu->dep);
yann@1
   256
			basedep = expr_alloc_and(expr_copy(parentdep), basedep);
yann@1
   257
			basedep = expr_eliminate_dups(basedep);
yann@1
   258
			menu->dep = basedep;
yann@1
   259
			if (menu->sym)
yann@1
   260
				prop = menu->sym->prop;
yann@1
   261
			else
yann@1
   262
				prop = menu->prompt;
yann@1
   263
			for (; prop; prop = prop->next) {
yann@1
   264
				if (prop->menu != menu)
yann@1
   265
					continue;
yann@1
   266
				dep = expr_transform(prop->visible.expr);
yann@1
   267
				dep = expr_alloc_and(expr_copy(basedep), dep);
yann@1
   268
				dep = expr_eliminate_dups(dep);
yann@1
   269
				if (menu->sym && menu->sym->type != S_TRISTATE)
yann@1
   270
					dep = expr_trans_bool(dep);
yann@1
   271
				prop->visible.expr = dep;
yann@1
   272
				if (prop->type == P_SELECT) {
yann@1
   273
					struct symbol *es = prop_get_symbol(prop);
yann@1
   274
					es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
yann@1
   275
							expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
yann@1
   276
				}
yann@1
   277
			}
yann@1
   278
		}
yann@1
   279
		for (menu = parent->list; menu; menu = menu->next)
yann@1
   280
			menu_finalize(menu);
yann@1
   281
	} else if (sym) {
yann@1
   282
		basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
yann@1
   283
		basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
yann@1
   284
		basedep = expr_eliminate_dups(expr_transform(basedep));
yann@1
   285
		last_menu = NULL;
yann@1
   286
		for (menu = parent->next; menu; menu = menu->next) {
yann@1
   287
			dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
yann@1
   288
			if (!expr_contains_symbol(dep, sym))
yann@1
   289
				break;
yann@1
   290
			if (expr_depends_symbol(dep, sym))
yann@1
   291
				goto next;
yann@1
   292
			dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
yann@1
   293
			dep = expr_eliminate_dups(expr_transform(dep));
yann@1
   294
			dep2 = expr_copy(basedep);
yann@1
   295
			expr_eliminate_eq(&dep, &dep2);
yann@1
   296
			expr_free(dep);
yann@1
   297
			if (!expr_is_yes(dep2)) {
yann@1
   298
				expr_free(dep2);
yann@1
   299
				break;
yann@1
   300
			}
yann@1
   301
			expr_free(dep2);
yann@1
   302
		next:
yann@1
   303
			menu_finalize(menu);
yann@1
   304
			menu->parent = parent;
yann@1
   305
			last_menu = menu;
yann@1
   306
		}
yann@1
   307
		if (last_menu) {
yann@1
   308
			parent->list = parent->next;
yann@1
   309
			parent->next = last_menu->next;
yann@1
   310
			last_menu->next = NULL;
yann@1
   311
		}
yann@1
   312
	}
yann@1
   313
	for (menu = parent->list; menu; menu = menu->next) {
yann@1
   314
		if (sym && sym_is_choice(sym) && menu->sym) {
yann@1
   315
			menu->sym->flags |= SYMBOL_CHOICEVAL;
yann@1
   316
			if (!menu->prompt)
yann@1
   317
				menu_warn(menu, "choice value must have a prompt");
yann@1
   318
			for (prop = menu->sym->prop; prop; prop = prop->next) {
yann@1
   319
				if (prop->type == P_PROMPT && prop->menu != menu) {
yann@1
   320
					prop_warn(prop, "choice values "
yann@1
   321
					    "currently only support a "
yann@1
   322
					    "single prompt");
yann@1
   323
				}
yann@1
   324
				if (prop->type == P_DEFAULT)
yann@1
   325
					prop_warn(prop, "defaults for choice "
yann@1
   326
					    "values not supported");
yann@1
   327
			}
yann@1
   328
			current_entry = menu;
yann@1
   329
			menu_set_type(sym->type);
yann@1
   330
			menu_add_symbol(P_CHOICE, sym, NULL);
yann@1
   331
			prop = sym_get_choice_prop(sym);
yann@1
   332
			for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
yann@1
   333
				;
yann@1
   334
			*ep = expr_alloc_one(E_CHOICE, NULL);
yann@1
   335
			(*ep)->right.sym = menu->sym;
yann@1
   336
		}
yann@1
   337
		if (menu->list && (!menu->prompt || !menu->prompt->text)) {
yann@1
   338
			for (last_menu = menu->list; ; last_menu = last_menu->next) {
yann@1
   339
				last_menu->parent = parent;
yann@1
   340
				if (!last_menu->next)
yann@1
   341
					break;
yann@1
   342
			}
yann@1
   343
			last_menu->next = menu->next;
yann@1
   344
			menu->next = menu->list;
yann@1
   345
			menu->list = NULL;
yann@1
   346
		}
yann@1
   347
	}
yann@1
   348
yann@1
   349
	if (sym && !(sym->flags & SYMBOL_WARNED)) {
yann@1
   350
		if (sym->type == S_UNKNOWN)
yann@1
   351
			menu_warn(parent, "config symbol defined without type");
yann@1
   352
yann@1
   353
		if (sym_is_choice(sym) && !parent->prompt)
yann@1
   354
			menu_warn(parent, "choice must have a prompt");
yann@1
   355
yann@1
   356
		/* Check properties connected to this symbol */
yann@1
   357
		sym_check_prop(sym);
yann@1
   358
		sym->flags |= SYMBOL_WARNED;
yann@1
   359
	}
yann@1
   360
yann@1
   361
	if (sym && !sym_is_optional(sym) && parent->prompt) {
yann@1
   362
		sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
yann@1
   363
				expr_alloc_and(parent->prompt->visible.expr,
yann@1
   364
					expr_alloc_symbol(&symbol_mod)));
yann@1
   365
	}
yann@1
   366
}
yann@1
   367
yann@1
   368
bool menu_is_visible(struct menu *menu)
yann@1
   369
{
yann@1
   370
	struct menu *child;
yann@1
   371
	struct symbol *sym;
yann@1
   372
	tristate visible;
yann@1
   373
yann@1
   374
	if (!menu->prompt)
yann@1
   375
		return false;
yann@1
   376
	sym = menu->sym;
yann@1
   377
	if (sym) {
yann@1
   378
		sym_calc_value(sym);
yann@1
   379
		visible = menu->prompt->visible.tri;
yann@1
   380
	} else
yann@1
   381
		visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
yann@1
   382
yann@1
   383
	if (visible != no)
yann@1
   384
		return true;
yann@1
   385
	if (!sym || sym_get_tristate_value(menu->sym) == no)
yann@1
   386
		return false;
yann@1
   387
yann@1
   388
	for (child = menu->list; child; child = child->next)
yann@1
   389
		if (menu_is_visible(child))
yann@1
   390
			return true;
yann@1
   391
	return false;
yann@1
   392
}
yann@1
   393
yann@1
   394
const char *menu_get_prompt(struct menu *menu)
yann@1
   395
{
yann@1
   396
	if (menu->prompt)
yann@1
   397
		return _(menu->prompt->text);
yann@1
   398
	else if (menu->sym)
yann@1
   399
		return _(menu->sym->name);
yann@1
   400
	return NULL;
yann@1
   401
}
yann@1
   402
yann@1
   403
struct menu *menu_get_root_menu(struct menu *menu)
yann@1
   404
{
yann@1
   405
	return &rootmenu;
yann@1
   406
}
yann@1
   407
yann@1
   408
struct menu *menu_get_parent_menu(struct menu *menu)
yann@1
   409
{
yann@1
   410
	enum prop_type type;
yann@1
   411
yann@1
   412
	for (; menu != &rootmenu; menu = menu->parent) {
yann@1
   413
		type = menu->prompt ? menu->prompt->type : 0;
yann@1
   414
		if (type == P_MENU)
yann@1
   415
			break;
yann@1
   416
	}
yann@1
   417
	return menu;
yann@1
   418
}
yann@1
   419