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 #include "lkc.h"
13 
14 struct symbol symbol_yes = {
15 	.name = "y",
16 	.curr = { "y", yes },
17 	.flags = SYMBOL_CONST|SYMBOL_VALID,
18 }, symbol_mod = {
19 	.name = "m",
20 	.curr = { "m", mod },
21 	.flags = SYMBOL_CONST|SYMBOL_VALID,
22 }, symbol_no = {
23 	.name = "n",
24 	.curr = { "n", no },
25 	.flags = SYMBOL_CONST|SYMBOL_VALID,
26 }, symbol_empty = {
27 	.name = "",
28 	.curr = { "", no },
29 	.flags = SYMBOL_VALID,
30 };
31 
32 struct symbol *sym_defconfig_list;
33 struct symbol *modules_sym;
34 tristate modules_val;
35 
36 struct expr *sym_env_list;
37 
sym_add_default(struct symbol * sym,const char * def)38 static 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, SYMBOL_CONST));
43 }
44 
sym_init(void)45 void sym_init(void)
46 {
47 	struct symbol *sym;
48 	struct utsname uts;
49 	static bool inited = false;
50 
51 	if (inited)
52 		return;
53 	inited = true;
54 
55 	uname(&uts);
56 
57 	sym = sym_lookup("UNAME_RELEASE", 0);
58 	sym->type = S_STRING;
59 	sym->flags |= SYMBOL_AUTO;
60 	sym_add_default(sym, uts.release);
61 }
62 
sym_get_type(struct symbol * sym)63 enum symbol_type sym_get_type(struct symbol *sym)
64 {
65 	enum symbol_type type = sym->type;
66 
67 	if (type == S_TRISTATE) {
68 		if (sym_is_choice_value(sym) && sym->visible == yes)
69 			type = S_BOOLEAN;
70 		else if (modules_val == no)
71 			type = S_BOOLEAN;
72 	}
73 	return type;
74 }
75 
sym_type_name(enum symbol_type type)76 const char *sym_type_name(enum symbol_type type)
77 {
78 	switch (type) {
79 	case S_BOOLEAN:
80 		return "boolean";
81 	case S_TRISTATE:
82 		return "tristate";
83 	case S_INT:
84 		return "integer";
85 	case S_HEX:
86 		return "hex";
87 	case S_STRING:
88 		return "string";
89 	case S_UNKNOWN:
90 		return "unknown";
91 	case S_OTHER:
92 		break;
93 	}
94 	return "???";
95 }
96 
sym_get_choice_prop(struct symbol * sym)97 struct property *sym_get_choice_prop(struct symbol *sym)
98 {
99 	struct property *prop;
100 
101 	for_all_choices(sym, prop)
102 		return prop;
103 	return NULL;
104 }
105 
sym_get_env_prop(struct symbol * sym)106 struct property *sym_get_env_prop(struct symbol *sym)
107 {
108 	struct property *prop;
109 
110 	for_all_properties(sym, prop, P_ENV)
111 		return prop;
112 	return NULL;
113 }
114 
sym_get_default_prop(struct symbol * sym)115 struct property *sym_get_default_prop(struct symbol *sym)
116 {
117 	struct property *prop;
118 
119 	for_all_defaults(sym, prop) {
120 		prop->visible.tri = expr_calc_value(prop->visible.expr);
121 		if (prop->visible.tri != no)
122 			return prop;
123 	}
124 	return NULL;
125 }
126 
sym_get_range_prop(struct symbol * sym)127 static struct property *sym_get_range_prop(struct symbol *sym)
128 {
129 	struct property *prop;
130 
131 	for_all_properties(sym, prop, P_RANGE) {
132 		prop->visible.tri = expr_calc_value(prop->visible.expr);
133 		if (prop->visible.tri != no)
134 			return prop;
135 	}
136 	return NULL;
137 }
138 
sym_get_range_val(struct symbol * sym,int base)139 static int sym_get_range_val(struct symbol *sym, int base)
140 {
141 	sym_calc_value(sym);
142 	switch (sym->type) {
143 	case S_INT:
144 		base = 10;
145 		break;
146 	case S_HEX:
147 		base = 16;
148 		break;
149 	default:
150 		break;
151 	}
152 	return strtol(sym->curr.val, NULL, base);
153 }
154 
sym_validate_range(struct symbol * sym)155 static void sym_validate_range(struct symbol *sym)
156 {
157 	struct property *prop;
158 	int base, val, val2;
159 	char str[64];
160 
161 	switch (sym->type) {
162 	case S_INT:
163 		base = 10;
164 		break;
165 	case S_HEX:
166 		base = 16;
167 		break;
168 	default:
169 		return;
170 	}
171 	prop = sym_get_range_prop(sym);
172 	if (!prop)
173 		return;
174 	val = strtol(sym->curr.val, NULL, base);
175 	val2 = sym_get_range_val(prop->expr->left.sym, base);
176 	if (val >= val2) {
177 		val2 = sym_get_range_val(prop->expr->right.sym, base);
178 		if (val <= val2)
179 			return;
180 	}
181 	if (sym->type == S_INT)
182 		sprintf(str, "%d", val2);
183 	else
184 		sprintf(str, "0x%x", val2);
185 	sym->curr.val = strdup(str);
186 }
187 
sym_calc_visibility(struct symbol * sym)188 static void sym_calc_visibility(struct symbol *sym)
189 {
190 	struct property *prop;
191 	tristate tri;
192 
193 	/* any prompt visible? */
194 	tri = no;
195 	for_all_prompts(sym, prop) {
196 		prop->visible.tri = expr_calc_value(prop->visible.expr);
197 		tri = EXPR_OR(tri, prop->visible.tri);
198 	}
199 	if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
200 		tri = yes;
201 	if (sym->visible != tri) {
202 		sym->visible = tri;
203 		sym_set_changed(sym);
204 	}
205 	if (sym_is_choice_value(sym))
206 		return;
207 	/* defaulting to "yes" if no explicit "depends on" are given */
208 	tri = yes;
209 	if (sym->dir_dep.expr)
210 		tri = expr_calc_value(sym->dir_dep.expr);
211 	if (tri == mod)
212 		tri = yes;
213 	if (sym->dir_dep.tri != tri) {
214 		sym->dir_dep.tri = tri;
215 		sym_set_changed(sym);
216 	}
217 	tri = no;
218 	if (sym->rev_dep.expr)
219 		tri = expr_calc_value(sym->rev_dep.expr);
220 	if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
221 		tri = yes;
222 	if (sym->rev_dep.tri != tri) {
223 		sym->rev_dep.tri = tri;
224 		sym_set_changed(sym);
225 	}
226 }
227 
228 /*
229  * Find the default symbol for a choice.
230  * First try the default values for the choice symbol
231  * Next locate the first visible choice value
232  * Return NULL if none was found
233  */
sym_choice_default(struct symbol * sym)234 struct symbol *sym_choice_default(struct symbol *sym)
235 {
236 	struct symbol *def_sym;
237 	struct property *prop;
238 	struct expr *e;
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 		if (def_sym->visible != no)
247 			return def_sym;
248 	}
249 
250 	/* just get the first visible value */
251 	prop = sym_get_choice_prop(sym);
252 	expr_list_for_each_sym(prop->expr, e, def_sym)
253 		if (def_sym->visible != no)
254 			return def_sym;
255 
256 	/* failed to locate any defaults */
257 	return NULL;
258 }
259 
sym_calc_choice(struct symbol * sym)260 static struct symbol *sym_calc_choice(struct symbol *sym)
261 {
262 	struct symbol *def_sym;
263 	struct property *prop;
264 	struct expr *e;
265 	int flags;
266 
267 	/* first calculate all choice values' visibilities */
268 	flags = sym->flags;
269 	prop = sym_get_choice_prop(sym);
270 	expr_list_for_each_sym(prop->expr, e, def_sym) {
271 		sym_calc_visibility(def_sym);
272 		if (def_sym->visible != no)
273 			flags &= def_sym->flags;
274 	}
275 
276 	sym->flags &= flags | ~SYMBOL_DEF_USER;
277 
278 	/* is the user choice visible? */
279 	def_sym = sym->def[S_DEF_USER].val;
280 	if (def_sym && def_sym->visible != no)
281 		return def_sym;
282 
283 	def_sym = sym_choice_default(sym);
284 
285 	if (def_sym == NULL)
286 		/* no choice? reset tristate value */
287 		sym->curr.tri = no;
288 
289 	return def_sym;
290 }
291 
sym_calc_value(struct symbol * sym)292 void sym_calc_value(struct symbol *sym)
293 {
294 	struct symbol_value newval, oldval;
295 	struct property *prop;
296 	struct expr *e;
297 
298 	if (!sym)
299 		return;
300 
301 	if (sym->flags & SYMBOL_VALID)
302 		return;
303 	sym->flags |= SYMBOL_VALID;
304 
305 	oldval = sym->curr;
306 
307 	switch (sym->type) {
308 	case S_INT:
309 	case S_HEX:
310 	case S_STRING:
311 		newval = symbol_empty.curr;
312 		break;
313 	case S_BOOLEAN:
314 	case S_TRISTATE:
315 		newval = symbol_no.curr;
316 		break;
317 	default:
318 		sym->curr.val = sym->name;
319 		sym->curr.tri = no;
320 		return;
321 	}
322 	if (!sym_is_choice_value(sym))
323 		sym->flags &= ~SYMBOL_WRITE;
324 
325 	sym_calc_visibility(sym);
326 
327 	/* set default if recursively called */
328 	sym->curr = newval;
329 
330 	switch (sym_get_type(sym)) {
331 	case S_BOOLEAN:
332 	case S_TRISTATE:
333 		if (sym_is_choice_value(sym) && sym->visible == yes) {
334 			prop = sym_get_choice_prop(sym);
335 			newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
336 		} else {
337 			if (sym->visible != no) {
338 				/* if the symbol is visible use the user value
339 				 * if available, otherwise try the default value
340 				 */
341 				sym->flags |= SYMBOL_WRITE;
342 				if (sym_has_value(sym)) {
343 					newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
344 							      sym->visible);
345 					goto calc_newval;
346 				}
347 			}
348 			if (sym->rev_dep.tri != no)
349 				sym->flags |= SYMBOL_WRITE;
350 			if (!sym_is_choice(sym)) {
351 				prop = sym_get_default_prop(sym);
352 				if (prop) {
353 					sym->flags |= SYMBOL_WRITE;
354 					newval.tri = EXPR_AND(expr_calc_value(prop->expr),
355 							      prop->visible.tri);
356 				}
357 			}
358 		calc_newval:
359 			if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
360 				struct expr *e;
361 				e = expr_simplify_unmet_dep(sym->rev_dep.expr,
362 				    sym->dir_dep.expr);
363 				fprintf(stderr, "warning: (");
364 				expr_fprint(e, stderr);
365 				fprintf(stderr, ") selects %s which has unmet direct dependencies (",
366 					sym->name);
367 				expr_fprint(sym->dir_dep.expr, stderr);
368 				fprintf(stderr, ")\n");
369 				expr_free(e);
370 			}
371 			newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
372 		}
373 		if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
374 			newval.tri = yes;
375 		break;
376 	case S_STRING:
377 	case S_HEX:
378 	case S_INT:
379 		if (sym->visible != no) {
380 			sym->flags |= SYMBOL_WRITE;
381 			if (sym_has_value(sym)) {
382 				newval.val = sym->def[S_DEF_USER].val;
383 				break;
384 			}
385 		}
386 		prop = sym_get_default_prop(sym);
387 		if (prop) {
388 			struct symbol *ds = prop_get_symbol(prop);
389 			if (ds) {
390 				sym->flags |= SYMBOL_WRITE;
391 				sym_calc_value(ds);
392 				newval.val = ds->curr.val;
393 			}
394 		}
395 		break;
396 	default:
397 		;
398 	}
399 
400 	sym->curr = newval;
401 	if (sym_is_choice(sym) && newval.tri == yes)
402 		sym->curr.val = sym_calc_choice(sym);
403 	sym_validate_range(sym);
404 
405 	if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
406 		sym_set_changed(sym);
407 		if (modules_sym == sym) {
408 			sym_set_all_changed();
409 			modules_val = modules_sym->curr.tri;
410 		}
411 	}
412 
413 	if (sym_is_choice(sym)) {
414 		struct symbol *choice_sym;
415 
416 		prop = sym_get_choice_prop(sym);
417 		expr_list_for_each_sym(prop->expr, e, choice_sym) {
418 			if ((sym->flags & SYMBOL_WRITE) &&
419 			    choice_sym->visible != no)
420 				choice_sym->flags |= SYMBOL_WRITE;
421 			if (sym->flags & SYMBOL_CHANGED)
422 				sym_set_changed(choice_sym);
423 		}
424 	}
425 
426 	if (sym->flags & SYMBOL_AUTO)
427 		sym->flags &= ~SYMBOL_WRITE;
428 }
429 
sym_clear_all_valid(void)430 void sym_clear_all_valid(void)
431 {
432 	struct symbol *sym;
433 	int i;
434 
435 	for_all_symbols(i, sym)
436 		sym->flags &= ~SYMBOL_VALID;
437 	sym_add_change_count(1);
438 	if (modules_sym)
439 		sym_calc_value(modules_sym);
440 }
441 
sym_set_changed(struct symbol * sym)442 void sym_set_changed(struct symbol *sym)
443 {
444 	struct property *prop;
445 
446 	sym->flags |= SYMBOL_CHANGED;
447 	for (prop = sym->prop; prop; prop = prop->next) {
448 		if (prop->menu)
449 			prop->menu->flags |= MENU_CHANGED;
450 	}
451 }
452 
sym_set_all_changed(void)453 void sym_set_all_changed(void)
454 {
455 	struct symbol *sym;
456 	int i;
457 
458 	for_all_symbols(i, sym)
459 		sym_set_changed(sym);
460 }
461 
sym_tristate_within_range(struct symbol * sym,tristate val)462 bool sym_tristate_within_range(struct symbol *sym, tristate val)
463 {
464 	int type = sym_get_type(sym);
465 
466 	if (sym->visible == no)
467 		return false;
468 
469 	if (type != S_BOOLEAN && type != S_TRISTATE)
470 		return false;
471 
472 	if (type == S_BOOLEAN && val == mod)
473 		return false;
474 	if (sym->visible <= sym->rev_dep.tri)
475 		return false;
476 	if (sym_is_choice_value(sym) && sym->visible == yes)
477 		return val == yes;
478 	return val >= sym->rev_dep.tri && val <= sym->visible;
479 }
480 
sym_set_tristate_value(struct symbol * sym,tristate val)481 bool sym_set_tristate_value(struct symbol *sym, tristate val)
482 {
483 	tristate oldval = sym_get_tristate_value(sym);
484 
485 	if (oldval != val && !sym_tristate_within_range(sym, val))
486 		return false;
487 
488 	if (!(sym->flags & SYMBOL_DEF_USER)) {
489 		sym->flags |= SYMBOL_DEF_USER;
490 		sym_set_changed(sym);
491 	}
492 	/*
493 	 * setting a choice value also resets the new flag of the choice
494 	 * symbol and all other choice values.
495 	 */
496 	if (sym_is_choice_value(sym) && val == yes) {
497 		struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
498 		struct property *prop;
499 		struct expr *e;
500 
501 		cs->def[S_DEF_USER].val = sym;
502 		cs->flags |= SYMBOL_DEF_USER;
503 		prop = sym_get_choice_prop(cs);
504 		for (e = prop->expr; e; e = e->left.expr) {
505 			if (e->right.sym->visible != no)
506 				e->right.sym->flags |= SYMBOL_DEF_USER;
507 		}
508 	}
509 
510 	sym->def[S_DEF_USER].tri = val;
511 	if (oldval != val)
512 		sym_clear_all_valid();
513 
514 	return true;
515 }
516 
sym_toggle_tristate_value(struct symbol * sym)517 tristate sym_toggle_tristate_value(struct symbol *sym)
518 {
519 	tristate oldval, newval;
520 
521 	oldval = newval = sym_get_tristate_value(sym);
522 	do {
523 		switch (newval) {
524 		case no:
525 			newval = mod;
526 			break;
527 		case mod:
528 			newval = yes;
529 			break;
530 		case yes:
531 			newval = no;
532 			break;
533 		}
534 		if (sym_set_tristate_value(sym, newval))
535 			break;
536 	} while (oldval != newval);
537 	return newval;
538 }
539 
sym_string_valid(struct symbol * sym,const char * str)540 bool sym_string_valid(struct symbol *sym, const char *str)
541 {
542 	signed char ch;
543 
544 	switch (sym->type) {
545 	case S_STRING:
546 		return true;
547 	case S_INT:
548 		ch = *str++;
549 		if (ch == '-')
550 			ch = *str++;
551 		if (!isdigit(ch))
552 			return false;
553 		if (ch == '0' && *str != 0)
554 			return false;
555 		while ((ch = *str++)) {
556 			if (!isdigit(ch))
557 				return false;
558 		}
559 		return true;
560 	case S_HEX:
561 		if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
562 			str += 2;
563 		ch = *str++;
564 		do {
565 			if (!isxdigit(ch))
566 				return false;
567 		} while ((ch = *str++));
568 		return true;
569 	case S_BOOLEAN:
570 	case S_TRISTATE:
571 		switch (str[0]) {
572 		case 'y': case 'Y':
573 		case 'm': case 'M':
574 		case 'n': case 'N':
575 			return true;
576 		}
577 		return false;
578 	default:
579 		return false;
580 	}
581 }
582 
sym_string_within_range(struct symbol * sym,const char * str)583 bool sym_string_within_range(struct symbol *sym, const char *str)
584 {
585 	struct property *prop;
586 	int val;
587 
588 	switch (sym->type) {
589 	case S_STRING:
590 		return sym_string_valid(sym, str);
591 	case S_INT:
592 		if (!sym_string_valid(sym, str))
593 			return false;
594 		prop = sym_get_range_prop(sym);
595 		if (!prop)
596 			return true;
597 		val = strtol(str, NULL, 10);
598 		return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
599 		       val <= sym_get_range_val(prop->expr->right.sym, 10);
600 	case S_HEX:
601 		if (!sym_string_valid(sym, str))
602 			return false;
603 		prop = sym_get_range_prop(sym);
604 		if (!prop)
605 			return true;
606 		val = strtol(str, NULL, 16);
607 		return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
608 		       val <= sym_get_range_val(prop->expr->right.sym, 16);
609 	case S_BOOLEAN:
610 	case S_TRISTATE:
611 		switch (str[0]) {
612 		case 'y': case 'Y':
613 			return sym_tristate_within_range(sym, yes);
614 		case 'm': case 'M':
615 			return sym_tristate_within_range(sym, mod);
616 		case 'n': case 'N':
617 			return sym_tristate_within_range(sym, no);
618 		}
619 		return false;
620 	default:
621 		return false;
622 	}
623 }
624 
sym_set_string_value(struct symbol * sym,const char * newval)625 bool sym_set_string_value(struct symbol *sym, const char *newval)
626 {
627 	const char *oldval;
628 	char *val;
629 	int size;
630 
631 	switch (sym->type) {
632 	case S_BOOLEAN:
633 	case S_TRISTATE:
634 		switch (newval[0]) {
635 		case 'y': case 'Y':
636 			return sym_set_tristate_value(sym, yes);
637 		case 'm': case 'M':
638 			return sym_set_tristate_value(sym, mod);
639 		case 'n': case 'N':
640 			return sym_set_tristate_value(sym, no);
641 		}
642 		return false;
643 	default:
644 		;
645 	}
646 
647 	if (!sym_string_within_range(sym, newval))
648 		return false;
649 
650 	if (!(sym->flags & SYMBOL_DEF_USER)) {
651 		sym->flags |= SYMBOL_DEF_USER;
652 		sym_set_changed(sym);
653 	}
654 
655 	oldval = sym->def[S_DEF_USER].val;
656 	size = strlen(newval) + 1;
657 	if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
658 		size += 2;
659 		sym->def[S_DEF_USER].val = val = malloc(size);
660 		*val++ = '0';
661 		*val++ = 'x';
662 	} else if (!oldval || strcmp(oldval, newval))
663 		sym->def[S_DEF_USER].val = val = malloc(size);
664 	else
665 		return true;
666 
667 	strcpy(val, newval);
668 	free((void *)oldval);
669 	sym_clear_all_valid();
670 
671 	return true;
672 }
673 
674 /*
675  * Find the default value associated to a symbol.
676  * For tristate symbol handle the modules=n case
677  * in which case "m" becomes "y".
678  * If the symbol does not have any default then fallback
679  * to the fixed default values.
680  */
sym_get_string_default(struct symbol * sym)681 const char *sym_get_string_default(struct symbol *sym)
682 {
683 	struct property *prop;
684 	struct symbol *ds;
685 	const char *str;
686 	tristate val;
687 
688 	sym_calc_visibility(sym);
689 	sym_calc_value(modules_sym);
690 	val = symbol_no.curr.tri;
691 	str = symbol_empty.curr.val;
692 
693 	/* If symbol has a default value look it up */
694 	prop = sym_get_default_prop(sym);
695 	if (prop != NULL) {
696 		switch (sym->type) {
697 		case S_BOOLEAN:
698 		case S_TRISTATE:
699 			/* The visibility may limit the value from yes => mod */
700 			val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
701 			break;
702 		default:
703 			/*
704 			 * The following fails to handle the situation
705 			 * where a default value is further limited by
706 			 * the valid range.
707 			 */
708 			ds = prop_get_symbol(prop);
709 			if (ds != NULL) {
710 				sym_calc_value(ds);
711 				str = (const char *)ds->curr.val;
712 			}
713 		}
714 	}
715 
716 	/* Handle select statements */
717 	val = EXPR_OR(val, sym->rev_dep.tri);
718 
719 	/* transpose mod to yes if modules are not enabled */
720 	if (val == mod)
721 		if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
722 			val = yes;
723 
724 	/* transpose mod to yes if type is bool */
725 	if (sym->type == S_BOOLEAN && val == mod)
726 		val = yes;
727 
728 	switch (sym->type) {
729 	case S_BOOLEAN:
730 	case S_TRISTATE:
731 		switch (val) {
732 		case no: return "n";
733 		case mod: return "m";
734 		case yes: return "y";
735 		}
736 	case S_INT:
737 	case S_HEX:
738 		return str;
739 	case S_STRING:
740 		return str;
741 	case S_OTHER:
742 	case S_UNKNOWN:
743 		break;
744 	}
745 	return "";
746 }
747 
sym_get_string_value(struct symbol * sym)748 const char *sym_get_string_value(struct symbol *sym)
749 {
750 	tristate val;
751 
752 	switch (sym->type) {
753 	case S_BOOLEAN:
754 	case S_TRISTATE:
755 		val = sym_get_tristate_value(sym);
756 		switch (val) {
757 		case no:
758 			return "n";
759 		case mod:
760 			sym_calc_value(modules_sym);
761 			return (modules_sym->curr.tri == no) ? "n" : "m";
762 		case yes:
763 			return "y";
764 		}
765 		break;
766 	default:
767 		;
768 	}
769 	return (const char *)sym->curr.val;
770 }
771 
sym_is_changable(struct symbol * sym)772 bool sym_is_changable(struct symbol *sym)
773 {
774 	return sym->visible > sym->rev_dep.tri;
775 }
776 
strhash(const char * s)777 static unsigned strhash(const char *s)
778 {
779 	/* fnv32 hash */
780 	unsigned hash = 2166136261U;
781 	for (; *s; s++)
782 		hash = (hash ^ *s) * 0x01000193;
783 	return hash;
784 }
785 
sym_lookup(const char * name,int flags)786 struct symbol *sym_lookup(const char *name, int flags)
787 {
788 	struct symbol *symbol;
789 	char *new_name;
790 	int hash;
791 
792 	if (name) {
793 		if (name[0] && !name[1]) {
794 			switch (name[0]) {
795 			case 'y': return &symbol_yes;
796 			case 'm': return &symbol_mod;
797 			case 'n': return &symbol_no;
798 			}
799 		}
800 		hash = strhash(name) % SYMBOL_HASHSIZE;
801 
802 		for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
803 			if (symbol->name &&
804 			    !strcmp(symbol->name, name) &&
805 			    (flags ? symbol->flags & flags
806 				   : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
807 				return symbol;
808 		}
809 		new_name = strdup(name);
810 	} else {
811 		new_name = NULL;
812 		hash = 0;
813 	}
814 
815 	symbol = malloc(sizeof(*symbol));
816 	memset(symbol, 0, sizeof(*symbol));
817 	symbol->name = new_name;
818 	symbol->type = S_UNKNOWN;
819 	symbol->flags |= flags;
820 
821 	symbol->next = symbol_hash[hash];
822 	symbol_hash[hash] = symbol;
823 
824 	return symbol;
825 }
826 
sym_find(const char * name)827 struct symbol *sym_find(const char *name)
828 {
829 	struct symbol *symbol = NULL;
830 	int hash = 0;
831 
832 	if (!name)
833 		return NULL;
834 
835 	if (name[0] && !name[1]) {
836 		switch (name[0]) {
837 		case 'y': return &symbol_yes;
838 		case 'm': return &symbol_mod;
839 		case 'n': return &symbol_no;
840 		}
841 	}
842 	hash = strhash(name) % SYMBOL_HASHSIZE;
843 
844 	for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
845 		if (symbol->name &&
846 		    !strcmp(symbol->name, name) &&
847 		    !(symbol->flags & SYMBOL_CONST))
848 				break;
849 	}
850 
851 	return symbol;
852 }
853 
854 /*
855  * Expand symbol's names embedded in the string given in argument. Symbols'
856  * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
857  * the empty string.
858  */
sym_expand_string_value(const char * in)859 const char *sym_expand_string_value(const char *in)
860 {
861 	const char *src;
862 	char *res;
863 	size_t reslen;
864 
865 	reslen = strlen(in) + 1;
866 	res = malloc(reslen);
867 	res[0] = '\0';
868 
869 	while ((src = strchr(in, '$'))) {
870 		char *p, name[SYMBOL_MAXLENGTH];
871 		const char *symval = "";
872 		struct symbol *sym;
873 		size_t newlen;
874 
875 		strncat(res, in, src - in);
876 		src++;
877 
878 		p = name;
879 		while (isalnum(*src) || *src == '_')
880 			*p++ = *src++;
881 		*p = '\0';
882 
883 		sym = sym_find(name);
884 		if (sym != NULL) {
885 			sym_calc_value(sym);
886 			symval = sym_get_string_value(sym);
887 		}
888 
889 		newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
890 		if (newlen > reslen) {
891 			reslen = newlen;
892 			res = realloc(res, reslen);
893 		}
894 
895 		strcat(res, symval);
896 		in = src;
897 	}
898 	strcat(res, in);
899 
900 	return res;
901 }
902 
sym_escape_string_value(const char * in)903 const char *sym_escape_string_value(const char *in)
904 {
905 	const char *p;
906 	size_t reslen;
907 	char *res;
908 	size_t l;
909 
910 	reslen = strlen(in) + strlen("\"\"") + 1;
911 
912 	p = in;
913 	for (;;) {
914 		l = strcspn(p, "\"\\");
915 		p += l;
916 
917 		if (p[0] == '\0')
918 			break;
919 
920 		reslen++;
921 		p++;
922 	}
923 
924 	res = malloc(reslen);
925 	res[0] = '\0';
926 
927 	strcat(res, "\"");
928 
929 	p = in;
930 	for (;;) {
931 		l = strcspn(p, "\"\\");
932 		strncat(res, p, l);
933 		p += l;
934 
935 		if (p[0] == '\0')
936 			break;
937 
938 		strcat(res, "\\");
939 		strncat(res, p++, 1);
940 	}
941 
942 	strcat(res, "\"");
943 	return res;
944 }
945 
sym_re_search(const char * pattern)946 struct symbol **sym_re_search(const char *pattern)
947 {
948 	struct symbol *sym, **sym_arr = NULL;
949 	int i, cnt, size;
950 	regex_t re;
951 
952 	cnt = size = 0;
953 	/* Skip if empty */
954 	if (strlen(pattern) == 0)
955 		return NULL;
956 	if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
957 		return NULL;
958 
959 	for_all_symbols(i, sym) {
960 		if (sym->flags & SYMBOL_CONST || !sym->name)
961 			continue;
962 		if (regexec(&re, sym->name, 0, NULL, 0))
963 			continue;
964 		if (cnt + 1 >= size) {
965 			void *tmp = sym_arr;
966 			size += 16;
967 			sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
968 			if (!sym_arr) {
969 				free(tmp);
970 				return NULL;
971 			}
972 		}
973 		sym_calc_value(sym);
974 		sym_arr[cnt++] = sym;
975 	}
976 	if (sym_arr)
977 		sym_arr[cnt] = NULL;
978 	regfree(&re);
979 
980 	return sym_arr;
981 }
982 
983 /*
984  * When we check for recursive dependencies we use a stack to save
985  * current state so we can print out relevant info to user.
986  * The entries are located on the call stack so no need to free memory.
987  * Note inser() remove() must always match to properly clear the stack.
988  */
989 static struct dep_stack {
990 	struct dep_stack *prev, *next;
991 	struct symbol *sym;
992 	struct property *prop;
993 	struct expr *expr;
994 } *check_top;
995 
dep_stack_insert(struct dep_stack * stack,struct symbol * sym)996 static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
997 {
998 	memset(stack, 0, sizeof(*stack));
999 	if (check_top)
1000 		check_top->next = stack;
1001 	stack->prev = check_top;
1002 	stack->sym = sym;
1003 	check_top = stack;
1004 }
1005 
dep_stack_remove(void)1006 static void dep_stack_remove(void)
1007 {
1008 	check_top = check_top->prev;
1009 	if (check_top)
1010 		check_top->next = NULL;
1011 }
1012 
1013 /*
1014  * Called when we have detected a recursive dependency.
1015  * check_top point to the top of the stact so we use
1016  * the ->prev pointer to locate the bottom of the stack.
1017  */
sym_check_print_recursive(struct symbol * last_sym)1018 static void sym_check_print_recursive(struct symbol *last_sym)
1019 {
1020 	struct dep_stack *stack;
1021 	struct symbol *sym, *next_sym;
1022 	struct menu *menu = NULL;
1023 	struct property *prop;
1024 	struct dep_stack cv_stack;
1025 
1026 	if (sym_is_choice_value(last_sym)) {
1027 		dep_stack_insert(&cv_stack, last_sym);
1028 		last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
1029 	}
1030 
1031 	for (stack = check_top; stack != NULL; stack = stack->prev)
1032 		if (stack->sym == last_sym)
1033 			break;
1034 	if (!stack) {
1035 		fprintf(stderr, "unexpected recursive dependency error\n");
1036 		return;
1037 	}
1038 
1039 	for (; stack; stack = stack->next) {
1040 		sym = stack->sym;
1041 		next_sym = stack->next ? stack->next->sym : last_sym;
1042 		prop = stack->prop;
1043 		if (prop == NULL)
1044 			prop = stack->sym->prop;
1045 
1046 		/* for choice values find the menu entry (used below) */
1047 		if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
1048 			for (prop = sym->prop; prop; prop = prop->next) {
1049 				menu = prop->menu;
1050 				if (prop->menu)
1051 					break;
1052 			}
1053 		}
1054 		if (stack->sym == last_sym)
1055 			fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
1056 				prop->file->name, prop->lineno);
1057 		if (stack->expr) {
1058 			fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
1059 				prop->file->name, prop->lineno,
1060 				sym->name ? sym->name : "<choice>",
1061 				prop_get_type_name(prop->type),
1062 				next_sym->name ? next_sym->name : "<choice>");
1063 		} else if (stack->prop) {
1064 			fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
1065 				prop->file->name, prop->lineno,
1066 				sym->name ? sym->name : "<choice>",
1067 				next_sym->name ? next_sym->name : "<choice>");
1068 		} else if (sym_is_choice(sym)) {
1069 			fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
1070 				menu->file->name, menu->lineno,
1071 				sym->name ? sym->name : "<choice>",
1072 				next_sym->name ? next_sym->name : "<choice>");
1073 		} else if (sym_is_choice_value(sym)) {
1074 			fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
1075 				menu->file->name, menu->lineno,
1076 				sym->name ? sym->name : "<choice>",
1077 				next_sym->name ? next_sym->name : "<choice>");
1078 		} else {
1079 			fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
1080 				prop->file->name, prop->lineno,
1081 				sym->name ? sym->name : "<choice>",
1082 				next_sym->name ? next_sym->name : "<choice>");
1083 		}
1084 	}
1085 
1086 	if (check_top == &cv_stack)
1087 		dep_stack_remove();
1088 }
1089 
sym_check_expr_deps(struct expr * e)1090 static struct symbol *sym_check_expr_deps(struct expr *e)
1091 {
1092 	struct symbol *sym;
1093 
1094 	if (!e)
1095 		return NULL;
1096 	switch (e->type) {
1097 	case E_OR:
1098 	case E_AND:
1099 		sym = sym_check_expr_deps(e->left.expr);
1100 		if (sym)
1101 			return sym;
1102 		return sym_check_expr_deps(e->right.expr);
1103 	case E_NOT:
1104 		return sym_check_expr_deps(e->left.expr);
1105 	case E_EQUAL:
1106 	case E_UNEQUAL:
1107 		sym = sym_check_deps(e->left.sym);
1108 		if (sym)
1109 			return sym;
1110 		return sym_check_deps(e->right.sym);
1111 	case E_SYMBOL:
1112 		return sym_check_deps(e->left.sym);
1113 	default:
1114 		break;
1115 	}
1116 	printf("Oops! How to check %d?\n", e->type);
1117 	return NULL;
1118 }
1119 
1120 /* return NULL when dependencies are OK */
sym_check_sym_deps(struct symbol * sym)1121 static struct symbol *sym_check_sym_deps(struct symbol *sym)
1122 {
1123 	struct symbol *sym2;
1124 	struct property *prop;
1125 	struct dep_stack stack;
1126 
1127 	dep_stack_insert(&stack, sym);
1128 
1129 	sym2 = sym_check_expr_deps(sym->rev_dep.expr);
1130 	if (sym2)
1131 		goto out;
1132 
1133 	for (prop = sym->prop; prop; prop = prop->next) {
1134 		if (prop->type == P_CHOICE || prop->type == P_SELECT)
1135 			continue;
1136 		stack.prop = prop;
1137 		sym2 = sym_check_expr_deps(prop->visible.expr);
1138 		if (sym2)
1139 			break;
1140 		if (prop->type != P_DEFAULT || sym_is_choice(sym))
1141 			continue;
1142 		stack.expr = prop->expr;
1143 		sym2 = sym_check_expr_deps(prop->expr);
1144 		if (sym2)
1145 			break;
1146 		stack.expr = NULL;
1147 	}
1148 
1149 out:
1150 	dep_stack_remove();
1151 
1152 	return sym2;
1153 }
1154 
sym_check_choice_deps(struct symbol * choice)1155 static struct symbol *sym_check_choice_deps(struct symbol *choice)
1156 {
1157 	struct symbol *sym, *sym2;
1158 	struct property *prop;
1159 	struct expr *e;
1160 	struct dep_stack stack;
1161 
1162 	dep_stack_insert(&stack, choice);
1163 
1164 	prop = sym_get_choice_prop(choice);
1165 	expr_list_for_each_sym(prop->expr, e, sym)
1166 		sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1167 
1168 	choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1169 	sym2 = sym_check_sym_deps(choice);
1170 	choice->flags &= ~SYMBOL_CHECK;
1171 	if (sym2)
1172 		goto out;
1173 
1174 	expr_list_for_each_sym(prop->expr, e, sym) {
1175 		sym2 = sym_check_sym_deps(sym);
1176 		if (sym2)
1177 			break;
1178 	}
1179 out:
1180 	expr_list_for_each_sym(prop->expr, e, sym)
1181 		sym->flags &= ~SYMBOL_CHECK;
1182 
1183 	if (sym2 && sym_is_choice_value(sym2) &&
1184 	    prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
1185 		sym2 = choice;
1186 
1187 	dep_stack_remove();
1188 
1189 	return sym2;
1190 }
1191 
sym_check_deps(struct symbol * sym)1192 struct symbol *sym_check_deps(struct symbol *sym)
1193 {
1194 	struct symbol *sym2;
1195 	struct property *prop;
1196 
1197 	if (sym->flags & SYMBOL_CHECK) {
1198 		sym_check_print_recursive(sym);
1199 		return sym;
1200 	}
1201 	if (sym->flags & SYMBOL_CHECKED)
1202 		return NULL;
1203 
1204 	if (sym_is_choice_value(sym)) {
1205 		struct dep_stack stack;
1206 
1207 		/* for choice groups start the check with main choice symbol */
1208 		dep_stack_insert(&stack, sym);
1209 		prop = sym_get_choice_prop(sym);
1210 		sym2 = sym_check_deps(prop_get_symbol(prop));
1211 		dep_stack_remove();
1212 	} else if (sym_is_choice(sym)) {
1213 		sym2 = sym_check_choice_deps(sym);
1214 	} else {
1215 		sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
1216 		sym2 = sym_check_sym_deps(sym);
1217 		sym->flags &= ~SYMBOL_CHECK;
1218 	}
1219 
1220 	if (sym2 && sym2 == sym)
1221 		sym2 = NULL;
1222 
1223 	return sym2;
1224 }
1225 
prop_alloc(enum prop_type type,struct symbol * sym)1226 struct property *prop_alloc(enum prop_type type, struct symbol *sym)
1227 {
1228 	struct property *prop;
1229 	struct property **propp;
1230 
1231 	prop = malloc(sizeof(*prop));
1232 	memset(prop, 0, sizeof(*prop));
1233 	prop->type = type;
1234 	prop->sym = sym;
1235 	prop->file = current_file;
1236 	prop->lineno = zconf_lineno();
1237 
1238 	/* append property to the prop list of symbol */
1239 	if (sym) {
1240 		for (propp = &sym->prop; *propp; propp = &(*propp)->next)
1241 			;
1242 		*propp = prop;
1243 	}
1244 
1245 	return prop;
1246 }
1247 
prop_get_symbol(struct property * prop)1248 struct symbol *prop_get_symbol(struct property *prop)
1249 {
1250 	if (prop->expr && (prop->expr->type == E_SYMBOL ||
1251 			   prop->expr->type == E_LIST))
1252 		return prop->expr->left.sym;
1253 	return NULL;
1254 }
1255 
prop_get_type_name(enum prop_type type)1256 const char *prop_get_type_name(enum prop_type type)
1257 {
1258 	switch (type) {
1259 	case P_PROMPT:
1260 		return "prompt";
1261 	case P_ENV:
1262 		return "env";
1263 	case P_COMMENT:
1264 		return "comment";
1265 	case P_MENU:
1266 		return "menu";
1267 	case P_DEFAULT:
1268 		return "default";
1269 	case P_CHOICE:
1270 		return "choice";
1271 	case P_SELECT:
1272 		return "select";
1273 	case P_RANGE:
1274 		return "range";
1275 	case P_SYMBOL:
1276 		return "symbol";
1277 	case P_UNKNOWN:
1278 		break;
1279 	}
1280 	return "unknown";
1281 }
1282 
prop_add_env(const char * env)1283 static void prop_add_env(const char *env)
1284 {
1285 	struct symbol *sym, *sym2;
1286 	struct property *prop;
1287 	char *p;
1288 
1289 	sym = current_entry->sym;
1290 	sym->flags |= SYMBOL_AUTO;
1291 	for_all_properties(sym, prop, P_ENV) {
1292 		sym2 = prop_get_symbol(prop);
1293 		if (strcmp(sym2->name, env))
1294 			menu_warn(current_entry, "redefining environment symbol from %s",
1295 				  sym2->name);
1296 		return;
1297 	}
1298 
1299 	prop = prop_alloc(P_ENV, sym);
1300 	prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
1301 
1302 	sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
1303 	sym_env_list->right.sym = sym;
1304 
1305 	p = getenv(env);
1306 	if (p)
1307 		sym_add_default(sym, p);
1308 	else
1309 		menu_warn(current_entry, "environment variable %s undefined", env);
1310 }
1311