summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Magnusson <ulfalizer@gmail.com>2015-06-08 16:13:26 +0200
committerUlf Magnusson <ulfalizer@gmail.com>2015-06-08 16:35:30 +0200
commit3cba566b908398b905f7e7229f4dc275db392cc0 (patch)
tree797306e37daa097e804e39a5dafbf433164217cc
parent707170188fe120c95b16806cbb52c39a4107f792 (diff)
Clean up global ordering.
kconfiglib.py is now arranged as follows: Public classes Public functions Internal classes Internal functions Internal global constants Bit arbitrary, but better than no ordering like before. :)
-rw-r--r--kconfiglib.py607
1 files changed, 309 insertions, 298 deletions
diff --git a/kconfiglib.py b/kconfiglib.py
index dc94da5..b421f87 100644
--- a/kconfiglib.py
+++ b/kconfiglib.py
@@ -70,6 +70,18 @@ import os
import re
import sys
+# File layout:
+#
+# Public classes (and the Symbol and Choice base class _HasVisibility)
+# Public functions
+# Internal classes
+# Internal functions
+# Internal global constants
+
+#
+# Public classes
+#
+
class Config(object):
"""Represents a Kconfig configuration, e.g. for i386 or ARM. This is the
@@ -1773,263 +1785,6 @@ class Config(object):
if self.print_warnings:
_stderr_msg("warning: " + msg, filename, linenr)
-#
-# Functions and constants related to types, expressions, parsing, evaluation
-# and printing
-#
-
-def _make_and(e1, e2):
- """Constructs an AND (&&) expression. Performs trivial simplification.
- Nones equate to 'y'.
-
- Note: returns None if e1 == e2 == None."""
- if e1 == "n" or e2 == "n":
- return "n"
- if e1 is None or e1 == "y":
- return e2
- if e2 is None or e2 == "y":
- return e1
-
- # Prefer to merge/update argument list if possible instead of creating
- # a new AND node
-
- if isinstance(e1, tuple) and e1[0] == AND:
- if isinstance(e2, tuple) and e2[0] == AND:
- return (AND, e1[1] + e2[1])
- return (AND, e1[1] + [e2])
-
- if isinstance(e2, tuple) and e2[0] == AND:
- return (AND, e2[1] + [e1])
-
- return (AND, [e1, e2])
-
-def _make_or(e1, e2):
- """Constructs an OR (||) expression. Performs trivial simplification and
- avoids Nones. Nones equate to 'y', which is usually what we want, but needs
- to be kept in mind."""
-
- # Perform trivial simplification and avoid None's (which
- # correspond to y's)
- if e1 is None or e2 is None or e1 == "y" or e2 == "y":
- return "y"
- if e1 == "n":
- return e2
- if e2 == "n":
- return e1
-
- # Prefer to merge/update argument list if possible instead of creating
- # a new OR node
-
- if isinstance(e1, tuple) and e1[0] == OR:
- if isinstance(e2, tuple) and e2[0] == OR:
- return (OR, e1[1] + e2[1])
- return (OR, e1[1] + [e2])
-
- if isinstance(e2, tuple) and e2[0] == OR:
- return (OR, e2[1] + [e1])
-
- return (OR, [e1, e2])
-
-def _get_expr_syms(expr):
- """Returns the set() of symbols appearing in expr."""
- res = set()
- if expr is None:
- return res
-
- def rec(expr):
- if isinstance(expr, Symbol):
- res.add(expr)
- return
- if isinstance(expr, str):
- return
-
- e0 = expr[0]
- if e0 == AND or e0 == OR:
- for term in expr[1]:
- rec(term)
- elif e0 == NOT:
- rec(expr[1])
- elif e0 == EQUAL or e0 == UNEQUAL:
- _, v1, v2 = expr
- if isinstance(v1, Symbol):
- res.add(v1)
- if isinstance(v2, Symbol):
- res.add(v2)
- else:
- _internal_error("Internal error while fetching symbols from an "
- "expression with token stream {0}.".format(expr))
-
- rec(expr)
- return res
-
-def _str_val(obj):
- """Returns the value of obj as a string. If obj is not a string (constant
- symbol), it must be a Symbol."""
- return obj if isinstance(obj, str) else obj.get_value()
-
-def _sym_str_string(sym_or_str):
- if isinstance(sym_or_str, str):
- return '"' + sym_or_str + '"'
- return sym_or_str.name
-
-def _intersperse(lst, op):
- """_expr_to_str() helper. Gets the string representation of each expression in lst
- and produces a list where op has been inserted between the elements."""
- if lst == []:
- return ""
-
- res = []
-
- def handle_sub_expr(expr):
- no_parens = isinstance(expr, (str, Symbol)) or \
- expr[0] in (EQUAL, UNEQUAL) or \
- precedence[op] <= precedence[expr[0]]
- if not no_parens:
- res.append("(")
- res.extend(_expr_to_str_rec(expr))
- if not no_parens:
- res.append(")")
-
- op_str = op_to_str[op]
-
- handle_sub_expr(lst[0])
- for expr in lst[1:]:
- res.append(op_str)
- handle_sub_expr(expr)
-
- return res
-
-def _expr_to_str_rec(expr):
- if expr is None:
- return [""]
-
- if isinstance(expr, (Symbol, str)):
- return [_sym_str_string(expr)]
-
- e0 = expr[0]
-
- if e0 == AND or e0 == OR:
- return _intersperse(expr[1], expr[0])
-
- if e0 == NOT:
- need_parens = not isinstance(expr[1], (str, Symbol))
-
- res = ["!"]
- if need_parens:
- res.append("(")
- res.extend(_expr_to_str_rec(expr[1]))
- if need_parens:
- res.append(")")
- return res
-
- if e0 == EQUAL or e0 == UNEQUAL:
- return [_sym_str_string(expr[1]),
- op_to_str[expr[0]],
- _sym_str_string(expr[2])]
-
-def _expr_to_str(expr):
- return "".join(_expr_to_str_rec(expr))
-
-# Tokens
-(T_AND, T_OR, T_NOT,
- T_OPEN_PAREN, T_CLOSE_PAREN,
- T_EQUAL, T_UNEQUAL,
- T_MAINMENU, T_MENU, T_ENDMENU,
- T_SOURCE, T_CHOICE, T_ENDCHOICE,
- T_COMMENT, T_CONFIG, T_MENUCONFIG,
- T_HELP, T_IF, T_ENDIF, T_DEPENDS, T_ON,
- T_OPTIONAL, T_PROMPT, T_DEFAULT,
- T_BOOL, T_TRISTATE, T_HEX, T_INT, T_STRING,
- T_DEF_BOOL, T_DEF_TRISTATE,
- T_SELECT, T_RANGE, T_OPTION, T_ALLNOCONFIG_Y, T_ENV,
- T_DEFCONFIG_LIST, T_MODULES, T_VISIBLE) = range(0, 39)
-
-# Keyword to token map. Note that the get() method is assigned directly as a
-# small optimization.
-get_keyword = { "mainmenu" : T_MAINMENU,
- "menu" : T_MENU,
- "endmenu" : T_ENDMENU,
- "endif" : T_ENDIF,
- "endchoice" : T_ENDCHOICE,
- "source" : T_SOURCE,
- "choice" : T_CHOICE,
- "config" : T_CONFIG,
- "comment" : T_COMMENT,
- "menuconfig" : T_MENUCONFIG,
- "help" : T_HELP,
- "if" : T_IF,
- "depends" : T_DEPENDS,
- "on" : T_ON,
- "optional" : T_OPTIONAL,
- "prompt" : T_PROMPT,
- "default" : T_DEFAULT,
- "bool" : T_BOOL,
- "boolean" : T_BOOL,
- "tristate" : T_TRISTATE,
- "int" : T_INT,
- "hex" : T_HEX,
- "def_bool" : T_DEF_BOOL,
- "def_tristate" : T_DEF_TRISTATE,
- "string" : T_STRING,
- "select" : T_SELECT,
- "range" : T_RANGE,
- "option" : T_OPTION,
- "allnoconfig_y" : T_ALLNOCONFIG_Y,
- "env" : T_ENV,
- "defconfig_list" : T_DEFCONFIG_LIST,
- "modules" : T_MODULES,
- "visible" : T_VISIBLE }.get
-
-# Strings to use for True and False
-bool_str = { False : "false", True : "true" }
-
-# Tokens after which identifier-like lexemes are treated as strings. T_CHOICE
-# is included to avoid symbols being registered for named choices.
-string_lex = frozenset((T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING, T_CHOICE,
- T_PROMPT, T_MENU, T_COMMENT, T_SOURCE, T_MAINMENU))
-
-# Matches the initial token on a line; see _tokenize().
-initial_token_re_match = re.compile(r"[^\w]*(\w+)").match
-
-# Matches an identifier/keyword optionally preceded by whitespace
-id_keyword_re_match = re.compile(r"\s*([\w./-]+)").match
-
-# Regular expressions for parsing .config files
-set_re_match = re.compile(r"CONFIG_(\w+)=(.*)").match
-unset_re_match = re.compile(r"# CONFIG_(\w+) is not set").match
-
-# Regular expression for finding $-references to symbols in strings
-sym_ref_re_search = re.compile(r"\$[A-Za-z0-9_]+").search
-
-# Integers representing symbol types
-UNKNOWN, BOOL, TRISTATE, STRING, HEX, INT = range(0, 6)
-
-# Strings to use for types
-typename = { UNKNOWN : "unknown", BOOL : "bool", TRISTATE : "tristate",
- STRING : "string", HEX : "hex", INT : "int" }
-
-# Token to type mapping
-token_to_type = { T_BOOL : BOOL, T_TRISTATE : TRISTATE, T_STRING : STRING,
- T_INT : INT, T_HEX : HEX }
-
-# Default values for symbols of different types (the value the symbol gets if
-# it is not assigned a user value and none of its 'default' clauses kick in)
-default_value = { BOOL : "n", TRISTATE : "n", STRING : "", INT : "", HEX : "" }
-
-# Indicates that no item is selected in a choice statement
-NO_SELECTION = 0
-
-# Integers representing expression types
-AND, OR, NOT, EQUAL, UNEQUAL = range(0, 5)
-
-# Map from tristate values to integers
-tri_to_int = { "n" : 0, "m" : 1, "y" : 2 }
-
-# Printing-related stuff
-
-op_to_str = { AND : " && ", OR : " || ", EQUAL : " = ", UNEQUAL : " != " }
-precedence = { OR : 0, AND : 1, NOT : 2 }
-
class Item(object):
"""Base class for symbols and other Kconfig constructs. Subclasses are
@@ -3342,16 +3097,41 @@ class Comment(Item):
return ["\n#\n# {0}\n#".format(self.text)]
return []
-def _make_block_conf(block):
- """Returns a list of .config strings for a block (list) of items."""
+class Kconfig_Syntax_Error(Exception):
+ """Exception raised for syntax errors."""
+ pass
- # Collect the substrings in a list and later use join() instead of += to
- # build the final .config contents. With older Python versions, this yields
- # linear instead of quadratic complexity.
- strings = []
- for item in block:
- strings.extend(item._make_conf())
- return strings
+class Internal_Error(Exception):
+ """Exception raised for internal errors."""
+ pass
+
+#
+# Public functions
+#
+
+def tri_less(v1, v2):
+ """Returns True if the tristate v1 is less than the tristate v2, where "n",
+ "m" and "y" are ordered from lowest to highest."""
+ return tri_to_int[v1] < tri_to_int[v2]
+
+def tri_less_eq(v1, v2):
+ """Returns True if the tristate v1 is less than or equal to the tristate
+ v2, where "n", "m" and "y" are ordered from lowest to highest."""
+ return tri_to_int[v1] <= tri_to_int[v2]
+
+def tri_greater(v1, v2):
+ """Returns True if the tristate v1 is greater than the tristate v2, where
+ "n", "m" and "y" are ordered from lowest to highest."""
+ return tri_to_int[v1] > tri_to_int[v2]
+
+def tri_greater_eq(v1, v2):
+ """Returns True if the tristate v1 is greater than or equal to the tristate
+ v2, where "n", "m" and "y" are ordered from lowest to highest."""
+ return tri_to_int[v1] >= tri_to_int[v2]
+
+#
+# Internal classes
+#
class _Feed(object):
@@ -3414,32 +3194,171 @@ class _FileFeed(_Feed):
return self.i
#
-# Misc. public global utility functions
+# Internal functions
#
-def tri_less(v1, v2):
- """Returns True if the tristate v1 is less than the tristate v2, where "n",
- "m" and "y" are ordered from lowest to highest."""
- return tri_to_int[v1] < tri_to_int[v2]
+def _make_and(e1, e2):
+ """Constructs an AND (&&) expression. Performs trivial simplification.
+ Nones equate to 'y'.
-def tri_less_eq(v1, v2):
- """Returns True if the tristate v1 is less than or equal to the tristate
- v2, where "n", "m" and "y" are ordered from lowest to highest."""
- return tri_to_int[v1] <= tri_to_int[v2]
+ Note: returns None if e1 == e2 == None."""
+ if e1 == "n" or e2 == "n":
+ return "n"
+ if e1 is None or e1 == "y":
+ return e2
+ if e2 is None or e2 == "y":
+ return e1
-def tri_greater(v1, v2):
- """Returns True if the tristate v1 is greater than the tristate v2, where
- "n", "m" and "y" are ordered from lowest to highest."""
- return tri_to_int[v1] > tri_to_int[v2]
+ # Prefer to merge/update argument list if possible instead of creating
+ # a new AND node
-def tri_greater_eq(v1, v2):
- """Returns True if the tristate v1 is greater than or equal to the tristate
- v2, where "n", "m" and "y" are ordered from lowest to highest."""
- return tri_to_int[v1] >= tri_to_int[v2]
+ if isinstance(e1, tuple) and e1[0] == AND:
+ if isinstance(e2, tuple) and e2[0] == AND:
+ return (AND, e1[1] + e2[1])
+ return (AND, e1[1] + [e2])
-#
-# Helper functions, mostly related to text processing
-#
+ if isinstance(e2, tuple) and e2[0] == AND:
+ return (AND, e2[1] + [e1])
+
+ return (AND, [e1, e2])
+
+def _make_or(e1, e2):
+ """Constructs an OR (||) expression. Performs trivial simplification and
+ avoids Nones. Nones equate to 'y', which is usually what we want, but needs
+ to be kept in mind."""
+
+ # Perform trivial simplification and avoid None's (which
+ # correspond to y's)
+ if e1 is None or e2 is None or e1 == "y" or e2 == "y":
+ return "y"
+ if e1 == "n":
+ return e2
+ if e2 == "n":
+ return e1
+
+ # Prefer to merge/update argument list if possible instead of creating
+ # a new OR node
+
+ if isinstance(e1, tuple) and e1[0] == OR:
+ if isinstance(e2, tuple) and e2[0] == OR:
+ return (OR, e1[1] + e2[1])
+ return (OR, e1[1] + [e2])
+
+ if isinstance(e2, tuple) and e2[0] == OR:
+ return (OR, e2[1] + [e1])
+
+ return (OR, [e1, e2])
+
+def _get_expr_syms(expr):
+ """Returns the set() of symbols appearing in expr."""
+ res = set()
+ if expr is None:
+ return res
+
+ def rec(expr):
+ if isinstance(expr, Symbol):
+ res.add(expr)
+ return
+ if isinstance(expr, str):
+ return
+
+ e0 = expr[0]
+ if e0 == AND or e0 == OR:
+ for term in expr[1]:
+ rec(term)
+ elif e0 == NOT:
+ rec(expr[1])
+ elif e0 == EQUAL or e0 == UNEQUAL:
+ _, v1, v2 = expr
+ if isinstance(v1, Symbol):
+ res.add(v1)
+ if isinstance(v2, Symbol):
+ res.add(v2)
+ else:
+ _internal_error("Internal error while fetching symbols from an "
+ "expression with token stream {0}.".format(expr))
+
+ rec(expr)
+ return res
+
+def _str_val(obj):
+ """Returns the value of obj as a string. If obj is not a string (constant
+ symbol), it must be a Symbol."""
+ return obj if isinstance(obj, str) else obj.get_value()
+
+def _make_block_conf(block):
+ """Returns a list of .config strings for a block (list) of items."""
+
+ # Collect the substrings in a list and later use join() instead of += to
+ # build the final .config contents. With older Python versions, this yields
+ # linear instead of quadratic complexity.
+ strings = []
+ for item in block:
+ strings.extend(item._make_conf())
+ return strings
+
+def _sym_str_string(sym_or_str):
+ if isinstance(sym_or_str, str):
+ return '"' + sym_or_str + '"'
+ return sym_or_str.name
+
+def _intersperse(lst, op):
+ """_expr_to_str() helper. Gets the string representation of each expression in lst
+ and produces a list where op has been inserted between the elements."""
+ if lst == []:
+ return ""
+
+ res = []
+
+ def handle_sub_expr(expr):
+ no_parens = isinstance(expr, (str, Symbol)) or \
+ expr[0] in (EQUAL, UNEQUAL) or \
+ precedence[op] <= precedence[expr[0]]
+ if not no_parens:
+ res.append("(")
+ res.extend(_expr_to_str_rec(expr))
+ if not no_parens:
+ res.append(")")
+
+ op_str = op_to_str[op]
+
+ handle_sub_expr(lst[0])
+ for expr in lst[1:]:
+ res.append(op_str)
+ handle_sub_expr(expr)
+
+ return res
+
+def _expr_to_str_rec(expr):
+ if expr is None:
+ return [""]
+
+ if isinstance(expr, (Symbol, str)):
+ return [_sym_str_string(expr)]
+
+ e0 = expr[0]
+
+ if e0 == AND or e0 == OR:
+ return _intersperse(expr[1], expr[0])
+
+ if e0 == NOT:
+ need_parens = not isinstance(expr[1], (str, Symbol))
+
+ res = ["!"]
+ if need_parens:
+ res.append("(")
+ res.extend(_expr_to_str_rec(expr[1]))
+ if need_parens:
+ res.append(")")
+ return res
+
+ if e0 == EQUAL or e0 == UNEQUAL:
+ return [_sym_str_string(expr[1]),
+ op_to_str[expr[0]],
+ _sym_str_string(expr[2])]
+
+def _expr_to_str(expr):
+ return "".join(_expr_to_str_rec(expr))
def _indentation(line):
"""Returns the length of the line's leading whitespace, treating tab stops
@@ -3500,18 +3419,6 @@ def _stderr_msg(msg, filename, linenr):
sys.stderr.write("{0}:{1}: ".format(_clean_up_path(filename), linenr))
sys.stderr.write(msg + "\n")
-#
-# Error handling
-#
-
-class Kconfig_Syntax_Error(Exception):
- """Exception raised for syntax errors."""
- pass
-
-class Internal_Error(Exception):
- """Exception raised for internal errors."""
- pass
-
def _tokenization_error(s, filename, linenr):
loc = "" if filename is None else "{0}:{1}: ".format(filename, linenr)
raise Kconfig_Syntax_Error("{0}Couldn't tokenize '{1}'"
@@ -3528,3 +3435,107 @@ def _internal_error(msg):
"\nSorry! You may want to send an email to ulfalizer a.t Google's " \
"email service to tell me about this. Include the message above " \
"and the stack trace and describe what you were doing.")
+
+#
+# Internal global constants
+#
+
+# Tokens
+(T_AND, T_OR, T_NOT,
+ T_OPEN_PAREN, T_CLOSE_PAREN,
+ T_EQUAL, T_UNEQUAL,
+ T_MAINMENU, T_MENU, T_ENDMENU,
+ T_SOURCE, T_CHOICE, T_ENDCHOICE,
+ T_COMMENT, T_CONFIG, T_MENUCONFIG,
+ T_HELP, T_IF, T_ENDIF, T_DEPENDS, T_ON,
+ T_OPTIONAL, T_PROMPT, T_DEFAULT,
+ T_BOOL, T_TRISTATE, T_HEX, T_INT, T_STRING,
+ T_DEF_BOOL, T_DEF_TRISTATE,
+ T_SELECT, T_RANGE, T_OPTION, T_ALLNOCONFIG_Y, T_ENV,
+ T_DEFCONFIG_LIST, T_MODULES, T_VISIBLE) = range(0, 39)
+
+# Keyword to token map. Note that the get() method is assigned directly as a
+# small optimization.
+get_keyword = { "mainmenu" : T_MAINMENU,
+ "menu" : T_MENU,
+ "endmenu" : T_ENDMENU,
+ "endif" : T_ENDIF,
+ "endchoice" : T_ENDCHOICE,
+ "source" : T_SOURCE,
+ "choice" : T_CHOICE,
+ "config" : T_CONFIG,
+ "comment" : T_COMMENT,
+ "menuconfig" : T_MENUCONFIG,
+ "help" : T_HELP,
+ "if" : T_IF,
+ "depends" : T_DEPENDS,
+ "on" : T_ON,
+ "optional" : T_OPTIONAL,
+ "prompt" : T_PROMPT,
+ "default" : T_DEFAULT,
+ "bool" : T_BOOL,
+ "boolean" : T_BOOL,
+ "tristate" : T_TRISTATE,
+ "int" : T_INT,
+ "hex" : T_HEX,
+ "def_bool" : T_DEF_BOOL,
+ "def_tristate" : T_DEF_TRISTATE,
+ "string" : T_STRING,
+ "select" : T_SELECT,
+ "range" : T_RANGE,
+ "option" : T_OPTION,
+ "allnoconfig_y" : T_ALLNOCONFIG_Y,
+ "env" : T_ENV,
+ "defconfig_list" : T_DEFCONFIG_LIST,
+ "modules" : T_MODULES,
+ "visible" : T_VISIBLE }.get
+
+# Strings to use for True and False
+bool_str = { False : "false", True : "true" }
+
+# Tokens after which identifier-like lexemes are treated as strings. T_CHOICE
+# is included to avoid symbols being registered for named choices.
+string_lex = frozenset((T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING, T_CHOICE,
+ T_PROMPT, T_MENU, T_COMMENT, T_SOURCE, T_MAINMENU))
+
+# Matches the initial token on a line; see _tokenize().
+initial_token_re_match = re.compile(r"[^\w]*(\w+)").match
+
+# Matches an identifier/keyword optionally preceded by whitespace
+id_keyword_re_match = re.compile(r"\s*([\w./-]+)").match
+
+# Regular expressions for parsing .config files
+set_re_match = re.compile(r"CONFIG_(\w+)=(.*)").match
+unset_re_match = re.compile(r"# CONFIG_(\w+) is not set").match
+
+# Regular expression for finding $-references to symbols in strings
+sym_ref_re_search = re.compile(r"\$[A-Za-z0-9_]+").search
+
+# Integers representing symbol types
+UNKNOWN, BOOL, TRISTATE, STRING, HEX, INT = range(0, 6)
+
+# Strings to use for types
+typename = { UNKNOWN : "unknown", BOOL : "bool", TRISTATE : "tristate",
+ STRING : "string", HEX : "hex", INT : "int" }
+
+# Token to type mapping
+token_to_type = { T_BOOL : BOOL, T_TRISTATE : TRISTATE, T_STRING : STRING,
+ T_INT : INT, T_HEX : HEX }
+
+# Default values for symbols of different types (the value the symbol gets if
+# it is not assigned a user value and none of its 'default' clauses kick in)
+default_value = { BOOL : "n", TRISTATE : "n", STRING : "", INT : "", HEX : "" }
+
+# Indicates that no item is selected in a choice statement
+NO_SELECTION = 0
+
+# Integers representing expression types
+AND, OR, NOT, EQUAL, UNEQUAL = range(0, 5)
+
+# Map from tristate values to integers
+tri_to_int = { "n" : 0, "m" : 1, "y" : 2 }
+
+# Printing-related stuff
+
+op_to_str = { AND : " && ", OR : " || ", EQUAL : " = ", UNEQUAL : " != " }
+precedence = { OR : 0, AND : 1, NOT : 2 }