kconfig/symbol.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Tue Oct 14 20:06:37 2008 +0000 (2008-10-14)
changeset 934 e2f4be0feb9d
parent 1 eeea35fbf182
child 943 1cca90ce0481
permissions -rw-r--r--
Correctly auto-complete with start-steps as well.

/trunk/ct-ng.comp | 2 1 1 0 +-
1 file changed, 1 insertion(+), 1 deletion(-)
     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 }