xref: /aosp_15_r20/external/toybox/kconfig/menu.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /*
2*cf5a6c84SAndroid Build Coastguard Worker  * Copyright (C) 2002 Roman Zippel <[email protected]>
3*cf5a6c84SAndroid Build Coastguard Worker  * Released under the terms of the GNU GPL v2.0.
4*cf5a6c84SAndroid Build Coastguard Worker  */
5*cf5a6c84SAndroid Build Coastguard Worker 
6*cf5a6c84SAndroid Build Coastguard Worker #include <stdlib.h>
7*cf5a6c84SAndroid Build Coastguard Worker #include <string.h>
8*cf5a6c84SAndroid Build Coastguard Worker 
9*cf5a6c84SAndroid Build Coastguard Worker #define LKC_DIRECT_LINK
10*cf5a6c84SAndroid Build Coastguard Worker #include "lkc.h"
11*cf5a6c84SAndroid Build Coastguard Worker 
12*cf5a6c84SAndroid Build Coastguard Worker struct menu rootmenu;
13*cf5a6c84SAndroid Build Coastguard Worker static struct menu **last_entry_ptr;
14*cf5a6c84SAndroid Build Coastguard Worker 
15*cf5a6c84SAndroid Build Coastguard Worker struct file *file_list;
16*cf5a6c84SAndroid Build Coastguard Worker struct file *current_file;
17*cf5a6c84SAndroid Build Coastguard Worker 
menu_warn(struct menu * menu,const char * fmt,...)18*cf5a6c84SAndroid Build Coastguard Worker static void menu_warn(struct menu *menu, const char *fmt, ...)
19*cf5a6c84SAndroid Build Coastguard Worker {
20*cf5a6c84SAndroid Build Coastguard Worker 	va_list ap;
21*cf5a6c84SAndroid Build Coastguard Worker 	va_start(ap, fmt);
22*cf5a6c84SAndroid Build Coastguard Worker 	fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
23*cf5a6c84SAndroid Build Coastguard Worker 	vfprintf(stderr, fmt, ap);
24*cf5a6c84SAndroid Build Coastguard Worker 	fprintf(stderr, "\n");
25*cf5a6c84SAndroid Build Coastguard Worker 	va_end(ap);
26*cf5a6c84SAndroid Build Coastguard Worker }
27*cf5a6c84SAndroid Build Coastguard Worker 
prop_warn(struct property * prop,const char * fmt,...)28*cf5a6c84SAndroid Build Coastguard Worker static void prop_warn(struct property *prop, const char *fmt, ...)
29*cf5a6c84SAndroid Build Coastguard Worker {
30*cf5a6c84SAndroid Build Coastguard Worker 	va_list ap;
31*cf5a6c84SAndroid Build Coastguard Worker 	va_start(ap, fmt);
32*cf5a6c84SAndroid Build Coastguard Worker 	fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
33*cf5a6c84SAndroid Build Coastguard Worker 	vfprintf(stderr, fmt, ap);
34*cf5a6c84SAndroid Build Coastguard Worker 	fprintf(stderr, "\n");
35*cf5a6c84SAndroid Build Coastguard Worker 	va_end(ap);
36*cf5a6c84SAndroid Build Coastguard Worker }
37*cf5a6c84SAndroid Build Coastguard Worker 
menu_init(void)38*cf5a6c84SAndroid Build Coastguard Worker void menu_init(void)
39*cf5a6c84SAndroid Build Coastguard Worker {
40*cf5a6c84SAndroid Build Coastguard Worker 	current_entry = current_menu = &rootmenu;
41*cf5a6c84SAndroid Build Coastguard Worker 	last_entry_ptr = &rootmenu.list;
42*cf5a6c84SAndroid Build Coastguard Worker }
43*cf5a6c84SAndroid Build Coastguard Worker 
menu_add_entry(struct symbol * sym)44*cf5a6c84SAndroid Build Coastguard Worker void menu_add_entry(struct symbol *sym)
45*cf5a6c84SAndroid Build Coastguard Worker {
46*cf5a6c84SAndroid Build Coastguard Worker 	struct menu *menu;
47*cf5a6c84SAndroid Build Coastguard Worker 
48*cf5a6c84SAndroid Build Coastguard Worker 	menu = malloc(sizeof(*menu));
49*cf5a6c84SAndroid Build Coastguard Worker 	memset(menu, 0, sizeof(*menu));
50*cf5a6c84SAndroid Build Coastguard Worker 	menu->sym = sym;
51*cf5a6c84SAndroid Build Coastguard Worker 	menu->parent = current_menu;
52*cf5a6c84SAndroid Build Coastguard Worker 	menu->file = current_file;
53*cf5a6c84SAndroid Build Coastguard Worker 	menu->lineno = zconf_lineno();
54*cf5a6c84SAndroid Build Coastguard Worker 
55*cf5a6c84SAndroid Build Coastguard Worker 	*last_entry_ptr = menu;
56*cf5a6c84SAndroid Build Coastguard Worker 	last_entry_ptr = &menu->next;
57*cf5a6c84SAndroid Build Coastguard Worker 	current_entry = menu;
58*cf5a6c84SAndroid Build Coastguard Worker }
59*cf5a6c84SAndroid Build Coastguard Worker 
menu_end_entry(void)60*cf5a6c84SAndroid Build Coastguard Worker void menu_end_entry(void)
61*cf5a6c84SAndroid Build Coastguard Worker {
62*cf5a6c84SAndroid Build Coastguard Worker }
63*cf5a6c84SAndroid Build Coastguard Worker 
menu_add_menu(void)64*cf5a6c84SAndroid Build Coastguard Worker struct menu *menu_add_menu(void)
65*cf5a6c84SAndroid Build Coastguard Worker {
66*cf5a6c84SAndroid Build Coastguard Worker 	menu_end_entry();
67*cf5a6c84SAndroid Build Coastguard Worker 	last_entry_ptr = &current_entry->list;
68*cf5a6c84SAndroid Build Coastguard Worker 	return current_menu = current_entry;
69*cf5a6c84SAndroid Build Coastguard Worker }
70*cf5a6c84SAndroid Build Coastguard Worker 
menu_end_menu(void)71*cf5a6c84SAndroid Build Coastguard Worker void menu_end_menu(void)
72*cf5a6c84SAndroid Build Coastguard Worker {
73*cf5a6c84SAndroid Build Coastguard Worker 	last_entry_ptr = &current_menu->next;
74*cf5a6c84SAndroid Build Coastguard Worker 	current_menu = current_menu->parent;
75*cf5a6c84SAndroid Build Coastguard Worker }
76*cf5a6c84SAndroid Build Coastguard Worker 
menu_check_dep(struct expr * e)77*cf5a6c84SAndroid Build Coastguard Worker struct expr *menu_check_dep(struct expr *e)
78*cf5a6c84SAndroid Build Coastguard Worker {
79*cf5a6c84SAndroid Build Coastguard Worker 	if (!e)
80*cf5a6c84SAndroid Build Coastguard Worker 		return e;
81*cf5a6c84SAndroid Build Coastguard Worker 
82*cf5a6c84SAndroid Build Coastguard Worker 	switch (e->type) {
83*cf5a6c84SAndroid Build Coastguard Worker 	case E_NOT:
84*cf5a6c84SAndroid Build Coastguard Worker 		e->left.expr = menu_check_dep(e->left.expr);
85*cf5a6c84SAndroid Build Coastguard Worker 		break;
86*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
87*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
88*cf5a6c84SAndroid Build Coastguard Worker 		e->left.expr = menu_check_dep(e->left.expr);
89*cf5a6c84SAndroid Build Coastguard Worker 		e->right.expr = menu_check_dep(e->right.expr);
90*cf5a6c84SAndroid Build Coastguard Worker 		break;
91*cf5a6c84SAndroid Build Coastguard Worker 	case E_SYMBOL:
92*cf5a6c84SAndroid Build Coastguard Worker 		/* change 'm' into 'm' && MODULES */
93*cf5a6c84SAndroid Build Coastguard Worker 		if (e->left.sym == &symbol_mod)
94*cf5a6c84SAndroid Build Coastguard Worker 			return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
95*cf5a6c84SAndroid Build Coastguard Worker 		break;
96*cf5a6c84SAndroid Build Coastguard Worker 	default:
97*cf5a6c84SAndroid Build Coastguard Worker 		break;
98*cf5a6c84SAndroid Build Coastguard Worker 	}
99*cf5a6c84SAndroid Build Coastguard Worker 	return e;
100*cf5a6c84SAndroid Build Coastguard Worker }
101*cf5a6c84SAndroid Build Coastguard Worker 
menu_add_dep(struct expr * dep)102*cf5a6c84SAndroid Build Coastguard Worker void menu_add_dep(struct expr *dep)
103*cf5a6c84SAndroid Build Coastguard Worker {
104*cf5a6c84SAndroid Build Coastguard Worker 	current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
105*cf5a6c84SAndroid Build Coastguard Worker }
106*cf5a6c84SAndroid Build Coastguard Worker 
menu_set_type(int type)107*cf5a6c84SAndroid Build Coastguard Worker void menu_set_type(int type)
108*cf5a6c84SAndroid Build Coastguard Worker {
109*cf5a6c84SAndroid Build Coastguard Worker 	struct symbol *sym = current_entry->sym;
110*cf5a6c84SAndroid Build Coastguard Worker 
111*cf5a6c84SAndroid Build Coastguard Worker 	if (sym->type == type)
112*cf5a6c84SAndroid Build Coastguard Worker 		return;
113*cf5a6c84SAndroid Build Coastguard Worker 	if (sym->type == S_UNKNOWN) {
114*cf5a6c84SAndroid Build Coastguard Worker 		sym->type = type;
115*cf5a6c84SAndroid Build Coastguard Worker 		return;
116*cf5a6c84SAndroid Build Coastguard Worker 	}
117*cf5a6c84SAndroid Build Coastguard Worker 	menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
118*cf5a6c84SAndroid Build Coastguard Worker 	    sym->name ? sym->name : "<choice>",
119*cf5a6c84SAndroid Build Coastguard Worker 	    sym_type_name(sym->type), sym_type_name(type));
120*cf5a6c84SAndroid Build Coastguard Worker }
121*cf5a6c84SAndroid Build Coastguard Worker 
menu_add_prop(enum prop_type type,char * prompt,struct expr * expr,struct expr * dep)122*cf5a6c84SAndroid Build Coastguard Worker struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
123*cf5a6c84SAndroid Build Coastguard Worker {
124*cf5a6c84SAndroid Build Coastguard Worker 	struct property *prop = prop_alloc(type, current_entry->sym);
125*cf5a6c84SAndroid Build Coastguard Worker 
126*cf5a6c84SAndroid Build Coastguard Worker 	prop->menu = current_entry;
127*cf5a6c84SAndroid Build Coastguard Worker 	prop->expr = expr;
128*cf5a6c84SAndroid Build Coastguard Worker 	prop->visible.expr = menu_check_dep(dep);
129*cf5a6c84SAndroid Build Coastguard Worker 
130*cf5a6c84SAndroid Build Coastguard Worker 	if (prompt) {
131*cf5a6c84SAndroid Build Coastguard Worker 		if (isspace(*prompt)) {
132*cf5a6c84SAndroid Build Coastguard Worker 			prop_warn(prop, "leading whitespace ignored");
133*cf5a6c84SAndroid Build Coastguard Worker 			while (isspace(*prompt))
134*cf5a6c84SAndroid Build Coastguard Worker 				prompt++;
135*cf5a6c84SAndroid Build Coastguard Worker 		}
136*cf5a6c84SAndroid Build Coastguard Worker 		if (current_entry->prompt)
137*cf5a6c84SAndroid Build Coastguard Worker 			prop_warn(prop, "prompt redefined");
138*cf5a6c84SAndroid Build Coastguard Worker 		current_entry->prompt = prop;
139*cf5a6c84SAndroid Build Coastguard Worker 	}
140*cf5a6c84SAndroid Build Coastguard Worker 	prop->text = prompt;
141*cf5a6c84SAndroid Build Coastguard Worker 
142*cf5a6c84SAndroid Build Coastguard Worker 	return prop;
143*cf5a6c84SAndroid Build Coastguard Worker }
144*cf5a6c84SAndroid Build Coastguard Worker 
menu_add_prompt(enum prop_type type,char * prompt,struct expr * dep)145*cf5a6c84SAndroid Build Coastguard Worker struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
146*cf5a6c84SAndroid Build Coastguard Worker {
147*cf5a6c84SAndroid Build Coastguard Worker 	return menu_add_prop(type, prompt, NULL, dep);
148*cf5a6c84SAndroid Build Coastguard Worker }
149*cf5a6c84SAndroid Build Coastguard Worker 
menu_add_expr(enum prop_type type,struct expr * expr,struct expr * dep)150*cf5a6c84SAndroid Build Coastguard Worker void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
151*cf5a6c84SAndroid Build Coastguard Worker {
152*cf5a6c84SAndroid Build Coastguard Worker 	menu_add_prop(type, NULL, expr, dep);
153*cf5a6c84SAndroid Build Coastguard Worker }
154*cf5a6c84SAndroid Build Coastguard Worker 
menu_add_symbol(enum prop_type type,struct symbol * sym,struct expr * dep)155*cf5a6c84SAndroid Build Coastguard Worker void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
156*cf5a6c84SAndroid Build Coastguard Worker {
157*cf5a6c84SAndroid Build Coastguard Worker 	menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
158*cf5a6c84SAndroid Build Coastguard Worker }
159*cf5a6c84SAndroid Build Coastguard Worker 
menu_add_option(int token,char * arg)160*cf5a6c84SAndroid Build Coastguard Worker void menu_add_option(int token, char *arg)
161*cf5a6c84SAndroid Build Coastguard Worker {
162*cf5a6c84SAndroid Build Coastguard Worker 	struct property *prop;
163*cf5a6c84SAndroid Build Coastguard Worker 
164*cf5a6c84SAndroid Build Coastguard Worker 	switch (token) {
165*cf5a6c84SAndroid Build Coastguard Worker 	case T_OPT_MODULES:
166*cf5a6c84SAndroid Build Coastguard Worker 		prop = prop_alloc(P_DEFAULT, modules_sym);
167*cf5a6c84SAndroid Build Coastguard Worker 		prop->expr = expr_alloc_symbol(current_entry->sym);
168*cf5a6c84SAndroid Build Coastguard Worker 		break;
169*cf5a6c84SAndroid Build Coastguard Worker 	case T_OPT_DEFCONFIG_LIST:
170*cf5a6c84SAndroid Build Coastguard Worker 		if (!sym_defconfig_list)
171*cf5a6c84SAndroid Build Coastguard Worker 			sym_defconfig_list = current_entry->sym;
172*cf5a6c84SAndroid Build Coastguard Worker 		else if (sym_defconfig_list != current_entry->sym)
173*cf5a6c84SAndroid Build Coastguard Worker 			zconf_error("trying to redefine defconfig symbol");
174*cf5a6c84SAndroid Build Coastguard Worker 		break;
175*cf5a6c84SAndroid Build Coastguard Worker 	}
176*cf5a6c84SAndroid Build Coastguard Worker }
177*cf5a6c84SAndroid Build Coastguard Worker 
menu_range_valid_sym(struct symbol * sym,struct symbol * sym2)178*cf5a6c84SAndroid Build Coastguard Worker static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
179*cf5a6c84SAndroid Build Coastguard Worker {
180*cf5a6c84SAndroid Build Coastguard Worker 	return sym2->type == S_INT || sym2->type == S_HEX ||
181*cf5a6c84SAndroid Build Coastguard Worker 	       (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
182*cf5a6c84SAndroid Build Coastguard Worker }
183*cf5a6c84SAndroid Build Coastguard Worker 
sym_check_prop(struct symbol * sym)184*cf5a6c84SAndroid Build Coastguard Worker void sym_check_prop(struct symbol *sym)
185*cf5a6c84SAndroid Build Coastguard Worker {
186*cf5a6c84SAndroid Build Coastguard Worker 	struct property *prop;
187*cf5a6c84SAndroid Build Coastguard Worker 	struct symbol *sym2;
188*cf5a6c84SAndroid Build Coastguard Worker 	for (prop = sym->prop; prop; prop = prop->next) {
189*cf5a6c84SAndroid Build Coastguard Worker 		switch (prop->type) {
190*cf5a6c84SAndroid Build Coastguard Worker 		case P_DEFAULT:
191*cf5a6c84SAndroid Build Coastguard Worker 			if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
192*cf5a6c84SAndroid Build Coastguard Worker 			    prop->expr->type != E_SYMBOL)
193*cf5a6c84SAndroid Build Coastguard Worker 				prop_warn(prop,
194*cf5a6c84SAndroid Build Coastguard Worker 				    "default for config symbol '%'"
195*cf5a6c84SAndroid Build Coastguard Worker 				    " must be a single symbol", sym->name);
196*cf5a6c84SAndroid Build Coastguard Worker 			break;
197*cf5a6c84SAndroid Build Coastguard Worker 		case P_SELECT:
198*cf5a6c84SAndroid Build Coastguard Worker 			sym2 = prop_get_symbol(prop);
199*cf5a6c84SAndroid Build Coastguard Worker 			if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
200*cf5a6c84SAndroid Build Coastguard Worker 				prop_warn(prop,
201*cf5a6c84SAndroid Build Coastguard Worker 				    "config symbol '%s' uses select, but is "
202*cf5a6c84SAndroid Build Coastguard Worker 				    "not boolean or tristate", sym->name);
203*cf5a6c84SAndroid Build Coastguard Worker 			else if (sym2->type == S_UNKNOWN)
204*cf5a6c84SAndroid Build Coastguard Worker 				prop_warn(prop,
205*cf5a6c84SAndroid Build Coastguard Worker 				    "'select' used by config symbol '%s' "
206*cf5a6c84SAndroid Build Coastguard Worker 				    "refer to undefined symbol '%s'",
207*cf5a6c84SAndroid Build Coastguard Worker 				    sym->name, sym2->name);
208*cf5a6c84SAndroid Build Coastguard Worker 			else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
209*cf5a6c84SAndroid Build Coastguard Worker 				prop_warn(prop,
210*cf5a6c84SAndroid Build Coastguard Worker 				    "'%s' has wrong type. 'select' only "
211*cf5a6c84SAndroid Build Coastguard Worker 				    "accept arguments of boolean and "
212*cf5a6c84SAndroid Build Coastguard Worker 				    "tristate type", sym2->name);
213*cf5a6c84SAndroid Build Coastguard Worker 			break;
214*cf5a6c84SAndroid Build Coastguard Worker 		case P_RANGE:
215*cf5a6c84SAndroid Build Coastguard Worker 			if (sym->type != S_INT && sym->type != S_HEX)
216*cf5a6c84SAndroid Build Coastguard Worker 				prop_warn(prop, "range is only allowed "
217*cf5a6c84SAndroid Build Coastguard Worker 				                "for int or hex symbols");
218*cf5a6c84SAndroid Build Coastguard Worker 			if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
219*cf5a6c84SAndroid Build Coastguard Worker 			    !menu_range_valid_sym(sym, prop->expr->right.sym))
220*cf5a6c84SAndroid Build Coastguard Worker 				prop_warn(prop, "range is invalid");
221*cf5a6c84SAndroid Build Coastguard Worker 			break;
222*cf5a6c84SAndroid Build Coastguard Worker 		default:
223*cf5a6c84SAndroid Build Coastguard Worker 			;
224*cf5a6c84SAndroid Build Coastguard Worker 		}
225*cf5a6c84SAndroid Build Coastguard Worker 	}
226*cf5a6c84SAndroid Build Coastguard Worker }
227*cf5a6c84SAndroid Build Coastguard Worker 
menu_finalize(struct menu * parent)228*cf5a6c84SAndroid Build Coastguard Worker void menu_finalize(struct menu *parent)
229*cf5a6c84SAndroid Build Coastguard Worker {
230*cf5a6c84SAndroid Build Coastguard Worker 	struct menu *menu, *last_menu;
231*cf5a6c84SAndroid Build Coastguard Worker 	struct symbol *sym;
232*cf5a6c84SAndroid Build Coastguard Worker 	struct property *prop;
233*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *parentdep, *basedep, *dep, *dep2, **ep;
234*cf5a6c84SAndroid Build Coastguard Worker 
235*cf5a6c84SAndroid Build Coastguard Worker 	sym = parent->sym;
236*cf5a6c84SAndroid Build Coastguard Worker 	if (parent->list) {
237*cf5a6c84SAndroid Build Coastguard Worker 		if (sym && sym_is_choice(sym)) {
238*cf5a6c84SAndroid Build Coastguard Worker 			/* find the first choice value and find out choice type */
239*cf5a6c84SAndroid Build Coastguard Worker 			for (menu = parent->list; menu; menu = menu->next) {
240*cf5a6c84SAndroid Build Coastguard Worker 				if (menu->sym) {
241*cf5a6c84SAndroid Build Coastguard Worker 					current_entry = parent;
242*cf5a6c84SAndroid Build Coastguard Worker 					menu_set_type(menu->sym->type);
243*cf5a6c84SAndroid Build Coastguard Worker 					current_entry = menu;
244*cf5a6c84SAndroid Build Coastguard Worker 					menu_set_type(sym->type);
245*cf5a6c84SAndroid Build Coastguard Worker 					break;
246*cf5a6c84SAndroid Build Coastguard Worker 				}
247*cf5a6c84SAndroid Build Coastguard Worker 			}
248*cf5a6c84SAndroid Build Coastguard Worker 			parentdep = expr_alloc_symbol(sym);
249*cf5a6c84SAndroid Build Coastguard Worker 		} else if (parent->prompt)
250*cf5a6c84SAndroid Build Coastguard Worker 			parentdep = parent->prompt->visible.expr;
251*cf5a6c84SAndroid Build Coastguard Worker 		else
252*cf5a6c84SAndroid Build Coastguard Worker 			parentdep = parent->dep;
253*cf5a6c84SAndroid Build Coastguard Worker 
254*cf5a6c84SAndroid Build Coastguard Worker 		for (menu = parent->list; menu; menu = menu->next) {
255*cf5a6c84SAndroid Build Coastguard Worker 			basedep = expr_transform(menu->dep);
256*cf5a6c84SAndroid Build Coastguard Worker 			basedep = expr_alloc_and(expr_copy(parentdep), basedep);
257*cf5a6c84SAndroid Build Coastguard Worker 			basedep = expr_eliminate_dups(basedep);
258*cf5a6c84SAndroid Build Coastguard Worker 			menu->dep = basedep;
259*cf5a6c84SAndroid Build Coastguard Worker 			if (menu->sym)
260*cf5a6c84SAndroid Build Coastguard Worker 				prop = menu->sym->prop;
261*cf5a6c84SAndroid Build Coastguard Worker 			else
262*cf5a6c84SAndroid Build Coastguard Worker 				prop = menu->prompt;
263*cf5a6c84SAndroid Build Coastguard Worker 			for (; prop; prop = prop->next) {
264*cf5a6c84SAndroid Build Coastguard Worker 				if (prop->menu != menu)
265*cf5a6c84SAndroid Build Coastguard Worker 					continue;
266*cf5a6c84SAndroid Build Coastguard Worker 				dep = expr_transform(prop->visible.expr);
267*cf5a6c84SAndroid Build Coastguard Worker 				dep = expr_alloc_and(expr_copy(basedep), dep);
268*cf5a6c84SAndroid Build Coastguard Worker 				dep = expr_eliminate_dups(dep);
269*cf5a6c84SAndroid Build Coastguard Worker 				if (menu->sym && menu->sym->type != S_TRISTATE)
270*cf5a6c84SAndroid Build Coastguard Worker 					dep = expr_trans_bool(dep);
271*cf5a6c84SAndroid Build Coastguard Worker 				prop->visible.expr = dep;
272*cf5a6c84SAndroid Build Coastguard Worker 				if (prop->type == P_SELECT) {
273*cf5a6c84SAndroid Build Coastguard Worker 					struct symbol *es = prop_get_symbol(prop);
274*cf5a6c84SAndroid Build Coastguard Worker 					es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
275*cf5a6c84SAndroid Build Coastguard Worker 							expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
276*cf5a6c84SAndroid Build Coastguard Worker 				}
277*cf5a6c84SAndroid Build Coastguard Worker 			}
278*cf5a6c84SAndroid Build Coastguard Worker 		}
279*cf5a6c84SAndroid Build Coastguard Worker 		for (menu = parent->list; menu; menu = menu->next)
280*cf5a6c84SAndroid Build Coastguard Worker 			menu_finalize(menu);
281*cf5a6c84SAndroid Build Coastguard Worker 	} else if (sym) {
282*cf5a6c84SAndroid Build Coastguard Worker 		basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
283*cf5a6c84SAndroid Build Coastguard Worker 		basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
284*cf5a6c84SAndroid Build Coastguard Worker 		basedep = expr_eliminate_dups(expr_transform(basedep));
285*cf5a6c84SAndroid Build Coastguard Worker 		last_menu = NULL;
286*cf5a6c84SAndroid Build Coastguard Worker 		for (menu = parent->next; menu; menu = menu->next) {
287*cf5a6c84SAndroid Build Coastguard Worker 			dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
288*cf5a6c84SAndroid Build Coastguard Worker 			if (!expr_contains_symbol(dep, sym))
289*cf5a6c84SAndroid Build Coastguard Worker 				break;
290*cf5a6c84SAndroid Build Coastguard Worker 			if (expr_depends_symbol(dep, sym))
291*cf5a6c84SAndroid Build Coastguard Worker 				goto next;
292*cf5a6c84SAndroid Build Coastguard Worker 			dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
293*cf5a6c84SAndroid Build Coastguard Worker 			dep = expr_eliminate_dups(expr_transform(dep));
294*cf5a6c84SAndroid Build Coastguard Worker 			dep2 = expr_copy(basedep);
295*cf5a6c84SAndroid Build Coastguard Worker 			expr_eliminate_eq(&dep, &dep2);
296*cf5a6c84SAndroid Build Coastguard Worker 			expr_free(dep);
297*cf5a6c84SAndroid Build Coastguard Worker 			if (!expr_is_yes(dep2)) {
298*cf5a6c84SAndroid Build Coastguard Worker 				expr_free(dep2);
299*cf5a6c84SAndroid Build Coastguard Worker 				break;
300*cf5a6c84SAndroid Build Coastguard Worker 			}
301*cf5a6c84SAndroid Build Coastguard Worker 			expr_free(dep2);
302*cf5a6c84SAndroid Build Coastguard Worker 		next:
303*cf5a6c84SAndroid Build Coastguard Worker 			menu_finalize(menu);
304*cf5a6c84SAndroid Build Coastguard Worker 			menu->parent = parent;
305*cf5a6c84SAndroid Build Coastguard Worker 			last_menu = menu;
306*cf5a6c84SAndroid Build Coastguard Worker 		}
307*cf5a6c84SAndroid Build Coastguard Worker 		if (last_menu) {
308*cf5a6c84SAndroid Build Coastguard Worker 			parent->list = parent->next;
309*cf5a6c84SAndroid Build Coastguard Worker 			parent->next = last_menu->next;
310*cf5a6c84SAndroid Build Coastguard Worker 			last_menu->next = NULL;
311*cf5a6c84SAndroid Build Coastguard Worker 		}
312*cf5a6c84SAndroid Build Coastguard Worker 	}
313*cf5a6c84SAndroid Build Coastguard Worker 	for (menu = parent->list; menu; menu = menu->next) {
314*cf5a6c84SAndroid Build Coastguard Worker 		if (sym && sym_is_choice(sym) && menu->sym) {
315*cf5a6c84SAndroid Build Coastguard Worker 			menu->sym->flags |= SYMBOL_CHOICEVAL;
316*cf5a6c84SAndroid Build Coastguard Worker 			if (!menu->prompt)
317*cf5a6c84SAndroid Build Coastguard Worker 				menu_warn(menu, "choice value must have a prompt");
318*cf5a6c84SAndroid Build Coastguard Worker 			for (prop = menu->sym->prop; prop; prop = prop->next) {
319*cf5a6c84SAndroid Build Coastguard Worker 				if (prop->type == P_PROMPT && prop->menu != menu) {
320*cf5a6c84SAndroid Build Coastguard Worker 					prop_warn(prop, "choice values "
321*cf5a6c84SAndroid Build Coastguard Worker 					    "currently only support a "
322*cf5a6c84SAndroid Build Coastguard Worker 					    "single prompt");
323*cf5a6c84SAndroid Build Coastguard Worker 				}
324*cf5a6c84SAndroid Build Coastguard Worker 				if (prop->type == P_DEFAULT)
325*cf5a6c84SAndroid Build Coastguard Worker 					prop_warn(prop, "defaults for choice "
326*cf5a6c84SAndroid Build Coastguard Worker 					    "values not supported");
327*cf5a6c84SAndroid Build Coastguard Worker 			}
328*cf5a6c84SAndroid Build Coastguard Worker 			current_entry = menu;
329*cf5a6c84SAndroid Build Coastguard Worker 			menu_set_type(sym->type);
330*cf5a6c84SAndroid Build Coastguard Worker 			menu_add_symbol(P_CHOICE, sym, NULL);
331*cf5a6c84SAndroid Build Coastguard Worker 			prop = sym_get_choice_prop(sym);
332*cf5a6c84SAndroid Build Coastguard Worker 			for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
333*cf5a6c84SAndroid Build Coastguard Worker 				;
334*cf5a6c84SAndroid Build Coastguard Worker 			*ep = expr_alloc_one(E_CHOICE, NULL);
335*cf5a6c84SAndroid Build Coastguard Worker 			(*ep)->right.sym = menu->sym;
336*cf5a6c84SAndroid Build Coastguard Worker 		}
337*cf5a6c84SAndroid Build Coastguard Worker 		if (menu->list && (!menu->prompt || !menu->prompt->text)) {
338*cf5a6c84SAndroid Build Coastguard Worker 			for (last_menu = menu->list; ; last_menu = last_menu->next) {
339*cf5a6c84SAndroid Build Coastguard Worker 				last_menu->parent = parent;
340*cf5a6c84SAndroid Build Coastguard Worker 				if (!last_menu->next)
341*cf5a6c84SAndroid Build Coastguard Worker 					break;
342*cf5a6c84SAndroid Build Coastguard Worker 			}
343*cf5a6c84SAndroid Build Coastguard Worker 			last_menu->next = menu->next;
344*cf5a6c84SAndroid Build Coastguard Worker 			menu->next = menu->list;
345*cf5a6c84SAndroid Build Coastguard Worker 			menu->list = NULL;
346*cf5a6c84SAndroid Build Coastguard Worker 		}
347*cf5a6c84SAndroid Build Coastguard Worker 	}
348*cf5a6c84SAndroid Build Coastguard Worker 
349*cf5a6c84SAndroid Build Coastguard Worker 	if (sym && !(sym->flags & SYMBOL_WARNED)) {
350*cf5a6c84SAndroid Build Coastguard Worker 		if (sym->type == S_UNKNOWN)
351*cf5a6c84SAndroid Build Coastguard Worker 			menu_warn(parent, "config symbol defined without type");
352*cf5a6c84SAndroid Build Coastguard Worker 
353*cf5a6c84SAndroid Build Coastguard Worker 		if (sym_is_choice(sym) && !parent->prompt)
354*cf5a6c84SAndroid Build Coastguard Worker 			menu_warn(parent, "choice must have a prompt");
355*cf5a6c84SAndroid Build Coastguard Worker 
356*cf5a6c84SAndroid Build Coastguard Worker 		/* Check properties connected to this symbol */
357*cf5a6c84SAndroid Build Coastguard Worker 		sym_check_prop(sym);
358*cf5a6c84SAndroid Build Coastguard Worker 		sym->flags |= SYMBOL_WARNED;
359*cf5a6c84SAndroid Build Coastguard Worker 	}
360*cf5a6c84SAndroid Build Coastguard Worker 
361*cf5a6c84SAndroid Build Coastguard Worker 	if (sym && !sym_is_optional(sym) && parent->prompt) {
362*cf5a6c84SAndroid Build Coastguard Worker 		sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
363*cf5a6c84SAndroid Build Coastguard Worker 				expr_alloc_and(parent->prompt->visible.expr,
364*cf5a6c84SAndroid Build Coastguard Worker 					expr_alloc_symbol(&symbol_mod)));
365*cf5a6c84SAndroid Build Coastguard Worker 	}
366*cf5a6c84SAndroid Build Coastguard Worker }
367*cf5a6c84SAndroid Build Coastguard Worker 
menu_is_visible(struct menu * menu)368*cf5a6c84SAndroid Build Coastguard Worker bool menu_is_visible(struct menu *menu)
369*cf5a6c84SAndroid Build Coastguard Worker {
370*cf5a6c84SAndroid Build Coastguard Worker 	struct menu *child;
371*cf5a6c84SAndroid Build Coastguard Worker 	struct symbol *sym;
372*cf5a6c84SAndroid Build Coastguard Worker 	tristate visible;
373*cf5a6c84SAndroid Build Coastguard Worker 
374*cf5a6c84SAndroid Build Coastguard Worker 	if (!menu->prompt)
375*cf5a6c84SAndroid Build Coastguard Worker 		return false;
376*cf5a6c84SAndroid Build Coastguard Worker 	sym = menu->sym;
377*cf5a6c84SAndroid Build Coastguard Worker 	if (sym) {
378*cf5a6c84SAndroid Build Coastguard Worker 		sym_calc_value(sym);
379*cf5a6c84SAndroid Build Coastguard Worker 		visible = menu->prompt->visible.tri;
380*cf5a6c84SAndroid Build Coastguard Worker 	} else
381*cf5a6c84SAndroid Build Coastguard Worker 		visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
382*cf5a6c84SAndroid Build Coastguard Worker 
383*cf5a6c84SAndroid Build Coastguard Worker 	if (visible != no)
384*cf5a6c84SAndroid Build Coastguard Worker 		return true;
385*cf5a6c84SAndroid Build Coastguard Worker 	if (!sym || sym_get_tristate_value(menu->sym) == no)
386*cf5a6c84SAndroid Build Coastguard Worker 		return false;
387*cf5a6c84SAndroid Build Coastguard Worker 
388*cf5a6c84SAndroid Build Coastguard Worker 	for (child = menu->list; child; child = child->next)
389*cf5a6c84SAndroid Build Coastguard Worker 		if (menu_is_visible(child))
390*cf5a6c84SAndroid Build Coastguard Worker 			return true;
391*cf5a6c84SAndroid Build Coastguard Worker 	return false;
392*cf5a6c84SAndroid Build Coastguard Worker }
393*cf5a6c84SAndroid Build Coastguard Worker 
menu_get_prompt(struct menu * menu)394*cf5a6c84SAndroid Build Coastguard Worker const char *menu_get_prompt(struct menu *menu)
395*cf5a6c84SAndroid Build Coastguard Worker {
396*cf5a6c84SAndroid Build Coastguard Worker 	if (menu->prompt)
397*cf5a6c84SAndroid Build Coastguard Worker 		return _(menu->prompt->text);
398*cf5a6c84SAndroid Build Coastguard Worker 	else if (menu->sym)
399*cf5a6c84SAndroid Build Coastguard Worker 		return _(menu->sym->name);
400*cf5a6c84SAndroid Build Coastguard Worker 	return NULL;
401*cf5a6c84SAndroid Build Coastguard Worker }
402*cf5a6c84SAndroid Build Coastguard Worker 
menu_get_root_menu(struct menu * menu)403*cf5a6c84SAndroid Build Coastguard Worker struct menu *menu_get_root_menu(struct menu *menu)
404*cf5a6c84SAndroid Build Coastguard Worker {
405*cf5a6c84SAndroid Build Coastguard Worker 	return &rootmenu;
406*cf5a6c84SAndroid Build Coastguard Worker }
407*cf5a6c84SAndroid Build Coastguard Worker 
menu_get_parent_menu(struct menu * menu)408*cf5a6c84SAndroid Build Coastguard Worker struct menu *menu_get_parent_menu(struct menu *menu)
409*cf5a6c84SAndroid Build Coastguard Worker {
410*cf5a6c84SAndroid Build Coastguard Worker 	enum prop_type type;
411*cf5a6c84SAndroid Build Coastguard Worker 
412*cf5a6c84SAndroid Build Coastguard Worker 	for (; menu != &rootmenu; menu = menu->parent) {
413*cf5a6c84SAndroid Build Coastguard Worker 		type = menu->prompt ? menu->prompt->type : 0;
414*cf5a6c84SAndroid Build Coastguard Worker 		if (type == P_MENU)
415*cf5a6c84SAndroid Build Coastguard Worker 			break;
416*cf5a6c84SAndroid Build Coastguard Worker 	}
417*cf5a6c84SAndroid Build Coastguard Worker 	return menu;
418*cf5a6c84SAndroid Build Coastguard Worker }
419*cf5a6c84SAndroid Build Coastguard Worker 
420