kconfig/symbol.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Sat Feb 24 11:00:05 2007 +0000 (2007-02-24)
changeset 1 eeea35fbf182
child 39 af42eec9d383
permissions -rw-r--r--
Add the full crosstool-NG sources to the new repository of its own.
You might just say: 'Yeah! crosstool-NG's got its own repo!".
Unfortunately, that's because the previous repo got damaged beyond repair and I had no backup.
That means I'm putting backups in place in the afternoon.
That also means we've lost history... :-(
     1 /*
     2  * Copyright (C) 2002 Roman Zippel <zippel@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("PROJECTVERSION", 0);
    66 	sym->type = S_STRING;
    67 	sym->flags |= SYMBOL_AUTO;
    68 	p = getenv("PROJECTVERSION");
    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 }