summaryrefslogtreecommitdiff
path: root/kconfiglib.py
diff options
context:
space:
mode:
Diffstat (limited to 'kconfiglib.py')
-rw-r--r--kconfiglib.py97
1 files changed, 59 insertions, 38 deletions
diff --git a/kconfiglib.py b/kconfiglib.py
index 6abb4e6..af5415d 100644
--- a/kconfiglib.py
+++ b/kconfiglib.py
@@ -2097,7 +2097,7 @@ class Kconfig(object):
def _parse_properties(self, node):
# Parses and adds properties to the MenuNode 'node' (type, 'prompt',
# 'default's, etc.) Properties are later copied up to symbols and
- # choices in a separate pass after parsing, in _propagate_deps().
+ # choices in a separate pass after parsing, in _copy_deps_to_sc().
#
# An older version of this code added properties directly to symbols
# and choices instead of to their menu nodes (and handled dependency
@@ -2536,17 +2536,28 @@ class Kconfig(object):
if node.item == MENU:
visible_if = self._make_and(visible_if, node.visibility)
+ # Propagate the menu node's dependencies to each child menu node.
+ #
+ # The recursive _finalize_tree() calls assume that the current
+ # "level" in the tree has already had dependencies propagated. This
+ # makes e.g. implicit submenu creation, which needs to look ahead,
+ # easier to implement.
self._propagate_deps(node, visible_if)
+ # Finalize the children
cur = node.list
while cur:
self._finalize_tree(cur, visible_if)
cur = cur.next
elif isinstance(node.item, Symbol):
- # The menu node is a symbol. See if we can create an implicit menu
- # rooted at it and finalize each child in that menu if so, like for
- # the choice/menu/if case above.
+ # Add the node's non-node-specific properties (defaults, ranges,
+ # etc.) to the Symbol
+ self._copy_deps_to_sc(node)
+
+ # See if we can create an implicit menu rooted at the Symbol and
+ # finalize each child menu node in that menu if so, like for the
+ # choice/menu/if case above
cur = node
while cur.next and _auto_menu_dep(node, cur.next):
# This also makes implicit submenu creation work recursively,
@@ -2572,17 +2583,12 @@ class Kconfig(object):
# Empty choices (node.list None) are possible, so this needs to go
# outside
if isinstance(node.item, Choice):
+ # Add the node's non-node-specific properties to the choice
+ self._copy_deps_to_sc(node)
_finalize_choice(node)
def _propagate_deps(self, node, visible_if):
- # This function combines two tasks:
- #
- # 1) Copy properties from menu nodes to symbols and choices
- #
- # 2) Propagate dependencies from 'if' and 'depends on' to all
- # properties
- #
- # See _parse_properties() as well.
+ # Propagates 'node's dependencies to its child menu nodes
# If the parent node holds a Choice, we use the Choice itself as the
# parent dependency. This makes sense as the value (mode) of the choice
@@ -2605,15 +2611,6 @@ class Kconfig(object):
if isinstance(cur.item, (Symbol, Choice)):
sc = cur.item
- # See the Symbol class docstring
- sc.direct_dep = self._make_or(sc.direct_dep, dep)
-
- # TODO: Profile this code and see if the 'if's are worthwhile.
- # Another potential optimization would be to assign the lists
- # from the MenuNode directly instead of using extend() in cases
- # where a symbol/choice only has a single MenuNode (the
- # majority of cases).
-
# Propagate 'visible if' dependencies to the prompt
if cur.prompt:
cur.prompt = (cur.prompt[0],
@@ -2624,45 +2621,69 @@ class Kconfig(object):
if cur.defaults:
cur.defaults = [(default, self._make_and(cond, dep))
for default, cond in cur.defaults]
- sc.defaults.extend(cur.defaults)
# Propagate dependencies to ranges
if cur.ranges:
cur.ranges = [(low, high, self._make_and(cond, dep))
for low, high, cond in cur.ranges]
- sc.ranges.extend(cur.ranges)
# Propagate dependencies to selects
if cur.selects:
cur.selects = [(target, self._make_and(cond, dep))
for target, cond in cur.selects]
- sc.selects.extend(cur.selects)
-
- # Modify the reverse dependencies of the selected symbol
- for target, cond in cur.selects:
- target.rev_dep = self._make_or(
- target.rev_dep,
- self._make_and(sc, cond))
# Propagate dependencies to implies
if cur.implies:
cur.implies = [(target, self._make_and(cond, dep))
for target, cond in cur.implies]
- sc.implies.extend(cur.implies)
-
- # Modify the weak reverse dependencies of the implied
- # symbol
- for target, cond in cur.implies:
- target.weak_rev_dep = self._make_or(
- target.weak_rev_dep,
- self._make_and(sc, cond))
cur = cur.next
+ def _copy_deps_to_sc(self, node):
+ # Copies properties from the menu node 'node' up to its
+ # contained symbol or choice.
+ #
+ # This can't be rolled into _propagate_deps(), because that function
+ # traverses the menu tree roughly breadth-first order, meaning
+ # properties on symbols and choices defined in multiple locations could
+ # end up in the wrong order.
+
+ # Symbol or choice
+ sc = node.item
+
+ # See the Symbol class docstring
+ sc.direct_dep = self._make_or(sc.direct_dep, node.dep)
+
+ if node.defaults:
+ sc.defaults.extend(node.defaults)
+
+ if node.ranges:
+ sc.ranges.extend(node.ranges)
+
+ if node.selects:
+ sc.selects.extend(node.selects)
+
+ # Modify the reverse dependencies of the selected symbol
+ for target, cond in node.selects:
+ target.rev_dep = self._make_or(
+ target.rev_dep,
+ self._make_and(sc, cond))
+
+ if node.implies:
+ sc.implies.extend(node.implies)
+
+ # Modify the weak reverse dependencies of the implied
+ # symbol
+ for target, cond in node.implies:
+ target.weak_rev_dep = self._make_or(
+ target.weak_rev_dep,
+ self._make_and(sc, cond))
+
+
#
# Misc.
#