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 = ¤t_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 = ¤t_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