blob: 7a47be9153f4e9bf69c2468c28c3befb31e837a6 [file] [log] [blame]
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001#
Masahiro Yamada91708182014-09-17 13:37:45 +09002# SPDX-License-Identifier: ISC
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003#
4# Author: Ulf Magnusson
5# https://github.com/ulfalizer/Kconfiglib
6
7# This is Kconfiglib, a Python library for scripting, debugging, and extracting
8# information from Kconfig-based configuration systems. To view the
9# documentation, run
10#
11# $ pydoc kconfiglib
12#
13# or, if you prefer HTML,
14#
15# $ pydoc -w kconfiglib
16#
17# The examples/ subdirectory contains examples, to be run with e.g.
18#
19# $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
20#
21# Look in testsuite.py for the test suite.
22
23"""
24Kconfiglib is a Python library for scripting and extracting information from
25Kconfig-based configuration systems. Features include the following:
26
27 - Symbol values and properties can be looked up and values assigned
28 programmatically.
29 - .config files can be read and written.
30 - Expressions can be evaluated in the context of a Kconfig configuration.
31 - Relations between symbols can be quickly determined, such as finding all
32 symbols that reference a particular symbol.
33 - Highly compatible with the scripts/kconfig/*conf utilities. The test suite
34 automatically compares outputs between Kconfiglib and the C implementation
35 for a large number of cases.
36
37For the Linux kernel, scripts are run using
38
Ulf Magnusson90c36d82015-08-13 19:55:40 +020039 $ make scriptconfig [ARCH=<arch>] SCRIPT=<path to script> [SCRIPT_ARG=<arg>]
Masahiro Yamadaf219e012014-09-01 19:57:37 +090040
Ulf Magnusson90c36d82015-08-13 19:55:40 +020041Using the 'scriptconfig' target ensures that required environment variables
42(SRCARCH, ARCH, srctree, KERNELVERSION, etc.) are set up correctly.
Masahiro Yamadaf219e012014-09-01 19:57:37 +090043
Ulf Magnusson90c36d82015-08-13 19:55:40 +020044Scripts receive the name of the Kconfig file to load in sys.argv[1]. As of
45Linux 4.1.0-rc5, this is always "Kconfig" from the kernel top-level directory.
46If an argument is provided with SCRIPT_ARG, it appears as sys.argv[2].
Masahiro Yamadaf219e012014-09-01 19:57:37 +090047
48To get an interactive Python prompt with Kconfiglib preloaded and a Config
Ulf Magnusson90c36d82015-08-13 19:55:40 +020049object 'c' created, run
Masahiro Yamadaf219e012014-09-01 19:57:37 +090050
Ulf Magnusson90c36d82015-08-13 19:55:40 +020051 $ make iscriptconfig [ARCH=<arch>]
Masahiro Yamadaf219e012014-09-01 19:57:37 +090052
Ulf Magnusson90c36d82015-08-13 19:55:40 +020053Kconfiglib supports both Python 2 and Python 3. For (i)scriptconfig, the Python
54interpreter to use can be passed in PYTHONCMD, which defaults to 'python'. PyPy
55works well too, and might give a nice speedup for long-running jobs.
Masahiro Yamadaf219e012014-09-01 19:57:37 +090056
Ulf Magnusson90c36d82015-08-13 19:55:40 +020057The examples/ directory contains short example scripts, which can be run with
58e.g.
Masahiro Yamadaf219e012014-09-01 19:57:37 +090059
60 $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
61
62or
63
Ulf Magnusson90c36d82015-08-13 19:55:40 +020064 $ make scriptconfig SCRIPT=Kconfiglib/examples/help_grep.py SCRIPT_ARG=kernel
Masahiro Yamadaf219e012014-09-01 19:57:37 +090065
Ulf Magnusson90c36d82015-08-13 19:55:40 +020066testsuite.py contains the test suite. See the top of the script for how to run
67it.
Masahiro Yamadaf219e012014-09-01 19:57:37 +090068
69Credits: Written by Ulf "Ulfalizer" Magnusson
70
Ulf Magnusson90c36d82015-08-13 19:55:40 +020071Send bug reports, suggestions and other feedback to ulfalizer a.t Google's
72email service. Don't wrestle with internal APIs. Tell me what you need and I
73might add it in a safe way as a client API instead."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +090074
75import os
76import re
Masahiro Yamadaf219e012014-09-01 19:57:37 +090077import sys
78
Ulf Magnusson90c36d82015-08-13 19:55:40 +020079# File layout:
80#
81# Public classes
82# Public functions
83# Internal classes
84# Internal functions
85# Internal global constants
86
87# Line length: 79 columns
88
89#
90# Public classes
91#
92
93class Config(object):
Masahiro Yamadaf219e012014-09-01 19:57:37 +090094
95 """Represents a Kconfig configuration, e.g. for i386 or ARM. This is the
96 set of symbols and other items appearing in the configuration together with
97 their values. Creating any number of Config objects -- including for
98 different architectures -- is safe; Kconfiglib has no global state."""
99
100 #
101 # Public interface
102 #
103
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200104 def __init__(self, filename="Kconfig", base_dir=None, print_warnings=True,
105 print_undef_assign=False):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900106 """Creates a new Config object, representing a Kconfig configuration.
107 Raises Kconfig_Syntax_Error on syntax errors.
108
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200109 filename (default: "Kconfig"): The base Kconfig file of the
110 configuration. For the Linux kernel, you'll probably want "Kconfig"
111 from the top-level directory, as environment variables will make
112 sure the right Kconfig is included from there
113 (arch/<architecture>/Kconfig). If you are using Kconfiglib via 'make
114 scriptconfig', the filename of the base base Kconfig file will be in
115 sys.argv[1].
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900116
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200117 base_dir (default: None): The base directory relative to which 'source'
118 statements within Kconfig files will work. For the Linux kernel this
119 should be the top-level directory of the kernel tree. $-references
120 to existing environment variables will be expanded.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900121
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200122 If None (the default), the environment variable 'srctree' will be
123 used if set, and the current directory otherwise. 'srctree' is set
124 by the Linux makefiles to the top-level kernel directory. A default
125 of "." would not work with an alternative build directory.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900126
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200127 print_warnings (default: True): Set to True if warnings related to this
128 configuration should be printed to stderr. This can be changed later
129 with Config.set_print_warnings(). It is provided as a constructor
130 argument since warnings might be generated during parsing.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900131
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200132 print_undef_assign (default: False): Set to True if informational
133 messages related to assignments to undefined symbols should be
134 printed to stderr for this configuration. Can be changed later with
135 Config.set_print_undef_assign()."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900136
137 # The set of all symbols, indexed by name (a string)
138 self.syms = {}
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200139 # Python 2/3 compatibility hack. This is the only one needed.
140 if sys.version_info[0] >= 3:
141 self.syms_iter = self.syms.values
142 else:
143 self.syms_iter = self.syms.itervalues
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900144
145 # The set of all defined symbols in the configuration in the order they
146 # appear in the Kconfig files. This excludes the special symbols n, m,
147 # and y as well as symbols that are referenced but never defined.
148 self.kconfig_syms = []
149
150 # The set of all named choices (yes, choices can have names), indexed
151 # by name (a string)
152 self.named_choices = {}
153
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200154 # Lists containing all choices, menus and comments in the configuration
155 self.choices = []
156 self.menus = []
157 self.comments = []
158
159 def register_special_symbol(type_, name, val):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900160 sym = Symbol()
161 sym.is_special_ = True
162 sym.is_defined_ = True
163 sym.config = self
164 sym.name = name
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200165 sym.type = type_
166 sym.cached_val = val
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900167 self.syms[name] = sym
168 return sym
169
170 # The special symbols n, m and y, used as shorthand for "n", "m" and
171 # "y"
172 self.n = register_special_symbol(TRISTATE, "n", "n")
173 self.m = register_special_symbol(TRISTATE, "m", "m")
174 self.y = register_special_symbol(TRISTATE, "y", "y")
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900175 # DEFCONFIG_LIST uses this
176 register_special_symbol(STRING, "UNAME_RELEASE", os.uname()[2])
177
178 # The symbol with "option defconfig_list" set, containing a list of
179 # default .config files
180 self.defconfig_sym = None
181
182 # See Symbol.get_(src)arch()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200183 self.arch = os.environ.get("ARCH")
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900184 self.srcarch = os.environ.get("SRCARCH")
185
186 # See Config.__init__(). We need this for get_defconfig_filename().
187 self.srctree = os.environ.get("srctree")
188 if self.srctree is None:
189 self.srctree = "."
190
191 self.filename = filename
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200192 if base_dir is None:
193 self.base_dir = self.srctree
194 else:
195 self.base_dir = os.path.expandvars(base_dir)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900196
197 # The 'mainmenu' text
198 self.mainmenu_text = None
199
200 # The filename of the most recently loaded .config file
201 self.config_filename = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900202 # The textual header of the most recently loaded .config, uncommented
203 self.config_header = None
204
205 self.print_warnings = print_warnings
206 self.print_undef_assign = print_undef_assign
207
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900208 # For parsing routines that stop when finding a line belonging to a
209 # different construct, these holds that line and the tokenized version
210 # of that line. The purpose is to avoid having to re-tokenize the line,
211 # which is inefficient and causes problems when recording references to
212 # symbols.
213 self.end_line = None
214 self.end_line_tokens = None
215
216 # See the comment in _parse_expr().
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200217 self._cur_item = None
218 self._line = None
219 self._filename = None
220 self._linenr = None
221 self._transform_m = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900222
223 # Parse the Kconfig files
224 self.top_block = self._parse_file(filename, None, None, None)
225
226 # Build Symbol.dep for all symbols
227 self._build_dep()
228
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900229 def get_arch(self):
230 """Returns the value the environment variable ARCH had at the time the
231 Config instance was created, or None if ARCH was not set. For the
232 kernel, this corresponds to the architecture being built for, with
233 values such as "i386" or "mips"."""
234 return self.arch
235
236 def get_srcarch(self):
237 """Returns the value the environment variable SRCARCH had at the time
238 the Config instance was created, or None if SRCARCH was not set. For
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200239 the kernel, this corresponds to the particular arch/ subdirectory
240 containing architecture-specific code."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900241 return self.srcarch
242
243 def get_srctree(self):
244 """Returns the value the environment variable srctree had at the time
245 the Config instance was created, or None if srctree was not defined.
246 This variable points to the source directory and is used when building
247 in a separate directory."""
248 return self.srctree
249
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200250 def get_base_dir(self):
251 """Returns the base directory relative to which 'source' statements
252 will work, passed as an argument to Config.__init__()."""
253 return self.base_dir
254
255 def get_kconfig_filename(self):
256 """Returns the name of the (base) kconfig file this configuration was
257 loaded from."""
258 return self.filename
259
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900260 def get_config_filename(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200261 """Returns the filename of the most recently loaded configuration file,
262 or None if no configuration has been loaded."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900263 return self.config_filename
264
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200265 def get_config_header(self):
266 """Returns the (uncommented) textual header of the .config file most
267 recently loaded with load_config(). Returns None if no .config file has
268 been loaded or if the most recently loaded .config file has no header.
269 The header consists of all lines up to but not including the first line
270 that either
271
272 1. Does not start with "#"
273 2. Has the form "# CONFIG_FOO is not set."
274 """
275 return self.config_header
276
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900277 def get_mainmenu_text(self):
278 """Returns the text of the 'mainmenu' statement (with $-references to
279 symbols replaced by symbol values), or None if the configuration has no
280 'mainmenu' statement."""
281 return None if self.mainmenu_text is None else \
282 self._expand_sym_refs(self.mainmenu_text)
283
284 def get_defconfig_filename(self):
285 """Returns the name of the defconfig file, which is the first existing
286 file in the list given in a symbol having 'option defconfig_list' set.
287 $-references to symbols will be expanded ("$FOO bar" -> "foo bar" if
288 FOO has the value "foo"). Returns None in case of no defconfig file.
289 Setting 'option defconfig_list' on multiple symbols currently results
290 in undefined behavior.
291
292 If the environment variable 'srctree' was set when the Config was
293 created, get_defconfig_filename() will first look relative to that
294 directory before looking in the current directory; see
Masahiro Yamada9d01b782015-05-27 11:39:22 +0900295 Config.__init__().
296
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200297 WARNING: A wart here is that scripts/kconfig/Makefile sometimes uses
298 the --defconfig=<defconfig> option when calling the C implementation of
299 e.g. 'make defconfig'. This option overrides the 'option
300 defconfig_list' symbol, meaning the result from
301 get_defconfig_filename() might not match what 'make defconfig' would
302 use. That probably ought to be worked around somehow, so that this
303 function always gives the "expected" result."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900304 if self.defconfig_sym is None:
305 return None
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200306 for filename, cond_expr in self.defconfig_sym.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900307 if self._eval_expr(cond_expr) == "y":
308 filename = self._expand_sym_refs(filename)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900309 # We first look in $srctree. os.path.join() won't work here as
310 # an absolute path in filename would override $srctree.
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200311 srctree_filename = os.path.normpath(self.srctree + "/" +
312 filename)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900313 if os.path.exists(srctree_filename):
314 return srctree_filename
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900315 if os.path.exists(filename):
316 return filename
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900317 return None
318
319 def get_symbol(self, name):
320 """Returns the symbol with name 'name', or None if no such symbol
321 appears in the configuration. An alternative shorthand is conf[name],
322 where conf is a Config instance, though that will instead raise
323 KeyError if the symbol does not exist."""
324 return self.syms.get(name)
325
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200326 def __getitem__(self, name):
327 """Returns the symbol with name 'name'. Raises KeyError if the symbol
328 does not appear in the configuration."""
329 return self.syms[name]
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900330
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200331 def get_symbols(self, all_symbols=True):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900332 """Returns a list of symbols from the configuration. An alternative for
333 iterating over all defined symbols (in the order of definition) is
334
335 for sym in config:
336 ...
337
338 which relies on Config implementing __iter__() and is equivalent to
339
340 for sym in config.get_symbols(False):
341 ...
342
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200343 all_symbols (default: True): If True, all symbols -- including special
344 and undefined symbols -- will be included in the result, in an
345 undefined order. If False, only symbols actually defined and not
346 merely referred to in the configuration will be included in the
347 result, and will appear in the order that they are defined within
348 the Kconfig configuration files."""
349 return list(self.syms.values()) if all_symbols else self.kconfig_syms
350
351 def __iter__(self):
352 """Convenience function for iterating over the set of all defined
353 symbols in the configuration, used like
354
355 for sym in conf:
356 ...
357
358 The iteration happens in the order of definition within the Kconfig
359 configuration files. Symbols only referred to but not defined will not
360 be included, nor will the special symbols n, m, and y. If you want to
361 include such symbols as well, see config.get_symbols()."""
362 return iter(self.kconfig_syms)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900363
364 def get_choices(self):
365 """Returns a list containing all choice statements in the
366 configuration, in the order they appear in the Kconfig files."""
367 return self.choices
368
369 def get_menus(self):
370 """Returns a list containing all menus in the configuration, in the
371 order they appear in the Kconfig files."""
372 return self.menus
373
374 def get_comments(self):
375 """Returns a list containing all comments in the configuration, in the
376 order they appear in the Kconfig files."""
377 return self.comments
378
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200379 def get_top_level_items(self):
380 """Returns a list containing the items (symbols, menus, choices, and
381 comments) at the top level of the configuration -- that is, all items
382 that do not appear within a menu or choice. The items appear in the
383 same order as within the configuration."""
384 return self.top_block
385
386 def load_config(self, filename, replace=True):
387 """Loads symbol values from a file in the familiar .config format.
388 Equivalent to calling Symbol.set_user_value() to set each of the
389 values.
390
391 "# CONFIG_FOO is not set" within a .config file is treated specially
392 and sets the user value of FOO to 'n'. The C implementation works the
393 same way.
394
395 filename: The .config file to load. $-references to existing
396 environment variables will be expanded. For scripts to work even when
397 an alternative build directory is used with the Linux kernel, you
398 need to refer to the top-level kernel directory with "$srctree".
399
400 replace (default: True): True if the configuration should replace the
401 old configuration; False if it should add to it."""
402
403 # Put this first so that a missing file doesn't screw up our state
404 filename = os.path.expandvars(filename)
405 line_feeder = _FileFeed(filename)
406
407 self.config_filename = filename
408
409 #
410 # Read header
411 #
412
413 def is_header_line(line):
414 return line is not None and line.startswith("#") and \
415 not _unset_re_match(line)
416
417 self.config_header = None
418
419 line = line_feeder.peek_next()
420 if is_header_line(line):
421 self.config_header = ""
422 while is_header_line(line_feeder.peek_next()):
423 self.config_header += line_feeder.get_next()[1:]
424 # Remove trailing newline
425 if self.config_header.endswith("\n"):
426 self.config_header = self.config_header[:-1]
427
428 #
429 # Read assignments. Hotspot for some workloads.
430 #
431
432 def warn_override(filename, linenr, name, old_user_val, new_user_val):
433 self._warn('overriding the value of {0}. '
434 'Old value: "{1}", new value: "{2}".'
435 .format(name, old_user_val, new_user_val),
436 filename, linenr)
437
438 # Invalidate everything to keep things simple. It might be possible to
439 # improve performance for the case where multiple configurations are
440 # loaded by only invalidating a symbol (and its dependent symbols) if
441 # the new user value differs from the old. One complication would be
442 # that symbols not mentioned in the .config must lose their user value
443 # when replace = True, which is the usual case.
444 if replace:
445 self.unset_user_values()
446 else:
447 self._invalidate_all()
448
449 while 1:
450 line = line_feeder.get_next()
451 if line is None:
452 return
453
454 line = line.rstrip()
455
456 set_match = _set_re_match(line)
457 if set_match:
458 name, val = set_match.groups()
459
460 if val.startswith('"'):
461 if len(val) < 2 or val[-1] != '"':
462 _parse_error(line, "malformed string literal",
463 line_feeder.filename, line_feeder.linenr)
464 # Strip quotes and remove escapings. The unescaping
465 # procedure should be safe since " can only appear as \"
466 # inside the string.
467 val = val[1:-1].replace('\\"', '"').replace("\\\\", "\\")
468
469 if name in self.syms:
470 sym = self.syms[name]
471 if sym.user_val is not None:
472 warn_override(line_feeder.filename, line_feeder.linenr,
473 name, sym.user_val, val)
474
475 if sym.is_choice_sym:
476 user_mode = sym.parent.user_mode
477 if user_mode is not None and user_mode != val:
478 self._warn("assignment to {0} changes mode of "
479 'containing choice from "{1}" to "{2}".'
480 .format(name, val, user_mode),
481 line_feeder.filename,
482 line_feeder.linenr)
483
484 sym._set_user_value_no_invalidate(val, True)
485 else:
486 if self.print_undef_assign:
487 _stderr_msg('note: attempt to assign the value "{0}" '
488 "to the undefined symbol {1}."
489 .format(val, name),
490 line_feeder.filename, line_feeder.linenr)
491 else:
492 unset_match = _unset_re_match(line)
493 if unset_match:
494 name = unset_match.group(1)
495 if name in self.syms:
496 sym = self.syms[name]
497 if sym.user_val is not None:
498 warn_override(line_feeder.filename,
499 line_feeder.linenr,
500 name, sym.user_val, "n")
501
502 sym._set_user_value_no_invalidate("n", True)
503
504 def write_config(self, filename, header=None):
505 """Writes out symbol values in the familiar .config format.
506
507 Kconfiglib makes sure the format matches what the C implementation
508 would generate, down to whitespace. This eases testing.
509
510 filename: The filename under which to save the configuration.
511
512 header (default: None): A textual header that will appear at the
513 beginning of the file, with each line commented out automatically.
514 None means no header."""
515
516 for sym in self.syms_iter():
517 sym.already_written = False
518
519 with open(filename, "w") as f:
520 # Write header
521 if header is not None:
522 f.write(_comment(header))
523 f.write("\n")
524
525 # Build and write configuration
526 conf_strings = []
527 _make_block_conf(self.top_block, conf_strings.append)
528 f.write("\n".join(conf_strings))
529 f.write("\n")
530
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900531 def eval(self, s):
532 """Returns the value of the expression 's' -- where 's' is represented
533 as a string -- in the context of the configuration. Raises
534 Kconfig_Syntax_Error if syntax errors are detected in 's'.
535
536 For example, if FOO and BAR are tristate symbols at least one of which
537 has the value "y", then config.eval("y && (FOO || BAR)") => "y"
538
Masahiro Yamada9d01b782015-05-27 11:39:22 +0900539 This function always yields a tristate value. To get the value of
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900540 non-bool, non-tristate symbols, use Symbol.get_value().
541
542 The result of this function is consistent with how evaluation works for
543 conditional expressions in the configuration as well as in the C
544 implementation. "m" and m are rewritten as '"m" && MODULES' and 'm &&
545 MODULES', respectively, and a result of "m" will get promoted to "y" if
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200546 we're running without modules.
547
548 Syntax checking is somewhat lax, partly to be compatible with lax
549 parsing in the C implementation."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900550 return self._eval_expr(self._parse_expr(self._tokenize(s, True), # Feed
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200551 None, # Current symbol/choice
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900552 s)) # line
553
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200554 def unset_user_values(self):
555 """Resets the values of all symbols, as if Config.load_config() or
556 Symbol.set_user_value() had never been called."""
557 for sym in self.syms_iter():
558 sym._unset_user_value_no_recursive_invalidate()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900559
560 def set_print_warnings(self, print_warnings):
561 """Determines whether warnings related to this configuration (for
562 things like attempting to assign illegal values to symbols with
563 Symbol.set_user_value()) should be printed to stderr.
564
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200565 print_warnings: True if warnings should be printed."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900566 self.print_warnings = print_warnings
567
568 def set_print_undef_assign(self, print_undef_assign):
569 """Determines whether informational messages related to assignments to
570 undefined symbols should be printed to stderr for this configuration.
571
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200572 print_undef_assign: If True, such messages will be printed."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900573 self.print_undef_assign = print_undef_assign
574
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900575 def __str__(self):
576 """Returns a string containing various information about the Config."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200577 return _lines("Configuration",
578 "File : " +
579 self.filename,
580 "Base directory : " +
581 self.base_dir,
582 "Value of $ARCH at creation time : " +
583 ("(not set)" if self.arch is None else self.arch),
584 "Value of $SRCARCH at creation time : " +
585 ("(not set)" if self.srcarch is None else
586 self.srcarch),
587 "Source tree (derived from $srctree;",
588 "defaults to '.' if $srctree isn't set) : " +
589 self.srctree,
590 "Most recently loaded .config : " +
591 ("(no .config loaded)"
592 if self.config_filename is None else
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900593 self.config_filename),
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200594 "Print warnings : " +
595 BOOL_STR[self.print_warnings],
596 "Print assignments to undefined symbols : " +
597 BOOL_STR[self.print_undef_assign])
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900598
599 #
600 # Private methods
601 #
602
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900603 #
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200604 # Kconfig parsing
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900605 #
606
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200607 def _parse_file(self, filename, parent, deps, visible_if_deps, res=None):
608 """Parses the Kconfig file 'filename'. Returns a list with the Items in
609 the file. See _parse_block() for the meaning of the parameters."""
610 return self._parse_block(_FileFeed(filename), None, parent, deps,
611 visible_if_deps, res)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900612
613 def _parse_block(self, line_feeder, end_marker, parent, deps,
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200614 visible_if_deps, res=None):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900615 """Parses a block, which is the contents of either a file or an if,
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200616 menu, or choice statement. Returns a list with the Items in the block.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900617
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200618 line_feeder: A _FileFeed instance feeding lines from a file. The
619 Kconfig language is line-based in practice.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900620
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200621 end_marker: The token that ends the block, e.g. T_ENDIF ("endif") for
622 ifs. None for files.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900623
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200624 parent: The enclosing menu or choice, or None if we're at the top
625 level.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900626
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200627 deps: Dependencies from enclosing menus, choices and ifs.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900628
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200629 visible_if_deps (default: None): 'visible if' dependencies from
630 enclosing menus.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900631
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200632 res (default: None): The list to add items to. If None, a new list is
633 created to hold the items."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900634
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200635 block = [] if res is None else res
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900636
637 while 1:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900638 # Do we already have a tokenized line that we determined wasn't
639 # part of whatever we were parsing earlier? See comment in
640 # Config.__init__().
641 if self.end_line is not None:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900642 line = self.end_line
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200643 tokens = self.end_line_tokens
644 tokens.unget_all()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900645
646 self.end_line = None
647 self.end_line_tokens = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900648 else:
649 line = line_feeder.get_next()
650 if line is None:
651 if end_marker is not None:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200652 raise Kconfig_Syntax_Error("Unexpected end of file {0}"
653 .format(line_feeder.filename))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900654 return block
655
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200656 tokens = self._tokenize(line, False, line_feeder.filename,
657 line_feeder.linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900658
659 t0 = tokens.get_next()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200660 if t0 is None:
661 continue
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900662
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200663 # Cases are ordered roughly by frequency, which speeds things up a
664 # bit
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900665
666 if t0 == T_CONFIG or t0 == T_MENUCONFIG:
667 # The tokenizer will automatically allocate a new Symbol object
668 # for any new names it encounters, so we don't need to worry
669 # about that here.
670 sym = tokens.get_next()
671
672 # Symbols defined in multiple places get the parent of their
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200673 # first definition. However, for symbols whose parents are
674 # choice statements, the choice statement takes precedence.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900675 if not sym.is_defined_ or isinstance(parent, Choice):
676 sym.parent = parent
677
678 sym.is_defined_ = True
679
680 self.kconfig_syms.append(sym)
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200681 block.append(sym)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900682
683 self._parse_properties(line_feeder, sym, deps, visible_if_deps)
684
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200685 elif t0 == T_SOURCE:
686 kconfig_file = tokens.get_next()
687 exp_kconfig_file = self._expand_sym_refs(kconfig_file)
688 f = os.path.join(self.base_dir, exp_kconfig_file)
689 if not os.path.exists(f):
690 raise IOError('{0}:{1}: sourced file "{2}" (expands to '
691 '"{3}") not found. Perhaps base_dir '
692 '(argument to Config.__init__(), currently '
693 '"{4}") is set to the wrong value.'
694 .format(line_feeder.filename,
695 line_feeder.linenr,
696 kconfig_file, exp_kconfig_file,
697 self.base_dir))
698 # Add items to the same block
699 self._parse_file(f, parent, deps, visible_if_deps, block)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900700
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200701 elif t0 == end_marker:
702 # We have reached the end of the block
703 return block
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900704
705 elif t0 == T_IF:
706 # If statements are treated as syntactic sugar for adding
707 # dependencies to enclosed items and do not have an explicit
708 # object representation.
709
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200710 dep_expr = self._parse_expr(tokens, None, line,
711 line_feeder.filename,
712 line_feeder.linenr)
713 # Add items to the same block
714 self._parse_block(line_feeder, T_ENDIF, parent,
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900715 _make_and(dep_expr, deps),
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200716 visible_if_deps, block)
717
718 elif t0 == T_COMMENT:
719 comment = Comment()
720
721 comment.config = self
722 comment.parent = parent
723 comment.filename = line_feeder.filename
724 comment.linenr = line_feeder.linenr
725 comment.text = tokens.get_next()
726
727 self.comments.append(comment)
728 block.append(comment)
729
730 self._parse_properties(line_feeder, comment, deps,
731 visible_if_deps)
732
733 elif t0 == T_MENU:
734 menu = Menu()
735
736 menu.config = self
737 menu.parent = parent
738 menu.filename = line_feeder.filename
739 menu.linenr = line_feeder.linenr
740 menu.title = tokens.get_next()
741
742 self.menus.append(menu)
743 block.append(menu)
744
745 # Parse properties and contents
746 self._parse_properties(line_feeder, menu, deps,
747 visible_if_deps)
748 menu.block = self._parse_block(line_feeder, T_ENDMENU, menu,
749 menu.dep_expr,
750 _make_and(visible_if_deps,
751 menu.visible_if_expr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900752
753 elif t0 == T_CHOICE:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200754 name = tokens.get_next()
755 if name is None:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900756 choice = Choice()
757 self.choices.append(choice)
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200758 else:
759 # Named choice
760 choice = self.named_choices.get(name)
761 if choice is None:
762 choice = Choice()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900763 choice.name = name
764 self.named_choices[name] = choice
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200765 self.choices.append(choice)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900766
767 choice.config = self
768 choice.parent = parent
769
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200770 choice.def_locations.append((line_feeder.filename,
771 line_feeder.linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900772
773 # Parse properties and contents
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200774 self._parse_properties(line_feeder, choice, deps,
775 visible_if_deps)
776 choice.block = self._parse_block(line_feeder, T_ENDCHOICE,
777 choice, deps, visible_if_deps)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900778
779 choice._determine_actual_symbols()
780
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200781 # If no type is specified for the choice, its type is that of
782 # the first choice item with a specified type
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900783 if choice.type == UNKNOWN:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200784 for item in choice.actual_symbols:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900785 if item.type != UNKNOWN:
786 choice.type = item.type
787 break
788
789 # Each choice item of UNKNOWN type gets the type of the choice
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200790 for item in choice.actual_symbols:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900791 if item.type == UNKNOWN:
792 item.type = choice.type
793
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200794 block.append(choice)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900795
796 elif t0 == T_MAINMENU:
797 text = tokens.get_next()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900798 if self.mainmenu_text is not None:
799 self._warn("overriding 'mainmenu' text. "
800 'Old value: "{0}", new value: "{1}".'
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200801 .format(self.mainmenu_text, text),
802 line_feeder.filename, line_feeder.linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900803 self.mainmenu_text = text
804
805 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200806 _parse_error(line, "unrecognized construct",
807 line_feeder.filename, line_feeder.linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900808
809 def _parse_properties(self, line_feeder, stmt, deps, visible_if_deps):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200810 """Parsing of properties for symbols, menus, choices, and comments.
811 Takes care of propagating dependencies from enclosing menus and ifs."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900812
813 def parse_val_and_cond(tokens, line, filename, linenr):
814 """Parses '<expr1> if <expr2>' constructs, where the 'if' part is
815 optional. Returns a tuple containing the parsed expressions, with
816 None as the second element if the 'if' part is missing."""
817 val = self._parse_expr(tokens, stmt, line, filename, linenr, False)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900818 if tokens.check(T_IF):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200819 return (val, self._parse_expr(tokens, stmt, line, filename,
820 linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900821 return (val, None)
822
823 # In case the symbol is defined in multiple locations, we need to
824 # remember what prompts, defaults, and selects are new for this
825 # definition, as "depends on" should only apply to the local
826 # definition.
827 new_prompt = None
828 new_def_exprs = []
829 new_selects = []
830
831 # Dependencies from 'depends on' statements
832 depends_on_expr = None
833
834 while 1:
835 line = line_feeder.get_next()
836 if line is None:
837 break
838
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200839 filename = line_feeder.filename
840 linenr = line_feeder.linenr
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900841
842 tokens = self._tokenize(line, False, filename, linenr)
843
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200844 t0 = tokens.get_next()
845 if t0 is None:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900846 continue
847
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200848 # Cases are ordered roughly by frequency, which speeds things up a
849 # bit
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900850
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200851 if t0 == T_DEPENDS:
852 if not tokens.check(T_ON):
853 _parse_error(line, 'expected "on" after "depends"',
854 filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900855
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200856 parsed_deps = self._parse_expr(tokens, stmt, line, filename,
857 linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900858
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200859 if isinstance(stmt, (Menu, Comment)):
860 stmt.orig_deps = _make_and(stmt.orig_deps, parsed_deps)
861 else:
862 depends_on_expr = _make_and(depends_on_expr, parsed_deps)
863
864 elif t0 == T_HELP:
865 # Find first non-blank (not all-space) line and get its
866 # indentation
867 line = line_feeder.next_nonblank()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900868 if line is None:
869 stmt.help = ""
870 break
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900871 indent = _indentation(line)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900872 if indent == 0:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200873 # If the first non-empty lines has zero indent, there is no
874 # help text
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900875 stmt.help = ""
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200876 line_feeder.unget()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900877 break
878
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900879 # The help text goes on till the first non-empty line with less
880 # indent
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200881 help_lines = [_deindent(line, indent)]
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900882 while 1:
883 line = line_feeder.get_next()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200884 if line is None or \
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900885 (not line.isspace() and _indentation(line) < indent):
886 stmt.help = "".join(help_lines)
887 break
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900888 help_lines.append(_deindent(line, indent))
889
890 if line is None:
891 break
892
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200893 line_feeder.unget()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900894
895 elif t0 == T_SELECT:
896 target = tokens.get_next()
897
898 stmt.referenced_syms.add(target)
899 stmt.selected_syms.add(target)
900
901 if tokens.check(T_IF):
902 new_selects.append((target,
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200903 self._parse_expr(tokens, stmt, line,
904 filename, linenr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900905 else:
906 new_selects.append((target, None))
907
908 elif t0 in (T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200909 stmt.type = TOKEN_TO_TYPE[t0]
910 if tokens.peek_next() is not None:
911 new_prompt = parse_val_and_cond(tokens, line, filename,
912 linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900913
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200914 elif t0 == T_DEFAULT:
915 new_def_exprs.append(parse_val_and_cond(tokens, line, filename,
916 linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900917
918 elif t0 == T_DEF_BOOL:
919 stmt.type = BOOL
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200920 if tokens.peek_next() is not None:
921 new_def_exprs.append(parse_val_and_cond(tokens, line,
922 filename, linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900923
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200924 elif t0 == T_PROMPT:
925 # 'prompt' properties override each other within a single
926 # definition of a symbol, but additional prompts can be added
927 # by defining the symbol multiple times; hence 'new_prompt'
928 # instead of 'prompt'.
929 new_prompt = parse_val_and_cond(tokens, line, filename, linenr)
930
931 elif t0 == T_RANGE:
932 low = tokens.get_next()
933 high = tokens.get_next()
934 stmt.referenced_syms.add(low)
935 stmt.referenced_syms.add(high)
936
937 if tokens.check(T_IF):
938 stmt.ranges.append((low, high,
939 self._parse_expr(tokens, stmt, line,
940 filename, linenr)))
941 else:
942 stmt.ranges.append((low, high, None))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900943
944 elif t0 == T_DEF_TRISTATE:
945 stmt.type = TRISTATE
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200946 if tokens.peek_next() is not None:
947 new_def_exprs.append(parse_val_and_cond(tokens, line,
948 filename, linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900949
950 elif t0 == T_OPTION:
951 if tokens.check(T_ENV) and tokens.check(T_EQUAL):
952 env_var = tokens.get_next()
953
954 stmt.is_special_ = True
955 stmt.is_from_env = True
956
957 if env_var not in os.environ:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200958 self._warn("The symbol {0} references the "
959 "non-existent environment variable {1} and "
960 "will get the empty string as its value. "
961 "If you're using Kconfiglib via "
962 "'make (i)scriptconfig', it should have "
963 "set up the environment correctly for you. "
964 "If you still got this message, that "
965 "might be an error, and you should email "
966 "ulfalizer a.t Google's email service."""
967 .format(stmt.name, env_var),
968 filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900969
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200970 stmt.cached_val = ""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900971 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200972 stmt.cached_val = os.environ[env_var]
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900973
974 elif tokens.check(T_DEFCONFIG_LIST):
975 self.defconfig_sym = stmt
976
977 elif tokens.check(T_MODULES):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200978 # To reduce warning spam, only warn if 'option modules' is
979 # set on some symbol that isn't MODULES, which should be
980 # safe. I haven't run into any projects that make use
981 # modules besides the kernel yet, and there it's likely to
982 # keep being called "MODULES".
983 if stmt.name != "MODULES":
984 self._warn("the 'modules' option is not supported. "
985 "Let me know if this is a problem for you; "
986 "it shouldn't be that hard to implement. "
987 "(Note that modules are still supported -- "
988 "Kconfiglib just assumes the symbol name "
989 "MODULES, like older versions of the C "
990 "implementation did when 'option modules' "
991 "wasn't used.)",
992 filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900993
Masahiro Yamada9d01b782015-05-27 11:39:22 +0900994 elif tokens.check(T_ALLNOCONFIG_Y):
995 if not isinstance(stmt, Symbol):
996 _parse_error(line,
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200997 "the 'allnoconfig_y' option is only "
998 "valid for symbols",
999 filename, linenr)
Masahiro Yamada9d01b782015-05-27 11:39:22 +09001000 stmt.allnoconfig_y = True
1001
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001002 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001003 _parse_error(line, "unrecognized option", filename, linenr)
1004
1005 elif t0 == T_VISIBLE:
1006 if not tokens.check(T_IF):
1007 _parse_error(line, 'expected "if" after "visible"',
1008 filename, linenr)
1009 if not isinstance(stmt, Menu):
1010 _parse_error(line,
1011 "'visible if' is only valid for menus",
1012 filename, linenr)
1013
1014 parsed_deps = self._parse_expr(tokens, stmt, line, filename,
1015 linenr)
1016 stmt.visible_if_expr = _make_and(stmt.visible_if_expr,
1017 parsed_deps)
1018
1019 elif t0 == T_OPTIONAL:
1020 if not isinstance(stmt, Choice):
1021 _parse_error(line,
1022 '"optional" is only valid for choices',
1023 filename,
1024 linenr)
1025 stmt.optional = True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001026
1027 else:
1028 # See comment in Config.__init__()
1029 self.end_line = line
1030 self.end_line_tokens = tokens
1031 break
1032
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001033 # Done parsing properties. Now propagate 'depends on' and enclosing
1034 # menu/if dependencies to expressions.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001035
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001036 # The set of symbols referenced directly by the statement plus all
1037 # symbols referenced by enclosing menus and ifs
1038 stmt.all_referenced_syms = stmt.referenced_syms | _get_expr_syms(deps)
1039
1040 # Save original dependencies from enclosing menus and ifs
1041 stmt.deps_from_containing = deps
1042
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001043 if isinstance(stmt, (Menu, Comment)):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001044 stmt.dep_expr = _make_and(stmt.orig_deps, deps)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001045 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001046 # Symbol or Choice
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001047
1048 # See comment for 'menu_dep'
1049 stmt.menu_dep = depends_on_expr
1050
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001051 # Propagate dependencies to prompts
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001052
1053 if new_prompt is not None:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001054 # Propagate 'visible if' dependencies from enclosing menus
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001055 prompt, cond_expr = new_prompt
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001056 cond_expr = _make_and(cond_expr, visible_if_deps)
1057 # Propagate 'depends on' dependencies
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001058 new_prompt = (prompt, _make_and(cond_expr, depends_on_expr))
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001059 # Save original
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001060 stmt.orig_prompts.append(new_prompt)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001061 # Finalize with dependencies from enclosing menus and ifs
1062 stmt.prompts.append((new_prompt[0],
1063 _make_and(new_prompt[1], deps)))
1064
1065 # Propagate dependencies to defaults
1066
1067 # Propagate 'depends on' dependencies
1068 new_def_exprs = [(val_expr, _make_and(cond_expr, depends_on_expr))
1069 for val_expr, cond_expr in new_def_exprs]
1070 # Save original
1071 stmt.orig_def_exprs.extend(new_def_exprs)
1072 # Finalize with dependencies from enclosing menus and ifs
1073 stmt.def_exprs.extend([(val_expr, _make_and(cond_expr, deps))
1074 for val_expr, cond_expr in new_def_exprs])
1075
1076 # Propagate dependencies to selects
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001077
1078 # Only symbols can select
1079 if isinstance(stmt, Symbol):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001080 # Propagate 'depends on' dependencies
1081 new_selects = [(target, _make_and(cond_expr, depends_on_expr))
1082 for target, cond_expr in new_selects]
1083 # Save original
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001084 stmt.orig_selects.extend(new_selects)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001085 # Finalize with dependencies from enclosing menus and ifs
1086 for target, cond in new_selects:
1087 target.rev_dep = _make_or(target.rev_dep,
1088 _make_and(stmt,
1089 _make_and(cond, deps)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001090
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001091 def _parse_expr(self, feed, cur_item, line, filename=None, linenr=None,
1092 transform_m=True):
1093 """Parses an expression from the tokens in 'feed' using a simple
1094 top-down approach. The result has the form
1095 '(<operator>, [<parsed operands>])', where <operator> is e.g.
1096 kconfiglib.AND. If there is only one operand (i.e., no && or ||), then
1097 the operand is returned directly. This also goes for subexpressions.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001098
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001099 feed: _Feed instance containing the tokens for the expression.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001100
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001101 cur_item: The item (Symbol, Choice, Menu, or Comment) currently being
1102 parsed, or None if we're not parsing an item. Used for recording
1103 references to symbols.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001104
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001105 line: The line containing the expression being parsed.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001106
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001107 filename (default: None): The file containing the expression.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001108
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001109 linenr (default: None): The line number containing the expression.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001110
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001111 transform_m (default: False): Determines if 'm' should be rewritten to
1112 'm && MODULES' -- see parse_val_and_cond().
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001113
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001114 Expression grammar, in decreasing order of precedence:
1115
1116 <expr> -> <symbol>
1117 <symbol> '=' <symbol>
1118 <symbol> '!=' <symbol>
1119 '(' <expr> ')'
1120 '!' <expr>
1121 <expr> '&&' <expr>
1122 <expr> '||' <expr>"""
1123
1124 # Use instance variables to avoid having to pass these as arguments
1125 # through the top-down parser in _parse_expr_rec(), which is tedious
1126 # and obfuscates the code. A profiler run shows no noticeable
1127 # performance difference.
1128 self._cur_item = cur_item
1129 self._transform_m = transform_m
1130 self._line = line
1131 self._filename = filename
1132 self._linenr = linenr
1133
1134 return self._parse_expr_rec(feed)
1135
1136 def _parse_expr_rec(self, feed):
1137 or_term = self._parse_or_term(feed)
1138 if not feed.check(T_OR):
1139 # Common case -- no need for an OR node since it's just a single
1140 # operand
1141 return or_term
1142 or_terms = [or_term, self._parse_or_term(feed)]
1143 while feed.check(T_OR):
1144 or_terms.append(self._parse_or_term(feed))
1145 return (OR, or_terms)
1146
1147 def _parse_or_term(self, feed):
1148 and_term = self._parse_factor(feed)
1149 if not feed.check(T_AND):
1150 # Common case -- no need for an AND node since it's just a single
1151 # operand
1152 return and_term
1153 and_terms = [and_term, self._parse_factor(feed)]
1154 while feed.check(T_AND):
1155 and_terms.append(self._parse_factor(feed))
1156 return (AND, and_terms)
1157
1158 def _parse_factor(self, feed):
1159 token = feed.get_next()
1160
1161 if isinstance(token, (Symbol, str)):
1162 if self._cur_item is not None and isinstance(token, Symbol):
1163 self._cur_item.referenced_syms.add(token)
1164
1165 next_token = feed.peek_next()
1166 # For conditional expressions ('depends on <expr>',
1167 # '... if <expr>', # etc.), "m" and m are rewritten to
1168 # "m" && MODULES.
1169 if next_token != T_EQUAL and next_token != T_UNEQUAL:
1170 if self._transform_m and (token is self.m or token == "m"):
1171 return (AND, ["m", self._sym_lookup("MODULES")])
1172 return token
1173
1174 relation = EQUAL if (feed.get_next() == T_EQUAL) else UNEQUAL
1175 token_2 = feed.get_next()
1176 if self._cur_item is not None and isinstance(token_2, Symbol):
1177 self._cur_item.referenced_syms.add(token_2)
1178 return (relation, token, token_2)
1179
1180 if token == T_NOT:
1181 return (NOT, self._parse_factor(feed))
1182
1183 if token == T_OPEN_PAREN:
1184 expr_parse = self._parse_expr_rec(feed)
1185 if not feed.check(T_CLOSE_PAREN):
1186 _parse_error(self._line, "missing end parenthesis",
1187 self._filename, self._linenr)
1188 return expr_parse
1189
1190 _parse_error(self._line, "malformed expression", self._filename,
1191 self._linenr)
1192
1193 def _tokenize(self, s, for_eval, filename=None, linenr=None):
1194 """Returns a _Feed instance containing tokens derived from the string
1195 's'. Registers any new symbols encountered (via _sym_lookup()).
1196
1197 (I experimented with a pure regular expression implementation, but it
1198 came out slower, less readable, and wouldn't have been as flexible.)
1199
1200 for_eval: True when parsing an expression for a call to Config.eval(),
1201 in which case we should not treat the first token specially nor
1202 register new symbols."""
1203
1204 s = s.strip()
1205 if s == "" or s[0] == "#":
1206 return _Feed([])
1207
1208 if for_eval:
1209 previous = None # The previous token seen
1210 tokens = []
1211 i = 0 # The current index in the string being tokenized
1212
1213 else:
1214 # The initial word on a line is parsed specially. Let
1215 # command_chars = [A-Za-z0-9_]. Then
1216 # - leading non-command_chars characters are ignored, and
1217 # - the first token consists the following one or more
1218 # command_chars characters.
1219 # This is why things like "----help--" are accepted.
1220 initial_token_match = _initial_token_re_match(s)
1221 if initial_token_match is None:
1222 return _Feed([])
1223 keyword = _get_keyword(initial_token_match.group(1))
1224 if keyword == T_HELP:
1225 # Avoid junk after "help", e.g. "---", being registered as a
1226 # symbol
1227 return _Feed([T_HELP])
1228 if keyword is None:
1229 # We expect a keyword as the first token
1230 _tokenization_error(s, filename, linenr)
1231
1232 previous = keyword
1233 tokens = [keyword]
1234 # The current index in the string being tokenized
1235 i = initial_token_match.end()
1236
1237 # _tokenize() is a hotspot during parsing, and this speeds things up a
1238 # bit
1239 strlen = len(s)
1240 append = tokens.append
1241
1242 # Main tokenization loop. (Handles tokens past the first one.)
1243 while i < strlen:
1244 # Test for an identifier/keyword preceded by whitespace first; this
1245 # is the most common case.
1246 id_keyword_match = _id_keyword_re_match(s, i)
1247 if id_keyword_match:
1248 # We have an identifier or keyword. The above also stripped any
1249 # whitespace for us.
1250 name = id_keyword_match.group(1)
1251 # Jump past it
1252 i = id_keyword_match.end()
1253
1254 keyword = _get_keyword(name)
1255 if keyword is not None:
1256 # It's a keyword
1257 append(keyword)
1258 elif previous in STRING_LEX:
1259 # What would ordinarily be considered an identifier is
1260 # treated as a string after certain tokens
1261 append(name)
1262 else:
1263 # It's a symbol name. _sym_lookup() will take care of
1264 # allocating a new Symbol instance if it's the first time
1265 # we see it.
1266 sym = self._sym_lookup(name, for_eval)
1267
1268 if previous == T_CONFIG or previous == T_MENUCONFIG:
1269 # If the previous token is T_(MENU)CONFIG
1270 # ("(menu)config"), we're tokenizing the first line of
1271 # a symbol definition, and should remember this as a
1272 # location where the symbol is defined
1273 sym.def_locations.append((filename, linenr))
1274 else:
1275 # Otherwise, it's a reference to the symbol
1276 sym.ref_locations.append((filename, linenr))
1277
1278 append(sym)
1279
1280 else:
1281 # Not an identifier/keyword
1282
1283 while i < strlen and s[i].isspace():
1284 i += 1
1285 if i == strlen:
1286 break
1287 c = s[i]
1288 i += 1
1289
1290 # String literal (constant symbol)
1291 if c == '"' or c == "'":
1292 if "\\" in s:
1293 # Slow path: This could probably be sped up, but it's a
1294 # very unusual case anyway.
1295 quote = c
1296 val = ""
1297 while 1:
1298 if i >= len(s):
1299 _tokenization_error(s, filename, linenr)
1300 c = s[i]
1301 if c == quote:
1302 break
1303 if c == "\\":
1304 if i + 1 >= len(s):
1305 _tokenization_error(s, filename, linenr)
1306 val += s[i + 1]
1307 i += 2
1308 else:
1309 val += c
1310 i += 1
1311 i += 1
1312 append(val)
1313 else:
1314 # Fast path: If the string contains no backslashes
1315 # (almost always) we can simply look for the matching
1316 # quote.
1317 end = s.find(c, i)
1318 if end == -1:
1319 _tokenization_error(s, filename, linenr)
1320 append(s[i:end])
1321 i = end + 1
1322
1323 elif c == "&":
1324 # Invalid characters are ignored
1325 if i >= len(s) or s[i] != "&": continue
1326 append(T_AND)
1327 i += 1
1328
1329 elif c == "|":
1330 # Invalid characters are ignored
1331 if i >= len(s) or s[i] != "|": continue
1332 append(T_OR)
1333 i += 1
1334
1335 elif c == "!":
1336 if i < len(s) and s[i] == "=":
1337 append(T_UNEQUAL)
1338 i += 1
1339 else:
1340 append(T_NOT)
1341
1342 elif c == "=": append(T_EQUAL)
1343 elif c == "(": append(T_OPEN_PAREN)
1344 elif c == ")": append(T_CLOSE_PAREN)
1345 elif c == "#": break # Comment
1346
1347 else: continue # Invalid characters are ignored
1348
1349 previous = tokens[-1]
1350
1351 return _Feed(tokens)
1352
1353 def _sym_lookup(self, name, for_eval=False):
1354 """Fetches the symbol 'name' from the symbol table, creating and
1355 registering it if it does not exist. If 'for_eval' is True, the symbol
1356 won't be added to the symbol table if it does not exist -- this is for
1357 Config.eval()."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001358 if name in self.syms:
1359 return self.syms[name]
1360
1361 new_sym = Symbol()
1362 new_sym.config = self
1363 new_sym.name = name
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001364 if for_eval:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001365 self._warn("no symbol {0} in configuration".format(name))
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001366 else:
1367 self.syms[name] = new_sym
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001368 return new_sym
1369
1370 #
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001371 # Expression evaluation
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001372 #
1373
1374 def _eval_expr(self, expr):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001375 """Evaluates an expression to "n", "m", or "y"."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001376
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001377 # Handles e.g. an "x if y" condition where the "if y" part is missing.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001378 if expr is None:
1379 return "y"
1380
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001381 res = self._eval_expr_rec(expr)
1382 if res == "m":
1383 # Promote "m" to "y" if we're running without modules.
1384 #
1385 # Internally, "m" is often rewritten to "m" && MODULES by both the
1386 # C implementation and Kconfiglib, which takes care of cases where
1387 # "m" should be demoted to "n" instead.
1388 modules_sym = self.syms.get("MODULES")
1389 if modules_sym is None or modules_sym.get_value() != "y":
1390 return "y"
1391 return res
1392
1393 def _eval_expr_rec(self, expr):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001394 if isinstance(expr, Symbol):
1395 # Non-bool/tristate symbols are always "n" in a tristate sense,
1396 # regardless of their value
1397 if expr.type != BOOL and expr.type != TRISTATE:
1398 return "n"
1399 return expr.get_value()
1400
1401 if isinstance(expr, str):
1402 return expr if (expr == "y" or expr == "m") else "n"
1403
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001404 # Ordered by frequency
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001405
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001406 if expr[0] == AND:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001407 res = "y"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001408 for subexpr in expr[1]:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001409 ev = self._eval_expr_rec(subexpr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001410 # Return immediately upon discovering an "n" term
1411 if ev == "n":
1412 return "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001413 if ev == "m":
1414 res = "m"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001415 # 'res' is either "m" or "y" here; we already handled the
1416 # short-circuiting "n" case in the loop.
1417 return res
1418
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001419 if expr[0] == NOT:
1420 ev = self._eval_expr_rec(expr[1])
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001421 if ev == "y":
1422 return "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001423 return "y" if (ev == "n") else "m"
1424
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001425 if expr[0] == OR:
1426 res = "n"
1427 for subexpr in expr[1]:
1428 ev = self._eval_expr_rec(subexpr)
1429 # Return immediately upon discovering a "y" term
1430 if ev == "y":
1431 return "y"
1432 if ev == "m":
1433 res = "m"
1434 # 'res' is either "n" or "m" here; we already handled the
1435 # short-circuiting "y" case in the loop.
1436 return res
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001437
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001438 if expr[0] == EQUAL:
1439 return "y" if (_str_val(expr[1]) == _str_val(expr[2])) else "n"
1440
1441 if expr[0] == UNEQUAL:
1442 return "y" if (_str_val(expr[1]) != _str_val(expr[2])) else "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001443
1444 _internal_error("Internal error while evaluating expression: "
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001445 "unknown operation {0}.".format(expr[0]))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001446
1447 def _eval_min(self, e1, e2):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001448 """Returns the minimum value of the two expressions. Equates None with
1449 'y'."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001450 e1_eval = self._eval_expr(e1)
1451 e2_eval = self._eval_expr(e2)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001452 return e1_eval if tri_less(e1_eval, e2_eval) else e2_eval
1453
1454 def _eval_max(self, e1, e2):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001455 """Returns the maximum value of the two expressions. Equates None with
1456 'y'."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001457 e1_eval = self._eval_expr(e1)
1458 e2_eval = self._eval_expr(e2)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001459 return e1_eval if tri_greater(e1_eval, e2_eval) else e2_eval
1460
1461 #
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001462 # Dependency tracking (for caching and invalidation)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001463 #
1464
1465 def _build_dep(self):
1466 """Populates the Symbol.dep sets, linking the symbol to the symbols
1467 that immediately depend on it in the sense that changing the value of
1468 the symbol might affect the values of those other symbols. This is used
1469 for caching/invalidation purposes. The calculated sets might be larger
1470 than necessary as we don't do any complicated analysis of the
1471 expressions."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001472
1473 # Adds 'sym' as a directly dependent symbol to all symbols that appear
1474 # in the expression 'e'
1475 def add_expr_deps(e, sym):
1476 for s in _get_expr_syms(e):
1477 s.dep.add(sym)
1478
1479 # The directly dependent symbols of a symbol are:
1480 # - Any symbols whose prompts, default values, rev_dep (select
1481 # condition), or ranges depend on the symbol
1482 # - Any symbols that belong to the same choice statement as the symbol
1483 # (these won't be included in 'dep' as that makes the dependency
1484 # graph unwieldy, but Symbol._get_dependent() will include them)
1485 # - Any symbols in a choice statement that depends on the symbol
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001486 for sym in self.syms_iter():
1487 for _, e in sym.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001488 add_expr_deps(e, sym)
1489
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001490 for v, e in sym.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001491 add_expr_deps(v, sym)
1492 add_expr_deps(e, sym)
1493
1494 add_expr_deps(sym.rev_dep, sym)
1495
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001496 for l, u, e in sym.ranges:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001497 add_expr_deps(l, sym)
1498 add_expr_deps(u, sym)
1499 add_expr_deps(e, sym)
1500
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001501 if sym.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001502 choice = sym.parent
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001503 for _, e in choice.prompts:
1504 add_expr_deps(e, sym)
1505 for _, e in choice.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001506 add_expr_deps(e, sym)
1507
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001508 def _eq_to_sym(self, eq):
1509 """_expr_depends_on() helper. For (in)equalities of the form sym = y/m
1510 or sym != n, returns sym. For other (in)equalities, returns None."""
1511 relation, left, right = eq
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001512
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001513 def transform_y_m_n(item):
1514 if item is self.y: return "y"
1515 if item is self.m: return "m"
1516 if item is self.n: return "n"
1517 return item
1518
1519 left = transform_y_m_n(left)
1520 right = transform_y_m_n(right)
1521
1522 # Make sure the symbol (if any) appears to the left
1523 if not isinstance(left, Symbol):
1524 left, right = right, left
1525 if not isinstance(left, Symbol):
1526 return None
1527 if (relation == EQUAL and (right == "y" or right == "m")) or \
1528 (relation == UNEQUAL and right == "n"):
1529 return left
1530 return None
1531
1532 def _expr_depends_on(self, expr, sym):
1533 """Reimplementation of expr_depends_symbol() from mconf.c. Used to
1534 determine if a submenu should be implicitly created, which influences
1535 what items inside choice statements are considered choice items."""
1536 if expr is None:
1537 return False
1538
1539 def rec(expr):
1540 if isinstance(expr, str):
1541 return False
1542 if isinstance(expr, Symbol):
1543 return expr is sym
1544
1545 if expr[0] in (EQUAL, UNEQUAL):
1546 return self._eq_to_sym(expr) is sym
1547 if expr[0] == AND:
1548 for and_expr in expr[1]:
1549 if rec(and_expr):
1550 return True
1551 return False
1552
1553 return rec(expr)
1554
1555 def _invalidate_all(self):
1556 for sym in self.syms_iter():
1557 sym._invalidate()
1558
1559 #
1560 # Printing and misc.
1561 #
1562
1563 def _expand_sym_refs(self, s):
1564 """Expands $-references to symbols in 's' to symbol values, or to the
1565 empty string for undefined symbols."""
1566
1567 while 1:
1568 sym_ref_match = _sym_ref_re_search(s)
1569 if sym_ref_match is None:
1570 return s
1571
1572 sym_name = sym_ref_match.group(0)[1:]
1573 sym = self.syms.get(sym_name)
1574 expansion = "" if sym is None else sym.get_value()
1575
1576 s = s[:sym_ref_match.start()] + \
1577 expansion + \
1578 s[sym_ref_match.end():]
1579
1580 def _expr_val_str(self, expr, no_value_str="(none)",
1581 get_val_instead_of_eval=False):
1582 """Printing helper. Returns a string with 'expr' and its value.
1583
1584 no_value_str: String to return when 'expr' is missing (None).
1585
1586 get_val_instead_of_eval: Assume 'expr' is a symbol or string (constant
1587 symbol) and get its value directly instead of evaluating it to a
1588 tristate value."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001589
1590 if expr is None:
1591 return no_value_str
1592
1593 if get_val_instead_of_eval:
1594 if isinstance(expr, str):
1595 return _expr_to_str(expr)
1596 val = expr.get_value()
1597 else:
1598 val = self._eval_expr(expr)
1599
1600 return "{0} (value: {1})".format(_expr_to_str(expr), _expr_to_str(val))
1601
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001602 def _get_sym_or_choice_str(self, sc):
1603 """Symbols and choices have many properties in common, so we factor out
1604 common __str__() stuff here. "sc" is short for "symbol or choice"."""
1605
1606 # As we deal a lot with string representations here, use some
1607 # convenient shorthand:
1608 s = _expr_to_str
1609
1610 #
1611 # Common symbol/choice properties
1612 #
1613
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001614 user_val_str = "(no user value)" if sc.user_val is None else \
1615 s(sc.user_val)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001616
1617 # Build prompts string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001618 if not sc.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001619 prompts_str = " (no prompts)"
1620 else:
1621 prompts_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001622 for prompt, cond_expr in sc.orig_prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001623 if cond_expr is None:
1624 prompts_str_rows.append(' "{0}"'.format(prompt))
1625 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001626 prompts_str_rows.append(
1627 ' "{0}" if {1}'.format(prompt,
1628 self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001629 prompts_str = "\n".join(prompts_str_rows)
1630
1631 # Build locations string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001632 if not sc.def_locations:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001633 locations_str = "(no locations)"
1634 else:
1635 locations_str = " ".join(["{0}:{1}".format(filename, linenr) for
1636 (filename, linenr) in sc.def_locations])
1637
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001638 # Build additional-dependencies-from-menus-and-ifs string
1639 additional_deps_str = " " + \
1640 self._expr_val_str(sc.deps_from_containing,
1641 "(no additional dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001642
1643 #
1644 # Symbol-specific stuff
1645 #
1646
1647 if isinstance(sc, Symbol):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001648 # Build ranges string
1649 if isinstance(sc, Symbol):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001650 if not sc.ranges:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001651 ranges_str = " (no ranges)"
1652 else:
1653 ranges_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001654 for l, u, cond_expr in sc.ranges:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001655 if cond_expr is None:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001656 ranges_str_rows.append(" [{0}, {1}]".format(s(l),
1657 s(u)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001658 else:
1659 ranges_str_rows.append(" [{0}, {1}] if {2}"
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001660 .format(s(l), s(u),
1661 self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001662 ranges_str = "\n".join(ranges_str_rows)
1663
1664 # Build default values string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001665 if not sc.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001666 defaults_str = " (no default values)"
1667 else:
1668 defaults_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001669 for val_expr, cond_expr in sc.orig_def_exprs:
1670 row_str = " " + self._expr_val_str(val_expr, "(none)",
1671 sc.type == STRING)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001672 defaults_str_rows.append(row_str)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001673 defaults_str_rows.append(" Condition: " +
1674 self._expr_val_str(cond_expr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001675 defaults_str = "\n".join(defaults_str_rows)
1676
1677 # Build selects string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001678 if not sc.orig_selects:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001679 selects_str = " (no selects)"
1680 else:
1681 selects_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001682 for target, cond_expr in sc.orig_selects:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001683 if cond_expr is None:
1684 selects_str_rows.append(" {0}".format(target.name))
1685 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001686 selects_str_rows.append(
1687 " {0} if {1}".format(target.name,
1688 self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001689 selects_str = "\n".join(selects_str_rows)
1690
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001691 res = _lines("Symbol " +
1692 ("(no name)" if sc.name is None else sc.name),
1693 "Type : " + TYPENAME[sc.type],
1694 "Value : " + s(sc.get_value()),
1695 "User value : " + user_val_str,
1696 "Visibility : " + s(_get_visibility(sc)),
1697 "Is choice item : " + BOOL_STR[sc.is_choice_sym],
1698 "Is defined : " + BOOL_STR[sc.is_defined_],
1699 "Is from env. : " + BOOL_STR[sc.is_from_env],
1700 "Is special : " + BOOL_STR[sc.is_special_] + "\n")
1701 if sc.ranges:
1702 res += _lines("Ranges:", ranges_str + "\n")
1703 res += _lines("Prompts:",
1704 prompts_str,
1705 "Default values:",
1706 defaults_str,
1707 "Selects:",
1708 selects_str,
1709 "Reverse (select-related) dependencies:",
1710 " (no reverse dependencies)" if sc.rev_dep == "n"
1711 else " " + self._expr_val_str(sc.rev_dep),
1712 "Additional dependencies from enclosing menus "
1713 "and ifs:",
1714 additional_deps_str,
1715 "Locations: " + locations_str)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001716
1717 return res
1718
1719 #
1720 # Choice-specific stuff
1721 #
1722
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001723 # Build selected symbol string
1724 sel = sc.get_selection()
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001725 sel_str = "(no selection)" if sel is None else sel.name
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001726
1727 # Build default values string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001728 if not sc.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001729 defaults_str = " (no default values)"
1730 else:
1731 defaults_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001732 for sym, cond_expr in sc.orig_def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001733 if cond_expr is None:
1734 defaults_str_rows.append(" {0}".format(sym.name))
1735 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001736 defaults_str_rows.append(" {0} if {1}".format(sym.name,
1737 self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001738 defaults_str = "\n".join(defaults_str_rows)
1739
1740 # Build contained symbols string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001741 names = [sym.name for sym in sc.actual_symbols]
1742 syms_string = " ".join(names) if names else "(empty)"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001743
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001744 return _lines("Choice",
1745 "Name (for named choices): " +
1746 ("(no name)" if sc.name is None else sc.name),
1747 "Type : " + TYPENAME[sc.type],
1748 "Selected symbol : " + sel_str,
1749 "User value : " + user_val_str,
1750 "Mode : " + s(sc.get_mode()),
1751 "Visibility : " + s(_get_visibility(sc)),
1752 "Optional : " + BOOL_STR[sc.optional],
1753 "Prompts:",
1754 prompts_str,
1755 "Defaults:",
1756 defaults_str,
1757 "Choice symbols:",
1758 " " + syms_string,
1759 "Additional dependencies from enclosing menus and "
1760 "ifs:",
1761 additional_deps_str,
1762 "Locations: " + locations_str)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001763
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001764 def _warn(self, msg, filename=None, linenr=None):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001765 """For printing warnings to stderr."""
1766 if self.print_warnings:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001767 _stderr_msg("warning: " + msg, filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001768
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001769class Item(object):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001770
1771 """Base class for symbols and other Kconfig constructs. Subclasses are
1772 Symbol, Choice, Menu, and Comment."""
1773
1774 def is_symbol(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001775 """Returns True if the item is a symbol. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001776 isinstance(item, kconfiglib.Symbol)."""
1777 return isinstance(self, Symbol)
1778
1779 def is_choice(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001780 """Returns True if the item is a choice. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001781 isinstance(item, kconfiglib.Choice)."""
1782 return isinstance(self, Choice)
1783
1784 def is_menu(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001785 """Returns True if the item is a menu. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001786 isinstance(item, kconfiglib.Menu)."""
1787 return isinstance(self, Menu)
1788
1789 def is_comment(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001790 """Returns True if the item is a comment. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001791 isinstance(item, kconfiglib.Comment)."""
1792 return isinstance(self, Comment)
1793
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001794class Symbol(Item):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001795
1796 """Represents a configuration symbol - e.g. FOO for
1797
1798 config FOO
1799 ..."""
1800
1801 #
1802 # Public interface
1803 #
1804
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001805 def get_config(self):
1806 """Returns the Config instance this symbol is from."""
1807 return self.config
1808
1809 def get_name(self):
1810 """Returns the name of the symbol."""
1811 return self.name
1812
1813 def get_type(self):
1814 """Returns the type of the symbol: one of UNKNOWN, BOOL, TRISTATE,
1815 STRING, HEX, or INT. These are defined at the top level of the module,
1816 so you'd do something like
1817
1818 if sym.get_type() == kconfiglib.STRING:
1819 ..."""
1820 return self.type
1821
1822 def get_prompts(self):
1823 """Returns a list of prompts defined for the symbol, in the order they
1824 appear in the configuration files. Returns the empty list for symbols
1825 with no prompt.
1826
1827 This list will have a single entry for the vast majority of symbols
1828 having prompts, but having multiple prompts for a single symbol is
1829 possible through having multiple 'config' entries for it."""
1830 return [prompt for prompt, _ in self.orig_prompts]
1831
1832 def get_help(self):
1833 """Returns the help text of the symbol, or None if the symbol has no
1834 help text."""
1835 return self.help
1836
1837 def get_parent(self):
1838 """Returns the menu or choice statement that contains the symbol, or
1839 None if the symbol is at the top level. Note that if statements are
1840 treated as syntactic and do not have an explicit class
1841 representation."""
1842 return self.parent
1843
1844 def get_def_locations(self):
1845 """Returns a list of (filename, linenr) tuples, where filename (string)
1846 and linenr (int) represent a location where the symbol is defined. For
1847 the vast majority of symbols this list will only contain one element.
1848 For the following Kconfig, FOO would get two entries: the lines marked
1849 with *.
1850
1851 config FOO *
1852 bool "foo prompt 1"
1853
1854 config FOO *
1855 bool "foo prompt 2"
1856 """
1857 return self.def_locations
1858
1859 def get_ref_locations(self):
1860 """Returns a list of (filename, linenr) tuples, where filename (string)
1861 and linenr (int) represent a location where the symbol is referenced in
1862 the configuration. For example, the lines marked by * would be included
1863 for FOO below:
1864
1865 config A
1866 bool
1867 default BAR || FOO *
1868
1869 config B
1870 tristate
1871 depends on FOO *
1872 default m if FOO *
1873
1874 if FOO *
1875 config A
1876 bool "A"
1877 endif
1878
1879 config FOO (definition not included)
1880 bool
1881 """
1882 return self.ref_locations
1883
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001884 def get_value(self):
1885 """Calculate and return the value of the symbol. See also
1886 Symbol.set_user_value()."""
1887
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001888 if self.cached_val is not None:
1889 return self.cached_val
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001890
1891 # As a quirk of Kconfig, undefined symbols get their name as their
1892 # value. This is why things like "FOO = bar" work for seeing if FOO has
1893 # the value "bar".
1894 if self.type == UNKNOWN:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001895 self.cached_val = self.name
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001896 return self.name
1897
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001898 new_val = DEFAULT_VALUE[self.type]
1899 vis = _get_visibility(self)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001900
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001901 # This is easiest to calculate together with the value
1902 self.write_to_conf = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001903
1904 if self.type == BOOL or self.type == TRISTATE:
1905 # The visibility and mode (modules-only or single-selection) of
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001906 # choice items will be taken into account in _get_visibility()
1907 if self.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001908 if vis != "n":
1909 choice = self.parent
1910 mode = choice.get_mode()
1911
1912 self.write_to_conf = (mode != "n")
1913
1914 if mode == "y":
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001915 if choice.get_selection() is self:
1916 new_val = "y"
1917 else:
1918 new_val = "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001919 elif mode == "m":
1920 if self.user_val == "m" or self.user_val == "y":
1921 new_val = "m"
1922
1923 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001924 # If the symbol is visible and has a user value, use that.
1925 # Otherwise, look at defaults.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001926 use_defaults = True
1927
1928 if vis != "n":
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001929 self.write_to_conf = True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001930 if self.user_val is not None:
1931 new_val = self.config._eval_min(self.user_val, vis)
1932 use_defaults = False
1933
1934 if use_defaults:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001935 for val_expr, cond_expr in self.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001936 cond_eval = self.config._eval_expr(cond_expr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001937 if cond_eval != "n":
1938 self.write_to_conf = True
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001939 new_val = self.config._eval_min(val_expr,
1940 cond_eval)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001941 break
1942
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001943 # Reverse (select-related) dependencies take precedence
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001944 rev_dep_val = self.config._eval_expr(self.rev_dep)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001945 if rev_dep_val != "n":
1946 self.write_to_conf = True
1947 new_val = self.config._eval_max(new_val, rev_dep_val)
1948
1949 # Promote "m" to "y" for booleans
1950 if new_val == "m" and self.type == BOOL:
1951 new_val = "y"
1952
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001953 elif self.type == INT or self.type == HEX:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001954 has_active_range = False
1955 low = None
1956 high = None
1957 use_defaults = True
1958
1959 base = 16 if self.type == HEX else 10
1960
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001961 for l, h, cond_expr in self.ranges:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001962 if self.config._eval_expr(cond_expr) != "n":
1963 has_active_range = True
1964
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001965 low_str = _str_val(l)
1966 high_str = _str_val(h)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001967 low = int(low_str, base) if \
1968 _is_base_n(low_str, base) else 0
1969 high = int(high_str, base) if \
1970 _is_base_n(high_str, base) else 0
1971
1972 break
1973
1974 if vis != "n":
1975 self.write_to_conf = True
1976
1977 if self.user_val is not None and \
1978 _is_base_n(self.user_val, base) and \
1979 (not has_active_range or
1980 low <= int(self.user_val, base) <= high):
1981
1982 # If the user value is OK, it is stored in exactly the same
1983 # form as specified in the assignment (with or without
1984 # "0x", etc).
1985
1986 use_defaults = False
1987 new_val = self.user_val
1988
1989 if use_defaults:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001990 for val_expr, cond_expr in self.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001991 if self.config._eval_expr(cond_expr) != "n":
1992 self.write_to_conf = True
1993
1994 # If the default value is OK, it is stored in exactly
1995 # the same form as specified. Otherwise, it is clamped
1996 # to the range, and the output has "0x" as appropriate
1997 # for the type.
1998
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001999 new_val = _str_val(val_expr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002000
2001 if _is_base_n(new_val, base):
2002 new_val_num = int(new_val, base)
2003 if has_active_range:
2004 clamped_val = None
2005
2006 if new_val_num < low:
2007 clamped_val = low
2008 elif new_val_num > high:
2009 clamped_val = high
2010
2011 if clamped_val is not None:
2012 new_val = (hex(clamped_val) if \
2013 self.type == HEX else str(clamped_val))
2014
2015 break
2016 else: # For the for loop
2017 # If no user value or default kicks in but the hex/int has
2018 # an active range, then the low end of the range is used,
2019 # provided it's > 0, with "0x" prepended as appropriate.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002020 if has_active_range and low > 0:
2021 new_val = (hex(low) if self.type == HEX else str(low))
2022
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002023 elif self.type == STRING:
2024 use_defaults = True
2025
2026 if vis != "n":
2027 self.write_to_conf = True
2028 if self.user_val is not None:
2029 new_val = self.user_val
2030 use_defaults = False
2031
2032 if use_defaults:
2033 for val_expr, cond_expr in self.def_exprs:
2034 if self.config._eval_expr(cond_expr) != "n":
2035 self.write_to_conf = True
2036 new_val = _str_val(val_expr)
2037 break
2038
2039 self.cached_val = new_val
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002040 return new_val
2041
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002042 def get_user_value(self):
2043 """Returns the value assigned to the symbol in a .config or via
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002044 Symbol.set_user_value() (provided the value was valid for the type of
2045 the symbol). Returns None in case of no user value."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002046 return self.user_val
2047
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002048 def get_upper_bound(self):
2049 """For string/hex/int symbols and for bool and tristate symbols that
2050 cannot be modified (see is_modifiable()), returns None.
2051
2052 Otherwise, returns the highest value the symbol can be set to with
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002053 Symbol.set_user_value() (that will not be truncated): one of "m" or
2054 "y", arranged from lowest to highest. This corresponds to the highest
2055 value the symbol could be given in e.g. the 'make menuconfig'
2056 interface.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002057
2058 See also the tri_less*() and tri_greater*() functions, which could come
2059 in handy."""
2060 if self.type != BOOL and self.type != TRISTATE:
2061 return None
2062 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002063 # A bool selected to "m" gets promoted to "y", pinning it
2064 if rev_dep == "m" and self.type == BOOL:
2065 return None
2066 vis = _get_visibility(self)
2067 if TRI_TO_INT[vis] > TRI_TO_INT[rev_dep]:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002068 return vis
2069 return None
2070
2071 def get_lower_bound(self):
2072 """For string/hex/int symbols and for bool and tristate symbols that
2073 cannot be modified (see is_modifiable()), returns None.
2074
2075 Otherwise, returns the lowest value the symbol can be set to with
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002076 Symbol.set_user_value() (that will not be truncated): one of "n" or
2077 "m", arranged from lowest to highest. This corresponds to the lowest
2078 value the symbol could be given in e.g. the 'make menuconfig'
2079 interface.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002080
2081 See also the tri_less*() and tri_greater*() functions, which could come
2082 in handy."""
2083 if self.type != BOOL and self.type != TRISTATE:
2084 return None
2085 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002086 # A bool selected to "m" gets promoted to "y", pinning it
2087 if rev_dep == "m" and self.type == BOOL:
2088 return None
2089 if TRI_TO_INT[_get_visibility(self)] > TRI_TO_INT[rev_dep]:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002090 return rev_dep
2091 return None
2092
2093 def get_assignable_values(self):
2094 """For string/hex/int symbols and for bool and tristate symbols that
2095 cannot be modified (see is_modifiable()), returns the empty list.
2096
2097 Otherwise, returns a list containing the user values that can be
2098 assigned to the symbol (that won't be truncated). Usage example:
2099
2100 if "m" in sym.get_assignable_values():
2101 sym.set_user_value("m")
2102
2103 This is basically a more convenient interface to
2104 get_lower/upper_bound() when wanting to test if a particular tristate
2105 value can be assigned."""
2106 if self.type != BOOL and self.type != TRISTATE:
2107 return []
2108 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002109 # A bool selected to "m" gets promoted to "y", pinning it
2110 if rev_dep == "m" and self.type == BOOL:
2111 return []
2112 res = ["n", "m", "y"][TRI_TO_INT[rev_dep] :
2113 TRI_TO_INT[_get_visibility(self)] + 1]
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002114 return res if len(res) > 1 else []
2115
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002116 def get_visibility(self):
2117 """Returns the visibility of the symbol: one of "n", "m" or "y". For
2118 bool and tristate symbols, this is an upper bound on the value users
2119 can set for the symbol. For other types of symbols, a visibility of "n"
2120 means the user value will be ignored. A visibility of "n" corresponds
2121 to not being visible in the 'make *config' interfaces.
2122
2123 Example (assuming we're running with modules enabled -- i.e., MODULES
2124 set to 'y'):
2125
2126 # Assume this has been assigned 'n'
2127 config N_SYM
2128 tristate "N_SYM"
2129
2130 # Assume this has been assigned 'm'
2131 config M_SYM
2132 tristate "M_SYM"
2133
2134 # Has visibility 'n'
2135 config A
2136 tristate "A"
2137 depends on N_SYM
2138
2139 # Has visibility 'm'
2140 config B
2141 tristate "B"
2142 depends on M_SYM
2143
2144 # Has visibility 'y'
2145 config C
2146 tristate "C"
2147
2148 # Has no prompt, and hence visibility 'n'
2149 config D
2150 tristate
2151
2152 Having visibility be tri-valued ensures that e.g. a symbol cannot be
2153 set to "y" by the user if it depends on a symbol with value "m", which
2154 wouldn't be safe.
2155
2156 You should probably look at get_lower/upper_bound(),
2157 get_assignable_values() and is_modifiable() before using this."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002158 return _get_visibility(self)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002159
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002160 def get_referenced_symbols(self, refs_from_enclosing=False):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002161 """Returns the set() of all symbols referenced by this symbol. For
2162 example, the symbol defined by
2163
2164 config FOO
2165 bool
2166 prompt "foo" if A && B
2167 default C if D
2168 depends on E
2169 select F if G
2170
2171 references the symbols A through G.
2172
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002173 refs_from_enclosing (default: False): If True, the symbols referenced
2174 by enclosing menus and ifs will be included in the result."""
2175 return self.all_referenced_syms if refs_from_enclosing else \
2176 self.referenced_syms
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002177
2178 def get_selected_symbols(self):
2179 """Returns the set() of all symbols X for which this symbol has a
2180 'select X' or 'select X if Y' (regardless of whether Y is satisfied or
2181 not). This is a subset of the symbols returned by
2182 get_referenced_symbols()."""
2183 return self.selected_syms
2184
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002185 def set_user_value(self, v):
2186 """Sets the user value of the symbol.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002187
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002188 Equal in effect to assigning the value to the symbol within a .config
2189 file. Use get_lower/upper_bound() or get_assignable_values() to find
2190 the range of currently assignable values for bool and tristate symbols;
2191 setting values outside this range will cause the user value to differ
2192 from the result of Symbol.get_value() (be truncated). Values that are
2193 invalid for the type (such as a_bool.set_user_value("foo")) are
2194 ignored, and a warning is emitted if an attempt is made to assign such
2195 a value.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002196
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002197 For any type of symbol, is_modifiable() can be used to check if a user
2198 value will currently have any effect on the symbol, as determined by
2199 its visibility and range of assignable values. Any value that is valid
2200 for the type (bool, tristate, etc.) will end up being reflected in
2201 get_user_value() though, and might have an effect later if conditions
2202 change. To get rid of the user value, use unset_user_value().
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002203
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002204 Any symbols dependent on the symbol are (recursively) invalidated, so
2205 things will just work with regards to dependencies.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002206
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002207 v: The user value to give to the symbol."""
2208 self._set_user_value_no_invalidate(v, False)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002209
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002210 # There might be something more efficient you could do here, but play
2211 # it safe.
2212 if self.name == "MODULES":
2213 self.config._invalidate_all()
2214 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002215
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002216 self._invalidate()
2217 self._invalidate_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002218
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002219 def unset_user_value(self):
2220 """Resets the user value of the symbol, as if the symbol had never
2221 gotten a user value via Config.load_config() or
2222 Symbol.set_user_value()."""
2223 self._unset_user_value_no_recursive_invalidate()
2224 self._invalidate_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002225
2226 def is_modifiable(self):
2227 """Returns True if the value of the symbol could be modified by calling
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002228 Symbol.set_user_value().
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002229
2230 For bools and tristates, this corresponds to the symbol being visible
2231 in the 'make menuconfig' interface and not already being pinned to a
2232 specific value (e.g. because it is selected by another symbol).
2233
2234 For strings and numbers, this corresponds to just being visible. (See
2235 Symbol.get_visibility().)"""
2236 if self.is_special_:
2237 return False
2238 if self.type == BOOL or self.type == TRISTATE:
2239 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002240 # A bool selected to "m" gets promoted to "y", pinning it
2241 if rev_dep == "m" and self.type == BOOL:
2242 return False
2243 return TRI_TO_INT[_get_visibility(self)] > TRI_TO_INT[rev_dep]
2244 return _get_visibility(self) != "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002245
2246 def is_defined(self):
2247 """Returns False if the symbol is referred to in the Kconfig but never
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002248 actually defined."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002249 return self.is_defined_
2250
2251 def is_special(self):
2252 """Returns True if the symbol is one of the special symbols n, m, y, or
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002253 UNAME_RELEASE, or gets its value from the environment."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002254 return self.is_special_
2255
2256 def is_from_environment(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002257 """Returns True if the symbol gets its value from the environment."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002258 return self.is_from_env
2259
2260 def has_ranges(self):
2261 """Returns True if the symbol is of type INT or HEX and has ranges that
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002262 limit what values it can take on."""
2263 return bool(self.ranges)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002264
2265 def is_choice_symbol(self):
2266 """Returns True if the symbol is in a choice statement and is an actual
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002267 choice symbol (see Choice.get_symbols())."""
2268 return self.is_choice_sym
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002269
2270 def is_choice_selection(self):
2271 """Returns True if the symbol is contained in a choice statement and is
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002272 the selected item. Equivalent to
2273
2274 sym.is_choice_symbol() and sym.get_parent().get_selection() is sym"""
2275 return self.is_choice_sym and self.parent.get_selection() is self
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002276
Masahiro Yamada9d01b782015-05-27 11:39:22 +09002277 def is_allnoconfig_y(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002278 """Returns True if the symbol has the 'allnoconfig_y' option set."""
Masahiro Yamada9d01b782015-05-27 11:39:22 +09002279 return self.allnoconfig_y
2280
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002281 def __str__(self):
2282 """Returns a string containing various information about the symbol."""
2283 return self.config._get_sym_or_choice_str(self)
2284
2285 #
2286 # Private methods
2287 #
2288
2289 def __init__(self):
2290 """Symbol constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002291 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002292
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002293 self.name = None
2294 self.type = UNKNOWN
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002295 self.prompts = []
2296 self.def_exprs = [] # 'default' properties
2297 self.ranges = [] # 'range' properties (for int and hex)
2298 self.help = None # Help text
2299 self.rev_dep = "n" # Reverse (select-related) dependencies
2300 self.config = None
2301 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002302
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002303 self.user_val = None # Value set by user
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002304
2305 # The prompt, default value and select conditions without any
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002306 # dependencies from menus and ifs propagated to them
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002307 self.orig_prompts = []
2308 self.orig_def_exprs = []
2309 self.orig_selects = []
2310
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002311 # Dependencies inherited from containing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002312 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002313 # The set of symbols referenced by this symbol (see
2314 # get_referenced_symbols())
2315 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002316 # The set of symbols selected by this symbol (see
2317 # get_selected_symbols())
2318 self.selected_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002319 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002320 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002321 self.all_referenced_syms = set()
2322
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002323 # This records only dependencies specified with 'depends on'. Needed
2324 # when determining actual choice items (hrrrr...). See also
2325 # Choice._determine_actual_symbols().
2326 self.menu_dep = None
2327
2328 # See Symbol.get_ref/def_locations().
2329 self.def_locations = []
2330 self.ref_locations = []
2331
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002332 # Populated in Config._build_dep() after parsing. Links the symbol to
2333 # the symbols that immediately depend on it (in a caching/invalidation
2334 # sense). The total set of dependent symbols for the symbol (the
2335 # transitive closure) is calculated on an as-needed basis in
2336 # _get_dependent().
2337 self.dep = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002338
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002339 # Cached values
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002340
2341 # Caches the calculated value
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002342 self.cached_val = None
2343 # Caches the visibility, which acts as an upper bound on the value
2344 self.cached_visibility = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002345 # Caches the total list of dependent symbols. Calculated in
2346 # _get_dependent().
2347 self.cached_deps = None
2348
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002349 # Flags
2350
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002351 # Does the symbol have an entry in the Kconfig file? The trailing
2352 # underscore avoids a collision with is_defined().
2353 self.is_defined_ = False
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002354 # Should the symbol get an entry in .config?
2355 self.write_to_conf = False
2356 # Set to true when _make_conf() is called on a symbol, so that symbols
2357 # defined in multiple locations only get one .config entry. We need to
2358 # reset it prior to writing out a new .config.
2359 self.already_written = False
2360 # This is set to True for "actual" choice symbols; see
2361 # Choice._determine_actual_symbols().
2362 self.is_choice_sym = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002363 # Does the symbol get its value in some special way, e.g. from the
2364 # environment or by being one of the special symbols n, m, and y? If
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002365 # so, the value is stored in self.cached_val, which is never
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002366 # invalidated. The trailing underscore avoids a collision with
2367 # is_special().
2368 self.is_special_ = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002369 # Does the symbol get its value from the environment?
2370 self.is_from_env = False
Masahiro Yamada9d01b782015-05-27 11:39:22 +09002371 # Does the symbol have the 'allnoconfig_y' option set?
2372 self.allnoconfig_y = False
2373
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002374 def _invalidate(self):
2375 if self.is_special_:
2376 return
2377
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002378 if self.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002379 self.parent._invalidate()
2380
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002381 self.cached_val = None
2382 self.cached_visibility = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002383
2384 def _invalidate_dependent(self):
2385 for sym in self._get_dependent():
2386 sym._invalidate()
2387
2388 def _set_user_value_no_invalidate(self, v, suppress_load_warnings):
2389 """Like set_user_value(), but does not invalidate any symbols.
2390
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002391 suppress_load_warnings: some warnings are annoying when loading a
2392 .config that can be helpful when manually invoking set_user_value().
2393 This flag is set to True to suppress such warnings.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002394
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002395 Perhaps this could be made optional for load_config() instead."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002396
2397 if self.is_special_:
2398 if self.is_from_env:
2399 self.config._warn('attempt to assign the value "{0}" to the '
2400 'symbol {1}, which gets its value from the '
2401 'environment. Assignment ignored.'
2402 .format(v, self.name))
2403 else:
2404 self.config._warn('attempt to assign the value "{0}" to the '
2405 'special symbol {1}. Assignment ignored.'
2406 .format(v, self.name))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002407 return
2408
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002409 if not self.is_defined_:
2410 filename, linenr = self.ref_locations[0]
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002411 if self.config.print_undef_assign:
2412 _stderr_msg('note: attempt to assign the value "{0}" to {1}, '
2413 "which is referenced at {2}:{3} but never "
2414 "defined. Assignment ignored."
2415 .format(v, self.name, filename, linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002416 return
2417
2418 # Check if the value is valid for our type
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002419 if not ((self.type == BOOL and (v == "y" or v == "n") ) or
2420 (self.type == TRISTATE and (v == "y" or v == "m" or
2421 v == "n") ) or
2422 (self.type == STRING ) or
2423 (self.type == INT and _is_base_n(v, 10) ) or
2424 (self.type == HEX and _is_base_n(v, 16) )):
2425 self.config._warn('the value "{0}" is invalid for {1}, which has '
2426 "type {2}. Assignment ignored."
2427 .format(v, self.name, TYPENAME[self.type]))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002428 return
2429
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002430 if not self.prompts and not suppress_load_warnings:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002431 self.config._warn('assigning "{0}" to the symbol {1} which '
2432 'lacks prompts and thus has visibility "n". '
2433 'The assignment will have no effect.'
2434 .format(v, self.name))
2435
2436 self.user_val = v
2437
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002438 if self.is_choice_sym and (self.type == BOOL or self.type == TRISTATE):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002439 choice = self.parent
2440 if v == "y":
2441 choice.user_val = self
2442 choice.user_mode = "y"
2443 elif v == "m":
2444 choice.user_val = None
2445 choice.user_mode = "m"
2446
2447 def _unset_user_value_no_recursive_invalidate(self):
2448 self._invalidate()
2449 self.user_val = None
2450
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002451 if self.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002452 self.parent._unset_user_value()
2453
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002454 def _make_conf(self, append_fn):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002455 if self.already_written:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002456 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002457
2458 self.already_written = True
2459
2460 # Note: write_to_conf is determined in get_value()
2461 val = self.get_value()
2462 if not self.write_to_conf:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002463 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002464
2465 if self.type == BOOL or self.type == TRISTATE:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002466 if val == "y" or val == "m":
2467 append_fn("CONFIG_{0}={1}".format(self.name, val))
2468 else:
2469 append_fn("# CONFIG_{0} is not set".format(self.name))
2470
2471 elif self.type == INT or self.type == HEX:
2472 append_fn("CONFIG_{0}={1}".format(self.name, val))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002473
2474 elif self.type == STRING:
2475 # Escape \ and "
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002476 append_fn('CONFIG_{0}="{1}"'
2477 .format(self.name,
2478 val.replace("\\", "\\\\").replace('"', '\\"')))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002479
2480 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002481 _internal_error("Internal error while creating .config: unknown "
2482 'type "{0}".'.format(self.type))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002483
2484 def _get_dependent(self):
2485 """Returns the set of symbols that should be invalidated if the value
2486 of the symbol changes, because they might be affected by the change.
2487 Note that this is an internal API -- it's probably of limited
2488 usefulness to clients."""
2489 if self.cached_deps is not None:
2490 return self.cached_deps
2491
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002492 res = set(self.dep)
2493 for s in self.dep:
2494 res |= s._get_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002495
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002496 if self.is_choice_sym:
2497 # Choice symbols also depend (recursively) on their siblings. The
2498 # siblings are not included in 'dep' to avoid dependency loops.
2499 for sibling in self.parent.actual_symbols:
2500 if sibling is not self:
2501 res.add(sibling)
2502 res |= sibling.dep
2503 for s in sibling.dep:
2504 res |= s._get_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002505
2506 self.cached_deps = res
2507 return res
2508
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002509 def _has_auto_menu_dep_on(self, on):
2510 """See Choice._determine_actual_symbols()."""
2511 if not isinstance(self.parent, Choice):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002512 _internal_error("Attempt to determine auto menu dependency for "
2513 "symbol ouside of choice.")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002514
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002515 if not self.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002516 # If we have no prompt, use the menu dependencies instead (what was
2517 # specified with 'depends on')
2518 return self.menu_dep is not None and \
2519 self.config._expr_depends_on(self.menu_dep, on)
2520
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002521 for _, cond_expr in self.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002522 if self.config._expr_depends_on(cond_expr, on):
2523 return True
2524
2525 return False
2526
2527class Menu(Item):
2528
2529 """Represents a menu statement."""
2530
2531 #
2532 # Public interface
2533 #
2534
2535 def get_config(self):
2536 """Return the Config instance this menu is from."""
2537 return self.config
2538
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002539 def get_title(self):
2540 """Returns the title text of the menu."""
2541 return self.title
2542
2543 def get_parent(self):
2544 """Returns the menu or choice statement that contains the menu, or
2545 None if the menu is at the top level. Note that if statements are
2546 treated as syntactic sugar and do not have an explicit class
2547 representation."""
2548 return self.parent
2549
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002550 def get_location(self):
2551 """Returns the location of the menu as a (filename, linenr) tuple,
2552 where filename is a string and linenr an int."""
2553 return (self.filename, self.linenr)
2554
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002555 def get_items(self, recursive=False):
2556 """Returns a list containing the items (symbols, menus, choice
2557 statements and comments) in in the menu, in the same order that the
2558 items appear within the menu.
2559
2560 recursive (default: False): True if items contained in items within the
2561 menu should be included recursively (preorder)."""
2562
2563 if not recursive:
2564 return self.block
2565
2566 res = []
2567 for item in self.block:
2568 res.append(item)
2569 if isinstance(item, Menu):
2570 res.extend(item.get_items(True))
2571 elif isinstance(item, Choice):
2572 res.extend(item.get_items())
2573 return res
2574
2575 def get_symbols(self, recursive=False):
2576 """Returns a list containing the symbols in the menu, in the same order
2577 that they appear within the menu.
2578
2579 recursive (default: False): True if symbols contained in items within
2580 the menu should be included recursively."""
2581
2582 return [item for item in self.get_items(recursive) if
2583 isinstance(item, Symbol)]
2584
2585 def get_visibility(self):
2586 """Returns the visibility of the menu. This also affects the visibility
2587 of subitems. See also Symbol.get_visibility()."""
2588 return self.config._eval_expr(self.dep_expr)
2589
2590 def get_visible_if_visibility(self):
2591 """Returns the visibility the menu gets from its 'visible if'
2592 condition. "y" if the menu has no 'visible if' condition."""
2593 return self.config._eval_expr(self.visible_if_expr)
2594
2595 def get_referenced_symbols(self, refs_from_enclosing=False):
2596 """See Symbol.get_referenced_symbols()."""
2597 return self.all_referenced_syms if refs_from_enclosing else \
2598 self.referenced_syms
2599
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002600 def __str__(self):
2601 """Returns a string containing various information about the menu."""
2602 depends_on_str = self.config._expr_val_str(self.orig_deps,
2603 "(no dependencies)")
2604 visible_if_str = self.config._expr_val_str(self.visible_if_expr,
2605 "(no dependencies)")
2606
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002607 additional_deps_str = " " + \
2608 self.config._expr_val_str(self.deps_from_containing,
2609 "(no additional dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002610
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002611 return _lines("Menu",
2612 "Title : " + self.title,
2613 "'depends on' dependencies : " + depends_on_str,
2614 "'visible if' dependencies : " + visible_if_str,
2615 "Additional dependencies from enclosing menus and "
2616 "ifs:",
2617 additional_deps_str,
2618 "Location: {0}:{1}".format(self.filename, self.linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002619
2620 #
2621 # Private methods
2622 #
2623
2624 def __init__(self):
2625 """Menu constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002626 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002627
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002628 self.title = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002629 self.dep_expr = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002630 self.visible_if_expr = None
2631 self.block = None
2632 self.config = None
2633 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002634
2635 # Dependency expression without dependencies from enclosing menus and
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002636 # ifs propagated
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002637 self.orig_deps = None
2638
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002639 # Dependencies inherited from containing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002640 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002641 # The set of symbols referenced by this menu (see
2642 # get_referenced_symbols())
2643 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002644 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002645 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002646 self.all_referenced_syms = None
2647
2648 self.filename = None
2649 self.linenr = None
2650
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002651 def _make_conf(self, append_fn):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002652 if self.config._eval_expr(self.dep_expr) != "n" and \
2653 self.config._eval_expr(self.visible_if_expr) != "n":
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002654 append_fn("\n#\n# {0}\n#".format(self.title))
2655 _make_block_conf(self.block, append_fn)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002656
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002657class Choice(Item):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002658
2659 """Represents a choice statement. A choice can be in one of three modes:
2660
2661 "n" - The choice is not visible and no symbols can be selected.
2662
2663 "m" - Any number of symbols can be set to "m". The rest will be "n". This
2664 is safe since potentially conflicting options don't actually get
2665 compiled into the kernel simultaneously with "m".
2666
2667 "y" - One symbol will be "y" while the rest are "n".
2668
2669 Only tristate choices can be in "m" mode, and the visibility of the choice
2670 is an upper bound on the mode, so that e.g. a choice that depends on a
2671 symbol with value "m" will be in "m" mode.
2672
2673 The mode changes automatically when a value is assigned to a symbol within
2674 the choice.
2675
2676 See Symbol.get_visibility() too."""
2677
2678 #
2679 # Public interface
2680 #
2681
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002682 def get_config(self):
2683 """Returns the Config instance this choice is from."""
2684 return self.config
2685
2686 def get_name(self):
2687 """For named choices, returns the name. Returns None for unnamed
2688 choices. No named choices appear anywhere in the kernel Kconfig files
2689 as of Linux 3.7.0-rc8."""
2690 return self.name
2691
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002692 def get_type(self):
2693 """Returns the type of the choice. See Symbol.get_type()."""
2694 return self.type
2695
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002696 def get_prompts(self):
2697 """Returns a list of prompts defined for the choice, in the order they
2698 appear in the configuration files. Returns the empty list for choices
2699 with no prompt.
2700
2701 This list will have a single entry for the vast majority of choices
2702 having prompts, but having multiple prompts for a single choice is
2703 possible through having multiple 'choice' entries for it (though I'm
2704 not sure if that ever happens in practice)."""
2705 return [prompt for prompt, _ in self.orig_prompts]
2706
2707 def get_help(self):
2708 """Returns the help text of the choice, or None if the choice has no
2709 help text."""
2710 return self.help
2711
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002712 def get_parent(self):
2713 """Returns the menu or choice statement that contains the choice, or
2714 None if the choice is at the top level. Note that if statements are
2715 treated as syntactic sugar and do not have an explicit class
2716 representation."""
2717 return self.parent
2718
2719 def get_def_locations(self):
2720 """Returns a list of (filename, linenr) tuples, where filename (string)
2721 and linenr (int) represent a location where the choice is defined. For
2722 the vast majority of choices (all of them as of Linux 3.7.0-rc8) this
2723 list will only contain one element, but its possible for named choices
2724 to be defined in multiple locations."""
2725 return self.def_locations
2726
2727 def get_selection(self):
2728 """Returns the symbol selected (either by the user or through
2729 defaults), or None if either no symbol is selected or the mode is not
2730 "y"."""
2731 if self.cached_selection is not None:
2732 if self.cached_selection == NO_SELECTION:
2733 return None
2734 return self.cached_selection
2735
2736 if self.get_mode() != "y":
2737 return self._cache_ret(None)
2738
2739 # User choice available?
2740 if self.user_val is not None and _get_visibility(self.user_val) == "y":
2741 return self._cache_ret(self.user_val)
2742
2743 if self.optional:
2744 return self._cache_ret(None)
2745
2746 return self._cache_ret(self.get_selection_from_defaults())
2747
2748 def get_selection_from_defaults(self):
2749 """Like Choice.get_selection(), but acts as if no symbol has been
2750 selected by the user and no 'optional' flag is in effect."""
2751
2752 if not self.actual_symbols:
2753 return None
2754
2755 for symbol, cond_expr in self.def_exprs:
2756 if self.config._eval_expr(cond_expr) != "n":
2757 chosen_symbol = symbol
2758 break
2759 else:
2760 chosen_symbol = self.actual_symbols[0]
2761
2762 # Is the chosen symbol visible?
2763 if _get_visibility(chosen_symbol) != "n":
2764 return chosen_symbol
2765 # Otherwise, pick the first visible symbol
2766 for sym in self.actual_symbols:
2767 if _get_visibility(sym) != "n":
2768 return sym
2769 return None
2770
2771 def get_user_selection(self):
2772 """If the choice is in "y" mode and has a user-selected symbol, returns
2773 that symbol. Otherwise, returns None."""
2774 return self.user_val
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002775
2776 def get_items(self):
2777 """Gets all items contained in the choice in the same order as within
2778 the configuration ("items" instead of "symbols" since choices and
2779 comments might appear within choices. This only happens in one place as
2780 of Linux 3.7.0-rc8, in drivers/usb/gadget/Kconfig)."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002781 return self.block
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002782
2783 def get_symbols(self):
2784 """Returns a list containing the choice's symbols.
2785
2786 A quirk (perhaps a bug) of Kconfig is that you can put items within a
2787 choice that will not be considered members of the choice insofar as
2788 selection is concerned. This happens for example if one symbol within a
2789 choice 'depends on' the symbol preceding it, or if you put non-symbol
2790 items within choices.
2791
2792 As of Linux 3.7.0-rc8, this seems to be used intentionally in one
2793 place: drivers/usb/gadget/Kconfig.
2794
2795 This function returns the "proper" symbols of the choice in the order
2796 they appear in the choice, excluding such items. If you want all items
2797 in the choice, use get_items()."""
2798 return self.actual_symbols
2799
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002800 def get_referenced_symbols(self, refs_from_enclosing=False):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002801 """See Symbol.get_referenced_symbols()."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002802 return self.all_referenced_syms if refs_from_enclosing else \
2803 self.referenced_syms
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002804
2805 def get_visibility(self):
2806 """Returns the visibility of the choice statement: one of "n", "m" or
2807 "y". This acts as an upper limit on the mode of the choice (though bool
2808 choices can only have the mode "y"). See the class documentation for an
2809 explanation of modes."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002810 return _get_visibility(self)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002811
2812 def get_mode(self):
2813 """Returns the mode of the choice. See the class documentation for
2814 an explanation of modes."""
2815 minimum_mode = "n" if self.optional else "m"
2816 mode = self.user_mode if self.user_mode is not None else minimum_mode
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002817 mode = self.config._eval_min(mode, _get_visibility(self))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002818
2819 # Promote "m" to "y" for boolean choices
2820 if mode == "m" and self.type == BOOL:
2821 return "y"
2822
2823 return mode
2824
2825 def is_optional(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002826 """Returns True if the choice has the 'optional' flag set (and so will
2827 default to "n" mode)."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002828 return self.optional
2829
2830 def __str__(self):
2831 """Returns a string containing various information about the choice
2832 statement."""
2833 return self.config._get_sym_or_choice_str(self)
2834
2835 #
2836 # Private methods
2837 #
2838
2839 def __init__(self):
2840 """Choice constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002841 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002842
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002843 self.name = None # Yes, choices can be named
2844 self.type = UNKNOWN
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002845 self.prompts = []
2846 self.def_exprs = [] # 'default' properties
2847 self.help = None # Help text
2848 self.block = None # List of contained items
2849 self.config = None
2850 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002851
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002852 self.user_val = None
2853 self.user_mode = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002854
2855 # We need to filter out symbols that appear within the choice block but
2856 # are not considered choice items (see
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002857 # Choice._determine_actual_symbols()) This list holds the "actual"
2858 # choice items.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002859 self.actual_symbols = []
2860
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002861 # The prompts and default values without any dependencies from
2862 # enclosing menus and ifs propagated
2863 self.orig_prompts = []
2864 self.orig_def_exprs = []
2865
2866 # Dependencies inherited from containing menus and ifs
2867 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002868 # The set of symbols referenced by this choice (see
2869 # get_referenced_symbols())
2870 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002871 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002872 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002873 self.all_referenced_syms = set()
2874
2875 # See Choice.get_def_locations()
2876 self.def_locations = []
2877
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002878 # Cached values
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002879 self.cached_selection = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002880 self.cached_visibility = None
2881
2882 self.optional = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002883
2884 def _determine_actual_symbols(self):
2885 """If a symbol's visibility depends on the preceding symbol within a
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002886 choice, it is no longer viewed as a choice item. (This is quite
2887 possibly a bug, but some things consciously use it... ugh. It stems
2888 from automatic submenu creation.) In addition, it's possible to have
2889 choices and comments within choices, and those shouldn't be considered
2890 choice items either. Only drivers/usb/gadget/Kconfig seems to depend on
2891 any of this. This method computes the "actual" items in the choice and
2892 sets the is_choice_sym flag on them (retrieved via is_choice_symbol()).
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002893
2894 Don't let this scare you: an earlier version simply checked for a
2895 sequence of symbols where all symbols after the first appeared in the
2896 'depends on' expression of the first, and that worked fine. The added
2897 complexity is to be future-proof in the event that
2898 drivers/usb/gadget/Kconfig turns even more sinister. It might very well
2899 be overkilling things (especially if that file is refactored ;)."""
2900
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002901 # Items might depend on each other in a tree structure, so we need a
2902 # stack to keep track of the current tentative parent
2903 stack = []
2904
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002905 for item in self.block:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002906 if not isinstance(item, Symbol):
2907 stack = []
2908 continue
2909
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002910 while stack:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002911 if item._has_auto_menu_dep_on(stack[-1]):
2912 # The item should not be viewed as a choice item, so don't
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002913 # set item.is_choice_sym
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002914 stack.append(item)
2915 break
2916 else:
2917 stack.pop()
2918 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002919 item.is_choice_sym = True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002920 self.actual_symbols.append(item)
2921 stack.append(item)
2922
2923 def _cache_ret(self, selection):
2924 # As None is used to indicate the lack of a cached value we can't use
2925 # that to cache the fact that the choice has no selection. Instead, we
2926 # use the symbolic constant NO_SELECTION.
2927 if selection is None:
2928 self.cached_selection = NO_SELECTION
2929 else:
2930 self.cached_selection = selection
2931
2932 return selection
2933
2934 def _invalidate(self):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002935 self.cached_selection = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002936 self.cached_visibility = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002937
2938 def _unset_user_value(self):
2939 self._invalidate()
2940 self.user_val = None
2941 self.user_mode = None
2942
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002943 def _make_conf(self, append_fn):
2944 _make_block_conf(self.block, append_fn)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002945
2946class Comment(Item):
2947
2948 """Represents a comment statement."""
2949
2950 #
2951 # Public interface
2952 #
2953
2954 def get_config(self):
2955 """Returns the Config instance this comment is from."""
2956 return self.config
2957
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002958 def get_text(self):
2959 """Returns the text of the comment."""
2960 return self.text
2961
2962 def get_parent(self):
2963 """Returns the menu or choice statement that contains the comment, or
2964 None if the comment is at the top level. Note that if statements are
2965 treated as syntactic sugar and do not have an explicit class
2966 representation."""
2967 return self.parent
2968
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002969 def get_location(self):
2970 """Returns the location of the comment as a (filename, linenr) tuple,
2971 where filename is a string and linenr an int."""
2972 return (self.filename, self.linenr)
2973
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002974 def get_visibility(self):
2975 """Returns the visibility of the comment. See also
2976 Symbol.get_visibility()."""
2977 return self.config._eval_expr(self.dep_expr)
2978
2979 def get_referenced_symbols(self, refs_from_enclosing=False):
2980 """See Symbol.get_referenced_symbols()."""
2981 return self.all_referenced_syms if refs_from_enclosing else \
2982 self.referenced_syms
2983
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002984 def __str__(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002985 """Returns a string containing various information about the
2986 comment."""
2987 dep_str = self.config._expr_val_str(self.orig_deps,
2988 "(no dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002989
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002990 additional_deps_str = " " + \
2991 self.config._expr_val_str(self.deps_from_containing,
2992 "(no additional dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002993
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002994 return _lines("Comment",
2995 "Text: " + str(self.text),
2996 "Dependencies: " + dep_str,
2997 "Additional dependencies from enclosing menus and "
2998 "ifs:",
2999 additional_deps_str,
3000 "Location: {0}:{1}".format(self.filename, self.linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003001
3002 #
3003 # Private methods
3004 #
3005
3006 def __init__(self):
3007 """Comment constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003008 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003009
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003010 self.text = None
3011 self.dep_expr = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003012 self.config = None
3013 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003014
3015 # Dependency expression without dependencies from enclosing menus and
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003016 # ifs propagated
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003017 self.orig_deps = None
3018
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003019 # Dependencies inherited from containing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003020 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003021 # The set of symbols referenced by this comment (see
3022 # get_referenced_symbols())
3023 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003024 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003025 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003026 self.all_referenced_syms = None
3027
3028 self.filename = None
3029 self.linenr = None
3030
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003031 def _make_conf(self, append_fn):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003032 if self.config._eval_expr(self.dep_expr) != "n":
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003033 append_fn("\n#\n# {0}\n#".format(self.text))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003034
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003035class Kconfig_Syntax_Error(Exception):
3036 """Exception raised for syntax errors."""
3037 pass
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003038
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003039class Internal_Error(Exception):
3040 """Exception raised for internal errors."""
3041 pass
3042
3043#
3044# Public functions
3045#
3046
3047def tri_less(v1, v2):
3048 """Returns True if the tristate v1 is less than the tristate v2, where "n",
3049 "m" and "y" are ordered from lowest to highest."""
3050 return TRI_TO_INT[v1] < TRI_TO_INT[v2]
3051
3052def tri_less_eq(v1, v2):
3053 """Returns True if the tristate v1 is less than or equal to the tristate
3054 v2, where "n", "m" and "y" are ordered from lowest to highest."""
3055 return TRI_TO_INT[v1] <= TRI_TO_INT[v2]
3056
3057def tri_greater(v1, v2):
3058 """Returns True if the tristate v1 is greater than the tristate v2, where
3059 "n", "m" and "y" are ordered from lowest to highest."""
3060 return TRI_TO_INT[v1] > TRI_TO_INT[v2]
3061
3062def tri_greater_eq(v1, v2):
3063 """Returns True if the tristate v1 is greater than or equal to the tristate
3064 v2, where "n", "m" and "y" are ordered from lowest to highest."""
3065 return TRI_TO_INT[v1] >= TRI_TO_INT[v2]
3066
3067#
3068# Internal classes
3069#
3070
3071class _Feed(object):
3072
3073 """Class for working with sequences in a stream-like fashion; handy for
3074 tokens."""
3075
3076 # This would be more helpful on the item classes, but would remove some
3077 # flexibility
3078 __slots__ = ['items', 'length', 'i']
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003079
3080 def __init__(self, items):
3081 self.items = items
3082 self.length = len(self.items)
3083 self.i = 0
3084
3085 def get_next(self):
3086 if self.i >= self.length:
3087 return None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003088 item = self.items[self.i]
3089 self.i += 1
3090 return item
3091
3092 def peek_next(self):
3093 return None if self.i >= self.length else self.items[self.i]
3094
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003095 def check(self, token):
3096 """Check if the next token is 'token'. If so, remove it from the token
3097 feed and return True. Otherwise, leave it in and return False."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003098 if self.i < self.length and self.items[self.i] == token:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003099 self.i += 1
3100 return True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003101 return False
3102
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003103 def unget_all(self):
3104 self.i = 0
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003105
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003106class _FileFeed(object):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003107
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003108 """Feeds lines from a file. Keeps track of the filename and current line
3109 number. Joins any line ending in \\ with the following line. We need to be
3110 careful to get the line number right in the presence of continuation
3111 lines."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003112
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003113 __slots__ = ['filename', 'lines', 'length', 'linenr']
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003114
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003115 def __init__(self, filename):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003116 self.filename = _clean_up_path(filename)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003117 with open(filename, "r") as f:
3118 # No interleaving of I/O and processing yet. Don't know if it would
3119 # help.
3120 self.lines = f.readlines()
3121 self.length = len(self.lines)
3122 self.linenr = 0
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003123
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003124 def get_next(self):
3125 if self.linenr >= self.length:
3126 return None
3127 line = self.lines[self.linenr]
3128 self.linenr += 1
3129 while line.endswith("\\\n"):
3130 line = line[:-2] + self.lines[self.linenr]
3131 self.linenr += 1
3132 return line
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003133
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003134 def peek_next(self):
3135 linenr = self.linenr
3136 if linenr >= self.length:
3137 return None
3138 line = self.lines[linenr]
3139 while line.endswith("\\\n"):
3140 linenr += 1
3141 line = line[:-2] + self.lines[linenr]
3142 return line
3143
3144 def unget(self):
3145 self.linenr -= 1
3146 while self.lines[self.linenr].endswith("\\\n"):
3147 self.linenr -= 1
3148
3149 def next_nonblank(self):
3150 """Removes lines up to and including the next non-blank (not all-space)
3151 line and returns it. Returns None if there are no more non-blank
3152 lines."""
3153 while 1:
3154 line = self.get_next()
3155 if line is None or not line.isspace():
3156 return line
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003157
3158#
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003159# Internal functions
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003160#
3161
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003162def _get_visibility(sc):
3163 """Symbols and Choices have a "visibility" that acts as an upper bound on
3164 the values a user can set for them, corresponding to the visibility in e.g.
3165 'make menuconfig'. This function calculates the visibility for the Symbol
3166 or Choice 'sc' -- the logic is nearly identical."""
3167 if sc.cached_visibility is None:
3168 vis = "n"
3169 for _, cond_expr in sc.prompts:
3170 vis = sc.config._eval_max(vis, cond_expr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003171
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003172 if isinstance(sc, Symbol) and sc.is_choice_sym:
3173 vis = sc.config._eval_min(vis, _get_visibility(sc.parent))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003174
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003175 # Promote "m" to "y" if we're dealing with a non-tristate
3176 if vis == "m" and sc.type != TRISTATE:
3177 vis = "y"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003178
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003179 sc.cached_visibility = vis
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003180
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003181 return sc.cached_visibility
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003182
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003183def _make_and(e1, e2):
3184 """Constructs an AND (&&) expression. Performs trivial simplification.
3185 Nones equate to 'y'.
3186
3187 Note: returns None if e1 == e2 == None."""
3188 if e1 is None or e1 == "y":
3189 return e2
3190 if e2 is None or e2 == "y":
3191 return e1
3192
3193 # Prefer to merge argument lists if possible to reduce the number of nodes
3194
3195 if isinstance(e1, tuple) and e1[0] == AND:
3196 if isinstance(e2, tuple) and e2[0] == AND:
3197 return (AND, e1[1] + e2[1])
3198 return (AND, e1[1] + [e2])
3199
3200 if isinstance(e2, tuple) and e2[0] == AND:
3201 return (AND, e2[1] + [e1])
3202
3203 return (AND, [e1, e2])
3204
3205def _make_or(e1, e2):
3206 """Constructs an OR (||) expression. Performs trivial simplification and
3207 avoids Nones. Nones equate to 'y', which is usually what we want, but needs
3208 to be kept in mind."""
3209
3210 # Perform trivial simplification and avoid None's (which
3211 # correspond to y's)
3212 if e1 is None or e2 is None or e1 == "y" or e2 == "y":
3213 return "y"
3214 if e1 == "n":
3215 return e2
3216
3217 # Prefer to merge argument lists if possible to reduce the number of nodes
3218
3219 if isinstance(e1, tuple) and e1[0] == OR:
3220 if isinstance(e2, tuple) and e2[0] == OR:
3221 return (OR, e1[1] + e2[1])
3222 return (OR, e1[1] + [e2])
3223
3224 if isinstance(e2, tuple) and e2[0] == OR:
3225 return (OR, e2[1] + [e1])
3226
3227 return (OR, [e1, e2])
3228
3229def _get_expr_syms_rec(expr, res):
3230 """_get_expr_syms() helper. Recurses through expressions."""
3231 if isinstance(expr, Symbol):
3232 res.add(expr)
3233 elif isinstance(expr, str):
3234 return
3235 elif expr[0] == AND or expr[0] == OR:
3236 for term in expr[1]:
3237 _get_expr_syms_rec(term, res)
3238 elif expr[0] == NOT:
3239 _get_expr_syms_rec(expr[1], res)
3240 elif expr[0] == EQUAL or expr[0] == UNEQUAL:
3241 if isinstance(expr[1], Symbol):
3242 res.add(expr[1])
3243 if isinstance(expr[2], Symbol):
3244 res.add(expr[2])
3245 else:
3246 _internal_error("Internal error while fetching symbols from an "
3247 "expression with token stream {0}.".format(expr))
3248
3249def _get_expr_syms(expr):
3250 """Returns the set() of symbols appearing in expr."""
3251 res = set()
3252 if expr is not None:
3253 _get_expr_syms_rec(expr, res)
3254 return res
3255
3256def _str_val(obj):
3257 """Returns the value of obj as a string. If obj is not a string (constant
3258 symbol), it must be a Symbol."""
3259 return obj if isinstance(obj, str) else obj.get_value()
3260
3261def _make_block_conf(block, append_fn):
3262 """Returns a list of .config strings for a block (list) of items."""
3263
3264 # Collect the substrings in a list and later use join() instead of += to
3265 # build the final .config contents. With older Python versions, this yields
3266 # linear instead of quadratic complexity.
3267 for item in block:
3268 item._make_conf(append_fn)
3269
3270def _sym_str_string(sym_or_str):
3271 if isinstance(sym_or_str, str):
3272 return '"' + sym_or_str + '"'
3273 return sym_or_str.name
3274
3275def _intersperse(lst, op):
3276 """_expr_to_str() helper. Gets the string representation of each expression
3277 in lst and produces a list where op has been inserted between the
3278 elements."""
3279 if not lst:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003280 return ""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003281
3282 res = []
3283
3284 def handle_sub_expr(expr):
3285 no_parens = isinstance(expr, (str, Symbol)) or \
3286 expr[0] in (EQUAL, UNEQUAL) or \
3287 PRECEDENCE[op] <= PRECEDENCE[expr[0]]
3288 if not no_parens:
3289 res.append("(")
3290 res.extend(_expr_to_str_rec(expr))
3291 if not no_parens:
3292 res.append(")")
3293
3294 op_str = OP_TO_STR[op]
3295
3296 handle_sub_expr(lst[0])
3297 for expr in lst[1:]:
3298 res.append(op_str)
3299 handle_sub_expr(expr)
3300
3301 return res
3302
3303def _expr_to_str_rec(expr):
3304 if expr is None:
3305 return [""]
3306
3307 if isinstance(expr, (Symbol, str)):
3308 return [_sym_str_string(expr)]
3309
3310 if expr[0] in (AND, OR):
3311 return _intersperse(expr[1], expr[0])
3312
3313 if expr[0] == NOT:
3314 need_parens = not isinstance(expr[1], (str, Symbol))
3315
3316 res = ["!"]
3317 if need_parens:
3318 res.append("(")
3319 res.extend(_expr_to_str_rec(expr[1]))
3320 if need_parens:
3321 res.append(")")
3322 return res
3323
3324 if expr[0] in (EQUAL, UNEQUAL):
3325 return [_sym_str_string(expr[1]),
3326 OP_TO_STR[expr[0]],
3327 _sym_str_string(expr[2])]
3328
3329def _expr_to_str(expr):
3330 return "".join(_expr_to_str_rec(expr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003331
3332def _indentation(line):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003333 """Returns the length of the line's leading whitespace, treating tab stops
3334 as being spaced 8 characters apart."""
3335 line = line.expandtabs()
3336 return len(line) - len(line.lstrip())
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003337
3338def _deindent(line, indent):
3339 """Deindent 'line' by 'indent' spaces."""
3340 line = line.expandtabs()
3341 if len(line) <= indent:
3342 return line
3343 return line[indent:]
3344
3345def _is_base_n(s, n):
3346 try:
3347 int(s, n)
3348 return True
3349 except ValueError:
3350 return False
3351
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003352def _lines(*args):
3353 """Returns a string consisting of all arguments, with newlines inserted
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003354 between them."""
3355 return "\n".join(args)
3356
3357def _comment(s):
3358 """Returns a new string with "#" inserted before each line in 's'."""
3359 if not s:
3360 return "#"
3361 res = "".join(["#" + line for line in s.splitlines(True)])
3362 if s.endswith("\n"):
3363 return res + "#"
3364 return res
3365
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003366def _clean_up_path(path):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003367 """Strips an initial "./" and any trailing slashes from 'path'."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003368 if path.startswith("./"):
3369 path = path[2:]
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003370 return path.rstrip("/")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003371
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003372def _stderr_msg(msg, filename, linenr):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003373 if filename is not None:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003374 sys.stderr.write("{0}:{1}: ".format(_clean_up_path(filename), linenr))
3375 sys.stderr.write(msg + "\n")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003376
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003377def _tokenization_error(s, filename, linenr):
3378 loc = "" if filename is None else "{0}:{1}: ".format(filename, linenr)
3379 raise Kconfig_Syntax_Error("{0}Couldn't tokenize '{1}'"
3380 .format(loc, s.strip()))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003381
3382def _parse_error(s, msg, filename, linenr):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003383 loc = "" if filename is None else "{0}:{1}: ".format(filename, linenr)
3384 raise Kconfig_Syntax_Error("{0}Couldn't parse '{1}'{2}"
3385 .format(loc, s.strip(),
3386 "." if msg is None else ": " + msg))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003387
3388def _internal_error(msg):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003389 raise Internal_Error(msg +
3390 "\nSorry! You may want to send an email to ulfalizer a.t Google's "
3391 "email service to tell me about this. Include the message above and the "
3392 "stack trace and describe what you were doing.")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003393
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003394#
3395# Internal global constants
3396#
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003397
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003398# Tokens
3399(T_AND, T_OR, T_NOT,
3400 T_OPEN_PAREN, T_CLOSE_PAREN,
3401 T_EQUAL, T_UNEQUAL,
3402 T_MAINMENU, T_MENU, T_ENDMENU,
3403 T_SOURCE, T_CHOICE, T_ENDCHOICE,
3404 T_COMMENT, T_CONFIG, T_MENUCONFIG,
3405 T_HELP, T_IF, T_ENDIF, T_DEPENDS, T_ON,
3406 T_OPTIONAL, T_PROMPT, T_DEFAULT,
3407 T_BOOL, T_TRISTATE, T_HEX, T_INT, T_STRING,
3408 T_DEF_BOOL, T_DEF_TRISTATE,
3409 T_SELECT, T_RANGE, T_OPTION, T_ALLNOCONFIG_Y, T_ENV,
3410 T_DEFCONFIG_LIST, T_MODULES, T_VISIBLE) = range(39)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003411
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003412# The leading underscore before the function assignments below prevent pydoc
3413# from listing them. The constants could be hidden too, but they're fairly
3414# obviously internal anyway, so don't bother spamming the code.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003415
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003416# Keyword to token map. Note that the get() method is assigned directly as a
3417# small optimization.
3418_get_keyword = \
3419 {"mainmenu": T_MAINMENU, "menu": T_MENU, "endmenu": T_ENDMENU,
3420 "endif": T_ENDIF, "endchoice": T_ENDCHOICE, "source": T_SOURCE,
3421 "choice": T_CHOICE, "config": T_CONFIG, "comment": T_COMMENT,
3422 "menuconfig": T_MENUCONFIG, "help": T_HELP, "if": T_IF,
3423 "depends": T_DEPENDS, "on": T_ON, "optional": T_OPTIONAL,
3424 "prompt": T_PROMPT, "default": T_DEFAULT, "bool": T_BOOL, "boolean": T_BOOL,
3425 "tristate": T_TRISTATE, "int": T_INT, "hex": T_HEX, "def_bool": T_DEF_BOOL,
3426 "def_tristate": T_DEF_TRISTATE, "string": T_STRING, "select": T_SELECT,
3427 "range": T_RANGE, "option": T_OPTION, "allnoconfig_y": T_ALLNOCONFIG_Y,
3428 "env": T_ENV, "defconfig_list": T_DEFCONFIG_LIST, "modules": T_MODULES,
3429 "visible": T_VISIBLE}.get
3430
3431# Strings to use for True and False
3432BOOL_STR = {False: "false", True: "true"}
3433
3434# Tokens after which identifier-like lexemes are treated as strings. T_CHOICE
3435# is included to avoid symbols being registered for named choices.
3436STRING_LEX = frozenset((T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING, T_CHOICE,
3437 T_PROMPT, T_MENU, T_COMMENT, T_SOURCE, T_MAINMENU))
3438
3439# Matches the initial token on a line; see _tokenize(). Also eats trailing
3440# whitespace as an optimization.
3441_initial_token_re_match = re.compile(r"[^\w]*(\w+)\s*").match
3442
3443# Matches an identifier/keyword optionally preceded by whitespace. Also eats
3444# trailing whitespace as an optimization.
3445_id_keyword_re_match = re.compile(r"\s*([\w./-]+)\s*").match
3446
3447# Regular expressions for parsing .config files
3448_set_re_match = re.compile(r"CONFIG_(\w+)=(.*)").match
3449_unset_re_match = re.compile(r"# CONFIG_(\w+) is not set").match
3450
3451# Regular expression for finding $-references to symbols in strings
3452_sym_ref_re_search = re.compile(r"\$[A-Za-z0-9_]+").search
3453
3454# Integers representing symbol types
3455UNKNOWN, BOOL, TRISTATE, STRING, HEX, INT = range(6)
3456
3457# Strings to use for types
3458TYPENAME = {UNKNOWN: "unknown", BOOL: "bool", TRISTATE: "tristate",
3459 STRING: "string", HEX: "hex", INT: "int"}
3460
3461# Token to type mapping
3462TOKEN_TO_TYPE = {T_BOOL: BOOL, T_TRISTATE: TRISTATE, T_STRING: STRING,
3463 T_INT: INT, T_HEX: HEX}
3464
3465# Default values for symbols of different types (the value the symbol gets if
3466# it is not assigned a user value and none of its 'default' clauses kick in)
3467DEFAULT_VALUE = {BOOL: "n", TRISTATE: "n", STRING: "", INT: "", HEX: ""}
3468
3469# Indicates that no item is selected in a choice statement
3470NO_SELECTION = 0
3471
3472# Integers representing expression types
3473AND, OR, NOT, EQUAL, UNEQUAL = range(5)
3474
3475# Map from tristate values to integers
3476TRI_TO_INT = {"n": 0, "m": 1, "y": 2}
3477
3478# Printing-related stuff
3479
3480OP_TO_STR = {AND: " && ", OR: " || ", EQUAL: " = ", UNEQUAL: " != "}
3481PRECEDENCE = {OR: 0, AND: 1, NOT: 2}