summaryrefslogtreecommitdiff
path: root/scripts/kconfig/menu.c
Unidiff
Diffstat (limited to 'scripts/kconfig/menu.c') (more/less context) (ignore whitespace changes)
-rw-r--r--scripts/kconfig/menu.c194
1 files changed, 141 insertions, 53 deletions
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 24be0ec..1631767 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -54,9 +54,34 @@ void menu_end_menu(void)
54 current_menu = current_menu->parent; 54 current_menu = current_menu->parent;
55} 55}
56 56
57struct expr *menu_check_dep(struct expr *e)
58{
59 if (!e)
60 return e;
61
62 switch (e->type) {
63 case E_NOT:
64 e->left.expr = menu_check_dep(e->left.expr);
65 break;
66 case E_OR:
67 case E_AND:
68 e->left.expr = menu_check_dep(e->left.expr);
69 e->right.expr = menu_check_dep(e->right.expr);
70 break;
71 case E_SYMBOL:
72 /* change 'm' into 'm' && MODULES */
73 if (e->left.sym == &symbol_mod)
74 return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
75 break;
76 default:
77 break;
78 }
79 return e;
80}
81
57void menu_add_dep(struct expr *dep) 82void menu_add_dep(struct expr *dep)
58{ 83{
59 current_entry->dep = expr_alloc_and(current_entry->dep, dep); 84 current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
60} 85}
61 86
62void menu_set_type(int type) 87void menu_set_type(int type)
@@ -69,56 +94,43 @@ void menu_set_type(int type)
69 sym->type = type; 94 sym->type = type;
70 return; 95 return;
71 } 96 }
72 fprintf(stderr, "%s:%d: type of '%s' redefined from '%s' to '%s'\n", 97 fprintf(stderr, "%s:%d:warning: type of '%s' redefined from '%s' to '%s'\n",
73 current_entry->file->name, current_entry->lineno, 98 current_entry->file->name, current_entry->lineno,
74 sym->name ? sym->name : "<choice>", sym_type_name(sym->type), sym_type_name(type)); 99 sym->name ? sym->name : "<choice>", sym_type_name(sym->type), sym_type_name(type));
75} 100}
76 101
77struct property *create_prop(enum prop_type type) 102struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
78{
79 struct property *prop;
80
81 prop = malloc(sizeof(*prop));
82 memset(prop, 0, sizeof(*prop));
83 prop->type = type;
84 prop->file = current_file;
85 prop->lineno = zconf_lineno();
86
87 return prop;
88}
89
90struct property *menu_add_prop(int token, char *prompt, struct symbol *def, struct expr *dep)
91{ 103{
92 struct property *prop = create_prop(token); 104 struct property *prop = prop_alloc(type, current_entry->sym);
93 struct property **propp;
94 105
95 prop->sym = current_entry->sym;
96 prop->menu = current_entry; 106 prop->menu = current_entry;
97 prop->text = prompt; 107 prop->text = prompt;
98 prop->def = def; 108 prop->expr = expr;
99 E_EXPR(prop->visible) = dep; 109 prop->visible.expr = menu_check_dep(dep);
100 110
101 if (prompt) 111 if (prompt) {
112 if (current_entry->prompt)
113 fprintf(stderr, "%s:%d: prompt redefined\n",
114 current_entry->file->name, current_entry->lineno);
102 current_entry->prompt = prop; 115 current_entry->prompt = prop;
103
104 /* append property to the prop list of symbol */
105 if (prop->sym) {
106 for (propp = &prop->sym->prop; *propp; propp = &(*propp)->next)
107 ;
108 *propp = prop;
109 } 116 }
110 117
111 return prop; 118 return prop;
112} 119}
113 120
114void menu_add_prompt(int token, char *prompt, struct expr *dep) 121void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
115{ 122{
116 current_entry->prompt = menu_add_prop(token, prompt, NULL, dep); 123 menu_add_prop(type, prompt, NULL, dep);
117} 124}
118 125
119void menu_add_default(int token, struct symbol *def, struct expr *dep) 126void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
120{ 127{
121 current_entry->prompt = menu_add_prop(token, NULL, def, dep); 128 menu_add_prop(type, NULL, expr, dep);
129}
130
131void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
132{
133 menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
122} 134}
123 135
124void menu_finalize(struct menu *parent) 136void menu_finalize(struct menu *parent)
@@ -126,7 +138,7 @@ void menu_finalize(struct menu *parent)
126 struct menu *menu, *last_menu; 138 struct menu *menu, *last_menu;
127 struct symbol *sym; 139 struct symbol *sym;
128 struct property *prop; 140 struct property *prop;
129 struct expr *parentdep, *basedep, *dep, *dep2; 141 struct expr *parentdep, *basedep, *dep, *dep2, **ep;
130 142
131 sym = parent->sym; 143 sym = parent->sym;
132 if (parent->list) { 144 if (parent->list) {
@@ -143,7 +155,7 @@ void menu_finalize(struct menu *parent)
143 } 155 }
144 parentdep = expr_alloc_symbol(sym); 156 parentdep = expr_alloc_symbol(sym);
145 } else if (parent->prompt) 157 } else if (parent->prompt)
146 parentdep = E_EXPR(parent->prompt->visible); 158 parentdep = parent->prompt->visible.expr;
147 else 159 else
148 parentdep = parent->dep; 160 parentdep = parent->dep;
149 161
@@ -159,23 +171,28 @@ void menu_finalize(struct menu *parent)
159 for (; prop; prop = prop->next) { 171 for (; prop; prop = prop->next) {
160 if (prop->menu != menu) 172 if (prop->menu != menu)
161 continue; 173 continue;
162 dep = expr_transform(E_EXPR(prop->visible)); 174 dep = expr_transform(prop->visible.expr);
163 dep = expr_alloc_and(expr_copy(basedep), dep); 175 dep = expr_alloc_and(expr_copy(basedep), dep);
164 dep = expr_eliminate_dups(dep); 176 dep = expr_eliminate_dups(dep);
165 if (menu->sym && menu->sym->type != S_TRISTATE) 177 if (menu->sym && menu->sym->type != S_TRISTATE)
166 dep = expr_trans_bool(dep); 178 dep = expr_trans_bool(dep);
167 E_EXPR(prop->visible) = dep; 179 prop->visible.expr = dep;
180 if (prop->type == P_SELECT) {
181 struct symbol *es = prop_get_symbol(prop);
182 es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
183 expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
184 }
168 } 185 }
169 } 186 }
170 for (menu = parent->list; menu; menu = menu->next) 187 for (menu = parent->list; menu; menu = menu->next)
171 menu_finalize(menu); 188 menu_finalize(menu);
172 } else if (sym && parent->prompt) { 189 } else if (sym) {
173 basedep = E_EXPR(parent->prompt->visible); 190 basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
174 basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); 191 basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
175 basedep = expr_eliminate_dups(expr_transform(basedep)); 192 basedep = expr_eliminate_dups(expr_transform(basedep));
176 last_menu = NULL; 193 last_menu = NULL;
177 for (menu = parent->next; menu; menu = menu->next) { 194 for (menu = parent->next; menu; menu = menu->next) {
178 dep = menu->prompt ? E_EXPR(menu->prompt->visible) : menu->dep; 195 dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
179 if (!expr_contains_symbol(dep, sym)) 196 if (!expr_contains_symbol(dep, sym))
180 break; 197 break;
181 if (expr_depends_symbol(dep, sym)) 198 if (expr_depends_symbol(dep, sym))
@@ -204,14 +221,27 @@ void menu_finalize(struct menu *parent)
204 for (menu = parent->list; menu; menu = menu->next) { 221 for (menu = parent->list; menu; menu = menu->next) {
205 if (sym && sym_is_choice(sym) && menu->sym) { 222 if (sym && sym_is_choice(sym) && menu->sym) {
206 menu->sym->flags |= SYMBOL_CHOICEVAL; 223 menu->sym->flags |= SYMBOL_CHOICEVAL;
224 if (!menu->prompt)
225 fprintf(stderr, "%s:%d:warning: choice value must have a prompt\n",
226 menu->file->name, menu->lineno);
227 for (prop = menu->sym->prop; prop; prop = prop->next) {
228 if (prop->type == P_PROMPT && prop->menu != menu) {
229 fprintf(stderr, "%s:%d:warning: choice values currently only support a single prompt\n",
230 prop->file->name, prop->lineno);
231
232 }
233 if (prop->type == P_DEFAULT)
234 fprintf(stderr, "%s:%d:warning: defaults for choice values not supported\n",
235 prop->file->name, prop->lineno);
236 }
207 current_entry = menu; 237 current_entry = menu;
208 menu_set_type(sym->type); 238 menu_set_type(sym->type);
209 menu_add_prop(P_CHOICE, NULL, parent->sym, NULL); 239 menu_add_symbol(P_CHOICE, sym, NULL);
210 prop = sym_get_choice_prop(parent->sym); 240 prop = sym_get_choice_prop(sym);
211 //dep = expr_alloc_one(E_CHOICE, dep); 241 for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
212 //dep->right.sym = menu->sym; 242 ;
213 prop->dep = expr_alloc_one(E_CHOICE, prop->dep); 243 *ep = expr_alloc_one(E_CHOICE, NULL);
214 prop->dep->right.sym = menu->sym; 244 (*ep)->right.sym = menu->sym;
215 } 245 }
216 if (menu->list && (!menu->prompt || !menu->prompt->text)) { 246 if (menu->list && (!menu->prompt || !menu->prompt->text)) {
217 for (last_menu = menu->list; ; last_menu = last_menu->next) { 247 for (last_menu = menu->list; ; last_menu = last_menu->next) {
@@ -224,20 +254,79 @@ void menu_finalize(struct menu *parent)
224 menu->list = NULL; 254 menu->list = NULL;
225 } 255 }
226 } 256 }
257
258 if (sym && !(sym->flags & SYMBOL_WARNED)) {
259 struct symbol *sym2;
260 if (sym->type == S_UNKNOWN)
261 fprintf(stderr, "%s:%d:warning: config symbol defined without type\n",
262 parent->file->name, parent->lineno);
263
264 if (sym_is_choice(sym) && !parent->prompt)
265 fprintf(stderr, "%s:%d:warning: choice must have a prompt\n",
266 parent->file->name, parent->lineno);
267
268 for (prop = sym->prop; prop; prop = prop->next) {
269 switch (prop->type) {
270 case P_DEFAULT:
271 if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
272 prop->expr->type != E_SYMBOL)
273 fprintf(stderr, "%s:%d:warning: default must be a single symbol\n",
274 prop->file->name, prop->lineno);
275 break;
276 case P_SELECT:
277 sym2 = prop_get_symbol(prop);
278 if ((sym->type != S_BOOLEAN && sym->type != S_TRISTATE) ||
279 (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE))
280 fprintf(stderr, "%s:%d:warning: enable is only allowed with boolean and tristate symbols\n",
281 prop->file->name, prop->lineno);
282 break;
283 case P_RANGE:
284 if (sym->type != S_INT && sym->type != S_HEX)
285 fprintf(stderr, "%s:%d:warning: range is only allowed for int or hex symbols\n",
286 prop->file->name, prop->lineno);
287 if (!sym_string_valid(sym, prop->expr->left.sym->name) ||
288 !sym_string_valid(sym, prop->expr->right.sym->name))
289 fprintf(stderr, "%s:%d:warning: range is invalid\n",
290 prop->file->name, prop->lineno);
291 break;
292 default:
293 ;
294 }
295 }
296 sym->flags |= SYMBOL_WARNED;
297 }
298
299 if (sym && !sym_is_optional(sym) && parent->prompt) {
300 sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
301 expr_alloc_and(parent->prompt->visible.expr,
302 expr_alloc_symbol(&symbol_mod)));
303 }
227} 304}
228 305
229bool menu_is_visible(struct menu *menu) 306bool menu_is_visible(struct menu *menu)
230{ 307{
308 struct menu *child;
309 struct symbol *sym;
231 tristate visible; 310 tristate visible;
232 311
233 if (!menu->prompt) 312 if (!menu->prompt)
234 return false; 313 return false;
235 if (menu->sym) { 314 sym = menu->sym;
236 sym_calc_value(menu->sym); 315 if (sym) {
237 visible = E_TRI(menu->prompt->visible); 316 sym_calc_value(sym);
317 visible = menu->prompt->visible.tri;
238 } else 318 } else
239 visible = E_CALC(menu->prompt->visible); 319 visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
240 return visible != no; 320
321 if (visible != no)
322 return true;
323 if (!sym || sym_get_tristate_value(menu->sym) == no)
324 return false;
325
326 for (child = menu->list; child; child = child->next)
327 if (menu_is_visible(child))
328 return true;
329 return false;
241} 330}
242 331
243const char *menu_get_prompt(struct menu *menu) 332const char *menu_get_prompt(struct menu *menu)
@@ -258,10 +347,9 @@ struct menu *menu_get_parent_menu(struct menu *menu)
258{ 347{
259 enum prop_type type; 348 enum prop_type type;
260 349
261 while (menu != &rootmenu) { 350 for (; menu != &rootmenu; menu = menu->parent) {
262 menu = menu->parent;
263 type = menu->prompt ? menu->prompt->type : 0; 351 type = menu->prompt ? menu->prompt->type : 0;
264 if (type == P_MENU || type == P_ROOTMENU) 352 if (type == P_MENU)
265 break; 353 break;
266 } 354 }
267 return menu; 355 return menu;