kconfig/symbol.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Sun Jul 13 10:32:38 2008 +0000 (2008-07-13)
changeset 645 8e58024f8e37
parent 1 eeea35fbf182
child 943 1cca90ce0481
permissions -rw-r--r--
Ioannis E. VENETIS <venetis@mail.capsl.udel.edu> pointed out that GMP and MPFR were not used by gcc.
Turned out that none could use GMP and MPFR as the config option changed its name, but the change was not propagated to all users.

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