Merge patches sent by Robert P. J. Day <rpjday@mindspring.com>.
Warning: the buildroot folks purposedly removed the skip-comment patch but didn't really said why. Keeping it for the sake of having it in svn just in case (removing it will be easier thant not having it at all).
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
9 #define LKC_DIRECT_LINK
13 static struct menu **last_entry_ptr;
15 struct file *file_list;
16 struct file *current_file;
18 static void menu_warn(struct menu *menu, const char *fmt, ...)
22 fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
23 vfprintf(stderr, fmt, ap);
24 fprintf(stderr, "\n");
28 static void prop_warn(struct property *prop, const char *fmt, ...)
32 fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
33 vfprintf(stderr, fmt, ap);
34 fprintf(stderr, "\n");
40 current_entry = current_menu = &rootmenu;
41 last_entry_ptr = &rootmenu.list;
44 void menu_add_entry(struct symbol *sym)
48 menu = malloc(sizeof(*menu));
49 memset(menu, 0, sizeof(*menu));
51 menu->parent = current_menu;
52 menu->file = current_file;
53 menu->lineno = zconf_lineno();
55 *last_entry_ptr = menu;
56 last_entry_ptr = &menu->next;
60 void menu_end_entry(void)
64 struct menu *menu_add_menu(void)
67 last_entry_ptr = ¤t_entry->list;
68 return current_menu = current_entry;
71 void menu_end_menu(void)
73 last_entry_ptr = ¤t_menu->next;
74 current_menu = current_menu->parent;
77 struct expr *menu_check_dep(struct expr *e)
84 e->left.expr = menu_check_dep(e->left.expr);
88 e->left.expr = menu_check_dep(e->left.expr);
89 e->right.expr = menu_check_dep(e->right.expr);
92 /* change 'm' into 'm' && MODULES */
93 if (e->left.sym == &symbol_mod)
94 return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
102 void menu_add_dep(struct expr *dep)
104 current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
107 void menu_set_type(int type)
109 struct symbol *sym = current_entry->sym;
111 if (sym->type == type)
113 if (sym->type == S_UNKNOWN) {
117 menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
118 sym->name ? sym->name : "<choice>",
119 sym_type_name(sym->type), sym_type_name(type));
122 struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
124 struct property *prop = prop_alloc(type, current_entry->sym);
126 prop->menu = current_entry;
128 prop->visible.expr = menu_check_dep(dep);
131 if (isspace(*prompt)) {
132 prop_warn(prop, "leading whitespace ignored");
133 while (isspace(*prompt))
136 if (current_entry->prompt)
137 prop_warn(prop, "prompt redefined");
138 current_entry->prompt = prop;
145 struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
147 return menu_add_prop(type, prompt, NULL, dep);
150 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
152 menu_add_prop(type, NULL, expr, dep);
155 void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
157 menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
160 void menu_add_option(int token, char *arg)
162 struct property *prop;
166 prop = prop_alloc(P_DEFAULT, modules_sym);
167 prop->expr = expr_alloc_symbol(current_entry->sym);
169 case T_OPT_DEFCONFIG_LIST:
170 if (!sym_defconfig_list)
171 sym_defconfig_list = current_entry->sym;
172 else if (sym_defconfig_list != current_entry->sym)
173 zconf_error("trying to redefine defconfig symbol");
178 static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
180 return sym2->type == S_INT || sym2->type == S_HEX ||
181 (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
184 void sym_check_prop(struct symbol *sym)
186 struct property *prop;
188 for (prop = sym->prop; prop; prop = prop->next) {
189 switch (prop->type) {
191 if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
192 prop->expr->type != E_SYMBOL)
194 "default for config symbol '%'"
195 " must be a single symbol", sym->name);
198 sym2 = prop_get_symbol(prop);
199 if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
201 "config symbol '%s' uses select, but is "
202 "not boolean or tristate", sym->name);
203 else if (sym2->type == S_UNKNOWN)
205 "'select' used by config symbol '%s' "
206 "refer to undefined symbol '%s'",
207 sym->name, sym2->name);
208 else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
210 "'%s' has wrong type. 'select' only "
211 "accept arguments of boolean and "
212 "tristate type", sym2->name);
215 if (sym->type != S_INT && sym->type != S_HEX)
216 prop_warn(prop, "range is only allowed "
217 "for int or hex symbols");
218 if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
219 !menu_range_valid_sym(sym, prop->expr->right.sym))
220 prop_warn(prop, "range is invalid");
228 void menu_finalize(struct menu *parent)
230 struct menu *menu, *last_menu;
232 struct property *prop;
233 struct expr *parentdep, *basedep, *dep, *dep2, **ep;
237 if (sym && sym_is_choice(sym)) {
238 /* find the first choice value and find out choice type */
239 for (menu = parent->list; menu; menu = menu->next) {
241 current_entry = parent;
242 menu_set_type(menu->sym->type);
243 current_entry = menu;
244 menu_set_type(sym->type);
248 parentdep = expr_alloc_symbol(sym);
249 } else if (parent->prompt)
250 parentdep = parent->prompt->visible.expr;
252 parentdep = parent->dep;
254 for (menu = parent->list; menu; menu = menu->next) {
255 basedep = expr_transform(menu->dep);
256 basedep = expr_alloc_and(expr_copy(parentdep), basedep);
257 basedep = expr_eliminate_dups(basedep);
260 prop = menu->sym->prop;
263 for (; prop; prop = prop->next) {
264 if (prop->menu != menu)
266 dep = expr_transform(prop->visible.expr);
267 dep = expr_alloc_and(expr_copy(basedep), dep);
268 dep = expr_eliminate_dups(dep);
269 if (menu->sym && menu->sym->type != S_TRISTATE)
270 dep = expr_trans_bool(dep);
271 prop->visible.expr = dep;
272 if (prop->type == P_SELECT) {
273 struct symbol *es = prop_get_symbol(prop);
274 es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
275 expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
279 for (menu = parent->list; menu; menu = menu->next)
282 basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
283 basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
284 basedep = expr_eliminate_dups(expr_transform(basedep));
286 for (menu = parent->next; menu; menu = menu->next) {
287 dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
288 if (!expr_contains_symbol(dep, sym))
290 if (expr_depends_symbol(dep, sym))
292 dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
293 dep = expr_eliminate_dups(expr_transform(dep));
294 dep2 = expr_copy(basedep);
295 expr_eliminate_eq(&dep, &dep2);
297 if (!expr_is_yes(dep2)) {
304 menu->parent = parent;
308 parent->list = parent->next;
309 parent->next = last_menu->next;
310 last_menu->next = NULL;
313 for (menu = parent->list; menu; menu = menu->next) {
314 if (sym && sym_is_choice(sym) && menu->sym) {
315 menu->sym->flags |= SYMBOL_CHOICEVAL;
317 menu_warn(menu, "choice value must have a prompt");
318 for (prop = menu->sym->prop; prop; prop = prop->next) {
319 if (prop->type == P_PROMPT && prop->menu != menu) {
320 prop_warn(prop, "choice values "
321 "currently only support a "
324 if (prop->type == P_DEFAULT)
325 prop_warn(prop, "defaults for choice "
326 "values not supported");
328 current_entry = menu;
329 menu_set_type(sym->type);
330 menu_add_symbol(P_CHOICE, sym, NULL);
331 prop = sym_get_choice_prop(sym);
332 for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
334 *ep = expr_alloc_one(E_CHOICE, NULL);
335 (*ep)->right.sym = menu->sym;
337 if (menu->list && (!menu->prompt || !menu->prompt->text)) {
338 for (last_menu = menu->list; ; last_menu = last_menu->next) {
339 last_menu->parent = parent;
340 if (!last_menu->next)
343 last_menu->next = menu->next;
344 menu->next = menu->list;
349 if (sym && !(sym->flags & SYMBOL_WARNED)) {
350 if (sym->type == S_UNKNOWN)
351 menu_warn(parent, "config symbol defined without type");
353 if (sym_is_choice(sym) && !parent->prompt)
354 menu_warn(parent, "choice must have a prompt");
356 /* Check properties connected to this symbol */
358 sym->flags |= SYMBOL_WARNED;
361 if (sym && !sym_is_optional(sym) && parent->prompt) {
362 sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
363 expr_alloc_and(parent->prompt->visible.expr,
364 expr_alloc_symbol(&symbol_mod)));
368 bool menu_is_visible(struct menu *menu)
379 visible = menu->prompt->visible.tri;
381 visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
385 if (!sym || sym_get_tristate_value(menu->sym) == no)
388 for (child = menu->list; child; child = child->next)
389 if (menu_is_visible(child))
394 const char *menu_get_prompt(struct menu *menu)
397 return _(menu->prompt->text);
399 return _(menu->sym->name);
403 struct menu *menu_get_root_menu(struct menu *menu)
408 struct menu *menu_get_parent_menu(struct menu *menu)
412 for (; menu != &rootmenu; menu = menu->parent) {
413 type = menu->prompt ? menu->prompt->type : 0;