diff options
| -rw-r--r-- | kconfiglib.py | 54 |
1 files changed, 52 insertions, 2 deletions
diff --git a/kconfiglib.py b/kconfiglib.py index cd1c7bd..06b0f24 100644 --- a/kconfiglib.py +++ b/kconfiglib.py @@ -528,6 +528,7 @@ import os import re import sys + # File layout: # # Public classes @@ -537,10 +538,12 @@ import sys # Line length: 79 columns + # # Public classes # + class Kconfig(object): """ Represents a Kconfig configuration, e.g. for x86 or ARM. This is the set of @@ -3656,6 +3659,7 @@ class Kconfig(object): if self._warn_for_redun_assign: self._warn(msg, filename, linenr) + class Symbol(object): """ Represents a configuration symbol: @@ -4591,6 +4595,7 @@ class Symbol(object): self.kconfig._warn(msg) + class Choice(object): """ Represents a choice statement: @@ -5036,6 +5041,7 @@ class Choice(object): if item._cached_vis is not None: item._rec_invalidate() + class MenuNode(object): """ Represents a menu node in the configuration. This corresponds to an entry @@ -5386,6 +5392,7 @@ class MenuNode(object): return "\n".join(lines) + class Variable(object): """ Represents a preprocessor variable/function. @@ -5440,14 +5447,17 @@ class Variable(object): "recursive" if self.is_recursive else "immediate", self.value) + class KconfigError(Exception): "Exception raised for Kconfig-related errors" KconfigSyntaxError = KconfigError # Backwards compatibility + class InternalError(Exception): "Never raised. Kept around for backwards compatibility." + # Workaround: # # If 'errno' and 'strerror' are set on IOError, then __str__() always returns @@ -5463,10 +5473,12 @@ class _KconfigIOError(IOError): def __str__(self): return self.msg + # # Public functions # + def expr_value(expr): """ Evaluates the expression 'expr' to a tristate value. Returns 0 (n), 1 (m), @@ -5523,6 +5535,7 @@ def expr_value(expr): if rel is GREATER: return 2*(comp > 0) return 2*(comp >= 0) # rel is GREATER_EQUAL + def standard_sc_expr_str(sc): """ Standard symbol/choice printing function. Uses plain Kconfig syntax, and @@ -5536,6 +5549,7 @@ def standard_sc_expr_str(sc): # Choice return "<choice {}>".format(sc.name) if sc.name else "<choice>" + def expr_str(expr, sc_expr_str_fn=standard_sc_expr_str): """ Returns the string representation of the expression 'expr', as in a Kconfig @@ -5579,6 +5593,7 @@ def expr_str(expr, sc_expr_str_fn=standard_sc_expr_str): return "{} {} {}".format(sc_expr_str_fn(expr[1]), _REL_TO_STR[expr[0]], sc_expr_str_fn(expr[2])) + def expr_items(expr): """ Returns a set() of all items (symbols and choices) that appear in the @@ -5604,6 +5619,7 @@ def expr_items(expr): rec(expr) return res + def split_expr(expr, op): """ Returns a list containing the top-level AND or OR operands in the @@ -5648,6 +5664,7 @@ def split_expr(expr, op): rec(expr) return res + def escape(s): r""" Escapes the string 's' in the same fashion as is done for display in @@ -5657,8 +5674,6 @@ def escape(s): # \ must be escaped before " to avoid double escaping return s.replace("\\", r"\\").replace('"', r'\"') -# unescape() helper -_unescape_sub = re.compile(r"\\(.)").sub def unescape(s): r""" @@ -5667,6 +5682,10 @@ def unescape(s): """ return _unescape_sub(r"\1", s) +# unescape() helper +_unescape_sub = re.compile(r"\\(.)").sub + + def standard_kconfig(): """ Helper for tools. Loads the top-level Kconfig specified as the first @@ -5687,6 +5706,7 @@ def standard_kconfig(): # formatting when reported as an unhandled exception. Strip them here. sys.exit(str(e).strip()) + def standard_config_filename(): """ Helper for tools. Returns the value of KCONFIG_CONFIG (which specifies the @@ -5697,6 +5717,7 @@ def standard_config_filename(): """ return os.environ.get("KCONFIG_CONFIG", ".config") + def load_allconfig(kconf, filename): """ Helper for all*config. Loads (merges) the configuration file specified by @@ -5752,10 +5773,12 @@ def load_allconfig(kconf, filename): kconf.enable_override_warnings() kconf.enable_redun_warnings() + # # Internal functions # + def _visibility(sc): # Symbols and Choices have a "visibility" that acts as an upper bound on # the values a user can set for them, corresponding to the visibility in @@ -5785,6 +5808,7 @@ def _visibility(sc): return vis + def _make_depend_on(sc, expr): # Adds 'sc' (symbol or choice) as a "dependee" to all symbols in 'expr'. # Constant symbols in 'expr' are skipped as they can never change value @@ -5803,6 +5827,7 @@ def _make_depend_on(sc, expr): # Non-constant symbol, or choice expr._dependents.add(sc) + def _parenthesize(expr, type_, sc_expr_str_fn): # expr_str() helper. Adds parentheses around expressions of type 'type_'. @@ -5810,6 +5835,7 @@ def _parenthesize(expr, type_, sc_expr_str_fn): return "({})".format(expr_str(expr, sc_expr_str_fn)) return expr_str(expr, sc_expr_str_fn) + def _ordered_unique(lst): # Returns 'lst' with any duplicates removed, preserving order. This hacky # version seems to be a common idiom. It relies on short-circuit evaluation @@ -5819,6 +5845,7 @@ def _ordered_unique(lst): seen_add = seen.add return [x for x in lst if x not in seen and not seen_add(x)] + def _is_base_n(s, n): try: int(s, n) @@ -5826,11 +5853,13 @@ def _is_base_n(s, n): except ValueError: return False + def _strcmp(s1, s2): # strcmp()-alike that returns -1, 0, or 1 return (s1 > s2) - (s1 < s2) + def _sym_to_num(sym): # expr_value() helper for converting a symbol to a number. Raises # ValueError for symbols that can't be converted. @@ -5841,6 +5870,7 @@ def _sym_to_num(sym): return sym.tri_value if sym.orig_type in _BOOL_TRISTATE else \ int(sym.str_value, _TYPE_TO_BASE[sym.orig_type]) + def _touch_dep_file(sym_name): # If sym_name is MY_SYM_NAME, touches my/sym/name.h. See the sync_deps() # docstring. @@ -5854,6 +5884,7 @@ def _touch_dep_file(sym_name): os.close(os.open( sym_path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o644)) + def _save_old(path): # See write_config() @@ -5880,6 +5911,7 @@ def _save_old(path): # over e.g. if .<filename>.old happens to be a directory. pass + def _decoding_error(e, filename, macro_linenr=None): # Gives the filename and context for UnicodeDecodeError's, which are a pain # to debug otherwise. 'e' is the UnicodeDecodeError object. @@ -5901,6 +5933,7 @@ def _decoding_error(e, filename, macro_linenr=None): e.object[e.start:e.end], e.reason)) + def _name_and_loc(sc): # Helper for giving the symbol/choice name and location(s) in e.g. warnings @@ -5919,6 +5952,7 @@ def _name_and_loc(sc): # Menu manipulation + def _expr_depends_on(expr, sym): # Reimplementation of expr_depends_symbol() from mconf.c. Used to determine # if a submenu should be implicitly created. This also influences which @@ -5946,6 +5980,7 @@ def _expr_depends_on(expr, sym): (_expr_depends_on(expr[1], sym) or _expr_depends_on(expr[2], sym)) + def _auto_menu_dep(node1, node2): # Returns True if node2 has an "automatic menu dependency" on node1. If # node2 has a prompt, we check its condition. Otherwise, we look directly @@ -5955,6 +5990,7 @@ def _auto_menu_dep(node1, node2): return _expr_depends_on(node2.prompt[1] if node2.prompt else node2.dep, node1.item) + def _flatten(node): # "Flattens" menu nodes without prompts (e.g. 'if' nodes and non-visible # symbols with children from automatic menu creation) so that their @@ -5983,6 +6019,7 @@ def _flatten(node): node = node.next + def _remove_ifs(node): # Removes 'if' nodes (which can be recognized by MenuNode.item being None), # which are assumed to already have been flattened. The C implementation @@ -6008,6 +6045,7 @@ def _remove_ifs(node): # due to tricky Python semantics. The order matters. cur.next = cur = next + def _finalize_choice(node): # Finalizes a choice, marking each symbol whose menu node has the choice as # the parent as a choice symbol, and automatically determining types if not @@ -6035,6 +6073,7 @@ def _finalize_choice(node): if not sym.orig_type: sym.orig_type = choice.orig_type + def _check_dep_loop_sym(sym, ignore_choice): # Detects dependency loops using depth-first search on the dependency graph # (which is calculated earlier in Kconfig._build_dep()). @@ -6109,6 +6148,7 @@ def _check_dep_loop_sym(sym, ignore_choice): # first element in it. return (sym,) + def _check_dep_loop_choice(choice, skip): if not choice._visited: # choice._visited == 0, unvisited @@ -6142,6 +6182,7 @@ def _check_dep_loop_choice(choice, skip): # first element in it. return (choice,) + def _found_dep_loop(loop, cur): # Called "on the way back" when we know we have a loop @@ -6193,23 +6234,28 @@ def _found_dep_loop(loop, cur): # Predefined preprocessor functions + def _filename_fn(kconf, _): return kconf._filename + def _lineno_fn(kconf, _): return str(kconf._linenr) + def _info_fn(kconf, _, msg): print("{}:{}: {}".format(kconf._filename, kconf._linenr, msg)) return "" + def _warning_if_fn(kconf, _, cond, msg): if cond == "y": kconf._warn(msg, kconf._filename, kconf._linenr) return "" + def _error_if_fn(kconf, _, cond, msg): if cond == "y": raise KconfigError("{}:{}: {}".format( @@ -6217,6 +6263,7 @@ def _error_if_fn(kconf, _, cond, msg): return "" + def _shell_fn(kconf, _, command): # Only import as needed, to save some startup time import subprocess @@ -6557,12 +6604,15 @@ _RELATIONS = frozenset(( # # Use ASCII regex matching on Python 3. It's already the default on Python 2. + def _re_match(regex): return re.compile(regex, 0 if _IS_PY2 else re.ASCII).match + def _re_search(regex): return re.compile(regex, 0 if _IS_PY2 else re.ASCII).search + # Various regular expressions used during parsing # The initial token on a line. Also eats leading and trailing whitespace, so |
