kconfiglib: update with 'imply' support
Corresponds to 375506d (File writing nit) from upstream
(https://github.com/ulfalizer/Kconfiglib).
Adds proper 'imply' support and fixes a few minor issues, one of which
previously triggered the following weird warning:
configs/taurus_defconfig: /tmp/tmpisI45S:6: warning: assignment to SPL_LDSCRIPT changes mode of containing choice from "arch/$(ARCH)/cpu/u-boot-spl.lds" to "y"
The change in 8639f69
(genconfig.py: Print defconfig next to warnings)
was reapplied.
tools/moveconfig.py previously depended on a hack that merged 'select's
with 'imply's. It was modified to look at the union of
Symbol.get_selected_symbols() and Symbol.get_implied_symbols(), which
should give the same behavior.
tools/genboardscfg.py was verified to produce identical board.cfg's
before and after the change.
Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
This commit is contained in:
parent
2719ae3346
commit
4e1102f6de
@ -73,6 +73,7 @@ email service. Don't wrestle with internal APIs. Tell me what you need and I
|
||||
might add it in a safe way as a client API instead."""
|
||||
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import sys
|
||||
|
||||
@ -137,10 +138,8 @@ class Config(object):
|
||||
# The set of all symbols, indexed by name (a string)
|
||||
self.syms = {}
|
||||
# Python 2/3 compatibility hack. This is the only one needed.
|
||||
if sys.version_info[0] >= 3:
|
||||
self.syms_iter = self.syms.values
|
||||
else:
|
||||
self.syms_iter = self.syms.itervalues
|
||||
self.syms_iter = self.syms.values if sys.version_info[0] >= 3 else \
|
||||
self.syms.itervalues
|
||||
|
||||
# The set of all defined symbols in the configuration in the order they
|
||||
# appear in the Kconfig files. This excludes the special symbols n, m,
|
||||
@ -173,7 +172,7 @@ class Config(object):
|
||||
self.m = register_special_symbol(TRISTATE, "m", "m")
|
||||
self.y = register_special_symbol(TRISTATE, "y", "y")
|
||||
# DEFCONFIG_LIST uses this
|
||||
register_special_symbol(STRING, "UNAME_RELEASE", os.uname()[2])
|
||||
register_special_symbol(STRING, "UNAME_RELEASE", platform.uname()[2])
|
||||
|
||||
# The symbol with "option defconfig_list" set, containing a list of
|
||||
# default .config files
|
||||
@ -183,16 +182,20 @@ class Config(object):
|
||||
self.arch = os.environ.get("ARCH")
|
||||
self.srcarch = os.environ.get("SRCARCH")
|
||||
|
||||
# If you set CONFIG_ in the environment, Kconfig will prefix all symbols
|
||||
# with its value when saving the configuration, instead of using the default, "CONFIG_".
|
||||
self.config_prefix = os.environ.get("CONFIG_")
|
||||
if self.config_prefix is None:
|
||||
self.config_prefix = "CONFIG_"
|
||||
|
||||
# See Config.__init__(). We need this for get_defconfig_filename().
|
||||
self.srctree = os.environ.get("srctree")
|
||||
if self.srctree is None:
|
||||
self.srctree = "."
|
||||
|
||||
self.filename = filename
|
||||
if base_dir is None:
|
||||
self.base_dir = self.srctree
|
||||
else:
|
||||
self.base_dir = os.path.expandvars(base_dir)
|
||||
self.base_dir = self.srctree if base_dir is None else \
|
||||
os.path.expandvars(base_dir)
|
||||
|
||||
# The 'mainmenu' text
|
||||
self.mainmenu_text = None
|
||||
@ -222,7 +225,8 @@ class Config(object):
|
||||
self._transform_m = None
|
||||
|
||||
# Parse the Kconfig files
|
||||
self.top_block = self._parse_file(filename, None, None, None)
|
||||
self.top_block = []
|
||||
self._parse_file(filename, None, None, None, self.top_block)
|
||||
|
||||
# Build Symbol.dep for all symbols
|
||||
self._build_dep()
|
||||
@ -405,6 +409,10 @@ class Config(object):
|
||||
"""
|
||||
|
||||
self._warnings = []
|
||||
# Regular expressions for parsing .config files
|
||||
_set_re_match = re.compile(r"{}(\w+)=(.*)".format(self.config_prefix)).match
|
||||
_unset_re_match = re.compile(r"# {}(\w+) is not set".format(self.config_prefix)).match
|
||||
|
||||
# Put this first so that a missing file doesn't screw up our state
|
||||
filename = os.path.expandvars(filename)
|
||||
line_feeder = _FileFeed(filename)
|
||||
@ -524,14 +532,12 @@ class Config(object):
|
||||
with open(filename, "w") as f:
|
||||
# Write header
|
||||
if header is not None:
|
||||
f.write(_comment(header))
|
||||
f.write("\n")
|
||||
f.write(_comment(header) + "\n")
|
||||
|
||||
# Build and write configuration
|
||||
conf_strings = []
|
||||
_make_block_conf(self.top_block, conf_strings.append)
|
||||
f.write("\n".join(conf_strings))
|
||||
f.write("\n")
|
||||
f.write("\n".join(conf_strings) + "\n")
|
||||
|
||||
def eval(self, s):
|
||||
"""Returns the value of the expression 's' -- where 's' is represented
|
||||
@ -609,16 +615,18 @@ class Config(object):
|
||||
# Kconfig parsing
|
||||
#
|
||||
|
||||
def _parse_file(self, filename, parent, deps, visible_if_deps, res=None):
|
||||
"""Parses the Kconfig file 'filename'. Returns a list with the Items in
|
||||
the file. See _parse_block() for the meaning of the parameters."""
|
||||
return self._parse_block(_FileFeed(filename), None, parent, deps,
|
||||
visible_if_deps, res)
|
||||
def _parse_file(self, filename, parent, deps, visible_if_deps, block):
|
||||
"""Parses the Kconfig file 'filename'. Appends the Items in the file
|
||||
(and any file it sources) to the list passed in the 'block' parameter.
|
||||
See _parse_block() for the meaning of the parameters."""
|
||||
self._parse_block(_FileFeed(filename), None, parent, deps,
|
||||
visible_if_deps, block)
|
||||
|
||||
def _parse_block(self, line_feeder, end_marker, parent, deps,
|
||||
visible_if_deps, res=None):
|
||||
visible_if_deps, block):
|
||||
"""Parses a block, which is the contents of either a file or an if,
|
||||
menu, or choice statement. Returns a list with the Items in the block.
|
||||
menu, or choice statement. Appends the Items to the list passed in the
|
||||
'block' parameter.
|
||||
|
||||
line_feeder: A _FileFeed instance feeding lines from a file. The
|
||||
Kconfig language is line-based in practice.
|
||||
@ -634,10 +642,7 @@ class Config(object):
|
||||
visible_if_deps (default: None): 'visible if' dependencies from
|
||||
enclosing menus.
|
||||
|
||||
res (default: None): The list to add items to. If None, a new list is
|
||||
created to hold the items."""
|
||||
|
||||
block = [] if res is None else res
|
||||
block: The list to add items to."""
|
||||
|
||||
while 1:
|
||||
# Do we already have a tokenized line that we determined wasn't
|
||||
@ -656,7 +661,7 @@ class Config(object):
|
||||
if end_marker is not None:
|
||||
raise Kconfig_Syntax_Error("Unexpected end of file {0}"
|
||||
.format(line_feeder.filename))
|
||||
return block
|
||||
return
|
||||
|
||||
tokens = self._tokenize(line, False, line_feeder.filename,
|
||||
line_feeder.linenr)
|
||||
@ -679,14 +684,13 @@ class Config(object):
|
||||
# choice statements, the choice statement takes precedence.
|
||||
if not sym.is_defined_ or isinstance(parent, Choice):
|
||||
sym.parent = parent
|
||||
|
||||
sym.is_defined_ = True
|
||||
|
||||
self._parse_properties(line_feeder, sym, deps, visible_if_deps)
|
||||
|
||||
self.kconfig_syms.append(sym)
|
||||
block.append(sym)
|
||||
|
||||
self._parse_properties(line_feeder, sym, deps, visible_if_deps)
|
||||
|
||||
elif t0 == T_SOURCE:
|
||||
kconfig_file = tokens.get_next()
|
||||
exp_kconfig_file = self._expand_sym_refs(kconfig_file)
|
||||
@ -705,7 +709,7 @@ class Config(object):
|
||||
|
||||
elif t0 == end_marker:
|
||||
# We have reached the end of the block
|
||||
return block
|
||||
return
|
||||
|
||||
elif t0 == T_IF:
|
||||
# If statements are treated as syntactic sugar for adding
|
||||
@ -722,38 +726,39 @@ class Config(object):
|
||||
|
||||
elif t0 == T_COMMENT:
|
||||
comment = Comment()
|
||||
|
||||
comment.config = self
|
||||
comment.parent = parent
|
||||
comment.filename = line_feeder.filename
|
||||
comment.linenr = line_feeder.linenr
|
||||
comment.text = tokens.get_next()
|
||||
|
||||
self.comments.append(comment)
|
||||
block.append(comment)
|
||||
|
||||
self._parse_properties(line_feeder, comment, deps,
|
||||
visible_if_deps)
|
||||
|
||||
self.comments.append(comment)
|
||||
block.append(comment)
|
||||
|
||||
elif t0 == T_MENU:
|
||||
menu = Menu()
|
||||
|
||||
menu.config = self
|
||||
menu.parent = parent
|
||||
menu.filename = line_feeder.filename
|
||||
menu.linenr = line_feeder.linenr
|
||||
menu.title = tokens.get_next()
|
||||
|
||||
self.menus.append(menu)
|
||||
block.append(menu)
|
||||
|
||||
# Parse properties and contents
|
||||
self._parse_properties(line_feeder, menu, deps,
|
||||
visible_if_deps)
|
||||
menu.block = self._parse_block(line_feeder, T_ENDMENU, menu,
|
||||
menu.dep_expr,
|
||||
_make_and(visible_if_deps,
|
||||
menu.visible_if_expr))
|
||||
|
||||
# This needs to go before _parse_block() so that we get the
|
||||
# proper menu ordering in the case of nested functions
|
||||
self.menus.append(menu)
|
||||
# Parse contents and put Items in menu.block
|
||||
self._parse_block(line_feeder, T_ENDMENU, menu, menu.dep_expr,
|
||||
_make_and(visible_if_deps,
|
||||
menu.visible_if_expr),
|
||||
menu.block)
|
||||
|
||||
block.append(menu)
|
||||
|
||||
elif t0 == T_CHOICE:
|
||||
name = tokens.get_next()
|
||||
@ -775,11 +780,12 @@ class Config(object):
|
||||
choice.def_locations.append((line_feeder.filename,
|
||||
line_feeder.linenr))
|
||||
|
||||
# Parse properties and contents
|
||||
self._parse_properties(line_feeder, choice, deps,
|
||||
visible_if_deps)
|
||||
choice.block = self._parse_block(line_feeder, T_ENDCHOICE,
|
||||
choice, deps, visible_if_deps)
|
||||
|
||||
# Parse contents and put Items in choice.block
|
||||
self._parse_block(line_feeder, T_ENDCHOICE, choice, deps,
|
||||
visible_if_deps, choice.block)
|
||||
|
||||
choice._determine_actual_symbols()
|
||||
|
||||
@ -819,19 +825,19 @@ class Config(object):
|
||||
"""Parses '<expr1> if <expr2>' constructs, where the 'if' part is
|
||||
optional. Returns a tuple containing the parsed expressions, with
|
||||
None as the second element if the 'if' part is missing."""
|
||||
val = self._parse_expr(tokens, stmt, line, filename, linenr, False)
|
||||
if tokens.check(T_IF):
|
||||
return (val, self._parse_expr(tokens, stmt, line, filename,
|
||||
linenr))
|
||||
return (val, None)
|
||||
return (self._parse_expr(tokens, stmt, line, filename, linenr,
|
||||
False),
|
||||
self._parse_expr(tokens, stmt, line, filename, linenr)
|
||||
if tokens.check(T_IF) else None)
|
||||
|
||||
# In case the symbol is defined in multiple locations, we need to
|
||||
# remember what prompts, defaults, and selects are new for this
|
||||
# definition, as "depends on" should only apply to the local
|
||||
# remember what prompts, defaults, selects, and implies are new for
|
||||
# this definition, as "depends on" should only apply to the local
|
||||
# definition.
|
||||
new_prompt = None
|
||||
new_def_exprs = []
|
||||
new_selects = []
|
||||
new_implies = []
|
||||
|
||||
# Dependencies from 'depends on' statements
|
||||
depends_on_expr = None
|
||||
@ -897,18 +903,27 @@ class Config(object):
|
||||
|
||||
line_feeder.unget()
|
||||
|
||||
elif t0 == T_SELECT or t0 == T_IMPLY:
|
||||
elif t0 == T_SELECT:
|
||||
target = tokens.get_next()
|
||||
|
||||
stmt.referenced_syms.add(target)
|
||||
stmt.selected_syms.add(target)
|
||||
|
||||
if tokens.check(T_IF):
|
||||
new_selects.append((target,
|
||||
self._parse_expr(tokens, stmt, line,
|
||||
filename, linenr)))
|
||||
else:
|
||||
new_selects.append((target, None))
|
||||
new_selects.append(
|
||||
(target,
|
||||
self._parse_expr(tokens, stmt, line, filename, linenr)
|
||||
if tokens.check(T_IF) else None))
|
||||
|
||||
elif t0 == T_IMPLY:
|
||||
target = tokens.get_next()
|
||||
|
||||
stmt.referenced_syms.add(target)
|
||||
stmt.implied_syms.add(target)
|
||||
|
||||
new_implies.append(
|
||||
(target,
|
||||
self._parse_expr(tokens, stmt, line, filename, linenr)
|
||||
if tokens.check(T_IF) else None))
|
||||
|
||||
elif t0 in (T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING):
|
||||
stmt.type = TOKEN_TO_TYPE[t0]
|
||||
@ -939,12 +954,10 @@ class Config(object):
|
||||
stmt.referenced_syms.add(low)
|
||||
stmt.referenced_syms.add(high)
|
||||
|
||||
if tokens.check(T_IF):
|
||||
stmt.ranges.append((low, high,
|
||||
self._parse_expr(tokens, stmt, line,
|
||||
filename, linenr)))
|
||||
else:
|
||||
stmt.ranges.append((low, high, None))
|
||||
stmt.ranges.append(
|
||||
(low, high,
|
||||
self._parse_expr(tokens, stmt, line, filename, linenr)
|
||||
if tokens.check(T_IF) else None))
|
||||
|
||||
elif t0 == T_DEF_TRISTATE:
|
||||
stmt.type = TRISTATE
|
||||
@ -1051,21 +1064,20 @@ class Config(object):
|
||||
# Symbol or Choice
|
||||
|
||||
# See comment for 'menu_dep'
|
||||
stmt.menu_dep = depends_on_expr
|
||||
stmt.menu_dep = _make_and(deps, depends_on_expr)
|
||||
|
||||
# Propagate dependencies to prompts
|
||||
|
||||
if new_prompt is not None:
|
||||
# Propagate 'visible if' dependencies from enclosing menus
|
||||
prompt, cond_expr = new_prompt
|
||||
cond_expr = _make_and(cond_expr, visible_if_deps)
|
||||
# Propagate 'depends on' dependencies
|
||||
new_prompt = (prompt, _make_and(cond_expr, depends_on_expr))
|
||||
# Propagate 'visible if' dependencies from menus and local
|
||||
# 'depends on' dependencies
|
||||
cond_expr = _make_and(_make_and(cond_expr, visible_if_deps),
|
||||
depends_on_expr)
|
||||
# Save original
|
||||
stmt.orig_prompts.append(new_prompt)
|
||||
stmt.orig_prompts.append((prompt, cond_expr))
|
||||
# Finalize with dependencies from enclosing menus and ifs
|
||||
stmt.prompts.append((new_prompt[0],
|
||||
_make_and(new_prompt[1], deps)))
|
||||
stmt.prompts.append((prompt, _make_and(cond_expr, deps)))
|
||||
|
||||
# Propagate dependencies to defaults
|
||||
|
||||
@ -1078,20 +1090,27 @@ class Config(object):
|
||||
stmt.def_exprs.extend([(val_expr, _make_and(cond_expr, deps))
|
||||
for val_expr, cond_expr in new_def_exprs])
|
||||
|
||||
# Propagate dependencies to selects
|
||||
# Propagate dependencies to selects and implies
|
||||
|
||||
# Only symbols can select
|
||||
# Only symbols can select and imply
|
||||
if isinstance(stmt, Symbol):
|
||||
# Propagate 'depends on' dependencies
|
||||
new_selects = [(target, _make_and(cond_expr, depends_on_expr))
|
||||
for target, cond_expr in new_selects]
|
||||
new_implies = [(target, _make_and(cond_expr, depends_on_expr))
|
||||
for target, cond_expr in new_implies]
|
||||
# Save original
|
||||
stmt.orig_selects.extend(new_selects)
|
||||
stmt.orig_implies.extend(new_implies)
|
||||
# Finalize with dependencies from enclosing menus and ifs
|
||||
for target, cond in new_selects:
|
||||
target.rev_dep = _make_or(target.rev_dep,
|
||||
_make_and(stmt,
|
||||
_make_and(cond, deps)))
|
||||
target.rev_dep = \
|
||||
_make_or(target.rev_dep,
|
||||
_make_and(stmt, _make_and(cond, deps)))
|
||||
for target, cond in new_implies:
|
||||
target.weak_rev_dep = \
|
||||
_make_or(target.weak_rev_dep,
|
||||
_make_and(stmt, _make_and(cond, deps)))
|
||||
|
||||
def _parse_expr(self, feed, cur_item, line, filename=None, linenr=None,
|
||||
transform_m=True):
|
||||
@ -1483,7 +1502,8 @@ class Config(object):
|
||||
|
||||
# The directly dependent symbols of a symbol are:
|
||||
# - Any symbols whose prompts, default values, rev_dep (select
|
||||
# condition), or ranges depend on the symbol
|
||||
# condition), weak_rev_dep (imply condition) or ranges depend on the
|
||||
# symbol
|
||||
# - Any symbols that belong to the same choice statement as the symbol
|
||||
# (these won't be included in 'dep' as that makes the dependency
|
||||
# graph unwieldy, but Symbol._get_dependent() will include them)
|
||||
@ -1497,6 +1517,7 @@ class Config(object):
|
||||
add_expr_deps(e, sym)
|
||||
|
||||
add_expr_deps(sym.rev_dep, sym)
|
||||
add_expr_deps(sym.weak_rev_dep, sym)
|
||||
|
||||
for l, u, e in sym.ranges:
|
||||
add_expr_deps(l, sym)
|
||||
@ -1625,20 +1646,16 @@ class Config(object):
|
||||
else:
|
||||
prompts_str_rows = []
|
||||
for prompt, cond_expr in sc.orig_prompts:
|
||||
if cond_expr is None:
|
||||
prompts_str_rows.append(' "{0}"'.format(prompt))
|
||||
else:
|
||||
prompts_str_rows.append(
|
||||
' "{0}" if {1}'.format(prompt,
|
||||
self._expr_val_str(cond_expr)))
|
||||
prompts_str_rows.append(
|
||||
' "{0}"'.format(prompt) if cond_expr is None else
|
||||
' "{0}" if {1}'.format(prompt,
|
||||
self._expr_val_str(cond_expr)))
|
||||
prompts_str = "\n".join(prompts_str_rows)
|
||||
|
||||
# Build locations string
|
||||
if not sc.def_locations:
|
||||
locations_str = "(no locations)"
|
||||
else:
|
||||
locations_str = " ".join(["{0}:{1}".format(filename, linenr) for
|
||||
(filename, linenr) in sc.def_locations])
|
||||
locations_str = "(no locations)" if not sc.def_locations else \
|
||||
" ".join(["{0}:{1}".format(filename, linenr) for
|
||||
filename, linenr in sc.def_locations])
|
||||
|
||||
# Build additional-dependencies-from-menus-and-ifs string
|
||||
additional_deps_str = " " + \
|
||||
@ -1657,13 +1674,11 @@ class Config(object):
|
||||
else:
|
||||
ranges_str_rows = []
|
||||
for l, u, cond_expr in sc.ranges:
|
||||
if cond_expr is None:
|
||||
ranges_str_rows.append(" [{0}, {1}]".format(s(l),
|
||||
s(u)))
|
||||
else:
|
||||
ranges_str_rows.append(" [{0}, {1}] if {2}"
|
||||
.format(s(l), s(u),
|
||||
self._expr_val_str(cond_expr)))
|
||||
ranges_str_rows.append(
|
||||
" [{0}, {1}]".format(s(l), s(u))
|
||||
if cond_expr is None else
|
||||
" [{0}, {1}] if {2}"
|
||||
.format(s(l), s(u), self._expr_val_str(cond_expr)))
|
||||
ranges_str = "\n".join(ranges_str_rows)
|
||||
|
||||
# Build default values string
|
||||
@ -1685,14 +1700,24 @@ class Config(object):
|
||||
else:
|
||||
selects_str_rows = []
|
||||
for target, cond_expr in sc.orig_selects:
|
||||
if cond_expr is None:
|
||||
selects_str_rows.append(" {0}".format(target.name))
|
||||
else:
|
||||
selects_str_rows.append(
|
||||
" {0} if {1}".format(target.name,
|
||||
self._expr_val_str(cond_expr)))
|
||||
selects_str_rows.append(
|
||||
" {0}".format(target.name) if cond_expr is None else
|
||||
" {0} if {1}".format(target.name,
|
||||
self._expr_val_str(cond_expr)))
|
||||
selects_str = "\n".join(selects_str_rows)
|
||||
|
||||
# Build implies string
|
||||
if not sc.orig_implies:
|
||||
implies_str = " (no implies)"
|
||||
else:
|
||||
implies_str_rows = []
|
||||
for target, cond_expr in sc.orig_implies:
|
||||
implies_str_rows.append(
|
||||
" {0}".format(target.name) if cond_expr is None else
|
||||
" {0} if {1}".format(target.name,
|
||||
self._expr_val_str(cond_expr)))
|
||||
implies_str = "\n".join(implies_str_rows)
|
||||
|
||||
res = _lines("Symbol " +
|
||||
("(no name)" if sc.name is None else sc.name),
|
||||
"Type : " + TYPENAME[sc.type],
|
||||
@ -1711,9 +1736,16 @@ class Config(object):
|
||||
defaults_str,
|
||||
"Selects:",
|
||||
selects_str,
|
||||
"Implies:",
|
||||
implies_str,
|
||||
"Reverse (select-related) dependencies:",
|
||||
" (no reverse dependencies)" if sc.rev_dep == "n"
|
||||
else " " + self._expr_val_str(sc.rev_dep),
|
||||
" (no reverse dependencies)"
|
||||
if sc.rev_dep == "n"
|
||||
else " " + self._expr_val_str(sc.rev_dep),
|
||||
"Weak reverse (imply-related) dependencies:",
|
||||
" (no weak reverse dependencies)"
|
||||
if sc.weak_rev_dep == "n"
|
||||
else " " + self._expr_val_str(sc.weak_rev_dep),
|
||||
"Additional dependencies from enclosing menus "
|
||||
"and ifs:",
|
||||
additional_deps_str,
|
||||
@ -1735,11 +1767,10 @@ class Config(object):
|
||||
else:
|
||||
defaults_str_rows = []
|
||||
for sym, cond_expr in sc.orig_def_exprs:
|
||||
if cond_expr is None:
|
||||
defaults_str_rows.append(" {0}".format(sym.name))
|
||||
else:
|
||||
defaults_str_rows.append(" {0} if {1}".format(sym.name,
|
||||
self._expr_val_str(cond_expr)))
|
||||
defaults_str_rows.append(
|
||||
" {0}".format(sym.name) if cond_expr is None else
|
||||
" {0} if {1}".format(sym.name,
|
||||
self._expr_val_str(cond_expr)))
|
||||
defaults_str = "\n".join(defaults_str_rows)
|
||||
|
||||
# Build contained symbols string
|
||||
@ -1919,26 +1950,25 @@ class Symbol(Item):
|
||||
self.write_to_conf = (mode != "n")
|
||||
|
||||
if mode == "y":
|
||||
if choice.get_selection() is self:
|
||||
new_val = "y"
|
||||
else:
|
||||
new_val = "n"
|
||||
new_val = "y" if choice.get_selection() is self \
|
||||
else "n"
|
||||
elif mode == "m":
|
||||
if self.user_val == "m" or self.user_val == "y":
|
||||
new_val = "m"
|
||||
|
||||
else:
|
||||
# If the symbol is visible and has a user value, use that.
|
||||
# Otherwise, look at defaults.
|
||||
use_defaults = True
|
||||
# Otherwise, look at defaults and weak reverse dependencies
|
||||
# (implies).
|
||||
use_defaults_and_weak_rev_deps = True
|
||||
|
||||
if vis != "n":
|
||||
self.write_to_conf = True
|
||||
if self.user_val is not None:
|
||||
new_val = self.config._eval_min(self.user_val, vis)
|
||||
use_defaults = False
|
||||
use_defaults_and_weak_rev_deps = False
|
||||
|
||||
if use_defaults:
|
||||
if use_defaults_and_weak_rev_deps:
|
||||
for val_expr, cond_expr in self.def_exprs:
|
||||
cond_eval = self.config._eval_expr(cond_expr)
|
||||
if cond_eval != "n":
|
||||
@ -1947,14 +1977,25 @@ class Symbol(Item):
|
||||
cond_eval)
|
||||
break
|
||||
|
||||
weak_rev_dep_val = \
|
||||
self.config._eval_expr(self.weak_rev_dep)
|
||||
if weak_rev_dep_val != "n":
|
||||
self.write_to_conf = True
|
||||
new_val = self.config._eval_max(new_val,
|
||||
weak_rev_dep_val)
|
||||
|
||||
# Reverse (select-related) dependencies take precedence
|
||||
rev_dep_val = self.config._eval_expr(self.rev_dep)
|
||||
if rev_dep_val != "n":
|
||||
self.write_to_conf = True
|
||||
new_val = self.config._eval_max(new_val, rev_dep_val)
|
||||
|
||||
# Promote "m" to "y" for booleans
|
||||
if new_val == "m" and self.type == BOOL:
|
||||
# We need to promote "m" to "y" in two circumstances:
|
||||
# 1) If our type is boolean
|
||||
# 2) If our weak_rev_dep (from IMPLY) is "y"
|
||||
if new_val == "m" and \
|
||||
(self.type == BOOL or
|
||||
self.config._eval_expr(self.weak_rev_dep) == "y"):
|
||||
new_val = "y"
|
||||
|
||||
elif self.type == INT or self.type == HEX:
|
||||
@ -2189,6 +2230,13 @@ class Symbol(Item):
|
||||
get_referenced_symbols()."""
|
||||
return self.selected_syms
|
||||
|
||||
def get_implied_symbols(self):
|
||||
"""Returns the set() of all symbols X for which this symbol has an
|
||||
'imply X' or 'imply X if Y' (regardless of whether Y is satisfied or
|
||||
not). This is a subset of the symbols returned by
|
||||
get_referenced_symbols()."""
|
||||
return self.implied_syms
|
||||
|
||||
def set_user_value(self, v):
|
||||
"""Sets the user value of the symbol.
|
||||
|
||||
@ -2304,16 +2352,18 @@ class Symbol(Item):
|
||||
self.ranges = [] # 'range' properties (for int and hex)
|
||||
self.help = None # Help text
|
||||
self.rev_dep = "n" # Reverse (select-related) dependencies
|
||||
self.weak_rev_dep = "n" # Weak reverse (imply-related) dependencies
|
||||
self.config = None
|
||||
self.parent = None
|
||||
|
||||
self.user_val = None # Value set by user
|
||||
|
||||
# The prompt, default value and select conditions without any
|
||||
# The prompt, default value, select, and imply conditions without any
|
||||
# dependencies from menus and ifs propagated to them
|
||||
self.orig_prompts = []
|
||||
self.orig_def_exprs = []
|
||||
self.orig_selects = []
|
||||
self.orig_implies = []
|
||||
|
||||
# Dependencies inherited from containing menus and ifs
|
||||
self.deps_from_containing = None
|
||||
@ -2323,13 +2373,15 @@ class Symbol(Item):
|
||||
# The set of symbols selected by this symbol (see
|
||||
# get_selected_symbols())
|
||||
self.selected_syms = set()
|
||||
# The set of symbols implied by this symbol (see get_implied_symbols())
|
||||
self.implied_syms = set()
|
||||
# Like 'referenced_syms', but includes symbols from
|
||||
# dependencies inherited from enclosing menus and ifs
|
||||
self.all_referenced_syms = set()
|
||||
|
||||
# This records only dependencies specified with 'depends on'. Needed
|
||||
# when determining actual choice items (hrrrr...). See also
|
||||
# Choice._determine_actual_symbols().
|
||||
# This records only dependencies from enclosing ifs and menus together
|
||||
# with local 'depends on' dependencies. Needed when determining actual
|
||||
# choice items (hrrrr...). See Choice._determine_actual_symbols().
|
||||
self.menu_dep = None
|
||||
|
||||
# See Symbol.get_ref/def_locations().
|
||||
@ -2470,18 +2522,17 @@ class Symbol(Item):
|
||||
return
|
||||
|
||||
if self.type == BOOL or self.type == TRISTATE:
|
||||
if val == "y" or val == "m":
|
||||
append_fn("CONFIG_{0}={1}".format(self.name, val))
|
||||
else:
|
||||
append_fn("# CONFIG_{0} is not set".format(self.name))
|
||||
append_fn("{0}{1}={2}".format(self.config.config_prefix, self.name, val)
|
||||
if val == "y" or val == "m" else
|
||||
"# {0}{1} is not set".format(self.config.config_prefix, self.name))
|
||||
|
||||
elif self.type == INT or self.type == HEX:
|
||||
append_fn("CONFIG_{0}={1}".format(self.name, val))
|
||||
append_fn("{0}{1}={2}".format(self.config.config_prefix, self.name, val))
|
||||
|
||||
elif self.type == STRING:
|
||||
# Escape \ and "
|
||||
append_fn('CONFIG_{0}="{1}"'
|
||||
.format(self.name,
|
||||
append_fn('{0}{1}="{2}"'
|
||||
.format(self.config.config_prefix, self.name,
|
||||
val.replace("\\", "\\\\").replace('"', '\\"')))
|
||||
|
||||
else:
|
||||
@ -2635,7 +2686,7 @@ class Menu(Item):
|
||||
self.title = None
|
||||
self.dep_expr = None
|
||||
self.visible_if_expr = None
|
||||
self.block = None
|
||||
self.block = [] # List of contained items
|
||||
self.config = None
|
||||
self.parent = None
|
||||
|
||||
@ -2852,7 +2903,7 @@ class Choice(Item):
|
||||
self.prompts = []
|
||||
self.def_exprs = [] # 'default' properties
|
||||
self.help = None # Help text
|
||||
self.block = None # List of contained items
|
||||
self.block = [] # List of contained items
|
||||
self.config = None
|
||||
self.parent = None
|
||||
|
||||
@ -3177,7 +3228,13 @@ def _get_visibility(sc):
|
||||
vis = sc.config._eval_max(vis, cond_expr)
|
||||
|
||||
if isinstance(sc, Symbol) and sc.is_choice_sym:
|
||||
vis = sc.config._eval_min(vis, _get_visibility(sc.parent))
|
||||
if sc.type == TRISTATE and vis == "m" and \
|
||||
sc.parent.get_mode() == "y":
|
||||
# Choice symbols with visibility "m" are not visible if the
|
||||
# choice has mode "y"
|
||||
vis = "n"
|
||||
else:
|
||||
vis = sc.config._eval_min(vis, _get_visibility(sc.parent))
|
||||
|
||||
# Promote "m" to "y" if we're dealing with a non-tristate
|
||||
if vis == "m" and sc.type != TRISTATE:
|
||||
@ -3434,7 +3491,7 @@ _get_keyword = \
|
||||
"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,
|
||||
"imply": T_IMPLY, "range": T_RANGE, "option": T_OPTION,
|
||||
"imply" : T_IMPLY, "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
|
||||
@ -3455,10 +3512,6 @@ _initial_token_re_match = re.compile(r"[^\w]*(\w+)\s*").match
|
||||
# trailing whitespace as an optimization.
|
||||
_id_keyword_re_match = re.compile(r"\s*([\w./-]+)\s*").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
|
||||
|
||||
|
@ -1472,7 +1472,7 @@ def find_kconfig_rules(kconf, config, imply_config):
|
||||
"""
|
||||
sym = kconf.get_symbol(imply_config)
|
||||
if sym:
|
||||
for sel in sym.get_selected_symbols():
|
||||
for sel in sym.get_selected_symbols() | sym.get_implied_symbols():
|
||||
if sel.get_name() == config:
|
||||
return sym
|
||||
return None
|
||||
|
Loading…
Reference in New Issue
Block a user