1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
14 static const char nohelp_text
[] = "There is no help available for this option.";
17 static struct menu
**last_entry_ptr
;
19 struct file
*file_list
;
20 struct file
*current_file
;
22 void menu_warn(struct menu
*menu
, const char *fmt
, ...)
26 fprintf(stderr
, "%s:%d:warning: ", menu
->file
->name
, menu
->lineno
);
27 vfprintf(stderr
, fmt
, ap
);
28 fprintf(stderr
, "\n");
32 static void prop_warn(struct property
*prop
, const char *fmt
, ...)
36 fprintf(stderr
, "%s:%d:warning: ", prop
->file
->name
, prop
->lineno
);
37 vfprintf(stderr
, fmt
, ap
);
38 fprintf(stderr
, "\n");
44 current_entry
= current_menu
= &rootmenu
;
45 last_entry_ptr
= &rootmenu
.list
;
48 void menu_add_entry(struct symbol
*sym
)
52 menu
= xmalloc(sizeof(*menu
));
53 memset(menu
, 0, sizeof(*menu
));
55 menu
->parent
= current_menu
;
56 menu
->file
= current_file
;
57 menu
->lineno
= zconf_lineno();
59 *last_entry_ptr
= menu
;
60 last_entry_ptr
= &menu
->next
;
63 menu_add_symbol(P_SYMBOL
, sym
, NULL
);
66 struct menu
*menu_add_menu(void)
68 last_entry_ptr
= ¤t_entry
->list
;
69 current_menu
= current_entry
;
73 void menu_end_menu(void)
75 last_entry_ptr
= ¤t_menu
->next
;
76 current_menu
= current_menu
->parent
;
80 * Rewrites 'm' to 'm' && MODULES, so that it evaluates to 'n' when running
83 static struct expr
*rewrite_m(struct expr
*e
)
90 e
->left
.expr
= rewrite_m(e
->left
.expr
);
94 e
->left
.expr
= rewrite_m(e
->left
.expr
);
95 e
->right
.expr
= rewrite_m(e
->right
.expr
);
98 /* change 'm' into 'm' && MODULES */
99 if (e
->left
.sym
== &symbol_mod
)
100 return expr_alloc_and(e
, expr_alloc_symbol(modules_sym
));
108 void menu_add_dep(struct expr
*dep
)
110 current_entry
->dep
= expr_alloc_and(current_entry
->dep
, dep
);
113 void menu_set_type(int type
)
115 struct symbol
*sym
= current_entry
->sym
;
117 if (sym
->type
== type
)
119 if (sym
->type
== S_UNKNOWN
) {
123 menu_warn(current_entry
,
124 "ignoring type redefinition of '%s' from '%s' to '%s'",
125 sym
->name
? sym
->name
: "<choice>",
126 sym_type_name(sym
->type
), sym_type_name(type
));
129 static struct property
*menu_add_prop(enum prop_type type
, struct expr
*expr
,
132 struct property
*prop
;
134 prop
= xmalloc(sizeof(*prop
));
135 memset(prop
, 0, sizeof(*prop
));
137 prop
->file
= current_file
;
138 prop
->lineno
= zconf_lineno();
139 prop
->menu
= current_entry
;
141 prop
->visible
.expr
= dep
;
143 /* append property to the prop list of symbol */
144 if (current_entry
->sym
) {
145 struct property
**propp
;
147 for (propp
= ¤t_entry
->sym
->prop
;
149 propp
= &(*propp
)->next
)
157 struct property
*menu_add_prompt(enum prop_type type
, char *prompt
,
160 struct property
*prop
= menu_add_prop(type
, NULL
, dep
);
162 if (isspace(*prompt
)) {
163 prop_warn(prop
, "leading whitespace ignored");
164 while (isspace(*prompt
))
167 if (current_entry
->prompt
)
168 prop_warn(prop
, "prompt redefined");
170 /* Apply all upper menus' visibilities to actual prompts. */
171 if (type
== P_PROMPT
) {
172 struct menu
*menu
= current_entry
;
174 while ((menu
= menu
->parent
) != NULL
) {
175 struct expr
*dup_expr
;
177 if (!menu
->visibility
)
180 * Do not add a reference to the menu's visibility
181 * expression but use a copy of it. Otherwise the
182 * expression reduction functions will modify
183 * expressions that have multiple references which
184 * can cause unwanted side effects.
186 dup_expr
= expr_copy(menu
->visibility
);
188 prop
->visible
.expr
= expr_alloc_and(prop
->visible
.expr
,
193 current_entry
->prompt
= prop
;
199 void menu_add_visibility(struct expr
*expr
)
201 current_entry
->visibility
= expr_alloc_and(current_entry
->visibility
,
205 void menu_add_expr(enum prop_type type
, struct expr
*expr
, struct expr
*dep
)
207 menu_add_prop(type
, expr
, dep
);
210 void menu_add_symbol(enum prop_type type
, struct symbol
*sym
, struct expr
*dep
)
212 menu_add_prop(type
, expr_alloc_symbol(sym
), dep
);
215 static int menu_validate_number(struct symbol
*sym
, struct symbol
*sym2
)
217 return sym2
->type
== S_INT
|| sym2
->type
== S_HEX
||
218 (sym2
->type
== S_UNKNOWN
&& sym_string_valid(sym
, sym2
->name
));
221 static void sym_check_prop(struct symbol
*sym
)
223 struct property
*prop
;
227 for (prop
= sym
->prop
; prop
; prop
= prop
->next
) {
228 switch (prop
->type
) {
230 if ((sym
->type
== S_STRING
|| sym
->type
== S_INT
|| sym
->type
== S_HEX
) &&
231 prop
->expr
->type
!= E_SYMBOL
)
233 "default for config symbol '%s'"
234 " must be a single symbol", sym
->name
);
235 if (prop
->expr
->type
!= E_SYMBOL
)
237 sym2
= prop_get_symbol(prop
);
238 if (sym
->type
== S_HEX
|| sym
->type
== S_INT
) {
239 if (!menu_validate_number(sym
, sym2
))
241 "'%s': number is invalid",
244 if (sym_is_choice(sym
)) {
245 struct property
*choice_prop
=
246 sym_get_choice_prop(sym2
);
249 prop_get_symbol(choice_prop
) != sym
)
251 "choice default symbol '%s' is not contained in the choice",
257 use
= prop
->type
== P_SELECT
? "select" : "imply";
258 sym2
= prop_get_symbol(prop
);
259 if (sym
->type
!= S_BOOLEAN
&& sym
->type
!= S_TRISTATE
)
261 "config symbol '%s' uses %s, but is "
262 "not bool or tristate", sym
->name
, use
);
263 else if (sym2
->type
!= S_UNKNOWN
&&
264 sym2
->type
!= S_BOOLEAN
&&
265 sym2
->type
!= S_TRISTATE
)
267 "'%s' has wrong type. '%s' only "
268 "accept arguments of bool and "
269 "tristate type", sym2
->name
, use
);
272 if (sym
->type
!= S_INT
&& sym
->type
!= S_HEX
)
273 prop_warn(prop
, "range is only allowed "
274 "for int or hex symbols");
275 if (!menu_validate_number(sym
, prop
->expr
->left
.sym
) ||
276 !menu_validate_number(sym
, prop
->expr
->right
.sym
))
277 prop_warn(prop
, "range is invalid");
285 void menu_finalize(struct menu
*parent
)
287 struct menu
*menu
, *last_menu
;
289 struct property
*prop
;
290 struct expr
*parentdep
, *basedep
, *dep
, *dep2
, **ep
;
295 * This menu node has children. We (recursively) process them
296 * and propagate parent dependencies before moving on.
299 if (sym
&& sym_is_choice(sym
)) {
300 if (sym
->type
== S_UNKNOWN
) {
301 /* find the first choice value to find out choice type */
302 current_entry
= parent
;
303 for (menu
= parent
->list
; menu
; menu
= menu
->next
) {
304 if (menu
->sym
&& menu
->sym
->type
!= S_UNKNOWN
) {
305 menu_set_type(menu
->sym
->type
);
310 /* set the type of the remaining choice values */
311 for (menu
= parent
->list
; menu
; menu
= menu
->next
) {
312 current_entry
= menu
;
313 if (menu
->sym
&& menu
->sym
->type
== S_UNKNOWN
)
314 menu_set_type(sym
->type
);
318 * Use the choice itself as the parent dependency of
319 * the contained items. This turns the mode of the
320 * choice into an upper bound on the visibility of the
321 * choice value symbols.
323 parentdep
= expr_alloc_symbol(sym
);
325 /* Menu node for 'menu', 'if' */
326 parentdep
= parent
->dep
;
329 /* For each child menu node... */
330 for (menu
= parent
->list
; menu
; menu
= menu
->next
) {
332 * Propagate parent dependencies to the child menu
333 * node, also rewriting and simplifying expressions
335 basedep
= rewrite_m(menu
->dep
);
336 basedep
= expr_transform(basedep
);
337 basedep
= expr_alloc_and(expr_copy(parentdep
), basedep
);
338 basedep
= expr_eliminate_dups(basedep
);
343 * Note: For symbols, all prompts are included
344 * too in the symbol's own property list
346 prop
= menu
->sym
->prop
;
349 * For non-symbol menu nodes, we just need to
354 /* For each property... */
355 for (; prop
; prop
= prop
->next
) {
356 if (prop
->menu
!= menu
)
360 * 1. The property lacks dependencies
361 * and so isn't location-specific,
364 * 2. The property belongs to a symbol
365 * defined in multiple locations and
366 * is from some other location. It
367 * will be handled there in that
375 * Propagate parent dependencies to the
376 * property's condition, rewriting and
377 * simplifying expressions at the same time
379 dep
= rewrite_m(prop
->visible
.expr
);
380 dep
= expr_transform(dep
);
381 dep
= expr_alloc_and(expr_copy(basedep
), dep
);
382 dep
= expr_eliminate_dups(dep
);
383 if (menu
->sym
&& menu
->sym
->type
!= S_TRISTATE
)
384 dep
= expr_trans_bool(dep
);
385 prop
->visible
.expr
= dep
;
388 * Handle selects and implies, which modify the
389 * dependencies of the selected/implied symbol
391 if (prop
->type
== P_SELECT
) {
392 struct symbol
*es
= prop_get_symbol(prop
);
393 es
->rev_dep
.expr
= expr_alloc_or(es
->rev_dep
.expr
,
394 expr_alloc_and(expr_alloc_symbol(menu
->sym
), expr_copy(dep
)));
395 } else if (prop
->type
== P_IMPLY
) {
396 struct symbol
*es
= prop_get_symbol(prop
);
397 es
->implied
.expr
= expr_alloc_or(es
->implied
.expr
,
398 expr_alloc_and(expr_alloc_symbol(menu
->sym
), expr_copy(dep
)));
403 if (sym
&& sym_is_choice(sym
))
404 expr_free(parentdep
);
407 * Recursively process children in the same fashion before
410 for (menu
= parent
->list
; menu
; menu
= menu
->next
)
414 * Automatic submenu creation. If sym is a symbol and A, B, C,
415 * ... are consecutive items (symbols, menus, ifs, etc.) that
416 * all depend on sym, then the following menu structure is
425 * This also works recursively, giving the following structure
426 * if A is a symbol and B depends on A:
435 basedep
= parent
->prompt
? parent
->prompt
->visible
.expr
: NULL
;
436 basedep
= expr_trans_compare(basedep
, E_UNEQUAL
, &symbol_no
);
437 basedep
= expr_eliminate_dups(expr_transform(basedep
));
439 /* Examine consecutive elements after sym */
441 for (menu
= parent
->next
; menu
; menu
= menu
->next
) {
442 dep
= menu
->prompt
? menu
->prompt
->visible
.expr
: menu
->dep
;
443 if (!expr_contains_symbol(dep
, sym
))
444 /* No dependency, quit */
446 if (expr_depends_symbol(dep
, sym
))
447 /* Absolute dependency, put in submenu */
451 * Also consider it a dependency on sym if our
452 * dependencies contain sym and are a "superset" of
453 * sym's dependencies, e.g. '(sym || Q) && R' when sym
456 * Note that 'R' might be from an enclosing menu or if,
457 * making this a more common case than it might seem.
459 dep
= expr_trans_compare(dep
, E_UNEQUAL
, &symbol_no
);
460 dep
= expr_eliminate_dups(expr_transform(dep
));
461 dep2
= expr_copy(basedep
);
462 expr_eliminate_eq(&dep
, &dep2
);
464 if (!expr_is_yes(dep2
)) {
465 /* Not superset, quit */
469 /* Superset, put in submenu */
473 menu
->parent
= parent
;
478 parent
->list
= parent
->next
;
479 parent
->next
= last_menu
->next
;
480 last_menu
->next
= NULL
;
483 sym
->dir_dep
.expr
= expr_alloc_or(sym
->dir_dep
.expr
, parent
->dep
);
485 for (menu
= parent
->list
; menu
; menu
= menu
->next
) {
486 if (sym
&& sym_is_choice(sym
) &&
487 menu
->sym
&& !sym_is_choice_value(menu
->sym
)) {
488 current_entry
= menu
;
489 menu
->sym
->flags
|= SYMBOL_CHOICEVAL
;
491 menu_warn(menu
, "choice value must have a prompt");
492 for (prop
= menu
->sym
->prop
; prop
; prop
= prop
->next
) {
493 if (prop
->type
== P_DEFAULT
)
494 prop_warn(prop
, "defaults for choice "
495 "values not supported");
496 if (prop
->menu
== menu
)
498 if (prop
->type
== P_PROMPT
&&
499 prop
->menu
->parent
->sym
!= sym
)
500 prop_warn(prop
, "choice value used outside its choice group");
502 /* Non-tristate choice values of tristate choices must
503 * depend on the choice being set to Y. The choice
504 * values' dependencies were propagated to their
505 * properties above, so the change here must be re-
508 if (sym
->type
== S_TRISTATE
&& menu
->sym
->type
!= S_TRISTATE
) {
509 basedep
= expr_alloc_comp(E_EQUAL
, sym
, &symbol_yes
);
510 menu
->dep
= expr_alloc_and(basedep
, menu
->dep
);
511 for (prop
= menu
->sym
->prop
; prop
; prop
= prop
->next
) {
512 if (prop
->menu
!= menu
)
514 prop
->visible
.expr
= expr_alloc_and(expr_copy(basedep
),
518 menu_add_symbol(P_CHOICE
, sym
, NULL
);
519 prop
= sym_get_choice_prop(sym
);
520 for (ep
= &prop
->expr
; *ep
; ep
= &(*ep
)->left
.expr
)
522 *ep
= expr_alloc_one(E_LIST
, NULL
);
523 (*ep
)->right
.sym
= menu
->sym
;
527 * This code serves two purposes:
529 * (1) Flattening 'if' blocks, which do not specify a submenu
530 * and only add dependencies.
532 * (Automatic submenu creation might still create a submenu
533 * from an 'if' before this code runs.)
535 * (2) "Undoing" any automatic submenus created earlier below
536 * promptless symbols.
541 * if ... (or promptless symbol)
549 * if ... (or promptless symbol)
554 if (menu
->list
&& (!menu
->prompt
|| !menu
->prompt
->text
)) {
555 for (last_menu
= menu
->list
; ; last_menu
= last_menu
->next
) {
556 last_menu
->parent
= parent
;
557 if (!last_menu
->next
)
560 last_menu
->next
= menu
->next
;
561 menu
->next
= menu
->list
;
566 if (sym
&& !(sym
->flags
& SYMBOL_WARNED
)) {
567 if (sym
->type
== S_UNKNOWN
)
568 menu_warn(parent
, "config symbol defined without type");
570 if (sym_is_choice(sym
) && !parent
->prompt
)
571 menu_warn(parent
, "choice must have a prompt");
573 /* Check properties connected to this symbol */
575 sym
->flags
|= SYMBOL_WARNED
;
579 * For non-optional choices, add a reverse dependency (corresponding to
580 * a select) of '<visibility> && m'. This prevents the user from
581 * setting the choice mode to 'n' when the choice is visible.
583 * This would also work for non-choice symbols, but only non-optional
584 * choices clear SYMBOL_OPTIONAL as of writing. Choices are implemented
585 * as a type of symbol.
587 if (sym
&& !sym_is_optional(sym
) && parent
->prompt
) {
588 sym
->rev_dep
.expr
= expr_alloc_or(sym
->rev_dep
.expr
,
589 expr_alloc_and(parent
->prompt
->visible
.expr
,
590 expr_alloc_symbol(&symbol_mod
)));
594 bool menu_has_prompt(struct menu
*menu
)
602 * Determine if a menu is empty.
603 * A menu is considered empty if it contains no or only
606 bool menu_is_empty(struct menu
*menu
)
610 for (child
= menu
->list
; child
; child
= child
->next
) {
611 if (menu_is_visible(child
))
617 bool menu_is_visible(struct menu
*menu
)
626 if (menu
->visibility
) {
627 if (expr_calc_value(menu
->visibility
) == no
)
634 visible
= menu
->prompt
->visible
.tri
;
636 visible
= menu
->prompt
->visible
.tri
= expr_calc_value(menu
->prompt
->visible
.expr
);
641 if (!sym
|| sym_get_tristate_value(menu
->sym
) == no
)
644 for (child
= menu
->list
; child
; child
= child
->next
) {
645 if (menu_is_visible(child
)) {
647 sym
->flags
|= SYMBOL_DEF_USER
;
655 const char *menu_get_prompt(struct menu
*menu
)
658 return menu
->prompt
->text
;
660 return menu
->sym
->name
;
664 struct menu
*menu_get_parent_menu(struct menu
*menu
)
668 for (; menu
!= &rootmenu
; menu
= menu
->parent
) {
669 type
= menu
->prompt
? menu
->prompt
->type
: 0;
676 static void get_def_str(struct gstr
*r
, struct menu
*menu
)
678 str_printf(r
, "Defined at %s:%d\n",
679 menu
->file
->name
, menu
->lineno
);
682 static void get_dep_str(struct gstr
*r
, struct expr
*expr
, const char *prefix
)
684 if (!expr_is_yes(expr
)) {
685 str_append(r
, prefix
);
686 expr_gstr_print(expr
, r
);
691 int __attribute__((weak
)) get_jump_key_char(void)
696 static void get_prompt_str(struct gstr
*r
, struct property
*prop
,
697 struct list_head
*head
)
700 struct menu
*submenu
[8], *menu
, *location
= NULL
;
701 struct jump_key
*jump
= NULL
;
703 str_printf(r
, " Prompt: %s\n", prop
->text
);
705 get_dep_str(r
, prop
->menu
->dep
, " Depends on: ");
707 * Most prompts in Linux have visibility that exactly matches their
708 * dependencies. For these, we print only the dependencies to improve
709 * readability. However, prompts with inline "if" expressions and
710 * prompts with a parent that has a "visible if" expression have
711 * differing dependencies and visibility. In these rare cases, we
714 if (!expr_eq(prop
->menu
->dep
, prop
->visible
.expr
))
715 get_dep_str(r
, prop
->visible
.expr
, " Visible if: ");
718 for (i
= 0; menu
!= &rootmenu
&& i
< 8; menu
= menu
->parent
) {
720 if (location
== NULL
&& menu_is_visible(menu
))
723 if (head
&& location
) {
724 jump
= xmalloc(sizeof(struct jump_key
));
725 jump
->target
= location
;
726 list_add_tail(&jump
->entries
, head
);
729 str_printf(r
, " Location:\n");
730 for (j
= 0; --i
>= 0; j
++) {
732 int indent
= 2 * j
+ 4;
735 if (jump
&& menu
== location
) {
736 jump
->offset
= strlen(r
->s
);
737 jk
= get_jump_key_char();
741 str_printf(r
, "(%c)", jk
);
745 str_printf(r
, "%*c-> %s", indent
, ' ', menu_get_prompt(menu
));
747 str_printf(r
, " (%s [=%s])", menu
->sym
->name
?
748 menu
->sym
->name
: "<choice>",
749 sym_get_string_value(menu
->sym
));
755 static void get_symbol_props_str(struct gstr
*r
, struct symbol
*sym
,
756 enum prop_type tok
, const char *prefix
)
759 struct property
*prop
;
761 for_all_properties(sym
, prop
, tok
) {
763 str_append(r
, prefix
);
766 str_printf(r
, " && ");
767 expr_gstr_print(prop
->expr
, r
);
774 * head is optional and may be NULL
776 static void get_symbol_str(struct gstr
*r
, struct symbol
*sym
,
777 struct list_head
*head
)
779 struct property
*prop
;
781 if (sym
&& sym
->name
) {
782 str_printf(r
, "Symbol: %s [=%s]\n", sym
->name
,
783 sym_get_string_value(sym
));
784 str_printf(r
, "Type : %s\n", sym_type_name(sym
->type
));
785 if (sym
->type
== S_INT
|| sym
->type
== S_HEX
) {
786 prop
= sym_get_range_prop(sym
);
788 str_printf(r
, "Range : ");
789 expr_gstr_print(prop
->expr
, r
);
795 /* Print the definitions with prompts before the ones without */
796 for_all_properties(sym
, prop
, P_SYMBOL
) {
797 if (prop
->menu
->prompt
) {
798 get_def_str(r
, prop
->menu
);
799 get_prompt_str(r
, prop
->menu
->prompt
, head
);
803 for_all_properties(sym
, prop
, P_SYMBOL
) {
804 if (!prop
->menu
->prompt
) {
805 get_def_str(r
, prop
->menu
);
806 get_dep_str(r
, prop
->menu
->dep
, " Depends on: ");
810 get_symbol_props_str(r
, sym
, P_SELECT
, "Selects: ");
811 if (sym
->rev_dep
.expr
) {
812 expr_gstr_print_revdep(sym
->rev_dep
.expr
, r
, yes
, "Selected by [y]:\n");
813 expr_gstr_print_revdep(sym
->rev_dep
.expr
, r
, mod
, "Selected by [m]:\n");
814 expr_gstr_print_revdep(sym
->rev_dep
.expr
, r
, no
, "Selected by [n]:\n");
817 get_symbol_props_str(r
, sym
, P_IMPLY
, "Implies: ");
818 if (sym
->implied
.expr
) {
819 expr_gstr_print_revdep(sym
->implied
.expr
, r
, yes
, "Implied by [y]:\n");
820 expr_gstr_print_revdep(sym
->implied
.expr
, r
, mod
, "Implied by [m]:\n");
821 expr_gstr_print_revdep(sym
->implied
.expr
, r
, no
, "Implied by [n]:\n");
824 str_append(r
, "\n\n");
827 struct gstr
get_relations_str(struct symbol
**sym_arr
, struct list_head
*head
)
830 struct gstr res
= str_new();
833 for (i
= 0; sym_arr
&& (sym
= sym_arr
[i
]); i
++)
834 get_symbol_str(&res
, sym
, head
);
836 str_append(&res
, "No matches found.\n");
841 void menu_get_ext_help(struct menu
*menu
, struct gstr
*help
)
843 struct symbol
*sym
= menu
->sym
;
844 const char *help_text
= nohelp_text
;
848 str_printf(help
, "%s%s:\n\n", CONFIG_
, sym
->name
);
849 help_text
= menu
->help
;
851 str_printf(help
, "%s\n", help_text
);
853 get_symbol_str(help
, sym
, NULL
);