minikconf: move command-line assignment out of the parser

KconfigParser.do_assignment() only exists to handle CONFIG_FOO=y/n
arguments from the command line; it is never invoked while parsing
a Kconfig source file.  Because main() called it on a parser that
had never been through parse_file(), a failing CONFIG_ check would
raise a KconfigParserError whose __init__ and location() touch
fields of "self" that do not exist yet.  The regex in main()
currently shields this, but it is fragile.

Move the prefix-stripping assignment to KconfigData as
do_cmdline_assignment(), simplify KconfigParser.parse() to accept
an existing KconfigData, and call it from main() so the parser is
only used for actual file parsing.

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini
2026-04-24 10:08:34 +02:00
parent dfec6f920e
commit e07ed5548e

View File

@@ -278,6 +278,10 @@ def do_var(self, var):
def do_assignment(self, var, val):
self.clauses.append(KconfigData.AssignmentClause(var, val))
def do_cmdline_assignment(self, var, val):
assert var.startswith("CONFIG_")
self.do_assignment(self.do_var(var[7:]), val)
def do_default(self, var, val, cond=None):
val = self.value_mangler(val)
self.clauses.append(KconfigData.DefaultClause(var, val, cond))
@@ -338,11 +342,8 @@ def __str__(self):
class KconfigParser:
@classmethod
def parse(cls, fp, mode=None):
data = KconfigData(mode or defconfig)
parser = cls(data)
parser.parse_file(fp)
return data
def parse(cls, fp, data):
cls(data).parse_file(fp)
def __init__(self, data):
self.data = data
@@ -361,14 +362,6 @@ def parse_file(self, fp):
self.get_token()
self.parse_config()
def do_assignment(self, var, val):
if not var.startswith("CONFIG_"):
raise KconfigParserError(
self, "assigned variable should start with CONFIG_"
)
var = self.data.do_var(var[7:])
self.data.do_assignment(var, val)
# file management -----
def error_path(self):
@@ -688,18 +681,16 @@ def scan_token(self):
sys.exit(1)
data = KconfigData(mode)
parser = KconfigParser(data)
external_vars = set()
for arg in argv[3:]:
m = re.match(r'^(CONFIG_[A-Z0-9_]+)=([yn]?)$', arg)
if m is not None:
name, value = m.groups()
parser.do_assignment(name, value == 'y')
data.do_cmdline_assignment(name, value == 'y')
external_vars.add(name[7:])
else:
fp = open(arg, 'rt', encoding='utf-8')
parser.parse_file(fp)
fp.close()
with open(arg, 'rt', encoding='utf-8') as fp:
KconfigParser.parse(fp, data)
config = data.compute_config()
for key in sorted(config.keys()):