From 81a0b2ede3f59784d271a60701291e2a0dfc2a7d Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Sun, 27 May 2018 19:18:40 +0200 Subject: oldconfig: Move from examples/ to root All the packaged code will appear in the root. --- examples/oldconfig.py | 344 -------------------------------------------------- 1 file changed, 344 deletions(-) delete mode 100755 examples/oldconfig.py (limited to 'examples') diff --git a/examples/oldconfig.py b/examples/oldconfig.py deleted file mode 100755 index 1b58831..0000000 --- a/examples/oldconfig.py +++ /dev/null @@ -1,344 +0,0 @@ -#!/usr/bin/env python - -# Implements oldconfig-like functionality: -# -# 1. Load existing .config -# 2. Prompt the user for the value of all changeable symbols/choices -# that aren't already set in the .config -# 3. Write new .config -# -# Unlike 'make oldconfig', this script doesn't print menu titles and -# comments, but instead gives the Kconfig locations of all symbols and -# choices. Printing menu titles and comments as well would be pretty easy to -# add (look at the parents of each item and print all menu prompts and -# comments unless they have already been printed). -# -# Inputting '?' on the prompt will display the help text of the item, if any. -# Hopefully no one will want to use that as a value. -# -# Sample session: -# -# OldconfigExample contents: -# -# config MODULES -# def_bool y -# option modules -# -# config BOOL_SYM -# bool "BOOL_SYM prompt" -# default y -# -# config TRISTATE_SYM -# tristate "TRISTATE_SYM prompt" -# default m -# -# config STRING_SYM -# string "STRING_SYM prompt" -# default "foo" -# -# config INT_SYM -# int "INT_SYM prompt" -# -# config HEX_SYM -# hex "HEX_SYM prompt" -# -# choice -# bool "A choice that defaults to CHOICE_B" -# default CHOICE_B -# -# config CHOICE_A -# bool "CHOICE_A's prompt" -# -# config CHOICE_B -# bool "CHOICE_B's prompt" -# -# config CHOICE_C -# bool "CHOICE_C's prompt" -# -# endchoice -# -# -# Running: -# -# $ touch .config # Run with empty .config -# -# $ python(3) oldconfig.py Kconfig -# BOOL_SYM prompt (BOOL_SYM, defined at Kconfig:5) [n/Y] foo -# Invalid tristate value -# BOOL_SYM prompt (BOOL_SYM, defined at Kconfig:5) [n/Y] n -# TRISTATE_SYM prompt (TRISTATE_SYM, defined at Kconfig:9) [n/M/y] -# STRING_SYM prompt (STRING_SYM, defined at Kconfig:13) [foo] bar -# INT_SYM prompt (INT_SYM, defined at Kconfig:17) [] 0x123 -# warning: the value '0x123' is invalid for INT_SYM (defined at Kconfig:17), which has type int. Assignment ignored. -# INT_SYM prompt (INT_SYM, defined at Kconfig:17) [] 123 -# HEX_SYM prompt (HEX_SYM, defined at Kconfig:20) [] 0x123 -# A choice that default to B (defined at Kconfig:23) -# 1. CHOICE_A's prompt (CHOICE_A) -# > 2. CHOICE_B's prompt (CHOICE_B) -# 3. CHOICE_C's prompt (CHOICE_C) -# choice[1-3]: 5 -# Bad index -# A choice that default to B (defined at Kconfig:23) -# 1. CHOICE_A's prompt (CHOICE_A) -# > 2. CHOICE_B's prompt (CHOICE_B) -# 3. CHOICE_C's prompt (CHOICE_C) -# choice[1-3]: 3 -# Configuration written to .config -# -# $ cat .config -# # Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) -# CONFIG_MODULES=y -# # CONFIG_BOOL_SYM is not set -# CONFIG_TRISTATE_SYM=m -# CONFIG_STRING_SYM="bar" -# CONFIG_INT_SYM=123 -# CONFIG_HEX_SYM=0x123 -# # CONFIG_CHOICE_A is not set -# # CONFIG_CHOICE_B is not set -# CONFIG_CHOICE_C=y -# -# $ python oldconfig.py Kconfig # Everything's already up to date -# Configuration written to .config -from __future__ import print_function -from kconfiglib import Kconfig, Symbol, Choice, BOOL, TRISTATE, HEX -import os -import sys - -# Python 2/3 compatibility hack -if sys.version_info[0] < 3: - input = raw_input - -def eprint(*args): - print(*args, file=sys.stderr) - -def print_help(node): - if node.help is not None: - print("\n" + node.help) - else: - print("\nNo help text\n") - -def name_and_loc_str(sym): - """ - Helper for printing the symbol name along with the location(s) in the - Kconfig files where the symbol is defined - """ - return "{}, defined at {}".format( - sym.name, - ", ".join("{}:{}".format(node.filename, node.linenr) - for node in sym.nodes)) - -def default_value_str(sym): - """ - Returns the "m/M/y" string in e.g. - - TRISTATE_SYM prompt (TRISTATE_SYM, defined at Kconfig:9) [n/M/y]: - - For string/int/hex, returns the default value as-is. - """ - if sym.type in (BOOL, TRISTATE): - return "/".join(("nmy" if sym.tri_value != tri else "NMY")[tri] - for tri in sym.assignable) - - # string/int/hex - return sym.str_value - -def do_oldconfig_for_node(node): - """ - Prompts the user for a value for the menu node item, where applicable in - oldconfig mode - """ - # See do_oldconfig() - global conf_changed - - # Only symbols and choices can be configured - if not isinstance(node.item, (Symbol, Choice)): - return - - # Skip symbols and choices that aren't visible - if not node.item.visibility: - return - - # Skip symbols and choices that don't have a prompt (at this location) - if not node.prompt: - return - - if isinstance(node.item, Symbol): - sym = node.item - - # Skip symbols that already have a user value - if sym.user_value is not None: - return - - # Skip symbols that can only have a single value, due to selects - if len(sym.assignable) == 1: - return - - # Skip symbols in choices in y mode. We ask once for the entire choice - # instead. - if sym.choice and sym.choice.tri_value == 2: - return - - # Loop until the user enters a valid value or enters a blank string - # (for the default value) - while True: - val = input("{} ({}) [{}] ".format( - node.prompt[0], name_and_loc_str(sym), - default_value_str(sym))) - - if val == "?": - print_help(node) - continue - - # Substitute a blank string with the default value the symbol - # would get - if not val: - val = sym.str_value - - # Automatically add a "0x" prefix for hex symbols, like the - # menuconfig interface does. This isn't done when loading .config - # files, hence why set_value() doesn't do it automatically. - if sym.type == HEX and not val.startswith(("0x", "0X")): - val = "0x" + val - - old_str_val = sym.str_value - - # Kconfiglib itself will print a warning here if the value - # is invalid, so we don't need to bother - if sym.set_value(val): - # Valid value input. We're done with this node. - - if sym.str_value != old_str_val: - conf_changed = True - - return - - else: - choice = node.item - - # Skip choices that already have a visible user selection... - if choice.user_selection and choice.user_selection.visibility == 2: - # ...unless there are new visible symbols in the choice. (We know - # they have y (2) visibility in that case, because m-visible - # symbols get demoted to n-visibility in y-mode choices, and the - # user-selected symbol had visibility y.) - for sym in choice.syms: - if sym is not choice.user_selection and sym.visibility and \ - sym.user_value is None: - # New visible symbols in the choice - break - else: - # No new visible symbols in the choice - return - - # Get a list of available selections. The mode of the choice limits - # the visibility of the choice value symbols, so this will indirectly - # skip choices in n and m mode. - options = [sym for sym in choice.syms if sym.visibility == 2] - - if not options: - # No y-visible choice value symbols - return - - # Loop until the user enters a valid selection or a blank string (for - # the default selection) - while True: - print("{} (defined at {}:{})".format( - node.prompt[0], node.filename, node.linenr)) - - for i, sym in enumerate(options, 1): - print("{} {}. {} ({})".format( - ">" if sym is choice.selection else " ", - i, - # Assume people don't define choice symbols with multiple - # prompts. That generates a warning anyway. - sym.nodes[0].prompt[0], - sym.name)) - - sel_index = input("choice[1-{}]: ".format(len(options))) - - if sel_index == "??": - print_help(node) - continue - - # Pick the default selection if the string is blank - if not sel_index: - choice.selection.set_value(2) - break - - try: - sel_index = int(sel_index) - except ValueError: - eprint("Bad index") - continue - - if not 1 <= sel_index <= len(options): - eprint("Bad index") - continue - - # Valid selection - - if options[sel_index - 1].tri_value != 2: - conf_changed = True - - options[sel_index - 1].set_value(2) - break - - # Give all of the non-selected visible choice symbols the user value n. - # This makes it so that the choice is no longer considered new once we - # do additional passes, if the reason that it was considered new was - # that it had new visible choice symbols. - # - # Only giving visible choice symbols the user value n means we will - # prompt for the choice again if later user selections make more new - # choice symbols visible, which is correct. - for sym in choice.syms: - if sym is not choice.user_selection and sym.visibility: - sym.set_value(0) - -# Entry point when run as an executable, split out so that setuptools' -# 'entry_points' can be used. It produces a handy oldconfig.exe launcher on -# Windows. -def main(): - if len(sys.argv) > 2: - sys.exit("usage: {} [Kconfig]".format(sys.argv[0])) - - kconf = Kconfig("Kconfig" if len(sys.argv) < 2 else sys.argv[1]) - - config_filename = os.environ.get("KCONFIG_CONFIG") - if config_filename is None: - config_filename = ".config" - - if not os.path.exists(config_filename): - sys.exit("{}: '{}' does not exist" - .format(sys.argv[0], config_filename)) - - kconf.load_config(config_filename) - do_oldconfig(kconf) - kconf.write_config(config_filename) - - print("Configuration saved to '{}'".format(config_filename)) - -def do_oldconfig(kconf): - # An earlier symbol in the Kconfig files might depend on a later symbol and - # become visible if its value changes. This flag is set to True if the - # value of any symbol changes, in which case we rerun the oldconfig to - # check for new visible symbols. - global conf_changed - - while True: - conf_changed = False - do_oldconfig_rec(kconf.top_node) - if not conf_changed: - break - -def do_oldconfig_rec(node): - while node: - do_oldconfig_for_node(node) - - if node.list: - do_oldconfig_rec(node.list) - - node = node.next - -if __name__ == "__main__": - main() -- cgit v1.2.3