menu_finalize() is one of the more opaque parts of Kconfig, and I need to make some changes to it to fix an issue related to modules. Add some comments related to expression rewriting and dependency propagation as a review aid. They will also help other people trying to understand the code.
Unified · Split
| @@ -306,6 +306,11 @@ void menu_finalize(struct menu *parent) · 305 unmodified lines | ||
| 306 | 306 | |
| 307 | 307 | sym = parent->sym; |
| 308 | 308 | if (parent->list) { |
| 309 | + /* | |
| 310 | + * This menu node has children. We (recursively) process them | |
| 311 | + * and propagate parent dependencies before moving on. | |
| 312 | + */ | |
| 313 | + | |
| 309 | 314 | if (sym && sym_is_choice(sym)) { |
| 310 | 315 | if (sym->type == S_UNKNOWN) { |
| 311 | 316 | /* find the first choice value to find out choice type */ |
| @@ -329,24 +334,66 @@ void menu_finalize(struct menu *parent) · 17 unmodified lines | ||
| 329 | 334 | else |
| 330 | 335 | parentdep = parent->dep; |
| 331 | 336 | |
| 337 | + /* For each child menu node... */ | |
| 332 | 338 | for (menu = parent->list; menu; menu = menu->next) { |
| 339 | + /* | |
| 340 | + * Propagate parent dependencies to the child menu | |
| 341 | + * node, also rewriting and simplifying expressions | |
| 342 | + */ | |
| 333 | 343 | basedep = expr_transform(menu->dep); |
| 334 | 344 | basedep = expr_alloc_and(expr_copy(parentdep), basedep); |
| 335 | 345 | basedep = expr_eliminate_dups(basedep); |
| 336 | 346 | menu->dep = basedep; |
| 347 | + | |
| 337 | 348 | if (menu->sym) |
| 349 | + /* | |
| 350 | + * Note: For symbols, all prompts are included | |
| 351 | + * too in the symbol's own property list | |
| 352 | + */ | |
| 338 | 353 | prop = menu->sym->prop; |
| 339 | 354 | else |
| 355 | + /* | |
| 356 | + * For non-symbol menu nodes, we just need to | |
| 357 | + * handle the prompt | |
| 358 | + */ | |
| 340 | 359 | prop = menu->prompt; |
| 360 | + | |
| 361 | + /* For each property... */ | |
| 341 | 362 | for (; prop; prop = prop->next) { |
| 342 | 363 | if (prop->menu != menu) |
| 364 | + /* | |
| 365 | + * Two possibilities: | |
| 366 | + * | |
| 367 | + * 1. The property lacks dependencies | |
| 368 | + * and so isn't location-specific, | |
| 369 | + * e.g. an 'option' | |
| 370 | + * | |
| 371 | + * 2. The property belongs to a symbol | |
| 372 | + * defined in multiple locations and | |
| 373 | + * is from some other location. It | |
| 374 | + * will be handled there in that | |
| 375 | + * case. | |
| 376 | + * | |
| 377 | + * Skip the property. | |
| 378 | + */ | |
| 343 | 379 | continue; |
| 380 | + | |
| 381 | + /* | |
| 382 | + * Propagate parent dependencies to the | |
| 383 | + * property's condition, rewriting and | |
| 384 | + * simplifying expressions at the same time | |
| 385 | + */ | |
| 344 | 386 | dep = expr_transform(prop->visible.expr); |
| 345 | 387 | dep = expr_alloc_and(expr_copy(basedep), dep); |
| 346 | 388 | dep = expr_eliminate_dups(dep); |
| 347 | 389 | if (menu->sym && menu->sym->type != S_TRISTATE) |
| 348 | 390 | dep = expr_trans_bool(dep); |
| 349 | 391 | prop->visible.expr = dep; |
| 392 | + | |
| 393 | + /* | |
| 394 | + * Handle selects and implies, which modify the | |
| 395 | + * dependencies of the selected/implied symbol | |
| 396 | + */ | |
| 350 | 397 | if (prop->type == P_SELECT) { |
| 351 | 398 | struct symbol *es = prop_get_symbol(prop); |
| 352 | 399 | es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, |
| @@ -358,6 +405,11 @@ void menu_finalize(struct menu *parent) · 5 unmodified lines | ||
| 358 | 405 | } |
| 359 | 406 | } |
| 360 | 407 | } |
| 408 | + | |
| 409 | + /* | |
| 410 | + * Recursively process children in the same fashion before | |
| 411 | + * moving on | |
| 412 | + */ | |
| 361 | 413 | for (menu = parent->list; menu; menu = menu->next) |
| 362 | 414 | menu_finalize(menu); |
| 363 | 415 | } else if (sym) { |