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