summaryrefslogtreecommitdiff
path: root/kconfiglib.py
diff options
context:
space:
mode:
authorUlf Magnusson <ulfalizer@gmail.com>2017-09-29 17:30:34 +0200
committerUlf Magnusson <ulfalizer@gmail.com>2017-09-29 20:07:39 +0200
commit250b370cb5a1d40d7c0e2a4df7275964c1d24fea (patch)
treea1fcf7f13f22232940718bd80e349f6cc752fa7b /kconfiglib.py
parentc54db8e7c9cde50a2b13cebe256cfd907b45d762 (diff)
Refactor load_config() and fix minor issues
Minor fixes: - Even with print_undef_assign=True, "# CONFIG_NOT_DEFINED is not set" would not generate a warning. - Change the warning when a variable is set more than once in the .config to be a bit more explicit. - Only de-quote and unescape assignments to string variables, which is nicer and matches the C implementation.
Diffstat (limited to 'kconfiglib.py')
-rw-r--r--kconfiglib.py117
1 files changed, 66 insertions, 51 deletions
diff --git a/kconfiglib.py b/kconfiglib.py
index 25fedd7..e1f9d29 100644
--- a/kconfiglib.py
+++ b/kconfiglib.py
@@ -408,24 +408,16 @@ class Config(object):
self._config_filename = filename
- # Small optimization
- set_re_match = self._set_re.match
- unset_re_match = self._unset_re.match
-
#
# Read header
#
- def is_header_line(line):
- return line is not None and line.startswith("#") and \
- not unset_re_match(line)
-
- if not is_header_line(line_feeder.peek_next()):
+ if not self._is_header_line(line_feeder.peek_next()):
self._config_header = None
else:
# Kinda inefficient, but this is an unlikely hotspot
self._config_header = ""
- while is_header_line(line_feeder.peek_next()):
+ while self._is_header_line(line_feeder.peek_next()):
self._config_header += line_feeder.get_next()[1:]
# Makes c.write_config(".config", c.get_config_header()) preserve
# the header exactly. We also handle weird cases like a .config
@@ -439,18 +431,16 @@ class Config(object):
# Read assignments. Hotspot for some workloads.
#
- def warn_override(filename, linenr, name, old_user_val, new_user_val):
- self._warn('overriding the value of {}. '
- 'Old value: "{}", new value: "{}".'
- .format(name, old_user_val, new_user_val),
- filename, linenr)
-
if replace:
# This invalidates all symbols as a side effect
self.unset_user_values()
else:
self._invalidate_all()
+ # Small optimization
+ set_re_match = self._set_re.match
+ unset_re_match = self._unset_re.match
+
while 1:
line = line_feeder.get_next()
if line is None:
@@ -461,49 +451,57 @@ class Config(object):
set_match = set_re_match(line)
if set_match:
name, val = set_match.groups()
+ if name not in self._syms:
+ self._warn_undef_assign_load(
+ name, val, line_feeder.filename, line_feeder.linenr)
+ continue
+
+ sym = self._syms[name]
- if val.startswith('"'):
+ if sym._type == STRING and val.startswith('"'):
if len(val) < 2 or val[-1] != '"':
- _parse_error(line, "malformed string literal",
- line_feeder.filename, line_feeder.linenr)
+ self._warn("malformed string literal",
+ line_feeder.filename,
+ line_feeder.linenr)
+ continue
# Strip quotes and remove escapings. The unescaping
# procedure should be safe since " can only appear as \"
# inside the string.
- val = val[1:-1].replace('\\"', '"').replace("\\\\", "\\")
-
- if name in self._syms:
- sym = self._syms[name]
- if sym._user_val is not None:
- warn_override(line_feeder.filename, line_feeder.linenr,
- name, sym._user_val, val)
-
- if sym._is_choice_sym:
- user_mode = sym._parent._user_mode
- if user_mode is not None and user_mode != val:
- self._warn("assignment to {} changes mode of "
- 'containing choice from "{}" to "{}".'
- .format(name, val, user_mode),
- line_feeder.filename,
- line_feeder.linenr)
-
- sym._set_user_value_no_invalidate(val, True)
- else:
- self._warn_undef_assign(
- 'attempt to assign the value "{}" to the undefined '
- "symbol {}".format(val, name),
- line_feeder.filename, line_feeder.linenr)
+ val = val[1:-1].replace('\\"', '"') \
+ .replace("\\\\", "\\")
+
+ if sym._is_choice_sym:
+ user_mode = sym._parent._user_mode
+ if user_mode is not None and user_mode != val:
+ self._warn("assignment to {} changes mode of "
+ 'containing choice from "{}" to "{}".'
+ .format(name, val, user_mode),
+ line_feeder.filename,
+ line_feeder.linenr)
+
else:
unset_match = unset_re_match(line)
- if unset_match:
- name = unset_match.group(1)
- if name in self._syms:
- sym = self._syms[name]
- if sym._user_val is not None:
- warn_override(line_feeder.filename,
- line_feeder.linenr,
- name, sym._user_val, "n")
+ if not unset_match:
+ continue
+
+ name = unset_match.group(1)
+ if name not in self._syms:
+ self._warn_undef_assign_load(
+ name, val, line_feeder.filename, line_feeder.linenr)
+ continue
+
+ sym = self._syms[name]
+ val = "n"
+
+ # Done parsing the assignment. Set the value.
- sym._set_user_value_no_invalidate("n", True)
+ if sym._user_val is not None:
+ self._warn('{} set more than once. Old value: "{}", new '
+ 'value: "{}".'
+ .format(name, sym._user_val, val),
+ line_feeder.filename, line_feeder.linenr)
+
+ sym._set_user_value_no_invalidate(val, True)
def write_config(self, filename, header=None):
"""Writes out symbol values in the familiar .config format.
@@ -1910,6 +1908,17 @@ class Config(object):
additional_deps_str,
"Locations: " + locations_str)
+ #
+ # Warnings and misc.
+ #
+
+ def _is_header_line(self, line):
+ """Returns True is the line could be part of the initial header in a
+ .config file (which is really just another comment, but can be handy
+ for storing metadata."""
+ return line is not None and line.startswith("#") and \
+ not self._unset_re.match(line)
+
def _warn(self, msg, filename=None, linenr=None):
"""For printing general warnings."""
if self._print_warnings:
@@ -1922,6 +1931,12 @@ class Config(object):
if self._print_undef_assign:
_stderr_msg("warning: " + msg, filename, linenr)
+ def _warn_undef_assign_load(self, name, val, filename, linenr):
+ """Special version for load_config()."""
+ self._warn_undef_assign(
+ 'attempt to assign the value "{}" to the undefined symbol {}' \
+ .format(val, name), filename, linenr)
+
class Item(object):
"""Base class for symbols and other Kconfig constructs. Subclasses are