kconfig/symbol.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Thu Aug 07 13:35:11 2008 +0000 (2008-08-07)
changeset 764 ff368787f62b
parent 1 eeea35fbf182
child 943 1cca90ce0481
permissions -rw-r--r--
When reporting bugs, TO is ymorin, CC is crossgcc ML, not the other way around.

/trunk/README | 4 2 2 0 ++--
1 file changed, 2 insertions(+), 2 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
}