summaryrefslogtreecommitdiff
path: root/examples
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
parentf64aaf971176305233f16a11911a660fa6f99561 (diff)
Kconfiglib 2 backup
WIP
Diffstat (limited to 'examples')
-rw-r--r--examples/allnoconfig.py87
-rw-r--r--examples/allnoconfig_simpler.py47
-rw-r--r--examples/allyesconfig.py133
-rw-r--r--examples/defconfig.py13
-rw-r--r--examples/defconfig_oldconfig.py12
-rw-r--r--examples/eval_expr.py20
-rw-r--r--examples/help_grep.py109
-rw-r--r--examples/print_refs.py13
-rw-r--r--examples/print_sym_info.py56
-rw-r--r--examples/print_tree.py80
-rw-r--r--examples/print_undefined.py15
11 files changed, 376 insertions, 209 deletions
diff --git a/examples/allnoconfig.py b/examples/allnoconfig.py
index 9423352..edc473d 100644
--- a/examples/allnoconfig.py
+++ b/examples/allnoconfig.py
@@ -1,40 +1,57 @@
-# Works like allnoconfig. Automatically verified by the testsuite to generate
-# identical output to 'make allnoconfig' for all ARCHes. The looping is done in
-# case setting one symbol to "n" allows other symbols to be set to "n" (due to
-# dependencies).
+# Works like 'make allnoconfig'. Verified by the test suite to generate
+# identical output to 'make allnoconfig' for all ARCHes.
+#
+# See allnoconfig_simpler.py for a much simpler version. This version
+# demonstrates some tree walking and value processing.
+#
+# Usage:
+#
+# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/allnoconfig.py
-import kconfiglib
+from kconfiglib import Config, Symbol, tri_less
import sys
-conf = kconfiglib.Config(sys.argv[1])
-
-# Do an initial pass to give allnoconfig_y symbols the user value 'y'. It might
-# be possible to handle this through "successive raising" similarly to the
-# "successive lowering" below too, but keep it simple.
-for sym in conf:
- if sym.get_type() in (kconfiglib.BOOL, kconfiglib.TRISTATE) and \
- sym.is_allnoconfig_y():
- sym.set_user_value('y')
-
-done = False
-while not done:
- done = True
-
- for sym in conf:
- # Choices take care of themselves for allnoconfig, so we only need to
- # worry about non-choice symbols
- if not sym.is_choice_symbol() and not sym.is_allnoconfig_y():
- # If we can assign a value to the symbol (where "n", "m" and "y"
- # are ordered from lowest to highest), then assign the lowest
- # value. lower_bound() returns None for symbols whose values cannot
- # (currently) be changed, as well as for non-bool/tristate symbols.
- lower_bound = sym.get_lower_bound()
- if lower_bound is not None and \
- kconfiglib.tri_less(lower_bound, sym.get_value()):
-
- sym.set_user_value(lower_bound)
- # We just changed the value of some symbol. As this may affect
- # other symbols, keep going.
- done = False
+def do_allnoconfig(node):
+ global no_changes
+
+ # Walk the tree of menu nodes. You can imagine this as going down/into menu
+ # entries in the menuconfig interface, setting each to 'n' (or the lowest
+ # assignable value).
+
+ while node is not None:
+ if isinstance(node.item, Symbol):
+ sym = node.item
+
+ # Is the symbol a non-choice symbol that can be set to a lower
+ # value than its current value?
+ if sym.choice is None and sym.assignable and \
+ tri_less(sym.assignable[0], sym.value):
+
+ # Yup, lower it
+ sym.set_value(sym.assignable[0])
+ no_changes = False
+
+ # Recursively lower children
+ if node.list is not None:
+ do_allnoconfig(node.list)
+
+ node = node.next
+
+conf = Config(sys.argv[1])
+
+while 1:
+ # For tricky dependencies involving '!', setting later symbols to 'n' might
+ # actually raise the value of earlier symbols. To be super safe, we do
+ # additional passes until a pass no longer changes the value of any symbol.
+ #
+ # This isn't actually needed for any ARCH in the kernel as of 4.14. A
+ # single pass gives the correct result.
+ no_changes = True
+
+ do_allnoconfig(conf.top_menu)
+
+ # Did the pass change any symbols?
+ if no_changes:
+ break
conf.write_config(".config")
diff --git a/examples/allnoconfig_simpler.py b/examples/allnoconfig_simpler.py
index f3cfe9a..e732669 100644
--- a/examples/allnoconfig_simpler.py
+++ b/examples/allnoconfig_simpler.py
@@ -1,28 +1,35 @@
# This is a simpler version of allnoconfig.py, corresponding to how the C
-# implementation does it. Setting a user value that's not in the assignable
-# range of the symbol (between get_lower_bound() and get_upper_bound(), or,
-# equivalently, not in get_assignable_values()) is OK; the value will simply
-# get truncated downwards or upwards as determined by the visibility and
-# selects.
+# implementation does it. Verified by the test suite to produce identical
+# output to 'make allnoconfig' for all ARCHes.
+#
+# Usage:
+#
+# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/allnoconfig_simpler.py
+#
+# Implementation/performance note
+# ===============================
+#
+# Kconfiglib immediately invalidates (flags for recalculation) all (possibly)
+# dependent symbols when a value is assigned to a symbol, which slows this down
+# a bit (due to tons of redundant invalidation), but makes any assignment
+# pattern safe ("just works"). Config.load_config() instead invalidates all
+# symbols up front, making it much faster. If you really need to eke out
+# performance, look at how load_config() does things (which involves internal
+# APIs that don't invalidate symbols). This has been fast enough for all cases
+# I've seen so far though (around 3 seconds for this particular script on my
+# Core i7 2600K, including the initial Kconfig parsing).
-# This version is a bit slower compared allnoconfig.py since Kconfiglib
-# invalidates all dependent symbols for each set_user_value() call. This does not
-# happen for load_config(), which instead invalidates all symbols once after
-# the configuration has been loaded. This is OK for load_config() since nearly
-# all symbols will tend to be affected anyway.
-
-import kconfiglib
+from kconfiglib import Config, BOOL, TRISTATE
import sys
-conf = kconfiglib.Config(sys.argv[1])
+conf = Config(sys.argv[1])
-# Avoid warnings printed by Kconfiglib when assigning a user value with
-# set_user_value() to a symbol that has no prompt (such assignments never have
-# an effect)
-conf.set_print_warnings(False)
+# Avoid warnings printed by Kconfiglib when assigning a value to a symbol that
+# has no prompt. Such assignments never have an effect.
+conf.disable_warnings()
-for sym in conf:
- if sym.get_type() in (kconfiglib.BOOL, kconfiglib.TRISTATE):
- sym.set_user_value("y" if sym.is_allnoconfig_y() else "n")
+for sym in conf.defined_syms:
+ if sym.type in (BOOL, TRISTATE):
+ sym.set_value("y" if sym.is_allnoconfig_y else "n")
conf.write_config(".config")
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")
diff --git a/examples/defconfig.py b/examples/defconfig.py
index 3e958e2..ce2bf6e 100644
--- a/examples/defconfig.py
+++ b/examples/defconfig.py
@@ -1,4 +1,8 @@
# Works like entering "make menuconfig" and immediately saving and exiting
+#
+# Usage:
+#
+# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/allyesconfig.py
import kconfiglib
import os
@@ -7,11 +11,12 @@ import sys
conf = kconfiglib.Config(sys.argv[1])
if os.path.exists(".config"):
+ print("using existing .config")
conf.load_config(".config")
else:
- defconfig = conf.get_defconfig_filename()
- if defconfig is not None:
- print("Using" + defconfig)
- conf.load_config(defconfig)
+ if conf.defconfig_filename is not None:
+ print("using " + conf.defconfig_filename)
+ conf.load_config(conf.defconfig_filename)
conf.write_config(".config")
+print("configuration written to .config")
diff --git a/examples/defconfig_oldconfig.py b/examples/defconfig_oldconfig.py
index 9a85440..98173e7 100644
--- a/examples/defconfig_oldconfig.py
+++ b/examples/defconfig_oldconfig.py
@@ -7,6 +7,10 @@
# yes n | make oldconfig
#
# This came up in https://github.com/ulfalizer/Kconfiglib/issues/15.
+#
+# Usage:
+#
+# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/defconfig_oldconfig.py
import kconfiglib
import sys
@@ -19,15 +23,15 @@ conf.write_config(".config")
# Mirrors the first oldconfig
conf.load_config(".config")
-conf["ETHERNET"].set_user_value('n')
+conf.syms["ETHERNET"].set_value('n')
conf.write_config(".config")
# Mirrors the second oldconfig
conf.load_config(".config")
-conf["ETHERNET"].set_user_value('y')
+conf.syms["ETHERNET"].set_value('y')
for s in conf:
- if s.get_user_value() is None and 'n' in s.get_assignable_values():
- s.set_user_value('n')
+ if s.user_value is None and 'n' in s.assignable:
+ s.set_value('n')
# Write the final configuration
conf.write_config(".config")
diff --git a/examples/eval_expr.py b/examples/eval_expr.py
index edb33e6..a907f35 100644
--- a/examples/eval_expr.py
+++ b/examples/eval_expr.py
@@ -1,8 +1,22 @@
-# Evaluates an expression in the context of a configuration. (Here we could
-# load a .config as well.)
+# Evaluates an expression (e.g. "X86_64 || (X86_32 && X86_LOCAL_APIC)") in the
+# context of a configuration. Note that this always yields a tristate value (n,
+# m, or y).
+#
+# Usage:
+#
+# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/eval_expr.py SCRIPT_ARG=<expr>
import kconfiglib
import sys
+if len(sys.argv) < 3:
+ print('Pass symbol name (without "CONFIG_" prefix) with SCRIPT_ARG=NAME')
+ sys.exit(1)
+
conf = kconfiglib.Config(sys.argv[1])
-print(conf.eval("(TRACE_IRQFLAGS_SUPPORT || PPC32) && STACKTRACE_SUPPORT"))
+
+# Enable modules so that 'm' doesn't get demoted to 'n'
+conf.syms["MODULES"].set_value("y")
+
+print("the expression '{}' evaluates to {}"
+ .format(sys.argv[2], conf.eval_string(sys.argv[2])))
diff --git a/examples/help_grep.py b/examples/help_grep.py
index 61ac936..fed1731 100644
--- a/examples/help_grep.py
+++ b/examples/help_grep.py
@@ -1,49 +1,72 @@
-# Does a case-insensitive search for a string in the help texts for symbols and
-# choices and the titles of menus and comments. Prints the matching items
-# together with their locations and the matching text. Used like
+# Does a case-insensitive search for a regular expression in the help texts of
+# symbols and choices and the prompts of menus and comments. Prints the
+# matching items together with their locations and the matching text.
#
-# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/help_grep.py SCRIPT_ARG=<search text>
+# Usage:
+#
+# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/help_grep.py SCRIPT_ARG=<regex>
+#
+# Shortened example output for SCRIPT_ARG=general:
+#
+# menu "General setup"
+# location: init/Kconfig:39
+#
+# config SYSVIPC
+# bool
+# prompt "System V IPC"
+# help
+# ...
+# exchange information. It is generally considered to be a good thing,
+# ...
+#
+# location: init/Kconfig:233
+#
+# config BSD_PROCESS_ACCT
+# bool
+# prompt "BSD Process Accounting" if MULTIUSER
+# help
+# ...
+# information. This is generally a good idea, so say Y.
+#
+# location: init/Kconfig:403
+#
+# ...
+
-import kconfiglib
+from kconfiglib import Config, Symbol, Choice, MENU, COMMENT
+import re
import sys
if len(sys.argv) < 3:
- print('Pass search string with SCRIPT_ARG="search string"')
+ print('Pass the regex with SCRIPT_ARG=regex')
sys.exit(1)
-search_string = sys.argv[2].lower()
-
-conf = kconfiglib.Config(sys.argv[1])
-
-for item in conf.get_symbols() + \
- conf.get_choices() + conf.get_menus() + conf.get_comments():
- if item.is_symbol() or item.is_choice():
- text = item.get_help()
- elif item.is_menu():
- text = item.get_title()
- else:
- # Comment
- text = item.get_text()
-
- # Case-insensitive search
- if text is not None and search_string in text.lower():
- if item.is_symbol() or item.is_choice():
- # Indent lines in help text. (There might be a nicer way. :)
- text = "\n".join([" " + s for s in text.splitlines()])
-
- # Don't worry about symbols/choices defined in multiple locations to
- # keep things simple
- fname, linenr = item.get_def_locations()[0]
- if item.is_symbol():
- print("config {0} at {1}:{2}:\n{3}"
- .format(item.get_name(), fname, linenr, text))
- elif item.is_choice():
- print("choice at {0}:{1}:\n{2}".format(fname, linenr, text))
-
- else:
- # Menu or comment
- fname, linenr = item.get_location()
- if item.is_menu():
- print('menu "{0}" at {1}:{2}'.format(text, fname, linenr))
- else:
- # Comment
- print('comment "{0}" at {1}:{2}'.format(text, fname, linenr))
+
+search = re.compile(sys.argv[2], re.IGNORECASE).search
+
+def search_tree(node):
+ while node is not None:
+ match = False
+
+ if isinstance(node.item, (Symbol, Choice)) and \
+ node.help is not None and search(node.help):
+ print(node.item)
+ match = True
+
+ elif node.item == MENU and search(node.prompt[0]):
+ print('menu "{}"'.format(node.prompt[0]))
+ match = True
+
+ elif node.item == COMMENT and search(node.prompt[0]):
+ print('comment "{}"'.format(node.prompt[0]))
+ match = True
+
+ if match:
+ print("location: {}:{}\n".format(node.filename, node.linenr))
+
+ if node.list is not None:
+ search_tree(node.list)
+
+ node = node.next
+
+conf = Config(sys.argv[1])
+search_tree(conf.top_menu)
diff --git a/examples/print_refs.py b/examples/print_refs.py
deleted file mode 100644
index ea62223..0000000
--- a/examples/print_refs.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Prints the names of all symbols that reference a particular symbol. (There's
-# also a method get_selected_symbols() for determining just selection
-# relations.)
-
-import kconfiglib
-import sys
-
-conf = kconfiglib.Config(sys.argv[1])
-
-x86 = conf["X86"]
-for sym in conf:
- if x86 in sym.get_referenced_symbols():
- print(sym.get_name())
diff --git a/examples/print_sym_info.py b/examples/print_sym_info.py
index c913358..2c1b0f0 100644
--- a/examples/print_sym_info.py
+++ b/examples/print_sym_info.py
@@ -1,18 +1,52 @@
-# Loads a Kconfig and a .config and prints information about a symbol.
+# Loads a Kconfig and a .config and prints a symbol.
+#
+# Usage:
+#
+# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/print_sym_info.py SCRIPT_ARG=<name>
+#
+# Example output for SCRIPT_ARG=modules:
+#
+# config MODULES
+# bool
+# prompt "Enable loadable module support"
+# option modules
+# help
+# Kernel modules are small pieces of compiled code which can
+# be inserted in the running kernel, rather than being
+# permanently built into the kernel. You use the "modprobe"
+# tool to add (and sometimes remove) them. If you say Y here,
+# many parts of the kernel can be built as modules (by
+# answering M instead of Y where indicated): this is most
+# useful for infrequently used options which are not required
+# for booting. For more information, see the man pages for
+# modprobe, lsmod, modinfo, insmod and rmmod.
+#
+# If you say Y here, you will need to run "make
+# modules_install" to put the modules under /lib/modules/
+# where modprobe can find them (you may need to be root to do
+# this).
+#
+# If unsure, say Y.
+#
+# value = n
+# visibility = y
+# currently assignable values: n, y
+# defined at init/Kconfig:1678
import kconfiglib
import sys
-# Create a Config object representing a Kconfig configuration. (Any number of
-# these can be created -- the library has no global state.)
+if len(sys.argv) < 3:
+ print('Pass symbol name (without "CONFIG_" prefix) with SCRIPT_ARG=<name>')
+ sys.exit(1)
+
conf = kconfiglib.Config(sys.argv[1])
+sym = conf.syms[sys.argv[2]]
-# Load values from a .config file. 'srctree' is an environment variable set by
-# the Linux makefiles to the top-level directory of the kernel tree. It needs
-# to be used here for the script to work with alternative build directories
-# (specified e.g. with O=).
-conf.load_config("$srctree/arch/x86/configs/i386_defconfig")
+print(sym)
+print("value = " + sym.value)
+print("visibility = " + sym.visibility)
+print("currently assignable values: " + ", ".join(sym.assignable))
-# Print some information about a symbol. (The Config class implements
-# __getitem__() to provide a handy syntax for getting symbols.)
-print(conf["SERIAL_UARTLITE_CONSOLE"])
+for node in sym.nodes:
+ print("defined at {}:{}".format(node.filename, node.linenr))
diff --git a/examples/print_tree.py b/examples/print_tree.py
index 1405ed5..da795c9 100644
--- a/examples/print_tree.py
+++ b/examples/print_tree.py
@@ -1,23 +1,67 @@
-# Prints a tree of all items in the configuration
+# Prints the menu tree of the configuration. Dependencies between symbols can
+# sometimes implicitly alter the menu structure (see kconfig-language.txt), and
+# that's implemented too.
+#
+# Usage:
+#
+# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
+#
+# Example output:
+#
+# ...
+# config HAVE_KERNEL_LZO
+# config HAVE_KERNEL_LZ4
+# choice
+# config KERNEL_GZIP
+# config KERNEL_BZIP2
+# config KERNEL_LZMA
+# config KERNEL_XZ
+# config KERNEL_LZO
+# config KERNEL_LZ4
+# config DEFAULT_HOSTNAME
+# config SWAP
+# config SYSVIPC
+# config SYSVIPC_SYSCTL
+# config POSIX_MQUEUE
+# config POSIX_MQUEUE_SYSCTL
+# config CROSS_MEMORY_ATTACH
+# config FHANDLE
+# config USELIB
+# config AUDIT
+# config HAVE_ARCH_AUDITSYSCALL
+# config AUDITSYSCALL
+# config AUDIT_WATCH
+# config AUDIT_TREE
+# menu "IRQ subsystem"
+# config MAY_HAVE_SPARSE_IRQ
+# config GENERIC_IRQ_LEGACY
+# config GENERIC_IRQ_PROBE
+# ...
-import kconfiglib
+from kconfiglib import Config, Symbol, Choice, MENU, COMMENT
import sys
-def print_with_indent(s, indent):
+def indent_print(s, indent):
print((" " * indent) + s)
-def print_items(items, indent):
- for item in items:
- if item.is_symbol():
- print_with_indent("config {0}".format(item.get_name()), indent)
- elif item.is_menu():
- print_with_indent('menu "{0}"'.format(item.get_title()), indent)
- print_items(item.get_items(), indent + 2)
- elif item.is_choice():
- print_with_indent('choice', indent)
- print_items(item.get_items(), indent + 2)
- elif item.is_comment():
- print_with_indent('comment "{0}"'.format(item.get_text()), indent)
-
-conf = kconfiglib.Config(sys.argv[1])
-print_items(conf.get_top_level_items(), 0)
+def print_items(node, indent):
+ while node is not None:
+ if isinstance(node.item, Symbol):
+ indent_print("config " + node.item.name, indent)
+
+ elif isinstance(node.item, Choice):
+ indent_print("choice", indent)
+
+ elif node.item == MENU:
+ indent_print('menu "{0}"'.format(node.prompt[0]), indent)
+
+ elif node.item == COMMENT:
+ indent_print('comment "{0}"'.format(node.prompt[0]), indent)
+
+ if node.list is not None:
+ print_items(node.list, indent + 2)
+
+ node = node.next
+
+conf = Config(sys.argv[1])
+print_items(conf.top_menu, 0)
diff --git a/examples/print_undefined.py b/examples/print_undefined.py
deleted file mode 100644
index fb8120b..0000000
--- a/examples/print_undefined.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Prints the names of all symbols that are referenced but never defined in the
-# current configuration together with the locations where they are referenced.
-# Integers being included in the list is not a bug, as these need to be treated
-# as symbols per the design of Kconfig.
-
-import kconfiglib
-import sys
-
-conf = kconfiglib.Config(sys.argv[1])
-
-for sym in conf.get_symbols():
- if not sym.is_defined():
- print(sym.get_name())
- for (filename, linenr) in sym.get_ref_locations():
- print(" {0}:{1}".format(filename, linenr))