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