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 | sym = parent->sym; | 307 | sym = parent->sym; |
| 308 | if (parent->list) { | 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 | if (sym && sym_is_choice(sym)) { | 314 | if (sym && sym_is_choice(sym)) { |
| 310 | if (sym->type == S_UNKNOWN) { | 315 | if (sym->type == S_UNKNOWN) { |
| 311 | /* find the first choice value to find out choice type */ | 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 | else | 334 | else |
| 330 | parentdep = parent->dep; | 335 | parentdep = parent->dep; |
| 331 | 336 | ||
| 337 | /* For each child menu node... */ | ||
| 332 | for (menu = parent->list; menu; menu = menu->next) { | 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 | basedep = expr_transform(menu->dep); | 343 | basedep = expr_transform(menu->dep); |
| 334 | basedep = expr_alloc_and(expr_copy(parentdep), basedep); | 344 | basedep = expr_alloc_and(expr_copy(parentdep), basedep); |
| 335 | basedep = expr_eliminate_dups(basedep); | 345 | basedep = expr_eliminate_dups(basedep); |
| 336 | menu->dep = basedep; | 346 | menu->dep = basedep; |
| 347 | |||
| 337 | if (menu->sym) | 348 | if (menu->sym) |
| 349 | /* | ||
| 350 | * Note: For symbols, all prompts are included | ||
| 351 | * too in the symbol's own property list | ||
| 352 | */ | ||
| 338 | prop = menu->sym->prop; | 353 | prop = menu->sym->prop; |
| 339 | else | 354 | else |
| 355 | /* | ||
| 356 | * For non-symbol menu nodes, we just need to | ||
| 357 | * handle the prompt | ||
| 358 | */ | ||
| 340 | prop = menu->prompt; | 359 | prop = menu->prompt; |
| 360 | |||
| 361 | /* For each property... */ | ||
| 341 | for (; prop; prop = prop->next) { | 362 | for (; prop; prop = prop->next) { |
| 342 | if (prop->menu != menu) | 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 | continue; | 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 | dep = expr_transform(prop->visible.expr); | 386 | dep = expr_transform(prop->visible.expr); |
| 345 | dep = expr_alloc_and(expr_copy(basedep), dep); | 387 | dep = expr_alloc_and(expr_copy(basedep), dep); |
| 346 | dep = expr_eliminate_dups(dep); | 388 | dep = expr_eliminate_dups(dep); |
| 347 | if (menu->sym && menu->sym->type != S_TRISTATE) | 389 | if (menu->sym && menu->sym->type != S_TRISTATE) |
| 348 | dep = expr_trans_bool(dep); | 390 | dep = expr_trans_bool(dep); |
| 349 | prop->visible.expr = dep; | 391 | prop->visible.expr = dep; |
| 392 | |||
| 393 | /* | ||
| 394 | * Handle selects and implies, which modify the | ||
| 395 | * dependencies of the selected/implied symbol | ||
| 396 | */ | ||
| 350 | if (prop->type == P_SELECT) { | 397 | if (prop->type == P_SELECT) { |
| 351 | struct symbol *es = prop_get_symbol(prop); | 398 | struct symbol *es = prop_get_symbol(prop); |
| 352 | es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, | 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 | for (menu = parent->list; menu; menu = menu->next) | 413 | for (menu = parent->list; menu; menu = menu->next) |
| 362 | menu_finalize(menu); | 414 | menu_finalize(menu); |
| 363 | } else if (sym) { | 415 | } else if (sym) { |