kconfig/menu.c
author "Yann E. MORIN" <yann.morin.1998@free.fr>
Sun May 05 00:01:05 2013 +0200 (2013-05-05)
changeset 3218 3709e61ad85b
parent 2451 d83221161129
permissions -rw-r--r--
complibs/cloog: add support for the ISL backend

CLooG 0.18+ will use ISL instead of PPL, so we have to configure
adequately depending of which backend is in use.

The Kconfig entries will decide for us which is selected, so we
can rely on either PPL xor ISL to be selected, not both.

Reported-by: "Plotnikov Dmitry" <leitz@ispras.ru>
[Dmitry did a preliminray patch to add ISL support,
which this patch is inspired from]
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
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@2448
    12
static const char nohelp_text[] = N_(
yann@2448
    13
	"There is no help available for this option.\n");
yann@2448
    14
yann@1
    15
struct menu rootmenu;
yann@1
    16
static struct menu **last_entry_ptr;
yann@1
    17
yann@1
    18
struct file *file_list;
yann@1
    19
struct file *current_file;
yann@1
    20
yann@943
    21
void menu_warn(struct menu *menu, const char *fmt, ...)
yann@1
    22
{
yann@1
    23
	va_list ap;
yann@1
    24
	va_start(ap, fmt);
yann@1
    25
	fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
yann@1
    26
	vfprintf(stderr, fmt, ap);
yann@1
    27
	fprintf(stderr, "\n");
yann@1
    28
	va_end(ap);
yann@1
    29
}
yann@1
    30
yann@1
    31
static void prop_warn(struct property *prop, const char *fmt, ...)
yann@1
    32
{
yann@1
    33
	va_list ap;
yann@1
    34
	va_start(ap, fmt);
yann@1
    35
	fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
yann@1
    36
	vfprintf(stderr, fmt, ap);
yann@1
    37
	fprintf(stderr, "\n");
yann@1
    38
	va_end(ap);
yann@1
    39
}
yann@1
    40
yann@2448
    41
void _menu_init(void)
yann@1
    42
{
yann@1
    43
	current_entry = current_menu = &rootmenu;
yann@1
    44
	last_entry_ptr = &rootmenu.list;
yann@1
    45
}
yann@1
    46
yann@1
    47
void menu_add_entry(struct symbol *sym)
yann@1
    48
{
yann@1
    49
	struct menu *menu;
yann@1
    50
yann@1
    51
	menu = malloc(sizeof(*menu));
yann@1
    52
	memset(menu, 0, sizeof(*menu));
yann@1
    53
	menu->sym = sym;
yann@1
    54
	menu->parent = current_menu;
yann@1
    55
	menu->file = current_file;
yann@1
    56
	menu->lineno = zconf_lineno();
yann@1
    57
yann@1
    58
	*last_entry_ptr = menu;
yann@1
    59
	last_entry_ptr = &menu->next;
yann@1
    60
	current_entry = menu;
yann@2448
    61
	if (sym)
yann@2448
    62
		menu_add_symbol(P_SYMBOL, sym, NULL);
yann@1
    63
}
yann@1
    64
yann@1
    65
void menu_end_entry(void)
yann@1
    66
{
yann@1
    67
}
yann@1
    68
yann@1
    69
struct menu *menu_add_menu(void)
yann@1
    70
{
yann@1
    71
	menu_end_entry();
yann@1
    72
	last_entry_ptr = &current_entry->list;
yann@1
    73
	return current_menu = current_entry;
yann@1
    74
}
yann@1
    75
yann@1
    76
void menu_end_menu(void)
yann@1
    77
{
yann@1
    78
	last_entry_ptr = &current_menu->next;
yann@1
    79
	current_menu = current_menu->parent;
yann@1
    80
}
yann@1
    81
yann@2448
    82
static struct expr *menu_check_dep(struct expr *e)
yann@1
    83
{
yann@1
    84
	if (!e)
yann@1
    85
		return e;
yann@1
    86
yann@1
    87
	switch (e->type) {
yann@1
    88
	case E_NOT:
yann@1
    89
		e->left.expr = menu_check_dep(e->left.expr);
yann@1
    90
		break;
yann@1
    91
	case E_OR:
yann@1
    92
	case E_AND:
yann@1
    93
		e->left.expr = menu_check_dep(e->left.expr);
yann@1
    94
		e->right.expr = menu_check_dep(e->right.expr);
yann@1
    95
		break;
yann@1
    96
	case E_SYMBOL:
yann@1
    97
		/* change 'm' into 'm' && MODULES */
yann@1
    98
		if (e->left.sym == &symbol_mod)
yann@1
    99
			return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
yann@1
   100
		break;
yann@1
   101
	default:
yann@1
   102
		break;
yann@1
   103
	}
yann@1
   104
	return e;
yann@1
   105
}
yann@1
   106
yann@1
   107
void menu_add_dep(struct expr *dep)
yann@1
   108
{
yann@1
   109
	current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
yann@1
   110
}
yann@1
   111
yann@1
   112
void menu_set_type(int type)
yann@1
   113
{
yann@1
   114
	struct symbol *sym = current_entry->sym;
yann@1
   115
yann@1
   116
	if (sym->type == type)
yann@1
   117
		return;
yann@1
   118
	if (sym->type == S_UNKNOWN) {
yann@1
   119
		sym->type = type;
yann@1
   120
		return;
yann@1
   121
	}
yann@1
   122
	menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
yann@1
   123
	    sym->name ? sym->name : "<choice>",
yann@1
   124
	    sym_type_name(sym->type), sym_type_name(type));
yann@1
   125
}
yann@1
   126
yann@1
   127
struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
yann@1
   128
{
yann@1
   129
	struct property *prop = prop_alloc(type, current_entry->sym);
yann@1
   130
yann@1
   131
	prop->menu = current_entry;
yann@1
   132
	prop->expr = expr;
yann@1
   133
	prop->visible.expr = menu_check_dep(dep);
yann@1
   134
yann@1
   135
	if (prompt) {
yann@2450
   136
		/* For crostool-NG, a leading pipe followed with spaces
yann@2450
   137
		 * means that pipe shall be removed, and the spaces should
yann@2450
   138
		 * not be trimmed.
yann@2450
   139
		 */
yann@2450
   140
		if (*prompt == '|')
yann@2450
   141
			prompt++;
yann@2450
   142
		else if (isspace(*prompt)) {
yann@2448
   143
			prop_warn(prop, "leading whitespace ignored");
yann@1
   144
			while (isspace(*prompt))
yann@1
   145
				prompt++;
yann@1
   146
		}
yann@2448
   147
		if (current_entry->prompt && current_entry != &rootmenu)
yann@1
   148
			prop_warn(prop, "prompt redefined");
yann@2448
   149
yann@2448
   150
		/* Apply all upper menus' visibilities to actual prompts. */
yann@2448
   151
		if(type == P_PROMPT) {
yann@2448
   152
			struct menu *menu = current_entry;
yann@2448
   153
yann@2448
   154
			while ((menu = menu->parent) != NULL) {
yann@2448
   155
				if (!menu->visibility)
yann@2448
   156
					continue;
yann@2448
   157
				prop->visible.expr
yann@2448
   158
					= expr_alloc_and(prop->visible.expr,
yann@2448
   159
							 menu->visibility);
yann@2448
   160
			}
yann@2448
   161
		}
yann@2448
   162
yann@1
   163
		current_entry->prompt = prop;
yann@1
   164
	}
yann@1
   165
	prop->text = prompt;
yann@1
   166
yann@1
   167
	return prop;
yann@1
   168
}
yann@1
   169
yann@1
   170
struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
yann@1
   171
{
yann@1
   172
	return menu_add_prop(type, prompt, NULL, dep);
yann@1
   173
}
yann@1
   174
yann@2448
   175
void menu_add_visibility(struct expr *expr)
yann@2448
   176
{
yann@2448
   177
	current_entry->visibility = expr_alloc_and(current_entry->visibility,
yann@2448
   178
	    expr);
yann@2448
   179
}
yann@2448
   180
yann@1
   181
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
yann@1
   182
{
yann@1
   183
	menu_add_prop(type, NULL, expr, dep);
yann@1
   184
}
yann@1
   185
yann@1
   186
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
yann@1
   187
{
yann@1
   188
	menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
yann@1
   189
}
yann@1
   190
yann@1
   191
void menu_add_option(int token, char *arg)
yann@1
   192
{
yann@1
   193
	struct property *prop;
yann@1
   194
yann@1
   195
	switch (token) {
yann@1
   196
	case T_OPT_MODULES:
yann@1
   197
		prop = prop_alloc(P_DEFAULT, modules_sym);
yann@1
   198
		prop->expr = expr_alloc_symbol(current_entry->sym);
yann@1
   199
		break;
yann@1
   200
	case T_OPT_DEFCONFIG_LIST:
yann@1
   201
		if (!sym_defconfig_list)
yann@1
   202
			sym_defconfig_list = current_entry->sym;
yann@1
   203
		else if (sym_defconfig_list != current_entry->sym)
yann@1
   204
			zconf_error("trying to redefine defconfig symbol");
yann@1
   205
		break;
yann@943
   206
	case T_OPT_ENV:
yann@943
   207
		prop_add_env(arg);
yann@943
   208
		break;
yann@1
   209
	}
yann@1
   210
}
yann@1
   211
yann@2448
   212
static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
yann@1
   213
{
yann@1
   214
	return sym2->type == S_INT || sym2->type == S_HEX ||
yann@1
   215
	       (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
yann@1
   216
}
yann@1
   217
yann@2448
   218
static void sym_check_prop(struct symbol *sym)
yann@1
   219
{
yann@1
   220
	struct property *prop;
yann@1
   221
	struct symbol *sym2;
yann@1
   222
	for (prop = sym->prop; prop; prop = prop->next) {
yann@1
   223
		switch (prop->type) {
yann@1
   224
		case P_DEFAULT:
yann@1
   225
			if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
yann@1
   226
			    prop->expr->type != E_SYMBOL)
yann@1
   227
				prop_warn(prop,
yann@2448
   228
				    "default for config symbol '%s'"
yann@1
   229
				    " must be a single symbol", sym->name);
yann@2448
   230
			if (prop->expr->type != E_SYMBOL)
yann@2448
   231
				break;
yann@2448
   232
			sym2 = prop_get_symbol(prop);
yann@2448
   233
			if (sym->type == S_HEX || sym->type == S_INT) {
yann@2448
   234
				if (!menu_validate_number(sym, sym2))
yann@2448
   235
					prop_warn(prop,
yann@2448
   236
					    "'%s': number is invalid",
yann@2448
   237
					    sym->name);
yann@2448
   238
			}
yann@1
   239
			break;
yann@1
   240
		case P_SELECT:
yann@1
   241
			sym2 = prop_get_symbol(prop);
yann@1
   242
			if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
yann@1
   243
				prop_warn(prop,
yann@1
   244
				    "config symbol '%s' uses select, but is "
yann@1
   245
				    "not boolean or tristate", sym->name);
yann@943
   246
			else if (sym2->type != S_UNKNOWN &&
yann@943
   247
			         sym2->type != S_BOOLEAN &&
yann@943
   248
			         sym2->type != S_TRISTATE)
yann@1
   249
				prop_warn(prop,
yann@1
   250
				    "'%s' has wrong type. 'select' only "
yann@1
   251
				    "accept arguments of boolean and "
yann@1
   252
				    "tristate type", sym2->name);
yann@1
   253
			break;
yann@1
   254
		case P_RANGE:
yann@1
   255
			if (sym->type != S_INT && sym->type != S_HEX)
yann@1
   256
				prop_warn(prop, "range is only allowed "
yann@1
   257
				                "for int or hex symbols");
yann@2448
   258
			if (!menu_validate_number(sym, prop->expr->left.sym) ||
yann@2448
   259
			    !menu_validate_number(sym, prop->expr->right.sym))
yann@1
   260
				prop_warn(prop, "range is invalid");
yann@1
   261
			break;
yann@1
   262
		default:
yann@1
   263
			;
yann@1
   264
		}
yann@1
   265
	}
yann@1
   266
}
yann@1
   267
yann@1
   268
void menu_finalize(struct menu *parent)
yann@1
   269
{
yann@1
   270
	struct menu *menu, *last_menu;
yann@1
   271
	struct symbol *sym;
yann@1
   272
	struct property *prop;
yann@1
   273
	struct expr *parentdep, *basedep, *dep, *dep2, **ep;
yann@1
   274
yann@1
   275
	sym = parent->sym;
yann@1
   276
	if (parent->list) {
yann@1
   277
		if (sym && sym_is_choice(sym)) {
yann@943
   278
			if (sym->type == S_UNKNOWN) {
yann@943
   279
				/* find the first choice value to find out choice type */
yann@943
   280
				current_entry = parent;
yann@943
   281
				for (menu = parent->list; menu; menu = menu->next) {
yann@943
   282
					if (menu->sym && menu->sym->type != S_UNKNOWN) {
yann@943
   283
						menu_set_type(menu->sym->type);
yann@943
   284
						break;
yann@943
   285
					}
yann@943
   286
				}
yann@943
   287
			}
yann@2451
   288
			if (parent->prompt &&
yann@2451
   289
			    !expr_is_yes(parent->prompt->visible.expr)) {
yann@2451
   290
				parent->visibility = expr_alloc_and (parent->visibility,
yann@2451
   291
								     parent->prompt->visible.expr);
yann@2451
   292
			}
yann@943
   293
			/* set the type of the remaining choice values */
yann@1
   294
			for (menu = parent->list; menu; menu = menu->next) {
yann@943
   295
				current_entry = menu;
yann@943
   296
				if (menu->sym && menu->sym->type == S_UNKNOWN)
yann@1
   297
					menu_set_type(sym->type);
yann@1
   298
			}
yann@1
   299
			parentdep = expr_alloc_symbol(sym);
yann@1
   300
		} else if (parent->prompt)
yann@1
   301
			parentdep = parent->prompt->visible.expr;
yann@1
   302
		else
yann@1
   303
			parentdep = parent->dep;
yann@1
   304
yann@1
   305
		for (menu = parent->list; menu; menu = menu->next) {
yann@1
   306
			basedep = expr_transform(menu->dep);
yann@1
   307
			basedep = expr_alloc_and(expr_copy(parentdep), basedep);
yann@1
   308
			basedep = expr_eliminate_dups(basedep);
yann@1
   309
			menu->dep = basedep;
yann@1
   310
			if (menu->sym)
yann@1
   311
				prop = menu->sym->prop;
yann@1
   312
			else
yann@1
   313
				prop = menu->prompt;
yann@1
   314
			for (; prop; prop = prop->next) {
yann@1
   315
				if (prop->menu != menu)
yann@1
   316
					continue;
yann@1
   317
				dep = expr_transform(prop->visible.expr);
yann@1
   318
				dep = expr_alloc_and(expr_copy(basedep), dep);
yann@1
   319
				dep = expr_eliminate_dups(dep);
yann@1
   320
				if (menu->sym && menu->sym->type != S_TRISTATE)
yann@1
   321
					dep = expr_trans_bool(dep);
yann@1
   322
				prop->visible.expr = dep;
yann@1
   323
				if (prop->type == P_SELECT) {
yann@1
   324
					struct symbol *es = prop_get_symbol(prop);
yann@1
   325
					es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
yann@1
   326
							expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
yann@1
   327
				}
yann@1
   328
			}
yann@1
   329
		}
yann@1
   330
		for (menu = parent->list; menu; menu = menu->next)
yann@1
   331
			menu_finalize(menu);
yann@1
   332
	} else if (sym) {
yann@1
   333
		basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
yann@1
   334
		basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
yann@1
   335
		basedep = expr_eliminate_dups(expr_transform(basedep));
yann@1
   336
		last_menu = NULL;
yann@1
   337
		for (menu = parent->next; menu; menu = menu->next) {
yann@1
   338
			dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
yann@1
   339
			if (!expr_contains_symbol(dep, sym))
yann@1
   340
				break;
yann@1
   341
			if (expr_depends_symbol(dep, sym))
yann@1
   342
				goto next;
yann@1
   343
			dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
yann@1
   344
			dep = expr_eliminate_dups(expr_transform(dep));
yann@1
   345
			dep2 = expr_copy(basedep);
yann@1
   346
			expr_eliminate_eq(&dep, &dep2);
yann@1
   347
			expr_free(dep);
yann@1
   348
			if (!expr_is_yes(dep2)) {
yann@1
   349
				expr_free(dep2);
yann@1
   350
				break;
yann@1
   351
			}
yann@1
   352
			expr_free(dep2);
yann@1
   353
		next:
yann@1
   354
			menu_finalize(menu);
yann@1
   355
			menu->parent = parent;
yann@1
   356
			last_menu = menu;
yann@1
   357
		}
yann@1
   358
		if (last_menu) {
yann@1
   359
			parent->list = parent->next;
yann@1
   360
			parent->next = last_menu->next;
yann@1
   361
			last_menu->next = NULL;
yann@1
   362
		}
yann@2448
   363
yann@2474
   364
		sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep);
yann@1
   365
	}
yann@1
   366
	for (menu = parent->list; menu; menu = menu->next) {
yann@943
   367
		if (sym && sym_is_choice(sym) &&
yann@943
   368
		    menu->sym && !sym_is_choice_value(menu->sym)) {
yann@943
   369
			current_entry = menu;
yann@1
   370
			menu->sym->flags |= SYMBOL_CHOICEVAL;
yann@1
   371
			if (!menu->prompt)
yann@1
   372
				menu_warn(menu, "choice value must have a prompt");
yann@1
   373
			for (prop = menu->sym->prop; prop; prop = prop->next) {
yann@1
   374
				if (prop->type == P_DEFAULT)
yann@1
   375
					prop_warn(prop, "defaults for choice "
yann@943
   376
						  "values not supported");
yann@943
   377
				if (prop->menu == menu)
yann@943
   378
					continue;
yann@943
   379
				if (prop->type == P_PROMPT &&
yann@943
   380
				    prop->menu->parent->sym != sym)
yann@943
   381
					prop_warn(prop, "choice value used outside its choice group");
yann@1
   382
			}
yann@943
   383
			/* Non-tristate choice values of tristate choices must
yann@943
   384
			 * depend on the choice being set to Y. The choice
yann@943
   385
			 * values' dependencies were propagated to their
yann@943
   386
			 * properties above, so the change here must be re-
yann@943
   387
			 * propagated.
yann@943
   388
			 */
yann@943
   389
			if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {
yann@943
   390
				basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);
yann@943
   391
				menu->dep = expr_alloc_and(basedep, menu->dep);
yann@943
   392
				for (prop = menu->sym->prop; prop; prop = prop->next) {
yann@943
   393
					if (prop->menu != menu)
yann@943
   394
						continue;
yann@943
   395
					prop->visible.expr = expr_alloc_and(expr_copy(basedep),
yann@943
   396
									    prop->visible.expr);
yann@943
   397
				}
yann@943
   398
			}
yann@1
   399
			menu_add_symbol(P_CHOICE, sym, NULL);
yann@1
   400
			prop = sym_get_choice_prop(sym);
yann@1
   401
			for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
yann@1
   402
				;
yann@943
   403
			*ep = expr_alloc_one(E_LIST, NULL);
yann@1
   404
			(*ep)->right.sym = menu->sym;
yann@1
   405
		}
yann@1
   406
		if (menu->list && (!menu->prompt || !menu->prompt->text)) {
yann@1
   407
			for (last_menu = menu->list; ; last_menu = last_menu->next) {
yann@1
   408
				last_menu->parent = parent;
yann@1
   409
				if (!last_menu->next)
yann@1
   410
					break;
yann@1
   411
			}
yann@1
   412
			last_menu->next = menu->next;
yann@1
   413
			menu->next = menu->list;
yann@1
   414
			menu->list = NULL;
yann@1
   415
		}
yann@1
   416
	}
yann@1
   417
yann@1
   418
	if (sym && !(sym->flags & SYMBOL_WARNED)) {
yann@1
   419
		if (sym->type == S_UNKNOWN)
yann@1
   420
			menu_warn(parent, "config symbol defined without type");
yann@1
   421
yann@1
   422
		if (sym_is_choice(sym) && !parent->prompt)
yann@1
   423
			menu_warn(parent, "choice must have a prompt");
yann@1
   424
yann@1
   425
		/* Check properties connected to this symbol */
yann@1
   426
		sym_check_prop(sym);
yann@1
   427
		sym->flags |= SYMBOL_WARNED;
yann@1
   428
	}
yann@1
   429
yann@1
   430
	if (sym && !sym_is_optional(sym) && parent->prompt) {
yann@1
   431
		sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
yann@1
   432
				expr_alloc_and(parent->prompt->visible.expr,
yann@1
   433
					expr_alloc_symbol(&symbol_mod)));
yann@1
   434
	}
yann@1
   435
}
yann@1
   436
yann@2448
   437
bool menu_has_prompt(struct menu *menu)
yann@2448
   438
{
yann@2448
   439
	if (!menu->prompt)
yann@2448
   440
		return false;
yann@2448
   441
	return true;
yann@2448
   442
}
yann@2448
   443
yann@1
   444
bool menu_is_visible(struct menu *menu)
yann@1
   445
{
yann@1
   446
	struct menu *child;
yann@1
   447
	struct symbol *sym;
yann@1
   448
	tristate visible;
yann@1
   449
yann@1
   450
	if (!menu->prompt)
yann@1
   451
		return false;
yann@2448
   452
yann@2448
   453
	if (menu->visibility) {
yann@2448
   454
		if (expr_calc_value(menu->visibility) == no)
yann@2448
   455
			return no;
yann@2448
   456
	}
yann@2448
   457
yann@1
   458
	sym = menu->sym;
yann@1
   459
	if (sym) {
yann@1
   460
		sym_calc_value(sym);
yann@1
   461
		visible = menu->prompt->visible.tri;
yann@1
   462
	} else
yann@1
   463
		visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
yann@1
   464
yann@1
   465
	if (visible != no)
yann@1
   466
		return true;
yann@2448
   467
yann@1
   468
	if (!sym || sym_get_tristate_value(menu->sym) == no)
yann@1
   469
		return false;
yann@1
   470
yann@2448
   471
	for (child = menu->list; child; child = child->next) {
yann@2448
   472
		if (menu_is_visible(child)) {
yann@2448
   473
			if (sym)
yann@2448
   474
				sym->flags |= SYMBOL_DEF_USER;
yann@1
   475
			return true;
yann@2448
   476
		}
yann@2448
   477
	}
yann@2448
   478
yann@1
   479
	return false;
yann@1
   480
}
yann@1
   481
yann@1
   482
const char *menu_get_prompt(struct menu *menu)
yann@1
   483
{
yann@1
   484
	if (menu->prompt)
yann@943
   485
		return menu->prompt->text;
yann@1
   486
	else if (menu->sym)
yann@943
   487
		return menu->sym->name;
yann@1
   488
	return NULL;
yann@1
   489
}
yann@1
   490
yann@1
   491
struct menu *menu_get_root_menu(struct menu *menu)
yann@1
   492
{
yann@1
   493
	return &rootmenu;
yann@1
   494
}
yann@1
   495
yann@1
   496
struct menu *menu_get_parent_menu(struct menu *menu)
yann@1
   497
{
yann@1
   498
	enum prop_type type;
yann@1
   499
yann@1
   500
	for (; menu != &rootmenu; menu = menu->parent) {
yann@1
   501
		type = menu->prompt ? menu->prompt->type : 0;
yann@1
   502
		if (type == P_MENU)
yann@1
   503
			break;
yann@1
   504
	}
yann@1
   505
	return menu;
yann@1
   506
}
yann@1
   507
yann@943
   508
bool menu_has_help(struct menu *menu)
yann@943
   509
{
yann@943
   510
	return menu->help != NULL;
yann@943
   511
}
yann@943
   512
yann@943
   513
const char *menu_get_help(struct menu *menu)
yann@943
   514
{
yann@943
   515
	if (menu->help)
yann@943
   516
		return menu->help;
yann@943
   517
	else
yann@943
   518
		return "";
yann@943
   519
}
yann@2448
   520
yann@2448
   521
static void get_prompt_str(struct gstr *r, struct property *prop)
yann@2448
   522
{
yann@2448
   523
	int i, j;
yann@2448
   524
	struct menu *submenu[8], *menu;
yann@2448
   525
yann@2448
   526
	str_printf(r, _("Prompt: %s\n"), _(prop->text));
yann@2448
   527
	str_printf(r, _("  Defined at %s:%d\n"), prop->menu->file->name,
yann@2448
   528
		prop->menu->lineno);
yann@2448
   529
	if (!expr_is_yes(prop->visible.expr)) {
yann@2448
   530
		str_append(r, _("  Depends on: "));
yann@2448
   531
		expr_gstr_print(prop->visible.expr, r);
yann@2448
   532
		str_append(r, "\n");
yann@2448
   533
	}
yann@2448
   534
	menu = prop->menu->parent;
yann@2448
   535
	for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
yann@2448
   536
		submenu[i++] = menu;
yann@2448
   537
	if (i > 0) {
yann@2448
   538
		str_printf(r, _("  Location:\n"));
yann@2448
   539
		for (j = 4; --i >= 0; j += 2) {
yann@2448
   540
			menu = submenu[i];
yann@2448
   541
			str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu)));
yann@2448
   542
			if (menu->sym) {
yann@2448
   543
				str_printf(r, " (%s [=%s])", menu->sym->name ?
yann@2448
   544
					menu->sym->name : _("<choice>"),
yann@2448
   545
					sym_get_string_value(menu->sym));
yann@2448
   546
			}
yann@2448
   547
			str_append(r, "\n");
yann@2448
   548
		}
yann@2448
   549
	}
yann@2448
   550
}
yann@2448
   551
yann@2448
   552
void get_symbol_str(struct gstr *r, struct symbol *sym)
yann@2448
   553
{
yann@2448
   554
	bool hit;
yann@2448
   555
	struct property *prop;
yann@2448
   556
yann@2448
   557
	if (sym && sym->name) {
yann@2448
   558
		str_printf(r, "Symbol: %s [=%s]\n", sym->name,
yann@2448
   559
			   sym_get_string_value(sym));
yann@2448
   560
		str_printf(r, "Type  : %s\n", sym_type_name(sym->type));
yann@2448
   561
		if (sym->type == S_INT || sym->type == S_HEX) {
yann@2448
   562
			prop = sym_get_range_prop(sym);
yann@2448
   563
			if (prop) {
yann@2448
   564
				str_printf(r, "Range : ");
yann@2448
   565
				expr_gstr_print(prop->expr, r);
yann@2448
   566
				str_append(r, "\n");
yann@2448
   567
			}
yann@2448
   568
		}
yann@2448
   569
	}
yann@2448
   570
	for_all_prompts(sym, prop)
yann@2448
   571
		get_prompt_str(r, prop);
yann@2448
   572
	hit = false;
yann@2448
   573
	for_all_properties(sym, prop, P_SELECT) {
yann@2448
   574
		if (!hit) {
yann@2448
   575
			str_append(r, "  Selects: ");
yann@2448
   576
			hit = true;
yann@2448
   577
		} else
yann@2448
   578
			str_printf(r, " && ");
yann@2448
   579
		expr_gstr_print(prop->expr, r);
yann@2448
   580
	}
yann@2448
   581
	if (hit)
yann@2448
   582
		str_append(r, "\n");
yann@2448
   583
	if (sym->rev_dep.expr) {
yann@2448
   584
		str_append(r, _("  Selected by: "));
yann@2448
   585
		expr_gstr_print(sym->rev_dep.expr, r);
yann@2448
   586
		str_append(r, "\n");
yann@2448
   587
	}
yann@2448
   588
	str_append(r, "\n\n");
yann@2448
   589
}
yann@2448
   590
yann@2448
   591
struct gstr get_relations_str(struct symbol **sym_arr)
yann@2448
   592
{
yann@2448
   593
	struct symbol *sym;
yann@2448
   594
	struct gstr res = str_new();
yann@2448
   595
	int i;
yann@2448
   596
yann@2448
   597
	for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
yann@2448
   598
		get_symbol_str(&res, sym);
yann@2448
   599
	if (!i)
yann@2448
   600
		str_append(&res, _("No matches found.\n"));
yann@2448
   601
	return res;
yann@2448
   602
}
yann@2448
   603
yann@2448
   604
yann@2448
   605
void menu_get_ext_help(struct menu *menu, struct gstr *help)
yann@2448
   606
{
yann@2448
   607
	struct symbol *sym = menu->sym;
yann@2448
   608
yann@2448
   609
	if (menu_has_help(menu)) {
yann@2448
   610
		if (sym->name) {
yann@2448
   611
			str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
yann@2448
   612
			str_append(help, _(menu_get_help(menu)));
yann@2448
   613
			str_append(help, "\n");
yann@2448
   614
		}
yann@2448
   615
	} else {
yann@2448
   616
		str_append(help, nohelp_text);
yann@2448
   617
	}
yann@2448
   618
	if (sym)
yann@2448
   619
		get_symbol_str(help, sym);
yann@2448
   620
}