summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Magnusson <ulfalizer@gmail.com>2018-10-22 15:13:32 +0200
committerUlf Magnusson <ulfalizer@gmail.com>2018-10-22 22:42:36 +0200
commit6023234566944b3ae06276b9a2227709b4fe0957 (patch)
tree71022c39c151ffdc74609aa27593d3aa0130e95e
parent72eca77f6d1bc06accebf187f590ceb2d3b5ab04 (diff)
Move _check_sym/choice_sanity() into the Kconfig class
This makes the calls to Kconfig._warn() a bit less awkward (self._warn() instead of sym/choice.kconfig._warn()). Also move the loops over the symbols/choices into the functions, as a small optimization.
-rw-r--r--kconfiglib.py316
1 files changed, 156 insertions, 160 deletions
diff --git a/kconfiglib.py b/kconfiglib.py
index 4f60251..6b031ae 100644
--- a/kconfiglib.py
+++ b/kconfiglib.py
@@ -974,14 +974,9 @@ class Kconfig(object):
self._finalize_tree(self.top_node, self.y)
- # Do sanity checks. Some of these depend on everything being
- # finalized.
-
- for sym in self.unique_defined_syms:
- _check_sym_sanity(sym)
-
- for choice in self.unique_choices:
- _check_choice_sanity(choice)
+ # Do sanity checks. Some of these depend on everything being finalized.
+ self._check_sym_sanity()
+ self._check_choice_sanity()
if os.environ.get("KCONFIG_STRICT") == "y":
self._check_undef_syms()
@@ -3238,6 +3233,159 @@ class Kconfig(object):
# Misc.
#
+ def _check_sym_sanity(self):
+ # Checks various symbol properties that are handiest to check after
+ # parsing. Only generates errors and warnings.
+
+ def num_ok(sym, type_):
+ # Returns True if the (possibly constant) symbol 'sym' is valid as a value
+ # for a symbol of type type_ (INT or HEX)
+
+ # 'not sym.nodes' implies a constant or undefined symbol, e.g. a plain
+ # "123"
+ if not sym.nodes:
+ return _is_base_n(sym.name, _TYPE_TO_BASE[type_])
+
+ return sym.orig_type is type_
+
+ for sym in self.unique_defined_syms:
+ if sym.orig_type in (BOOL, TRISTATE):
+ # A helper function could be factored out here, but keep it
+ # speedy/straightforward
+
+ for target_sym, _ in sym.selects:
+ if target_sym.orig_type not in (BOOL, TRISTATE, UNKNOWN):
+ self._warn("{} selects the {} symbol {}, which is not "
+ "bool or tristate"
+ .format(_name_and_loc(sym),
+ TYPE_TO_STR[target_sym.orig_type],
+ _name_and_loc(target_sym)))
+
+ for target_sym, _ in sym.implies:
+ if target_sym.orig_type not in (BOOL, TRISTATE, UNKNOWN):
+ self._warn("{} implies the {} symbol {}, which is not "
+ "bool or tristate"
+ .format(_name_and_loc(sym),
+ TYPE_TO_STR[target_sym.orig_type],
+ _name_and_loc(target_sym)))
+
+ elif sym.orig_type in (STRING, INT, HEX):
+ for default, _ in sym.defaults:
+ if not isinstance(default, Symbol):
+ raise KconfigError(
+ "the {} symbol {} has a malformed default {} -- expected "
+ "a single symbol"
+ .format(TYPE_TO_STR[sym.orig_type], _name_and_loc(sym),
+ expr_str(default)))
+
+ if sym.orig_type is STRING:
+ if not default.is_constant and not default.nodes and \
+ not default.name.isupper():
+ # 'default foo' on a string symbol could be either a symbol
+ # reference or someone leaving out the quotes. Guess that
+ # the quotes were left out if 'foo' isn't all-uppercase
+ # (and no symbol named 'foo' exists).
+ self._warn("style: quotes recommended around "
+ "default value for string symbol "
+ + _name_and_loc(sym))
+
+ elif sym.orig_type in (INT, HEX) and \
+ not num_ok(default, sym.orig_type):
+
+ self._warn("the {0} symbol {1} has a non-{0} default {2}"
+ .format(TYPE_TO_STR[sym.orig_type],
+ _name_and_loc(sym),
+ _name_and_loc(default)))
+
+ if sym.selects or sym.implies:
+ self._warn("the {} symbol {} has selects or implies"
+ .format(TYPE_TO_STR[sym.orig_type],
+ _name_and_loc(sym)))
+
+ else: # UNKNOWN
+ self._warn("{} defined without a type"
+ .format(_name_and_loc(sym)))
+
+
+ if sym.ranges:
+ if sym.orig_type not in (INT, HEX):
+ self._warn(
+ "the {} symbol {} has ranges, but is not int or hex"
+ .format(TYPE_TO_STR[sym.orig_type],
+ _name_and_loc(sym)))
+ else:
+ for low, high, _ in sym.ranges:
+ if not num_ok(low, sym.orig_type) or \
+ not num_ok(high, sym.orig_type):
+
+ self._warn("the {0} symbol {1} has a non-{0} "
+ "range [{2}, {3}]"
+ .format(TYPE_TO_STR[sym.orig_type],
+ _name_and_loc(sym),
+ _name_and_loc(low),
+ _name_and_loc(high)))
+
+ def _check_choice_sanity(self):
+ # Checks various choice properties that are handiest to check after
+ # parsing. Only generates errors and warnings.
+
+ def warn_select_imply(sym, expr, expr_type):
+ msg = "the choice symbol {} is {} by the following symbols, which " \
+ "has no effect: ".format(_name_and_loc(sym), expr_type)
+
+ # si = select/imply
+ for si in split_expr(expr, OR):
+ msg += "\n - " + _name_and_loc(split_expr(si, AND)[0])
+
+ self._warn(msg)
+
+ for choice in self.unique_choices:
+ if choice.orig_type not in (BOOL, TRISTATE):
+ self._warn("{} defined with type {}"
+ .format(_name_and_loc(choice),
+ TYPE_TO_STR[choice.orig_type]))
+
+ for node in choice.nodes:
+ if node.prompt:
+ break
+ else:
+ self._warn(_name_and_loc(choice) + " defined without a prompt")
+
+ for default, _ in choice.defaults:
+ if not isinstance(default, Symbol):
+ raise KconfigError(
+ "{} has a malformed default {}"
+ .format(_name_and_loc(choice), expr_str(default)))
+
+ if default.choice is not choice:
+ self._warn("the default selection {} of {} is not "
+ "contained in the choice"
+ .format(_name_and_loc(default),
+ _name_and_loc(choice)))
+
+ for sym in choice.syms:
+ if sym.defaults:
+ self._warn("default on the choice symbol {} will have "
+ "no effect, as defaults do not affect choice "
+ "symbols".format(_name_and_loc(sym)))
+
+ if sym.rev_dep is not sym.kconfig.n:
+ warn_select_imply(sym, sym.rev_dep, "selected")
+
+ if sym.weak_rev_dep is not sym.kconfig.n:
+ warn_select_imply(sym, sym.weak_rev_dep, "implied")
+
+ for node in sym.nodes:
+ if node.parent.item is choice:
+ if not node.prompt:
+ self._warn("the choice symbol {} has no prompt"
+ .format(_name_and_loc(sym)))
+
+ elif node.prompt:
+ self._warn("the choice symbol {} is defined with a "
+ "prompt outside the choice"
+ .format(_name_and_loc(sym)))
+
def _parse_error(self, msg):
if self._filename is None:
loc = ""
@@ -5824,158 +5972,6 @@ def _found_dep_loop(loop, cur):
raise KconfigError(msg)
-def _check_sym_sanity(sym):
- # Checks various symbol properties that are handiest to check after
- # parsing. Only generates errors and warnings.
-
- if sym.orig_type in (BOOL, TRISTATE):
- # A helper function could be factored out here, but keep it
- # speedy/straightforward for now. bool/tristate symbols are by far the
- # most common, and most lack selects and implies.
-
- for target_sym, _ in sym.selects:
- if target_sym.orig_type not in (BOOL, TRISTATE, UNKNOWN):
- sym.kconfig._warn("{} selects the {} symbol {}, which is not "
- "bool or tristate"
- .format(_name_and_loc(sym),
- TYPE_TO_STR[target_sym.orig_type],
- _name_and_loc(target_sym)))
-
- for target_sym, _ in sym.implies:
- if target_sym.orig_type not in (BOOL, TRISTATE, UNKNOWN):
- sym.kconfig._warn("{} implies the {} symbol {}, which is not "
- "bool or tristate"
- .format(_name_and_loc(sym),
- TYPE_TO_STR[target_sym.orig_type],
- _name_and_loc(target_sym)))
-
- elif sym.orig_type in (STRING, INT, HEX):
- for default, _ in sym.defaults:
- if not isinstance(default, Symbol):
- raise KconfigError(
- "the {} symbol {} has a malformed default {} -- expected "
- "a single symbol"
- .format(TYPE_TO_STR[sym.orig_type], _name_and_loc(sym),
- expr_str(default)))
-
- if sym.orig_type is STRING:
- if not default.is_constant and not default.nodes and \
- not default.name.isupper():
- # 'default foo' on a string symbol could be either a symbol
- # reference or someone leaving out the quotes. Guess that
- # the quotes were left out if 'foo' isn't all-uppercase
- # (and no symbol named 'foo' exists).
- sym.kconfig._warn("style: quotes recommended around "
- "default value for string symbol "
- + _name_and_loc(sym))
-
- elif sym.orig_type in (INT, HEX) and \
- not _int_hex_ok(default, sym.orig_type):
-
- sym.kconfig._warn("the {0} symbol {1} has a non-{0} default {2}"
- .format(TYPE_TO_STR[sym.orig_type],
- _name_and_loc(sym),
- _name_and_loc(default)))
-
- if sym.selects or sym.implies:
- sym.kconfig._warn("the {} symbol {} has selects or implies"
- .format(TYPE_TO_STR[sym.orig_type],
- _name_and_loc(sym)))
-
- else: # UNKNOWN
- sym.kconfig._warn("{} defined without a type"
- .format(_name_and_loc(sym)))
-
-
- if sym.ranges:
- if sym.orig_type not in (INT, HEX):
- sym.kconfig._warn(
- "the {} symbol {} has ranges, but is not int or hex"
- .format(TYPE_TO_STR[sym.orig_type], _name_and_loc(sym)))
- else:
- for low, high, _ in sym.ranges:
- if not _int_hex_ok(low, sym.orig_type) or \
- not _int_hex_ok(high, sym.orig_type):
-
- sym.kconfig._warn("the {0} symbol {1} has a non-{0} range "
- "[{2}, {3}]"
- .format(TYPE_TO_STR[sym.orig_type],
- _name_and_loc(sym),
- _name_and_loc(low),
- _name_and_loc(high)))
-
-
-def _int_hex_ok(sym, type_):
- # Returns True if the (possibly constant) symbol 'sym' is valid as a value
- # for a symbol of type type_ (INT or HEX)
-
- # 'not sym.nodes' implies a constant or undefined symbol, e.g. a plain
- # "123"
- if not sym.nodes:
- return _is_base_n(sym.name, _TYPE_TO_BASE[type_])
-
- return sym.orig_type is type_
-
-def _check_choice_sanity(choice):
- # Checks various choice properties that are handiest to check after
- # parsing. Only generates errors and warnings.
-
- if choice.orig_type not in (BOOL, TRISTATE):
- choice.kconfig._warn("{} defined with type {}"
- .format(_name_and_loc(choice),
- TYPE_TO_STR[choice.orig_type]))
-
- for node in choice.nodes:
- if node.prompt:
- break
- else:
- choice.kconfig._warn(_name_and_loc(choice) +
- " defined without a prompt")
-
- for default, _ in choice.defaults:
- if not isinstance(default, Symbol):
- raise KconfigError(
- "{} has a malformed default {}"
- .format(_name_and_loc(choice), expr_str(default)))
-
- if default.choice is not choice:
- choice.kconfig._warn("the default selection {} of {} is not "
- "contained in the choice"
- .format(_name_and_loc(default),
- _name_and_loc(choice)))
-
- for sym in choice.syms:
- if sym.defaults:
- sym.kconfig._warn("default on the choice symbol {} will have "
- "no effect".format(_name_and_loc(sym)))
-
- if sym.rev_dep is not sym.kconfig.n:
- _warn_choice_select_imply(sym, sym.rev_dep, "selected")
-
- if sym.weak_rev_dep is not sym.kconfig.n:
- _warn_choice_select_imply(sym, sym.weak_rev_dep, "implied")
-
- for node in sym.nodes:
- if node.parent.item is choice:
- if not node.prompt:
- sym.kconfig._warn("the choice symbol {} has no prompt"
- .format(_name_and_loc(sym)))
-
- elif node.prompt:
- sym.kconfig._warn("the choice symbol {} is defined with a "
- "prompt outside the choice"
- .format(_name_and_loc(sym)))
-
-def _warn_choice_select_imply(sym, expr, expr_type):
- msg = "the choice symbol {} is {} by the following symbols, which has " \
- "no effect: ".format(_name_and_loc(sym), expr_type)
-
- # si = select/imply
- for si in split_expr(expr, OR):
- msg += "\n - " + _name_and_loc(split_expr(si, AND)[0])
-
- sym.kconfig._warn(msg)
-
# Predefined preprocessor functions