.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |
---|
3 | | - * Released under the terms of the GNU GPL v2.0. |
---|
4 | 4 | */ |
---|
5 | 5 | |
---|
6 | 6 | #include <ctype.h> |
---|
.. | .. |
---|
65 | 65 | struct menu *menu_add_menu(void) |
---|
66 | 66 | { |
---|
67 | 67 | last_entry_ptr = ¤t_entry->list; |
---|
68 | | - return current_menu = current_entry; |
---|
| 68 | + current_menu = current_entry; |
---|
| 69 | + return current_menu; |
---|
69 | 70 | } |
---|
70 | 71 | |
---|
71 | 72 | void menu_end_menu(void) |
---|
.. | .. |
---|
124 | 125 | sym_type_name(sym->type), sym_type_name(type)); |
---|
125 | 126 | } |
---|
126 | 127 | |
---|
127 | | -static struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) |
---|
| 128 | +static struct property *menu_add_prop(enum prop_type type, struct expr *expr, |
---|
| 129 | + struct expr *dep) |
---|
128 | 130 | { |
---|
129 | | - struct property *prop = prop_alloc(type, current_entry->sym); |
---|
| 131 | + struct property *prop; |
---|
130 | 132 | |
---|
| 133 | + prop = xmalloc(sizeof(*prop)); |
---|
| 134 | + memset(prop, 0, sizeof(*prop)); |
---|
| 135 | + prop->type = type; |
---|
| 136 | + prop->file = current_file; |
---|
| 137 | + prop->lineno = zconf_lineno(); |
---|
131 | 138 | prop->menu = current_entry; |
---|
132 | 139 | prop->expr = expr; |
---|
133 | 140 | prop->visible.expr = dep; |
---|
134 | 141 | |
---|
135 | | - if (prompt) { |
---|
136 | | - if (isspace(*prompt)) { |
---|
137 | | - prop_warn(prop, "leading whitespace ignored"); |
---|
138 | | - while (isspace(*prompt)) |
---|
139 | | - prompt++; |
---|
140 | | - } |
---|
141 | | - if (current_entry->prompt && current_entry != &rootmenu) |
---|
142 | | - prop_warn(prop, "prompt redefined"); |
---|
| 142 | + /* append property to the prop list of symbol */ |
---|
| 143 | + if (current_entry->sym) { |
---|
| 144 | + struct property **propp; |
---|
143 | 145 | |
---|
144 | | - /* Apply all upper menus' visibilities to actual prompts. */ |
---|
145 | | - if(type == P_PROMPT) { |
---|
146 | | - struct menu *menu = current_entry; |
---|
147 | | - |
---|
148 | | - while ((menu = menu->parent) != NULL) { |
---|
149 | | - struct expr *dup_expr; |
---|
150 | | - |
---|
151 | | - if (!menu->visibility) |
---|
152 | | - continue; |
---|
153 | | - /* |
---|
154 | | - * Do not add a reference to the |
---|
155 | | - * menu's visibility expression but |
---|
156 | | - * use a copy of it. Otherwise the |
---|
157 | | - * expression reduction functions |
---|
158 | | - * will modify expressions that have |
---|
159 | | - * multiple references which can |
---|
160 | | - * cause unwanted side effects. |
---|
161 | | - */ |
---|
162 | | - dup_expr = expr_copy(menu->visibility); |
---|
163 | | - |
---|
164 | | - prop->visible.expr |
---|
165 | | - = expr_alloc_and(prop->visible.expr, |
---|
166 | | - dup_expr); |
---|
167 | | - } |
---|
168 | | - } |
---|
169 | | - |
---|
170 | | - current_entry->prompt = prop; |
---|
| 146 | + for (propp = ¤t_entry->sym->prop; |
---|
| 147 | + *propp; |
---|
| 148 | + propp = &(*propp)->next) |
---|
| 149 | + ; |
---|
| 150 | + *propp = prop; |
---|
171 | 151 | } |
---|
172 | | - prop->text = prompt; |
---|
173 | 152 | |
---|
174 | 153 | return prop; |
---|
175 | 154 | } |
---|
176 | 155 | |
---|
177 | | -struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) |
---|
| 156 | +struct property *menu_add_prompt(enum prop_type type, char *prompt, |
---|
| 157 | + struct expr *dep) |
---|
178 | 158 | { |
---|
179 | | - return menu_add_prop(type, prompt, NULL, dep); |
---|
| 159 | + struct property *prop = menu_add_prop(type, NULL, dep); |
---|
| 160 | + |
---|
| 161 | + if (isspace(*prompt)) { |
---|
| 162 | + prop_warn(prop, "leading whitespace ignored"); |
---|
| 163 | + while (isspace(*prompt)) |
---|
| 164 | + prompt++; |
---|
| 165 | + } |
---|
| 166 | + if (current_entry->prompt) |
---|
| 167 | + prop_warn(prop, "prompt redefined"); |
---|
| 168 | + |
---|
| 169 | + /* Apply all upper menus' visibilities to actual prompts. */ |
---|
| 170 | + if (type == P_PROMPT) { |
---|
| 171 | + struct menu *menu = current_entry; |
---|
| 172 | + |
---|
| 173 | + while ((menu = menu->parent) != NULL) { |
---|
| 174 | + struct expr *dup_expr; |
---|
| 175 | + |
---|
| 176 | + if (!menu->visibility) |
---|
| 177 | + continue; |
---|
| 178 | + /* |
---|
| 179 | + * Do not add a reference to the menu's visibility |
---|
| 180 | + * expression but use a copy of it. Otherwise the |
---|
| 181 | + * expression reduction functions will modify |
---|
| 182 | + * expressions that have multiple references which |
---|
| 183 | + * can cause unwanted side effects. |
---|
| 184 | + */ |
---|
| 185 | + dup_expr = expr_copy(menu->visibility); |
---|
| 186 | + |
---|
| 187 | + prop->visible.expr = expr_alloc_and(prop->visible.expr, |
---|
| 188 | + dup_expr); |
---|
| 189 | + } |
---|
| 190 | + } |
---|
| 191 | + |
---|
| 192 | + current_entry->prompt = prop; |
---|
| 193 | + prop->text = prompt; |
---|
| 194 | + |
---|
| 195 | + return prop; |
---|
180 | 196 | } |
---|
181 | 197 | |
---|
182 | 198 | void menu_add_visibility(struct expr *expr) |
---|
.. | .. |
---|
187 | 203 | |
---|
188 | 204 | void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) |
---|
189 | 205 | { |
---|
190 | | - menu_add_prop(type, NULL, expr, dep); |
---|
| 206 | + menu_add_prop(type, expr, dep); |
---|
191 | 207 | } |
---|
192 | 208 | |
---|
193 | 209 | void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) |
---|
194 | 210 | { |
---|
195 | | - menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); |
---|
| 211 | + menu_add_prop(type, expr_alloc_symbol(sym), dep); |
---|
196 | 212 | } |
---|
197 | 213 | |
---|
198 | | -void menu_add_option(int token, char *arg) |
---|
| 214 | +void menu_add_option_modules(void) |
---|
199 | 215 | { |
---|
200 | | - switch (token) { |
---|
201 | | - case T_OPT_MODULES: |
---|
202 | | - if (modules_sym) |
---|
203 | | - zconf_error("symbol '%s' redefines option 'modules'" |
---|
204 | | - " already defined by symbol '%s'", |
---|
205 | | - current_entry->sym->name, |
---|
206 | | - modules_sym->name |
---|
207 | | - ); |
---|
208 | | - modules_sym = current_entry->sym; |
---|
209 | | - break; |
---|
210 | | - case T_OPT_DEFCONFIG_LIST: |
---|
211 | | - if (!sym_defconfig_list) |
---|
212 | | - sym_defconfig_list = current_entry->sym; |
---|
213 | | - else if (sym_defconfig_list != current_entry->sym) |
---|
214 | | - zconf_error("trying to redefine defconfig symbol"); |
---|
215 | | - sym_defconfig_list->flags |= SYMBOL_NO_WRITE; |
---|
216 | | - break; |
---|
217 | | - case T_OPT_ALLNOCONFIG_Y: |
---|
218 | | - current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y; |
---|
219 | | - break; |
---|
220 | | - } |
---|
| 216 | + if (modules_sym) |
---|
| 217 | + zconf_error("symbol '%s' redefines option 'modules' already defined by symbol '%s'", |
---|
| 218 | + current_entry->sym->name, modules_sym->name); |
---|
| 219 | + modules_sym = current_entry->sym; |
---|
| 220 | +} |
---|
| 221 | + |
---|
| 222 | +void menu_add_option_defconfig_list(void) |
---|
| 223 | +{ |
---|
| 224 | + if (!sym_defconfig_list) |
---|
| 225 | + sym_defconfig_list = current_entry->sym; |
---|
| 226 | + else if (sym_defconfig_list != current_entry->sym) |
---|
| 227 | + zconf_error("trying to redefine defconfig symbol"); |
---|
| 228 | + sym_defconfig_list->flags |= SYMBOL_NO_WRITE; |
---|
| 229 | +} |
---|
| 230 | + |
---|
| 231 | +void menu_add_option_allnoconfig_y(void) |
---|
| 232 | +{ |
---|
| 233 | + current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y; |
---|
221 | 234 | } |
---|
222 | 235 | |
---|
223 | 236 | static int menu_validate_number(struct symbol *sym, struct symbol *sym2) |
---|
.. | .. |
---|
329 | 342 | * choice value symbols. |
---|
330 | 343 | */ |
---|
331 | 344 | parentdep = expr_alloc_symbol(sym); |
---|
332 | | - } else if (parent->prompt) |
---|
333 | | - /* Menu node for 'menu' */ |
---|
334 | | - parentdep = parent->prompt->visible.expr; |
---|
335 | | - else |
---|
336 | | - /* Menu node for 'if' */ |
---|
| 345 | + } else { |
---|
| 346 | + /* Menu node for 'menu', 'if' */ |
---|
337 | 347 | parentdep = parent->dep; |
---|
| 348 | + } |
---|
338 | 349 | |
---|
339 | 350 | /* For each child menu node... */ |
---|
340 | 351 | for (menu = parent->list; menu; menu = menu->next) { |
---|
.. | .. |
---|
701 | 712 | return ""; |
---|
702 | 713 | } |
---|
703 | 714 | |
---|
| 715 | +static void get_def_str(struct gstr *r, struct menu *menu) |
---|
| 716 | +{ |
---|
| 717 | + str_printf(r, "Defined at %s:%d\n", |
---|
| 718 | + menu->file->name, menu->lineno); |
---|
| 719 | +} |
---|
| 720 | + |
---|
| 721 | +static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix) |
---|
| 722 | +{ |
---|
| 723 | + if (!expr_is_yes(expr)) { |
---|
| 724 | + str_append(r, prefix); |
---|
| 725 | + expr_gstr_print(expr, r); |
---|
| 726 | + str_append(r, "\n"); |
---|
| 727 | + } |
---|
| 728 | +} |
---|
| 729 | + |
---|
704 | 730 | static void get_prompt_str(struct gstr *r, struct property *prop, |
---|
705 | 731 | struct list_head *head) |
---|
706 | 732 | { |
---|
.. | .. |
---|
708 | 734 | struct menu *submenu[8], *menu, *location = NULL; |
---|
709 | 735 | struct jump_key *jump = NULL; |
---|
710 | 736 | |
---|
711 | | - str_printf(r, "Prompt: %s\n", prop->text); |
---|
| 737 | + str_printf(r, " Prompt: %s\n", prop->text); |
---|
| 738 | + |
---|
| 739 | + get_dep_str(r, prop->menu->dep, " Depends on: "); |
---|
| 740 | + /* |
---|
| 741 | + * Most prompts in Linux have visibility that exactly matches their |
---|
| 742 | + * dependencies. For these, we print only the dependencies to improve |
---|
| 743 | + * readability. However, prompts with inline "if" expressions and |
---|
| 744 | + * prompts with a parent that has a "visible if" expression have |
---|
| 745 | + * differing dependencies and visibility. In these rare cases, we |
---|
| 746 | + * print both. |
---|
| 747 | + */ |
---|
| 748 | + if (!expr_eq(prop->menu->dep, prop->visible.expr)) |
---|
| 749 | + get_dep_str(r, prop->visible.expr, " Visible if: "); |
---|
| 750 | + |
---|
712 | 751 | menu = prop->menu->parent; |
---|
713 | 752 | for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) { |
---|
714 | 753 | bool accessible = menu_is_visible(menu); |
---|
.. | .. |
---|
758 | 797 | } |
---|
759 | 798 | } |
---|
760 | 799 | |
---|
761 | | -/* |
---|
762 | | - * get property of type P_SYMBOL |
---|
763 | | - */ |
---|
764 | | -static struct property *get_symbol_prop(struct symbol *sym) |
---|
765 | | -{ |
---|
766 | | - struct property *prop = NULL; |
---|
767 | | - |
---|
768 | | - for_all_properties(sym, prop, P_SYMBOL) |
---|
769 | | - break; |
---|
770 | | - return prop; |
---|
771 | | -} |
---|
772 | | - |
---|
773 | 800 | static void get_symbol_props_str(struct gstr *r, struct symbol *sym, |
---|
774 | 801 | enum prop_type tok, const char *prefix) |
---|
775 | 802 | { |
---|
.. | .. |
---|
809 | 836 | } |
---|
810 | 837 | } |
---|
811 | 838 | } |
---|
812 | | - for_all_prompts(sym, prop) |
---|
813 | | - get_prompt_str(r, prop, head); |
---|
814 | 839 | |
---|
815 | | - prop = get_symbol_prop(sym); |
---|
816 | | - if (prop) { |
---|
817 | | - str_printf(r, " Defined at %s:%d\n", prop->menu->file->name, |
---|
818 | | - prop->menu->lineno); |
---|
819 | | - if (!expr_is_yes(prop->visible.expr)) { |
---|
820 | | - str_append(r, " Depends on: "); |
---|
821 | | - expr_gstr_print(prop->visible.expr, r); |
---|
822 | | - str_append(r, "\n"); |
---|
| 840 | + /* Print the definitions with prompts before the ones without */ |
---|
| 841 | + for_all_properties(sym, prop, P_SYMBOL) { |
---|
| 842 | + if (prop->menu->prompt) { |
---|
| 843 | + get_def_str(r, prop->menu); |
---|
| 844 | + get_prompt_str(r, prop->menu->prompt, head); |
---|
823 | 845 | } |
---|
824 | 846 | } |
---|
825 | 847 | |
---|
826 | | - get_symbol_props_str(r, sym, P_SELECT, " Selects: "); |
---|
827 | | - if (sym->rev_dep.expr) { |
---|
828 | | - expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, " Selected by [y]:\n"); |
---|
829 | | - expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, " Selected by [m]:\n"); |
---|
830 | | - expr_gstr_print_revdep(sym->rev_dep.expr, r, no, " Selected by [n]:\n"); |
---|
| 848 | + for_all_properties(sym, prop, P_SYMBOL) { |
---|
| 849 | + if (!prop->menu->prompt) { |
---|
| 850 | + get_def_str(r, prop->menu); |
---|
| 851 | + get_dep_str(r, prop->menu->dep, " Depends on: "); |
---|
| 852 | + } |
---|
831 | 853 | } |
---|
832 | 854 | |
---|
833 | | - get_symbol_props_str(r, sym, P_IMPLY, " Implies: "); |
---|
| 855 | + get_symbol_props_str(r, sym, P_SELECT, "Selects: "); |
---|
| 856 | + if (sym->rev_dep.expr) { |
---|
| 857 | + expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, "Selected by [y]:\n"); |
---|
| 858 | + expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, "Selected by [m]:\n"); |
---|
| 859 | + expr_gstr_print_revdep(sym->rev_dep.expr, r, no, "Selected by [n]:\n"); |
---|
| 860 | + } |
---|
| 861 | + |
---|
| 862 | + get_symbol_props_str(r, sym, P_IMPLY, "Implies: "); |
---|
834 | 863 | if (sym->implied.expr) { |
---|
835 | | - expr_gstr_print_revdep(sym->implied.expr, r, yes, " Implied by [y]:\n"); |
---|
836 | | - expr_gstr_print_revdep(sym->implied.expr, r, mod, " Implied by [m]:\n"); |
---|
837 | | - expr_gstr_print_revdep(sym->implied.expr, r, no, " Implied by [n]:\n"); |
---|
| 864 | + expr_gstr_print_revdep(sym->implied.expr, r, yes, "Implied by [y]:\n"); |
---|
| 865 | + expr_gstr_print_revdep(sym->implied.expr, r, mod, "Implied by [m]:\n"); |
---|
| 866 | + expr_gstr_print_revdep(sym->implied.expr, r, no, "Implied by [n]:\n"); |
---|
838 | 867 | } |
---|
839 | 868 | |
---|
840 | 869 | str_append(r, "\n\n"); |
---|