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