summaryrefslogtreecommitdiff
path: root/examples/allyesconfig.py
diff options
context:
space:
mode:
authorUlf Magnusson <ulfalizer@gmail.com>2017-10-09 23:05:00 +0200
committerUlf Magnusson <ulfalizer@gmail.com>2017-10-24 19:24:08 +0200
commitdd0e227216e247d2040cdd40bf7397702880cdc4 (patch)
tree4c76ebb2e7555d28214cddecf32ffb424fa1732b /examples/allyesconfig.py
parentf64aaf971176305233f16a11911a660fa6f99561 (diff)
Kconfiglib 2 backup
WIP
Diffstat (limited to 'examples/allyesconfig.py')
-rw-r--r--examples/allyesconfig.py133
1 files changed, 90 insertions, 43 deletions
diff --git a/examples/allyesconfig.py b/examples/allyesconfig.py
index 906343c..4847c05 100644
--- a/examples/allyesconfig.py
+++ b/examples/allyesconfig.py
@@ -1,65 +1,112 @@
-# Works like allyesconfig. This is a bit more involved than allnoconfig as we
-# need to handle choices in two different modes:
+# Works like 'make allyesconfig'. Verified by the test suite to generate
+# identical output to 'make allyesconfig' for all ARCHES.
#
-# "y": One symbol is "y", the rest are "n".
-# "m": Any number of symbols are "m", the rest are "n".
+# This could be implemented as a straightforward tree walk just like
+# allnoconfig.py (or even simpler like allnoconfig_simpler.py), but do it a bit
+# differently (roundabout) just to demonstrate some other possibilities.
#
-# Only tristate choices can be in "m" mode. It is safe since the code for two
-# conflicting options will appear as separate modules instead of simultaneously
-# in the kernel.
+# allyesconfig is a bit more involved than allnoconfig as we need to handle
+# choices in two different modes:
#
-# If a choice can be in "y" mode, it will be. If it can only be in "m" mode
-# (due to dependencies), then all the options will be set to "m".
+# y: One symbol is "y", the rest are "n"
+# m: Any number of symbols are "m", the rest are "n"
#
-# The looping is in case setting one symbol to "y" (or "m") allows the value of
-# other symbols to be raised.
+# Only tristate choices can be in "m" mode. No "m" mode choices seem to appear
+# for allyesconfig on the kernel Kconfigs as of 4.14, but we still handle it.
+#
+# Usage:
+#
+# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/allyesconfig.py
-import kconfiglib
+from kconfiglib import Config, Choice, tri_less
import sys
-conf = kconfiglib.Config(sys.argv[1])
+conf = Config(sys.argv[1])
+
+# Collect all the choices in the configuration. Demonstrates how the menu node
+# tree can be walked iteratively by using the parent pointers.
+
+choices = []
+node = conf.top_menu
+
+while 1:
+ if isinstance(node.item, Choice):
+ choices.append(node.item)
+
+ # Iterative tree walking by using parent pointers.
+ #
+ # Recursing on next pointers can blow the Python stack. Recursing on child
+ # pointers is safe (as is done in the other examples). This gives a
+ # template for how you can avoid recursing on both. The same logic is found
+ # in the C implementation.
+
+ if node.list is not None:
+ # Jump to child node if available
+ node = node.list
+
+ elif node.next is not None:
+ # Otherwise, jump to next node if available
+ node = node.next
-# Get a list of all symbols that are not in choices
-non_choice_syms = [sym for sym in conf.get_symbols() if
- not sym.is_choice_symbol()]
+ else:
+ # Otherwise, look for parents with next nodes to jump to
+ while node.parent is not None:
+ node = node.parent
+ if node.next is not None:
+ node = node.next
+ break
+ else:
+ # No parents with next nodes, all nodes visited
+ break
-done = False
-while not done:
- done = True
+# Collect all symbols that are not in choices
+non_choice_syms = [sym for sym in conf.defined_syms if sym.choice is None]
+
+while 1:
+ no_changes = True
# Handle symbols outside of choices
for sym in non_choice_syms:
- upper_bound = sym.get_upper_bound()
-
- # See corresponding comment for allnoconfig implementation
- if upper_bound is not None and \
- kconfiglib.tri_less(sym.get_value(), upper_bound):
- sym.set_user_value(upper_bound)
- done = False
+ # See allnoconfig example. [-1] gives the last (highest) assignable
+ # value.
+ if sym.assignable and tri_less(sym.value, sym.assignable[-1]):
+ sym.set_value(sym.assignable[-1])
+ no_changes = False
- # Handle symbols within choices
+ # Handle choices
- for choice in conf.get_choices():
+ for choice in choices:
+ # Handle a choice whose visibility allows it to be in "y" mode
- # Handle choices whose visibility allow them to be in "y" mode
+ if choice.visibility == "y":
+ selection = choice.default_selection
- if choice.get_visibility() == "y":
- selection = choice.get_selection_from_defaults()
+ # Does the choice have a default selection that we haven't already
+ # selected?
if selection is not None and \
- selection is not choice.get_user_selection():
- selection.set_user_value("y")
- done = False
+ selection is not choice.user_value:
- # Handle choices whose visibility only allow them to be in "m" mode.
+ # Yup, select it
+ selection.set_value("y")
+ no_changes = False
+
+ # Handle a choice whose visibility only allows it to be in "m" mode.
# This might happen if a choice depends on a symbol that can only be
- # "m" for example.
-
- elif choice.get_visibility() == "m":
- for sym in choice.get_symbols():
- if sym.get_value() != "m" and \
- sym.get_upper_bound() != "n":
- sym.set_user_value("m")
- done = False
+ # "m", for example.
+
+ elif choice.visibility == "m":
+ for sym in choice.symbols:
+
+ # Does the choice have a symbol that can be "m" that we haven't
+ # already set to "m"?
+ if sym.user_value != "m" and "m" in sym.assignable:
+
+ # Yup, set it
+ sym.set_value("m")
+ no_changes = False
+
+ if no_changes:
+ break
conf.write_config(".config")