kconfig/symbol.c
changeset 1 eeea35fbf182
child 39 af42eec9d383
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/kconfig/symbol.c	Sat Feb 24 11:00:05 2007 +0000
     1.3 @@ -0,0 +1,882 @@
     1.4 +/*
     1.5 + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
     1.6 + * Released under the terms of the GNU GPL v2.0.
     1.7 + */
     1.8 +
     1.9 +#include <ctype.h>
    1.10 +#include <stdlib.h>
    1.11 +#include <string.h>
    1.12 +#include <regex.h>
    1.13 +#include <sys/utsname.h>
    1.14 +
    1.15 +#define LKC_DIRECT_LINK
    1.16 +#include "lkc.h"
    1.17 +
    1.18 +struct symbol symbol_yes = {
    1.19 +	.name = "y",
    1.20 +	.curr = { "y", yes },
    1.21 +	.flags = SYMBOL_CONST|SYMBOL_VALID,
    1.22 +}, symbol_mod = {
    1.23 +	.name = "m",
    1.24 +	.curr = { "m", mod },
    1.25 +	.flags = SYMBOL_CONST|SYMBOL_VALID,
    1.26 +}, symbol_no = {
    1.27 +	.name = "n",
    1.28 +	.curr = { "n", no },
    1.29 +	.flags = SYMBOL_CONST|SYMBOL_VALID,
    1.30 +}, symbol_empty = {
    1.31 +	.name = "",
    1.32 +	.curr = { "", no },
    1.33 +	.flags = SYMBOL_VALID,
    1.34 +};
    1.35 +
    1.36 +int sym_change_count;
    1.37 +struct symbol *sym_defconfig_list;
    1.38 +struct symbol *modules_sym;
    1.39 +tristate modules_val;
    1.40 +
    1.41 +void sym_add_default(struct symbol *sym, const char *def)
    1.42 +{
    1.43 +	struct property *prop = prop_alloc(P_DEFAULT, sym);
    1.44 +
    1.45 +	prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
    1.46 +}
    1.47 +
    1.48 +void sym_init(void)
    1.49 +{
    1.50 +	struct symbol *sym;
    1.51 +	struct utsname uts;
    1.52 +	char *p;
    1.53 +	static bool inited = false;
    1.54 +
    1.55 +	if (inited)
    1.56 +		return;
    1.57 +	inited = true;
    1.58 +
    1.59 +	uname(&uts);
    1.60 +
    1.61 +	sym = sym_lookup("ARCH", 0);
    1.62 +	sym->type = S_STRING;
    1.63 +	sym->flags |= SYMBOL_AUTO;
    1.64 +	p = getenv("ARCH");
    1.65 +	if (p)
    1.66 +		sym_add_default(sym, p);
    1.67 +
    1.68 +	sym = sym_lookup("PROJECTVERSION", 0);
    1.69 +	sym->type = S_STRING;
    1.70 +	sym->flags |= SYMBOL_AUTO;
    1.71 +	p = getenv("PROJECTVERSION");
    1.72 +	if (p)
    1.73 +		sym_add_default(sym, p);
    1.74 +
    1.75 +	sym = sym_lookup("UNAME_RELEASE", 0);
    1.76 +	sym->type = S_STRING;
    1.77 +	sym->flags |= SYMBOL_AUTO;
    1.78 +	sym_add_default(sym, uts.release);
    1.79 +}
    1.80 +
    1.81 +enum symbol_type sym_get_type(struct symbol *sym)
    1.82 +{
    1.83 +	enum symbol_type type = sym->type;
    1.84 +
    1.85 +	if (type == S_TRISTATE) {
    1.86 +		if (sym_is_choice_value(sym) && sym->visible == yes)
    1.87 +			type = S_BOOLEAN;
    1.88 +		else if (modules_val == no)
    1.89 +			type = S_BOOLEAN;
    1.90 +	}
    1.91 +	return type;
    1.92 +}
    1.93 +
    1.94 +const char *sym_type_name(enum symbol_type type)
    1.95 +{
    1.96 +	switch (type) {
    1.97 +	case S_BOOLEAN:
    1.98 +		return "boolean";
    1.99 +	case S_TRISTATE:
   1.100 +		return "tristate";
   1.101 +	case S_INT:
   1.102 +		return "integer";
   1.103 +	case S_HEX:
   1.104 +		return "hex";
   1.105 +	case S_STRING:
   1.106 +		return "string";
   1.107 +	case S_UNKNOWN:
   1.108 +		return "unknown";
   1.109 +	case S_OTHER:
   1.110 +		break;
   1.111 +	}
   1.112 +	return "???";
   1.113 +}
   1.114 +
   1.115 +struct property *sym_get_choice_prop(struct symbol *sym)
   1.116 +{
   1.117 +	struct property *prop;
   1.118 +
   1.119 +	for_all_choices(sym, prop)
   1.120 +		return prop;
   1.121 +	return NULL;
   1.122 +}
   1.123 +
   1.124 +struct property *sym_get_default_prop(struct symbol *sym)
   1.125 +{
   1.126 +	struct property *prop;
   1.127 +
   1.128 +	for_all_defaults(sym, prop) {
   1.129 +		prop->visible.tri = expr_calc_value(prop->visible.expr);
   1.130 +		if (prop->visible.tri != no)
   1.131 +			return prop;
   1.132 +	}
   1.133 +	return NULL;
   1.134 +}
   1.135 +
   1.136 +struct property *sym_get_range_prop(struct symbol *sym)
   1.137 +{
   1.138 +	struct property *prop;
   1.139 +
   1.140 +	for_all_properties(sym, prop, P_RANGE) {
   1.141 +		prop->visible.tri = expr_calc_value(prop->visible.expr);
   1.142 +		if (prop->visible.tri != no)
   1.143 +			return prop;
   1.144 +	}
   1.145 +	return NULL;
   1.146 +}
   1.147 +
   1.148 +static int sym_get_range_val(struct symbol *sym, int base)
   1.149 +{
   1.150 +	sym_calc_value(sym);
   1.151 +	switch (sym->type) {
   1.152 +	case S_INT:
   1.153 +		base = 10;
   1.154 +		break;
   1.155 +	case S_HEX:
   1.156 +		base = 16;
   1.157 +		break;
   1.158 +	default:
   1.159 +		break;
   1.160 +	}
   1.161 +	return strtol(sym->curr.val, NULL, base);
   1.162 +}
   1.163 +
   1.164 +static void sym_validate_range(struct symbol *sym)
   1.165 +{
   1.166 +	struct property *prop;
   1.167 +	int base, val, val2;
   1.168 +	char str[64];
   1.169 +
   1.170 +	switch (sym->type) {
   1.171 +	case S_INT:
   1.172 +		base = 10;
   1.173 +		break;
   1.174 +	case S_HEX:
   1.175 +		base = 16;
   1.176 +		break;
   1.177 +	default:
   1.178 +		return;
   1.179 +	}
   1.180 +	prop = sym_get_range_prop(sym);
   1.181 +	if (!prop)
   1.182 +		return;
   1.183 +	val = strtol(sym->curr.val, NULL, base);
   1.184 +	val2 = sym_get_range_val(prop->expr->left.sym, base);
   1.185 +	if (val >= val2) {
   1.186 +		val2 = sym_get_range_val(prop->expr->right.sym, base);
   1.187 +		if (val <= val2)
   1.188 +			return;
   1.189 +	}
   1.190 +	if (sym->type == S_INT)
   1.191 +		sprintf(str, "%d", val2);
   1.192 +	else
   1.193 +		sprintf(str, "0x%x", val2);
   1.194 +	sym->curr.val = strdup(str);
   1.195 +}
   1.196 +
   1.197 +static void sym_calc_visibility(struct symbol *sym)
   1.198 +{
   1.199 +	struct property *prop;
   1.200 +	tristate tri;
   1.201 +
   1.202 +	/* any prompt visible? */
   1.203 +	tri = no;
   1.204 +	for_all_prompts(sym, prop) {
   1.205 +		prop->visible.tri = expr_calc_value(prop->visible.expr);
   1.206 +		tri = E_OR(tri, prop->visible.tri);
   1.207 +	}
   1.208 +	if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
   1.209 +		tri = yes;
   1.210 +	if (sym->visible != tri) {
   1.211 +		sym->visible = tri;
   1.212 +		sym_set_changed(sym);
   1.213 +	}
   1.214 +	if (sym_is_choice_value(sym))
   1.215 +		return;
   1.216 +	tri = no;
   1.217 +	if (sym->rev_dep.expr)
   1.218 +		tri = expr_calc_value(sym->rev_dep.expr);
   1.219 +	if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
   1.220 +		tri = yes;
   1.221 +	if (sym->rev_dep.tri != tri) {
   1.222 +		sym->rev_dep.tri = tri;
   1.223 +		sym_set_changed(sym);
   1.224 +	}
   1.225 +}
   1.226 +
   1.227 +static struct symbol *sym_calc_choice(struct symbol *sym)
   1.228 +{
   1.229 +	struct symbol *def_sym;
   1.230 +	struct property *prop;
   1.231 +	struct expr *e;
   1.232 +
   1.233 +	/* is the user choice visible? */
   1.234 +	def_sym = sym->def[S_DEF_USER].val;
   1.235 +	if (def_sym) {
   1.236 +		sym_calc_visibility(def_sym);
   1.237 +		if (def_sym->visible != no)
   1.238 +			return def_sym;
   1.239 +	}
   1.240 +
   1.241 +	/* any of the defaults visible? */
   1.242 +	for_all_defaults(sym, prop) {
   1.243 +		prop->visible.tri = expr_calc_value(prop->visible.expr);
   1.244 +		if (prop->visible.tri == no)
   1.245 +			continue;
   1.246 +		def_sym = prop_get_symbol(prop);
   1.247 +		sym_calc_visibility(def_sym);
   1.248 +		if (def_sym->visible != no)
   1.249 +			return def_sym;
   1.250 +	}
   1.251 +
   1.252 +	/* just get the first visible value */
   1.253 +	prop = sym_get_choice_prop(sym);
   1.254 +	for (e = prop->expr; e; e = e->left.expr) {
   1.255 +		def_sym = e->right.sym;
   1.256 +		sym_calc_visibility(def_sym);
   1.257 +		if (def_sym->visible != no)
   1.258 +			return def_sym;
   1.259 +	}
   1.260 +
   1.261 +	/* no choice? reset tristate value */
   1.262 +	sym->curr.tri = no;
   1.263 +	return NULL;
   1.264 +}
   1.265 +
   1.266 +void sym_calc_value(struct symbol *sym)
   1.267 +{
   1.268 +	struct symbol_value newval, oldval;
   1.269 +	struct property *prop;
   1.270 +	struct expr *e;
   1.271 +
   1.272 +	if (!sym)
   1.273 +		return;
   1.274 +
   1.275 +	if (sym->flags & SYMBOL_VALID)
   1.276 +		return;
   1.277 +	sym->flags |= SYMBOL_VALID;
   1.278 +
   1.279 +	oldval = sym->curr;
   1.280 +
   1.281 +	switch (sym->type) {
   1.282 +	case S_INT:
   1.283 +	case S_HEX:
   1.284 +	case S_STRING:
   1.285 +		newval = symbol_empty.curr;
   1.286 +		break;
   1.287 +	case S_BOOLEAN:
   1.288 +	case S_TRISTATE:
   1.289 +		newval = symbol_no.curr;
   1.290 +		break;
   1.291 +	default:
   1.292 +		sym->curr.val = sym->name;
   1.293 +		sym->curr.tri = no;
   1.294 +		return;
   1.295 +	}
   1.296 +	if (!sym_is_choice_value(sym))
   1.297 +		sym->flags &= ~SYMBOL_WRITE;
   1.298 +
   1.299 +	sym_calc_visibility(sym);
   1.300 +
   1.301 +	/* set default if recursively called */
   1.302 +	sym->curr = newval;
   1.303 +
   1.304 +	switch (sym_get_type(sym)) {
   1.305 +	case S_BOOLEAN:
   1.306 +	case S_TRISTATE:
   1.307 +		if (sym_is_choice_value(sym) && sym->visible == yes) {
   1.308 +			prop = sym_get_choice_prop(sym);
   1.309 +			newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
   1.310 +		} else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
   1.311 +			sym->flags |= SYMBOL_WRITE;
   1.312 +			if (sym_has_value(sym))
   1.313 +				newval.tri = sym->def[S_DEF_USER].tri;
   1.314 +			else if (!sym_is_choice(sym)) {
   1.315 +				prop = sym_get_default_prop(sym);
   1.316 +				if (prop)
   1.317 +					newval.tri = expr_calc_value(prop->expr);
   1.318 +			}
   1.319 +			newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
   1.320 +		} else if (!sym_is_choice(sym)) {
   1.321 +			prop = sym_get_default_prop(sym);
   1.322 +			if (prop) {
   1.323 +				sym->flags |= SYMBOL_WRITE;
   1.324 +				newval.tri = expr_calc_value(prop->expr);
   1.325 +			}
   1.326 +		}
   1.327 +		if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
   1.328 +			newval.tri = yes;
   1.329 +		break;
   1.330 +	case S_STRING:
   1.331 +	case S_HEX:
   1.332 +	case S_INT:
   1.333 +		if (sym->visible != no) {
   1.334 +			sym->flags |= SYMBOL_WRITE;
   1.335 +			if (sym_has_value(sym)) {
   1.336 +				newval.val = sym->def[S_DEF_USER].val;
   1.337 +				break;
   1.338 +			}
   1.339 +		}
   1.340 +		prop = sym_get_default_prop(sym);
   1.341 +		if (prop) {
   1.342 +			struct symbol *ds = prop_get_symbol(prop);
   1.343 +			if (ds) {
   1.344 +				sym->flags |= SYMBOL_WRITE;
   1.345 +				sym_calc_value(ds);
   1.346 +				newval.val = ds->curr.val;
   1.347 +			}
   1.348 +		}
   1.349 +		break;
   1.350 +	default:
   1.351 +		;
   1.352 +	}
   1.353 +
   1.354 +	sym->curr = newval;
   1.355 +	if (sym_is_choice(sym) && newval.tri == yes)
   1.356 +		sym->curr.val = sym_calc_choice(sym);
   1.357 +	sym_validate_range(sym);
   1.358 +
   1.359 +	if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
   1.360 +		sym_set_changed(sym);
   1.361 +		if (modules_sym == sym) {
   1.362 +			sym_set_all_changed();
   1.363 +			modules_val = modules_sym->curr.tri;
   1.364 +		}
   1.365 +	}
   1.366 +
   1.367 +	if (sym_is_choice(sym)) {
   1.368 +		int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
   1.369 +		prop = sym_get_choice_prop(sym);
   1.370 +		for (e = prop->expr; e; e = e->left.expr) {
   1.371 +			e->right.sym->flags |= flags;
   1.372 +			if (flags & SYMBOL_CHANGED)
   1.373 +				sym_set_changed(e->right.sym);
   1.374 +		}
   1.375 +	}
   1.376 +}
   1.377 +
   1.378 +void sym_clear_all_valid(void)
   1.379 +{
   1.380 +	struct symbol *sym;
   1.381 +	int i;
   1.382 +
   1.383 +	for_all_symbols(i, sym)
   1.384 +		sym->flags &= ~SYMBOL_VALID;
   1.385 +	sym_change_count++;
   1.386 +	if (modules_sym)
   1.387 +		sym_calc_value(modules_sym);
   1.388 +}
   1.389 +
   1.390 +void sym_set_changed(struct symbol *sym)
   1.391 +{
   1.392 +	struct property *prop;
   1.393 +
   1.394 +	sym->flags |= SYMBOL_CHANGED;
   1.395 +	for (prop = sym->prop; prop; prop = prop->next) {
   1.396 +		if (prop->menu)
   1.397 +			prop->menu->flags |= MENU_CHANGED;
   1.398 +	}
   1.399 +}
   1.400 +
   1.401 +void sym_set_all_changed(void)
   1.402 +{
   1.403 +	struct symbol *sym;
   1.404 +	int i;
   1.405 +
   1.406 +	for_all_symbols(i, sym)
   1.407 +		sym_set_changed(sym);
   1.408 +}
   1.409 +
   1.410 +bool sym_tristate_within_range(struct symbol *sym, tristate val)
   1.411 +{
   1.412 +	int type = sym_get_type(sym);
   1.413 +
   1.414 +	if (sym->visible == no)
   1.415 +		return false;
   1.416 +
   1.417 +	if (type != S_BOOLEAN && type != S_TRISTATE)
   1.418 +		return false;
   1.419 +
   1.420 +	if (type == S_BOOLEAN && val == mod)
   1.421 +		return false;
   1.422 +	if (sym->visible <= sym->rev_dep.tri)
   1.423 +		return false;
   1.424 +	if (sym_is_choice_value(sym) && sym->visible == yes)
   1.425 +		return val == yes;
   1.426 +	return val >= sym->rev_dep.tri && val <= sym->visible;
   1.427 +}
   1.428 +
   1.429 +bool sym_set_tristate_value(struct symbol *sym, tristate val)
   1.430 +{
   1.431 +	tristate oldval = sym_get_tristate_value(sym);
   1.432 +
   1.433 +	if (oldval != val && !sym_tristate_within_range(sym, val))
   1.434 +		return false;
   1.435 +
   1.436 +	if (!(sym->flags & SYMBOL_DEF_USER)) {
   1.437 +		sym->flags |= SYMBOL_DEF_USER;
   1.438 +		sym_set_changed(sym);
   1.439 +	}
   1.440 +	/*
   1.441 +	 * setting a choice value also resets the new flag of the choice
   1.442 +	 * symbol and all other choice values.
   1.443 +	 */
   1.444 +	if (sym_is_choice_value(sym) && val == yes) {
   1.445 +		struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
   1.446 +		struct property *prop;
   1.447 +		struct expr *e;
   1.448 +
   1.449 +		cs->def[S_DEF_USER].val = sym;
   1.450 +		cs->flags |= SYMBOL_DEF_USER;
   1.451 +		prop = sym_get_choice_prop(cs);
   1.452 +		for (e = prop->expr; e; e = e->left.expr) {
   1.453 +			if (e->right.sym->visible != no)
   1.454 +				e->right.sym->flags |= SYMBOL_DEF_USER;
   1.455 +		}
   1.456 +	}
   1.457 +
   1.458 +	sym->def[S_DEF_USER].tri = val;
   1.459 +	if (oldval != val)
   1.460 +		sym_clear_all_valid();
   1.461 +
   1.462 +	return true;
   1.463 +}
   1.464 +
   1.465 +tristate sym_toggle_tristate_value(struct symbol *sym)
   1.466 +{
   1.467 +	tristate oldval, newval;
   1.468 +
   1.469 +	oldval = newval = sym_get_tristate_value(sym);
   1.470 +	do {
   1.471 +		switch (newval) {
   1.472 +		case no:
   1.473 +			newval = mod;
   1.474 +			break;
   1.475 +		case mod:
   1.476 +			newval = yes;
   1.477 +			break;
   1.478 +		case yes:
   1.479 +			newval = no;
   1.480 +			break;
   1.481 +		}
   1.482 +		if (sym_set_tristate_value(sym, newval))
   1.483 +			break;
   1.484 +	} while (oldval != newval);
   1.485 +	return newval;
   1.486 +}
   1.487 +
   1.488 +bool sym_string_valid(struct symbol *sym, const char *str)
   1.489 +{
   1.490 +	signed char ch;
   1.491 +
   1.492 +	switch (sym->type) {
   1.493 +	case S_STRING:
   1.494 +		return true;
   1.495 +	case S_INT:
   1.496 +		ch = *str++;
   1.497 +		if (ch == '-')
   1.498 +			ch = *str++;
   1.499 +		if (!isdigit(ch))
   1.500 +			return false;
   1.501 +		if (ch == '0' && *str != 0)
   1.502 +			return false;
   1.503 +		while ((ch = *str++)) {
   1.504 +			if (!isdigit(ch))
   1.505 +				return false;
   1.506 +		}
   1.507 +		return true;
   1.508 +	case S_HEX:
   1.509 +		if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
   1.510 +			str += 2;
   1.511 +		ch = *str++;
   1.512 +		do {
   1.513 +			if (!isxdigit(ch))
   1.514 +				return false;
   1.515 +		} while ((ch = *str++));
   1.516 +		return true;
   1.517 +	case S_BOOLEAN:
   1.518 +	case S_TRISTATE:
   1.519 +		switch (str[0]) {
   1.520 +		case 'y': case 'Y':
   1.521 +		case 'm': case 'M':
   1.522 +		case 'n': case 'N':
   1.523 +			return true;
   1.524 +		}
   1.525 +		return false;
   1.526 +	default:
   1.527 +		return false;
   1.528 +	}
   1.529 +}
   1.530 +
   1.531 +bool sym_string_within_range(struct symbol *sym, const char *str)
   1.532 +{
   1.533 +	struct property *prop;
   1.534 +	int val;
   1.535 +
   1.536 +	switch (sym->type) {
   1.537 +	case S_STRING:
   1.538 +		return sym_string_valid(sym, str);
   1.539 +	case S_INT:
   1.540 +		if (!sym_string_valid(sym, str))
   1.541 +			return false;
   1.542 +		prop = sym_get_range_prop(sym);
   1.543 +		if (!prop)
   1.544 +			return true;
   1.545 +		val = strtol(str, NULL, 10);
   1.546 +		return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
   1.547 +		       val <= sym_get_range_val(prop->expr->right.sym, 10);
   1.548 +	case S_HEX:
   1.549 +		if (!sym_string_valid(sym, str))
   1.550 +			return false;
   1.551 +		prop = sym_get_range_prop(sym);
   1.552 +		if (!prop)
   1.553 +			return true;
   1.554 +		val = strtol(str, NULL, 16);
   1.555 +		return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
   1.556 +		       val <= sym_get_range_val(prop->expr->right.sym, 16);
   1.557 +	case S_BOOLEAN:
   1.558 +	case S_TRISTATE:
   1.559 +		switch (str[0]) {
   1.560 +		case 'y': case 'Y':
   1.561 +			return sym_tristate_within_range(sym, yes);
   1.562 +		case 'm': case 'M':
   1.563 +			return sym_tristate_within_range(sym, mod);
   1.564 +		case 'n': case 'N':
   1.565 +			return sym_tristate_within_range(sym, no);
   1.566 +		}
   1.567 +		return false;
   1.568 +	default:
   1.569 +		return false;
   1.570 +	}
   1.571 +}
   1.572 +
   1.573 +bool sym_set_string_value(struct symbol *sym, const char *newval)
   1.574 +{
   1.575 +	const char *oldval;
   1.576 +	char *val;
   1.577 +	int size;
   1.578 +
   1.579 +	switch (sym->type) {
   1.580 +	case S_BOOLEAN:
   1.581 +	case S_TRISTATE:
   1.582 +		switch (newval[0]) {
   1.583 +		case 'y': case 'Y':
   1.584 +			return sym_set_tristate_value(sym, yes);
   1.585 +		case 'm': case 'M':
   1.586 +			return sym_set_tristate_value(sym, mod);
   1.587 +		case 'n': case 'N':
   1.588 +			return sym_set_tristate_value(sym, no);
   1.589 +		}
   1.590 +		return false;
   1.591 +	default:
   1.592 +		;
   1.593 +	}
   1.594 +
   1.595 +	if (!sym_string_within_range(sym, newval))
   1.596 +		return false;
   1.597 +
   1.598 +	if (!(sym->flags & SYMBOL_DEF_USER)) {
   1.599 +		sym->flags |= SYMBOL_DEF_USER;
   1.600 +		sym_set_changed(sym);
   1.601 +	}
   1.602 +
   1.603 +	oldval = sym->def[S_DEF_USER].val;
   1.604 +	size = strlen(newval) + 1;
   1.605 +	if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
   1.606 +		size += 2;
   1.607 +		sym->def[S_DEF_USER].val = val = malloc(size);
   1.608 +		*val++ = '0';
   1.609 +		*val++ = 'x';
   1.610 +	} else if (!oldval || strcmp(oldval, newval))
   1.611 +		sym->def[S_DEF_USER].val = val = malloc(size);
   1.612 +	else
   1.613 +		return true;
   1.614 +
   1.615 +	strcpy(val, newval);
   1.616 +	free((void *)oldval);
   1.617 +	sym_clear_all_valid();
   1.618 +
   1.619 +	return true;
   1.620 +}
   1.621 +
   1.622 +const char *sym_get_string_value(struct symbol *sym)
   1.623 +{
   1.624 +	tristate val;
   1.625 +
   1.626 +	switch (sym->type) {
   1.627 +	case S_BOOLEAN:
   1.628 +	case S_TRISTATE:
   1.629 +		val = sym_get_tristate_value(sym);
   1.630 +		switch (val) {
   1.631 +		case no:
   1.632 +			return "n";
   1.633 +		case mod:
   1.634 +			return "m";
   1.635 +		case yes:
   1.636 +			return "y";
   1.637 +		}
   1.638 +		break;
   1.639 +	default:
   1.640 +		;
   1.641 +	}
   1.642 +	return (const char *)sym->curr.val;
   1.643 +}
   1.644 +
   1.645 +bool sym_is_changable(struct symbol *sym)
   1.646 +{
   1.647 +	return sym->visible > sym->rev_dep.tri;
   1.648 +}
   1.649 +
   1.650 +struct symbol *sym_lookup(const char *name, int isconst)
   1.651 +{
   1.652 +	struct symbol *symbol;
   1.653 +	const char *ptr;
   1.654 +	char *new_name;
   1.655 +	int hash = 0;
   1.656 +
   1.657 +	if (name) {
   1.658 +		if (name[0] && !name[1]) {
   1.659 +			switch (name[0]) {
   1.660 +			case 'y': return &symbol_yes;
   1.661 +			case 'm': return &symbol_mod;
   1.662 +			case 'n': return &symbol_no;
   1.663 +			}
   1.664 +		}
   1.665 +		for (ptr = name; *ptr; ptr++)
   1.666 +			hash += *ptr;
   1.667 +		hash &= 0xff;
   1.668 +
   1.669 +		for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
   1.670 +			if (!strcmp(symbol->name, name)) {
   1.671 +				if ((isconst && symbol->flags & SYMBOL_CONST) ||
   1.672 +				    (!isconst && !(symbol->flags & SYMBOL_CONST)))
   1.673 +					return symbol;
   1.674 +			}
   1.675 +		}
   1.676 +		new_name = strdup(name);
   1.677 +	} else {
   1.678 +		new_name = NULL;
   1.679 +		hash = 256;
   1.680 +	}
   1.681 +
   1.682 +	symbol = malloc(sizeof(*symbol));
   1.683 +	memset(symbol, 0, sizeof(*symbol));
   1.684 +	symbol->name = new_name;
   1.685 +	symbol->type = S_UNKNOWN;
   1.686 +	if (isconst)
   1.687 +		symbol->flags |= SYMBOL_CONST;
   1.688 +
   1.689 +	symbol->next = symbol_hash[hash];
   1.690 +	symbol_hash[hash] = symbol;
   1.691 +
   1.692 +	return symbol;
   1.693 +}
   1.694 +
   1.695 +struct symbol *sym_find(const char *name)
   1.696 +{
   1.697 +	struct symbol *symbol = NULL;
   1.698 +	const char *ptr;
   1.699 +	int hash = 0;
   1.700 +
   1.701 +	if (!name)
   1.702 +		return NULL;
   1.703 +
   1.704 +	if (name[0] && !name[1]) {
   1.705 +		switch (name[0]) {
   1.706 +		case 'y': return &symbol_yes;
   1.707 +		case 'm': return &symbol_mod;
   1.708 +		case 'n': return &symbol_no;
   1.709 +		}
   1.710 +	}
   1.711 +	for (ptr = name; *ptr; ptr++)
   1.712 +		hash += *ptr;
   1.713 +	hash &= 0xff;
   1.714 +
   1.715 +	for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
   1.716 +		if (!strcmp(symbol->name, name) &&
   1.717 +		    !(symbol->flags & SYMBOL_CONST))
   1.718 +				break;
   1.719 +	}
   1.720 +
   1.721 +	return symbol;
   1.722 +}
   1.723 +
   1.724 +struct symbol **sym_re_search(const char *pattern)
   1.725 +{
   1.726 +	struct symbol *sym, **sym_arr = NULL;
   1.727 +	int i, cnt, size;
   1.728 +	regex_t re;
   1.729 +
   1.730 +	cnt = size = 0;
   1.731 +	/* Skip if empty */
   1.732 +	if (strlen(pattern) == 0)
   1.733 +		return NULL;
   1.734 +	if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
   1.735 +		return NULL;
   1.736 +
   1.737 +	for_all_symbols(i, sym) {
   1.738 +		if (sym->flags & SYMBOL_CONST || !sym->name)
   1.739 +			continue;
   1.740 +		if (regexec(&re, sym->name, 0, NULL, 0))
   1.741 +			continue;
   1.742 +		if (cnt + 1 >= size) {
   1.743 +			void *tmp = sym_arr;
   1.744 +			size += 16;
   1.745 +			sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
   1.746 +			if (!sym_arr) {
   1.747 +				free(tmp);
   1.748 +				return NULL;
   1.749 +			}
   1.750 +		}
   1.751 +		sym_arr[cnt++] = sym;
   1.752 +	}
   1.753 +	if (sym_arr)
   1.754 +		sym_arr[cnt] = NULL;
   1.755 +	regfree(&re);
   1.756 +
   1.757 +	return sym_arr;
   1.758 +}
   1.759 +
   1.760 +
   1.761 +struct symbol *sym_check_deps(struct symbol *sym);
   1.762 +
   1.763 +static struct symbol *sym_check_expr_deps(struct expr *e)
   1.764 +{
   1.765 +	struct symbol *sym;
   1.766 +
   1.767 +	if (!e)
   1.768 +		return NULL;
   1.769 +	switch (e->type) {
   1.770 +	case E_OR:
   1.771 +	case E_AND:
   1.772 +		sym = sym_check_expr_deps(e->left.expr);
   1.773 +		if (sym)
   1.774 +			return sym;
   1.775 +		return sym_check_expr_deps(e->right.expr);
   1.776 +	case E_NOT:
   1.777 +		return sym_check_expr_deps(e->left.expr);
   1.778 +	case E_EQUAL:
   1.779 +	case E_UNEQUAL:
   1.780 +		sym = sym_check_deps(e->left.sym);
   1.781 +		if (sym)
   1.782 +			return sym;
   1.783 +		return sym_check_deps(e->right.sym);
   1.784 +	case E_SYMBOL:
   1.785 +		return sym_check_deps(e->left.sym);
   1.786 +	default:
   1.787 +		break;
   1.788 +	}
   1.789 +	printf("Oops! How to check %d?\n", e->type);
   1.790 +	return NULL;
   1.791 +}
   1.792 +
   1.793 +struct symbol *sym_check_deps(struct symbol *sym)
   1.794 +{
   1.795 +	struct symbol *sym2;
   1.796 +	struct property *prop;
   1.797 +
   1.798 +	if (sym->flags & SYMBOL_CHECK) {
   1.799 +		printf("Warning! Found recursive dependency: %s", sym->name);
   1.800 +		return sym;
   1.801 +	}
   1.802 +	if (sym->flags & SYMBOL_CHECKED)
   1.803 +		return NULL;
   1.804 +
   1.805 +	sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
   1.806 +	sym2 = sym_check_expr_deps(sym->rev_dep.expr);
   1.807 +	if (sym2)
   1.808 +		goto out;
   1.809 +
   1.810 +	for (prop = sym->prop; prop; prop = prop->next) {
   1.811 +		if (prop->type == P_CHOICE || prop->type == P_SELECT)
   1.812 +			continue;
   1.813 +		sym2 = sym_check_expr_deps(prop->visible.expr);
   1.814 +		if (sym2)
   1.815 +			goto out;
   1.816 +		if (prop->type != P_DEFAULT || sym_is_choice(sym))
   1.817 +			continue;
   1.818 +		sym2 = sym_check_expr_deps(prop->expr);
   1.819 +		if (sym2)
   1.820 +			goto out;
   1.821 +	}
   1.822 +out:
   1.823 +	if (sym2) {
   1.824 +		printf(" %s", sym->name);
   1.825 +		if (sym2 == sym) {
   1.826 +			printf("\n");
   1.827 +			sym2 = NULL;
   1.828 +		}
   1.829 +	}
   1.830 +	sym->flags &= ~SYMBOL_CHECK;
   1.831 +	return sym2;
   1.832 +}
   1.833 +
   1.834 +struct property *prop_alloc(enum prop_type type, struct symbol *sym)
   1.835 +{
   1.836 +	struct property *prop;
   1.837 +	struct property **propp;
   1.838 +
   1.839 +	prop = malloc(sizeof(*prop));
   1.840 +	memset(prop, 0, sizeof(*prop));
   1.841 +	prop->type = type;
   1.842 +	prop->sym = sym;
   1.843 +	prop->file = current_file;
   1.844 +	prop->lineno = zconf_lineno();
   1.845 +
   1.846 +	/* append property to the prop list of symbol */
   1.847 +	if (sym) {
   1.848 +		for (propp = &sym->prop; *propp; propp = &(*propp)->next)
   1.849 +			;
   1.850 +		*propp = prop;
   1.851 +	}
   1.852 +
   1.853 +	return prop;
   1.854 +}
   1.855 +
   1.856 +struct symbol *prop_get_symbol(struct property *prop)
   1.857 +{
   1.858 +	if (prop->expr && (prop->expr->type == E_SYMBOL ||
   1.859 +			   prop->expr->type == E_CHOICE))
   1.860 +		return prop->expr->left.sym;
   1.861 +	return NULL;
   1.862 +}
   1.863 +
   1.864 +const char *prop_get_type_name(enum prop_type type)
   1.865 +{
   1.866 +	switch (type) {
   1.867 +	case P_PROMPT:
   1.868 +		return "prompt";
   1.869 +	case P_COMMENT:
   1.870 +		return "comment";
   1.871 +	case P_MENU:
   1.872 +		return "menu";
   1.873 +	case P_DEFAULT:
   1.874 +		return "default";
   1.875 +	case P_CHOICE:
   1.876 +		return "choice";
   1.877 +	case P_SELECT:
   1.878 +		return "select";
   1.879 +	case P_RANGE:
   1.880 +		return "range";
   1.881 +	case P_UNKNOWN:
   1.882 +		break;
   1.883 +	}
   1.884 +	return "unknown";
   1.885 +}