blob: 68b470a3a7d9adfc5ec48647d6a6e899b63d8b5d [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
Ulf Magnusson4e1102f2017-09-19 12:52:55 +020076import platform
Masahiro Yamadaf219e012014-09-01 19:57:37 +090077import re
Masahiro Yamadaf219e012014-09-01 19:57:37 +090078import sys
79
Ulf Magnusson90c36d82015-08-13 19:55:40 +020080# File layout:
81#
82# Public classes
83# Public functions
84# Internal classes
85# Internal functions
86# Internal global constants
87
88# Line length: 79 columns
89
90#
91# Public classes
92#
93
94class Config(object):
Masahiro Yamadaf219e012014-09-01 19:57:37 +090095
96 """Represents a Kconfig configuration, e.g. for i386 or ARM. This is the
97 set of symbols and other items appearing in the configuration together with
98 their values. Creating any number of Config objects -- including for
99 different architectures -- is safe; Kconfiglib has no global state."""
100
101 #
102 # Public interface
103 #
104
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200105 def __init__(self, filename="Kconfig", base_dir=None, print_warnings=True,
106 print_undef_assign=False):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900107 """Creates a new Config object, representing a Kconfig configuration.
108 Raises Kconfig_Syntax_Error on syntax errors.
109
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200110 filename (default: "Kconfig"): The base Kconfig file of the
111 configuration. For the Linux kernel, you'll probably want "Kconfig"
112 from the top-level directory, as environment variables will make
113 sure the right Kconfig is included from there
114 (arch/<architecture>/Kconfig). If you are using Kconfiglib via 'make
115 scriptconfig', the filename of the base base Kconfig file will be in
116 sys.argv[1].
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900117
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200118 base_dir (default: None): The base directory relative to which 'source'
119 statements within Kconfig files will work. For the Linux kernel this
120 should be the top-level directory of the kernel tree. $-references
121 to existing environment variables will be expanded.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900122
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200123 If None (the default), the environment variable 'srctree' will be
124 used if set, and the current directory otherwise. 'srctree' is set
125 by the Linux makefiles to the top-level kernel directory. A default
126 of "." would not work with an alternative build directory.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900127
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200128 print_warnings (default: True): Set to True if warnings related to this
129 configuration should be printed to stderr. This can be changed later
130 with Config.set_print_warnings(). It is provided as a constructor
131 argument since warnings might be generated during parsing.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900132
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200133 print_undef_assign (default: False): Set to True if informational
134 messages related to assignments to undefined symbols should be
135 printed to stderr for this configuration. Can be changed later with
136 Config.set_print_undef_assign()."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900137
138 # The set of all symbols, indexed by name (a string)
139 self.syms = {}
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200140 # Python 2/3 compatibility hack. This is the only one needed.
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200141 self.syms_iter = self.syms.values if sys.version_info[0] >= 3 else \
142 self.syms.itervalues
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900143
144 # The set of all defined symbols in the configuration in the order they
145 # appear in the Kconfig files. This excludes the special symbols n, m,
146 # and y as well as symbols that are referenced but never defined.
147 self.kconfig_syms = []
148
149 # The set of all named choices (yes, choices can have names), indexed
150 # by name (a string)
151 self.named_choices = {}
152
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200153 # Lists containing all choices, menus and comments in the configuration
154 self.choices = []
155 self.menus = []
156 self.comments = []
157
158 def register_special_symbol(type_, name, val):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900159 sym = Symbol()
160 sym.is_special_ = True
161 sym.is_defined_ = True
162 sym.config = self
163 sym.name = name
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200164 sym.type = type_
165 sym.cached_val = val
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900166 self.syms[name] = sym
167 return sym
168
169 # The special symbols n, m and y, used as shorthand for "n", "m" and
170 # "y"
171 self.n = register_special_symbol(TRISTATE, "n", "n")
172 self.m = register_special_symbol(TRISTATE, "m", "m")
173 self.y = register_special_symbol(TRISTATE, "y", "y")
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900174 # DEFCONFIG_LIST uses this
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200175 register_special_symbol(STRING, "UNAME_RELEASE", platform.uname()[2])
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900176
177 # The symbol with "option defconfig_list" set, containing a list of
178 # default .config files
179 self.defconfig_sym = None
180
181 # See Symbol.get_(src)arch()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200182 self.arch = os.environ.get("ARCH")
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900183 self.srcarch = os.environ.get("SRCARCH")
184
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200185 # If you set CONFIG_ in the environment, Kconfig will prefix all symbols
186 # with its value when saving the configuration, instead of using the default, "CONFIG_".
187 self.config_prefix = os.environ.get("CONFIG_")
188 if self.config_prefix is None:
189 self.config_prefix = "CONFIG_"
190
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900191 # See Config.__init__(). We need this for get_defconfig_filename().
192 self.srctree = os.environ.get("srctree")
193 if self.srctree is None:
194 self.srctree = "."
195
196 self.filename = filename
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200197 self.base_dir = self.srctree if base_dir is None else \
198 os.path.expandvars(base_dir)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900199
200 # The 'mainmenu' text
201 self.mainmenu_text = None
202
203 # The filename of the most recently loaded .config file
204 self.config_filename = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900205 # The textual header of the most recently loaded .config, uncommented
206 self.config_header = None
207
208 self.print_warnings = print_warnings
209 self.print_undef_assign = print_undef_assign
Simon Glass8639f692017-08-04 03:30:30 -0600210 self._warnings = []
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900211
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900212 # For parsing routines that stop when finding a line belonging to a
213 # different construct, these holds that line and the tokenized version
214 # of that line. The purpose is to avoid having to re-tokenize the line,
215 # which is inefficient and causes problems when recording references to
216 # symbols.
217 self.end_line = None
218 self.end_line_tokens = None
219
220 # See the comment in _parse_expr().
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200221 self._cur_item = None
222 self._line = None
223 self._filename = None
224 self._linenr = None
225 self._transform_m = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900226
227 # Parse the Kconfig files
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200228 self.top_block = []
229 self._parse_file(filename, None, None, None, self.top_block)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900230
231 # Build Symbol.dep for all symbols
232 self._build_dep()
233
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900234 def get_arch(self):
235 """Returns the value the environment variable ARCH had at the time the
236 Config instance was created, or None if ARCH was not set. For the
237 kernel, this corresponds to the architecture being built for, with
238 values such as "i386" or "mips"."""
239 return self.arch
240
241 def get_srcarch(self):
242 """Returns the value the environment variable SRCARCH had at the time
243 the Config instance was created, or None if SRCARCH was not set. For
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200244 the kernel, this corresponds to the particular arch/ subdirectory
245 containing architecture-specific code."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900246 return self.srcarch
247
248 def get_srctree(self):
249 """Returns the value the environment variable srctree had at the time
250 the Config instance was created, or None if srctree was not defined.
251 This variable points to the source directory and is used when building
252 in a separate directory."""
253 return self.srctree
254
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200255 def get_base_dir(self):
256 """Returns the base directory relative to which 'source' statements
257 will work, passed as an argument to Config.__init__()."""
258 return self.base_dir
259
260 def get_kconfig_filename(self):
261 """Returns the name of the (base) kconfig file this configuration was
262 loaded from."""
263 return self.filename
264
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900265 def get_config_filename(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200266 """Returns the filename of the most recently loaded configuration file,
267 or None if no configuration has been loaded."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900268 return self.config_filename
269
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200270 def get_config_header(self):
271 """Returns the (uncommented) textual header of the .config file most
272 recently loaded with load_config(). Returns None if no .config file has
273 been loaded or if the most recently loaded .config file has no header.
274 The header consists of all lines up to but not including the first line
275 that either
276
277 1. Does not start with "#"
278 2. Has the form "# CONFIG_FOO is not set."
279 """
280 return self.config_header
281
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900282 def get_mainmenu_text(self):
283 """Returns the text of the 'mainmenu' statement (with $-references to
284 symbols replaced by symbol values), or None if the configuration has no
285 'mainmenu' statement."""
286 return None if self.mainmenu_text is None else \
287 self._expand_sym_refs(self.mainmenu_text)
288
289 def get_defconfig_filename(self):
290 """Returns the name of the defconfig file, which is the first existing
291 file in the list given in a symbol having 'option defconfig_list' set.
292 $-references to symbols will be expanded ("$FOO bar" -> "foo bar" if
293 FOO has the value "foo"). Returns None in case of no defconfig file.
294 Setting 'option defconfig_list' on multiple symbols currently results
295 in undefined behavior.
296
297 If the environment variable 'srctree' was set when the Config was
298 created, get_defconfig_filename() will first look relative to that
299 directory before looking in the current directory; see
Masahiro Yamada9d01b782015-05-27 11:39:22 +0900300 Config.__init__().
301
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200302 WARNING: A wart here is that scripts/kconfig/Makefile sometimes uses
303 the --defconfig=<defconfig> option when calling the C implementation of
304 e.g. 'make defconfig'. This option overrides the 'option
305 defconfig_list' symbol, meaning the result from
306 get_defconfig_filename() might not match what 'make defconfig' would
307 use. That probably ought to be worked around somehow, so that this
308 function always gives the "expected" result."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900309 if self.defconfig_sym is None:
310 return None
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200311 for filename, cond_expr in self.defconfig_sym.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900312 if self._eval_expr(cond_expr) == "y":
313 filename = self._expand_sym_refs(filename)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900314 # We first look in $srctree. os.path.join() won't work here as
315 # an absolute path in filename would override $srctree.
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200316 srctree_filename = os.path.normpath(self.srctree + "/" +
317 filename)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900318 if os.path.exists(srctree_filename):
319 return srctree_filename
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900320 if os.path.exists(filename):
321 return filename
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900322 return None
323
324 def get_symbol(self, name):
325 """Returns the symbol with name 'name', or None if no such symbol
326 appears in the configuration. An alternative shorthand is conf[name],
327 where conf is a Config instance, though that will instead raise
328 KeyError if the symbol does not exist."""
329 return self.syms.get(name)
330
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200331 def __getitem__(self, name):
332 """Returns the symbol with name 'name'. Raises KeyError if the symbol
333 does not appear in the configuration."""
334 return self.syms[name]
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900335
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200336 def get_symbols(self, all_symbols=True):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900337 """Returns a list of symbols from the configuration. An alternative for
338 iterating over all defined symbols (in the order of definition) is
339
340 for sym in config:
341 ...
342
343 which relies on Config implementing __iter__() and is equivalent to
344
345 for sym in config.get_symbols(False):
346 ...
347
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200348 all_symbols (default: True): If True, all symbols -- including special
349 and undefined symbols -- will be included in the result, in an
350 undefined order. If False, only symbols actually defined and not
351 merely referred to in the configuration will be included in the
352 result, and will appear in the order that they are defined within
353 the Kconfig configuration files."""
354 return list(self.syms.values()) if all_symbols else self.kconfig_syms
355
356 def __iter__(self):
357 """Convenience function for iterating over the set of all defined
358 symbols in the configuration, used like
359
360 for sym in conf:
361 ...
362
363 The iteration happens in the order of definition within the Kconfig
364 configuration files. Symbols only referred to but not defined will not
365 be included, nor will the special symbols n, m, and y. If you want to
366 include such symbols as well, see config.get_symbols()."""
367 return iter(self.kconfig_syms)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900368
369 def get_choices(self):
370 """Returns a list containing all choice statements in the
371 configuration, in the order they appear in the Kconfig files."""
372 return self.choices
373
374 def get_menus(self):
375 """Returns a list containing all menus in the configuration, in the
376 order they appear in the Kconfig files."""
377 return self.menus
378
379 def get_comments(self):
380 """Returns a list containing all comments in the configuration, in the
381 order they appear in the Kconfig files."""
382 return self.comments
383
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200384 def get_top_level_items(self):
385 """Returns a list containing the items (symbols, menus, choices, and
386 comments) at the top level of the configuration -- that is, all items
387 that do not appear within a menu or choice. The items appear in the
388 same order as within the configuration."""
389 return self.top_block
390
391 def load_config(self, filename, replace=True):
392 """Loads symbol values from a file in the familiar .config format.
393 Equivalent to calling Symbol.set_user_value() to set each of the
394 values.
395
396 "# CONFIG_FOO is not set" within a .config file is treated specially
397 and sets the user value of FOO to 'n'. The C implementation works the
398 same way.
399
400 filename: The .config file to load. $-references to existing
401 environment variables will be expanded. For scripts to work even when
402 an alternative build directory is used with the Linux kernel, you
403 need to refer to the top-level kernel directory with "$srctree".
404
405 replace (default: True): True if the configuration should replace the
Simon Glass8639f692017-08-04 03:30:30 -0600406 old configuration; False if it should add to it.
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200407
Simon Glass8639f692017-08-04 03:30:30 -0600408 Returns a list or warnings (hopefully empty)
409 """
410
411 self._warnings = []
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200412 # Regular expressions for parsing .config files
413 _set_re_match = re.compile(r"{}(\w+)=(.*)".format(self.config_prefix)).match
414 _unset_re_match = re.compile(r"# {}(\w+) is not set".format(self.config_prefix)).match
415
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200416 # Put this first so that a missing file doesn't screw up our state
417 filename = os.path.expandvars(filename)
418 line_feeder = _FileFeed(filename)
419
420 self.config_filename = filename
421
422 #
423 # Read header
424 #
425
426 def is_header_line(line):
427 return line is not None and line.startswith("#") and \
428 not _unset_re_match(line)
429
430 self.config_header = None
431
432 line = line_feeder.peek_next()
433 if is_header_line(line):
434 self.config_header = ""
435 while is_header_line(line_feeder.peek_next()):
436 self.config_header += line_feeder.get_next()[1:]
437 # Remove trailing newline
438 if self.config_header.endswith("\n"):
439 self.config_header = self.config_header[:-1]
440
441 #
442 # Read assignments. Hotspot for some workloads.
443 #
444
445 def warn_override(filename, linenr, name, old_user_val, new_user_val):
446 self._warn('overriding the value of {0}. '
447 'Old value: "{1}", new value: "{2}".'
448 .format(name, old_user_val, new_user_val),
449 filename, linenr)
450
451 # Invalidate everything to keep things simple. It might be possible to
452 # improve performance for the case where multiple configurations are
453 # loaded by only invalidating a symbol (and its dependent symbols) if
454 # the new user value differs from the old. One complication would be
455 # that symbols not mentioned in the .config must lose their user value
456 # when replace = True, which is the usual case.
457 if replace:
458 self.unset_user_values()
459 else:
460 self._invalidate_all()
461
462 while 1:
463 line = line_feeder.get_next()
464 if line is None:
Simon Glass8639f692017-08-04 03:30:30 -0600465 return self._warnings
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200466
467 line = line.rstrip()
468
469 set_match = _set_re_match(line)
470 if set_match:
471 name, val = set_match.groups()
472
473 if val.startswith('"'):
474 if len(val) < 2 or val[-1] != '"':
475 _parse_error(line, "malformed string literal",
476 line_feeder.filename, line_feeder.linenr)
477 # Strip quotes and remove escapings. The unescaping
478 # procedure should be safe since " can only appear as \"
479 # inside the string.
480 val = val[1:-1].replace('\\"', '"').replace("\\\\", "\\")
481
482 if name in self.syms:
483 sym = self.syms[name]
484 if sym.user_val is not None:
485 warn_override(line_feeder.filename, line_feeder.linenr,
486 name, sym.user_val, val)
487
488 if sym.is_choice_sym:
489 user_mode = sym.parent.user_mode
490 if user_mode is not None and user_mode != val:
491 self._warn("assignment to {0} changes mode of "
492 'containing choice from "{1}" to "{2}".'
493 .format(name, val, user_mode),
494 line_feeder.filename,
495 line_feeder.linenr)
496
497 sym._set_user_value_no_invalidate(val, True)
498 else:
499 if self.print_undef_assign:
500 _stderr_msg('note: attempt to assign the value "{0}" '
501 "to the undefined symbol {1}."
502 .format(val, name),
503 line_feeder.filename, line_feeder.linenr)
504 else:
505 unset_match = _unset_re_match(line)
506 if unset_match:
507 name = unset_match.group(1)
508 if name in self.syms:
509 sym = self.syms[name]
510 if sym.user_val is not None:
511 warn_override(line_feeder.filename,
512 line_feeder.linenr,
513 name, sym.user_val, "n")
514
515 sym._set_user_value_no_invalidate("n", True)
516
517 def write_config(self, filename, header=None):
518 """Writes out symbol values in the familiar .config format.
519
520 Kconfiglib makes sure the format matches what the C implementation
521 would generate, down to whitespace. This eases testing.
522
523 filename: The filename under which to save the configuration.
524
525 header (default: None): A textual header that will appear at the
526 beginning of the file, with each line commented out automatically.
527 None means no header."""
528
529 for sym in self.syms_iter():
530 sym.already_written = False
531
532 with open(filename, "w") as f:
533 # Write header
534 if header is not None:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200535 f.write(_comment(header) + "\n")
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200536
537 # Build and write configuration
538 conf_strings = []
539 _make_block_conf(self.top_block, conf_strings.append)
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200540 f.write("\n".join(conf_strings) + "\n")
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200541
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900542 def eval(self, s):
543 """Returns the value of the expression 's' -- where 's' is represented
544 as a string -- in the context of the configuration. Raises
545 Kconfig_Syntax_Error if syntax errors are detected in 's'.
546
547 For example, if FOO and BAR are tristate symbols at least one of which
548 has the value "y", then config.eval("y && (FOO || BAR)") => "y"
549
Masahiro Yamada9d01b782015-05-27 11:39:22 +0900550 This function always yields a tristate value. To get the value of
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900551 non-bool, non-tristate symbols, use Symbol.get_value().
552
553 The result of this function is consistent with how evaluation works for
554 conditional expressions in the configuration as well as in the C
555 implementation. "m" and m are rewritten as '"m" && MODULES' and 'm &&
556 MODULES', respectively, and a result of "m" will get promoted to "y" if
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200557 we're running without modules.
558
559 Syntax checking is somewhat lax, partly to be compatible with lax
560 parsing in the C implementation."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900561 return self._eval_expr(self._parse_expr(self._tokenize(s, True), # Feed
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200562 None, # Current symbol/choice
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900563 s)) # line
564
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200565 def unset_user_values(self):
566 """Resets the values of all symbols, as if Config.load_config() or
567 Symbol.set_user_value() had never been called."""
568 for sym in self.syms_iter():
569 sym._unset_user_value_no_recursive_invalidate()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900570
571 def set_print_warnings(self, print_warnings):
572 """Determines whether warnings related to this configuration (for
573 things like attempting to assign illegal values to symbols with
574 Symbol.set_user_value()) should be printed to stderr.
575
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200576 print_warnings: True if warnings should be printed."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900577 self.print_warnings = print_warnings
578
579 def set_print_undef_assign(self, print_undef_assign):
580 """Determines whether informational messages related to assignments to
581 undefined symbols should be printed to stderr for this configuration.
582
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200583 print_undef_assign: If True, such messages will be printed."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900584 self.print_undef_assign = print_undef_assign
585
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900586 def __str__(self):
587 """Returns a string containing various information about the Config."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200588 return _lines("Configuration",
589 "File : " +
590 self.filename,
591 "Base directory : " +
592 self.base_dir,
593 "Value of $ARCH at creation time : " +
594 ("(not set)" if self.arch is None else self.arch),
595 "Value of $SRCARCH at creation time : " +
596 ("(not set)" if self.srcarch is None else
597 self.srcarch),
598 "Source tree (derived from $srctree;",
599 "defaults to '.' if $srctree isn't set) : " +
600 self.srctree,
601 "Most recently loaded .config : " +
602 ("(no .config loaded)"
603 if self.config_filename is None else
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900604 self.config_filename),
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200605 "Print warnings : " +
606 BOOL_STR[self.print_warnings],
607 "Print assignments to undefined symbols : " +
608 BOOL_STR[self.print_undef_assign])
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900609
610 #
611 # Private methods
612 #
613
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900614 #
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200615 # Kconfig parsing
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900616 #
617
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200618 def _parse_file(self, filename, parent, deps, visible_if_deps, block):
619 """Parses the Kconfig file 'filename'. Appends the Items in the file
620 (and any file it sources) to the list passed in the 'block' parameter.
621 See _parse_block() for the meaning of the parameters."""
622 self._parse_block(_FileFeed(filename), None, parent, deps,
623 visible_if_deps, block)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900624
625 def _parse_block(self, line_feeder, end_marker, parent, deps,
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200626 visible_if_deps, block):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900627 """Parses a block, which is the contents of either a file or an if,
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200628 menu, or choice statement. Appends the Items to the list passed in the
629 'block' parameter.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900630
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200631 line_feeder: A _FileFeed instance feeding lines from a file. The
632 Kconfig language is line-based in practice.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900633
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200634 end_marker: The token that ends the block, e.g. T_ENDIF ("endif") for
635 ifs. None for files.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900636
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200637 parent: The enclosing menu or choice, or None if we're at the top
638 level.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900639
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200640 deps: Dependencies from enclosing menus, choices and ifs.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900641
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200642 visible_if_deps (default: None): 'visible if' dependencies from
643 enclosing menus.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900644
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200645 block: The list to add items to."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900646
647 while 1:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900648 # Do we already have a tokenized line that we determined wasn't
649 # part of whatever we were parsing earlier? See comment in
650 # Config.__init__().
651 if self.end_line is not None:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900652 line = self.end_line
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200653 tokens = self.end_line_tokens
654 tokens.unget_all()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900655
656 self.end_line = None
657 self.end_line_tokens = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900658 else:
659 line = line_feeder.get_next()
660 if line is None:
661 if end_marker is not None:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200662 raise Kconfig_Syntax_Error("Unexpected end of file {0}"
663 .format(line_feeder.filename))
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200664 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900665
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200666 tokens = self._tokenize(line, False, line_feeder.filename,
667 line_feeder.linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900668
669 t0 = tokens.get_next()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200670 if t0 is None:
671 continue
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900672
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200673 # Cases are ordered roughly by frequency, which speeds things up a
674 # bit
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900675
676 if t0 == T_CONFIG or t0 == T_MENUCONFIG:
677 # The tokenizer will automatically allocate a new Symbol object
678 # for any new names it encounters, so we don't need to worry
679 # about that here.
680 sym = tokens.get_next()
681
682 # Symbols defined in multiple places get the parent of their
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200683 # first definition. However, for symbols whose parents are
684 # choice statements, the choice statement takes precedence.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900685 if not sym.is_defined_ or isinstance(parent, Choice):
686 sym.parent = parent
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900687 sym.is_defined_ = True
688
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200689 self._parse_properties(line_feeder, sym, deps, visible_if_deps)
690
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900691 self.kconfig_syms.append(sym)
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200692 block.append(sym)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900693
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200694 elif t0 == T_SOURCE:
695 kconfig_file = tokens.get_next()
696 exp_kconfig_file = self._expand_sym_refs(kconfig_file)
697 f = os.path.join(self.base_dir, exp_kconfig_file)
698 if not os.path.exists(f):
699 raise IOError('{0}:{1}: sourced file "{2}" (expands to '
700 '"{3}") not found. Perhaps base_dir '
701 '(argument to Config.__init__(), currently '
702 '"{4}") is set to the wrong value.'
703 .format(line_feeder.filename,
704 line_feeder.linenr,
705 kconfig_file, exp_kconfig_file,
706 self.base_dir))
707 # Add items to the same block
708 self._parse_file(f, parent, deps, visible_if_deps, block)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900709
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200710 elif t0 == end_marker:
711 # We have reached the end of the block
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200712 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900713
714 elif t0 == T_IF:
715 # If statements are treated as syntactic sugar for adding
716 # dependencies to enclosed items and do not have an explicit
717 # object representation.
718
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200719 dep_expr = self._parse_expr(tokens, None, line,
720 line_feeder.filename,
721 line_feeder.linenr)
722 # Add items to the same block
723 self._parse_block(line_feeder, T_ENDIF, parent,
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900724 _make_and(dep_expr, deps),
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200725 visible_if_deps, block)
726
727 elif t0 == T_COMMENT:
728 comment = Comment()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200729 comment.config = self
730 comment.parent = parent
731 comment.filename = line_feeder.filename
732 comment.linenr = line_feeder.linenr
733 comment.text = tokens.get_next()
734
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200735 self._parse_properties(line_feeder, comment, deps,
736 visible_if_deps)
737
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200738 self.comments.append(comment)
739 block.append(comment)
740
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200741 elif t0 == T_MENU:
742 menu = Menu()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200743 menu.config = self
744 menu.parent = parent
745 menu.filename = line_feeder.filename
746 menu.linenr = line_feeder.linenr
747 menu.title = tokens.get_next()
748
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200749 self._parse_properties(line_feeder, menu, deps,
750 visible_if_deps)
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200751
752 # This needs to go before _parse_block() so that we get the
753 # proper menu ordering in the case of nested functions
754 self.menus.append(menu)
755 # Parse contents and put Items in menu.block
756 self._parse_block(line_feeder, T_ENDMENU, menu, menu.dep_expr,
757 _make_and(visible_if_deps,
758 menu.visible_if_expr),
759 menu.block)
760
761 block.append(menu)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900762
763 elif t0 == T_CHOICE:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200764 name = tokens.get_next()
765 if name is None:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900766 choice = Choice()
767 self.choices.append(choice)
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200768 else:
769 # Named choice
770 choice = self.named_choices.get(name)
771 if choice is None:
772 choice = Choice()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900773 choice.name = name
774 self.named_choices[name] = choice
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200775 self.choices.append(choice)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900776
777 choice.config = self
778 choice.parent = parent
779
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200780 choice.def_locations.append((line_feeder.filename,
781 line_feeder.linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900782
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200783 self._parse_properties(line_feeder, choice, deps,
784 visible_if_deps)
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200785
786 # Parse contents and put Items in choice.block
787 self._parse_block(line_feeder, T_ENDCHOICE, choice, deps,
788 visible_if_deps, choice.block)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900789
790 choice._determine_actual_symbols()
791
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200792 # If no type is specified for the choice, its type is that of
793 # the first choice item with a specified type
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900794 if choice.type == UNKNOWN:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200795 for item in choice.actual_symbols:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900796 if item.type != UNKNOWN:
797 choice.type = item.type
798 break
799
800 # Each choice item of UNKNOWN type gets the type of the choice
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200801 for item in choice.actual_symbols:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900802 if item.type == UNKNOWN:
803 item.type = choice.type
804
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200805 block.append(choice)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900806
807 elif t0 == T_MAINMENU:
808 text = tokens.get_next()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900809 if self.mainmenu_text is not None:
810 self._warn("overriding 'mainmenu' text. "
811 'Old value: "{0}", new value: "{1}".'
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200812 .format(self.mainmenu_text, text),
813 line_feeder.filename, line_feeder.linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900814 self.mainmenu_text = text
815
816 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200817 _parse_error(line, "unrecognized construct",
818 line_feeder.filename, line_feeder.linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900819
820 def _parse_properties(self, line_feeder, stmt, deps, visible_if_deps):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200821 """Parsing of properties for symbols, menus, choices, and comments.
822 Takes care of propagating dependencies from enclosing menus and ifs."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900823
824 def parse_val_and_cond(tokens, line, filename, linenr):
825 """Parses '<expr1> if <expr2>' constructs, where the 'if' part is
826 optional. Returns a tuple containing the parsed expressions, with
827 None as the second element if the 'if' part is missing."""
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200828 return (self._parse_expr(tokens, stmt, line, filename, linenr,
829 False),
830 self._parse_expr(tokens, stmt, line, filename, linenr)
831 if tokens.check(T_IF) else None)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900832
833 # In case the symbol is defined in multiple locations, we need to
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200834 # remember what prompts, defaults, selects, and implies are new for
835 # this definition, as "depends on" should only apply to the local
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900836 # definition.
837 new_prompt = None
838 new_def_exprs = []
839 new_selects = []
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200840 new_implies = []
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900841
842 # Dependencies from 'depends on' statements
843 depends_on_expr = None
844
845 while 1:
846 line = line_feeder.get_next()
847 if line is None:
848 break
849
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200850 filename = line_feeder.filename
851 linenr = line_feeder.linenr
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900852
853 tokens = self._tokenize(line, False, filename, linenr)
854
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200855 t0 = tokens.get_next()
856 if t0 is None:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900857 continue
858
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200859 # Cases are ordered roughly by frequency, which speeds things up a
860 # bit
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900861
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200862 if t0 == T_DEPENDS:
863 if not tokens.check(T_ON):
864 _parse_error(line, 'expected "on" after "depends"',
865 filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900866
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200867 parsed_deps = self._parse_expr(tokens, stmt, line, filename,
868 linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900869
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200870 if isinstance(stmt, (Menu, Comment)):
871 stmt.orig_deps = _make_and(stmt.orig_deps, parsed_deps)
872 else:
873 depends_on_expr = _make_and(depends_on_expr, parsed_deps)
874
875 elif t0 == T_HELP:
876 # Find first non-blank (not all-space) line and get its
877 # indentation
878 line = line_feeder.next_nonblank()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900879 if line is None:
880 stmt.help = ""
881 break
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900882 indent = _indentation(line)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900883 if indent == 0:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200884 # If the first non-empty lines has zero indent, there is no
885 # help text
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900886 stmt.help = ""
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200887 line_feeder.unget()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900888 break
889
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900890 # The help text goes on till the first non-empty line with less
891 # indent
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200892 help_lines = [_deindent(line, indent)]
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900893 while 1:
894 line = line_feeder.get_next()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200895 if line is None or \
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900896 (not line.isspace() and _indentation(line) < indent):
897 stmt.help = "".join(help_lines)
898 break
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900899 help_lines.append(_deindent(line, indent))
900
901 if line is None:
902 break
903
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200904 line_feeder.unget()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900905
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200906 elif t0 == T_SELECT:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900907 target = tokens.get_next()
908
909 stmt.referenced_syms.add(target)
910 stmt.selected_syms.add(target)
911
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200912 new_selects.append(
913 (target,
914 self._parse_expr(tokens, stmt, line, filename, linenr)
915 if tokens.check(T_IF) else None))
916
917 elif t0 == T_IMPLY:
918 target = tokens.get_next()
919
920 stmt.referenced_syms.add(target)
921 stmt.implied_syms.add(target)
922
923 new_implies.append(
924 (target,
925 self._parse_expr(tokens, stmt, line, filename, linenr)
926 if tokens.check(T_IF) else None))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900927
928 elif t0 in (T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200929 stmt.type = TOKEN_TO_TYPE[t0]
930 if tokens.peek_next() is not None:
931 new_prompt = parse_val_and_cond(tokens, line, filename,
932 linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900933
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200934 elif t0 == T_DEFAULT:
935 new_def_exprs.append(parse_val_and_cond(tokens, line, filename,
936 linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900937
938 elif t0 == T_DEF_BOOL:
939 stmt.type = BOOL
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200940 if tokens.peek_next() is not None:
941 new_def_exprs.append(parse_val_and_cond(tokens, line,
942 filename, linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900943
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200944 elif t0 == T_PROMPT:
945 # 'prompt' properties override each other within a single
946 # definition of a symbol, but additional prompts can be added
947 # by defining the symbol multiple times; hence 'new_prompt'
948 # instead of 'prompt'.
949 new_prompt = parse_val_and_cond(tokens, line, filename, linenr)
950
951 elif t0 == T_RANGE:
952 low = tokens.get_next()
953 high = tokens.get_next()
954 stmt.referenced_syms.add(low)
955 stmt.referenced_syms.add(high)
956
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200957 stmt.ranges.append(
958 (low, high,
959 self._parse_expr(tokens, stmt, line, filename, linenr)
960 if tokens.check(T_IF) else None))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900961
962 elif t0 == T_DEF_TRISTATE:
963 stmt.type = TRISTATE
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200964 if tokens.peek_next() is not None:
965 new_def_exprs.append(parse_val_and_cond(tokens, line,
966 filename, linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900967
968 elif t0 == T_OPTION:
969 if tokens.check(T_ENV) and tokens.check(T_EQUAL):
970 env_var = tokens.get_next()
971
972 stmt.is_special_ = True
973 stmt.is_from_env = True
974
975 if env_var not in os.environ:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200976 self._warn("The symbol {0} references the "
977 "non-existent environment variable {1} and "
978 "will get the empty string as its value. "
979 "If you're using Kconfiglib via "
980 "'make (i)scriptconfig', it should have "
981 "set up the environment correctly for you. "
982 "If you still got this message, that "
983 "might be an error, and you should email "
984 "ulfalizer a.t Google's email service."""
985 .format(stmt.name, env_var),
986 filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900987
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200988 stmt.cached_val = ""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900989 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200990 stmt.cached_val = os.environ[env_var]
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900991
992 elif tokens.check(T_DEFCONFIG_LIST):
993 self.defconfig_sym = stmt
994
995 elif tokens.check(T_MODULES):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200996 # To reduce warning spam, only warn if 'option modules' is
997 # set on some symbol that isn't MODULES, which should be
998 # safe. I haven't run into any projects that make use
999 # modules besides the kernel yet, and there it's likely to
1000 # keep being called "MODULES".
1001 if stmt.name != "MODULES":
1002 self._warn("the 'modules' option is not supported. "
1003 "Let me know if this is a problem for you; "
1004 "it shouldn't be that hard to implement. "
1005 "(Note that modules are still supported -- "
1006 "Kconfiglib just assumes the symbol name "
1007 "MODULES, like older versions of the C "
1008 "implementation did when 'option modules' "
1009 "wasn't used.)",
1010 filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001011
Masahiro Yamada9d01b782015-05-27 11:39:22 +09001012 elif tokens.check(T_ALLNOCONFIG_Y):
1013 if not isinstance(stmt, Symbol):
1014 _parse_error(line,
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001015 "the 'allnoconfig_y' option is only "
1016 "valid for symbols",
1017 filename, linenr)
Masahiro Yamada9d01b782015-05-27 11:39:22 +09001018 stmt.allnoconfig_y = True
1019
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001020 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001021 _parse_error(line, "unrecognized option", filename, linenr)
1022
1023 elif t0 == T_VISIBLE:
1024 if not tokens.check(T_IF):
1025 _parse_error(line, 'expected "if" after "visible"',
1026 filename, linenr)
1027 if not isinstance(stmt, Menu):
1028 _parse_error(line,
1029 "'visible if' is only valid for menus",
1030 filename, linenr)
1031
1032 parsed_deps = self._parse_expr(tokens, stmt, line, filename,
1033 linenr)
1034 stmt.visible_if_expr = _make_and(stmt.visible_if_expr,
1035 parsed_deps)
1036
1037 elif t0 == T_OPTIONAL:
1038 if not isinstance(stmt, Choice):
1039 _parse_error(line,
1040 '"optional" is only valid for choices',
1041 filename,
1042 linenr)
1043 stmt.optional = True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001044
1045 else:
1046 # See comment in Config.__init__()
1047 self.end_line = line
1048 self.end_line_tokens = tokens
1049 break
1050
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001051 # Done parsing properties. Now propagate 'depends on' and enclosing
1052 # menu/if dependencies to expressions.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001053
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001054 # The set of symbols referenced directly by the statement plus all
1055 # symbols referenced by enclosing menus and ifs
1056 stmt.all_referenced_syms = stmt.referenced_syms | _get_expr_syms(deps)
1057
1058 # Save original dependencies from enclosing menus and ifs
1059 stmt.deps_from_containing = deps
1060
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001061 if isinstance(stmt, (Menu, Comment)):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001062 stmt.dep_expr = _make_and(stmt.orig_deps, deps)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001063 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001064 # Symbol or Choice
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001065
1066 # See comment for 'menu_dep'
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001067 stmt.menu_dep = _make_and(deps, depends_on_expr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001068
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001069 # Propagate dependencies to prompts
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001070
1071 if new_prompt is not None:
1072 prompt, cond_expr = new_prompt
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001073 # Propagate 'visible if' dependencies from menus and local
1074 # 'depends on' dependencies
1075 cond_expr = _make_and(_make_and(cond_expr, visible_if_deps),
1076 depends_on_expr)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001077 # Save original
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001078 stmt.orig_prompts.append((prompt, cond_expr))
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001079 # Finalize with dependencies from enclosing menus and ifs
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001080 stmt.prompts.append((prompt, _make_and(cond_expr, deps)))
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001081
1082 # Propagate dependencies to defaults
1083
1084 # Propagate 'depends on' dependencies
1085 new_def_exprs = [(val_expr, _make_and(cond_expr, depends_on_expr))
1086 for val_expr, cond_expr in new_def_exprs]
1087 # Save original
1088 stmt.orig_def_exprs.extend(new_def_exprs)
1089 # Finalize with dependencies from enclosing menus and ifs
1090 stmt.def_exprs.extend([(val_expr, _make_and(cond_expr, deps))
1091 for val_expr, cond_expr in new_def_exprs])
1092
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001093 # Propagate dependencies to selects and implies
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001094
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001095 # Only symbols can select and imply
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001096 if isinstance(stmt, Symbol):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001097 # Propagate 'depends on' dependencies
1098 new_selects = [(target, _make_and(cond_expr, depends_on_expr))
1099 for target, cond_expr in new_selects]
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001100 new_implies = [(target, _make_and(cond_expr, depends_on_expr))
1101 for target, cond_expr in new_implies]
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001102 # Save original
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001103 stmt.orig_selects.extend(new_selects)
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001104 stmt.orig_implies.extend(new_implies)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001105 # Finalize with dependencies from enclosing menus and ifs
1106 for target, cond in new_selects:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001107 target.rev_dep = \
1108 _make_or(target.rev_dep,
1109 _make_and(stmt, _make_and(cond, deps)))
1110 for target, cond in new_implies:
1111 target.weak_rev_dep = \
1112 _make_or(target.weak_rev_dep,
1113 _make_and(stmt, _make_and(cond, deps)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001114
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001115 def _parse_expr(self, feed, cur_item, line, filename=None, linenr=None,
1116 transform_m=True):
1117 """Parses an expression from the tokens in 'feed' using a simple
1118 top-down approach. The result has the form
1119 '(<operator>, [<parsed operands>])', where <operator> is e.g.
1120 kconfiglib.AND. If there is only one operand (i.e., no && or ||), then
1121 the operand is returned directly. This also goes for subexpressions.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001122
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001123 feed: _Feed instance containing the tokens for the expression.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001124
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001125 cur_item: The item (Symbol, Choice, Menu, or Comment) currently being
1126 parsed, or None if we're not parsing an item. Used for recording
1127 references to symbols.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001128
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001129 line: The line containing the expression being parsed.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001130
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001131 filename (default: None): The file containing the expression.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001132
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001133 linenr (default: None): The line number containing the expression.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001134
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001135 transform_m (default: False): Determines if 'm' should be rewritten to
1136 'm && MODULES' -- see parse_val_and_cond().
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001137
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001138 Expression grammar, in decreasing order of precedence:
1139
1140 <expr> -> <symbol>
1141 <symbol> '=' <symbol>
1142 <symbol> '!=' <symbol>
1143 '(' <expr> ')'
1144 '!' <expr>
1145 <expr> '&&' <expr>
1146 <expr> '||' <expr>"""
1147
1148 # Use instance variables to avoid having to pass these as arguments
1149 # through the top-down parser in _parse_expr_rec(), which is tedious
1150 # and obfuscates the code. A profiler run shows no noticeable
1151 # performance difference.
1152 self._cur_item = cur_item
1153 self._transform_m = transform_m
1154 self._line = line
1155 self._filename = filename
1156 self._linenr = linenr
1157
1158 return self._parse_expr_rec(feed)
1159
1160 def _parse_expr_rec(self, feed):
1161 or_term = self._parse_or_term(feed)
1162 if not feed.check(T_OR):
1163 # Common case -- no need for an OR node since it's just a single
1164 # operand
1165 return or_term
1166 or_terms = [or_term, self._parse_or_term(feed)]
1167 while feed.check(T_OR):
1168 or_terms.append(self._parse_or_term(feed))
1169 return (OR, or_terms)
1170
1171 def _parse_or_term(self, feed):
1172 and_term = self._parse_factor(feed)
1173 if not feed.check(T_AND):
1174 # Common case -- no need for an AND node since it's just a single
1175 # operand
1176 return and_term
1177 and_terms = [and_term, self._parse_factor(feed)]
1178 while feed.check(T_AND):
1179 and_terms.append(self._parse_factor(feed))
1180 return (AND, and_terms)
1181
1182 def _parse_factor(self, feed):
1183 token = feed.get_next()
1184
1185 if isinstance(token, (Symbol, str)):
1186 if self._cur_item is not None and isinstance(token, Symbol):
1187 self._cur_item.referenced_syms.add(token)
1188
1189 next_token = feed.peek_next()
1190 # For conditional expressions ('depends on <expr>',
1191 # '... if <expr>', # etc.), "m" and m are rewritten to
1192 # "m" && MODULES.
1193 if next_token != T_EQUAL and next_token != T_UNEQUAL:
1194 if self._transform_m and (token is self.m or token == "m"):
1195 return (AND, ["m", self._sym_lookup("MODULES")])
1196 return token
1197
1198 relation = EQUAL if (feed.get_next() == T_EQUAL) else UNEQUAL
1199 token_2 = feed.get_next()
1200 if self._cur_item is not None and isinstance(token_2, Symbol):
1201 self._cur_item.referenced_syms.add(token_2)
1202 return (relation, token, token_2)
1203
1204 if token == T_NOT:
1205 return (NOT, self._parse_factor(feed))
1206
1207 if token == T_OPEN_PAREN:
1208 expr_parse = self._parse_expr_rec(feed)
1209 if not feed.check(T_CLOSE_PAREN):
1210 _parse_error(self._line, "missing end parenthesis",
1211 self._filename, self._linenr)
1212 return expr_parse
1213
1214 _parse_error(self._line, "malformed expression", self._filename,
1215 self._linenr)
1216
1217 def _tokenize(self, s, for_eval, filename=None, linenr=None):
1218 """Returns a _Feed instance containing tokens derived from the string
1219 's'. Registers any new symbols encountered (via _sym_lookup()).
1220
1221 (I experimented with a pure regular expression implementation, but it
1222 came out slower, less readable, and wouldn't have been as flexible.)
1223
1224 for_eval: True when parsing an expression for a call to Config.eval(),
1225 in which case we should not treat the first token specially nor
1226 register new symbols."""
1227
1228 s = s.strip()
1229 if s == "" or s[0] == "#":
1230 return _Feed([])
1231
1232 if for_eval:
1233 previous = None # The previous token seen
1234 tokens = []
1235 i = 0 # The current index in the string being tokenized
1236
1237 else:
1238 # The initial word on a line is parsed specially. Let
1239 # command_chars = [A-Za-z0-9_]. Then
1240 # - leading non-command_chars characters are ignored, and
1241 # - the first token consists the following one or more
1242 # command_chars characters.
1243 # This is why things like "----help--" are accepted.
1244 initial_token_match = _initial_token_re_match(s)
1245 if initial_token_match is None:
1246 return _Feed([])
1247 keyword = _get_keyword(initial_token_match.group(1))
1248 if keyword == T_HELP:
1249 # Avoid junk after "help", e.g. "---", being registered as a
1250 # symbol
1251 return _Feed([T_HELP])
1252 if keyword is None:
1253 # We expect a keyword as the first token
1254 _tokenization_error(s, filename, linenr)
1255
1256 previous = keyword
1257 tokens = [keyword]
1258 # The current index in the string being tokenized
1259 i = initial_token_match.end()
1260
1261 # _tokenize() is a hotspot during parsing, and this speeds things up a
1262 # bit
1263 strlen = len(s)
1264 append = tokens.append
1265
1266 # Main tokenization loop. (Handles tokens past the first one.)
1267 while i < strlen:
1268 # Test for an identifier/keyword preceded by whitespace first; this
1269 # is the most common case.
1270 id_keyword_match = _id_keyword_re_match(s, i)
1271 if id_keyword_match:
1272 # We have an identifier or keyword. The above also stripped any
1273 # whitespace for us.
1274 name = id_keyword_match.group(1)
1275 # Jump past it
1276 i = id_keyword_match.end()
1277
1278 keyword = _get_keyword(name)
1279 if keyword is not None:
1280 # It's a keyword
1281 append(keyword)
1282 elif previous in STRING_LEX:
1283 # What would ordinarily be considered an identifier is
1284 # treated as a string after certain tokens
1285 append(name)
1286 else:
1287 # It's a symbol name. _sym_lookup() will take care of
1288 # allocating a new Symbol instance if it's the first time
1289 # we see it.
1290 sym = self._sym_lookup(name, for_eval)
1291
1292 if previous == T_CONFIG or previous == T_MENUCONFIG:
1293 # If the previous token is T_(MENU)CONFIG
1294 # ("(menu)config"), we're tokenizing the first line of
1295 # a symbol definition, and should remember this as a
1296 # location where the symbol is defined
1297 sym.def_locations.append((filename, linenr))
1298 else:
1299 # Otherwise, it's a reference to the symbol
1300 sym.ref_locations.append((filename, linenr))
1301
1302 append(sym)
1303
1304 else:
1305 # Not an identifier/keyword
1306
1307 while i < strlen and s[i].isspace():
1308 i += 1
1309 if i == strlen:
1310 break
1311 c = s[i]
1312 i += 1
1313
1314 # String literal (constant symbol)
1315 if c == '"' or c == "'":
1316 if "\\" in s:
1317 # Slow path: This could probably be sped up, but it's a
1318 # very unusual case anyway.
1319 quote = c
1320 val = ""
1321 while 1:
1322 if i >= len(s):
1323 _tokenization_error(s, filename, linenr)
1324 c = s[i]
1325 if c == quote:
1326 break
1327 if c == "\\":
1328 if i + 1 >= len(s):
1329 _tokenization_error(s, filename, linenr)
1330 val += s[i + 1]
1331 i += 2
1332 else:
1333 val += c
1334 i += 1
1335 i += 1
1336 append(val)
1337 else:
1338 # Fast path: If the string contains no backslashes
1339 # (almost always) we can simply look for the matching
1340 # quote.
1341 end = s.find(c, i)
1342 if end == -1:
1343 _tokenization_error(s, filename, linenr)
1344 append(s[i:end])
1345 i = end + 1
1346
1347 elif c == "&":
1348 # Invalid characters are ignored
1349 if i >= len(s) or s[i] != "&": continue
1350 append(T_AND)
1351 i += 1
1352
1353 elif c == "|":
1354 # Invalid characters are ignored
1355 if i >= len(s) or s[i] != "|": continue
1356 append(T_OR)
1357 i += 1
1358
1359 elif c == "!":
1360 if i < len(s) and s[i] == "=":
1361 append(T_UNEQUAL)
1362 i += 1
1363 else:
1364 append(T_NOT)
1365
1366 elif c == "=": append(T_EQUAL)
1367 elif c == "(": append(T_OPEN_PAREN)
1368 elif c == ")": append(T_CLOSE_PAREN)
1369 elif c == "#": break # Comment
1370
1371 else: continue # Invalid characters are ignored
1372
1373 previous = tokens[-1]
1374
1375 return _Feed(tokens)
1376
1377 def _sym_lookup(self, name, for_eval=False):
1378 """Fetches the symbol 'name' from the symbol table, creating and
1379 registering it if it does not exist. If 'for_eval' is True, the symbol
1380 won't be added to the symbol table if it does not exist -- this is for
1381 Config.eval()."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001382 if name in self.syms:
1383 return self.syms[name]
1384
1385 new_sym = Symbol()
1386 new_sym.config = self
1387 new_sym.name = name
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001388 if for_eval:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001389 self._warn("no symbol {0} in configuration".format(name))
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001390 else:
1391 self.syms[name] = new_sym
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001392 return new_sym
1393
1394 #
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001395 # Expression evaluation
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001396 #
1397
1398 def _eval_expr(self, expr):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001399 """Evaluates an expression to "n", "m", or "y"."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001400
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001401 # Handles e.g. an "x if y" condition where the "if y" part is missing.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001402 if expr is None:
1403 return "y"
1404
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001405 res = self._eval_expr_rec(expr)
1406 if res == "m":
1407 # Promote "m" to "y" if we're running without modules.
1408 #
1409 # Internally, "m" is often rewritten to "m" && MODULES by both the
1410 # C implementation and Kconfiglib, which takes care of cases where
1411 # "m" should be demoted to "n" instead.
1412 modules_sym = self.syms.get("MODULES")
1413 if modules_sym is None or modules_sym.get_value() != "y":
1414 return "y"
1415 return res
1416
1417 def _eval_expr_rec(self, expr):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001418 if isinstance(expr, Symbol):
1419 # Non-bool/tristate symbols are always "n" in a tristate sense,
1420 # regardless of their value
1421 if expr.type != BOOL and expr.type != TRISTATE:
1422 return "n"
1423 return expr.get_value()
1424
1425 if isinstance(expr, str):
1426 return expr if (expr == "y" or expr == "m") else "n"
1427
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001428 # Ordered by frequency
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001429
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001430 if expr[0] == AND:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001431 res = "y"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001432 for subexpr in expr[1]:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001433 ev = self._eval_expr_rec(subexpr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001434 # Return immediately upon discovering an "n" term
1435 if ev == "n":
1436 return "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001437 if ev == "m":
1438 res = "m"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001439 # 'res' is either "m" or "y" here; we already handled the
1440 # short-circuiting "n" case in the loop.
1441 return res
1442
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001443 if expr[0] == NOT:
1444 ev = self._eval_expr_rec(expr[1])
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001445 if ev == "y":
1446 return "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001447 return "y" if (ev == "n") else "m"
1448
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001449 if expr[0] == OR:
1450 res = "n"
1451 for subexpr in expr[1]:
1452 ev = self._eval_expr_rec(subexpr)
1453 # Return immediately upon discovering a "y" term
1454 if ev == "y":
1455 return "y"
1456 if ev == "m":
1457 res = "m"
1458 # 'res' is either "n" or "m" here; we already handled the
1459 # short-circuiting "y" case in the loop.
1460 return res
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001461
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001462 if expr[0] == EQUAL:
1463 return "y" if (_str_val(expr[1]) == _str_val(expr[2])) else "n"
1464
1465 if expr[0] == UNEQUAL:
1466 return "y" if (_str_val(expr[1]) != _str_val(expr[2])) else "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001467
1468 _internal_error("Internal error while evaluating expression: "
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001469 "unknown operation {0}.".format(expr[0]))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001470
1471 def _eval_min(self, e1, e2):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001472 """Returns the minimum value of the two expressions. Equates None with
1473 'y'."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001474 e1_eval = self._eval_expr(e1)
1475 e2_eval = self._eval_expr(e2)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001476 return e1_eval if tri_less(e1_eval, e2_eval) else e2_eval
1477
1478 def _eval_max(self, e1, e2):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001479 """Returns the maximum value of the two expressions. Equates None with
1480 'y'."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001481 e1_eval = self._eval_expr(e1)
1482 e2_eval = self._eval_expr(e2)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001483 return e1_eval if tri_greater(e1_eval, e2_eval) else e2_eval
1484
1485 #
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001486 # Dependency tracking (for caching and invalidation)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001487 #
1488
1489 def _build_dep(self):
1490 """Populates the Symbol.dep sets, linking the symbol to the symbols
1491 that immediately depend on it in the sense that changing the value of
1492 the symbol might affect the values of those other symbols. This is used
1493 for caching/invalidation purposes. The calculated sets might be larger
1494 than necessary as we don't do any complicated analysis of the
1495 expressions."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001496
1497 # Adds 'sym' as a directly dependent symbol to all symbols that appear
1498 # in the expression 'e'
1499 def add_expr_deps(e, sym):
1500 for s in _get_expr_syms(e):
1501 s.dep.add(sym)
1502
1503 # The directly dependent symbols of a symbol are:
1504 # - Any symbols whose prompts, default values, rev_dep (select
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001505 # condition), weak_rev_dep (imply condition) or ranges depend on the
1506 # symbol
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001507 # - Any symbols that belong to the same choice statement as the symbol
1508 # (these won't be included in 'dep' as that makes the dependency
1509 # graph unwieldy, but Symbol._get_dependent() will include them)
1510 # - Any symbols in a choice statement that depends on the symbol
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001511 for sym in self.syms_iter():
1512 for _, e in sym.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001513 add_expr_deps(e, sym)
1514
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001515 for v, e in sym.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001516 add_expr_deps(v, sym)
1517 add_expr_deps(e, sym)
1518
1519 add_expr_deps(sym.rev_dep, sym)
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001520 add_expr_deps(sym.weak_rev_dep, sym)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001521
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001522 for l, u, e in sym.ranges:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001523 add_expr_deps(l, sym)
1524 add_expr_deps(u, sym)
1525 add_expr_deps(e, sym)
1526
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001527 if sym.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001528 choice = sym.parent
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001529 for _, e in choice.prompts:
1530 add_expr_deps(e, sym)
1531 for _, e in choice.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001532 add_expr_deps(e, sym)
1533
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001534 def _eq_to_sym(self, eq):
1535 """_expr_depends_on() helper. For (in)equalities of the form sym = y/m
1536 or sym != n, returns sym. For other (in)equalities, returns None."""
1537 relation, left, right = eq
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001538
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001539 def transform_y_m_n(item):
1540 if item is self.y: return "y"
1541 if item is self.m: return "m"
1542 if item is self.n: return "n"
1543 return item
1544
1545 left = transform_y_m_n(left)
1546 right = transform_y_m_n(right)
1547
1548 # Make sure the symbol (if any) appears to the left
1549 if not isinstance(left, Symbol):
1550 left, right = right, left
1551 if not isinstance(left, Symbol):
1552 return None
1553 if (relation == EQUAL and (right == "y" or right == "m")) or \
1554 (relation == UNEQUAL and right == "n"):
1555 return left
1556 return None
1557
1558 def _expr_depends_on(self, expr, sym):
1559 """Reimplementation of expr_depends_symbol() from mconf.c. Used to
1560 determine if a submenu should be implicitly created, which influences
1561 what items inside choice statements are considered choice items."""
1562 if expr is None:
1563 return False
1564
1565 def rec(expr):
1566 if isinstance(expr, str):
1567 return False
1568 if isinstance(expr, Symbol):
1569 return expr is sym
1570
1571 if expr[0] in (EQUAL, UNEQUAL):
1572 return self._eq_to_sym(expr) is sym
1573 if expr[0] == AND:
1574 for and_expr in expr[1]:
1575 if rec(and_expr):
1576 return True
1577 return False
1578
1579 return rec(expr)
1580
1581 def _invalidate_all(self):
1582 for sym in self.syms_iter():
1583 sym._invalidate()
1584
1585 #
1586 # Printing and misc.
1587 #
1588
1589 def _expand_sym_refs(self, s):
1590 """Expands $-references to symbols in 's' to symbol values, or to the
1591 empty string for undefined symbols."""
1592
1593 while 1:
1594 sym_ref_match = _sym_ref_re_search(s)
1595 if sym_ref_match is None:
1596 return s
1597
1598 sym_name = sym_ref_match.group(0)[1:]
1599 sym = self.syms.get(sym_name)
1600 expansion = "" if sym is None else sym.get_value()
1601
1602 s = s[:sym_ref_match.start()] + \
1603 expansion + \
1604 s[sym_ref_match.end():]
1605
1606 def _expr_val_str(self, expr, no_value_str="(none)",
1607 get_val_instead_of_eval=False):
1608 """Printing helper. Returns a string with 'expr' and its value.
1609
1610 no_value_str: String to return when 'expr' is missing (None).
1611
1612 get_val_instead_of_eval: Assume 'expr' is a symbol or string (constant
1613 symbol) and get its value directly instead of evaluating it to a
1614 tristate value."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001615
1616 if expr is None:
1617 return no_value_str
1618
1619 if get_val_instead_of_eval:
1620 if isinstance(expr, str):
1621 return _expr_to_str(expr)
1622 val = expr.get_value()
1623 else:
1624 val = self._eval_expr(expr)
1625
1626 return "{0} (value: {1})".format(_expr_to_str(expr), _expr_to_str(val))
1627
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001628 def _get_sym_or_choice_str(self, sc):
1629 """Symbols and choices have many properties in common, so we factor out
1630 common __str__() stuff here. "sc" is short for "symbol or choice"."""
1631
1632 # As we deal a lot with string representations here, use some
1633 # convenient shorthand:
1634 s = _expr_to_str
1635
1636 #
1637 # Common symbol/choice properties
1638 #
1639
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001640 user_val_str = "(no user value)" if sc.user_val is None else \
1641 s(sc.user_val)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001642
1643 # Build prompts string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001644 if not sc.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001645 prompts_str = " (no prompts)"
1646 else:
1647 prompts_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001648 for prompt, cond_expr in sc.orig_prompts:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001649 prompts_str_rows.append(
1650 ' "{0}"'.format(prompt) if cond_expr is None else
1651 ' "{0}" if {1}'.format(prompt,
1652 self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001653 prompts_str = "\n".join(prompts_str_rows)
1654
1655 # Build locations string
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001656 locations_str = "(no locations)" if not sc.def_locations else \
1657 " ".join(["{0}:{1}".format(filename, linenr) for
1658 filename, linenr in sc.def_locations])
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001659
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001660 # Build additional-dependencies-from-menus-and-ifs string
1661 additional_deps_str = " " + \
1662 self._expr_val_str(sc.deps_from_containing,
1663 "(no additional dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001664
1665 #
1666 # Symbol-specific stuff
1667 #
1668
1669 if isinstance(sc, Symbol):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001670 # Build ranges string
1671 if isinstance(sc, Symbol):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001672 if not sc.ranges:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001673 ranges_str = " (no ranges)"
1674 else:
1675 ranges_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001676 for l, u, cond_expr in sc.ranges:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001677 ranges_str_rows.append(
1678 " [{0}, {1}]".format(s(l), s(u))
1679 if cond_expr is None else
1680 " [{0}, {1}] if {2}"
1681 .format(s(l), s(u), self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001682 ranges_str = "\n".join(ranges_str_rows)
1683
1684 # Build default values string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001685 if not sc.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001686 defaults_str = " (no default values)"
1687 else:
1688 defaults_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001689 for val_expr, cond_expr in sc.orig_def_exprs:
1690 row_str = " " + self._expr_val_str(val_expr, "(none)",
1691 sc.type == STRING)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001692 defaults_str_rows.append(row_str)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001693 defaults_str_rows.append(" Condition: " +
1694 self._expr_val_str(cond_expr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001695 defaults_str = "\n".join(defaults_str_rows)
1696
1697 # Build selects string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001698 if not sc.orig_selects:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001699 selects_str = " (no selects)"
1700 else:
1701 selects_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001702 for target, cond_expr in sc.orig_selects:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001703 selects_str_rows.append(
1704 " {0}".format(target.name) if cond_expr is None else
1705 " {0} if {1}".format(target.name,
1706 self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001707 selects_str = "\n".join(selects_str_rows)
1708
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001709 # Build implies string
1710 if not sc.orig_implies:
1711 implies_str = " (no implies)"
1712 else:
1713 implies_str_rows = []
1714 for target, cond_expr in sc.orig_implies:
1715 implies_str_rows.append(
1716 " {0}".format(target.name) if cond_expr is None else
1717 " {0} if {1}".format(target.name,
1718 self._expr_val_str(cond_expr)))
1719 implies_str = "\n".join(implies_str_rows)
1720
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001721 res = _lines("Symbol " +
1722 ("(no name)" if sc.name is None else sc.name),
1723 "Type : " + TYPENAME[sc.type],
1724 "Value : " + s(sc.get_value()),
1725 "User value : " + user_val_str,
1726 "Visibility : " + s(_get_visibility(sc)),
1727 "Is choice item : " + BOOL_STR[sc.is_choice_sym],
1728 "Is defined : " + BOOL_STR[sc.is_defined_],
1729 "Is from env. : " + BOOL_STR[sc.is_from_env],
1730 "Is special : " + BOOL_STR[sc.is_special_] + "\n")
1731 if sc.ranges:
1732 res += _lines("Ranges:", ranges_str + "\n")
1733 res += _lines("Prompts:",
1734 prompts_str,
1735 "Default values:",
1736 defaults_str,
1737 "Selects:",
1738 selects_str,
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001739 "Implies:",
1740 implies_str,
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001741 "Reverse (select-related) dependencies:",
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001742 " (no reverse dependencies)"
1743 if sc.rev_dep == "n"
1744 else " " + self._expr_val_str(sc.rev_dep),
1745 "Weak reverse (imply-related) dependencies:",
1746 " (no weak reverse dependencies)"
1747 if sc.weak_rev_dep == "n"
1748 else " " + self._expr_val_str(sc.weak_rev_dep),
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001749 "Additional dependencies from enclosing menus "
1750 "and ifs:",
1751 additional_deps_str,
1752 "Locations: " + locations_str)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001753
1754 return res
1755
1756 #
1757 # Choice-specific stuff
1758 #
1759
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001760 # Build selected symbol string
1761 sel = sc.get_selection()
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001762 sel_str = "(no selection)" if sel is None else sel.name
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001763
1764 # Build default values string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001765 if not sc.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001766 defaults_str = " (no default values)"
1767 else:
1768 defaults_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001769 for sym, cond_expr in sc.orig_def_exprs:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001770 defaults_str_rows.append(
1771 " {0}".format(sym.name) if cond_expr is None else
1772 " {0} if {1}".format(sym.name,
1773 self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001774 defaults_str = "\n".join(defaults_str_rows)
1775
1776 # Build contained symbols string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001777 names = [sym.name for sym in sc.actual_symbols]
1778 syms_string = " ".join(names) if names else "(empty)"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001779
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001780 return _lines("Choice",
1781 "Name (for named choices): " +
1782 ("(no name)" if sc.name is None else sc.name),
1783 "Type : " + TYPENAME[sc.type],
1784 "Selected symbol : " + sel_str,
1785 "User value : " + user_val_str,
1786 "Mode : " + s(sc.get_mode()),
1787 "Visibility : " + s(_get_visibility(sc)),
1788 "Optional : " + BOOL_STR[sc.optional],
1789 "Prompts:",
1790 prompts_str,
1791 "Defaults:",
1792 defaults_str,
1793 "Choice symbols:",
1794 " " + syms_string,
1795 "Additional dependencies from enclosing menus and "
1796 "ifs:",
1797 additional_deps_str,
1798 "Locations: " + locations_str)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001799
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001800 def _warn(self, msg, filename=None, linenr=None):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001801 """For printing warnings to stderr."""
Simon Glass8639f692017-08-04 03:30:30 -06001802 msg = _build_msg("warning: " + msg, filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001803 if self.print_warnings:
Simon Glass8639f692017-08-04 03:30:30 -06001804 sys.stderr.write(msg + "\n")
1805 self._warnings.append(msg)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001806
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001807class Item(object):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001808
1809 """Base class for symbols and other Kconfig constructs. Subclasses are
1810 Symbol, Choice, Menu, and Comment."""
1811
1812 def is_symbol(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001813 """Returns True if the item is a symbol. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001814 isinstance(item, kconfiglib.Symbol)."""
1815 return isinstance(self, Symbol)
1816
1817 def is_choice(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001818 """Returns True if the item is a choice. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001819 isinstance(item, kconfiglib.Choice)."""
1820 return isinstance(self, Choice)
1821
1822 def is_menu(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001823 """Returns True if the item is a menu. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001824 isinstance(item, kconfiglib.Menu)."""
1825 return isinstance(self, Menu)
1826
1827 def is_comment(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001828 """Returns True if the item is a comment. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001829 isinstance(item, kconfiglib.Comment)."""
1830 return isinstance(self, Comment)
1831
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001832class Symbol(Item):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001833
1834 """Represents a configuration symbol - e.g. FOO for
1835
1836 config FOO
1837 ..."""
1838
1839 #
1840 # Public interface
1841 #
1842
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001843 def get_config(self):
1844 """Returns the Config instance this symbol is from."""
1845 return self.config
1846
1847 def get_name(self):
1848 """Returns the name of the symbol."""
1849 return self.name
1850
1851 def get_type(self):
1852 """Returns the type of the symbol: one of UNKNOWN, BOOL, TRISTATE,
1853 STRING, HEX, or INT. These are defined at the top level of the module,
1854 so you'd do something like
1855
1856 if sym.get_type() == kconfiglib.STRING:
1857 ..."""
1858 return self.type
1859
1860 def get_prompts(self):
1861 """Returns a list of prompts defined for the symbol, in the order they
1862 appear in the configuration files. Returns the empty list for symbols
1863 with no prompt.
1864
1865 This list will have a single entry for the vast majority of symbols
1866 having prompts, but having multiple prompts for a single symbol is
1867 possible through having multiple 'config' entries for it."""
1868 return [prompt for prompt, _ in self.orig_prompts]
1869
1870 def get_help(self):
1871 """Returns the help text of the symbol, or None if the symbol has no
1872 help text."""
1873 return self.help
1874
1875 def get_parent(self):
1876 """Returns the menu or choice statement that contains the symbol, or
1877 None if the symbol is at the top level. Note that if statements are
1878 treated as syntactic and do not have an explicit class
1879 representation."""
1880 return self.parent
1881
1882 def get_def_locations(self):
1883 """Returns a list of (filename, linenr) tuples, where filename (string)
1884 and linenr (int) represent a location where the symbol is defined. For
1885 the vast majority of symbols this list will only contain one element.
1886 For the following Kconfig, FOO would get two entries: the lines marked
1887 with *.
1888
1889 config FOO *
1890 bool "foo prompt 1"
1891
1892 config FOO *
1893 bool "foo prompt 2"
1894 """
1895 return self.def_locations
1896
1897 def get_ref_locations(self):
1898 """Returns a list of (filename, linenr) tuples, where filename (string)
1899 and linenr (int) represent a location where the symbol is referenced in
1900 the configuration. For example, the lines marked by * would be included
1901 for FOO below:
1902
1903 config A
1904 bool
1905 default BAR || FOO *
1906
1907 config B
1908 tristate
1909 depends on FOO *
1910 default m if FOO *
1911
1912 if FOO *
1913 config A
1914 bool "A"
1915 endif
1916
1917 config FOO (definition not included)
1918 bool
1919 """
1920 return self.ref_locations
1921
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001922 def get_value(self):
1923 """Calculate and return the value of the symbol. See also
1924 Symbol.set_user_value()."""
1925
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001926 if self.cached_val is not None:
1927 return self.cached_val
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001928
1929 # As a quirk of Kconfig, undefined symbols get their name as their
1930 # value. This is why things like "FOO = bar" work for seeing if FOO has
1931 # the value "bar".
1932 if self.type == UNKNOWN:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001933 self.cached_val = self.name
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001934 return self.name
1935
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001936 new_val = DEFAULT_VALUE[self.type]
1937 vis = _get_visibility(self)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001938
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001939 # This is easiest to calculate together with the value
1940 self.write_to_conf = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001941
1942 if self.type == BOOL or self.type == TRISTATE:
1943 # The visibility and mode (modules-only or single-selection) of
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001944 # choice items will be taken into account in _get_visibility()
1945 if self.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001946 if vis != "n":
1947 choice = self.parent
1948 mode = choice.get_mode()
1949
1950 self.write_to_conf = (mode != "n")
1951
1952 if mode == "y":
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001953 new_val = "y" if choice.get_selection() is self \
1954 else "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001955 elif mode == "m":
1956 if self.user_val == "m" or self.user_val == "y":
1957 new_val = "m"
1958
1959 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001960 # If the symbol is visible and has a user value, use that.
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001961 # Otherwise, look at defaults and weak reverse dependencies
1962 # (implies).
1963 use_defaults_and_weak_rev_deps = True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001964
1965 if vis != "n":
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001966 self.write_to_conf = True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001967 if self.user_val is not None:
1968 new_val = self.config._eval_min(self.user_val, vis)
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001969 use_defaults_and_weak_rev_deps = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001970
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001971 if use_defaults_and_weak_rev_deps:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001972 for val_expr, cond_expr in self.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001973 cond_eval = self.config._eval_expr(cond_expr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001974 if cond_eval != "n":
1975 self.write_to_conf = True
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001976 new_val = self.config._eval_min(val_expr,
1977 cond_eval)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001978 break
1979
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001980 weak_rev_dep_val = \
1981 self.config._eval_expr(self.weak_rev_dep)
1982 if weak_rev_dep_val != "n":
1983 self.write_to_conf = True
1984 new_val = self.config._eval_max(new_val,
1985 weak_rev_dep_val)
1986
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001987 # Reverse (select-related) dependencies take precedence
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001988 rev_dep_val = self.config._eval_expr(self.rev_dep)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001989 if rev_dep_val != "n":
1990 self.write_to_conf = True
1991 new_val = self.config._eval_max(new_val, rev_dep_val)
1992
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001993 # We need to promote "m" to "y" in two circumstances:
1994 # 1) If our type is boolean
1995 # 2) If our weak_rev_dep (from IMPLY) is "y"
1996 if new_val == "m" and \
1997 (self.type == BOOL or
1998 self.config._eval_expr(self.weak_rev_dep) == "y"):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001999 new_val = "y"
2000
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002001 elif self.type == INT or self.type == HEX:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002002 has_active_range = False
2003 low = None
2004 high = None
2005 use_defaults = True
2006
2007 base = 16 if self.type == HEX else 10
2008
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002009 for l, h, cond_expr in self.ranges:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002010 if self.config._eval_expr(cond_expr) != "n":
2011 has_active_range = True
2012
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002013 low_str = _str_val(l)
2014 high_str = _str_val(h)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002015 low = int(low_str, base) if \
2016 _is_base_n(low_str, base) else 0
2017 high = int(high_str, base) if \
2018 _is_base_n(high_str, base) else 0
2019
2020 break
2021
2022 if vis != "n":
2023 self.write_to_conf = True
2024
2025 if self.user_val is not None and \
2026 _is_base_n(self.user_val, base) and \
2027 (not has_active_range or
2028 low <= int(self.user_val, base) <= high):
2029
2030 # If the user value is OK, it is stored in exactly the same
2031 # form as specified in the assignment (with or without
2032 # "0x", etc).
2033
2034 use_defaults = False
2035 new_val = self.user_val
2036
2037 if use_defaults:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002038 for val_expr, cond_expr in self.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002039 if self.config._eval_expr(cond_expr) != "n":
2040 self.write_to_conf = True
2041
2042 # If the default value is OK, it is stored in exactly
2043 # the same form as specified. Otherwise, it is clamped
2044 # to the range, and the output has "0x" as appropriate
2045 # for the type.
2046
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002047 new_val = _str_val(val_expr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002048
2049 if _is_base_n(new_val, base):
2050 new_val_num = int(new_val, base)
2051 if has_active_range:
2052 clamped_val = None
2053
2054 if new_val_num < low:
2055 clamped_val = low
2056 elif new_val_num > high:
2057 clamped_val = high
2058
2059 if clamped_val is not None:
2060 new_val = (hex(clamped_val) if \
2061 self.type == HEX else str(clamped_val))
2062
2063 break
2064 else: # For the for loop
2065 # If no user value or default kicks in but the hex/int has
2066 # an active range, then the low end of the range is used,
2067 # provided it's > 0, with "0x" prepended as appropriate.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002068 if has_active_range and low > 0:
2069 new_val = (hex(low) if self.type == HEX else str(low))
2070
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002071 elif self.type == STRING:
2072 use_defaults = True
2073
2074 if vis != "n":
2075 self.write_to_conf = True
2076 if self.user_val is not None:
2077 new_val = self.user_val
2078 use_defaults = False
2079
2080 if use_defaults:
2081 for val_expr, cond_expr in self.def_exprs:
2082 if self.config._eval_expr(cond_expr) != "n":
2083 self.write_to_conf = True
2084 new_val = _str_val(val_expr)
2085 break
2086
2087 self.cached_val = new_val
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002088 return new_val
2089
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002090 def get_user_value(self):
2091 """Returns the value assigned to the symbol in a .config or via
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002092 Symbol.set_user_value() (provided the value was valid for the type of
2093 the symbol). Returns None in case of no user value."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002094 return self.user_val
2095
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002096 def get_upper_bound(self):
2097 """For string/hex/int symbols and for bool and tristate symbols that
2098 cannot be modified (see is_modifiable()), returns None.
2099
2100 Otherwise, returns the highest value the symbol can be set to with
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002101 Symbol.set_user_value() (that will not be truncated): one of "m" or
2102 "y", arranged from lowest to highest. This corresponds to the highest
2103 value the symbol could be given in e.g. the 'make menuconfig'
2104 interface.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002105
2106 See also the tri_less*() and tri_greater*() functions, which could come
2107 in handy."""
2108 if self.type != BOOL and self.type != TRISTATE:
2109 return None
2110 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002111 # A bool selected to "m" gets promoted to "y", pinning it
2112 if rev_dep == "m" and self.type == BOOL:
2113 return None
2114 vis = _get_visibility(self)
2115 if TRI_TO_INT[vis] > TRI_TO_INT[rev_dep]:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002116 return vis
2117 return None
2118
2119 def get_lower_bound(self):
2120 """For string/hex/int symbols and for bool and tristate symbols that
2121 cannot be modified (see is_modifiable()), returns None.
2122
2123 Otherwise, returns the lowest value the symbol can be set to with
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002124 Symbol.set_user_value() (that will not be truncated): one of "n" or
2125 "m", arranged from lowest to highest. This corresponds to the lowest
2126 value the symbol could be given in e.g. the 'make menuconfig'
2127 interface.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002128
2129 See also the tri_less*() and tri_greater*() functions, which could come
2130 in handy."""
2131 if self.type != BOOL and self.type != TRISTATE:
2132 return None
2133 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002134 # A bool selected to "m" gets promoted to "y", pinning it
2135 if rev_dep == "m" and self.type == BOOL:
2136 return None
2137 if TRI_TO_INT[_get_visibility(self)] > TRI_TO_INT[rev_dep]:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002138 return rev_dep
2139 return None
2140
2141 def get_assignable_values(self):
2142 """For string/hex/int symbols and for bool and tristate symbols that
2143 cannot be modified (see is_modifiable()), returns the empty list.
2144
2145 Otherwise, returns a list containing the user values that can be
2146 assigned to the symbol (that won't be truncated). Usage example:
2147
2148 if "m" in sym.get_assignable_values():
2149 sym.set_user_value("m")
2150
2151 This is basically a more convenient interface to
2152 get_lower/upper_bound() when wanting to test if a particular tristate
2153 value can be assigned."""
2154 if self.type != BOOL and self.type != TRISTATE:
2155 return []
2156 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002157 # A bool selected to "m" gets promoted to "y", pinning it
2158 if rev_dep == "m" and self.type == BOOL:
2159 return []
2160 res = ["n", "m", "y"][TRI_TO_INT[rev_dep] :
2161 TRI_TO_INT[_get_visibility(self)] + 1]
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002162 return res if len(res) > 1 else []
2163
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002164 def get_visibility(self):
2165 """Returns the visibility of the symbol: one of "n", "m" or "y". For
2166 bool and tristate symbols, this is an upper bound on the value users
2167 can set for the symbol. For other types of symbols, a visibility of "n"
2168 means the user value will be ignored. A visibility of "n" corresponds
2169 to not being visible in the 'make *config' interfaces.
2170
2171 Example (assuming we're running with modules enabled -- i.e., MODULES
2172 set to 'y'):
2173
2174 # Assume this has been assigned 'n'
2175 config N_SYM
2176 tristate "N_SYM"
2177
2178 # Assume this has been assigned 'm'
2179 config M_SYM
2180 tristate "M_SYM"
2181
2182 # Has visibility 'n'
2183 config A
2184 tristate "A"
2185 depends on N_SYM
2186
2187 # Has visibility 'm'
2188 config B
2189 tristate "B"
2190 depends on M_SYM
2191
2192 # Has visibility 'y'
2193 config C
2194 tristate "C"
2195
2196 # Has no prompt, and hence visibility 'n'
2197 config D
2198 tristate
2199
2200 Having visibility be tri-valued ensures that e.g. a symbol cannot be
2201 set to "y" by the user if it depends on a symbol with value "m", which
2202 wouldn't be safe.
2203
2204 You should probably look at get_lower/upper_bound(),
2205 get_assignable_values() and is_modifiable() before using this."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002206 return _get_visibility(self)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002207
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002208 def get_referenced_symbols(self, refs_from_enclosing=False):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002209 """Returns the set() of all symbols referenced by this symbol. For
2210 example, the symbol defined by
2211
2212 config FOO
2213 bool
2214 prompt "foo" if A && B
2215 default C if D
2216 depends on E
2217 select F if G
2218
2219 references the symbols A through G.
2220
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002221 refs_from_enclosing (default: False): If True, the symbols referenced
2222 by enclosing menus and ifs will be included in the result."""
2223 return self.all_referenced_syms if refs_from_enclosing else \
2224 self.referenced_syms
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002225
2226 def get_selected_symbols(self):
2227 """Returns the set() of all symbols X for which this symbol has a
2228 'select X' or 'select X if Y' (regardless of whether Y is satisfied or
2229 not). This is a subset of the symbols returned by
2230 get_referenced_symbols()."""
2231 return self.selected_syms
2232
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002233 def get_implied_symbols(self):
2234 """Returns the set() of all symbols X for which this symbol has an
2235 'imply X' or 'imply X if Y' (regardless of whether Y is satisfied or
2236 not). This is a subset of the symbols returned by
2237 get_referenced_symbols()."""
2238 return self.implied_syms
2239
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002240 def set_user_value(self, v):
2241 """Sets the user value of the symbol.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002242
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002243 Equal in effect to assigning the value to the symbol within a .config
2244 file. Use get_lower/upper_bound() or get_assignable_values() to find
2245 the range of currently assignable values for bool and tristate symbols;
2246 setting values outside this range will cause the user value to differ
2247 from the result of Symbol.get_value() (be truncated). Values that are
2248 invalid for the type (such as a_bool.set_user_value("foo")) are
2249 ignored, and a warning is emitted if an attempt is made to assign such
2250 a value.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002251
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002252 For any type of symbol, is_modifiable() can be used to check if a user
2253 value will currently have any effect on the symbol, as determined by
2254 its visibility and range of assignable values. Any value that is valid
2255 for the type (bool, tristate, etc.) will end up being reflected in
2256 get_user_value() though, and might have an effect later if conditions
2257 change. To get rid of the user value, use unset_user_value().
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002258
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002259 Any symbols dependent on the symbol are (recursively) invalidated, so
2260 things will just work with regards to dependencies.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002261
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002262 v: The user value to give to the symbol."""
2263 self._set_user_value_no_invalidate(v, False)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002264
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002265 # There might be something more efficient you could do here, but play
2266 # it safe.
2267 if self.name == "MODULES":
2268 self.config._invalidate_all()
2269 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002270
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002271 self._invalidate()
2272 self._invalidate_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002273
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002274 def unset_user_value(self):
2275 """Resets the user value of the symbol, as if the symbol had never
2276 gotten a user value via Config.load_config() or
2277 Symbol.set_user_value()."""
2278 self._unset_user_value_no_recursive_invalidate()
2279 self._invalidate_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002280
2281 def is_modifiable(self):
2282 """Returns True if the value of the symbol could be modified by calling
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002283 Symbol.set_user_value().
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002284
2285 For bools and tristates, this corresponds to the symbol being visible
2286 in the 'make menuconfig' interface and not already being pinned to a
2287 specific value (e.g. because it is selected by another symbol).
2288
2289 For strings and numbers, this corresponds to just being visible. (See
2290 Symbol.get_visibility().)"""
2291 if self.is_special_:
2292 return False
2293 if self.type == BOOL or self.type == TRISTATE:
2294 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002295 # A bool selected to "m" gets promoted to "y", pinning it
2296 if rev_dep == "m" and self.type == BOOL:
2297 return False
2298 return TRI_TO_INT[_get_visibility(self)] > TRI_TO_INT[rev_dep]
2299 return _get_visibility(self) != "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002300
2301 def is_defined(self):
2302 """Returns False if the symbol is referred to in the Kconfig but never
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002303 actually defined."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002304 return self.is_defined_
2305
2306 def is_special(self):
2307 """Returns True if the symbol is one of the special symbols n, m, y, or
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002308 UNAME_RELEASE, or gets its value from the environment."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002309 return self.is_special_
2310
2311 def is_from_environment(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002312 """Returns True if the symbol gets its value from the environment."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002313 return self.is_from_env
2314
2315 def has_ranges(self):
2316 """Returns True if the symbol is of type INT or HEX and has ranges that
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002317 limit what values it can take on."""
2318 return bool(self.ranges)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002319
2320 def is_choice_symbol(self):
2321 """Returns True if the symbol is in a choice statement and is an actual
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002322 choice symbol (see Choice.get_symbols())."""
2323 return self.is_choice_sym
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002324
2325 def is_choice_selection(self):
2326 """Returns True if the symbol is contained in a choice statement and is
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002327 the selected item. Equivalent to
2328
2329 sym.is_choice_symbol() and sym.get_parent().get_selection() is sym"""
2330 return self.is_choice_sym and self.parent.get_selection() is self
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002331
Masahiro Yamada9d01b782015-05-27 11:39:22 +09002332 def is_allnoconfig_y(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002333 """Returns True if the symbol has the 'allnoconfig_y' option set."""
Masahiro Yamada9d01b782015-05-27 11:39:22 +09002334 return self.allnoconfig_y
2335
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002336 def __str__(self):
2337 """Returns a string containing various information about the symbol."""
2338 return self.config._get_sym_or_choice_str(self)
2339
2340 #
2341 # Private methods
2342 #
2343
2344 def __init__(self):
2345 """Symbol constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002346 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002347
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002348 self.name = None
2349 self.type = UNKNOWN
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002350 self.prompts = []
2351 self.def_exprs = [] # 'default' properties
2352 self.ranges = [] # 'range' properties (for int and hex)
2353 self.help = None # Help text
2354 self.rev_dep = "n" # Reverse (select-related) dependencies
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002355 self.weak_rev_dep = "n" # Weak reverse (imply-related) dependencies
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002356 self.config = None
2357 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002358
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002359 self.user_val = None # Value set by user
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002360
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002361 # The prompt, default value, select, and imply conditions without any
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002362 # dependencies from menus and ifs propagated to them
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002363 self.orig_prompts = []
2364 self.orig_def_exprs = []
2365 self.orig_selects = []
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002366 self.orig_implies = []
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002367
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002368 # Dependencies inherited from containing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002369 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002370 # The set of symbols referenced by this symbol (see
2371 # get_referenced_symbols())
2372 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002373 # The set of symbols selected by this symbol (see
2374 # get_selected_symbols())
2375 self.selected_syms = set()
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002376 # The set of symbols implied by this symbol (see get_implied_symbols())
2377 self.implied_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002378 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002379 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002380 self.all_referenced_syms = set()
2381
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002382 # This records only dependencies from enclosing ifs and menus together
2383 # with local 'depends on' dependencies. Needed when determining actual
2384 # choice items (hrrrr...). See Choice._determine_actual_symbols().
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002385 self.menu_dep = None
2386
2387 # See Symbol.get_ref/def_locations().
2388 self.def_locations = []
2389 self.ref_locations = []
2390
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002391 # Populated in Config._build_dep() after parsing. Links the symbol to
2392 # the symbols that immediately depend on it (in a caching/invalidation
2393 # sense). The total set of dependent symbols for the symbol (the
2394 # transitive closure) is calculated on an as-needed basis in
2395 # _get_dependent().
2396 self.dep = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002397
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002398 # Cached values
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002399
2400 # Caches the calculated value
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002401 self.cached_val = None
2402 # Caches the visibility, which acts as an upper bound on the value
2403 self.cached_visibility = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002404 # Caches the total list of dependent symbols. Calculated in
2405 # _get_dependent().
2406 self.cached_deps = None
2407
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002408 # Flags
2409
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002410 # Does the symbol have an entry in the Kconfig file? The trailing
2411 # underscore avoids a collision with is_defined().
2412 self.is_defined_ = False
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002413 # Should the symbol get an entry in .config?
2414 self.write_to_conf = False
2415 # Set to true when _make_conf() is called on a symbol, so that symbols
2416 # defined in multiple locations only get one .config entry. We need to
2417 # reset it prior to writing out a new .config.
2418 self.already_written = False
2419 # This is set to True for "actual" choice symbols; see
2420 # Choice._determine_actual_symbols().
2421 self.is_choice_sym = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002422 # Does the symbol get its value in some special way, e.g. from the
2423 # environment or by being one of the special symbols n, m, and y? If
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002424 # so, the value is stored in self.cached_val, which is never
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002425 # invalidated. The trailing underscore avoids a collision with
2426 # is_special().
2427 self.is_special_ = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002428 # Does the symbol get its value from the environment?
2429 self.is_from_env = False
Masahiro Yamada9d01b782015-05-27 11:39:22 +09002430 # Does the symbol have the 'allnoconfig_y' option set?
2431 self.allnoconfig_y = False
2432
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002433 def _invalidate(self):
2434 if self.is_special_:
2435 return
2436
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002437 if self.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002438 self.parent._invalidate()
2439
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002440 self.cached_val = None
2441 self.cached_visibility = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002442
2443 def _invalidate_dependent(self):
2444 for sym in self._get_dependent():
2445 sym._invalidate()
2446
2447 def _set_user_value_no_invalidate(self, v, suppress_load_warnings):
2448 """Like set_user_value(), but does not invalidate any symbols.
2449
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002450 suppress_load_warnings: some warnings are annoying when loading a
2451 .config that can be helpful when manually invoking set_user_value().
2452 This flag is set to True to suppress such warnings.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002453
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002454 Perhaps this could be made optional for load_config() instead."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002455
2456 if self.is_special_:
2457 if self.is_from_env:
2458 self.config._warn('attempt to assign the value "{0}" to the '
2459 'symbol {1}, which gets its value from the '
2460 'environment. Assignment ignored.'
2461 .format(v, self.name))
2462 else:
2463 self.config._warn('attempt to assign the value "{0}" to the '
2464 'special symbol {1}. Assignment ignored.'
2465 .format(v, self.name))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002466 return
2467
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002468 if not self.is_defined_:
2469 filename, linenr = self.ref_locations[0]
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002470 if self.config.print_undef_assign:
2471 _stderr_msg('note: attempt to assign the value "{0}" to {1}, '
2472 "which is referenced at {2}:{3} but never "
2473 "defined. Assignment ignored."
2474 .format(v, self.name, filename, linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002475 return
2476
2477 # Check if the value is valid for our type
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002478 if not ((self.type == BOOL and (v == "y" or v == "n") ) or
2479 (self.type == TRISTATE and (v == "y" or v == "m" or
2480 v == "n") ) or
2481 (self.type == STRING ) or
2482 (self.type == INT and _is_base_n(v, 10) ) or
2483 (self.type == HEX and _is_base_n(v, 16) )):
2484 self.config._warn('the value "{0}" is invalid for {1}, which has '
2485 "type {2}. Assignment ignored."
2486 .format(v, self.name, TYPENAME[self.type]))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002487 return
2488
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002489 if not self.prompts and not suppress_load_warnings:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002490 self.config._warn('assigning "{0}" to the symbol {1} which '
2491 'lacks prompts and thus has visibility "n". '
2492 'The assignment will have no effect.'
2493 .format(v, self.name))
2494
2495 self.user_val = v
2496
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002497 if self.is_choice_sym and (self.type == BOOL or self.type == TRISTATE):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002498 choice = self.parent
2499 if v == "y":
2500 choice.user_val = self
2501 choice.user_mode = "y"
2502 elif v == "m":
2503 choice.user_val = None
2504 choice.user_mode = "m"
2505
2506 def _unset_user_value_no_recursive_invalidate(self):
2507 self._invalidate()
2508 self.user_val = None
2509
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002510 if self.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002511 self.parent._unset_user_value()
2512
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002513 def _make_conf(self, append_fn):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002514 if self.already_written:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002515 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002516
2517 self.already_written = True
2518
2519 # Note: write_to_conf is determined in get_value()
2520 val = self.get_value()
2521 if not self.write_to_conf:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002522 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002523
2524 if self.type == BOOL or self.type == TRISTATE:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002525 append_fn("{0}{1}={2}".format(self.config.config_prefix, self.name, val)
2526 if val == "y" or val == "m" else
2527 "# {0}{1} is not set".format(self.config.config_prefix, self.name))
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002528
2529 elif self.type == INT or self.type == HEX:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002530 append_fn("{0}{1}={2}".format(self.config.config_prefix, self.name, val))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002531
2532 elif self.type == STRING:
2533 # Escape \ and "
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002534 append_fn('{0}{1}="{2}"'
2535 .format(self.config.config_prefix, self.name,
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002536 val.replace("\\", "\\\\").replace('"', '\\"')))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002537
2538 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002539 _internal_error("Internal error while creating .config: unknown "
2540 'type "{0}".'.format(self.type))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002541
2542 def _get_dependent(self):
2543 """Returns the set of symbols that should be invalidated if the value
2544 of the symbol changes, because they might be affected by the change.
2545 Note that this is an internal API -- it's probably of limited
2546 usefulness to clients."""
2547 if self.cached_deps is not None:
2548 return self.cached_deps
2549
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002550 res = set(self.dep)
2551 for s in self.dep:
2552 res |= s._get_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002553
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002554 if self.is_choice_sym:
2555 # Choice symbols also depend (recursively) on their siblings. The
2556 # siblings are not included in 'dep' to avoid dependency loops.
2557 for sibling in self.parent.actual_symbols:
2558 if sibling is not self:
2559 res.add(sibling)
2560 res |= sibling.dep
2561 for s in sibling.dep:
2562 res |= s._get_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002563
2564 self.cached_deps = res
2565 return res
2566
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002567 def _has_auto_menu_dep_on(self, on):
2568 """See Choice._determine_actual_symbols()."""
2569 if not isinstance(self.parent, Choice):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002570 _internal_error("Attempt to determine auto menu dependency for "
2571 "symbol ouside of choice.")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002572
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002573 if not self.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002574 # If we have no prompt, use the menu dependencies instead (what was
2575 # specified with 'depends on')
2576 return self.menu_dep is not None and \
2577 self.config._expr_depends_on(self.menu_dep, on)
2578
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002579 for _, cond_expr in self.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002580 if self.config._expr_depends_on(cond_expr, on):
2581 return True
2582
2583 return False
2584
2585class Menu(Item):
2586
2587 """Represents a menu statement."""
2588
2589 #
2590 # Public interface
2591 #
2592
2593 def get_config(self):
2594 """Return the Config instance this menu is from."""
2595 return self.config
2596
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002597 def get_title(self):
2598 """Returns the title text of the menu."""
2599 return self.title
2600
2601 def get_parent(self):
2602 """Returns the menu or choice statement that contains the menu, or
2603 None if the menu is at the top level. Note that if statements are
2604 treated as syntactic sugar and do not have an explicit class
2605 representation."""
2606 return self.parent
2607
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002608 def get_location(self):
2609 """Returns the location of the menu as a (filename, linenr) tuple,
2610 where filename is a string and linenr an int."""
2611 return (self.filename, self.linenr)
2612
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002613 def get_items(self, recursive=False):
2614 """Returns a list containing the items (symbols, menus, choice
2615 statements and comments) in in the menu, in the same order that the
2616 items appear within the menu.
2617
2618 recursive (default: False): True if items contained in items within the
2619 menu should be included recursively (preorder)."""
2620
2621 if not recursive:
2622 return self.block
2623
2624 res = []
2625 for item in self.block:
2626 res.append(item)
2627 if isinstance(item, Menu):
2628 res.extend(item.get_items(True))
2629 elif isinstance(item, Choice):
2630 res.extend(item.get_items())
2631 return res
2632
2633 def get_symbols(self, recursive=False):
2634 """Returns a list containing the symbols in the menu, in the same order
2635 that they appear within the menu.
2636
2637 recursive (default: False): True if symbols contained in items within
2638 the menu should be included recursively."""
2639
2640 return [item for item in self.get_items(recursive) if
2641 isinstance(item, Symbol)]
2642
2643 def get_visibility(self):
2644 """Returns the visibility of the menu. This also affects the visibility
2645 of subitems. See also Symbol.get_visibility()."""
2646 return self.config._eval_expr(self.dep_expr)
2647
2648 def get_visible_if_visibility(self):
2649 """Returns the visibility the menu gets from its 'visible if'
2650 condition. "y" if the menu has no 'visible if' condition."""
2651 return self.config._eval_expr(self.visible_if_expr)
2652
2653 def get_referenced_symbols(self, refs_from_enclosing=False):
2654 """See Symbol.get_referenced_symbols()."""
2655 return self.all_referenced_syms if refs_from_enclosing else \
2656 self.referenced_syms
2657
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002658 def __str__(self):
2659 """Returns a string containing various information about the menu."""
2660 depends_on_str = self.config._expr_val_str(self.orig_deps,
2661 "(no dependencies)")
2662 visible_if_str = self.config._expr_val_str(self.visible_if_expr,
2663 "(no dependencies)")
2664
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002665 additional_deps_str = " " + \
2666 self.config._expr_val_str(self.deps_from_containing,
2667 "(no additional dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002668
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002669 return _lines("Menu",
2670 "Title : " + self.title,
2671 "'depends on' dependencies : " + depends_on_str,
2672 "'visible if' dependencies : " + visible_if_str,
2673 "Additional dependencies from enclosing menus and "
2674 "ifs:",
2675 additional_deps_str,
2676 "Location: {0}:{1}".format(self.filename, self.linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002677
2678 #
2679 # Private methods
2680 #
2681
2682 def __init__(self):
2683 """Menu constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002684 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002685
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002686 self.title = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002687 self.dep_expr = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002688 self.visible_if_expr = None
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002689 self.block = [] # List of contained items
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002690 self.config = None
2691 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002692
2693 # Dependency expression without dependencies from enclosing menus and
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002694 # ifs propagated
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002695 self.orig_deps = None
2696
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002697 # Dependencies inherited from containing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002698 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002699 # The set of symbols referenced by this menu (see
2700 # get_referenced_symbols())
2701 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002702 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002703 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002704 self.all_referenced_syms = None
2705
2706 self.filename = None
2707 self.linenr = None
2708
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002709 def _make_conf(self, append_fn):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002710 if self.config._eval_expr(self.dep_expr) != "n" and \
2711 self.config._eval_expr(self.visible_if_expr) != "n":
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002712 append_fn("\n#\n# {0}\n#".format(self.title))
2713 _make_block_conf(self.block, append_fn)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002714
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002715class Choice(Item):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002716
2717 """Represents a choice statement. A choice can be in one of three modes:
2718
2719 "n" - The choice is not visible and no symbols can be selected.
2720
2721 "m" - Any number of symbols can be set to "m". The rest will be "n". This
2722 is safe since potentially conflicting options don't actually get
2723 compiled into the kernel simultaneously with "m".
2724
2725 "y" - One symbol will be "y" while the rest are "n".
2726
2727 Only tristate choices can be in "m" mode, and the visibility of the choice
2728 is an upper bound on the mode, so that e.g. a choice that depends on a
2729 symbol with value "m" will be in "m" mode.
2730
2731 The mode changes automatically when a value is assigned to a symbol within
2732 the choice.
2733
2734 See Symbol.get_visibility() too."""
2735
2736 #
2737 # Public interface
2738 #
2739
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002740 def get_config(self):
2741 """Returns the Config instance this choice is from."""
2742 return self.config
2743
2744 def get_name(self):
2745 """For named choices, returns the name. Returns None for unnamed
2746 choices. No named choices appear anywhere in the kernel Kconfig files
2747 as of Linux 3.7.0-rc8."""
2748 return self.name
2749
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002750 def get_type(self):
2751 """Returns the type of the choice. See Symbol.get_type()."""
2752 return self.type
2753
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002754 def get_prompts(self):
2755 """Returns a list of prompts defined for the choice, in the order they
2756 appear in the configuration files. Returns the empty list for choices
2757 with no prompt.
2758
2759 This list will have a single entry for the vast majority of choices
2760 having prompts, but having multiple prompts for a single choice is
2761 possible through having multiple 'choice' entries for it (though I'm
2762 not sure if that ever happens in practice)."""
2763 return [prompt for prompt, _ in self.orig_prompts]
2764
2765 def get_help(self):
2766 """Returns the help text of the choice, or None if the choice has no
2767 help text."""
2768 return self.help
2769
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002770 def get_parent(self):
2771 """Returns the menu or choice statement that contains the choice, or
2772 None if the choice is at the top level. Note that if statements are
2773 treated as syntactic sugar and do not have an explicit class
2774 representation."""
2775 return self.parent
2776
2777 def get_def_locations(self):
2778 """Returns a list of (filename, linenr) tuples, where filename (string)
2779 and linenr (int) represent a location where the choice is defined. For
2780 the vast majority of choices (all of them as of Linux 3.7.0-rc8) this
2781 list will only contain one element, but its possible for named choices
2782 to be defined in multiple locations."""
2783 return self.def_locations
2784
2785 def get_selection(self):
2786 """Returns the symbol selected (either by the user or through
2787 defaults), or None if either no symbol is selected or the mode is not
2788 "y"."""
2789 if self.cached_selection is not None:
2790 if self.cached_selection == NO_SELECTION:
2791 return None
2792 return self.cached_selection
2793
2794 if self.get_mode() != "y":
2795 return self._cache_ret(None)
2796
2797 # User choice available?
2798 if self.user_val is not None and _get_visibility(self.user_val) == "y":
2799 return self._cache_ret(self.user_val)
2800
2801 if self.optional:
2802 return self._cache_ret(None)
2803
2804 return self._cache_ret(self.get_selection_from_defaults())
2805
2806 def get_selection_from_defaults(self):
2807 """Like Choice.get_selection(), but acts as if no symbol has been
2808 selected by the user and no 'optional' flag is in effect."""
2809
2810 if not self.actual_symbols:
2811 return None
2812
2813 for symbol, cond_expr in self.def_exprs:
2814 if self.config._eval_expr(cond_expr) != "n":
2815 chosen_symbol = symbol
2816 break
2817 else:
2818 chosen_symbol = self.actual_symbols[0]
2819
2820 # Is the chosen symbol visible?
2821 if _get_visibility(chosen_symbol) != "n":
2822 return chosen_symbol
2823 # Otherwise, pick the first visible symbol
2824 for sym in self.actual_symbols:
2825 if _get_visibility(sym) != "n":
2826 return sym
2827 return None
2828
2829 def get_user_selection(self):
2830 """If the choice is in "y" mode and has a user-selected symbol, returns
2831 that symbol. Otherwise, returns None."""
2832 return self.user_val
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002833
2834 def get_items(self):
2835 """Gets all items contained in the choice in the same order as within
2836 the configuration ("items" instead of "symbols" since choices and
2837 comments might appear within choices. This only happens in one place as
2838 of Linux 3.7.0-rc8, in drivers/usb/gadget/Kconfig)."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002839 return self.block
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002840
2841 def get_symbols(self):
2842 """Returns a list containing the choice's symbols.
2843
2844 A quirk (perhaps a bug) of Kconfig is that you can put items within a
2845 choice that will not be considered members of the choice insofar as
2846 selection is concerned. This happens for example if one symbol within a
2847 choice 'depends on' the symbol preceding it, or if you put non-symbol
2848 items within choices.
2849
2850 As of Linux 3.7.0-rc8, this seems to be used intentionally in one
2851 place: drivers/usb/gadget/Kconfig.
2852
2853 This function returns the "proper" symbols of the choice in the order
2854 they appear in the choice, excluding such items. If you want all items
2855 in the choice, use get_items()."""
2856 return self.actual_symbols
2857
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002858 def get_referenced_symbols(self, refs_from_enclosing=False):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002859 """See Symbol.get_referenced_symbols()."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002860 return self.all_referenced_syms if refs_from_enclosing else \
2861 self.referenced_syms
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002862
2863 def get_visibility(self):
2864 """Returns the visibility of the choice statement: one of "n", "m" or
2865 "y". This acts as an upper limit on the mode of the choice (though bool
2866 choices can only have the mode "y"). See the class documentation for an
2867 explanation of modes."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002868 return _get_visibility(self)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002869
2870 def get_mode(self):
2871 """Returns the mode of the choice. See the class documentation for
2872 an explanation of modes."""
2873 minimum_mode = "n" if self.optional else "m"
2874 mode = self.user_mode if self.user_mode is not None else minimum_mode
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002875 mode = self.config._eval_min(mode, _get_visibility(self))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002876
2877 # Promote "m" to "y" for boolean choices
2878 if mode == "m" and self.type == BOOL:
2879 return "y"
2880
2881 return mode
2882
2883 def is_optional(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002884 """Returns True if the choice has the 'optional' flag set (and so will
2885 default to "n" mode)."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002886 return self.optional
2887
2888 def __str__(self):
2889 """Returns a string containing various information about the choice
2890 statement."""
2891 return self.config._get_sym_or_choice_str(self)
2892
2893 #
2894 # Private methods
2895 #
2896
2897 def __init__(self):
2898 """Choice constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002899 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002900
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002901 self.name = None # Yes, choices can be named
2902 self.type = UNKNOWN
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002903 self.prompts = []
2904 self.def_exprs = [] # 'default' properties
2905 self.help = None # Help text
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002906 self.block = [] # List of contained items
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002907 self.config = None
2908 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002909
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002910 self.user_val = None
2911 self.user_mode = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002912
2913 # We need to filter out symbols that appear within the choice block but
2914 # are not considered choice items (see
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002915 # Choice._determine_actual_symbols()) This list holds the "actual"
2916 # choice items.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002917 self.actual_symbols = []
2918
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002919 # The prompts and default values without any dependencies from
2920 # enclosing menus and ifs propagated
2921 self.orig_prompts = []
2922 self.orig_def_exprs = []
2923
2924 # Dependencies inherited from containing menus and ifs
2925 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002926 # The set of symbols referenced by this choice (see
2927 # get_referenced_symbols())
2928 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002929 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002930 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002931 self.all_referenced_syms = set()
2932
2933 # See Choice.get_def_locations()
2934 self.def_locations = []
2935
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002936 # Cached values
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002937 self.cached_selection = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002938 self.cached_visibility = None
2939
2940 self.optional = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002941
2942 def _determine_actual_symbols(self):
2943 """If a symbol's visibility depends on the preceding symbol within a
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002944 choice, it is no longer viewed as a choice item. (This is quite
2945 possibly a bug, but some things consciously use it... ugh. It stems
2946 from automatic submenu creation.) In addition, it's possible to have
2947 choices and comments within choices, and those shouldn't be considered
2948 choice items either. Only drivers/usb/gadget/Kconfig seems to depend on
2949 any of this. This method computes the "actual" items in the choice and
2950 sets the is_choice_sym flag on them (retrieved via is_choice_symbol()).
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002951
2952 Don't let this scare you: an earlier version simply checked for a
2953 sequence of symbols where all symbols after the first appeared in the
2954 'depends on' expression of the first, and that worked fine. The added
2955 complexity is to be future-proof in the event that
2956 drivers/usb/gadget/Kconfig turns even more sinister. It might very well
2957 be overkilling things (especially if that file is refactored ;)."""
2958
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002959 # Items might depend on each other in a tree structure, so we need a
2960 # stack to keep track of the current tentative parent
2961 stack = []
2962
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002963 for item in self.block:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002964 if not isinstance(item, Symbol):
2965 stack = []
2966 continue
2967
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002968 while stack:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002969 if item._has_auto_menu_dep_on(stack[-1]):
2970 # The item should not be viewed as a choice item, so don't
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002971 # set item.is_choice_sym
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002972 stack.append(item)
2973 break
2974 else:
2975 stack.pop()
2976 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002977 item.is_choice_sym = True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002978 self.actual_symbols.append(item)
2979 stack.append(item)
2980
2981 def _cache_ret(self, selection):
2982 # As None is used to indicate the lack of a cached value we can't use
2983 # that to cache the fact that the choice has no selection. Instead, we
2984 # use the symbolic constant NO_SELECTION.
2985 if selection is None:
2986 self.cached_selection = NO_SELECTION
2987 else:
2988 self.cached_selection = selection
2989
2990 return selection
2991
2992 def _invalidate(self):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002993 self.cached_selection = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002994 self.cached_visibility = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002995
2996 def _unset_user_value(self):
2997 self._invalidate()
2998 self.user_val = None
2999 self.user_mode = None
3000
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003001 def _make_conf(self, append_fn):
3002 _make_block_conf(self.block, append_fn)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003003
3004class Comment(Item):
3005
3006 """Represents a comment statement."""
3007
3008 #
3009 # Public interface
3010 #
3011
3012 def get_config(self):
3013 """Returns the Config instance this comment is from."""
3014 return self.config
3015
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003016 def get_text(self):
3017 """Returns the text of the comment."""
3018 return self.text
3019
3020 def get_parent(self):
3021 """Returns the menu or choice statement that contains the comment, or
3022 None if the comment is at the top level. Note that if statements are
3023 treated as syntactic sugar and do not have an explicit class
3024 representation."""
3025 return self.parent
3026
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003027 def get_location(self):
3028 """Returns the location of the comment as a (filename, linenr) tuple,
3029 where filename is a string and linenr an int."""
3030 return (self.filename, self.linenr)
3031
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003032 def get_visibility(self):
3033 """Returns the visibility of the comment. See also
3034 Symbol.get_visibility()."""
3035 return self.config._eval_expr(self.dep_expr)
3036
3037 def get_referenced_symbols(self, refs_from_enclosing=False):
3038 """See Symbol.get_referenced_symbols()."""
3039 return self.all_referenced_syms if refs_from_enclosing else \
3040 self.referenced_syms
3041
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003042 def __str__(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003043 """Returns a string containing various information about the
3044 comment."""
3045 dep_str = self.config._expr_val_str(self.orig_deps,
3046 "(no dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003047
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003048 additional_deps_str = " " + \
3049 self.config._expr_val_str(self.deps_from_containing,
3050 "(no additional dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003051
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003052 return _lines("Comment",
3053 "Text: " + str(self.text),
3054 "Dependencies: " + dep_str,
3055 "Additional dependencies from enclosing menus and "
3056 "ifs:",
3057 additional_deps_str,
3058 "Location: {0}:{1}".format(self.filename, self.linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003059
3060 #
3061 # Private methods
3062 #
3063
3064 def __init__(self):
3065 """Comment constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003066 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003067
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003068 self.text = None
3069 self.dep_expr = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003070 self.config = None
3071 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003072
3073 # Dependency expression without dependencies from enclosing menus and
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003074 # ifs propagated
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003075 self.orig_deps = None
3076
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003077 # Dependencies inherited from containing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003078 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003079 # The set of symbols referenced by this comment (see
3080 # get_referenced_symbols())
3081 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003082 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003083 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003084 self.all_referenced_syms = None
3085
3086 self.filename = None
3087 self.linenr = None
3088
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003089 def _make_conf(self, append_fn):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003090 if self.config._eval_expr(self.dep_expr) != "n":
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003091 append_fn("\n#\n# {0}\n#".format(self.text))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003092
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003093class Kconfig_Syntax_Error(Exception):
3094 """Exception raised for syntax errors."""
3095 pass
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003096
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003097class Internal_Error(Exception):
3098 """Exception raised for internal errors."""
3099 pass
3100
3101#
3102# Public functions
3103#
3104
3105def tri_less(v1, v2):
3106 """Returns True if the tristate v1 is less than the tristate v2, where "n",
3107 "m" and "y" are ordered from lowest to highest."""
3108 return TRI_TO_INT[v1] < TRI_TO_INT[v2]
3109
3110def tri_less_eq(v1, v2):
3111 """Returns True if the tristate v1 is less than or equal to the tristate
3112 v2, where "n", "m" and "y" are ordered from lowest to highest."""
3113 return TRI_TO_INT[v1] <= TRI_TO_INT[v2]
3114
3115def tri_greater(v1, v2):
3116 """Returns True if the tristate v1 is greater than the tristate v2, where
3117 "n", "m" and "y" are ordered from lowest to highest."""
3118 return TRI_TO_INT[v1] > TRI_TO_INT[v2]
3119
3120def tri_greater_eq(v1, v2):
3121 """Returns True if the tristate v1 is greater than or equal to the tristate
3122 v2, where "n", "m" and "y" are ordered from lowest to highest."""
3123 return TRI_TO_INT[v1] >= TRI_TO_INT[v2]
3124
3125#
3126# Internal classes
3127#
3128
3129class _Feed(object):
3130
3131 """Class for working with sequences in a stream-like fashion; handy for
3132 tokens."""
3133
3134 # This would be more helpful on the item classes, but would remove some
3135 # flexibility
3136 __slots__ = ['items', 'length', 'i']
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003137
3138 def __init__(self, items):
3139 self.items = items
3140 self.length = len(self.items)
3141 self.i = 0
3142
3143 def get_next(self):
3144 if self.i >= self.length:
3145 return None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003146 item = self.items[self.i]
3147 self.i += 1
3148 return item
3149
3150 def peek_next(self):
3151 return None if self.i >= self.length else self.items[self.i]
3152
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003153 def check(self, token):
3154 """Check if the next token is 'token'. If so, remove it from the token
3155 feed and return True. Otherwise, leave it in and return False."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003156 if self.i < self.length and self.items[self.i] == token:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003157 self.i += 1
3158 return True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003159 return False
3160
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003161 def unget_all(self):
3162 self.i = 0
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003163
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003164class _FileFeed(object):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003165
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003166 """Feeds lines from a file. Keeps track of the filename and current line
3167 number. Joins any line ending in \\ with the following line. We need to be
3168 careful to get the line number right in the presence of continuation
3169 lines."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003170
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003171 __slots__ = ['filename', 'lines', 'length', 'linenr']
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003172
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003173 def __init__(self, filename):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003174 self.filename = _clean_up_path(filename)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003175 with open(filename, "r") as f:
3176 # No interleaving of I/O and processing yet. Don't know if it would
3177 # help.
3178 self.lines = f.readlines()
3179 self.length = len(self.lines)
3180 self.linenr = 0
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003181
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003182 def get_next(self):
3183 if self.linenr >= self.length:
3184 return None
3185 line = self.lines[self.linenr]
3186 self.linenr += 1
3187 while line.endswith("\\\n"):
3188 line = line[:-2] + self.lines[self.linenr]
3189 self.linenr += 1
3190 return line
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003191
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003192 def peek_next(self):
3193 linenr = self.linenr
3194 if linenr >= self.length:
3195 return None
3196 line = self.lines[linenr]
3197 while line.endswith("\\\n"):
3198 linenr += 1
3199 line = line[:-2] + self.lines[linenr]
3200 return line
3201
3202 def unget(self):
3203 self.linenr -= 1
3204 while self.lines[self.linenr].endswith("\\\n"):
3205 self.linenr -= 1
3206
3207 def next_nonblank(self):
3208 """Removes lines up to and including the next non-blank (not all-space)
3209 line and returns it. Returns None if there are no more non-blank
3210 lines."""
3211 while 1:
3212 line = self.get_next()
3213 if line is None or not line.isspace():
3214 return line
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003215
3216#
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003217# Internal functions
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003218#
3219
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003220def _get_visibility(sc):
3221 """Symbols and Choices have a "visibility" that acts as an upper bound on
3222 the values a user can set for them, corresponding to the visibility in e.g.
3223 'make menuconfig'. This function calculates the visibility for the Symbol
3224 or Choice 'sc' -- the logic is nearly identical."""
3225 if sc.cached_visibility is None:
3226 vis = "n"
3227 for _, cond_expr in sc.prompts:
3228 vis = sc.config._eval_max(vis, cond_expr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003229
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003230 if isinstance(sc, Symbol) and sc.is_choice_sym:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02003231 if sc.type == TRISTATE and vis == "m" and \
3232 sc.parent.get_mode() == "y":
3233 # Choice symbols with visibility "m" are not visible if the
3234 # choice has mode "y"
3235 vis = "n"
3236 else:
3237 vis = sc.config._eval_min(vis, _get_visibility(sc.parent))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003238
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003239 # Promote "m" to "y" if we're dealing with a non-tristate
3240 if vis == "m" and sc.type != TRISTATE:
3241 vis = "y"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003242
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003243 sc.cached_visibility = vis
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003244
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003245 return sc.cached_visibility
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003246
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003247def _make_and(e1, e2):
3248 """Constructs an AND (&&) expression. Performs trivial simplification.
3249 Nones equate to 'y'.
3250
3251 Note: returns None if e1 == e2 == None."""
3252 if e1 is None or e1 == "y":
3253 return e2
3254 if e2 is None or e2 == "y":
3255 return e1
3256
3257 # Prefer to merge argument lists if possible to reduce the number of nodes
3258
3259 if isinstance(e1, tuple) and e1[0] == AND:
3260 if isinstance(e2, tuple) and e2[0] == AND:
3261 return (AND, e1[1] + e2[1])
3262 return (AND, e1[1] + [e2])
3263
3264 if isinstance(e2, tuple) and e2[0] == AND:
3265 return (AND, e2[1] + [e1])
3266
3267 return (AND, [e1, e2])
3268
3269def _make_or(e1, e2):
3270 """Constructs an OR (||) expression. Performs trivial simplification and
3271 avoids Nones. Nones equate to 'y', which is usually what we want, but needs
3272 to be kept in mind."""
3273
3274 # Perform trivial simplification and avoid None's (which
3275 # correspond to y's)
3276 if e1 is None or e2 is None or e1 == "y" or e2 == "y":
3277 return "y"
3278 if e1 == "n":
3279 return e2
3280
3281 # Prefer to merge argument lists if possible to reduce the number of nodes
3282
3283 if isinstance(e1, tuple) and e1[0] == OR:
3284 if isinstance(e2, tuple) and e2[0] == OR:
3285 return (OR, e1[1] + e2[1])
3286 return (OR, e1[1] + [e2])
3287
3288 if isinstance(e2, tuple) and e2[0] == OR:
3289 return (OR, e2[1] + [e1])
3290
3291 return (OR, [e1, e2])
3292
3293def _get_expr_syms_rec(expr, res):
3294 """_get_expr_syms() helper. Recurses through expressions."""
3295 if isinstance(expr, Symbol):
3296 res.add(expr)
3297 elif isinstance(expr, str):
3298 return
3299 elif expr[0] == AND or expr[0] == OR:
3300 for term in expr[1]:
3301 _get_expr_syms_rec(term, res)
3302 elif expr[0] == NOT:
3303 _get_expr_syms_rec(expr[1], res)
3304 elif expr[0] == EQUAL or expr[0] == UNEQUAL:
3305 if isinstance(expr[1], Symbol):
3306 res.add(expr[1])
3307 if isinstance(expr[2], Symbol):
3308 res.add(expr[2])
3309 else:
3310 _internal_error("Internal error while fetching symbols from an "
3311 "expression with token stream {0}.".format(expr))
3312
3313def _get_expr_syms(expr):
3314 """Returns the set() of symbols appearing in expr."""
3315 res = set()
3316 if expr is not None:
3317 _get_expr_syms_rec(expr, res)
3318 return res
3319
3320def _str_val(obj):
3321 """Returns the value of obj as a string. If obj is not a string (constant
3322 symbol), it must be a Symbol."""
3323 return obj if isinstance(obj, str) else obj.get_value()
3324
3325def _make_block_conf(block, append_fn):
3326 """Returns a list of .config strings for a block (list) of items."""
3327
3328 # Collect the substrings in a list and later use join() instead of += to
3329 # build the final .config contents. With older Python versions, this yields
3330 # linear instead of quadratic complexity.
3331 for item in block:
3332 item._make_conf(append_fn)
3333
3334def _sym_str_string(sym_or_str):
3335 if isinstance(sym_or_str, str):
3336 return '"' + sym_or_str + '"'
3337 return sym_or_str.name
3338
3339def _intersperse(lst, op):
3340 """_expr_to_str() helper. Gets the string representation of each expression
3341 in lst and produces a list where op has been inserted between the
3342 elements."""
3343 if not lst:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003344 return ""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003345
3346 res = []
3347
3348 def handle_sub_expr(expr):
3349 no_parens = isinstance(expr, (str, Symbol)) or \
3350 expr[0] in (EQUAL, UNEQUAL) or \
3351 PRECEDENCE[op] <= PRECEDENCE[expr[0]]
3352 if not no_parens:
3353 res.append("(")
3354 res.extend(_expr_to_str_rec(expr))
3355 if not no_parens:
3356 res.append(")")
3357
3358 op_str = OP_TO_STR[op]
3359
3360 handle_sub_expr(lst[0])
3361 for expr in lst[1:]:
3362 res.append(op_str)
3363 handle_sub_expr(expr)
3364
3365 return res
3366
3367def _expr_to_str_rec(expr):
3368 if expr is None:
3369 return [""]
3370
3371 if isinstance(expr, (Symbol, str)):
3372 return [_sym_str_string(expr)]
3373
3374 if expr[0] in (AND, OR):
3375 return _intersperse(expr[1], expr[0])
3376
3377 if expr[0] == NOT:
3378 need_parens = not isinstance(expr[1], (str, Symbol))
3379
3380 res = ["!"]
3381 if need_parens:
3382 res.append("(")
3383 res.extend(_expr_to_str_rec(expr[1]))
3384 if need_parens:
3385 res.append(")")
3386 return res
3387
3388 if expr[0] in (EQUAL, UNEQUAL):
3389 return [_sym_str_string(expr[1]),
3390 OP_TO_STR[expr[0]],
3391 _sym_str_string(expr[2])]
3392
3393def _expr_to_str(expr):
3394 return "".join(_expr_to_str_rec(expr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003395
3396def _indentation(line):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003397 """Returns the length of the line's leading whitespace, treating tab stops
3398 as being spaced 8 characters apart."""
3399 line = line.expandtabs()
3400 return len(line) - len(line.lstrip())
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003401
3402def _deindent(line, indent):
3403 """Deindent 'line' by 'indent' spaces."""
3404 line = line.expandtabs()
3405 if len(line) <= indent:
3406 return line
3407 return line[indent:]
3408
3409def _is_base_n(s, n):
3410 try:
3411 int(s, n)
3412 return True
3413 except ValueError:
3414 return False
3415
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003416def _lines(*args):
3417 """Returns a string consisting of all arguments, with newlines inserted
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003418 between them."""
3419 return "\n".join(args)
3420
3421def _comment(s):
3422 """Returns a new string with "#" inserted before each line in 's'."""
3423 if not s:
3424 return "#"
3425 res = "".join(["#" + line for line in s.splitlines(True)])
3426 if s.endswith("\n"):
3427 return res + "#"
3428 return res
3429
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003430def _clean_up_path(path):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003431 """Strips an initial "./" and any trailing slashes from 'path'."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003432 if path.startswith("./"):
3433 path = path[2:]
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003434 return path.rstrip("/")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003435
Simon Glass8639f692017-08-04 03:30:30 -06003436def _build_msg(msg, filename, linenr):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003437 if filename is not None:
Simon Glass8639f692017-08-04 03:30:30 -06003438 msg = "{0}:{1}: ".format(_clean_up_path(filename), linenr) + msg
3439 return msg
3440
3441def _stderr_msg(msg, filename, linenr):
3442 sys.stderr.write(_build_msg(msg, filename, linenr) + "\n")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003443
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003444def _tokenization_error(s, filename, linenr):
3445 loc = "" if filename is None else "{0}:{1}: ".format(filename, linenr)
3446 raise Kconfig_Syntax_Error("{0}Couldn't tokenize '{1}'"
3447 .format(loc, s.strip()))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003448
3449def _parse_error(s, msg, filename, linenr):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003450 loc = "" if filename is None else "{0}:{1}: ".format(filename, linenr)
3451 raise Kconfig_Syntax_Error("{0}Couldn't parse '{1}'{2}"
3452 .format(loc, s.strip(),
3453 "." if msg is None else ": " + msg))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003454
3455def _internal_error(msg):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003456 raise Internal_Error(msg +
3457 "\nSorry! You may want to send an email to ulfalizer a.t Google's "
3458 "email service to tell me about this. Include the message above and the "
3459 "stack trace and describe what you were doing.")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003460
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003461#
3462# Internal global constants
3463#
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003464
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003465# Tokens
3466(T_AND, T_OR, T_NOT,
3467 T_OPEN_PAREN, T_CLOSE_PAREN,
3468 T_EQUAL, T_UNEQUAL,
3469 T_MAINMENU, T_MENU, T_ENDMENU,
3470 T_SOURCE, T_CHOICE, T_ENDCHOICE,
3471 T_COMMENT, T_CONFIG, T_MENUCONFIG,
3472 T_HELP, T_IF, T_ENDIF, T_DEPENDS, T_ON,
3473 T_OPTIONAL, T_PROMPT, T_DEFAULT,
3474 T_BOOL, T_TRISTATE, T_HEX, T_INT, T_STRING,
3475 T_DEF_BOOL, T_DEF_TRISTATE,
Tom Rinid0361072017-03-03 15:33:29 -05003476 T_SELECT, T_IMPLY, T_RANGE, T_OPTION, T_ALLNOCONFIG_Y, T_ENV,
3477 T_DEFCONFIG_LIST, T_MODULES, T_VISIBLE) = range(40)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003478
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003479# The leading underscore before the function assignments below prevent pydoc
3480# from listing them. The constants could be hidden too, but they're fairly
3481# obviously internal anyway, so don't bother spamming the code.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003482
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003483# Keyword to token map. Note that the get() method is assigned directly as a
3484# small optimization.
3485_get_keyword = \
3486 {"mainmenu": T_MAINMENU, "menu": T_MENU, "endmenu": T_ENDMENU,
3487 "endif": T_ENDIF, "endchoice": T_ENDCHOICE, "source": T_SOURCE,
3488 "choice": T_CHOICE, "config": T_CONFIG, "comment": T_COMMENT,
3489 "menuconfig": T_MENUCONFIG, "help": T_HELP, "if": T_IF,
3490 "depends": T_DEPENDS, "on": T_ON, "optional": T_OPTIONAL,
3491 "prompt": T_PROMPT, "default": T_DEFAULT, "bool": T_BOOL, "boolean": T_BOOL,
3492 "tristate": T_TRISTATE, "int": T_INT, "hex": T_HEX, "def_bool": T_DEF_BOOL,
3493 "def_tristate": T_DEF_TRISTATE, "string": T_STRING, "select": T_SELECT,
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02003494 "imply" : T_IMPLY, "range": T_RANGE, "option": T_OPTION,
Tom Rinid0361072017-03-03 15:33:29 -05003495 "allnoconfig_y": T_ALLNOCONFIG_Y, "env": T_ENV,
3496 "defconfig_list": T_DEFCONFIG_LIST, "modules": T_MODULES,
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003497 "visible": T_VISIBLE}.get
3498
3499# Strings to use for True and False
3500BOOL_STR = {False: "false", True: "true"}
3501
3502# Tokens after which identifier-like lexemes are treated as strings. T_CHOICE
3503# is included to avoid symbols being registered for named choices.
3504STRING_LEX = frozenset((T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING, T_CHOICE,
3505 T_PROMPT, T_MENU, T_COMMENT, T_SOURCE, T_MAINMENU))
3506
3507# Matches the initial token on a line; see _tokenize(). Also eats trailing
3508# whitespace as an optimization.
3509_initial_token_re_match = re.compile(r"[^\w]*(\w+)\s*").match
3510
3511# Matches an identifier/keyword optionally preceded by whitespace. Also eats
3512# trailing whitespace as an optimization.
3513_id_keyword_re_match = re.compile(r"\s*([\w./-]+)\s*").match
3514
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003515# Regular expression for finding $-references to symbols in strings
3516_sym_ref_re_search = re.compile(r"\$[A-Za-z0-9_]+").search
3517
3518# Integers representing symbol types
3519UNKNOWN, BOOL, TRISTATE, STRING, HEX, INT = range(6)
3520
3521# Strings to use for types
3522TYPENAME = {UNKNOWN: "unknown", BOOL: "bool", TRISTATE: "tristate",
3523 STRING: "string", HEX: "hex", INT: "int"}
3524
3525# Token to type mapping
3526TOKEN_TO_TYPE = {T_BOOL: BOOL, T_TRISTATE: TRISTATE, T_STRING: STRING,
3527 T_INT: INT, T_HEX: HEX}
3528
3529# Default values for symbols of different types (the value the symbol gets if
3530# it is not assigned a user value and none of its 'default' clauses kick in)
3531DEFAULT_VALUE = {BOOL: "n", TRISTATE: "n", STRING: "", INT: "", HEX: ""}
3532
3533# Indicates that no item is selected in a choice statement
3534NO_SELECTION = 0
3535
3536# Integers representing expression types
3537AND, OR, NOT, EQUAL, UNEQUAL = range(5)
3538
3539# Map from tristate values to integers
3540TRI_TO_INT = {"n": 0, "m": 1, "y": 2}
3541
3542# Printing-related stuff
3543
3544OP_TO_STR = {AND: " && ", OR: " || ", EQUAL: " = ", UNEQUAL: " != "}
3545PRECEDENCE = {OR: 0, AND: 1, NOT: 2}