kconfig/symbol.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
parent 1 eeea35fbf182
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 <ctype.h>
yann@1
     7
#include <stdlib.h>
yann@1
     8
#include <string.h>
yann@1
     9
#include <regex.h>
yann@1
    10
#include <sys/utsname.h>
yann@1
    11
yann@1
    12
#define LKC_DIRECT_LINK
yann@1
    13
#include "lkc.h"
yann@1
    14
yann@1
    15
struct symbol symbol_yes = {
yann@1
    16
	.name = "y",
yann@1
    17
	.curr = { "y", yes },
yann@1
    18
	.flags = SYMBOL_CONST|SYMBOL_VALID,
yann@1
    19
}, symbol_mod = {
yann@1
    20
	.name = "m",
yann@1
    21
	.curr = { "m", mod },
yann@1
    22
	.flags = SYMBOL_CONST|SYMBOL_VALID,
yann@1
    23
}, symbol_no = {
yann@1
    24
	.name = "n",
yann@1
    25
	.curr = { "n", no },
yann@1
    26
	.flags = SYMBOL_CONST|SYMBOL_VALID,
yann@1
    27
}, symbol_empty = {
yann@1
    28
	.name = "",
yann@1
    29
	.curr = { "", no },
yann@1
    30
	.flags = SYMBOL_VALID,
yann@1
    31
};
yann@1
    32
yann@1
    33
struct symbol *sym_defconfig_list;
yann@1
    34
struct symbol *modules_sym;
yann@1
    35
tristate modules_val;
yann@1
    36
yann@1
    37
void sym_add_default(struct symbol *sym, const char *def)
yann@1
    38
{
yann@1
    39
	struct property *prop = prop_alloc(P_DEFAULT, sym);
yann@1
    40
yann@1
    41
	prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
yann@1
    42
}
yann@1
    43
yann@1
    44
void sym_init(void)
yann@1
    45
{
yann@1
    46
	struct symbol *sym;
yann@1
    47
	struct utsname uts;
yann@1
    48
	char *p;
yann@1
    49
	static bool inited = false;
yann@1
    50
yann@1
    51
	if (inited)
yann@1
    52
		return;
yann@1
    53
	inited = true;
yann@1
    54
yann@1
    55
	uname(&uts);
yann@1
    56
yann@1
    57
	sym = sym_lookup("ARCH", 0);
yann@1
    58
	sym->type = S_STRING;
yann@1
    59
	sym->flags |= SYMBOL_AUTO;
yann@1
    60
	p = getenv("ARCH");
yann@1
    61
	if (p)
yann@1
    62
		sym_add_default(sym, p);
yann@1
    63
yann@1
    64
	sym = sym_lookup("PROJECTVERSION", 0);
yann@1
    65
	sym->type = S_STRING;
yann@1
    66
	sym->flags |= SYMBOL_AUTO;
yann@1
    67
	p = getenv("PROJECTVERSION");
yann@1
    68
	if (p)
yann@1
    69
		sym_add_default(sym, p);
yann@1
    70
yann@1
    71
	sym = sym_lookup("UNAME_RELEASE", 0);
yann@1
    72
	sym->type = S_STRING;
yann@1
    73
	sym->flags |= SYMBOL_AUTO;
yann@1
    74
	sym_add_default(sym, uts.release);
yann@1
    75
}
yann@1
    76
yann@1
    77
enum symbol_type sym_get_type(struct symbol *sym)
yann@1
    78
{
yann@1
    79
	enum symbol_type type = sym->type;
yann@1
    80
yann@1
    81
	if (type == S_TRISTATE) {
yann@1
    82
		if (sym_is_choice_value(sym) && sym->visible == yes)
yann@1
    83
			type = S_BOOLEAN;
yann@1
    84
		else if (modules_val == no)
yann@1
    85
			type = S_BOOLEAN;
yann@1
    86
	}
yann@1
    87
	return type;
yann@1
    88
}
yann@1
    89
yann@1
    90
const char *sym_type_name(enum symbol_type type)
yann@1
    91
{
yann@1
    92
	switch (type) {
yann@1
    93
	case S_BOOLEAN:
yann@1
    94
		return "boolean";
yann@1
    95
	case S_TRISTATE:
yann@1
    96
		return "tristate";
yann@1
    97
	case S_INT:
yann@1
    98
		return "integer";
yann@1
    99
	case S_HEX:
yann@1
   100
		return "hex";
yann@1
   101
	case S_STRING:
yann@1
   102
		return "string";
yann@1
   103
	case S_UNKNOWN:
yann@1
   104
		return "unknown";
yann@1
   105
	case S_OTHER:
yann@1
   106
		break;
yann@1
   107
	}
yann@1
   108
	return "???";
yann@1
   109
}
yann@1
   110
yann@1
   111
struct property *sym_get_choice_prop(struct symbol *sym)
yann@1
   112
{
yann@1
   113
	struct property *prop;
yann@1
   114
yann@1
   115
	for_all_choices(sym, prop)
yann@1
   116
		return prop;
yann@1
   117
	return NULL;
yann@1
   118
}
yann@1
   119
yann@1
   120
struct property *sym_get_default_prop(struct symbol *sym)
yann@1
   121
{
yann@1
   122
	struct property *prop;
yann@1
   123
yann@1
   124
	for_all_defaults(sym, prop) {
yann@1
   125
		prop->visible.tri = expr_calc_value(prop->visible.expr);
yann@1
   126
		if (prop->visible.tri != no)
yann@1
   127
			return prop;
yann@1
   128
	}
yann@1
   129
	return NULL;
yann@1
   130
}
yann@1
   131
yann@1
   132
struct property *sym_get_range_prop(struct symbol *sym)
yann@1
   133
{
yann@1
   134
	struct property *prop;
yann@1
   135
yann@1
   136
	for_all_properties(sym, prop, P_RANGE) {
yann@1
   137
		prop->visible.tri = expr_calc_value(prop->visible.expr);
yann@1
   138
		if (prop->visible.tri != no)
yann@1
   139
			return prop;
yann@1
   140
	}
yann@1
   141
	return NULL;
yann@1
   142
}
yann@1
   143
yann@1
   144
static int sym_get_range_val(struct symbol *sym, int base)
yann@1
   145
{
yann@1
   146
	sym_calc_value(sym);
yann@1
   147
	switch (sym->type) {
yann@1
   148
	case S_INT:
yann@1
   149
		base = 10;
yann@1
   150
		break;
yann@1
   151
	case S_HEX:
yann@1
   152
		base = 16;
yann@1
   153
		break;
yann@1
   154
	default:
yann@1
   155
		break;
yann@1
   156
	}
yann@1
   157
	return strtol(sym->curr.val, NULL, base);
yann@1
   158
}
yann@1
   159
yann@1
   160
static void sym_validate_range(struct symbol *sym)
yann@1
   161
{
yann@1
   162
	struct property *prop;
yann@1
   163
	int base, val, val2;
yann@1
   164
	char str[64];
yann@1
   165
yann@1
   166
	switch (sym->type) {
yann@1
   167
	case S_INT:
yann@1
   168
		base = 10;
yann@1
   169
		break;
yann@1
   170
	case S_HEX:
yann@1
   171
		base = 16;
yann@1
   172
		break;
yann@1
   173
	default:
yann@1
   174
		return;
yann@1
   175
	}
yann@1
   176
	prop = sym_get_range_prop(sym);
yann@1
   177
	if (!prop)
yann@1
   178
		return;
yann@1
   179
	val = strtol(sym->curr.val, NULL, base);
yann@1
   180
	val2 = sym_get_range_val(prop->expr->left.sym, base);
yann@1
   181
	if (val >= val2) {
yann@1
   182
		val2 = sym_get_range_val(prop->expr->right.sym, base);
yann@1
   183
		if (val <= val2)
yann@1
   184
			return;
yann@1
   185
	}
yann@1
   186
	if (sym->type == S_INT)
yann@1
   187
		sprintf(str, "%d", val2);
yann@1
   188
	else
yann@1
   189
		sprintf(str, "0x%x", val2);
yann@1
   190
	sym->curr.val = strdup(str);
yann@1
   191
}
yann@1
   192
yann@1
   193
static void sym_calc_visibility(struct symbol *sym)
yann@1
   194
{
yann@1
   195
	struct property *prop;
yann@1
   196
	tristate tri;
yann@1
   197
yann@1
   198
	/* any prompt visible? */
yann@1
   199
	tri = no;
yann@1
   200
	for_all_prompts(sym, prop) {
yann@1
   201
		prop->visible.tri = expr_calc_value(prop->visible.expr);
yann@1
   202
		tri = E_OR(tri, prop->visible.tri);
yann@1
   203
	}
yann@1
   204
	if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
yann@1
   205
		tri = yes;
yann@1
   206
	if (sym->visible != tri) {
yann@1
   207
		sym->visible = tri;
yann@1
   208
		sym_set_changed(sym);
yann@1
   209
	}
yann@1
   210
	if (sym_is_choice_value(sym))
yann@1
   211
		return;
yann@1
   212
	tri = no;
yann@1
   213
	if (sym->rev_dep.expr)
yann@1
   214
		tri = expr_calc_value(sym->rev_dep.expr);
yann@1
   215
	if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
yann@1
   216
		tri = yes;
yann@1
   217
	if (sym->rev_dep.tri != tri) {
yann@1
   218
		sym->rev_dep.tri = tri;
yann@1
   219
		sym_set_changed(sym);
yann@1
   220
	}
yann@1
   221
}
yann@1
   222
yann@1
   223
static struct symbol *sym_calc_choice(struct symbol *sym)
yann@1
   224
{
yann@1
   225
	struct symbol *def_sym;
yann@1
   226
	struct property *prop;
yann@1
   227
	struct expr *e;
yann@1
   228
yann@1
   229
	/* is the user choice visible? */
yann@1
   230
	def_sym = sym->def[S_DEF_USER].val;
yann@1
   231
	if (def_sym) {
yann@1
   232
		sym_calc_visibility(def_sym);
yann@1
   233
		if (def_sym->visible != no)
yann@1
   234
			return def_sym;
yann@1
   235
	}
yann@1
   236
yann@1
   237
	/* any of the defaults visible? */
yann@1
   238
	for_all_defaults(sym, prop) {
yann@1
   239
		prop->visible.tri = expr_calc_value(prop->visible.expr);
yann@1
   240
		if (prop->visible.tri == no)
yann@1
   241
			continue;
yann@1
   242
		def_sym = prop_get_symbol(prop);
yann@1
   243
		sym_calc_visibility(def_sym);
yann@1
   244
		if (def_sym->visible != no)
yann@1
   245
			return def_sym;
yann@1
   246
	}
yann@1
   247
yann@1
   248
	/* just get the first visible value */
yann@1
   249
	prop = sym_get_choice_prop(sym);
yann@1
   250
	for (e = prop->expr; e; e = e->left.expr) {
yann@1
   251
		def_sym = e->right.sym;
yann@1
   252
		sym_calc_visibility(def_sym);
yann@1
   253
		if (def_sym->visible != no)
yann@1
   254
			return def_sym;
yann@1
   255
	}
yann@1
   256
yann@1
   257
	/* no choice? reset tristate value */
yann@1
   258
	sym->curr.tri = no;
yann@1
   259
	return NULL;
yann@1
   260
}
yann@1
   261
yann@1
   262
void sym_calc_value(struct symbol *sym)
yann@1
   263
{
yann@1
   264
	struct symbol_value newval, oldval;
yann@1
   265
	struct property *prop;
yann@1
   266
	struct expr *e;
yann@1
   267
yann@1
   268
	if (!sym)
yann@1
   269
		return;
yann@1
   270
yann@1
   271
	if (sym->flags & SYMBOL_VALID)
yann@1
   272
		return;
yann@1
   273
	sym->flags |= SYMBOL_VALID;
yann@1
   274
yann@1
   275
	oldval = sym->curr;
yann@1
   276
yann@1
   277
	switch (sym->type) {
yann@1
   278
	case S_INT:
yann@1
   279
	case S_HEX:
yann@1
   280
	case S_STRING:
yann@1
   281
		newval = symbol_empty.curr;
yann@1
   282
		break;
yann@1
   283
	case S_BOOLEAN:
yann@1
   284
	case S_TRISTATE:
yann@1
   285
		newval = symbol_no.curr;
yann@1
   286
		break;
yann@1
   287
	default:
yann@1
   288
		sym->curr.val = sym->name;
yann@1
   289
		sym->curr.tri = no;
yann@1
   290
		return;
yann@1
   291
	}
yann@1
   292
	if (!sym_is_choice_value(sym))
yann@1
   293
		sym->flags &= ~SYMBOL_WRITE;
yann@1
   294
yann@1
   295
	sym_calc_visibility(sym);
yann@1
   296
yann@1
   297
	/* set default if recursively called */
yann@1
   298
	sym->curr = newval;
yann@1
   299
yann@1
   300
	switch (sym_get_type(sym)) {
yann@1
   301
	case S_BOOLEAN:
yann@1
   302
	case S_TRISTATE:
yann@1
   303
		if (sym_is_choice_value(sym) && sym->visible == yes) {
yann@1
   304
			prop = sym_get_choice_prop(sym);
yann@1
   305
			newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
yann@1
   306
		} else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
yann@1
   307
			sym->flags |= SYMBOL_WRITE;
yann@1
   308
			if (sym_has_value(sym))
yann@1
   309
				newval.tri = sym->def[S_DEF_USER].tri;
yann@1
   310
			else if (!sym_is_choice(sym)) {
yann@1
   311
				prop = sym_get_default_prop(sym);
yann@1
   312
				if (prop)
yann@1
   313
					newval.tri = expr_calc_value(prop->expr);
yann@1
   314
			}
yann@1
   315
			newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
yann@1
   316
		} else if (!sym_is_choice(sym)) {
yann@1
   317
			prop = sym_get_default_prop(sym);
yann@1
   318
			if (prop) {
yann@1
   319
				sym->flags |= SYMBOL_WRITE;
yann@1
   320
				newval.tri = expr_calc_value(prop->expr);
yann@1
   321
			}
yann@1
   322
		}
yann@1
   323
		if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
yann@1
   324
			newval.tri = yes;
yann@1
   325
		break;
yann@1
   326
	case S_STRING:
yann@1
   327
	case S_HEX:
yann@1
   328
	case S_INT:
yann@1
   329
		if (sym->visible != no) {
yann@1
   330
			sym->flags |= SYMBOL_WRITE;
yann@1
   331
			if (sym_has_value(sym)) {
yann@1
   332
				newval.val = sym->def[S_DEF_USER].val;
yann@1
   333
				break;
yann@1
   334
			}
yann@1
   335
		}
yann@1
   336
		prop = sym_get_default_prop(sym);
yann@1
   337
		if (prop) {
yann@1
   338
			struct symbol *ds = prop_get_symbol(prop);
yann@1
   339
			if (ds) {
yann@1
   340
				sym->flags |= SYMBOL_WRITE;
yann@1
   341
				sym_calc_value(ds);
yann@1
   342
				newval.val = ds->curr.val;
yann@1
   343
			}
yann@1
   344
		}
yann@1
   345
		break;
yann@1
   346
	default:
yann@1
   347
		;
yann@1
   348
	}
yann@1
   349
yann@1
   350
	sym->curr = newval;
yann@1
   351
	if (sym_is_choice(sym) && newval.tri == yes)
yann@1
   352
		sym->curr.val = sym_calc_choice(sym);
yann@1
   353
	sym_validate_range(sym);
yann@1
   354
yann@1
   355
	if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
yann@1
   356
		sym_set_changed(sym);
yann@1
   357
		if (modules_sym == sym) {
yann@1
   358
			sym_set_all_changed();
yann@1
   359
			modules_val = modules_sym->curr.tri;
yann@1
   360
		}
yann@1
   361
	}
yann@1
   362
yann@1
   363
	if (sym_is_choice(sym)) {
yann@1
   364
		int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
yann@1
   365
		prop = sym_get_choice_prop(sym);
yann@1
   366
		for (e = prop->expr; e; e = e->left.expr) {
yann@1
   367
			e->right.sym->flags |= flags;
yann@1
   368
			if (flags & SYMBOL_CHANGED)
yann@1
   369
				sym_set_changed(e->right.sym);
yann@1
   370
		}
yann@1
   371
	}
yann@1
   372
}
yann@1
   373
yann@1
   374
void sym_clear_all_valid(void)
yann@1
   375
{
yann@1
   376
	struct symbol *sym;
yann@1
   377
	int i;
yann@1
   378
yann@1
   379
	for_all_symbols(i, sym)
yann@1
   380
		sym->flags &= ~SYMBOL_VALID;
yann@39
   381
	sym_add_change_count(1);
yann@1
   382
	if (modules_sym)
yann@1
   383
		sym_calc_value(modules_sym);
yann@1
   384
}
yann@1
   385
yann@1
   386
void sym_set_changed(struct symbol *sym)
yann@1
   387
{
yann@1
   388
	struct property *prop;
yann@1
   389
yann@1
   390
	sym->flags |= SYMBOL_CHANGED;
yann@1
   391
	for (prop = sym->prop; prop; prop = prop->next) {
yann@1
   392
		if (prop->menu)
yann@1
   393
			prop->menu->flags |= MENU_CHANGED;
yann@1
   394
	}
yann@1
   395
}
yann@1
   396
yann@1
   397
void sym_set_all_changed(void)
yann@1
   398
{
yann@1
   399
	struct symbol *sym;
yann@1
   400
	int i;
yann@1
   401
yann@1
   402
	for_all_symbols(i, sym)
yann@1
   403
		sym_set_changed(sym);
yann@1
   404
}
yann@1
   405
yann@1
   406
bool sym_tristate_within_range(struct symbol *sym, tristate val)
yann@1
   407
{
yann@1
   408
	int type = sym_get_type(sym);
yann@1
   409
yann@1
   410
	if (sym->visible == no)
yann@1
   411
		return false;
yann@1
   412
yann@1
   413
	if (type != S_BOOLEAN && type != S_TRISTATE)
yann@1
   414
		return false;
yann@1
   415
yann@1
   416
	if (type == S_BOOLEAN && val == mod)
yann@1
   417
		return false;
yann@1
   418
	if (sym->visible <= sym->rev_dep.tri)
yann@1
   419
		return false;
yann@1
   420
	if (sym_is_choice_value(sym) && sym->visible == yes)
yann@1
   421
		return val == yes;
yann@1
   422
	return val >= sym->rev_dep.tri && val <= sym->visible;
yann@1
   423
}
yann@1
   424
yann@1
   425
bool sym_set_tristate_value(struct symbol *sym, tristate val)
yann@1
   426
{
yann@1
   427
	tristate oldval = sym_get_tristate_value(sym);
yann@1
   428
yann@1
   429
	if (oldval != val && !sym_tristate_within_range(sym, val))
yann@1
   430
		return false;
yann@1
   431
yann@1
   432
	if (!(sym->flags & SYMBOL_DEF_USER)) {
yann@1
   433
		sym->flags |= SYMBOL_DEF_USER;
yann@1
   434
		sym_set_changed(sym);
yann@1
   435
	}
yann@1
   436
	/*
yann@1
   437
	 * setting a choice value also resets the new flag of the choice
yann@1
   438
	 * symbol and all other choice values.
yann@1
   439
	 */
yann@1
   440
	if (sym_is_choice_value(sym) && val == yes) {
yann@1
   441
		struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
yann@1
   442
		struct property *prop;
yann@1
   443
		struct expr *e;
yann@1
   444
yann@1
   445
		cs->def[S_DEF_USER].val = sym;
yann@1
   446
		cs->flags |= SYMBOL_DEF_USER;
yann@1
   447
		prop = sym_get_choice_prop(cs);
yann@1
   448
		for (e = prop->expr; e; e = e->left.expr) {
yann@1
   449
			if (e->right.sym->visible != no)
yann@1
   450
				e->right.sym->flags |= SYMBOL_DEF_USER;
yann@1
   451
		}
yann@1
   452
	}
yann@1
   453
yann@1
   454
	sym->def[S_DEF_USER].tri = val;
yann@1
   455
	if (oldval != val)
yann@1
   456
		sym_clear_all_valid();
yann@1
   457
yann@1
   458
	return true;
yann@1
   459
}
yann@1
   460
yann@1
   461
tristate sym_toggle_tristate_value(struct symbol *sym)
yann@1
   462
{
yann@1
   463
	tristate oldval, newval;
yann@1
   464
yann@1
   465
	oldval = newval = sym_get_tristate_value(sym);
yann@1
   466
	do {
yann@1
   467
		switch (newval) {
yann@1
   468
		case no:
yann@1
   469
			newval = mod;
yann@1
   470
			break;
yann@1
   471
		case mod:
yann@1
   472
			newval = yes;
yann@1
   473
			break;
yann@1
   474
		case yes:
yann@1
   475
			newval = no;
yann@1
   476
			break;
yann@1
   477
		}
yann@1
   478
		if (sym_set_tristate_value(sym, newval))
yann@1
   479
			break;
yann@1
   480
	} while (oldval != newval);
yann@1
   481
	return newval;
yann@1
   482
}
yann@1
   483
yann@1
   484
bool sym_string_valid(struct symbol *sym, const char *str)
yann@1
   485
{
yann@1
   486
	signed char ch;
yann@1
   487
yann@1
   488
	switch (sym->type) {
yann@1
   489
	case S_STRING:
yann@1
   490
		return true;
yann@1
   491
	case S_INT:
yann@1
   492
		ch = *str++;
yann@1
   493
		if (ch == '-')
yann@1
   494
			ch = *str++;
yann@1
   495
		if (!isdigit(ch))
yann@1
   496
			return false;
yann@1
   497
		if (ch == '0' && *str != 0)
yann@1
   498
			return false;
yann@1
   499
		while ((ch = *str++)) {
yann@1
   500
			if (!isdigit(ch))
yann@1
   501
				return false;
yann@1
   502
		}
yann@1
   503
		return true;
yann@1
   504
	case S_HEX:
yann@1
   505
		if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
yann@1
   506
			str += 2;
yann@1
   507
		ch = *str++;
yann@1
   508
		do {
yann@1
   509
			if (!isxdigit(ch))
yann@1
   510
				return false;
yann@1
   511
		} while ((ch = *str++));
yann@1
   512
		return true;
yann@1
   513
	case S_BOOLEAN:
yann@1
   514
	case S_TRISTATE:
yann@1
   515
		switch (str[0]) {
yann@1
   516
		case 'y': case 'Y':
yann@1
   517
		case 'm': case 'M':
yann@1
   518
		case 'n': case 'N':
yann@1
   519
			return true;
yann@1
   520
		}
yann@1
   521
		return false;
yann@1
   522
	default:
yann@1
   523
		return false;
yann@1
   524
	}
yann@1
   525
}
yann@1
   526
yann@1
   527
bool sym_string_within_range(struct symbol *sym, const char *str)
yann@1
   528
{
yann@1
   529
	struct property *prop;
yann@1
   530
	int val;
yann@1
   531
yann@1
   532
	switch (sym->type) {
yann@1
   533
	case S_STRING:
yann@1
   534
		return sym_string_valid(sym, str);
yann@1
   535
	case S_INT:
yann@1
   536
		if (!sym_string_valid(sym, str))
yann@1
   537
			return false;
yann@1
   538
		prop = sym_get_range_prop(sym);
yann@1
   539
		if (!prop)
yann@1
   540
			return true;
yann@1
   541
		val = strtol(str, NULL, 10);
yann@1
   542
		return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
yann@1
   543
		       val <= sym_get_range_val(prop->expr->right.sym, 10);
yann@1
   544
	case S_HEX:
yann@1
   545
		if (!sym_string_valid(sym, str))
yann@1
   546
			return false;
yann@1
   547
		prop = sym_get_range_prop(sym);
yann@1
   548
		if (!prop)
yann@1
   549
			return true;
yann@1
   550
		val = strtol(str, NULL, 16);
yann@1
   551
		return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
yann@1
   552
		       val <= sym_get_range_val(prop->expr->right.sym, 16);
yann@1
   553
	case S_BOOLEAN:
yann@1
   554
	case S_TRISTATE:
yann@1
   555
		switch (str[0]) {
yann@1
   556
		case 'y': case 'Y':
yann@1
   557
			return sym_tristate_within_range(sym, yes);
yann@1
   558
		case 'm': case 'M':
yann@1
   559
			return sym_tristate_within_range(sym, mod);
yann@1
   560
		case 'n': case 'N':
yann@1
   561
			return sym_tristate_within_range(sym, no);
yann@1
   562
		}
yann@1
   563
		return false;
yann@1
   564
	default:
yann@1
   565
		return false;
yann@1
   566
	}
yann@1
   567
}
yann@1
   568
yann@1
   569
bool sym_set_string_value(struct symbol *sym, const char *newval)
yann@1
   570
{
yann@1
   571
	const char *oldval;
yann@1
   572
	char *val;
yann@1
   573
	int size;
yann@1
   574
yann@1
   575
	switch (sym->type) {
yann@1
   576
	case S_BOOLEAN:
yann@1
   577
	case S_TRISTATE:
yann@1
   578
		switch (newval[0]) {
yann@1
   579
		case 'y': case 'Y':
yann@1
   580
			return sym_set_tristate_value(sym, yes);
yann@1
   581
		case 'm': case 'M':
yann@1
   582
			return sym_set_tristate_value(sym, mod);
yann@1
   583
		case 'n': case 'N':
yann@1
   584
			return sym_set_tristate_value(sym, no);
yann@1
   585
		}
yann@1
   586
		return false;
yann@1
   587
	default:
yann@1
   588
		;
yann@1
   589
	}
yann@1
   590
yann@1
   591
	if (!sym_string_within_range(sym, newval))
yann@1
   592
		return false;
yann@1
   593
yann@1
   594
	if (!(sym->flags & SYMBOL_DEF_USER)) {
yann@1
   595
		sym->flags |= SYMBOL_DEF_USER;
yann@1
   596
		sym_set_changed(sym);
yann@1
   597
	}
yann@1
   598
yann@1
   599
	oldval = sym->def[S_DEF_USER].val;
yann@1
   600
	size = strlen(newval) + 1;
yann@1
   601
	if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
yann@1
   602
		size += 2;
yann@1
   603
		sym->def[S_DEF_USER].val = val = malloc(size);
yann@1
   604
		*val++ = '0';
yann@1
   605
		*val++ = 'x';
yann@1
   606
	} else if (!oldval || strcmp(oldval, newval))
yann@1
   607
		sym->def[S_DEF_USER].val = val = malloc(size);
yann@1
   608
	else
yann@1
   609
		return true;
yann@1
   610
yann@1
   611
	strcpy(val, newval);
yann@1
   612
	free((void *)oldval);
yann@1
   613
	sym_clear_all_valid();
yann@1
   614
yann@1
   615
	return true;
yann@1
   616
}
yann@1
   617
yann@1
   618
const char *sym_get_string_value(struct symbol *sym)
yann@1
   619
{
yann@1
   620
	tristate val;
yann@1
   621
yann@1
   622
	switch (sym->type) {
yann@1
   623
	case S_BOOLEAN:
yann@1
   624
	case S_TRISTATE:
yann@1
   625
		val = sym_get_tristate_value(sym);
yann@1
   626
		switch (val) {
yann@1
   627
		case no:
yann@1
   628
			return "n";
yann@1
   629
		case mod:
yann@1
   630
			return "m";
yann@1
   631
		case yes:
yann@1
   632
			return "y";
yann@1
   633
		}
yann@1
   634
		break;
yann@1
   635
	default:
yann@1
   636
		;
yann@1
   637
	}
yann@1
   638
	return (const char *)sym->curr.val;
yann@1
   639
}
yann@1
   640
yann@1
   641
bool sym_is_changable(struct symbol *sym)
yann@1
   642
{
yann@1
   643
	return sym->visible > sym->rev_dep.tri;
yann@1
   644
}
yann@1
   645
yann@1
   646
struct symbol *sym_lookup(const char *name, int isconst)
yann@1
   647
{
yann@1
   648
	struct symbol *symbol;
yann@1
   649
	const char *ptr;
yann@1
   650
	char *new_name;
yann@1
   651
	int hash = 0;
yann@1
   652
yann@1
   653
	if (name) {
yann@1
   654
		if (name[0] && !name[1]) {
yann@1
   655
			switch (name[0]) {
yann@1
   656
			case 'y': return &symbol_yes;
yann@1
   657
			case 'm': return &symbol_mod;
yann@1
   658
			case 'n': return &symbol_no;
yann@1
   659
			}
yann@1
   660
		}
yann@1
   661
		for (ptr = name; *ptr; ptr++)
yann@1
   662
			hash += *ptr;
yann@1
   663
		hash &= 0xff;
yann@1
   664
yann@1
   665
		for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
yann@1
   666
			if (!strcmp(symbol->name, name)) {
yann@1
   667
				if ((isconst && symbol->flags & SYMBOL_CONST) ||
yann@1
   668
				    (!isconst && !(symbol->flags & SYMBOL_CONST)))
yann@1
   669
					return symbol;
yann@1
   670
			}
yann@1
   671
		}
yann@1
   672
		new_name = strdup(name);
yann@1
   673
	} else {
yann@1
   674
		new_name = NULL;
yann@1
   675
		hash = 256;
yann@1
   676
	}
yann@1
   677
yann@1
   678
	symbol = malloc(sizeof(*symbol));
yann@1
   679
	memset(symbol, 0, sizeof(*symbol));
yann@1
   680
	symbol->name = new_name;
yann@1
   681
	symbol->type = S_UNKNOWN;
yann@1
   682
	if (isconst)
yann@1
   683
		symbol->flags |= SYMBOL_CONST;
yann@1
   684
yann@1
   685
	symbol->next = symbol_hash[hash];
yann@1
   686
	symbol_hash[hash] = symbol;
yann@1
   687
yann@1
   688
	return symbol;
yann@1
   689
}
yann@1
   690
yann@1
   691
struct symbol *sym_find(const char *name)
yann@1
   692
{
yann@1
   693
	struct symbol *symbol = NULL;
yann@1
   694
	const char *ptr;
yann@1
   695
	int hash = 0;
yann@1
   696
yann@1
   697
	if (!name)
yann@1
   698
		return NULL;
yann@1
   699
yann@1
   700
	if (name[0] && !name[1]) {
yann@1
   701
		switch (name[0]) {
yann@1
   702
		case 'y': return &symbol_yes;
yann@1
   703
		case 'm': return &symbol_mod;
yann@1
   704
		case 'n': return &symbol_no;
yann@1
   705
		}
yann@1
   706
	}
yann@1
   707
	for (ptr = name; *ptr; ptr++)
yann@1
   708
		hash += *ptr;
yann@1
   709
	hash &= 0xff;
yann@1
   710
yann@1
   711
	for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
yann@1
   712
		if (!strcmp(symbol->name, name) &&
yann@1
   713
		    !(symbol->flags & SYMBOL_CONST))
yann@1
   714
				break;
yann@1
   715
	}
yann@1
   716
yann@1
   717
	return symbol;
yann@1
   718
}
yann@1
   719
yann@1
   720
struct symbol **sym_re_search(const char *pattern)
yann@1
   721
{
yann@1
   722
	struct symbol *sym, **sym_arr = NULL;
yann@1
   723
	int i, cnt, size;
yann@1
   724
	regex_t re;
yann@1
   725
yann@1
   726
	cnt = size = 0;
yann@1
   727
	/* Skip if empty */
yann@1
   728
	if (strlen(pattern) == 0)
yann@1
   729
		return NULL;
yann@1
   730
	if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
yann@1
   731
		return NULL;
yann@1
   732
yann@1
   733
	for_all_symbols(i, sym) {
yann@1
   734
		if (sym->flags & SYMBOL_CONST || !sym->name)
yann@1
   735
			continue;
yann@1
   736
		if (regexec(&re, sym->name, 0, NULL, 0))
yann@1
   737
			continue;
yann@1
   738
		if (cnt + 1 >= size) {
yann@1
   739
			void *tmp = sym_arr;
yann@1
   740
			size += 16;
yann@1
   741
			sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
yann@1
   742
			if (!sym_arr) {
yann@1
   743
				free(tmp);
yann@1
   744
				return NULL;
yann@1
   745
			}
yann@1
   746
		}
yann@1
   747
		sym_arr[cnt++] = sym;
yann@1
   748
	}
yann@1
   749
	if (sym_arr)
yann@1
   750
		sym_arr[cnt] = NULL;
yann@1
   751
	regfree(&re);
yann@1
   752
yann@1
   753
	return sym_arr;
yann@1
   754
}
yann@1
   755
yann@1
   756
yann@1
   757
struct symbol *sym_check_deps(struct symbol *sym);
yann@1
   758
yann@1
   759
static struct symbol *sym_check_expr_deps(struct expr *e)
yann@1
   760
{
yann@1
   761
	struct symbol *sym;
yann@1
   762
yann@1
   763
	if (!e)
yann@1
   764
		return NULL;
yann@1
   765
	switch (e->type) {
yann@1
   766
	case E_OR:
yann@1
   767
	case E_AND:
yann@1
   768
		sym = sym_check_expr_deps(e->left.expr);
yann@1
   769
		if (sym)
yann@1
   770
			return sym;
yann@1
   771
		return sym_check_expr_deps(e->right.expr);
yann@1
   772
	case E_NOT:
yann@1
   773
		return sym_check_expr_deps(e->left.expr);
yann@1
   774
	case E_EQUAL:
yann@1
   775
	case E_UNEQUAL:
yann@1
   776
		sym = sym_check_deps(e->left.sym);
yann@1
   777
		if (sym)
yann@1
   778
			return sym;
yann@1
   779
		return sym_check_deps(e->right.sym);
yann@1
   780
	case E_SYMBOL:
yann@1
   781
		return sym_check_deps(e->left.sym);
yann@1
   782
	default:
yann@1
   783
		break;
yann@1
   784
	}
yann@1
   785
	printf("Oops! How to check %d?\n", e->type);
yann@1
   786
	return NULL;
yann@1
   787
}
yann@1
   788
yann@1
   789
struct symbol *sym_check_deps(struct symbol *sym)
yann@1
   790
{
yann@1
   791
	struct symbol *sym2;
yann@1
   792
	struct property *prop;
yann@1
   793
yann@1
   794
	if (sym->flags & SYMBOL_CHECK) {
yann@1
   795
		printf("Warning! Found recursive dependency: %s", sym->name);
yann@1
   796
		return sym;
yann@1
   797
	}
yann@1
   798
	if (sym->flags & SYMBOL_CHECKED)
yann@1
   799
		return NULL;
yann@1
   800
yann@1
   801
	sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
yann@1
   802
	sym2 = sym_check_expr_deps(sym->rev_dep.expr);
yann@1
   803
	if (sym2)
yann@1
   804
		goto out;
yann@1
   805
yann@1
   806
	for (prop = sym->prop; prop; prop = prop->next) {
yann@1
   807
		if (prop->type == P_CHOICE || prop->type == P_SELECT)
yann@1
   808
			continue;
yann@1
   809
		sym2 = sym_check_expr_deps(prop->visible.expr);
yann@1
   810
		if (sym2)
yann@1
   811
			goto out;
yann@1
   812
		if (prop->type != P_DEFAULT || sym_is_choice(sym))
yann@1
   813
			continue;
yann@1
   814
		sym2 = sym_check_expr_deps(prop->expr);
yann@1
   815
		if (sym2)
yann@1
   816
			goto out;
yann@1
   817
	}
yann@1
   818
out:
yann@1
   819
	if (sym2) {
yann@1
   820
		printf(" %s", sym->name);
yann@1
   821
		if (sym2 == sym) {
yann@1
   822
			printf("\n");
yann@1
   823
			sym2 = NULL;
yann@1
   824
		}
yann@1
   825
	}
yann@1
   826
	sym->flags &= ~SYMBOL_CHECK;
yann@1
   827
	return sym2;
yann@1
   828
}
yann@1
   829
yann@1
   830
struct property *prop_alloc(enum prop_type type, struct symbol *sym)
yann@1
   831
{
yann@1
   832
	struct property *prop;
yann@1
   833
	struct property **propp;
yann@1
   834
yann@1
   835
	prop = malloc(sizeof(*prop));
yann@1
   836
	memset(prop, 0, sizeof(*prop));
yann@1
   837
	prop->type = type;
yann@1
   838
	prop->sym = sym;
yann@1
   839
	prop->file = current_file;
yann@1
   840
	prop->lineno = zconf_lineno();
yann@1
   841
yann@1
   842
	/* append property to the prop list of symbol */
yann@1
   843
	if (sym) {
yann@1
   844
		for (propp = &sym->prop; *propp; propp = &(*propp)->next)
yann@1
   845
			;
yann@1
   846
		*propp = prop;
yann@1
   847
	}
yann@1
   848
yann@1
   849
	return prop;
yann@1
   850
}
yann@1
   851
yann@1
   852
struct symbol *prop_get_symbol(struct property *prop)
yann@1
   853
{
yann@1
   854
	if (prop->expr && (prop->expr->type == E_SYMBOL ||
yann@1
   855
			   prop->expr->type == E_CHOICE))
yann@1
   856
		return prop->expr->left.sym;
yann@1
   857
	return NULL;
yann@1
   858
}
yann@1
   859
yann@1
   860
const char *prop_get_type_name(enum prop_type type)
yann@1
   861
{
yann@1
   862
	switch (type) {
yann@1
   863
	case P_PROMPT:
yann@1
   864
		return "prompt";
yann@1
   865
	case P_COMMENT:
yann@1
   866
		return "comment";
yann@1
   867
	case P_MENU:
yann@1
   868
		return "menu";
yann@1
   869
	case P_DEFAULT:
yann@1
   870
		return "default";
yann@1
   871
	case P_CHOICE:
yann@1
   872
		return "choice";
yann@1
   873
	case P_SELECT:
yann@1
   874
		return "select";
yann@1
   875
	case P_RANGE:
yann@1
   876
		return "range";
yann@1
   877
	case P_UNKNOWN:
yann@1
   878
		break;
yann@1
   879
	}
yann@1
   880
	return "unknown";
yann@1
   881
}