blob: d68af056b6bd4948e7d239bf1a946a9875a95d3a [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001# SPDX-License-Identifier: ISC
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002#
3# Author: Ulf Magnusson
4# https://github.com/ulfalizer/Kconfiglib
5
6# This is Kconfiglib, a Python library for scripting, debugging, and extracting
7# information from Kconfig-based configuration systems. To view the
8# documentation, run
9#
10# $ pydoc kconfiglib
11#
12# or, if you prefer HTML,
13#
14# $ pydoc -w kconfiglib
15#
16# The examples/ subdirectory contains examples, to be run with e.g.
17#
18# $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
19#
20# Look in testsuite.py for the test suite.
21
22"""
23Kconfiglib is a Python library for scripting and extracting information from
24Kconfig-based configuration systems. Features include the following:
25
26 - Symbol values and properties can be looked up and values assigned
27 programmatically.
28 - .config files can be read and written.
29 - Expressions can be evaluated in the context of a Kconfig configuration.
30 - Relations between symbols can be quickly determined, such as finding all
31 symbols that reference a particular symbol.
32 - Highly compatible with the scripts/kconfig/*conf utilities. The test suite
33 automatically compares outputs between Kconfiglib and the C implementation
34 for a large number of cases.
35
36For the Linux kernel, scripts are run using
37
Ulf Magnusson90c36d82015-08-13 19:55:40 +020038 $ make scriptconfig [ARCH=<arch>] SCRIPT=<path to script> [SCRIPT_ARG=<arg>]
Masahiro Yamadaf219e012014-09-01 19:57:37 +090039
Ulf Magnusson90c36d82015-08-13 19:55:40 +020040Using the 'scriptconfig' target ensures that required environment variables
41(SRCARCH, ARCH, srctree, KERNELVERSION, etc.) are set up correctly.
Masahiro Yamadaf219e012014-09-01 19:57:37 +090042
Ulf Magnusson90c36d82015-08-13 19:55:40 +020043Scripts receive the name of the Kconfig file to load in sys.argv[1]. As of
44Linux 4.1.0-rc5, this is always "Kconfig" from the kernel top-level directory.
45If an argument is provided with SCRIPT_ARG, it appears as sys.argv[2].
Masahiro Yamadaf219e012014-09-01 19:57:37 +090046
47To get an interactive Python prompt with Kconfiglib preloaded and a Config
Ulf Magnusson90c36d82015-08-13 19:55:40 +020048object 'c' created, run
Masahiro Yamadaf219e012014-09-01 19:57:37 +090049
Ulf Magnusson90c36d82015-08-13 19:55:40 +020050 $ make iscriptconfig [ARCH=<arch>]
Masahiro Yamadaf219e012014-09-01 19:57:37 +090051
Ulf Magnusson90c36d82015-08-13 19:55:40 +020052Kconfiglib supports both Python 2 and Python 3. For (i)scriptconfig, the Python
53interpreter to use can be passed in PYTHONCMD, which defaults to 'python'. PyPy
54works well too, and might give a nice speedup for long-running jobs.
Masahiro Yamadaf219e012014-09-01 19:57:37 +090055
Ulf Magnusson90c36d82015-08-13 19:55:40 +020056The examples/ directory contains short example scripts, which can be run with
57e.g.
Masahiro Yamadaf219e012014-09-01 19:57:37 +090058
59 $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
60
61or
62
Ulf Magnusson90c36d82015-08-13 19:55:40 +020063 $ make scriptconfig SCRIPT=Kconfiglib/examples/help_grep.py SCRIPT_ARG=kernel
Masahiro Yamadaf219e012014-09-01 19:57:37 +090064
Ulf Magnusson90c36d82015-08-13 19:55:40 +020065testsuite.py contains the test suite. See the top of the script for how to run
66it.
Masahiro Yamadaf219e012014-09-01 19:57:37 +090067
68Credits: Written by Ulf "Ulfalizer" Magnusson
69
Ulf Magnusson90c36d82015-08-13 19:55:40 +020070Send bug reports, suggestions and other feedback to ulfalizer a.t Google's
71email service. Don't wrestle with internal APIs. Tell me what you need and I
72might add it in a safe way as a client API instead."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +090073
74import os
Ulf Magnusson4e1102f2017-09-19 12:52:55 +020075import platform
Masahiro Yamadaf219e012014-09-01 19:57:37 +090076import re
Masahiro Yamadaf219e012014-09-01 19:57:37 +090077import sys
78
Ulf Magnusson90c36d82015-08-13 19:55:40 +020079# File layout:
80#
81# Public classes
82# Public functions
83# Internal classes
84# Internal functions
85# Internal global constants
86
87# Line length: 79 columns
88
89#
90# Public classes
91#
92
93class Config(object):
Masahiro Yamadaf219e012014-09-01 19:57:37 +090094
95 """Represents a Kconfig configuration, e.g. for i386 or ARM. This is the
96 set of symbols and other items appearing in the configuration together with
97 their values. Creating any number of Config objects -- including for
98 different architectures -- is safe; Kconfiglib has no global state."""
99
100 #
101 # Public interface
102 #
103
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200104 def __init__(self, filename="Kconfig", base_dir=None, print_warnings=True,
105 print_undef_assign=False):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900106 """Creates a new Config object, representing a Kconfig configuration.
107 Raises Kconfig_Syntax_Error on syntax errors.
108
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200109 filename (default: "Kconfig"): The base Kconfig file of the
110 configuration. For the Linux kernel, you'll probably want "Kconfig"
111 from the top-level directory, as environment variables will make
112 sure the right Kconfig is included from there
113 (arch/<architecture>/Kconfig). If you are using Kconfiglib via 'make
114 scriptconfig', the filename of the base base Kconfig file will be in
115 sys.argv[1].
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900116
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200117 base_dir (default: None): The base directory relative to which 'source'
118 statements within Kconfig files will work. For the Linux kernel this
119 should be the top-level directory of the kernel tree. $-references
120 to existing environment variables will be expanded.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900121
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200122 If None (the default), the environment variable 'srctree' will be
123 used if set, and the current directory otherwise. 'srctree' is set
124 by the Linux makefiles to the top-level kernel directory. A default
125 of "." would not work with an alternative build directory.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900126
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200127 print_warnings (default: True): Set to True if warnings related to this
128 configuration should be printed to stderr. This can be changed later
129 with Config.set_print_warnings(). It is provided as a constructor
130 argument since warnings might be generated during parsing.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900131
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200132 print_undef_assign (default: False): Set to True if informational
133 messages related to assignments to undefined symbols should be
134 printed to stderr for this configuration. Can be changed later with
135 Config.set_print_undef_assign()."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900136
137 # The set of all symbols, indexed by name (a string)
138 self.syms = {}
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200139 # Python 2/3 compatibility hack. This is the only one needed.
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200140 self.syms_iter = self.syms.values if sys.version_info[0] >= 3 else \
141 self.syms.itervalues
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900142
143 # The set of all defined symbols in the configuration in the order they
144 # appear in the Kconfig files. This excludes the special symbols n, m,
145 # and y as well as symbols that are referenced but never defined.
146 self.kconfig_syms = []
147
148 # The set of all named choices (yes, choices can have names), indexed
149 # by name (a string)
150 self.named_choices = {}
151
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200152 # Lists containing all choices, menus and comments in the configuration
153 self.choices = []
154 self.menus = []
155 self.comments = []
156
157 def register_special_symbol(type_, name, val):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900158 sym = Symbol()
159 sym.is_special_ = True
160 sym.is_defined_ = True
161 sym.config = self
162 sym.name = name
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200163 sym.type = type_
164 sym.cached_val = val
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900165 self.syms[name] = sym
166 return sym
167
168 # The special symbols n, m and y, used as shorthand for "n", "m" and
169 # "y"
170 self.n = register_special_symbol(TRISTATE, "n", "n")
171 self.m = register_special_symbol(TRISTATE, "m", "m")
172 self.y = register_special_symbol(TRISTATE, "y", "y")
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900173 # DEFCONFIG_LIST uses this
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200174 register_special_symbol(STRING, "UNAME_RELEASE", platform.uname()[2])
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900175
176 # The symbol with "option defconfig_list" set, containing a list of
177 # default .config files
178 self.defconfig_sym = None
179
180 # See Symbol.get_(src)arch()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200181 self.arch = os.environ.get("ARCH")
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900182 self.srcarch = os.environ.get("SRCARCH")
183
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200184 # If you set CONFIG_ in the environment, Kconfig will prefix all symbols
185 # with its value when saving the configuration, instead of using the default, "CONFIG_".
186 self.config_prefix = os.environ.get("CONFIG_")
187 if self.config_prefix is None:
188 self.config_prefix = "CONFIG_"
189
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900190 # See Config.__init__(). We need this for get_defconfig_filename().
191 self.srctree = os.environ.get("srctree")
192 if self.srctree is None:
193 self.srctree = "."
194
195 self.filename = filename
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200196 self.base_dir = self.srctree if base_dir is None else \
197 os.path.expandvars(base_dir)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900198
199 # The 'mainmenu' text
200 self.mainmenu_text = None
201
202 # The filename of the most recently loaded .config file
203 self.config_filename = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900204 # The textual header of the most recently loaded .config, uncommented
205 self.config_header = None
206
207 self.print_warnings = print_warnings
208 self.print_undef_assign = print_undef_assign
Simon Glass8639f692017-08-04 03:30:30 -0600209 self._warnings = []
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900210
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900211 # For parsing routines that stop when finding a line belonging to a
212 # different construct, these holds that line and the tokenized version
213 # of that line. The purpose is to avoid having to re-tokenize the line,
214 # which is inefficient and causes problems when recording references to
215 # symbols.
216 self.end_line = None
217 self.end_line_tokens = None
218
219 # See the comment in _parse_expr().
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200220 self._cur_item = None
221 self._line = None
222 self._filename = None
223 self._linenr = None
224 self._transform_m = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900225
226 # Parse the Kconfig files
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200227 self.top_block = []
228 self._parse_file(filename, None, None, None, self.top_block)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900229
230 # Build Symbol.dep for all symbols
231 self._build_dep()
232
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900233 def get_arch(self):
234 """Returns the value the environment variable ARCH had at the time the
235 Config instance was created, or None if ARCH was not set. For the
236 kernel, this corresponds to the architecture being built for, with
237 values such as "i386" or "mips"."""
238 return self.arch
239
240 def get_srcarch(self):
241 """Returns the value the environment variable SRCARCH had at the time
242 the Config instance was created, or None if SRCARCH was not set. For
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200243 the kernel, this corresponds to the particular arch/ subdirectory
244 containing architecture-specific code."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900245 return self.srcarch
246
247 def get_srctree(self):
248 """Returns the value the environment variable srctree had at the time
249 the Config instance was created, or None if srctree was not defined.
250 This variable points to the source directory and is used when building
251 in a separate directory."""
252 return self.srctree
253
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200254 def get_base_dir(self):
255 """Returns the base directory relative to which 'source' statements
256 will work, passed as an argument to Config.__init__()."""
257 return self.base_dir
258
259 def get_kconfig_filename(self):
260 """Returns the name of the (base) kconfig file this configuration was
261 loaded from."""
262 return self.filename
263
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900264 def get_config_filename(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200265 """Returns the filename of the most recently loaded configuration file,
266 or None if no configuration has been loaded."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900267 return self.config_filename
268
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200269 def get_config_header(self):
270 """Returns the (uncommented) textual header of the .config file most
271 recently loaded with load_config(). Returns None if no .config file has
272 been loaded or if the most recently loaded .config file has no header.
273 The header consists of all lines up to but not including the first line
274 that either
275
276 1. Does not start with "#"
277 2. Has the form "# CONFIG_FOO is not set."
278 """
279 return self.config_header
280
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900281 def get_mainmenu_text(self):
282 """Returns the text of the 'mainmenu' statement (with $-references to
283 symbols replaced by symbol values), or None if the configuration has no
284 'mainmenu' statement."""
285 return None if self.mainmenu_text is None else \
286 self._expand_sym_refs(self.mainmenu_text)
287
288 def get_defconfig_filename(self):
289 """Returns the name of the defconfig file, which is the first existing
290 file in the list given in a symbol having 'option defconfig_list' set.
291 $-references to symbols will be expanded ("$FOO bar" -> "foo bar" if
292 FOO has the value "foo"). Returns None in case of no defconfig file.
293 Setting 'option defconfig_list' on multiple symbols currently results
294 in undefined behavior.
295
296 If the environment variable 'srctree' was set when the Config was
297 created, get_defconfig_filename() will first look relative to that
298 directory before looking in the current directory; see
Masahiro Yamada9d01b782015-05-27 11:39:22 +0900299 Config.__init__().
300
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200301 WARNING: A wart here is that scripts/kconfig/Makefile sometimes uses
302 the --defconfig=<defconfig> option when calling the C implementation of
303 e.g. 'make defconfig'. This option overrides the 'option
304 defconfig_list' symbol, meaning the result from
305 get_defconfig_filename() might not match what 'make defconfig' would
306 use. That probably ought to be worked around somehow, so that this
307 function always gives the "expected" result."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900308 if self.defconfig_sym is None:
309 return None
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200310 for filename, cond_expr in self.defconfig_sym.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900311 if self._eval_expr(cond_expr) == "y":
312 filename = self._expand_sym_refs(filename)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900313 # We first look in $srctree. os.path.join() won't work here as
314 # an absolute path in filename would override $srctree.
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200315 srctree_filename = os.path.normpath(self.srctree + "/" +
316 filename)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900317 if os.path.exists(srctree_filename):
318 return srctree_filename
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900319 if os.path.exists(filename):
320 return filename
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900321 return None
322
323 def get_symbol(self, name):
324 """Returns the symbol with name 'name', or None if no such symbol
325 appears in the configuration. An alternative shorthand is conf[name],
326 where conf is a Config instance, though that will instead raise
327 KeyError if the symbol does not exist."""
328 return self.syms.get(name)
329
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200330 def __getitem__(self, name):
331 """Returns the symbol with name 'name'. Raises KeyError if the symbol
332 does not appear in the configuration."""
333 return self.syms[name]
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900334
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200335 def get_symbols(self, all_symbols=True):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900336 """Returns a list of symbols from the configuration. An alternative for
337 iterating over all defined symbols (in the order of definition) is
338
339 for sym in config:
340 ...
341
342 which relies on Config implementing __iter__() and is equivalent to
343
344 for sym in config.get_symbols(False):
345 ...
346
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200347 all_symbols (default: True): If True, all symbols -- including special
348 and undefined symbols -- will be included in the result, in an
349 undefined order. If False, only symbols actually defined and not
350 merely referred to in the configuration will be included in the
351 result, and will appear in the order that they are defined within
352 the Kconfig configuration files."""
353 return list(self.syms.values()) if all_symbols else self.kconfig_syms
354
355 def __iter__(self):
356 """Convenience function for iterating over the set of all defined
357 symbols in the configuration, used like
358
359 for sym in conf:
360 ...
361
362 The iteration happens in the order of definition within the Kconfig
363 configuration files. Symbols only referred to but not defined will not
364 be included, nor will the special symbols n, m, and y. If you want to
365 include such symbols as well, see config.get_symbols()."""
366 return iter(self.kconfig_syms)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900367
368 def get_choices(self):
369 """Returns a list containing all choice statements in the
370 configuration, in the order they appear in the Kconfig files."""
371 return self.choices
372
373 def get_menus(self):
374 """Returns a list containing all menus in the configuration, in the
375 order they appear in the Kconfig files."""
376 return self.menus
377
378 def get_comments(self):
379 """Returns a list containing all comments in the configuration, in the
380 order they appear in the Kconfig files."""
381 return self.comments
382
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200383 def get_top_level_items(self):
384 """Returns a list containing the items (symbols, menus, choices, and
385 comments) at the top level of the configuration -- that is, all items
386 that do not appear within a menu or choice. The items appear in the
387 same order as within the configuration."""
388 return self.top_block
389
390 def load_config(self, filename, replace=True):
391 """Loads symbol values from a file in the familiar .config format.
392 Equivalent to calling Symbol.set_user_value() to set each of the
393 values.
394
395 "# CONFIG_FOO is not set" within a .config file is treated specially
396 and sets the user value of FOO to 'n'. The C implementation works the
397 same way.
398
399 filename: The .config file to load. $-references to existing
400 environment variables will be expanded. For scripts to work even when
401 an alternative build directory is used with the Linux kernel, you
402 need to refer to the top-level kernel directory with "$srctree".
403
404 replace (default: True): True if the configuration should replace the
Simon Glass8639f692017-08-04 03:30:30 -0600405 old configuration; False if it should add to it.
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200406
Simon Glass8639f692017-08-04 03:30:30 -0600407 Returns a list or warnings (hopefully empty)
408 """
409
410 self._warnings = []
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200411 # Regular expressions for parsing .config files
412 _set_re_match = re.compile(r"{}(\w+)=(.*)".format(self.config_prefix)).match
413 _unset_re_match = re.compile(r"# {}(\w+) is not set".format(self.config_prefix)).match
414
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200415 # Put this first so that a missing file doesn't screw up our state
416 filename = os.path.expandvars(filename)
417 line_feeder = _FileFeed(filename)
418
419 self.config_filename = filename
420
421 #
422 # Read header
423 #
424
425 def is_header_line(line):
426 return line is not None and line.startswith("#") and \
427 not _unset_re_match(line)
428
429 self.config_header = None
430
431 line = line_feeder.peek_next()
432 if is_header_line(line):
433 self.config_header = ""
434 while is_header_line(line_feeder.peek_next()):
435 self.config_header += line_feeder.get_next()[1:]
436 # Remove trailing newline
437 if self.config_header.endswith("\n"):
438 self.config_header = self.config_header[:-1]
439
440 #
441 # Read assignments. Hotspot for some workloads.
442 #
443
444 def warn_override(filename, linenr, name, old_user_val, new_user_val):
445 self._warn('overriding the value of {0}. '
446 'Old value: "{1}", new value: "{2}".'
447 .format(name, old_user_val, new_user_val),
448 filename, linenr)
449
450 # Invalidate everything to keep things simple. It might be possible to
451 # improve performance for the case where multiple configurations are
452 # loaded by only invalidating a symbol (and its dependent symbols) if
453 # the new user value differs from the old. One complication would be
454 # that symbols not mentioned in the .config must lose their user value
455 # when replace = True, which is the usual case.
456 if replace:
457 self.unset_user_values()
458 else:
459 self._invalidate_all()
460
461 while 1:
462 line = line_feeder.get_next()
463 if line is None:
Simon Glass8639f692017-08-04 03:30:30 -0600464 return self._warnings
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200465
466 line = line.rstrip()
467
468 set_match = _set_re_match(line)
469 if set_match:
470 name, val = set_match.groups()
471
472 if val.startswith('"'):
473 if len(val) < 2 or val[-1] != '"':
474 _parse_error(line, "malformed string literal",
475 line_feeder.filename, line_feeder.linenr)
476 # Strip quotes and remove escapings. The unescaping
477 # procedure should be safe since " can only appear as \"
478 # inside the string.
479 val = val[1:-1].replace('\\"', '"').replace("\\\\", "\\")
480
481 if name in self.syms:
482 sym = self.syms[name]
483 if sym.user_val is not None:
484 warn_override(line_feeder.filename, line_feeder.linenr,
485 name, sym.user_val, val)
486
487 if sym.is_choice_sym:
488 user_mode = sym.parent.user_mode
489 if user_mode is not None and user_mode != val:
490 self._warn("assignment to {0} changes mode of "
491 'containing choice from "{1}" to "{2}".'
492 .format(name, val, user_mode),
493 line_feeder.filename,
494 line_feeder.linenr)
495
496 sym._set_user_value_no_invalidate(val, True)
497 else:
498 if self.print_undef_assign:
499 _stderr_msg('note: attempt to assign the value "{0}" '
500 "to the undefined symbol {1}."
501 .format(val, name),
502 line_feeder.filename, line_feeder.linenr)
503 else:
504 unset_match = _unset_re_match(line)
505 if unset_match:
506 name = unset_match.group(1)
507 if name in self.syms:
508 sym = self.syms[name]
509 if sym.user_val is not None:
510 warn_override(line_feeder.filename,
511 line_feeder.linenr,
512 name, sym.user_val, "n")
513
514 sym._set_user_value_no_invalidate("n", True)
515
516 def write_config(self, filename, header=None):
517 """Writes out symbol values in the familiar .config format.
518
519 Kconfiglib makes sure the format matches what the C implementation
520 would generate, down to whitespace. This eases testing.
521
522 filename: The filename under which to save the configuration.
523
524 header (default: None): A textual header that will appear at the
525 beginning of the file, with each line commented out automatically.
526 None means no header."""
527
528 for sym in self.syms_iter():
529 sym.already_written = False
530
531 with open(filename, "w") as f:
532 # Write header
533 if header is not None:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200534 f.write(_comment(header) + "\n")
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200535
536 # Build and write configuration
537 conf_strings = []
538 _make_block_conf(self.top_block, conf_strings.append)
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200539 f.write("\n".join(conf_strings) + "\n")
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200540
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900541 def eval(self, s):
542 """Returns the value of the expression 's' -- where 's' is represented
543 as a string -- in the context of the configuration. Raises
544 Kconfig_Syntax_Error if syntax errors are detected in 's'.
545
546 For example, if FOO and BAR are tristate symbols at least one of which
547 has the value "y", then config.eval("y && (FOO || BAR)") => "y"
548
Masahiro Yamada9d01b782015-05-27 11:39:22 +0900549 This function always yields a tristate value. To get the value of
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900550 non-bool, non-tristate symbols, use Symbol.get_value().
551
552 The result of this function is consistent with how evaluation works for
553 conditional expressions in the configuration as well as in the C
554 implementation. "m" and m are rewritten as '"m" && MODULES' and 'm &&
555 MODULES', respectively, and a result of "m" will get promoted to "y" if
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200556 we're running without modules.
557
558 Syntax checking is somewhat lax, partly to be compatible with lax
559 parsing in the C implementation."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900560 return self._eval_expr(self._parse_expr(self._tokenize(s, True), # Feed
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200561 None, # Current symbol/choice
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900562 s)) # line
563
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200564 def unset_user_values(self):
565 """Resets the values of all symbols, as if Config.load_config() or
566 Symbol.set_user_value() had never been called."""
567 for sym in self.syms_iter():
568 sym._unset_user_value_no_recursive_invalidate()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900569
570 def set_print_warnings(self, print_warnings):
571 """Determines whether warnings related to this configuration (for
572 things like attempting to assign illegal values to symbols with
573 Symbol.set_user_value()) should be printed to stderr.
574
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200575 print_warnings: True if warnings should be printed."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900576 self.print_warnings = print_warnings
577
578 def set_print_undef_assign(self, print_undef_assign):
579 """Determines whether informational messages related to assignments to
580 undefined symbols should be printed to stderr for this configuration.
581
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200582 print_undef_assign: If True, such messages will be printed."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900583 self.print_undef_assign = print_undef_assign
584
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900585 def __str__(self):
586 """Returns a string containing various information about the Config."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200587 return _lines("Configuration",
588 "File : " +
589 self.filename,
590 "Base directory : " +
591 self.base_dir,
592 "Value of $ARCH at creation time : " +
593 ("(not set)" if self.arch is None else self.arch),
594 "Value of $SRCARCH at creation time : " +
595 ("(not set)" if self.srcarch is None else
596 self.srcarch),
597 "Source tree (derived from $srctree;",
598 "defaults to '.' if $srctree isn't set) : " +
599 self.srctree,
600 "Most recently loaded .config : " +
601 ("(no .config loaded)"
602 if self.config_filename is None else
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900603 self.config_filename),
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200604 "Print warnings : " +
605 BOOL_STR[self.print_warnings],
606 "Print assignments to undefined symbols : " +
607 BOOL_STR[self.print_undef_assign])
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900608
609 #
610 # Private methods
611 #
612
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900613 #
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200614 # Kconfig parsing
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900615 #
616
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200617 def _parse_file(self, filename, parent, deps, visible_if_deps, block):
618 """Parses the Kconfig file 'filename'. Appends the Items in the file
619 (and any file it sources) to the list passed in the 'block' parameter.
620 See _parse_block() for the meaning of the parameters."""
621 self._parse_block(_FileFeed(filename), None, parent, deps,
622 visible_if_deps, block)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900623
624 def _parse_block(self, line_feeder, end_marker, parent, deps,
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200625 visible_if_deps, block):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900626 """Parses a block, which is the contents of either a file or an if,
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200627 menu, or choice statement. Appends the Items to the list passed in the
628 'block' parameter.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900629
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200630 line_feeder: A _FileFeed instance feeding lines from a file. The
631 Kconfig language is line-based in practice.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900632
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200633 end_marker: The token that ends the block, e.g. T_ENDIF ("endif") for
634 ifs. None for files.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900635
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200636 parent: The enclosing menu or choice, or None if we're at the top
637 level.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900638
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200639 deps: Dependencies from enclosing menus, choices and ifs.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900640
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200641 visible_if_deps (default: None): 'visible if' dependencies from
642 enclosing menus.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900643
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200644 block: The list to add items to."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900645
646 while 1:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900647 # Do we already have a tokenized line that we determined wasn't
648 # part of whatever we were parsing earlier? See comment in
649 # Config.__init__().
650 if self.end_line is not None:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900651 line = self.end_line
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200652 tokens = self.end_line_tokens
653 tokens.unget_all()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900654
655 self.end_line = None
656 self.end_line_tokens = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900657 else:
658 line = line_feeder.get_next()
659 if line is None:
660 if end_marker is not None:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200661 raise Kconfig_Syntax_Error("Unexpected end of file {0}"
662 .format(line_feeder.filename))
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200663 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900664
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200665 tokens = self._tokenize(line, False, line_feeder.filename,
666 line_feeder.linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900667
668 t0 = tokens.get_next()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200669 if t0 is None:
670 continue
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900671
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200672 # Cases are ordered roughly by frequency, which speeds things up a
673 # bit
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900674
675 if t0 == T_CONFIG or t0 == T_MENUCONFIG:
676 # The tokenizer will automatically allocate a new Symbol object
677 # for any new names it encounters, so we don't need to worry
678 # about that here.
679 sym = tokens.get_next()
680
681 # Symbols defined in multiple places get the parent of their
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200682 # first definition. However, for symbols whose parents are
683 # choice statements, the choice statement takes precedence.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900684 if not sym.is_defined_ or isinstance(parent, Choice):
685 sym.parent = parent
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900686 sym.is_defined_ = True
687
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200688 self._parse_properties(line_feeder, sym, deps, visible_if_deps)
689
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900690 self.kconfig_syms.append(sym)
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200691 block.append(sym)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900692
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200693 elif t0 == T_SOURCE:
694 kconfig_file = tokens.get_next()
695 exp_kconfig_file = self._expand_sym_refs(kconfig_file)
696 f = os.path.join(self.base_dir, exp_kconfig_file)
697 if not os.path.exists(f):
698 raise IOError('{0}:{1}: sourced file "{2}" (expands to '
699 '"{3}") not found. Perhaps base_dir '
700 '(argument to Config.__init__(), currently '
701 '"{4}") is set to the wrong value.'
702 .format(line_feeder.filename,
703 line_feeder.linenr,
704 kconfig_file, exp_kconfig_file,
705 self.base_dir))
706 # Add items to the same block
707 self._parse_file(f, parent, deps, visible_if_deps, block)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900708
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200709 elif t0 == end_marker:
710 # We have reached the end of the block
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200711 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900712
713 elif t0 == T_IF:
714 # If statements are treated as syntactic sugar for adding
715 # dependencies to enclosed items and do not have an explicit
716 # object representation.
717
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200718 dep_expr = self._parse_expr(tokens, None, line,
719 line_feeder.filename,
720 line_feeder.linenr)
721 # Add items to the same block
722 self._parse_block(line_feeder, T_ENDIF, parent,
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900723 _make_and(dep_expr, deps),
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200724 visible_if_deps, block)
725
726 elif t0 == T_COMMENT:
727 comment = Comment()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200728 comment.config = self
729 comment.parent = parent
730 comment.filename = line_feeder.filename
731 comment.linenr = line_feeder.linenr
732 comment.text = tokens.get_next()
733
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200734 self._parse_properties(line_feeder, comment, deps,
735 visible_if_deps)
736
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200737 self.comments.append(comment)
738 block.append(comment)
739
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200740 elif t0 == T_MENU:
741 menu = Menu()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200742 menu.config = self
743 menu.parent = parent
744 menu.filename = line_feeder.filename
745 menu.linenr = line_feeder.linenr
746 menu.title = tokens.get_next()
747
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200748 self._parse_properties(line_feeder, menu, deps,
749 visible_if_deps)
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200750
751 # This needs to go before _parse_block() so that we get the
752 # proper menu ordering in the case of nested functions
753 self.menus.append(menu)
754 # Parse contents and put Items in menu.block
755 self._parse_block(line_feeder, T_ENDMENU, menu, menu.dep_expr,
756 _make_and(visible_if_deps,
757 menu.visible_if_expr),
758 menu.block)
759
760 block.append(menu)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900761
762 elif t0 == T_CHOICE:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200763 name = tokens.get_next()
764 if name is None:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900765 choice = Choice()
766 self.choices.append(choice)
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200767 else:
768 # Named choice
769 choice = self.named_choices.get(name)
770 if choice is None:
771 choice = Choice()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900772 choice.name = name
773 self.named_choices[name] = choice
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200774 self.choices.append(choice)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900775
776 choice.config = self
777 choice.parent = parent
778
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200779 choice.def_locations.append((line_feeder.filename,
780 line_feeder.linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900781
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200782 self._parse_properties(line_feeder, choice, deps,
783 visible_if_deps)
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200784
785 # Parse contents and put Items in choice.block
786 self._parse_block(line_feeder, T_ENDCHOICE, choice, deps,
787 visible_if_deps, choice.block)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900788
789 choice._determine_actual_symbols()
790
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200791 # If no type is specified for the choice, its type is that of
792 # the first choice item with a specified type
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900793 if choice.type == UNKNOWN:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200794 for item in choice.actual_symbols:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900795 if item.type != UNKNOWN:
796 choice.type = item.type
797 break
798
799 # Each choice item of UNKNOWN type gets the type of the choice
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200800 for item in choice.actual_symbols:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900801 if item.type == UNKNOWN:
802 item.type = choice.type
803
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200804 block.append(choice)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900805
806 elif t0 == T_MAINMENU:
807 text = tokens.get_next()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900808 if self.mainmenu_text is not None:
809 self._warn("overriding 'mainmenu' text. "
810 'Old value: "{0}", new value: "{1}".'
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200811 .format(self.mainmenu_text, text),
812 line_feeder.filename, line_feeder.linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900813 self.mainmenu_text = text
814
815 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200816 _parse_error(line, "unrecognized construct",
817 line_feeder.filename, line_feeder.linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900818
819 def _parse_properties(self, line_feeder, stmt, deps, visible_if_deps):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200820 """Parsing of properties for symbols, menus, choices, and comments.
821 Takes care of propagating dependencies from enclosing menus and ifs."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900822
823 def parse_val_and_cond(tokens, line, filename, linenr):
824 """Parses '<expr1> if <expr2>' constructs, where the 'if' part is
825 optional. Returns a tuple containing the parsed expressions, with
826 None as the second element if the 'if' part is missing."""
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200827 return (self._parse_expr(tokens, stmt, line, filename, linenr,
828 False),
829 self._parse_expr(tokens, stmt, line, filename, linenr)
830 if tokens.check(T_IF) else None)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900831
832 # In case the symbol is defined in multiple locations, we need to
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200833 # remember what prompts, defaults, selects, and implies are new for
834 # this definition, as "depends on" should only apply to the local
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900835 # definition.
836 new_prompt = None
837 new_def_exprs = []
838 new_selects = []
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200839 new_implies = []
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900840
841 # Dependencies from 'depends on' statements
842 depends_on_expr = None
843
844 while 1:
845 line = line_feeder.get_next()
846 if line is None:
847 break
848
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200849 filename = line_feeder.filename
850 linenr = line_feeder.linenr
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900851
852 tokens = self._tokenize(line, False, filename, linenr)
853
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200854 t0 = tokens.get_next()
855 if t0 is None:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900856 continue
857
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200858 # Cases are ordered roughly by frequency, which speeds things up a
859 # bit
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900860
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200861 if t0 == T_DEPENDS:
862 if not tokens.check(T_ON):
863 _parse_error(line, 'expected "on" after "depends"',
864 filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900865
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200866 parsed_deps = self._parse_expr(tokens, stmt, line, filename,
867 linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900868
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200869 if isinstance(stmt, (Menu, Comment)):
870 stmt.orig_deps = _make_and(stmt.orig_deps, parsed_deps)
871 else:
872 depends_on_expr = _make_and(depends_on_expr, parsed_deps)
873
874 elif t0 == T_HELP:
875 # Find first non-blank (not all-space) line and get its
876 # indentation
877 line = line_feeder.next_nonblank()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900878 if line is None:
879 stmt.help = ""
880 break
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900881 indent = _indentation(line)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900882 if indent == 0:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200883 # If the first non-empty lines has zero indent, there is no
884 # help text
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900885 stmt.help = ""
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200886 line_feeder.unget()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900887 break
888
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900889 # The help text goes on till the first non-empty line with less
890 # indent
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200891 help_lines = [_deindent(line, indent)]
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900892 while 1:
893 line = line_feeder.get_next()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200894 if line is None or \
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900895 (not line.isspace() and _indentation(line) < indent):
896 stmt.help = "".join(help_lines)
897 break
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900898 help_lines.append(_deindent(line, indent))
899
900 if line is None:
901 break
902
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200903 line_feeder.unget()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900904
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200905 elif t0 == T_SELECT:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900906 target = tokens.get_next()
907
908 stmt.referenced_syms.add(target)
909 stmt.selected_syms.add(target)
910
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200911 new_selects.append(
912 (target,
913 self._parse_expr(tokens, stmt, line, filename, linenr)
914 if tokens.check(T_IF) else None))
915
916 elif t0 == T_IMPLY:
917 target = tokens.get_next()
918
919 stmt.referenced_syms.add(target)
920 stmt.implied_syms.add(target)
921
922 new_implies.append(
923 (target,
924 self._parse_expr(tokens, stmt, line, filename, linenr)
925 if tokens.check(T_IF) else None))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900926
927 elif t0 in (T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200928 stmt.type = TOKEN_TO_TYPE[t0]
929 if tokens.peek_next() is not None:
930 new_prompt = parse_val_and_cond(tokens, line, filename,
931 linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900932
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200933 elif t0 == T_DEFAULT:
934 new_def_exprs.append(parse_val_and_cond(tokens, line, filename,
935 linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900936
937 elif t0 == T_DEF_BOOL:
938 stmt.type = BOOL
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200939 if tokens.peek_next() is not None:
940 new_def_exprs.append(parse_val_and_cond(tokens, line,
941 filename, linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900942
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200943 elif t0 == T_PROMPT:
944 # 'prompt' properties override each other within a single
945 # definition of a symbol, but additional prompts can be added
946 # by defining the symbol multiple times; hence 'new_prompt'
947 # instead of 'prompt'.
948 new_prompt = parse_val_and_cond(tokens, line, filename, linenr)
949
950 elif t0 == T_RANGE:
951 low = tokens.get_next()
952 high = tokens.get_next()
953 stmt.referenced_syms.add(low)
954 stmt.referenced_syms.add(high)
955
Ulf Magnusson4e1102f2017-09-19 12:52:55 +0200956 stmt.ranges.append(
957 (low, high,
958 self._parse_expr(tokens, stmt, line, filename, linenr)
959 if tokens.check(T_IF) else None))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900960
961 elif t0 == T_DEF_TRISTATE:
962 stmt.type = TRISTATE
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200963 if tokens.peek_next() is not None:
964 new_def_exprs.append(parse_val_and_cond(tokens, line,
965 filename, linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900966
967 elif t0 == T_OPTION:
968 if tokens.check(T_ENV) and tokens.check(T_EQUAL):
969 env_var = tokens.get_next()
970
971 stmt.is_special_ = True
972 stmt.is_from_env = True
973
974 if env_var not in os.environ:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200975 self._warn("The symbol {0} references the "
976 "non-existent environment variable {1} and "
977 "will get the empty string as its value. "
978 "If you're using Kconfiglib via "
979 "'make (i)scriptconfig', it should have "
980 "set up the environment correctly for you. "
981 "If you still got this message, that "
982 "might be an error, and you should email "
983 "ulfalizer a.t Google's email service."""
984 .format(stmt.name, env_var),
985 filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900986
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200987 stmt.cached_val = ""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900988 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200989 stmt.cached_val = os.environ[env_var]
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900990
991 elif tokens.check(T_DEFCONFIG_LIST):
992 self.defconfig_sym = stmt
993
994 elif tokens.check(T_MODULES):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200995 # To reduce warning spam, only warn if 'option modules' is
996 # set on some symbol that isn't MODULES, which should be
997 # safe. I haven't run into any projects that make use
998 # modules besides the kernel yet, and there it's likely to
999 # keep being called "MODULES".
1000 if stmt.name != "MODULES":
1001 self._warn("the 'modules' option is not supported. "
1002 "Let me know if this is a problem for you; "
1003 "it shouldn't be that hard to implement. "
1004 "(Note that modules are still supported -- "
1005 "Kconfiglib just assumes the symbol name "
1006 "MODULES, like older versions of the C "
1007 "implementation did when 'option modules' "
1008 "wasn't used.)",
1009 filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001010
Masahiro Yamada9d01b782015-05-27 11:39:22 +09001011 elif tokens.check(T_ALLNOCONFIG_Y):
1012 if not isinstance(stmt, Symbol):
1013 _parse_error(line,
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001014 "the 'allnoconfig_y' option is only "
1015 "valid for symbols",
1016 filename, linenr)
Masahiro Yamada9d01b782015-05-27 11:39:22 +09001017 stmt.allnoconfig_y = True
1018
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001019 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001020 _parse_error(line, "unrecognized option", filename, linenr)
1021
1022 elif t0 == T_VISIBLE:
1023 if not tokens.check(T_IF):
1024 _parse_error(line, 'expected "if" after "visible"',
1025 filename, linenr)
1026 if not isinstance(stmt, Menu):
1027 _parse_error(line,
1028 "'visible if' is only valid for menus",
1029 filename, linenr)
1030
1031 parsed_deps = self._parse_expr(tokens, stmt, line, filename,
1032 linenr)
1033 stmt.visible_if_expr = _make_and(stmt.visible_if_expr,
1034 parsed_deps)
1035
1036 elif t0 == T_OPTIONAL:
1037 if not isinstance(stmt, Choice):
1038 _parse_error(line,
1039 '"optional" is only valid for choices',
1040 filename,
1041 linenr)
1042 stmt.optional = True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001043
1044 else:
1045 # See comment in Config.__init__()
1046 self.end_line = line
1047 self.end_line_tokens = tokens
1048 break
1049
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001050 # Done parsing properties. Now propagate 'depends on' and enclosing
1051 # menu/if dependencies to expressions.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001052
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001053 # The set of symbols referenced directly by the statement plus all
1054 # symbols referenced by enclosing menus and ifs
1055 stmt.all_referenced_syms = stmt.referenced_syms | _get_expr_syms(deps)
1056
1057 # Save original dependencies from enclosing menus and ifs
1058 stmt.deps_from_containing = deps
1059
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001060 if isinstance(stmt, (Menu, Comment)):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001061 stmt.dep_expr = _make_and(stmt.orig_deps, deps)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001062 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001063 # Symbol or Choice
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001064
1065 # See comment for 'menu_dep'
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001066 stmt.menu_dep = _make_and(deps, depends_on_expr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001067
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001068 # Propagate dependencies to prompts
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001069
1070 if new_prompt is not None:
1071 prompt, cond_expr = new_prompt
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001072 # Propagate 'visible if' dependencies from menus and local
1073 # 'depends on' dependencies
1074 cond_expr = _make_and(_make_and(cond_expr, visible_if_deps),
1075 depends_on_expr)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001076 # Save original
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001077 stmt.orig_prompts.append((prompt, cond_expr))
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001078 # Finalize with dependencies from enclosing menus and ifs
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001079 stmt.prompts.append((prompt, _make_and(cond_expr, deps)))
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001080
1081 # Propagate dependencies to defaults
1082
1083 # Propagate 'depends on' dependencies
1084 new_def_exprs = [(val_expr, _make_and(cond_expr, depends_on_expr))
1085 for val_expr, cond_expr in new_def_exprs]
1086 # Save original
1087 stmt.orig_def_exprs.extend(new_def_exprs)
1088 # Finalize with dependencies from enclosing menus and ifs
1089 stmt.def_exprs.extend([(val_expr, _make_and(cond_expr, deps))
1090 for val_expr, cond_expr in new_def_exprs])
1091
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001092 # Propagate dependencies to selects and implies
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001093
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001094 # Only symbols can select and imply
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001095 if isinstance(stmt, Symbol):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001096 # Propagate 'depends on' dependencies
1097 new_selects = [(target, _make_and(cond_expr, depends_on_expr))
1098 for target, cond_expr in new_selects]
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001099 new_implies = [(target, _make_and(cond_expr, depends_on_expr))
1100 for target, cond_expr in new_implies]
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001101 # Save original
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001102 stmt.orig_selects.extend(new_selects)
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001103 stmt.orig_implies.extend(new_implies)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001104 # Finalize with dependencies from enclosing menus and ifs
1105 for target, cond in new_selects:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001106 target.rev_dep = \
1107 _make_or(target.rev_dep,
1108 _make_and(stmt, _make_and(cond, deps)))
1109 for target, cond in new_implies:
1110 target.weak_rev_dep = \
1111 _make_or(target.weak_rev_dep,
1112 _make_and(stmt, _make_and(cond, deps)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001113
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001114 def _parse_expr(self, feed, cur_item, line, filename=None, linenr=None,
1115 transform_m=True):
1116 """Parses an expression from the tokens in 'feed' using a simple
1117 top-down approach. The result has the form
1118 '(<operator>, [<parsed operands>])', where <operator> is e.g.
1119 kconfiglib.AND. If there is only one operand (i.e., no && or ||), then
1120 the operand is returned directly. This also goes for subexpressions.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001121
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001122 feed: _Feed instance containing the tokens for the expression.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001123
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001124 cur_item: The item (Symbol, Choice, Menu, or Comment) currently being
1125 parsed, or None if we're not parsing an item. Used for recording
1126 references to symbols.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001127
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001128 line: The line containing the expression being parsed.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001129
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001130 filename (default: None): The file containing the expression.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001131
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001132 linenr (default: None): The line number containing the expression.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001133
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001134 transform_m (default: False): Determines if 'm' should be rewritten to
1135 'm && MODULES' -- see parse_val_and_cond().
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001136
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001137 Expression grammar, in decreasing order of precedence:
1138
1139 <expr> -> <symbol>
1140 <symbol> '=' <symbol>
1141 <symbol> '!=' <symbol>
1142 '(' <expr> ')'
1143 '!' <expr>
1144 <expr> '&&' <expr>
1145 <expr> '||' <expr>"""
1146
1147 # Use instance variables to avoid having to pass these as arguments
1148 # through the top-down parser in _parse_expr_rec(), which is tedious
1149 # and obfuscates the code. A profiler run shows no noticeable
1150 # performance difference.
1151 self._cur_item = cur_item
1152 self._transform_m = transform_m
1153 self._line = line
1154 self._filename = filename
1155 self._linenr = linenr
1156
1157 return self._parse_expr_rec(feed)
1158
1159 def _parse_expr_rec(self, feed):
1160 or_term = self._parse_or_term(feed)
1161 if not feed.check(T_OR):
1162 # Common case -- no need for an OR node since it's just a single
1163 # operand
1164 return or_term
1165 or_terms = [or_term, self._parse_or_term(feed)]
1166 while feed.check(T_OR):
1167 or_terms.append(self._parse_or_term(feed))
1168 return (OR, or_terms)
1169
1170 def _parse_or_term(self, feed):
1171 and_term = self._parse_factor(feed)
1172 if not feed.check(T_AND):
1173 # Common case -- no need for an AND node since it's just a single
1174 # operand
1175 return and_term
1176 and_terms = [and_term, self._parse_factor(feed)]
1177 while feed.check(T_AND):
1178 and_terms.append(self._parse_factor(feed))
1179 return (AND, and_terms)
1180
1181 def _parse_factor(self, feed):
1182 token = feed.get_next()
1183
1184 if isinstance(token, (Symbol, str)):
1185 if self._cur_item is not None and isinstance(token, Symbol):
1186 self._cur_item.referenced_syms.add(token)
1187
1188 next_token = feed.peek_next()
1189 # For conditional expressions ('depends on <expr>',
1190 # '... if <expr>', # etc.), "m" and m are rewritten to
1191 # "m" && MODULES.
1192 if next_token != T_EQUAL and next_token != T_UNEQUAL:
1193 if self._transform_m and (token is self.m or token == "m"):
1194 return (AND, ["m", self._sym_lookup("MODULES")])
1195 return token
1196
1197 relation = EQUAL if (feed.get_next() == T_EQUAL) else UNEQUAL
1198 token_2 = feed.get_next()
1199 if self._cur_item is not None and isinstance(token_2, Symbol):
1200 self._cur_item.referenced_syms.add(token_2)
1201 return (relation, token, token_2)
1202
1203 if token == T_NOT:
1204 return (NOT, self._parse_factor(feed))
1205
1206 if token == T_OPEN_PAREN:
1207 expr_parse = self._parse_expr_rec(feed)
1208 if not feed.check(T_CLOSE_PAREN):
1209 _parse_error(self._line, "missing end parenthesis",
1210 self._filename, self._linenr)
1211 return expr_parse
1212
1213 _parse_error(self._line, "malformed expression", self._filename,
1214 self._linenr)
1215
1216 def _tokenize(self, s, for_eval, filename=None, linenr=None):
1217 """Returns a _Feed instance containing tokens derived from the string
1218 's'. Registers any new symbols encountered (via _sym_lookup()).
1219
1220 (I experimented with a pure regular expression implementation, but it
1221 came out slower, less readable, and wouldn't have been as flexible.)
1222
1223 for_eval: True when parsing an expression for a call to Config.eval(),
1224 in which case we should not treat the first token specially nor
1225 register new symbols."""
1226
1227 s = s.strip()
1228 if s == "" or s[0] == "#":
1229 return _Feed([])
1230
1231 if for_eval:
1232 previous = None # The previous token seen
1233 tokens = []
1234 i = 0 # The current index in the string being tokenized
1235
1236 else:
1237 # The initial word on a line is parsed specially. Let
1238 # command_chars = [A-Za-z0-9_]. Then
1239 # - leading non-command_chars characters are ignored, and
1240 # - the first token consists the following one or more
1241 # command_chars characters.
1242 # This is why things like "----help--" are accepted.
1243 initial_token_match = _initial_token_re_match(s)
1244 if initial_token_match is None:
1245 return _Feed([])
1246 keyword = _get_keyword(initial_token_match.group(1))
1247 if keyword == T_HELP:
1248 # Avoid junk after "help", e.g. "---", being registered as a
1249 # symbol
1250 return _Feed([T_HELP])
1251 if keyword is None:
1252 # We expect a keyword as the first token
1253 _tokenization_error(s, filename, linenr)
1254
1255 previous = keyword
1256 tokens = [keyword]
1257 # The current index in the string being tokenized
1258 i = initial_token_match.end()
1259
1260 # _tokenize() is a hotspot during parsing, and this speeds things up a
1261 # bit
1262 strlen = len(s)
1263 append = tokens.append
1264
1265 # Main tokenization loop. (Handles tokens past the first one.)
1266 while i < strlen:
1267 # Test for an identifier/keyword preceded by whitespace first; this
1268 # is the most common case.
1269 id_keyword_match = _id_keyword_re_match(s, i)
1270 if id_keyword_match:
1271 # We have an identifier or keyword. The above also stripped any
1272 # whitespace for us.
1273 name = id_keyword_match.group(1)
1274 # Jump past it
1275 i = id_keyword_match.end()
1276
1277 keyword = _get_keyword(name)
1278 if keyword is not None:
1279 # It's a keyword
1280 append(keyword)
1281 elif previous in STRING_LEX:
1282 # What would ordinarily be considered an identifier is
1283 # treated as a string after certain tokens
1284 append(name)
1285 else:
1286 # It's a symbol name. _sym_lookup() will take care of
1287 # allocating a new Symbol instance if it's the first time
1288 # we see it.
1289 sym = self._sym_lookup(name, for_eval)
1290
1291 if previous == T_CONFIG or previous == T_MENUCONFIG:
1292 # If the previous token is T_(MENU)CONFIG
1293 # ("(menu)config"), we're tokenizing the first line of
1294 # a symbol definition, and should remember this as a
1295 # location where the symbol is defined
1296 sym.def_locations.append((filename, linenr))
1297 else:
1298 # Otherwise, it's a reference to the symbol
1299 sym.ref_locations.append((filename, linenr))
1300
1301 append(sym)
1302
1303 else:
1304 # Not an identifier/keyword
1305
1306 while i < strlen and s[i].isspace():
1307 i += 1
1308 if i == strlen:
1309 break
1310 c = s[i]
1311 i += 1
1312
1313 # String literal (constant symbol)
1314 if c == '"' or c == "'":
1315 if "\\" in s:
1316 # Slow path: This could probably be sped up, but it's a
1317 # very unusual case anyway.
1318 quote = c
1319 val = ""
1320 while 1:
1321 if i >= len(s):
1322 _tokenization_error(s, filename, linenr)
1323 c = s[i]
1324 if c == quote:
1325 break
1326 if c == "\\":
1327 if i + 1 >= len(s):
1328 _tokenization_error(s, filename, linenr)
1329 val += s[i + 1]
1330 i += 2
1331 else:
1332 val += c
1333 i += 1
1334 i += 1
1335 append(val)
1336 else:
1337 # Fast path: If the string contains no backslashes
1338 # (almost always) we can simply look for the matching
1339 # quote.
1340 end = s.find(c, i)
1341 if end == -1:
1342 _tokenization_error(s, filename, linenr)
1343 append(s[i:end])
1344 i = end + 1
1345
1346 elif c == "&":
1347 # Invalid characters are ignored
1348 if i >= len(s) or s[i] != "&": continue
1349 append(T_AND)
1350 i += 1
1351
1352 elif c == "|":
1353 # Invalid characters are ignored
1354 if i >= len(s) or s[i] != "|": continue
1355 append(T_OR)
1356 i += 1
1357
1358 elif c == "!":
1359 if i < len(s) and s[i] == "=":
1360 append(T_UNEQUAL)
1361 i += 1
1362 else:
1363 append(T_NOT)
1364
1365 elif c == "=": append(T_EQUAL)
1366 elif c == "(": append(T_OPEN_PAREN)
1367 elif c == ")": append(T_CLOSE_PAREN)
1368 elif c == "#": break # Comment
1369
1370 else: continue # Invalid characters are ignored
1371
1372 previous = tokens[-1]
1373
1374 return _Feed(tokens)
1375
1376 def _sym_lookup(self, name, for_eval=False):
1377 """Fetches the symbol 'name' from the symbol table, creating and
1378 registering it if it does not exist. If 'for_eval' is True, the symbol
1379 won't be added to the symbol table if it does not exist -- this is for
1380 Config.eval()."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001381 if name in self.syms:
1382 return self.syms[name]
1383
1384 new_sym = Symbol()
1385 new_sym.config = self
1386 new_sym.name = name
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001387 if for_eval:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001388 self._warn("no symbol {0} in configuration".format(name))
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001389 else:
1390 self.syms[name] = new_sym
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001391 return new_sym
1392
1393 #
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001394 # Expression evaluation
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001395 #
1396
1397 def _eval_expr(self, expr):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001398 """Evaluates an expression to "n", "m", or "y"."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001399
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001400 # Handles e.g. an "x if y" condition where the "if y" part is missing.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001401 if expr is None:
1402 return "y"
1403
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001404 res = self._eval_expr_rec(expr)
1405 if res == "m":
1406 # Promote "m" to "y" if we're running without modules.
1407 #
1408 # Internally, "m" is often rewritten to "m" && MODULES by both the
1409 # C implementation and Kconfiglib, which takes care of cases where
1410 # "m" should be demoted to "n" instead.
1411 modules_sym = self.syms.get("MODULES")
1412 if modules_sym is None or modules_sym.get_value() != "y":
1413 return "y"
1414 return res
1415
1416 def _eval_expr_rec(self, expr):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001417 if isinstance(expr, Symbol):
1418 # Non-bool/tristate symbols are always "n" in a tristate sense,
1419 # regardless of their value
1420 if expr.type != BOOL and expr.type != TRISTATE:
1421 return "n"
1422 return expr.get_value()
1423
1424 if isinstance(expr, str):
1425 return expr if (expr == "y" or expr == "m") else "n"
1426
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001427 # Ordered by frequency
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001428
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001429 if expr[0] == AND:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001430 res = "y"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001431 for subexpr in expr[1]:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001432 ev = self._eval_expr_rec(subexpr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001433 # Return immediately upon discovering an "n" term
1434 if ev == "n":
1435 return "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001436 if ev == "m":
1437 res = "m"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001438 # 'res' is either "m" or "y" here; we already handled the
1439 # short-circuiting "n" case in the loop.
1440 return res
1441
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001442 if expr[0] == NOT:
1443 ev = self._eval_expr_rec(expr[1])
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001444 if ev == "y":
1445 return "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001446 return "y" if (ev == "n") else "m"
1447
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001448 if expr[0] == OR:
1449 res = "n"
1450 for subexpr in expr[1]:
1451 ev = self._eval_expr_rec(subexpr)
1452 # Return immediately upon discovering a "y" term
1453 if ev == "y":
1454 return "y"
1455 if ev == "m":
1456 res = "m"
1457 # 'res' is either "n" or "m" here; we already handled the
1458 # short-circuiting "y" case in the loop.
1459 return res
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001460
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001461 if expr[0] == EQUAL:
1462 return "y" if (_str_val(expr[1]) == _str_val(expr[2])) else "n"
1463
1464 if expr[0] == UNEQUAL:
1465 return "y" if (_str_val(expr[1]) != _str_val(expr[2])) else "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001466
1467 _internal_error("Internal error while evaluating expression: "
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001468 "unknown operation {0}.".format(expr[0]))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001469
1470 def _eval_min(self, e1, e2):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001471 """Returns the minimum value of the two expressions. Equates None with
1472 'y'."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001473 e1_eval = self._eval_expr(e1)
1474 e2_eval = self._eval_expr(e2)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001475 return e1_eval if tri_less(e1_eval, e2_eval) else e2_eval
1476
1477 def _eval_max(self, e1, e2):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001478 """Returns the maximum value of the two expressions. Equates None with
1479 'y'."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001480 e1_eval = self._eval_expr(e1)
1481 e2_eval = self._eval_expr(e2)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001482 return e1_eval if tri_greater(e1_eval, e2_eval) else e2_eval
1483
1484 #
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001485 # Dependency tracking (for caching and invalidation)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001486 #
1487
1488 def _build_dep(self):
1489 """Populates the Symbol.dep sets, linking the symbol to the symbols
1490 that immediately depend on it in the sense that changing the value of
1491 the symbol might affect the values of those other symbols. This is used
1492 for caching/invalidation purposes. The calculated sets might be larger
1493 than necessary as we don't do any complicated analysis of the
1494 expressions."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001495
1496 # Adds 'sym' as a directly dependent symbol to all symbols that appear
1497 # in the expression 'e'
1498 def add_expr_deps(e, sym):
1499 for s in _get_expr_syms(e):
1500 s.dep.add(sym)
1501
1502 # The directly dependent symbols of a symbol are:
1503 # - Any symbols whose prompts, default values, rev_dep (select
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001504 # condition), weak_rev_dep (imply condition) or ranges depend on the
1505 # symbol
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001506 # - Any symbols that belong to the same choice statement as the symbol
1507 # (these won't be included in 'dep' as that makes the dependency
1508 # graph unwieldy, but Symbol._get_dependent() will include them)
1509 # - Any symbols in a choice statement that depends on the symbol
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001510 for sym in self.syms_iter():
1511 for _, e in sym.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001512 add_expr_deps(e, sym)
1513
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001514 for v, e in sym.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001515 add_expr_deps(v, sym)
1516 add_expr_deps(e, sym)
1517
1518 add_expr_deps(sym.rev_dep, sym)
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001519 add_expr_deps(sym.weak_rev_dep, sym)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001520
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001521 for l, u, e in sym.ranges:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001522 add_expr_deps(l, sym)
1523 add_expr_deps(u, sym)
1524 add_expr_deps(e, sym)
1525
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001526 if sym.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001527 choice = sym.parent
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001528 for _, e in choice.prompts:
1529 add_expr_deps(e, sym)
1530 for _, e in choice.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001531 add_expr_deps(e, sym)
1532
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001533 def _eq_to_sym(self, eq):
1534 """_expr_depends_on() helper. For (in)equalities of the form sym = y/m
1535 or sym != n, returns sym. For other (in)equalities, returns None."""
1536 relation, left, right = eq
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001537
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001538 def transform_y_m_n(item):
1539 if item is self.y: return "y"
1540 if item is self.m: return "m"
1541 if item is self.n: return "n"
1542 return item
1543
1544 left = transform_y_m_n(left)
1545 right = transform_y_m_n(right)
1546
1547 # Make sure the symbol (if any) appears to the left
1548 if not isinstance(left, Symbol):
1549 left, right = right, left
1550 if not isinstance(left, Symbol):
1551 return None
1552 if (relation == EQUAL and (right == "y" or right == "m")) or \
1553 (relation == UNEQUAL and right == "n"):
1554 return left
1555 return None
1556
1557 def _expr_depends_on(self, expr, sym):
1558 """Reimplementation of expr_depends_symbol() from mconf.c. Used to
1559 determine if a submenu should be implicitly created, which influences
1560 what items inside choice statements are considered choice items."""
1561 if expr is None:
1562 return False
1563
1564 def rec(expr):
1565 if isinstance(expr, str):
1566 return False
1567 if isinstance(expr, Symbol):
1568 return expr is sym
1569
1570 if expr[0] in (EQUAL, UNEQUAL):
1571 return self._eq_to_sym(expr) is sym
1572 if expr[0] == AND:
1573 for and_expr in expr[1]:
1574 if rec(and_expr):
1575 return True
1576 return False
1577
1578 return rec(expr)
1579
1580 def _invalidate_all(self):
1581 for sym in self.syms_iter():
1582 sym._invalidate()
1583
1584 #
1585 # Printing and misc.
1586 #
1587
1588 def _expand_sym_refs(self, s):
1589 """Expands $-references to symbols in 's' to symbol values, or to the
1590 empty string for undefined symbols."""
1591
1592 while 1:
1593 sym_ref_match = _sym_ref_re_search(s)
1594 if sym_ref_match is None:
1595 return s
1596
1597 sym_name = sym_ref_match.group(0)[1:]
1598 sym = self.syms.get(sym_name)
1599 expansion = "" if sym is None else sym.get_value()
1600
1601 s = s[:sym_ref_match.start()] + \
1602 expansion + \
1603 s[sym_ref_match.end():]
1604
1605 def _expr_val_str(self, expr, no_value_str="(none)",
1606 get_val_instead_of_eval=False):
1607 """Printing helper. Returns a string with 'expr' and its value.
1608
1609 no_value_str: String to return when 'expr' is missing (None).
1610
1611 get_val_instead_of_eval: Assume 'expr' is a symbol or string (constant
1612 symbol) and get its value directly instead of evaluating it to a
1613 tristate value."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001614
1615 if expr is None:
1616 return no_value_str
1617
1618 if get_val_instead_of_eval:
1619 if isinstance(expr, str):
1620 return _expr_to_str(expr)
1621 val = expr.get_value()
1622 else:
1623 val = self._eval_expr(expr)
1624
1625 return "{0} (value: {1})".format(_expr_to_str(expr), _expr_to_str(val))
1626
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001627 def _get_sym_or_choice_str(self, sc):
1628 """Symbols and choices have many properties in common, so we factor out
1629 common __str__() stuff here. "sc" is short for "symbol or choice"."""
1630
1631 # As we deal a lot with string representations here, use some
1632 # convenient shorthand:
1633 s = _expr_to_str
1634
1635 #
1636 # Common symbol/choice properties
1637 #
1638
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001639 user_val_str = "(no user value)" if sc.user_val is None else \
1640 s(sc.user_val)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001641
1642 # Build prompts string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001643 if not sc.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001644 prompts_str = " (no prompts)"
1645 else:
1646 prompts_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001647 for prompt, cond_expr in sc.orig_prompts:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001648 prompts_str_rows.append(
1649 ' "{0}"'.format(prompt) if cond_expr is None else
1650 ' "{0}" if {1}'.format(prompt,
1651 self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001652 prompts_str = "\n".join(prompts_str_rows)
1653
1654 # Build locations string
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001655 locations_str = "(no locations)" if not sc.def_locations else \
1656 " ".join(["{0}:{1}".format(filename, linenr) for
1657 filename, linenr in sc.def_locations])
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001658
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001659 # Build additional-dependencies-from-menus-and-ifs string
1660 additional_deps_str = " " + \
1661 self._expr_val_str(sc.deps_from_containing,
1662 "(no additional dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001663
1664 #
1665 # Symbol-specific stuff
1666 #
1667
1668 if isinstance(sc, Symbol):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001669 # Build ranges string
1670 if isinstance(sc, Symbol):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001671 if not sc.ranges:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001672 ranges_str = " (no ranges)"
1673 else:
1674 ranges_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001675 for l, u, cond_expr in sc.ranges:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001676 ranges_str_rows.append(
1677 " [{0}, {1}]".format(s(l), s(u))
1678 if cond_expr is None else
1679 " [{0}, {1}] if {2}"
1680 .format(s(l), s(u), self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001681 ranges_str = "\n".join(ranges_str_rows)
1682
1683 # Build default values string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001684 if not sc.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001685 defaults_str = " (no default values)"
1686 else:
1687 defaults_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001688 for val_expr, cond_expr in sc.orig_def_exprs:
1689 row_str = " " + self._expr_val_str(val_expr, "(none)",
1690 sc.type == STRING)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001691 defaults_str_rows.append(row_str)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001692 defaults_str_rows.append(" Condition: " +
1693 self._expr_val_str(cond_expr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001694 defaults_str = "\n".join(defaults_str_rows)
1695
1696 # Build selects string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001697 if not sc.orig_selects:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001698 selects_str = " (no selects)"
1699 else:
1700 selects_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001701 for target, cond_expr in sc.orig_selects:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001702 selects_str_rows.append(
1703 " {0}".format(target.name) if cond_expr is None else
1704 " {0} if {1}".format(target.name,
1705 self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001706 selects_str = "\n".join(selects_str_rows)
1707
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001708 # Build implies string
1709 if not sc.orig_implies:
1710 implies_str = " (no implies)"
1711 else:
1712 implies_str_rows = []
1713 for target, cond_expr in sc.orig_implies:
1714 implies_str_rows.append(
1715 " {0}".format(target.name) if cond_expr is None else
1716 " {0} if {1}".format(target.name,
1717 self._expr_val_str(cond_expr)))
1718 implies_str = "\n".join(implies_str_rows)
1719
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001720 res = _lines("Symbol " +
1721 ("(no name)" if sc.name is None else sc.name),
1722 "Type : " + TYPENAME[sc.type],
1723 "Value : " + s(sc.get_value()),
1724 "User value : " + user_val_str,
1725 "Visibility : " + s(_get_visibility(sc)),
1726 "Is choice item : " + BOOL_STR[sc.is_choice_sym],
1727 "Is defined : " + BOOL_STR[sc.is_defined_],
1728 "Is from env. : " + BOOL_STR[sc.is_from_env],
1729 "Is special : " + BOOL_STR[sc.is_special_] + "\n")
1730 if sc.ranges:
1731 res += _lines("Ranges:", ranges_str + "\n")
1732 res += _lines("Prompts:",
1733 prompts_str,
1734 "Default values:",
1735 defaults_str,
1736 "Selects:",
1737 selects_str,
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001738 "Implies:",
1739 implies_str,
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001740 "Reverse (select-related) dependencies:",
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001741 " (no reverse dependencies)"
1742 if sc.rev_dep == "n"
1743 else " " + self._expr_val_str(sc.rev_dep),
1744 "Weak reverse (imply-related) dependencies:",
1745 " (no weak reverse dependencies)"
1746 if sc.weak_rev_dep == "n"
1747 else " " + self._expr_val_str(sc.weak_rev_dep),
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001748 "Additional dependencies from enclosing menus "
1749 "and ifs:",
1750 additional_deps_str,
1751 "Locations: " + locations_str)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001752
1753 return res
1754
1755 #
1756 # Choice-specific stuff
1757 #
1758
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001759 # Build selected symbol string
1760 sel = sc.get_selection()
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001761 sel_str = "(no selection)" if sel is None else sel.name
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001762
1763 # Build default values string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001764 if not sc.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001765 defaults_str = " (no default values)"
1766 else:
1767 defaults_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001768 for sym, cond_expr in sc.orig_def_exprs:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001769 defaults_str_rows.append(
1770 " {0}".format(sym.name) if cond_expr is None else
1771 " {0} if {1}".format(sym.name,
1772 self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001773 defaults_str = "\n".join(defaults_str_rows)
1774
1775 # Build contained symbols string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001776 names = [sym.name for sym in sc.actual_symbols]
1777 syms_string = " ".join(names) if names else "(empty)"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001778
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001779 return _lines("Choice",
1780 "Name (for named choices): " +
1781 ("(no name)" if sc.name is None else sc.name),
1782 "Type : " + TYPENAME[sc.type],
1783 "Selected symbol : " + sel_str,
1784 "User value : " + user_val_str,
1785 "Mode : " + s(sc.get_mode()),
1786 "Visibility : " + s(_get_visibility(sc)),
1787 "Optional : " + BOOL_STR[sc.optional],
1788 "Prompts:",
1789 prompts_str,
1790 "Defaults:",
1791 defaults_str,
1792 "Choice symbols:",
1793 " " + syms_string,
1794 "Additional dependencies from enclosing menus and "
1795 "ifs:",
1796 additional_deps_str,
1797 "Locations: " + locations_str)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001798
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001799 def _warn(self, msg, filename=None, linenr=None):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001800 """For printing warnings to stderr."""
Simon Glass8639f692017-08-04 03:30:30 -06001801 msg = _build_msg("warning: " + msg, filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001802 if self.print_warnings:
Simon Glass8639f692017-08-04 03:30:30 -06001803 sys.stderr.write(msg + "\n")
1804 self._warnings.append(msg)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001805
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001806class Item(object):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001807
1808 """Base class for symbols and other Kconfig constructs. Subclasses are
1809 Symbol, Choice, Menu, and Comment."""
1810
1811 def is_symbol(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001812 """Returns True if the item is a symbol. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001813 isinstance(item, kconfiglib.Symbol)."""
1814 return isinstance(self, Symbol)
1815
1816 def is_choice(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001817 """Returns True if the item is a choice. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001818 isinstance(item, kconfiglib.Choice)."""
1819 return isinstance(self, Choice)
1820
1821 def is_menu(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001822 """Returns True if the item is a menu. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001823 isinstance(item, kconfiglib.Menu)."""
1824 return isinstance(self, Menu)
1825
1826 def is_comment(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001827 """Returns True if the item is a comment. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001828 isinstance(item, kconfiglib.Comment)."""
1829 return isinstance(self, Comment)
1830
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001831class Symbol(Item):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001832
1833 """Represents a configuration symbol - e.g. FOO for
1834
1835 config FOO
1836 ..."""
1837
1838 #
1839 # Public interface
1840 #
1841
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001842 def get_config(self):
1843 """Returns the Config instance this symbol is from."""
1844 return self.config
1845
1846 def get_name(self):
1847 """Returns the name of the symbol."""
1848 return self.name
1849
1850 def get_type(self):
1851 """Returns the type of the symbol: one of UNKNOWN, BOOL, TRISTATE,
1852 STRING, HEX, or INT. These are defined at the top level of the module,
1853 so you'd do something like
1854
1855 if sym.get_type() == kconfiglib.STRING:
1856 ..."""
1857 return self.type
1858
1859 def get_prompts(self):
1860 """Returns a list of prompts defined for the symbol, in the order they
1861 appear in the configuration files. Returns the empty list for symbols
1862 with no prompt.
1863
1864 This list will have a single entry for the vast majority of symbols
1865 having prompts, but having multiple prompts for a single symbol is
1866 possible through having multiple 'config' entries for it."""
1867 return [prompt for prompt, _ in self.orig_prompts]
1868
1869 def get_help(self):
1870 """Returns the help text of the symbol, or None if the symbol has no
1871 help text."""
1872 return self.help
1873
1874 def get_parent(self):
1875 """Returns the menu or choice statement that contains the symbol, or
1876 None if the symbol is at the top level. Note that if statements are
1877 treated as syntactic and do not have an explicit class
1878 representation."""
1879 return self.parent
1880
1881 def get_def_locations(self):
1882 """Returns a list of (filename, linenr) tuples, where filename (string)
1883 and linenr (int) represent a location where the symbol is defined. For
1884 the vast majority of symbols this list will only contain one element.
1885 For the following Kconfig, FOO would get two entries: the lines marked
1886 with *.
1887
1888 config FOO *
1889 bool "foo prompt 1"
1890
1891 config FOO *
1892 bool "foo prompt 2"
1893 """
1894 return self.def_locations
1895
1896 def get_ref_locations(self):
1897 """Returns a list of (filename, linenr) tuples, where filename (string)
1898 and linenr (int) represent a location where the symbol is referenced in
1899 the configuration. For example, the lines marked by * would be included
1900 for FOO below:
1901
1902 config A
1903 bool
1904 default BAR || FOO *
1905
1906 config B
1907 tristate
1908 depends on FOO *
1909 default m if FOO *
1910
1911 if FOO *
1912 config A
1913 bool "A"
1914 endif
1915
1916 config FOO (definition not included)
1917 bool
1918 """
1919 return self.ref_locations
1920
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001921 def get_value(self):
1922 """Calculate and return the value of the symbol. See also
1923 Symbol.set_user_value()."""
1924
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001925 if self.cached_val is not None:
1926 return self.cached_val
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001927
1928 # As a quirk of Kconfig, undefined symbols get their name as their
1929 # value. This is why things like "FOO = bar" work for seeing if FOO has
1930 # the value "bar".
1931 if self.type == UNKNOWN:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001932 self.cached_val = self.name
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001933 return self.name
1934
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001935 new_val = DEFAULT_VALUE[self.type]
1936 vis = _get_visibility(self)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001937
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001938 # This is easiest to calculate together with the value
1939 self.write_to_conf = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001940
1941 if self.type == BOOL or self.type == TRISTATE:
1942 # The visibility and mode (modules-only or single-selection) of
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001943 # choice items will be taken into account in _get_visibility()
1944 if self.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001945 if vis != "n":
1946 choice = self.parent
1947 mode = choice.get_mode()
1948
1949 self.write_to_conf = (mode != "n")
1950
1951 if mode == "y":
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001952 new_val = "y" if choice.get_selection() is self \
1953 else "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001954 elif mode == "m":
1955 if self.user_val == "m" or self.user_val == "y":
1956 new_val = "m"
1957
1958 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001959 # If the symbol is visible and has a user value, use that.
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001960 # Otherwise, look at defaults and weak reverse dependencies
1961 # (implies).
1962 use_defaults_and_weak_rev_deps = True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001963
1964 if vis != "n":
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001965 self.write_to_conf = True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001966 if self.user_val is not None:
1967 new_val = self.config._eval_min(self.user_val, vis)
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001968 use_defaults_and_weak_rev_deps = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001969
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001970 if use_defaults_and_weak_rev_deps:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001971 for val_expr, cond_expr in self.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001972 cond_eval = self.config._eval_expr(cond_expr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001973 if cond_eval != "n":
1974 self.write_to_conf = True
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001975 new_val = self.config._eval_min(val_expr,
1976 cond_eval)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001977 break
1978
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001979 weak_rev_dep_val = \
1980 self.config._eval_expr(self.weak_rev_dep)
1981 if weak_rev_dep_val != "n":
1982 self.write_to_conf = True
1983 new_val = self.config._eval_max(new_val,
1984 weak_rev_dep_val)
1985
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001986 # Reverse (select-related) dependencies take precedence
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001987 rev_dep_val = self.config._eval_expr(self.rev_dep)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001988 if rev_dep_val != "n":
1989 self.write_to_conf = True
1990 new_val = self.config._eval_max(new_val, rev_dep_val)
1991
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02001992 # We need to promote "m" to "y" in two circumstances:
1993 # 1) If our type is boolean
1994 # 2) If our weak_rev_dep (from IMPLY) is "y"
1995 if new_val == "m" and \
1996 (self.type == BOOL or
1997 self.config._eval_expr(self.weak_rev_dep) == "y"):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001998 new_val = "y"
1999
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002000 elif self.type == INT or self.type == HEX:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002001 has_active_range = False
2002 low = None
2003 high = None
2004 use_defaults = True
2005
2006 base = 16 if self.type == HEX else 10
2007
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002008 for l, h, cond_expr in self.ranges:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002009 if self.config._eval_expr(cond_expr) != "n":
2010 has_active_range = True
2011
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002012 low_str = _str_val(l)
2013 high_str = _str_val(h)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002014 low = int(low_str, base) if \
2015 _is_base_n(low_str, base) else 0
2016 high = int(high_str, base) if \
2017 _is_base_n(high_str, base) else 0
2018
2019 break
2020
2021 if vis != "n":
2022 self.write_to_conf = True
2023
2024 if self.user_val is not None and \
2025 _is_base_n(self.user_val, base) and \
2026 (not has_active_range or
2027 low <= int(self.user_val, base) <= high):
2028
2029 # If the user value is OK, it is stored in exactly the same
2030 # form as specified in the assignment (with or without
2031 # "0x", etc).
2032
2033 use_defaults = False
2034 new_val = self.user_val
2035
2036 if use_defaults:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002037 for val_expr, cond_expr in self.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002038 if self.config._eval_expr(cond_expr) != "n":
2039 self.write_to_conf = True
2040
2041 # If the default value is OK, it is stored in exactly
2042 # the same form as specified. Otherwise, it is clamped
2043 # to the range, and the output has "0x" as appropriate
2044 # for the type.
2045
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002046 new_val = _str_val(val_expr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002047
2048 if _is_base_n(new_val, base):
2049 new_val_num = int(new_val, base)
2050 if has_active_range:
2051 clamped_val = None
2052
2053 if new_val_num < low:
2054 clamped_val = low
2055 elif new_val_num > high:
2056 clamped_val = high
2057
2058 if clamped_val is not None:
2059 new_val = (hex(clamped_val) if \
2060 self.type == HEX else str(clamped_val))
2061
2062 break
2063 else: # For the for loop
2064 # If no user value or default kicks in but the hex/int has
2065 # an active range, then the low end of the range is used,
2066 # provided it's > 0, with "0x" prepended as appropriate.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002067 if has_active_range and low > 0:
2068 new_val = (hex(low) if self.type == HEX else str(low))
2069
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002070 elif self.type == STRING:
2071 use_defaults = True
2072
2073 if vis != "n":
2074 self.write_to_conf = True
2075 if self.user_val is not None:
2076 new_val = self.user_val
2077 use_defaults = False
2078
2079 if use_defaults:
2080 for val_expr, cond_expr in self.def_exprs:
2081 if self.config._eval_expr(cond_expr) != "n":
2082 self.write_to_conf = True
2083 new_val = _str_val(val_expr)
2084 break
2085
2086 self.cached_val = new_val
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002087 return new_val
2088
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002089 def get_user_value(self):
2090 """Returns the value assigned to the symbol in a .config or via
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002091 Symbol.set_user_value() (provided the value was valid for the type of
2092 the symbol). Returns None in case of no user value."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002093 return self.user_val
2094
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002095 def get_upper_bound(self):
2096 """For string/hex/int symbols and for bool and tristate symbols that
2097 cannot be modified (see is_modifiable()), returns None.
2098
2099 Otherwise, returns the highest value the symbol can be set to with
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002100 Symbol.set_user_value() (that will not be truncated): one of "m" or
2101 "y", arranged from lowest to highest. This corresponds to the highest
2102 value the symbol could be given in e.g. the 'make menuconfig'
2103 interface.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002104
2105 See also the tri_less*() and tri_greater*() functions, which could come
2106 in handy."""
2107 if self.type != BOOL and self.type != TRISTATE:
2108 return None
2109 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002110 # A bool selected to "m" gets promoted to "y", pinning it
2111 if rev_dep == "m" and self.type == BOOL:
2112 return None
2113 vis = _get_visibility(self)
2114 if TRI_TO_INT[vis] > TRI_TO_INT[rev_dep]:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002115 return vis
2116 return None
2117
2118 def get_lower_bound(self):
2119 """For string/hex/int symbols and for bool and tristate symbols that
2120 cannot be modified (see is_modifiable()), returns None.
2121
2122 Otherwise, returns the lowest value the symbol can be set to with
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002123 Symbol.set_user_value() (that will not be truncated): one of "n" or
2124 "m", arranged from lowest to highest. This corresponds to the lowest
2125 value the symbol could be given in e.g. the 'make menuconfig'
2126 interface.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002127
2128 See also the tri_less*() and tri_greater*() functions, which could come
2129 in handy."""
2130 if self.type != BOOL and self.type != TRISTATE:
2131 return None
2132 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002133 # A bool selected to "m" gets promoted to "y", pinning it
2134 if rev_dep == "m" and self.type == BOOL:
2135 return None
2136 if TRI_TO_INT[_get_visibility(self)] > TRI_TO_INT[rev_dep]:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002137 return rev_dep
2138 return None
2139
2140 def get_assignable_values(self):
2141 """For string/hex/int symbols and for bool and tristate symbols that
2142 cannot be modified (see is_modifiable()), returns the empty list.
2143
2144 Otherwise, returns a list containing the user values that can be
2145 assigned to the symbol (that won't be truncated). Usage example:
2146
2147 if "m" in sym.get_assignable_values():
2148 sym.set_user_value("m")
2149
2150 This is basically a more convenient interface to
2151 get_lower/upper_bound() when wanting to test if a particular tristate
2152 value can be assigned."""
2153 if self.type != BOOL and self.type != TRISTATE:
2154 return []
2155 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002156 # A bool selected to "m" gets promoted to "y", pinning it
2157 if rev_dep == "m" and self.type == BOOL:
2158 return []
2159 res = ["n", "m", "y"][TRI_TO_INT[rev_dep] :
2160 TRI_TO_INT[_get_visibility(self)] + 1]
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002161 return res if len(res) > 1 else []
2162
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002163 def get_visibility(self):
2164 """Returns the visibility of the symbol: one of "n", "m" or "y". For
2165 bool and tristate symbols, this is an upper bound on the value users
2166 can set for the symbol. For other types of symbols, a visibility of "n"
2167 means the user value will be ignored. A visibility of "n" corresponds
2168 to not being visible in the 'make *config' interfaces.
2169
2170 Example (assuming we're running with modules enabled -- i.e., MODULES
2171 set to 'y'):
2172
2173 # Assume this has been assigned 'n'
2174 config N_SYM
2175 tristate "N_SYM"
2176
2177 # Assume this has been assigned 'm'
2178 config M_SYM
2179 tristate "M_SYM"
2180
2181 # Has visibility 'n'
2182 config A
2183 tristate "A"
2184 depends on N_SYM
2185
2186 # Has visibility 'm'
2187 config B
2188 tristate "B"
2189 depends on M_SYM
2190
2191 # Has visibility 'y'
2192 config C
2193 tristate "C"
2194
2195 # Has no prompt, and hence visibility 'n'
2196 config D
2197 tristate
2198
2199 Having visibility be tri-valued ensures that e.g. a symbol cannot be
2200 set to "y" by the user if it depends on a symbol with value "m", which
2201 wouldn't be safe.
2202
2203 You should probably look at get_lower/upper_bound(),
2204 get_assignable_values() and is_modifiable() before using this."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002205 return _get_visibility(self)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002206
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002207 def get_referenced_symbols(self, refs_from_enclosing=False):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002208 """Returns the set() of all symbols referenced by this symbol. For
2209 example, the symbol defined by
2210
2211 config FOO
2212 bool
2213 prompt "foo" if A && B
2214 default C if D
2215 depends on E
2216 select F if G
2217
2218 references the symbols A through G.
2219
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002220 refs_from_enclosing (default: False): If True, the symbols referenced
2221 by enclosing menus and ifs will be included in the result."""
2222 return self.all_referenced_syms if refs_from_enclosing else \
2223 self.referenced_syms
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002224
2225 def get_selected_symbols(self):
2226 """Returns the set() of all symbols X for which this symbol has a
2227 'select X' or 'select X if Y' (regardless of whether Y is satisfied or
2228 not). This is a subset of the symbols returned by
2229 get_referenced_symbols()."""
2230 return self.selected_syms
2231
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002232 def get_implied_symbols(self):
2233 """Returns the set() of all symbols X for which this symbol has an
2234 'imply X' or 'imply X if Y' (regardless of whether Y is satisfied or
2235 not). This is a subset of the symbols returned by
2236 get_referenced_symbols()."""
2237 return self.implied_syms
2238
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002239 def set_user_value(self, v):
2240 """Sets the user value of the symbol.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002241
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002242 Equal in effect to assigning the value to the symbol within a .config
2243 file. Use get_lower/upper_bound() or get_assignable_values() to find
2244 the range of currently assignable values for bool and tristate symbols;
2245 setting values outside this range will cause the user value to differ
2246 from the result of Symbol.get_value() (be truncated). Values that are
2247 invalid for the type (such as a_bool.set_user_value("foo")) are
2248 ignored, and a warning is emitted if an attempt is made to assign such
2249 a value.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002250
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002251 For any type of symbol, is_modifiable() can be used to check if a user
2252 value will currently have any effect on the symbol, as determined by
2253 its visibility and range of assignable values. Any value that is valid
2254 for the type (bool, tristate, etc.) will end up being reflected in
2255 get_user_value() though, and might have an effect later if conditions
2256 change. To get rid of the user value, use unset_user_value().
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002257
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002258 Any symbols dependent on the symbol are (recursively) invalidated, so
2259 things will just work with regards to dependencies.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002260
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002261 v: The user value to give to the symbol."""
2262 self._set_user_value_no_invalidate(v, False)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002263
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002264 # There might be something more efficient you could do here, but play
2265 # it safe.
2266 if self.name == "MODULES":
2267 self.config._invalidate_all()
2268 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002269
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002270 self._invalidate()
2271 self._invalidate_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002272
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002273 def unset_user_value(self):
2274 """Resets the user value of the symbol, as if the symbol had never
2275 gotten a user value via Config.load_config() or
2276 Symbol.set_user_value()."""
2277 self._unset_user_value_no_recursive_invalidate()
2278 self._invalidate_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002279
2280 def is_modifiable(self):
2281 """Returns True if the value of the symbol could be modified by calling
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002282 Symbol.set_user_value().
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002283
2284 For bools and tristates, this corresponds to the symbol being visible
2285 in the 'make menuconfig' interface and not already being pinned to a
2286 specific value (e.g. because it is selected by another symbol).
2287
2288 For strings and numbers, this corresponds to just being visible. (See
2289 Symbol.get_visibility().)"""
2290 if self.is_special_:
2291 return False
2292 if self.type == BOOL or self.type == TRISTATE:
2293 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002294 # A bool selected to "m" gets promoted to "y", pinning it
2295 if rev_dep == "m" and self.type == BOOL:
2296 return False
2297 return TRI_TO_INT[_get_visibility(self)] > TRI_TO_INT[rev_dep]
2298 return _get_visibility(self) != "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002299
2300 def is_defined(self):
2301 """Returns False if the symbol is referred to in the Kconfig but never
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002302 actually defined."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002303 return self.is_defined_
2304
2305 def is_special(self):
2306 """Returns True if the symbol is one of the special symbols n, m, y, or
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002307 UNAME_RELEASE, or gets its value from the environment."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002308 return self.is_special_
2309
2310 def is_from_environment(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002311 """Returns True if the symbol gets its value from the environment."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002312 return self.is_from_env
2313
2314 def has_ranges(self):
2315 """Returns True if the symbol is of type INT or HEX and has ranges that
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002316 limit what values it can take on."""
2317 return bool(self.ranges)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002318
2319 def is_choice_symbol(self):
2320 """Returns True if the symbol is in a choice statement and is an actual
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002321 choice symbol (see Choice.get_symbols())."""
2322 return self.is_choice_sym
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002323
2324 def is_choice_selection(self):
2325 """Returns True if the symbol is contained in a choice statement and is
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002326 the selected item. Equivalent to
2327
2328 sym.is_choice_symbol() and sym.get_parent().get_selection() is sym"""
2329 return self.is_choice_sym and self.parent.get_selection() is self
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002330
Masahiro Yamada9d01b782015-05-27 11:39:22 +09002331 def is_allnoconfig_y(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002332 """Returns True if the symbol has the 'allnoconfig_y' option set."""
Masahiro Yamada9d01b782015-05-27 11:39:22 +09002333 return self.allnoconfig_y
2334
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002335 def __str__(self):
2336 """Returns a string containing various information about the symbol."""
2337 return self.config._get_sym_or_choice_str(self)
2338
2339 #
2340 # Private methods
2341 #
2342
2343 def __init__(self):
2344 """Symbol constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002345 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002346
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002347 self.name = None
2348 self.type = UNKNOWN
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002349 self.prompts = []
2350 self.def_exprs = [] # 'default' properties
2351 self.ranges = [] # 'range' properties (for int and hex)
2352 self.help = None # Help text
2353 self.rev_dep = "n" # Reverse (select-related) dependencies
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002354 self.weak_rev_dep = "n" # Weak reverse (imply-related) dependencies
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002355 self.config = None
2356 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002357
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002358 self.user_val = None # Value set by user
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002359
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002360 # The prompt, default value, select, and imply conditions without any
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002361 # dependencies from menus and ifs propagated to them
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002362 self.orig_prompts = []
2363 self.orig_def_exprs = []
2364 self.orig_selects = []
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002365 self.orig_implies = []
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002366
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002367 # Dependencies inherited from containing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002368 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002369 # The set of symbols referenced by this symbol (see
2370 # get_referenced_symbols())
2371 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002372 # The set of symbols selected by this symbol (see
2373 # get_selected_symbols())
2374 self.selected_syms = set()
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002375 # The set of symbols implied by this symbol (see get_implied_symbols())
2376 self.implied_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002377 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002378 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002379 self.all_referenced_syms = set()
2380
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002381 # This records only dependencies from enclosing ifs and menus together
2382 # with local 'depends on' dependencies. Needed when determining actual
2383 # choice items (hrrrr...). See Choice._determine_actual_symbols().
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002384 self.menu_dep = None
2385
2386 # See Symbol.get_ref/def_locations().
2387 self.def_locations = []
2388 self.ref_locations = []
2389
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002390 # Populated in Config._build_dep() after parsing. Links the symbol to
2391 # the symbols that immediately depend on it (in a caching/invalidation
2392 # sense). The total set of dependent symbols for the symbol (the
2393 # transitive closure) is calculated on an as-needed basis in
2394 # _get_dependent().
2395 self.dep = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002396
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002397 # Cached values
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002398
2399 # Caches the calculated value
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002400 self.cached_val = None
2401 # Caches the visibility, which acts as an upper bound on the value
2402 self.cached_visibility = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002403 # Caches the total list of dependent symbols. Calculated in
2404 # _get_dependent().
2405 self.cached_deps = None
2406
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002407 # Flags
2408
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002409 # Does the symbol have an entry in the Kconfig file? The trailing
2410 # underscore avoids a collision with is_defined().
2411 self.is_defined_ = False
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002412 # Should the symbol get an entry in .config?
2413 self.write_to_conf = False
2414 # Set to true when _make_conf() is called on a symbol, so that symbols
2415 # defined in multiple locations only get one .config entry. We need to
2416 # reset it prior to writing out a new .config.
2417 self.already_written = False
2418 # This is set to True for "actual" choice symbols; see
2419 # Choice._determine_actual_symbols().
2420 self.is_choice_sym = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002421 # Does the symbol get its value in some special way, e.g. from the
2422 # environment or by being one of the special symbols n, m, and y? If
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002423 # so, the value is stored in self.cached_val, which is never
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002424 # invalidated. The trailing underscore avoids a collision with
2425 # is_special().
2426 self.is_special_ = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002427 # Does the symbol get its value from the environment?
2428 self.is_from_env = False
Masahiro Yamada9d01b782015-05-27 11:39:22 +09002429 # Does the symbol have the 'allnoconfig_y' option set?
2430 self.allnoconfig_y = False
2431
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002432 def _invalidate(self):
2433 if self.is_special_:
2434 return
2435
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002436 if self.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002437 self.parent._invalidate()
2438
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002439 self.cached_val = None
2440 self.cached_visibility = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002441
2442 def _invalidate_dependent(self):
2443 for sym in self._get_dependent():
2444 sym._invalidate()
2445
2446 def _set_user_value_no_invalidate(self, v, suppress_load_warnings):
2447 """Like set_user_value(), but does not invalidate any symbols.
2448
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002449 suppress_load_warnings: some warnings are annoying when loading a
2450 .config that can be helpful when manually invoking set_user_value().
2451 This flag is set to True to suppress such warnings.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002452
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002453 Perhaps this could be made optional for load_config() instead."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002454
2455 if self.is_special_:
2456 if self.is_from_env:
2457 self.config._warn('attempt to assign the value "{0}" to the '
2458 'symbol {1}, which gets its value from the '
2459 'environment. Assignment ignored.'
2460 .format(v, self.name))
2461 else:
2462 self.config._warn('attempt to assign the value "{0}" to the '
2463 'special symbol {1}. Assignment ignored.'
2464 .format(v, self.name))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002465 return
2466
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002467 if not self.is_defined_:
2468 filename, linenr = self.ref_locations[0]
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002469 if self.config.print_undef_assign:
2470 _stderr_msg('note: attempt to assign the value "{0}" to {1}, '
2471 "which is referenced at {2}:{3} but never "
2472 "defined. Assignment ignored."
2473 .format(v, self.name, filename, linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002474 return
2475
2476 # Check if the value is valid for our type
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002477 if not ((self.type == BOOL and (v == "y" or v == "n") ) or
2478 (self.type == TRISTATE and (v == "y" or v == "m" or
2479 v == "n") ) or
2480 (self.type == STRING ) or
2481 (self.type == INT and _is_base_n(v, 10) ) or
2482 (self.type == HEX and _is_base_n(v, 16) )):
2483 self.config._warn('the value "{0}" is invalid for {1}, which has '
2484 "type {2}. Assignment ignored."
2485 .format(v, self.name, TYPENAME[self.type]))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002486 return
2487
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002488 if not self.prompts and not suppress_load_warnings:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002489 self.config._warn('assigning "{0}" to the symbol {1} which '
2490 'lacks prompts and thus has visibility "n". '
2491 'The assignment will have no effect.'
2492 .format(v, self.name))
2493
2494 self.user_val = v
2495
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002496 if self.is_choice_sym and (self.type == BOOL or self.type == TRISTATE):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002497 choice = self.parent
2498 if v == "y":
2499 choice.user_val = self
2500 choice.user_mode = "y"
2501 elif v == "m":
2502 choice.user_val = None
2503 choice.user_mode = "m"
2504
2505 def _unset_user_value_no_recursive_invalidate(self):
2506 self._invalidate()
2507 self.user_val = None
2508
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002509 if self.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002510 self.parent._unset_user_value()
2511
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002512 def _make_conf(self, append_fn):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002513 if self.already_written:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002514 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002515
2516 self.already_written = True
2517
2518 # Note: write_to_conf is determined in get_value()
2519 val = self.get_value()
2520 if not self.write_to_conf:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002521 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002522
2523 if self.type == BOOL or self.type == TRISTATE:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002524 append_fn("{0}{1}={2}".format(self.config.config_prefix, self.name, val)
2525 if val == "y" or val == "m" else
2526 "# {0}{1} is not set".format(self.config.config_prefix, self.name))
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002527
2528 elif self.type == INT or self.type == HEX:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002529 append_fn("{0}{1}={2}".format(self.config.config_prefix, self.name, val))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002530
2531 elif self.type == STRING:
2532 # Escape \ and "
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002533 append_fn('{0}{1}="{2}"'
2534 .format(self.config.config_prefix, self.name,
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002535 val.replace("\\", "\\\\").replace('"', '\\"')))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002536
2537 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002538 _internal_error("Internal error while creating .config: unknown "
2539 'type "{0}".'.format(self.type))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002540
2541 def _get_dependent(self):
2542 """Returns the set of symbols that should be invalidated if the value
2543 of the symbol changes, because they might be affected by the change.
2544 Note that this is an internal API -- it's probably of limited
2545 usefulness to clients."""
2546 if self.cached_deps is not None:
2547 return self.cached_deps
2548
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002549 res = set(self.dep)
2550 for s in self.dep:
2551 res |= s._get_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002552
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002553 if self.is_choice_sym:
2554 # Choice symbols also depend (recursively) on their siblings. The
2555 # siblings are not included in 'dep' to avoid dependency loops.
2556 for sibling in self.parent.actual_symbols:
2557 if sibling is not self:
2558 res.add(sibling)
2559 res |= sibling.dep
2560 for s in sibling.dep:
2561 res |= s._get_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002562
2563 self.cached_deps = res
2564 return res
2565
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002566 def _has_auto_menu_dep_on(self, on):
2567 """See Choice._determine_actual_symbols()."""
2568 if not isinstance(self.parent, Choice):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002569 _internal_error("Attempt to determine auto menu dependency for "
2570 "symbol ouside of choice.")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002571
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002572 if not self.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002573 # If we have no prompt, use the menu dependencies instead (what was
2574 # specified with 'depends on')
2575 return self.menu_dep is not None and \
2576 self.config._expr_depends_on(self.menu_dep, on)
2577
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002578 for _, cond_expr in self.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002579 if self.config._expr_depends_on(cond_expr, on):
2580 return True
2581
2582 return False
2583
2584class Menu(Item):
2585
2586 """Represents a menu statement."""
2587
2588 #
2589 # Public interface
2590 #
2591
2592 def get_config(self):
2593 """Return the Config instance this menu is from."""
2594 return self.config
2595
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002596 def get_title(self):
2597 """Returns the title text of the menu."""
2598 return self.title
2599
2600 def get_parent(self):
2601 """Returns the menu or choice statement that contains the menu, or
2602 None if the menu is at the top level. Note that if statements are
2603 treated as syntactic sugar and do not have an explicit class
2604 representation."""
2605 return self.parent
2606
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002607 def get_location(self):
2608 """Returns the location of the menu as a (filename, linenr) tuple,
2609 where filename is a string and linenr an int."""
2610 return (self.filename, self.linenr)
2611
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002612 def get_items(self, recursive=False):
2613 """Returns a list containing the items (symbols, menus, choice
2614 statements and comments) in in the menu, in the same order that the
2615 items appear within the menu.
2616
2617 recursive (default: False): True if items contained in items within the
2618 menu should be included recursively (preorder)."""
2619
2620 if not recursive:
2621 return self.block
2622
2623 res = []
2624 for item in self.block:
2625 res.append(item)
2626 if isinstance(item, Menu):
2627 res.extend(item.get_items(True))
2628 elif isinstance(item, Choice):
2629 res.extend(item.get_items())
2630 return res
2631
2632 def get_symbols(self, recursive=False):
2633 """Returns a list containing the symbols in the menu, in the same order
2634 that they appear within the menu.
2635
2636 recursive (default: False): True if symbols contained in items within
2637 the menu should be included recursively."""
2638
2639 return [item for item in self.get_items(recursive) if
2640 isinstance(item, Symbol)]
2641
2642 def get_visibility(self):
2643 """Returns the visibility of the menu. This also affects the visibility
2644 of subitems. See also Symbol.get_visibility()."""
2645 return self.config._eval_expr(self.dep_expr)
2646
2647 def get_visible_if_visibility(self):
2648 """Returns the visibility the menu gets from its 'visible if'
2649 condition. "y" if the menu has no 'visible if' condition."""
2650 return self.config._eval_expr(self.visible_if_expr)
2651
2652 def get_referenced_symbols(self, refs_from_enclosing=False):
2653 """See Symbol.get_referenced_symbols()."""
2654 return self.all_referenced_syms if refs_from_enclosing else \
2655 self.referenced_syms
2656
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002657 def __str__(self):
2658 """Returns a string containing various information about the menu."""
2659 depends_on_str = self.config._expr_val_str(self.orig_deps,
2660 "(no dependencies)")
2661 visible_if_str = self.config._expr_val_str(self.visible_if_expr,
2662 "(no dependencies)")
2663
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002664 additional_deps_str = " " + \
2665 self.config._expr_val_str(self.deps_from_containing,
2666 "(no additional dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002667
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002668 return _lines("Menu",
2669 "Title : " + self.title,
2670 "'depends on' dependencies : " + depends_on_str,
2671 "'visible if' dependencies : " + visible_if_str,
2672 "Additional dependencies from enclosing menus and "
2673 "ifs:",
2674 additional_deps_str,
2675 "Location: {0}:{1}".format(self.filename, self.linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002676
2677 #
2678 # Private methods
2679 #
2680
2681 def __init__(self):
2682 """Menu constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002683 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002684
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002685 self.title = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002686 self.dep_expr = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002687 self.visible_if_expr = None
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002688 self.block = [] # List of contained items
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002689 self.config = None
2690 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002691
2692 # Dependency expression without dependencies from enclosing menus and
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002693 # ifs propagated
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002694 self.orig_deps = None
2695
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002696 # Dependencies inherited from containing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002697 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002698 # The set of symbols referenced by this menu (see
2699 # get_referenced_symbols())
2700 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002701 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002702 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002703 self.all_referenced_syms = None
2704
2705 self.filename = None
2706 self.linenr = None
2707
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002708 def _make_conf(self, append_fn):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002709 if self.config._eval_expr(self.dep_expr) != "n" and \
2710 self.config._eval_expr(self.visible_if_expr) != "n":
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002711 append_fn("\n#\n# {0}\n#".format(self.title))
2712 _make_block_conf(self.block, append_fn)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002713
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002714class Choice(Item):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002715
2716 """Represents a choice statement. A choice can be in one of three modes:
2717
2718 "n" - The choice is not visible and no symbols can be selected.
2719
2720 "m" - Any number of symbols can be set to "m". The rest will be "n". This
2721 is safe since potentially conflicting options don't actually get
2722 compiled into the kernel simultaneously with "m".
2723
2724 "y" - One symbol will be "y" while the rest are "n".
2725
2726 Only tristate choices can be in "m" mode, and the visibility of the choice
2727 is an upper bound on the mode, so that e.g. a choice that depends on a
2728 symbol with value "m" will be in "m" mode.
2729
2730 The mode changes automatically when a value is assigned to a symbol within
2731 the choice.
2732
2733 See Symbol.get_visibility() too."""
2734
2735 #
2736 # Public interface
2737 #
2738
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002739 def get_config(self):
2740 """Returns the Config instance this choice is from."""
2741 return self.config
2742
2743 def get_name(self):
2744 """For named choices, returns the name. Returns None for unnamed
2745 choices. No named choices appear anywhere in the kernel Kconfig files
2746 as of Linux 3.7.0-rc8."""
2747 return self.name
2748
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002749 def get_type(self):
2750 """Returns the type of the choice. See Symbol.get_type()."""
2751 return self.type
2752
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002753 def get_prompts(self):
2754 """Returns a list of prompts defined for the choice, in the order they
2755 appear in the configuration files. Returns the empty list for choices
2756 with no prompt.
2757
2758 This list will have a single entry for the vast majority of choices
2759 having prompts, but having multiple prompts for a single choice is
2760 possible through having multiple 'choice' entries for it (though I'm
2761 not sure if that ever happens in practice)."""
2762 return [prompt for prompt, _ in self.orig_prompts]
2763
2764 def get_help(self):
2765 """Returns the help text of the choice, or None if the choice has no
2766 help text."""
2767 return self.help
2768
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002769 def get_parent(self):
2770 """Returns the menu or choice statement that contains the choice, or
2771 None if the choice is at the top level. Note that if statements are
2772 treated as syntactic sugar and do not have an explicit class
2773 representation."""
2774 return self.parent
2775
2776 def get_def_locations(self):
2777 """Returns a list of (filename, linenr) tuples, where filename (string)
2778 and linenr (int) represent a location where the choice is defined. For
2779 the vast majority of choices (all of them as of Linux 3.7.0-rc8) this
2780 list will only contain one element, but its possible for named choices
2781 to be defined in multiple locations."""
2782 return self.def_locations
2783
2784 def get_selection(self):
2785 """Returns the symbol selected (either by the user or through
2786 defaults), or None if either no symbol is selected or the mode is not
2787 "y"."""
2788 if self.cached_selection is not None:
2789 if self.cached_selection == NO_SELECTION:
2790 return None
2791 return self.cached_selection
2792
2793 if self.get_mode() != "y":
2794 return self._cache_ret(None)
2795
2796 # User choice available?
2797 if self.user_val is not None and _get_visibility(self.user_val) == "y":
2798 return self._cache_ret(self.user_val)
2799
2800 if self.optional:
2801 return self._cache_ret(None)
2802
2803 return self._cache_ret(self.get_selection_from_defaults())
2804
2805 def get_selection_from_defaults(self):
2806 """Like Choice.get_selection(), but acts as if no symbol has been
2807 selected by the user and no 'optional' flag is in effect."""
2808
2809 if not self.actual_symbols:
2810 return None
2811
2812 for symbol, cond_expr in self.def_exprs:
2813 if self.config._eval_expr(cond_expr) != "n":
2814 chosen_symbol = symbol
2815 break
2816 else:
2817 chosen_symbol = self.actual_symbols[0]
2818
2819 # Is the chosen symbol visible?
2820 if _get_visibility(chosen_symbol) != "n":
2821 return chosen_symbol
2822 # Otherwise, pick the first visible symbol
2823 for sym in self.actual_symbols:
2824 if _get_visibility(sym) != "n":
2825 return sym
2826 return None
2827
2828 def get_user_selection(self):
2829 """If the choice is in "y" mode and has a user-selected symbol, returns
2830 that symbol. Otherwise, returns None."""
2831 return self.user_val
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002832
2833 def get_items(self):
2834 """Gets all items contained in the choice in the same order as within
2835 the configuration ("items" instead of "symbols" since choices and
2836 comments might appear within choices. This only happens in one place as
2837 of Linux 3.7.0-rc8, in drivers/usb/gadget/Kconfig)."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002838 return self.block
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002839
2840 def get_symbols(self):
2841 """Returns a list containing the choice's symbols.
2842
2843 A quirk (perhaps a bug) of Kconfig is that you can put items within a
2844 choice that will not be considered members of the choice insofar as
2845 selection is concerned. This happens for example if one symbol within a
2846 choice 'depends on' the symbol preceding it, or if you put non-symbol
2847 items within choices.
2848
2849 As of Linux 3.7.0-rc8, this seems to be used intentionally in one
2850 place: drivers/usb/gadget/Kconfig.
2851
2852 This function returns the "proper" symbols of the choice in the order
2853 they appear in the choice, excluding such items. If you want all items
2854 in the choice, use get_items()."""
2855 return self.actual_symbols
2856
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002857 def get_referenced_symbols(self, refs_from_enclosing=False):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002858 """See Symbol.get_referenced_symbols()."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002859 return self.all_referenced_syms if refs_from_enclosing else \
2860 self.referenced_syms
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002861
2862 def get_visibility(self):
2863 """Returns the visibility of the choice statement: one of "n", "m" or
2864 "y". This acts as an upper limit on the mode of the choice (though bool
2865 choices can only have the mode "y"). See the class documentation for an
2866 explanation of modes."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002867 return _get_visibility(self)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002868
2869 def get_mode(self):
2870 """Returns the mode of the choice. See the class documentation for
2871 an explanation of modes."""
2872 minimum_mode = "n" if self.optional else "m"
2873 mode = self.user_mode if self.user_mode is not None else minimum_mode
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002874 mode = self.config._eval_min(mode, _get_visibility(self))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002875
2876 # Promote "m" to "y" for boolean choices
2877 if mode == "m" and self.type == BOOL:
2878 return "y"
2879
2880 return mode
2881
2882 def is_optional(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002883 """Returns True if the choice has the 'optional' flag set (and so will
2884 default to "n" mode)."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002885 return self.optional
2886
2887 def __str__(self):
2888 """Returns a string containing various information about the choice
2889 statement."""
2890 return self.config._get_sym_or_choice_str(self)
2891
2892 #
2893 # Private methods
2894 #
2895
2896 def __init__(self):
2897 """Choice constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002898 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002899
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002900 self.name = None # Yes, choices can be named
2901 self.type = UNKNOWN
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002902 self.prompts = []
2903 self.def_exprs = [] # 'default' properties
2904 self.help = None # Help text
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02002905 self.block = [] # List of contained items
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002906 self.config = None
2907 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002908
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002909 self.user_val = None
2910 self.user_mode = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002911
2912 # We need to filter out symbols that appear within the choice block but
2913 # are not considered choice items (see
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002914 # Choice._determine_actual_symbols()) This list holds the "actual"
2915 # choice items.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002916 self.actual_symbols = []
2917
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002918 # The prompts and default values without any dependencies from
2919 # enclosing menus and ifs propagated
2920 self.orig_prompts = []
2921 self.orig_def_exprs = []
2922
2923 # Dependencies inherited from containing menus and ifs
2924 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002925 # The set of symbols referenced by this choice (see
2926 # get_referenced_symbols())
2927 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002928 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002929 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002930 self.all_referenced_syms = set()
2931
2932 # See Choice.get_def_locations()
2933 self.def_locations = []
2934
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002935 # Cached values
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002936 self.cached_selection = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002937 self.cached_visibility = None
2938
2939 self.optional = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002940
2941 def _determine_actual_symbols(self):
2942 """If a symbol's visibility depends on the preceding symbol within a
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002943 choice, it is no longer viewed as a choice item. (This is quite
2944 possibly a bug, but some things consciously use it... ugh. It stems
2945 from automatic submenu creation.) In addition, it's possible to have
2946 choices and comments within choices, and those shouldn't be considered
2947 choice items either. Only drivers/usb/gadget/Kconfig seems to depend on
2948 any of this. This method computes the "actual" items in the choice and
2949 sets the is_choice_sym flag on them (retrieved via is_choice_symbol()).
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002950
2951 Don't let this scare you: an earlier version simply checked for a
2952 sequence of symbols where all symbols after the first appeared in the
2953 'depends on' expression of the first, and that worked fine. The added
2954 complexity is to be future-proof in the event that
2955 drivers/usb/gadget/Kconfig turns even more sinister. It might very well
2956 be overkilling things (especially if that file is refactored ;)."""
2957
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002958 # Items might depend on each other in a tree structure, so we need a
2959 # stack to keep track of the current tentative parent
2960 stack = []
2961
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002962 for item in self.block:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002963 if not isinstance(item, Symbol):
2964 stack = []
2965 continue
2966
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002967 while stack:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002968 if item._has_auto_menu_dep_on(stack[-1]):
2969 # The item should not be viewed as a choice item, so don't
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002970 # set item.is_choice_sym
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002971 stack.append(item)
2972 break
2973 else:
2974 stack.pop()
2975 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002976 item.is_choice_sym = True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002977 self.actual_symbols.append(item)
2978 stack.append(item)
2979
2980 def _cache_ret(self, selection):
2981 # As None is used to indicate the lack of a cached value we can't use
2982 # that to cache the fact that the choice has no selection. Instead, we
2983 # use the symbolic constant NO_SELECTION.
2984 if selection is None:
2985 self.cached_selection = NO_SELECTION
2986 else:
2987 self.cached_selection = selection
2988
2989 return selection
2990
2991 def _invalidate(self):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002992 self.cached_selection = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002993 self.cached_visibility = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002994
2995 def _unset_user_value(self):
2996 self._invalidate()
2997 self.user_val = None
2998 self.user_mode = None
2999
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003000 def _make_conf(self, append_fn):
3001 _make_block_conf(self.block, append_fn)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003002
3003class Comment(Item):
3004
3005 """Represents a comment statement."""
3006
3007 #
3008 # Public interface
3009 #
3010
3011 def get_config(self):
3012 """Returns the Config instance this comment is from."""
3013 return self.config
3014
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003015 def get_text(self):
3016 """Returns the text of the comment."""
3017 return self.text
3018
3019 def get_parent(self):
3020 """Returns the menu or choice statement that contains the comment, or
3021 None if the comment is at the top level. Note that if statements are
3022 treated as syntactic sugar and do not have an explicit class
3023 representation."""
3024 return self.parent
3025
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003026 def get_location(self):
3027 """Returns the location of the comment as a (filename, linenr) tuple,
3028 where filename is a string and linenr an int."""
3029 return (self.filename, self.linenr)
3030
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003031 def get_visibility(self):
3032 """Returns the visibility of the comment. See also
3033 Symbol.get_visibility()."""
3034 return self.config._eval_expr(self.dep_expr)
3035
3036 def get_referenced_symbols(self, refs_from_enclosing=False):
3037 """See Symbol.get_referenced_symbols()."""
3038 return self.all_referenced_syms if refs_from_enclosing else \
3039 self.referenced_syms
3040
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003041 def __str__(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003042 """Returns a string containing various information about the
3043 comment."""
3044 dep_str = self.config._expr_val_str(self.orig_deps,
3045 "(no dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003046
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003047 additional_deps_str = " " + \
3048 self.config._expr_val_str(self.deps_from_containing,
3049 "(no additional dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003050
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003051 return _lines("Comment",
3052 "Text: " + str(self.text),
3053 "Dependencies: " + dep_str,
3054 "Additional dependencies from enclosing menus and "
3055 "ifs:",
3056 additional_deps_str,
3057 "Location: {0}:{1}".format(self.filename, self.linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003058
3059 #
3060 # Private methods
3061 #
3062
3063 def __init__(self):
3064 """Comment constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003065 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003066
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003067 self.text = None
3068 self.dep_expr = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003069 self.config = None
3070 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003071
3072 # Dependency expression without dependencies from enclosing menus and
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003073 # ifs propagated
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003074 self.orig_deps = None
3075
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003076 # Dependencies inherited from containing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003077 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003078 # The set of symbols referenced by this comment (see
3079 # get_referenced_symbols())
3080 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003081 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003082 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003083 self.all_referenced_syms = None
3084
3085 self.filename = None
3086 self.linenr = None
3087
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003088 def _make_conf(self, append_fn):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003089 if self.config._eval_expr(self.dep_expr) != "n":
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003090 append_fn("\n#\n# {0}\n#".format(self.text))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003091
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003092class Kconfig_Syntax_Error(Exception):
3093 """Exception raised for syntax errors."""
3094 pass
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003095
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003096class Internal_Error(Exception):
3097 """Exception raised for internal errors."""
3098 pass
3099
3100#
3101# Public functions
3102#
3103
3104def tri_less(v1, v2):
3105 """Returns True if the tristate v1 is less than the tristate v2, where "n",
3106 "m" and "y" are ordered from lowest to highest."""
3107 return TRI_TO_INT[v1] < TRI_TO_INT[v2]
3108
3109def tri_less_eq(v1, v2):
3110 """Returns True if the tristate v1 is less than or equal to the tristate
3111 v2, where "n", "m" and "y" are ordered from lowest to highest."""
3112 return TRI_TO_INT[v1] <= TRI_TO_INT[v2]
3113
3114def tri_greater(v1, v2):
3115 """Returns True if the tristate v1 is greater than the tristate v2, where
3116 "n", "m" and "y" are ordered from lowest to highest."""
3117 return TRI_TO_INT[v1] > TRI_TO_INT[v2]
3118
3119def tri_greater_eq(v1, v2):
3120 """Returns True if the tristate v1 is greater than or equal to the tristate
3121 v2, where "n", "m" and "y" are ordered from lowest to highest."""
3122 return TRI_TO_INT[v1] >= TRI_TO_INT[v2]
3123
3124#
3125# Internal classes
3126#
3127
3128class _Feed(object):
3129
3130 """Class for working with sequences in a stream-like fashion; handy for
3131 tokens."""
3132
3133 # This would be more helpful on the item classes, but would remove some
3134 # flexibility
3135 __slots__ = ['items', 'length', 'i']
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003136
3137 def __init__(self, items):
3138 self.items = items
3139 self.length = len(self.items)
3140 self.i = 0
3141
3142 def get_next(self):
3143 if self.i >= self.length:
3144 return None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003145 item = self.items[self.i]
3146 self.i += 1
3147 return item
3148
3149 def peek_next(self):
3150 return None if self.i >= self.length else self.items[self.i]
3151
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003152 def check(self, token):
3153 """Check if the next token is 'token'. If so, remove it from the token
3154 feed and return True. Otherwise, leave it in and return False."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003155 if self.i < self.length and self.items[self.i] == token:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003156 self.i += 1
3157 return True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003158 return False
3159
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003160 def unget_all(self):
3161 self.i = 0
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003162
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003163class _FileFeed(object):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003164
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003165 """Feeds lines from a file. Keeps track of the filename and current line
3166 number. Joins any line ending in \\ with the following line. We need to be
3167 careful to get the line number right in the presence of continuation
3168 lines."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003169
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003170 __slots__ = ['filename', 'lines', 'length', 'linenr']
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003171
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003172 def __init__(self, filename):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003173 self.filename = _clean_up_path(filename)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003174 with open(filename, "r") as f:
3175 # No interleaving of I/O and processing yet. Don't know if it would
3176 # help.
3177 self.lines = f.readlines()
3178 self.length = len(self.lines)
3179 self.linenr = 0
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003180
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003181 def get_next(self):
3182 if self.linenr >= self.length:
3183 return None
3184 line = self.lines[self.linenr]
3185 self.linenr += 1
3186 while line.endswith("\\\n"):
3187 line = line[:-2] + self.lines[self.linenr]
3188 self.linenr += 1
3189 return line
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003190
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003191 def peek_next(self):
3192 linenr = self.linenr
3193 if linenr >= self.length:
3194 return None
3195 line = self.lines[linenr]
3196 while line.endswith("\\\n"):
3197 linenr += 1
3198 line = line[:-2] + self.lines[linenr]
3199 return line
3200
3201 def unget(self):
3202 self.linenr -= 1
3203 while self.lines[self.linenr].endswith("\\\n"):
3204 self.linenr -= 1
3205
3206 def next_nonblank(self):
3207 """Removes lines up to and including the next non-blank (not all-space)
3208 line and returns it. Returns None if there are no more non-blank
3209 lines."""
3210 while 1:
3211 line = self.get_next()
3212 if line is None or not line.isspace():
3213 return line
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003214
3215#
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003216# Internal functions
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003217#
3218
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003219def _get_visibility(sc):
3220 """Symbols and Choices have a "visibility" that acts as an upper bound on
3221 the values a user can set for them, corresponding to the visibility in e.g.
3222 'make menuconfig'. This function calculates the visibility for the Symbol
3223 or Choice 'sc' -- the logic is nearly identical."""
3224 if sc.cached_visibility is None:
3225 vis = "n"
3226 for _, cond_expr in sc.prompts:
3227 vis = sc.config._eval_max(vis, cond_expr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003228
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003229 if isinstance(sc, Symbol) and sc.is_choice_sym:
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02003230 if sc.type == TRISTATE and vis == "m" and \
3231 sc.parent.get_mode() == "y":
3232 # Choice symbols with visibility "m" are not visible if the
3233 # choice has mode "y"
3234 vis = "n"
3235 else:
3236 vis = sc.config._eval_min(vis, _get_visibility(sc.parent))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003237
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003238 # Promote "m" to "y" if we're dealing with a non-tristate
3239 if vis == "m" and sc.type != TRISTATE:
3240 vis = "y"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003241
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003242 sc.cached_visibility = vis
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003243
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003244 return sc.cached_visibility
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003245
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003246def _make_and(e1, e2):
3247 """Constructs an AND (&&) expression. Performs trivial simplification.
3248 Nones equate to 'y'.
3249
3250 Note: returns None if e1 == e2 == None."""
3251 if e1 is None or e1 == "y":
3252 return e2
3253 if e2 is None or e2 == "y":
3254 return e1
3255
3256 # Prefer to merge argument lists if possible to reduce the number of nodes
3257
3258 if isinstance(e1, tuple) and e1[0] == AND:
3259 if isinstance(e2, tuple) and e2[0] == AND:
3260 return (AND, e1[1] + e2[1])
3261 return (AND, e1[1] + [e2])
3262
3263 if isinstance(e2, tuple) and e2[0] == AND:
3264 return (AND, e2[1] + [e1])
3265
3266 return (AND, [e1, e2])
3267
3268def _make_or(e1, e2):
3269 """Constructs an OR (||) expression. Performs trivial simplification and
3270 avoids Nones. Nones equate to 'y', which is usually what we want, but needs
3271 to be kept in mind."""
3272
3273 # Perform trivial simplification and avoid None's (which
3274 # correspond to y's)
3275 if e1 is None or e2 is None or e1 == "y" or e2 == "y":
3276 return "y"
3277 if e1 == "n":
3278 return e2
3279
3280 # Prefer to merge argument lists if possible to reduce the number of nodes
3281
3282 if isinstance(e1, tuple) and e1[0] == OR:
3283 if isinstance(e2, tuple) and e2[0] == OR:
3284 return (OR, e1[1] + e2[1])
3285 return (OR, e1[1] + [e2])
3286
3287 if isinstance(e2, tuple) and e2[0] == OR:
3288 return (OR, e2[1] + [e1])
3289
3290 return (OR, [e1, e2])
3291
3292def _get_expr_syms_rec(expr, res):
3293 """_get_expr_syms() helper. Recurses through expressions."""
3294 if isinstance(expr, Symbol):
3295 res.add(expr)
3296 elif isinstance(expr, str):
3297 return
3298 elif expr[0] == AND or expr[0] == OR:
3299 for term in expr[1]:
3300 _get_expr_syms_rec(term, res)
3301 elif expr[0] == NOT:
3302 _get_expr_syms_rec(expr[1], res)
3303 elif expr[0] == EQUAL or expr[0] == UNEQUAL:
3304 if isinstance(expr[1], Symbol):
3305 res.add(expr[1])
3306 if isinstance(expr[2], Symbol):
3307 res.add(expr[2])
3308 else:
3309 _internal_error("Internal error while fetching symbols from an "
3310 "expression with token stream {0}.".format(expr))
3311
3312def _get_expr_syms(expr):
3313 """Returns the set() of symbols appearing in expr."""
3314 res = set()
3315 if expr is not None:
3316 _get_expr_syms_rec(expr, res)
3317 return res
3318
3319def _str_val(obj):
3320 """Returns the value of obj as a string. If obj is not a string (constant
3321 symbol), it must be a Symbol."""
3322 return obj if isinstance(obj, str) else obj.get_value()
3323
3324def _make_block_conf(block, append_fn):
3325 """Returns a list of .config strings for a block (list) of items."""
3326
3327 # Collect the substrings in a list and later use join() instead of += to
3328 # build the final .config contents. With older Python versions, this yields
3329 # linear instead of quadratic complexity.
3330 for item in block:
3331 item._make_conf(append_fn)
3332
3333def _sym_str_string(sym_or_str):
3334 if isinstance(sym_or_str, str):
3335 return '"' + sym_or_str + '"'
3336 return sym_or_str.name
3337
3338def _intersperse(lst, op):
3339 """_expr_to_str() helper. Gets the string representation of each expression
3340 in lst and produces a list where op has been inserted between the
3341 elements."""
3342 if not lst:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003343 return ""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003344
3345 res = []
3346
3347 def handle_sub_expr(expr):
3348 no_parens = isinstance(expr, (str, Symbol)) or \
3349 expr[0] in (EQUAL, UNEQUAL) or \
3350 PRECEDENCE[op] <= PRECEDENCE[expr[0]]
3351 if not no_parens:
3352 res.append("(")
3353 res.extend(_expr_to_str_rec(expr))
3354 if not no_parens:
3355 res.append(")")
3356
3357 op_str = OP_TO_STR[op]
3358
3359 handle_sub_expr(lst[0])
3360 for expr in lst[1:]:
3361 res.append(op_str)
3362 handle_sub_expr(expr)
3363
3364 return res
3365
3366def _expr_to_str_rec(expr):
3367 if expr is None:
3368 return [""]
3369
3370 if isinstance(expr, (Symbol, str)):
3371 return [_sym_str_string(expr)]
3372
3373 if expr[0] in (AND, OR):
3374 return _intersperse(expr[1], expr[0])
3375
3376 if expr[0] == NOT:
3377 need_parens = not isinstance(expr[1], (str, Symbol))
3378
3379 res = ["!"]
3380 if need_parens:
3381 res.append("(")
3382 res.extend(_expr_to_str_rec(expr[1]))
3383 if need_parens:
3384 res.append(")")
3385 return res
3386
3387 if expr[0] in (EQUAL, UNEQUAL):
3388 return [_sym_str_string(expr[1]),
3389 OP_TO_STR[expr[0]],
3390 _sym_str_string(expr[2])]
3391
3392def _expr_to_str(expr):
3393 return "".join(_expr_to_str_rec(expr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003394
3395def _indentation(line):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003396 """Returns the length of the line's leading whitespace, treating tab stops
3397 as being spaced 8 characters apart."""
3398 line = line.expandtabs()
3399 return len(line) - len(line.lstrip())
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003400
3401def _deindent(line, indent):
3402 """Deindent 'line' by 'indent' spaces."""
3403 line = line.expandtabs()
3404 if len(line) <= indent:
3405 return line
3406 return line[indent:]
3407
3408def _is_base_n(s, n):
3409 try:
3410 int(s, n)
3411 return True
3412 except ValueError:
3413 return False
3414
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003415def _lines(*args):
3416 """Returns a string consisting of all arguments, with newlines inserted
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003417 between them."""
3418 return "\n".join(args)
3419
3420def _comment(s):
3421 """Returns a new string with "#" inserted before each line in 's'."""
3422 if not s:
3423 return "#"
3424 res = "".join(["#" + line for line in s.splitlines(True)])
3425 if s.endswith("\n"):
3426 return res + "#"
3427 return res
3428
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003429def _clean_up_path(path):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003430 """Strips an initial "./" and any trailing slashes from 'path'."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003431 if path.startswith("./"):
3432 path = path[2:]
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003433 return path.rstrip("/")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003434
Simon Glass8639f692017-08-04 03:30:30 -06003435def _build_msg(msg, filename, linenr):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003436 if filename is not None:
Simon Glass8639f692017-08-04 03:30:30 -06003437 msg = "{0}:{1}: ".format(_clean_up_path(filename), linenr) + msg
3438 return msg
3439
3440def _stderr_msg(msg, filename, linenr):
3441 sys.stderr.write(_build_msg(msg, filename, linenr) + "\n")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003442
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003443def _tokenization_error(s, filename, linenr):
3444 loc = "" if filename is None else "{0}:{1}: ".format(filename, linenr)
3445 raise Kconfig_Syntax_Error("{0}Couldn't tokenize '{1}'"
3446 .format(loc, s.strip()))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003447
3448def _parse_error(s, msg, filename, linenr):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003449 loc = "" if filename is None else "{0}:{1}: ".format(filename, linenr)
3450 raise Kconfig_Syntax_Error("{0}Couldn't parse '{1}'{2}"
3451 .format(loc, s.strip(),
3452 "." if msg is None else ": " + msg))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003453
3454def _internal_error(msg):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003455 raise Internal_Error(msg +
3456 "\nSorry! You may want to send an email to ulfalizer a.t Google's "
3457 "email service to tell me about this. Include the message above and the "
3458 "stack trace and describe what you were doing.")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003459
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003460#
3461# Internal global constants
3462#
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003463
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003464# Tokens
3465(T_AND, T_OR, T_NOT,
3466 T_OPEN_PAREN, T_CLOSE_PAREN,
3467 T_EQUAL, T_UNEQUAL,
3468 T_MAINMENU, T_MENU, T_ENDMENU,
3469 T_SOURCE, T_CHOICE, T_ENDCHOICE,
3470 T_COMMENT, T_CONFIG, T_MENUCONFIG,
3471 T_HELP, T_IF, T_ENDIF, T_DEPENDS, T_ON,
3472 T_OPTIONAL, T_PROMPT, T_DEFAULT,
3473 T_BOOL, T_TRISTATE, T_HEX, T_INT, T_STRING,
3474 T_DEF_BOOL, T_DEF_TRISTATE,
Tom Rinid0361072017-03-03 15:33:29 -05003475 T_SELECT, T_IMPLY, T_RANGE, T_OPTION, T_ALLNOCONFIG_Y, T_ENV,
3476 T_DEFCONFIG_LIST, T_MODULES, T_VISIBLE) = range(40)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003477
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003478# The leading underscore before the function assignments below prevent pydoc
3479# from listing them. The constants could be hidden too, but they're fairly
3480# obviously internal anyway, so don't bother spamming the code.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003481
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003482# Keyword to token map. Note that the get() method is assigned directly as a
3483# small optimization.
3484_get_keyword = \
3485 {"mainmenu": T_MAINMENU, "menu": T_MENU, "endmenu": T_ENDMENU,
3486 "endif": T_ENDIF, "endchoice": T_ENDCHOICE, "source": T_SOURCE,
3487 "choice": T_CHOICE, "config": T_CONFIG, "comment": T_COMMENT,
3488 "menuconfig": T_MENUCONFIG, "help": T_HELP, "if": T_IF,
3489 "depends": T_DEPENDS, "on": T_ON, "optional": T_OPTIONAL,
3490 "prompt": T_PROMPT, "default": T_DEFAULT, "bool": T_BOOL, "boolean": T_BOOL,
3491 "tristate": T_TRISTATE, "int": T_INT, "hex": T_HEX, "def_bool": T_DEF_BOOL,
3492 "def_tristate": T_DEF_TRISTATE, "string": T_STRING, "select": T_SELECT,
Ulf Magnusson4e1102f2017-09-19 12:52:55 +02003493 "imply" : T_IMPLY, "range": T_RANGE, "option": T_OPTION,
Tom Rinid0361072017-03-03 15:33:29 -05003494 "allnoconfig_y": T_ALLNOCONFIG_Y, "env": T_ENV,
3495 "defconfig_list": T_DEFCONFIG_LIST, "modules": T_MODULES,
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003496 "visible": T_VISIBLE}.get
3497
3498# Strings to use for True and False
3499BOOL_STR = {False: "false", True: "true"}
3500
3501# Tokens after which identifier-like lexemes are treated as strings. T_CHOICE
3502# is included to avoid symbols being registered for named choices.
3503STRING_LEX = frozenset((T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING, T_CHOICE,
3504 T_PROMPT, T_MENU, T_COMMENT, T_SOURCE, T_MAINMENU))
3505
3506# Matches the initial token on a line; see _tokenize(). Also eats trailing
3507# whitespace as an optimization.
3508_initial_token_re_match = re.compile(r"[^\w]*(\w+)\s*").match
3509
3510# Matches an identifier/keyword optionally preceded by whitespace. Also eats
3511# trailing whitespace as an optimization.
3512_id_keyword_re_match = re.compile(r"\s*([\w./-]+)\s*").match
3513
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003514# Regular expression for finding $-references to symbols in strings
3515_sym_ref_re_search = re.compile(r"\$[A-Za-z0-9_]+").search
3516
3517# Integers representing symbol types
3518UNKNOWN, BOOL, TRISTATE, STRING, HEX, INT = range(6)
3519
3520# Strings to use for types
3521TYPENAME = {UNKNOWN: "unknown", BOOL: "bool", TRISTATE: "tristate",
3522 STRING: "string", HEX: "hex", INT: "int"}
3523
3524# Token to type mapping
3525TOKEN_TO_TYPE = {T_BOOL: BOOL, T_TRISTATE: TRISTATE, T_STRING: STRING,
3526 T_INT: INT, T_HEX: HEX}
3527
3528# Default values for symbols of different types (the value the symbol gets if
3529# it is not assigned a user value and none of its 'default' clauses kick in)
3530DEFAULT_VALUE = {BOOL: "n", TRISTATE: "n", STRING: "", INT: "", HEX: ""}
3531
3532# Indicates that no item is selected in a choice statement
3533NO_SELECTION = 0
3534
3535# Integers representing expression types
3536AND, OR, NOT, EQUAL, UNEQUAL = range(5)
3537
3538# Map from tristate values to integers
3539TRI_TO_INT = {"n": 0, "m": 1, "y": 2}
3540
3541# Printing-related stuff
3542
3543OP_TO_STR = {AND: " && ", OR: " || ", EQUAL: " = ", UNEQUAL: " != "}
3544PRECEDENCE = {OR: 0, AND: 1, NOT: 2}