Chameleon

Chameleon Svn Source Tree

Root/tags/2.0/i386/config/menu.c

Source at commit 1808 created 12 years 3 months ago.
By blackosx, Revise layout of package installer 'Welcome' file so it looks cleaner. Change the copyright notice to begin from 2009 as seen in the Chameleon 2.0 r431 installer. Should this date be set earlier?
1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5#include <stdlib.h>
6#include <string.h>
7
8#define LKC_DIRECT_LINK
9#include "lkc.h"
10
11static const char nohelp_text[] = N_(
12"There is no help available for this option.\n");
13
14struct menu rootmenu;
15static struct menu **last_entry_ptr;
16
17struct file *file_list;
18struct file *current_file;
19
20void menu_warn(struct menu *menu, const char *fmt, ...)
21{
22va_list ap;
23va_start(ap, fmt);
24fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
25vfprintf(stderr, fmt, ap);
26fprintf(stderr, "\n");
27va_end(ap);
28}
29
30static void prop_warn(struct property *prop, const char *fmt, ...)
31{
32va_list ap;
33va_start(ap, fmt);
34fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
35vfprintf(stderr, fmt, ap);
36fprintf(stderr, "\n");
37va_end(ap);
38}
39
40void _menu_init(void)
41{
42current_entry = current_menu = &rootmenu;
43last_entry_ptr = &rootmenu.list;
44}
45
46void menu_add_entry(struct symbol *sym)
47{
48struct menu *menu;
49
50menu = malloc(sizeof(*menu));
51memset(menu, 0, sizeof(*menu));
52menu->sym = sym;
53menu->parent = current_menu;
54menu->file = current_file;
55menu->lineno = zconf_lineno();
56
57*last_entry_ptr = menu;
58last_entry_ptr = &menu->next;
59current_entry = menu;
60if (sym)
61menu_add_symbol(P_SYMBOL, sym, NULL);
62}
63
64void menu_end_entry(void)
65{
66}
67
68struct menu *menu_add_menu(void)
69{
70menu_end_entry();
71last_entry_ptr = &current_entry->list;
72return current_menu = current_entry;
73}
74
75void menu_end_menu(void)
76{
77last_entry_ptr = &current_menu->next;
78current_menu = current_menu->parent;
79}
80
81static struct expr *menu_check_dep(struct expr *e)
82{
83if (!e)
84return e;
85
86switch (e->type) {
87case E_NOT:
88e->left.expr = menu_check_dep(e->left.expr);
89break;
90case E_OR:
91case E_AND:
92e->left.expr = menu_check_dep(e->left.expr);
93e->right.expr = menu_check_dep(e->right.expr);
94break;
95case E_SYMBOL:
96/* change 'm' into 'm' && MODULES */
97if (e->left.sym == &symbol_mod)
98return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
99break;
100default:
101break;
102}
103return e;
104}
105
106void menu_add_dep(struct expr *dep)
107{
108current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
109}
110
111void menu_set_type(int type)
112{
113struct symbol *sym = current_entry->sym;
114
115if (sym->type == type)
116return;
117if (sym->type == S_UNKNOWN) {
118sym->type = type;
119return;
120}
121menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
122 sym->name ? sym->name : "<choice>",
123 sym_type_name(sym->type), sym_type_name(type));
124}
125
126struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
127{
128struct property *prop = prop_alloc(type, current_entry->sym);
129
130prop->menu = current_entry;
131prop->expr = expr;
132prop->visible.expr = menu_check_dep(dep);
133
134if (prompt) {
135if (isspace(*prompt)) {
136prop_warn(prop, "leading whitespace ignored");
137while (isspace(*prompt))
138prompt++;
139}
140if (current_entry->prompt && current_entry != &rootmenu)
141prop_warn(prop, "prompt redefined");
142
143/* Apply all upper menus' visibilities to actual prompts. */
144if(type == P_PROMPT) {
145struct menu *menu = current_entry;
146
147while ((menu = menu->parent) != NULL) {
148if (!menu->visibility)
149continue;
150prop->visible.expr
151= expr_alloc_and(prop->visible.expr,
152 menu->visibility);
153}
154}
155
156current_entry->prompt = prop;
157}
158prop->text = prompt;
159
160return prop;
161}
162
163struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
164{
165return menu_add_prop(type, prompt, NULL, dep);
166}
167
168void menu_add_visibility(struct expr *expr)
169{
170current_entry->visibility = expr_alloc_and(current_entry->visibility,
171 expr);
172}
173
174void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
175{
176menu_add_prop(type, NULL, expr, dep);
177}
178
179void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
180{
181menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
182}
183
184void menu_add_option(int token, char *arg)
185{
186struct property *prop;
187
188switch (token) {
189case T_OPT_MODULES:
190prop = prop_alloc(P_DEFAULT, modules_sym);
191prop->expr = expr_alloc_symbol(current_entry->sym);
192break;
193case T_OPT_DEFCONFIG_LIST:
194if (!sym_defconfig_list)
195sym_defconfig_list = current_entry->sym;
196else if (sym_defconfig_list != current_entry->sym)
197zconf_error("trying to redefine defconfig symbol");
198break;
199case T_OPT_ENV:
200//prop_add_env(arg);
201break;
202}
203}
204
205static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
206{
207return sym2->type == S_INT || sym2->type == S_HEX ||
208 (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
209}
210
211static void sym_check_prop(struct symbol *sym)
212{
213struct property *prop;
214struct symbol *sym2;
215for (prop = sym->prop; prop; prop = prop->next) {
216switch (prop->type) {
217case P_DEFAULT:
218if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
219 prop->expr->type != E_SYMBOL)
220prop_warn(prop,
221 "default for config symbol '%s'"
222 " must be a single symbol", sym->name);
223if (prop->expr->type != E_SYMBOL)
224break;
225sym2 = prop_get_symbol(prop);
226if (sym->type == S_HEX || sym->type == S_INT) {
227if (!menu_validate_number(sym, sym2))
228prop_warn(prop,
229 "'%s': number is invalid",
230 sym->name);
231}
232break;
233case P_SELECT:
234sym2 = prop_get_symbol(prop);
235if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
236prop_warn(prop,
237 "config symbol '%s' uses select, but is "
238 "not boolean or tristate", sym->name);
239else if (sym2->type != S_UNKNOWN &&
240 sym2->type != S_BOOLEAN &&
241 sym2->type != S_TRISTATE)
242prop_warn(prop,
243 "'%s' has wrong type. 'select' only "
244 "accept arguments of boolean and "
245 "tristate type", sym2->name);
246break;
247case P_RANGE:
248if (sym->type != S_INT && sym->type != S_HEX)
249prop_warn(prop, "range is only allowed "
250 "for int or hex symbols");
251if (!menu_validate_number(sym, prop->expr->left.sym) ||
252 !menu_validate_number(sym, prop->expr->right.sym))
253prop_warn(prop, "range is invalid");
254break;
255default:
256;
257}
258}
259}
260
261void menu_finalize(struct menu *parent)
262{
263struct menu *menu, *last_menu;
264struct symbol *sym;
265struct property *prop;
266struct expr *parentdep, *basedep, *dep, *dep2, **ep;
267
268sym = parent->sym;
269if (parent->list) {
270if (sym && sym_is_choice(sym)) {
271if (sym->type == S_UNKNOWN) {
272/* find the first choice value to find out choice type */
273current_entry = parent;
274for (menu = parent->list; menu; menu = menu->next) {
275if (menu->sym && menu->sym->type != S_UNKNOWN) {
276menu_set_type(menu->sym->type);
277break;
278}
279}
280}
281/* set the type of the remaining choice values */
282for (menu = parent->list; menu; menu = menu->next) {
283current_entry = menu;
284if (menu->sym && menu->sym->type == S_UNKNOWN)
285menu_set_type(sym->type);
286}
287parentdep = expr_alloc_symbol(sym);
288} else if (parent->prompt)
289parentdep = parent->prompt->visible.expr;
290else
291parentdep = parent->dep;
292
293for (menu = parent->list; menu; menu = menu->next) {
294basedep = expr_transform(menu->dep);
295basedep = expr_alloc_and(expr_copy(parentdep), basedep);
296basedep = expr_eliminate_dups(basedep);
297menu->dep = basedep;
298if (menu->sym)
299prop = menu->sym->prop;
300else
301prop = menu->prompt;
302for (; prop; prop = prop->next) {
303if (prop->menu != menu)
304continue;
305dep = expr_transform(prop->visible.expr);
306dep = expr_alloc_and(expr_copy(basedep), dep);
307dep = expr_eliminate_dups(dep);
308if (menu->sym && menu->sym->type != S_TRISTATE)
309dep = expr_trans_bool(dep);
310prop->visible.expr = dep;
311if (prop->type == P_SELECT) {
312struct symbol *es = prop_get_symbol(prop);
313es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
314expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
315}
316}
317}
318for (menu = parent->list; menu; menu = menu->next)
319menu_finalize(menu);
320} else if (sym) {
321basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
322basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
323basedep = expr_eliminate_dups(expr_transform(basedep));
324last_menu = NULL;
325for (menu = parent->next; menu; menu = menu->next) {
326dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
327if (!expr_contains_symbol(dep, sym))
328break;
329if (expr_depends_symbol(dep, sym))
330goto next;
331dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
332dep = expr_eliminate_dups(expr_transform(dep));
333dep2 = expr_copy(basedep);
334expr_eliminate_eq(&dep, &dep2);
335expr_free(dep);
336if (!expr_is_yes(dep2)) {
337expr_free(dep2);
338break;
339}
340expr_free(dep2);
341next:
342menu_finalize(menu);
343menu->parent = parent;
344last_menu = menu;
345}
346if (last_menu) {
347parent->list = parent->next;
348parent->next = last_menu->next;
349last_menu->next = NULL;
350}
351
352sym->dir_dep.expr = parent->dep;
353}
354for (menu = parent->list; menu; menu = menu->next) {
355if (sym && sym_is_choice(sym) &&
356 menu->sym && !sym_is_choice_value(menu->sym)) {
357current_entry = menu;
358menu->sym->flags |= SYMBOL_CHOICEVAL;
359if (!menu->prompt)
360menu_warn(menu, "choice value must have a prompt");
361for (prop = menu->sym->prop; prop; prop = prop->next) {
362if (prop->type == P_DEFAULT)
363prop_warn(prop, "defaults for choice "
364 "values not supported");
365if (prop->menu == menu)
366continue;
367if (prop->type == P_PROMPT &&
368 prop->menu->parent->sym != sym)
369prop_warn(prop, "choice value used outside its choice group");
370}
371/* Non-tristate choice values of tristate choices must
372 * depend on the choice being set to Y. The choice
373 * values' dependencies were propagated to their
374 * properties above, so the change here must be re-
375 * propagated.
376 */
377if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {
378basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);
379menu->dep = expr_alloc_and(basedep, menu->dep);
380for (prop = menu->sym->prop; prop; prop = prop->next) {
381if (prop->menu != menu)
382continue;
383prop->visible.expr = expr_alloc_and(expr_copy(basedep),
384 prop->visible.expr);
385}
386}
387menu_add_symbol(P_CHOICE, sym, NULL);
388prop = sym_get_choice_prop(sym);
389for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
390;
391*ep = expr_alloc_one(E_LIST, NULL);
392(*ep)->right.sym = menu->sym;
393}
394if (menu->list && (!menu->prompt || !menu->prompt->text)) {
395for (last_menu = menu->list; ; last_menu = last_menu->next) {
396last_menu->parent = parent;
397if (!last_menu->next)
398break;
399}
400last_menu->next = menu->next;
401menu->next = menu->list;
402menu->list = NULL;
403}
404}
405
406if (sym && !(sym->flags & SYMBOL_WARNED)) {
407if (sym->type == S_UNKNOWN)
408menu_warn(parent, "config symbol defined without type");
409
410if (sym_is_choice(sym) && !parent->prompt)
411menu_warn(parent, "choice must have a prompt");
412
413/* Check properties connected to this symbol */
414sym_check_prop(sym);
415sym->flags |= SYMBOL_WARNED;
416}
417
418if (sym && !sym_is_optional(sym) && parent->prompt) {
419sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
420expr_alloc_and(parent->prompt->visible.expr,
421expr_alloc_symbol(&symbol_mod)));
422}
423}
424
425bool menu_has_prompt(struct menu *menu)
426{
427if (!menu->prompt)
428return false;
429return true;
430}
431
432bool menu_is_visible(struct menu *menu)
433{
434struct menu *child;
435struct symbol *sym;
436tristate visible;
437
438if (!menu->prompt)
439return false;
440
441if (menu->visibility) {
442if (expr_calc_value(menu->visibility) == no)
443return no;
444}
445
446sym = menu->sym;
447if (sym) {
448sym_calc_value(sym);
449visible = menu->prompt->visible.tri;
450} else
451visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
452
453if (visible != no)
454return true;
455
456if (!sym || sym_get_tristate_value(menu->sym) == no)
457return false;
458
459for (child = menu->list; child; child = child->next) {
460if (menu_is_visible(child)) {
461if (sym)
462sym->flags |= SYMBOL_DEF_USER;
463return true;
464}
465}
466
467return false;
468}
469
470const char *menu_get_prompt(struct menu *menu)
471{
472if (menu->prompt)
473return menu->prompt->text;
474else if (menu->sym)
475return menu->sym->name;
476return NULL;
477}
478
479struct menu *menu_get_root_menu(struct menu *menu)
480{
481return &rootmenu;
482}
483
484struct menu *menu_get_parent_menu(struct menu *menu)
485{
486enum prop_type type;
487
488for (; menu != &rootmenu; menu = menu->parent) {
489type = menu->prompt ? menu->prompt->type : 0;
490if (type == P_MENU)
491break;
492}
493return menu;
494}
495
496bool menu_has_help(struct menu *menu)
497{
498return menu->help != NULL;
499}
500
501const char *menu_get_help(struct menu *menu)
502{
503if (menu->help)
504return menu->help;
505else
506return "";
507}
508
509static void get_prompt_str(struct gstr *r, struct property *prop)
510{
511int i, j;
512struct menu *submenu[8], *menu;
513
514str_printf(r, _("Prompt: %s\n"), _(prop->text));
515str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name,
516prop->menu->lineno);
517if (!expr_is_yes(prop->visible.expr)) {
518str_append(r, _(" Depends on: "));
519expr_gstr_print(prop->visible.expr, r);
520str_append(r, "\n");
521}
522menu = prop->menu->parent;
523for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
524submenu[i++] = menu;
525if (i > 0) {
526str_printf(r, _(" Location:\n"));
527for (j = 4; --i >= 0; j += 2) {
528menu = submenu[i];
529str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu)));
530if (menu->sym) {
531str_printf(r, " (%s [=%s])", menu->sym->name ?
532menu->sym->name : _("<choice>"),
533sym_get_string_value(menu->sym));
534}
535str_append(r, "\n");
536}
537}
538}
539
540void get_symbol_str(struct gstr *r, struct symbol *sym)
541{
542bool hit;
543struct property *prop;
544
545if (sym && sym->name) {
546str_printf(r, "Symbol: %s [=%s]\n", sym->name,
547 sym_get_string_value(sym));
548str_printf(r, "Type : %s\n", sym_type_name(sym->type));
549if (sym->type == S_INT || sym->type == S_HEX) {
550prop = sym_get_range_prop(sym);
551if (prop) {
552str_printf(r, "Range : ");
553expr_gstr_print(prop->expr, r);
554str_append(r, "\n");
555}
556}
557}
558for_all_prompts(sym, prop)
559get_prompt_str(r, prop);
560hit = false;
561for_all_properties(sym, prop, P_SELECT) {
562if (!hit) {
563str_append(r, " Selects: ");
564hit = true;
565} else
566str_printf(r, " && ");
567expr_gstr_print(prop->expr, r);
568}
569if (hit)
570str_append(r, "\n");
571if (sym->rev_dep.expr) {
572str_append(r, _(" Selected by: "));
573expr_gstr_print(sym->rev_dep.expr, r);
574str_append(r, "\n");
575}
576str_append(r, "\n\n");
577}
578
579struct gstr get_relations_str(struct symbol **sym_arr)
580{
581struct symbol *sym;
582struct gstr res = str_new();
583int i;
584
585for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
586get_symbol_str(&res, sym);
587if (!i)
588str_append(&res, _("No matches found.\n"));
589return res;
590}
591
592
593void menu_get_ext_help(struct menu *menu, struct gstr *help)
594{
595struct symbol *sym = menu->sym;
596
597if (menu_has_help(menu)) {
598if (sym->name) {
599str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
600str_append(help, _(menu_get_help(menu)));
601str_append(help, "\n");
602}
603} else {
604str_append(help, nohelp_text);
605}
606if (sym)
607get_symbol_str(help, sym);
608}
609

Archive Download this file

Revision: 1808