blob: 352ad438eed2955aeb6ec5349fc437032f659c5b [file] [log] [blame]
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001#
Masahiro Yamada91708182014-09-17 13:37:45 +09002# SPDX-License-Identifier: ISC
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003#
4# Author: Ulf Magnusson
5# https://github.com/ulfalizer/Kconfiglib
6
7# This is Kconfiglib, a Python library for scripting, debugging, and extracting
8# information from Kconfig-based configuration systems. To view the
9# documentation, run
10#
11# $ pydoc kconfiglib
12#
13# or, if you prefer HTML,
14#
15# $ pydoc -w kconfiglib
16#
17# The examples/ subdirectory contains examples, to be run with e.g.
18#
19# $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
20#
21# Look in testsuite.py for the test suite.
22
23"""
24Kconfiglib is a Python library for scripting and extracting information from
25Kconfig-based configuration systems. Features include the following:
26
27 - Symbol values and properties can be looked up and values assigned
28 programmatically.
29 - .config files can be read and written.
30 - Expressions can be evaluated in the context of a Kconfig configuration.
31 - Relations between symbols can be quickly determined, such as finding all
32 symbols that reference a particular symbol.
33 - Highly compatible with the scripts/kconfig/*conf utilities. The test suite
34 automatically compares outputs between Kconfiglib and the C implementation
35 for a large number of cases.
36
37For the Linux kernel, scripts are run using
38
Ulf Magnusson90c36d82015-08-13 19:55:40 +020039 $ make scriptconfig [ARCH=<arch>] SCRIPT=<path to script> [SCRIPT_ARG=<arg>]
Masahiro Yamadaf219e012014-09-01 19:57:37 +090040
Ulf Magnusson90c36d82015-08-13 19:55:40 +020041Using the 'scriptconfig' target ensures that required environment variables
42(SRCARCH, ARCH, srctree, KERNELVERSION, etc.) are set up correctly.
Masahiro Yamadaf219e012014-09-01 19:57:37 +090043
Ulf Magnusson90c36d82015-08-13 19:55:40 +020044Scripts receive the name of the Kconfig file to load in sys.argv[1]. As of
45Linux 4.1.0-rc5, this is always "Kconfig" from the kernel top-level directory.
46If an argument is provided with SCRIPT_ARG, it appears as sys.argv[2].
Masahiro Yamadaf219e012014-09-01 19:57:37 +090047
48To get an interactive Python prompt with Kconfiglib preloaded and a Config
Ulf Magnusson90c36d82015-08-13 19:55:40 +020049object 'c' created, run
Masahiro Yamadaf219e012014-09-01 19:57:37 +090050
Ulf Magnusson90c36d82015-08-13 19:55:40 +020051 $ make iscriptconfig [ARCH=<arch>]
Masahiro Yamadaf219e012014-09-01 19:57:37 +090052
Ulf Magnusson90c36d82015-08-13 19:55:40 +020053Kconfiglib supports both Python 2 and Python 3. For (i)scriptconfig, the Python
54interpreter to use can be passed in PYTHONCMD, which defaults to 'python'. PyPy
55works well too, and might give a nice speedup for long-running jobs.
Masahiro Yamadaf219e012014-09-01 19:57:37 +090056
Ulf Magnusson90c36d82015-08-13 19:55:40 +020057The examples/ directory contains short example scripts, which can be run with
58e.g.
Masahiro Yamadaf219e012014-09-01 19:57:37 +090059
60 $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
61
62or
63
Ulf Magnusson90c36d82015-08-13 19:55:40 +020064 $ make scriptconfig SCRIPT=Kconfiglib/examples/help_grep.py SCRIPT_ARG=kernel
Masahiro Yamadaf219e012014-09-01 19:57:37 +090065
Ulf Magnusson90c36d82015-08-13 19:55:40 +020066testsuite.py contains the test suite. See the top of the script for how to run
67it.
Masahiro Yamadaf219e012014-09-01 19:57:37 +090068
69Credits: Written by Ulf "Ulfalizer" Magnusson
70
Ulf Magnusson90c36d82015-08-13 19:55:40 +020071Send bug reports, suggestions and other feedback to ulfalizer a.t Google's
72email service. Don't wrestle with internal APIs. Tell me what you need and I
73might add it in a safe way as a client API instead."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +090074
75import os
76import re
Masahiro Yamadaf219e012014-09-01 19:57:37 +090077import sys
78
Ulf Magnusson90c36d82015-08-13 19:55:40 +020079# File layout:
80#
81# Public classes
82# Public functions
83# Internal classes
84# Internal functions
85# Internal global constants
86
87# Line length: 79 columns
88
89#
90# Public classes
91#
92
93class Config(object):
Masahiro Yamadaf219e012014-09-01 19:57:37 +090094
95 """Represents a Kconfig configuration, e.g. for i386 or ARM. This is the
96 set of symbols and other items appearing in the configuration together with
97 their values. Creating any number of Config objects -- including for
98 different architectures -- is safe; Kconfiglib has no global state."""
99
100 #
101 # Public interface
102 #
103
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200104 def __init__(self, filename="Kconfig", base_dir=None, print_warnings=True,
105 print_undef_assign=False):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900106 """Creates a new Config object, representing a Kconfig configuration.
107 Raises Kconfig_Syntax_Error on syntax errors.
108
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200109 filename (default: "Kconfig"): The base Kconfig file of the
110 configuration. For the Linux kernel, you'll probably want "Kconfig"
111 from the top-level directory, as environment variables will make
112 sure the right Kconfig is included from there
113 (arch/<architecture>/Kconfig). If you are using Kconfiglib via 'make
114 scriptconfig', the filename of the base base Kconfig file will be in
115 sys.argv[1].
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900116
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200117 base_dir (default: None): The base directory relative to which 'source'
118 statements within Kconfig files will work. For the Linux kernel this
119 should be the top-level directory of the kernel tree. $-references
120 to existing environment variables will be expanded.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900121
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200122 If None (the default), the environment variable 'srctree' will be
123 used if set, and the current directory otherwise. 'srctree' is set
124 by the Linux makefiles to the top-level kernel directory. A default
125 of "." would not work with an alternative build directory.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900126
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200127 print_warnings (default: True): Set to True if warnings related to this
128 configuration should be printed to stderr. This can be changed later
129 with Config.set_print_warnings(). It is provided as a constructor
130 argument since warnings might be generated during parsing.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900131
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200132 print_undef_assign (default: False): Set to True if informational
133 messages related to assignments to undefined symbols should be
134 printed to stderr for this configuration. Can be changed later with
135 Config.set_print_undef_assign()."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900136
137 # The set of all symbols, indexed by name (a string)
138 self.syms = {}
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200139 # Python 2/3 compatibility hack. This is the only one needed.
140 if sys.version_info[0] >= 3:
141 self.syms_iter = self.syms.values
142 else:
143 self.syms_iter = self.syms.itervalues
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900144
145 # The set of all defined symbols in the configuration in the order they
146 # appear in the Kconfig files. This excludes the special symbols n, m,
147 # and y as well as symbols that are referenced but never defined.
148 self.kconfig_syms = []
149
150 # The set of all named choices (yes, choices can have names), indexed
151 # by name (a string)
152 self.named_choices = {}
153
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200154 # Lists containing all choices, menus and comments in the configuration
155 self.choices = []
156 self.menus = []
157 self.comments = []
158
159 def register_special_symbol(type_, name, val):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900160 sym = Symbol()
161 sym.is_special_ = True
162 sym.is_defined_ = True
163 sym.config = self
164 sym.name = name
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200165 sym.type = type_
166 sym.cached_val = val
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900167 self.syms[name] = sym
168 return sym
169
170 # The special symbols n, m and y, used as shorthand for "n", "m" and
171 # "y"
172 self.n = register_special_symbol(TRISTATE, "n", "n")
173 self.m = register_special_symbol(TRISTATE, "m", "m")
174 self.y = register_special_symbol(TRISTATE, "y", "y")
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900175 # DEFCONFIG_LIST uses this
176 register_special_symbol(STRING, "UNAME_RELEASE", os.uname()[2])
177
178 # The symbol with "option defconfig_list" set, containing a list of
179 # default .config files
180 self.defconfig_sym = None
181
182 # See Symbol.get_(src)arch()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200183 self.arch = os.environ.get("ARCH")
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900184 self.srcarch = os.environ.get("SRCARCH")
185
186 # See Config.__init__(). We need this for get_defconfig_filename().
187 self.srctree = os.environ.get("srctree")
188 if self.srctree is None:
189 self.srctree = "."
190
191 self.filename = filename
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200192 if base_dir is None:
193 self.base_dir = self.srctree
194 else:
195 self.base_dir = os.path.expandvars(base_dir)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900196
197 # The 'mainmenu' text
198 self.mainmenu_text = None
199
200 # The filename of the most recently loaded .config file
201 self.config_filename = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900202 # The textual header of the most recently loaded .config, uncommented
203 self.config_header = None
204
205 self.print_warnings = print_warnings
206 self.print_undef_assign = print_undef_assign
Simon Glass8639f692017-08-04 03:30:30 -0600207 self._warnings = []
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900208
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900209 # For parsing routines that stop when finding a line belonging to a
210 # different construct, these holds that line and the tokenized version
211 # of that line. The purpose is to avoid having to re-tokenize the line,
212 # which is inefficient and causes problems when recording references to
213 # symbols.
214 self.end_line = None
215 self.end_line_tokens = None
216
217 # See the comment in _parse_expr().
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200218 self._cur_item = None
219 self._line = None
220 self._filename = None
221 self._linenr = None
222 self._transform_m = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900223
224 # Parse the Kconfig files
225 self.top_block = self._parse_file(filename, None, None, None)
226
227 # Build Symbol.dep for all symbols
228 self._build_dep()
229
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900230 def get_arch(self):
231 """Returns the value the environment variable ARCH had at the time the
232 Config instance was created, or None if ARCH was not set. For the
233 kernel, this corresponds to the architecture being built for, with
234 values such as "i386" or "mips"."""
235 return self.arch
236
237 def get_srcarch(self):
238 """Returns the value the environment variable SRCARCH had at the time
239 the Config instance was created, or None if SRCARCH was not set. For
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200240 the kernel, this corresponds to the particular arch/ subdirectory
241 containing architecture-specific code."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900242 return self.srcarch
243
244 def get_srctree(self):
245 """Returns the value the environment variable srctree had at the time
246 the Config instance was created, or None if srctree was not defined.
247 This variable points to the source directory and is used when building
248 in a separate directory."""
249 return self.srctree
250
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200251 def get_base_dir(self):
252 """Returns the base directory relative to which 'source' statements
253 will work, passed as an argument to Config.__init__()."""
254 return self.base_dir
255
256 def get_kconfig_filename(self):
257 """Returns the name of the (base) kconfig file this configuration was
258 loaded from."""
259 return self.filename
260
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900261 def get_config_filename(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200262 """Returns the filename of the most recently loaded configuration file,
263 or None if no configuration has been loaded."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900264 return self.config_filename
265
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200266 def get_config_header(self):
267 """Returns the (uncommented) textual header of the .config file most
268 recently loaded with load_config(). Returns None if no .config file has
269 been loaded or if the most recently loaded .config file has no header.
270 The header consists of all lines up to but not including the first line
271 that either
272
273 1. Does not start with "#"
274 2. Has the form "# CONFIG_FOO is not set."
275 """
276 return self.config_header
277
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900278 def get_mainmenu_text(self):
279 """Returns the text of the 'mainmenu' statement (with $-references to
280 symbols replaced by symbol values), or None if the configuration has no
281 'mainmenu' statement."""
282 return None if self.mainmenu_text is None else \
283 self._expand_sym_refs(self.mainmenu_text)
284
285 def get_defconfig_filename(self):
286 """Returns the name of the defconfig file, which is the first existing
287 file in the list given in a symbol having 'option defconfig_list' set.
288 $-references to symbols will be expanded ("$FOO bar" -> "foo bar" if
289 FOO has the value "foo"). Returns None in case of no defconfig file.
290 Setting 'option defconfig_list' on multiple symbols currently results
291 in undefined behavior.
292
293 If the environment variable 'srctree' was set when the Config was
294 created, get_defconfig_filename() will first look relative to that
295 directory before looking in the current directory; see
Masahiro Yamada9d01b782015-05-27 11:39:22 +0900296 Config.__init__().
297
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200298 WARNING: A wart here is that scripts/kconfig/Makefile sometimes uses
299 the --defconfig=<defconfig> option when calling the C implementation of
300 e.g. 'make defconfig'. This option overrides the 'option
301 defconfig_list' symbol, meaning the result from
302 get_defconfig_filename() might not match what 'make defconfig' would
303 use. That probably ought to be worked around somehow, so that this
304 function always gives the "expected" result."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900305 if self.defconfig_sym is None:
306 return None
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200307 for filename, cond_expr in self.defconfig_sym.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900308 if self._eval_expr(cond_expr) == "y":
309 filename = self._expand_sym_refs(filename)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900310 # We first look in $srctree. os.path.join() won't work here as
311 # an absolute path in filename would override $srctree.
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200312 srctree_filename = os.path.normpath(self.srctree + "/" +
313 filename)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900314 if os.path.exists(srctree_filename):
315 return srctree_filename
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900316 if os.path.exists(filename):
317 return filename
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900318 return None
319
320 def get_symbol(self, name):
321 """Returns the symbol with name 'name', or None if no such symbol
322 appears in the configuration. An alternative shorthand is conf[name],
323 where conf is a Config instance, though that will instead raise
324 KeyError if the symbol does not exist."""
325 return self.syms.get(name)
326
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200327 def __getitem__(self, name):
328 """Returns the symbol with name 'name'. Raises KeyError if the symbol
329 does not appear in the configuration."""
330 return self.syms[name]
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900331
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200332 def get_symbols(self, all_symbols=True):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900333 """Returns a list of symbols from the configuration. An alternative for
334 iterating over all defined symbols (in the order of definition) is
335
336 for sym in config:
337 ...
338
339 which relies on Config implementing __iter__() and is equivalent to
340
341 for sym in config.get_symbols(False):
342 ...
343
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200344 all_symbols (default: True): If True, all symbols -- including special
345 and undefined symbols -- will be included in the result, in an
346 undefined order. If False, only symbols actually defined and not
347 merely referred to in the configuration will be included in the
348 result, and will appear in the order that they are defined within
349 the Kconfig configuration files."""
350 return list(self.syms.values()) if all_symbols else self.kconfig_syms
351
352 def __iter__(self):
353 """Convenience function for iterating over the set of all defined
354 symbols in the configuration, used like
355
356 for sym in conf:
357 ...
358
359 The iteration happens in the order of definition within the Kconfig
360 configuration files. Symbols only referred to but not defined will not
361 be included, nor will the special symbols n, m, and y. If you want to
362 include such symbols as well, see config.get_symbols()."""
363 return iter(self.kconfig_syms)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900364
365 def get_choices(self):
366 """Returns a list containing all choice statements in the
367 configuration, in the order they appear in the Kconfig files."""
368 return self.choices
369
370 def get_menus(self):
371 """Returns a list containing all menus in the configuration, in the
372 order they appear in the Kconfig files."""
373 return self.menus
374
375 def get_comments(self):
376 """Returns a list containing all comments in the configuration, in the
377 order they appear in the Kconfig files."""
378 return self.comments
379
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200380 def get_top_level_items(self):
381 """Returns a list containing the items (symbols, menus, choices, and
382 comments) at the top level of the configuration -- that is, all items
383 that do not appear within a menu or choice. The items appear in the
384 same order as within the configuration."""
385 return self.top_block
386
387 def load_config(self, filename, replace=True):
388 """Loads symbol values from a file in the familiar .config format.
389 Equivalent to calling Symbol.set_user_value() to set each of the
390 values.
391
392 "# CONFIG_FOO is not set" within a .config file is treated specially
393 and sets the user value of FOO to 'n'. The C implementation works the
394 same way.
395
396 filename: The .config file to load. $-references to existing
397 environment variables will be expanded. For scripts to work even when
398 an alternative build directory is used with the Linux kernel, you
399 need to refer to the top-level kernel directory with "$srctree".
400
401 replace (default: True): True if the configuration should replace the
Simon Glass8639f692017-08-04 03:30:30 -0600402 old configuration; False if it should add to it.
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200403
Simon Glass8639f692017-08-04 03:30:30 -0600404 Returns a list or warnings (hopefully empty)
405 """
406
407 self._warnings = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200408 # Put this first so that a missing file doesn't screw up our state
409 filename = os.path.expandvars(filename)
410 line_feeder = _FileFeed(filename)
411
412 self.config_filename = filename
413
414 #
415 # Read header
416 #
417
418 def is_header_line(line):
419 return line is not None and line.startswith("#") and \
420 not _unset_re_match(line)
421
422 self.config_header = None
423
424 line = line_feeder.peek_next()
425 if is_header_line(line):
426 self.config_header = ""
427 while is_header_line(line_feeder.peek_next()):
428 self.config_header += line_feeder.get_next()[1:]
429 # Remove trailing newline
430 if self.config_header.endswith("\n"):
431 self.config_header = self.config_header[:-1]
432
433 #
434 # Read assignments. Hotspot for some workloads.
435 #
436
437 def warn_override(filename, linenr, name, old_user_val, new_user_val):
438 self._warn('overriding the value of {0}. '
439 'Old value: "{1}", new value: "{2}".'
440 .format(name, old_user_val, new_user_val),
441 filename, linenr)
442
443 # Invalidate everything to keep things simple. It might be possible to
444 # improve performance for the case where multiple configurations are
445 # loaded by only invalidating a symbol (and its dependent symbols) if
446 # the new user value differs from the old. One complication would be
447 # that symbols not mentioned in the .config must lose their user value
448 # when replace = True, which is the usual case.
449 if replace:
450 self.unset_user_values()
451 else:
452 self._invalidate_all()
453
454 while 1:
455 line = line_feeder.get_next()
456 if line is None:
Simon Glass8639f692017-08-04 03:30:30 -0600457 return self._warnings
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200458
459 line = line.rstrip()
460
461 set_match = _set_re_match(line)
462 if set_match:
463 name, val = set_match.groups()
464
465 if val.startswith('"'):
466 if len(val) < 2 or val[-1] != '"':
467 _parse_error(line, "malformed string literal",
468 line_feeder.filename, line_feeder.linenr)
469 # Strip quotes and remove escapings. The unescaping
470 # procedure should be safe since " can only appear as \"
471 # inside the string.
472 val = val[1:-1].replace('\\"', '"').replace("\\\\", "\\")
473
474 if name in self.syms:
475 sym = self.syms[name]
476 if sym.user_val is not None:
477 warn_override(line_feeder.filename, line_feeder.linenr,
478 name, sym.user_val, val)
479
480 if sym.is_choice_sym:
481 user_mode = sym.parent.user_mode
482 if user_mode is not None and user_mode != val:
483 self._warn("assignment to {0} changes mode of "
484 'containing choice from "{1}" to "{2}".'
485 .format(name, val, user_mode),
486 line_feeder.filename,
487 line_feeder.linenr)
488
489 sym._set_user_value_no_invalidate(val, True)
490 else:
491 if self.print_undef_assign:
492 _stderr_msg('note: attempt to assign the value "{0}" '
493 "to the undefined symbol {1}."
494 .format(val, name),
495 line_feeder.filename, line_feeder.linenr)
496 else:
497 unset_match = _unset_re_match(line)
498 if unset_match:
499 name = unset_match.group(1)
500 if name in self.syms:
501 sym = self.syms[name]
502 if sym.user_val is not None:
503 warn_override(line_feeder.filename,
504 line_feeder.linenr,
505 name, sym.user_val, "n")
506
507 sym._set_user_value_no_invalidate("n", True)
508
509 def write_config(self, filename, header=None):
510 """Writes out symbol values in the familiar .config format.
511
512 Kconfiglib makes sure the format matches what the C implementation
513 would generate, down to whitespace. This eases testing.
514
515 filename: The filename under which to save the configuration.
516
517 header (default: None): A textual header that will appear at the
518 beginning of the file, with each line commented out automatically.
519 None means no header."""
520
521 for sym in self.syms_iter():
522 sym.already_written = False
523
524 with open(filename, "w") as f:
525 # Write header
526 if header is not None:
527 f.write(_comment(header))
528 f.write("\n")
529
530 # Build and write configuration
531 conf_strings = []
532 _make_block_conf(self.top_block, conf_strings.append)
533 f.write("\n".join(conf_strings))
534 f.write("\n")
535
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900536 def eval(self, s):
537 """Returns the value of the expression 's' -- where 's' is represented
538 as a string -- in the context of the configuration. Raises
539 Kconfig_Syntax_Error if syntax errors are detected in 's'.
540
541 For example, if FOO and BAR are tristate symbols at least one of which
542 has the value "y", then config.eval("y && (FOO || BAR)") => "y"
543
Masahiro Yamada9d01b782015-05-27 11:39:22 +0900544 This function always yields a tristate value. To get the value of
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900545 non-bool, non-tristate symbols, use Symbol.get_value().
546
547 The result of this function is consistent with how evaluation works for
548 conditional expressions in the configuration as well as in the C
549 implementation. "m" and m are rewritten as '"m" && MODULES' and 'm &&
550 MODULES', respectively, and a result of "m" will get promoted to "y" if
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200551 we're running without modules.
552
553 Syntax checking is somewhat lax, partly to be compatible with lax
554 parsing in the C implementation."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900555 return self._eval_expr(self._parse_expr(self._tokenize(s, True), # Feed
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200556 None, # Current symbol/choice
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900557 s)) # line
558
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200559 def unset_user_values(self):
560 """Resets the values of all symbols, as if Config.load_config() or
561 Symbol.set_user_value() had never been called."""
562 for sym in self.syms_iter():
563 sym._unset_user_value_no_recursive_invalidate()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900564
565 def set_print_warnings(self, print_warnings):
566 """Determines whether warnings related to this configuration (for
567 things like attempting to assign illegal values to symbols with
568 Symbol.set_user_value()) should be printed to stderr.
569
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200570 print_warnings: True if warnings should be printed."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900571 self.print_warnings = print_warnings
572
573 def set_print_undef_assign(self, print_undef_assign):
574 """Determines whether informational messages related to assignments to
575 undefined symbols should be printed to stderr for this configuration.
576
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200577 print_undef_assign: If True, such messages will be printed."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900578 self.print_undef_assign = print_undef_assign
579
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900580 def __str__(self):
581 """Returns a string containing various information about the Config."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200582 return _lines("Configuration",
583 "File : " +
584 self.filename,
585 "Base directory : " +
586 self.base_dir,
587 "Value of $ARCH at creation time : " +
588 ("(not set)" if self.arch is None else self.arch),
589 "Value of $SRCARCH at creation time : " +
590 ("(not set)" if self.srcarch is None else
591 self.srcarch),
592 "Source tree (derived from $srctree;",
593 "defaults to '.' if $srctree isn't set) : " +
594 self.srctree,
595 "Most recently loaded .config : " +
596 ("(no .config loaded)"
597 if self.config_filename is None else
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900598 self.config_filename),
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200599 "Print warnings : " +
600 BOOL_STR[self.print_warnings],
601 "Print assignments to undefined symbols : " +
602 BOOL_STR[self.print_undef_assign])
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900603
604 #
605 # Private methods
606 #
607
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900608 #
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200609 # Kconfig parsing
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900610 #
611
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200612 def _parse_file(self, filename, parent, deps, visible_if_deps, res=None):
613 """Parses the Kconfig file 'filename'. Returns a list with the Items in
614 the file. See _parse_block() for the meaning of the parameters."""
615 return self._parse_block(_FileFeed(filename), None, parent, deps,
616 visible_if_deps, res)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900617
618 def _parse_block(self, line_feeder, end_marker, parent, deps,
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200619 visible_if_deps, res=None):
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900620 """Parses a block, which is the contents of either a file or an if,
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200621 menu, or choice statement. Returns a list with the Items in the block.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900622
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200623 line_feeder: A _FileFeed instance feeding lines from a file. The
624 Kconfig language is line-based in practice.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900625
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200626 end_marker: The token that ends the block, e.g. T_ENDIF ("endif") for
627 ifs. None for files.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900628
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200629 parent: The enclosing menu or choice, or None if we're at the top
630 level.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900631
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200632 deps: Dependencies from enclosing menus, choices and ifs.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900633
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200634 visible_if_deps (default: None): 'visible if' dependencies from
635 enclosing menus.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900636
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200637 res (default: None): The list to add items to. If None, a new list is
638 created to hold the items."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900639
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200640 block = [] if res is None else res
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900641
642 while 1:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900643 # Do we already have a tokenized line that we determined wasn't
644 # part of whatever we were parsing earlier? See comment in
645 # Config.__init__().
646 if self.end_line is not None:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900647 line = self.end_line
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200648 tokens = self.end_line_tokens
649 tokens.unget_all()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900650
651 self.end_line = None
652 self.end_line_tokens = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900653 else:
654 line = line_feeder.get_next()
655 if line is None:
656 if end_marker is not None:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200657 raise Kconfig_Syntax_Error("Unexpected end of file {0}"
658 .format(line_feeder.filename))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900659 return block
660
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200661 tokens = self._tokenize(line, False, line_feeder.filename,
662 line_feeder.linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900663
664 t0 = tokens.get_next()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200665 if t0 is None:
666 continue
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900667
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200668 # Cases are ordered roughly by frequency, which speeds things up a
669 # bit
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900670
671 if t0 == T_CONFIG or t0 == T_MENUCONFIG:
672 # The tokenizer will automatically allocate a new Symbol object
673 # for any new names it encounters, so we don't need to worry
674 # about that here.
675 sym = tokens.get_next()
676
677 # Symbols defined in multiple places get the parent of their
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200678 # first definition. However, for symbols whose parents are
679 # choice statements, the choice statement takes precedence.
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900680 if not sym.is_defined_ or isinstance(parent, Choice):
681 sym.parent = parent
682
683 sym.is_defined_ = True
684
685 self.kconfig_syms.append(sym)
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200686 block.append(sym)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900687
688 self._parse_properties(line_feeder, sym, deps, visible_if_deps)
689
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200690 elif t0 == T_SOURCE:
691 kconfig_file = tokens.get_next()
692 exp_kconfig_file = self._expand_sym_refs(kconfig_file)
693 f = os.path.join(self.base_dir, exp_kconfig_file)
694 if not os.path.exists(f):
695 raise IOError('{0}:{1}: sourced file "{2}" (expands to '
696 '"{3}") not found. Perhaps base_dir '
697 '(argument to Config.__init__(), currently '
698 '"{4}") is set to the wrong value.'
699 .format(line_feeder.filename,
700 line_feeder.linenr,
701 kconfig_file, exp_kconfig_file,
702 self.base_dir))
703 # Add items to the same block
704 self._parse_file(f, parent, deps, visible_if_deps, block)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900705
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200706 elif t0 == end_marker:
707 # We have reached the end of the block
708 return block
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900709
710 elif t0 == T_IF:
711 # If statements are treated as syntactic sugar for adding
712 # dependencies to enclosed items and do not have an explicit
713 # object representation.
714
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200715 dep_expr = self._parse_expr(tokens, None, line,
716 line_feeder.filename,
717 line_feeder.linenr)
718 # Add items to the same block
719 self._parse_block(line_feeder, T_ENDIF, parent,
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900720 _make_and(dep_expr, deps),
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200721 visible_if_deps, block)
722
723 elif t0 == T_COMMENT:
724 comment = Comment()
725
726 comment.config = self
727 comment.parent = parent
728 comment.filename = line_feeder.filename
729 comment.linenr = line_feeder.linenr
730 comment.text = tokens.get_next()
731
732 self.comments.append(comment)
733 block.append(comment)
734
735 self._parse_properties(line_feeder, comment, deps,
736 visible_if_deps)
737
738 elif t0 == T_MENU:
739 menu = Menu()
740
741 menu.config = self
742 menu.parent = parent
743 menu.filename = line_feeder.filename
744 menu.linenr = line_feeder.linenr
745 menu.title = tokens.get_next()
746
747 self.menus.append(menu)
748 block.append(menu)
749
750 # Parse properties and contents
751 self._parse_properties(line_feeder, menu, deps,
752 visible_if_deps)
753 menu.block = self._parse_block(line_feeder, T_ENDMENU, menu,
754 menu.dep_expr,
755 _make_and(visible_if_deps,
756 menu.visible_if_expr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900757
758 elif t0 == T_CHOICE:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200759 name = tokens.get_next()
760 if name is None:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900761 choice = Choice()
762 self.choices.append(choice)
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200763 else:
764 # Named choice
765 choice = self.named_choices.get(name)
766 if choice is None:
767 choice = Choice()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900768 choice.name = name
769 self.named_choices[name] = choice
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200770 self.choices.append(choice)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900771
772 choice.config = self
773 choice.parent = parent
774
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200775 choice.def_locations.append((line_feeder.filename,
776 line_feeder.linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900777
778 # Parse properties and contents
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200779 self._parse_properties(line_feeder, choice, deps,
780 visible_if_deps)
781 choice.block = self._parse_block(line_feeder, T_ENDCHOICE,
782 choice, deps, visible_if_deps)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900783
784 choice._determine_actual_symbols()
785
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200786 # If no type is specified for the choice, its type is that of
787 # the first choice item with a specified type
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900788 if choice.type == UNKNOWN:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200789 for item in choice.actual_symbols:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900790 if item.type != UNKNOWN:
791 choice.type = item.type
792 break
793
794 # Each choice item of UNKNOWN type gets the type of the choice
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200795 for item in choice.actual_symbols:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900796 if item.type == UNKNOWN:
797 item.type = choice.type
798
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200799 block.append(choice)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900800
801 elif t0 == T_MAINMENU:
802 text = tokens.get_next()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900803 if self.mainmenu_text is not None:
804 self._warn("overriding 'mainmenu' text. "
805 'Old value: "{0}", new value: "{1}".'
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200806 .format(self.mainmenu_text, text),
807 line_feeder.filename, line_feeder.linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900808 self.mainmenu_text = text
809
810 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200811 _parse_error(line, "unrecognized construct",
812 line_feeder.filename, line_feeder.linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900813
814 def _parse_properties(self, line_feeder, stmt, deps, visible_if_deps):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200815 """Parsing of properties for symbols, menus, choices, and comments.
816 Takes care of propagating dependencies from enclosing menus and ifs."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900817
818 def parse_val_and_cond(tokens, line, filename, linenr):
819 """Parses '<expr1> if <expr2>' constructs, where the 'if' part is
820 optional. Returns a tuple containing the parsed expressions, with
821 None as the second element if the 'if' part is missing."""
822 val = self._parse_expr(tokens, stmt, line, filename, linenr, False)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900823 if tokens.check(T_IF):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200824 return (val, self._parse_expr(tokens, stmt, line, filename,
825 linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900826 return (val, None)
827
828 # In case the symbol is defined in multiple locations, we need to
829 # remember what prompts, defaults, and selects are new for this
830 # definition, as "depends on" should only apply to the local
831 # definition.
832 new_prompt = None
833 new_def_exprs = []
834 new_selects = []
835
836 # Dependencies from 'depends on' statements
837 depends_on_expr = None
838
839 while 1:
840 line = line_feeder.get_next()
841 if line is None:
842 break
843
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200844 filename = line_feeder.filename
845 linenr = line_feeder.linenr
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900846
847 tokens = self._tokenize(line, False, filename, linenr)
848
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200849 t0 = tokens.get_next()
850 if t0 is None:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900851 continue
852
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200853 # Cases are ordered roughly by frequency, which speeds things up a
854 # bit
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900855
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200856 if t0 == T_DEPENDS:
857 if not tokens.check(T_ON):
858 _parse_error(line, 'expected "on" after "depends"',
859 filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900860
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200861 parsed_deps = self._parse_expr(tokens, stmt, line, filename,
862 linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900863
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200864 if isinstance(stmt, (Menu, Comment)):
865 stmt.orig_deps = _make_and(stmt.orig_deps, parsed_deps)
866 else:
867 depends_on_expr = _make_and(depends_on_expr, parsed_deps)
868
869 elif t0 == T_HELP:
870 # Find first non-blank (not all-space) line and get its
871 # indentation
872 line = line_feeder.next_nonblank()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900873 if line is None:
874 stmt.help = ""
875 break
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900876 indent = _indentation(line)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900877 if indent == 0:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200878 # If the first non-empty lines has zero indent, there is no
879 # help text
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900880 stmt.help = ""
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200881 line_feeder.unget()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900882 break
883
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900884 # The help text goes on till the first non-empty line with less
885 # indent
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200886 help_lines = [_deindent(line, indent)]
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900887 while 1:
888 line = line_feeder.get_next()
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200889 if line is None or \
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900890 (not line.isspace() and _indentation(line) < indent):
891 stmt.help = "".join(help_lines)
892 break
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900893 help_lines.append(_deindent(line, indent))
894
895 if line is None:
896 break
897
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200898 line_feeder.unget()
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900899
Tom Rinid0361072017-03-03 15:33:29 -0500900 elif t0 == T_SELECT or t0 == T_IMPLY:
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900901 target = tokens.get_next()
902
903 stmt.referenced_syms.add(target)
904 stmt.selected_syms.add(target)
905
906 if tokens.check(T_IF):
907 new_selects.append((target,
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200908 self._parse_expr(tokens, stmt, line,
909 filename, linenr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900910 else:
911 new_selects.append((target, None))
912
913 elif t0 in (T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200914 stmt.type = TOKEN_TO_TYPE[t0]
915 if tokens.peek_next() is not None:
916 new_prompt = parse_val_and_cond(tokens, line, filename,
917 linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900918
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200919 elif t0 == T_DEFAULT:
920 new_def_exprs.append(parse_val_and_cond(tokens, line, filename,
921 linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900922
923 elif t0 == T_DEF_BOOL:
924 stmt.type = BOOL
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200925 if tokens.peek_next() is not None:
926 new_def_exprs.append(parse_val_and_cond(tokens, line,
927 filename, linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900928
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200929 elif t0 == T_PROMPT:
930 # 'prompt' properties override each other within a single
931 # definition of a symbol, but additional prompts can be added
932 # by defining the symbol multiple times; hence 'new_prompt'
933 # instead of 'prompt'.
934 new_prompt = parse_val_and_cond(tokens, line, filename, linenr)
935
936 elif t0 == T_RANGE:
937 low = tokens.get_next()
938 high = tokens.get_next()
939 stmt.referenced_syms.add(low)
940 stmt.referenced_syms.add(high)
941
942 if tokens.check(T_IF):
943 stmt.ranges.append((low, high,
944 self._parse_expr(tokens, stmt, line,
945 filename, linenr)))
946 else:
947 stmt.ranges.append((low, high, None))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900948
949 elif t0 == T_DEF_TRISTATE:
950 stmt.type = TRISTATE
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200951 if tokens.peek_next() is not None:
952 new_def_exprs.append(parse_val_and_cond(tokens, line,
953 filename, linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900954
955 elif t0 == T_OPTION:
956 if tokens.check(T_ENV) and tokens.check(T_EQUAL):
957 env_var = tokens.get_next()
958
959 stmt.is_special_ = True
960 stmt.is_from_env = True
961
962 if env_var not in os.environ:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200963 self._warn("The symbol {0} references the "
964 "non-existent environment variable {1} and "
965 "will get the empty string as its value. "
966 "If you're using Kconfiglib via "
967 "'make (i)scriptconfig', it should have "
968 "set up the environment correctly for you. "
969 "If you still got this message, that "
970 "might be an error, and you should email "
971 "ulfalizer a.t Google's email service."""
972 .format(stmt.name, env_var),
973 filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900974
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200975 stmt.cached_val = ""
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900976 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200977 stmt.cached_val = os.environ[env_var]
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900978
979 elif tokens.check(T_DEFCONFIG_LIST):
980 self.defconfig_sym = stmt
981
982 elif tokens.check(T_MODULES):
Ulf Magnusson90c36d82015-08-13 19:55:40 +0200983 # To reduce warning spam, only warn if 'option modules' is
984 # set on some symbol that isn't MODULES, which should be
985 # safe. I haven't run into any projects that make use
986 # modules besides the kernel yet, and there it's likely to
987 # keep being called "MODULES".
988 if stmt.name != "MODULES":
989 self._warn("the 'modules' option is not supported. "
990 "Let me know if this is a problem for you; "
991 "it shouldn't be that hard to implement. "
992 "(Note that modules are still supported -- "
993 "Kconfiglib just assumes the symbol name "
994 "MODULES, like older versions of the C "
995 "implementation did when 'option modules' "
996 "wasn't used.)",
997 filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +0900998
Masahiro Yamada9d01b782015-05-27 11:39:22 +0900999 elif tokens.check(T_ALLNOCONFIG_Y):
1000 if not isinstance(stmt, Symbol):
1001 _parse_error(line,
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001002 "the 'allnoconfig_y' option is only "
1003 "valid for symbols",
1004 filename, linenr)
Masahiro Yamada9d01b782015-05-27 11:39:22 +09001005 stmt.allnoconfig_y = True
1006
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001007 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001008 _parse_error(line, "unrecognized option", filename, linenr)
1009
1010 elif t0 == T_VISIBLE:
1011 if not tokens.check(T_IF):
1012 _parse_error(line, 'expected "if" after "visible"',
1013 filename, linenr)
1014 if not isinstance(stmt, Menu):
1015 _parse_error(line,
1016 "'visible if' is only valid for menus",
1017 filename, linenr)
1018
1019 parsed_deps = self._parse_expr(tokens, stmt, line, filename,
1020 linenr)
1021 stmt.visible_if_expr = _make_and(stmt.visible_if_expr,
1022 parsed_deps)
1023
1024 elif t0 == T_OPTIONAL:
1025 if not isinstance(stmt, Choice):
1026 _parse_error(line,
1027 '"optional" is only valid for choices',
1028 filename,
1029 linenr)
1030 stmt.optional = True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001031
1032 else:
1033 # See comment in Config.__init__()
1034 self.end_line = line
1035 self.end_line_tokens = tokens
1036 break
1037
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001038 # Done parsing properties. Now propagate 'depends on' and enclosing
1039 # menu/if dependencies to expressions.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001040
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001041 # The set of symbols referenced directly by the statement plus all
1042 # symbols referenced by enclosing menus and ifs
1043 stmt.all_referenced_syms = stmt.referenced_syms | _get_expr_syms(deps)
1044
1045 # Save original dependencies from enclosing menus and ifs
1046 stmt.deps_from_containing = deps
1047
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001048 if isinstance(stmt, (Menu, Comment)):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001049 stmt.dep_expr = _make_and(stmt.orig_deps, deps)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001050 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001051 # Symbol or Choice
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001052
1053 # See comment for 'menu_dep'
1054 stmt.menu_dep = depends_on_expr
1055
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001056 # Propagate dependencies to prompts
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001057
1058 if new_prompt is not None:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001059 # Propagate 'visible if' dependencies from enclosing menus
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001060 prompt, cond_expr = new_prompt
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001061 cond_expr = _make_and(cond_expr, visible_if_deps)
1062 # Propagate 'depends on' dependencies
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001063 new_prompt = (prompt, _make_and(cond_expr, depends_on_expr))
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001064 # Save original
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001065 stmt.orig_prompts.append(new_prompt)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001066 # Finalize with dependencies from enclosing menus and ifs
1067 stmt.prompts.append((new_prompt[0],
1068 _make_and(new_prompt[1], deps)))
1069
1070 # Propagate dependencies to defaults
1071
1072 # Propagate 'depends on' dependencies
1073 new_def_exprs = [(val_expr, _make_and(cond_expr, depends_on_expr))
1074 for val_expr, cond_expr in new_def_exprs]
1075 # Save original
1076 stmt.orig_def_exprs.extend(new_def_exprs)
1077 # Finalize with dependencies from enclosing menus and ifs
1078 stmt.def_exprs.extend([(val_expr, _make_and(cond_expr, deps))
1079 for val_expr, cond_expr in new_def_exprs])
1080
1081 # Propagate dependencies to selects
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001082
1083 # Only symbols can select
1084 if isinstance(stmt, Symbol):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001085 # Propagate 'depends on' dependencies
1086 new_selects = [(target, _make_and(cond_expr, depends_on_expr))
1087 for target, cond_expr in new_selects]
1088 # Save original
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001089 stmt.orig_selects.extend(new_selects)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001090 # Finalize with dependencies from enclosing menus and ifs
1091 for target, cond in new_selects:
1092 target.rev_dep = _make_or(target.rev_dep,
1093 _make_and(stmt,
1094 _make_and(cond, deps)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001095
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001096 def _parse_expr(self, feed, cur_item, line, filename=None, linenr=None,
1097 transform_m=True):
1098 """Parses an expression from the tokens in 'feed' using a simple
1099 top-down approach. The result has the form
1100 '(<operator>, [<parsed operands>])', where <operator> is e.g.
1101 kconfiglib.AND. If there is only one operand (i.e., no && or ||), then
1102 the operand is returned directly. This also goes for subexpressions.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001103
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001104 feed: _Feed instance containing the tokens for the expression.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001105
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001106 cur_item: The item (Symbol, Choice, Menu, or Comment) currently being
1107 parsed, or None if we're not parsing an item. Used for recording
1108 references to symbols.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001109
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001110 line: The line containing the expression being parsed.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001111
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001112 filename (default: None): The file containing the expression.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001113
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001114 linenr (default: None): The line number containing the expression.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001115
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001116 transform_m (default: False): Determines if 'm' should be rewritten to
1117 'm && MODULES' -- see parse_val_and_cond().
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001118
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001119 Expression grammar, in decreasing order of precedence:
1120
1121 <expr> -> <symbol>
1122 <symbol> '=' <symbol>
1123 <symbol> '!=' <symbol>
1124 '(' <expr> ')'
1125 '!' <expr>
1126 <expr> '&&' <expr>
1127 <expr> '||' <expr>"""
1128
1129 # Use instance variables to avoid having to pass these as arguments
1130 # through the top-down parser in _parse_expr_rec(), which is tedious
1131 # and obfuscates the code. A profiler run shows no noticeable
1132 # performance difference.
1133 self._cur_item = cur_item
1134 self._transform_m = transform_m
1135 self._line = line
1136 self._filename = filename
1137 self._linenr = linenr
1138
1139 return self._parse_expr_rec(feed)
1140
1141 def _parse_expr_rec(self, feed):
1142 or_term = self._parse_or_term(feed)
1143 if not feed.check(T_OR):
1144 # Common case -- no need for an OR node since it's just a single
1145 # operand
1146 return or_term
1147 or_terms = [or_term, self._parse_or_term(feed)]
1148 while feed.check(T_OR):
1149 or_terms.append(self._parse_or_term(feed))
1150 return (OR, or_terms)
1151
1152 def _parse_or_term(self, feed):
1153 and_term = self._parse_factor(feed)
1154 if not feed.check(T_AND):
1155 # Common case -- no need for an AND node since it's just a single
1156 # operand
1157 return and_term
1158 and_terms = [and_term, self._parse_factor(feed)]
1159 while feed.check(T_AND):
1160 and_terms.append(self._parse_factor(feed))
1161 return (AND, and_terms)
1162
1163 def _parse_factor(self, feed):
1164 token = feed.get_next()
1165
1166 if isinstance(token, (Symbol, str)):
1167 if self._cur_item is not None and isinstance(token, Symbol):
1168 self._cur_item.referenced_syms.add(token)
1169
1170 next_token = feed.peek_next()
1171 # For conditional expressions ('depends on <expr>',
1172 # '... if <expr>', # etc.), "m" and m are rewritten to
1173 # "m" && MODULES.
1174 if next_token != T_EQUAL and next_token != T_UNEQUAL:
1175 if self._transform_m and (token is self.m or token == "m"):
1176 return (AND, ["m", self._sym_lookup("MODULES")])
1177 return token
1178
1179 relation = EQUAL if (feed.get_next() == T_EQUAL) else UNEQUAL
1180 token_2 = feed.get_next()
1181 if self._cur_item is not None and isinstance(token_2, Symbol):
1182 self._cur_item.referenced_syms.add(token_2)
1183 return (relation, token, token_2)
1184
1185 if token == T_NOT:
1186 return (NOT, self._parse_factor(feed))
1187
1188 if token == T_OPEN_PAREN:
1189 expr_parse = self._parse_expr_rec(feed)
1190 if not feed.check(T_CLOSE_PAREN):
1191 _parse_error(self._line, "missing end parenthesis",
1192 self._filename, self._linenr)
1193 return expr_parse
1194
1195 _parse_error(self._line, "malformed expression", self._filename,
1196 self._linenr)
1197
1198 def _tokenize(self, s, for_eval, filename=None, linenr=None):
1199 """Returns a _Feed instance containing tokens derived from the string
1200 's'. Registers any new symbols encountered (via _sym_lookup()).
1201
1202 (I experimented with a pure regular expression implementation, but it
1203 came out slower, less readable, and wouldn't have been as flexible.)
1204
1205 for_eval: True when parsing an expression for a call to Config.eval(),
1206 in which case we should not treat the first token specially nor
1207 register new symbols."""
1208
1209 s = s.strip()
1210 if s == "" or s[0] == "#":
1211 return _Feed([])
1212
1213 if for_eval:
1214 previous = None # The previous token seen
1215 tokens = []
1216 i = 0 # The current index in the string being tokenized
1217
1218 else:
1219 # The initial word on a line is parsed specially. Let
1220 # command_chars = [A-Za-z0-9_]. Then
1221 # - leading non-command_chars characters are ignored, and
1222 # - the first token consists the following one or more
1223 # command_chars characters.
1224 # This is why things like "----help--" are accepted.
1225 initial_token_match = _initial_token_re_match(s)
1226 if initial_token_match is None:
1227 return _Feed([])
1228 keyword = _get_keyword(initial_token_match.group(1))
1229 if keyword == T_HELP:
1230 # Avoid junk after "help", e.g. "---", being registered as a
1231 # symbol
1232 return _Feed([T_HELP])
1233 if keyword is None:
1234 # We expect a keyword as the first token
1235 _tokenization_error(s, filename, linenr)
1236
1237 previous = keyword
1238 tokens = [keyword]
1239 # The current index in the string being tokenized
1240 i = initial_token_match.end()
1241
1242 # _tokenize() is a hotspot during parsing, and this speeds things up a
1243 # bit
1244 strlen = len(s)
1245 append = tokens.append
1246
1247 # Main tokenization loop. (Handles tokens past the first one.)
1248 while i < strlen:
1249 # Test for an identifier/keyword preceded by whitespace first; this
1250 # is the most common case.
1251 id_keyword_match = _id_keyword_re_match(s, i)
1252 if id_keyword_match:
1253 # We have an identifier or keyword. The above also stripped any
1254 # whitespace for us.
1255 name = id_keyword_match.group(1)
1256 # Jump past it
1257 i = id_keyword_match.end()
1258
1259 keyword = _get_keyword(name)
1260 if keyword is not None:
1261 # It's a keyword
1262 append(keyword)
1263 elif previous in STRING_LEX:
1264 # What would ordinarily be considered an identifier is
1265 # treated as a string after certain tokens
1266 append(name)
1267 else:
1268 # It's a symbol name. _sym_lookup() will take care of
1269 # allocating a new Symbol instance if it's the first time
1270 # we see it.
1271 sym = self._sym_lookup(name, for_eval)
1272
1273 if previous == T_CONFIG or previous == T_MENUCONFIG:
1274 # If the previous token is T_(MENU)CONFIG
1275 # ("(menu)config"), we're tokenizing the first line of
1276 # a symbol definition, and should remember this as a
1277 # location where the symbol is defined
1278 sym.def_locations.append((filename, linenr))
1279 else:
1280 # Otherwise, it's a reference to the symbol
1281 sym.ref_locations.append((filename, linenr))
1282
1283 append(sym)
1284
1285 else:
1286 # Not an identifier/keyword
1287
1288 while i < strlen and s[i].isspace():
1289 i += 1
1290 if i == strlen:
1291 break
1292 c = s[i]
1293 i += 1
1294
1295 # String literal (constant symbol)
1296 if c == '"' or c == "'":
1297 if "\\" in s:
1298 # Slow path: This could probably be sped up, but it's a
1299 # very unusual case anyway.
1300 quote = c
1301 val = ""
1302 while 1:
1303 if i >= len(s):
1304 _tokenization_error(s, filename, linenr)
1305 c = s[i]
1306 if c == quote:
1307 break
1308 if c == "\\":
1309 if i + 1 >= len(s):
1310 _tokenization_error(s, filename, linenr)
1311 val += s[i + 1]
1312 i += 2
1313 else:
1314 val += c
1315 i += 1
1316 i += 1
1317 append(val)
1318 else:
1319 # Fast path: If the string contains no backslashes
1320 # (almost always) we can simply look for the matching
1321 # quote.
1322 end = s.find(c, i)
1323 if end == -1:
1324 _tokenization_error(s, filename, linenr)
1325 append(s[i:end])
1326 i = end + 1
1327
1328 elif c == "&":
1329 # Invalid characters are ignored
1330 if i >= len(s) or s[i] != "&": continue
1331 append(T_AND)
1332 i += 1
1333
1334 elif c == "|":
1335 # Invalid characters are ignored
1336 if i >= len(s) or s[i] != "|": continue
1337 append(T_OR)
1338 i += 1
1339
1340 elif c == "!":
1341 if i < len(s) and s[i] == "=":
1342 append(T_UNEQUAL)
1343 i += 1
1344 else:
1345 append(T_NOT)
1346
1347 elif c == "=": append(T_EQUAL)
1348 elif c == "(": append(T_OPEN_PAREN)
1349 elif c == ")": append(T_CLOSE_PAREN)
1350 elif c == "#": break # Comment
1351
1352 else: continue # Invalid characters are ignored
1353
1354 previous = tokens[-1]
1355
1356 return _Feed(tokens)
1357
1358 def _sym_lookup(self, name, for_eval=False):
1359 """Fetches the symbol 'name' from the symbol table, creating and
1360 registering it if it does not exist. If 'for_eval' is True, the symbol
1361 won't be added to the symbol table if it does not exist -- this is for
1362 Config.eval()."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001363 if name in self.syms:
1364 return self.syms[name]
1365
1366 new_sym = Symbol()
1367 new_sym.config = self
1368 new_sym.name = name
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001369 if for_eval:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001370 self._warn("no symbol {0} in configuration".format(name))
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001371 else:
1372 self.syms[name] = new_sym
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001373 return new_sym
1374
1375 #
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001376 # Expression evaluation
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001377 #
1378
1379 def _eval_expr(self, expr):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001380 """Evaluates an expression to "n", "m", or "y"."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001381
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001382 # Handles e.g. an "x if y" condition where the "if y" part is missing.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001383 if expr is None:
1384 return "y"
1385
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001386 res = self._eval_expr_rec(expr)
1387 if res == "m":
1388 # Promote "m" to "y" if we're running without modules.
1389 #
1390 # Internally, "m" is often rewritten to "m" && MODULES by both the
1391 # C implementation and Kconfiglib, which takes care of cases where
1392 # "m" should be demoted to "n" instead.
1393 modules_sym = self.syms.get("MODULES")
1394 if modules_sym is None or modules_sym.get_value() != "y":
1395 return "y"
1396 return res
1397
1398 def _eval_expr_rec(self, expr):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001399 if isinstance(expr, Symbol):
1400 # Non-bool/tristate symbols are always "n" in a tristate sense,
1401 # regardless of their value
1402 if expr.type != BOOL and expr.type != TRISTATE:
1403 return "n"
1404 return expr.get_value()
1405
1406 if isinstance(expr, str):
1407 return expr if (expr == "y" or expr == "m") else "n"
1408
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001409 # Ordered by frequency
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001410
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001411 if expr[0] == AND:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001412 res = "y"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001413 for subexpr in expr[1]:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001414 ev = self._eval_expr_rec(subexpr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001415 # Return immediately upon discovering an "n" term
1416 if ev == "n":
1417 return "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001418 if ev == "m":
1419 res = "m"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001420 # 'res' is either "m" or "y" here; we already handled the
1421 # short-circuiting "n" case in the loop.
1422 return res
1423
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001424 if expr[0] == NOT:
1425 ev = self._eval_expr_rec(expr[1])
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001426 if ev == "y":
1427 return "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001428 return "y" if (ev == "n") else "m"
1429
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001430 if expr[0] == OR:
1431 res = "n"
1432 for subexpr in expr[1]:
1433 ev = self._eval_expr_rec(subexpr)
1434 # Return immediately upon discovering a "y" term
1435 if ev == "y":
1436 return "y"
1437 if ev == "m":
1438 res = "m"
1439 # 'res' is either "n" or "m" here; we already handled the
1440 # short-circuiting "y" case in the loop.
1441 return res
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001442
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001443 if expr[0] == EQUAL:
1444 return "y" if (_str_val(expr[1]) == _str_val(expr[2])) else "n"
1445
1446 if expr[0] == UNEQUAL:
1447 return "y" if (_str_val(expr[1]) != _str_val(expr[2])) else "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001448
1449 _internal_error("Internal error while evaluating expression: "
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001450 "unknown operation {0}.".format(expr[0]))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001451
1452 def _eval_min(self, e1, e2):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001453 """Returns the minimum value of the two expressions. Equates None with
1454 'y'."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001455 e1_eval = self._eval_expr(e1)
1456 e2_eval = self._eval_expr(e2)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001457 return e1_eval if tri_less(e1_eval, e2_eval) else e2_eval
1458
1459 def _eval_max(self, e1, e2):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001460 """Returns the maximum value of the two expressions. Equates None with
1461 'y'."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001462 e1_eval = self._eval_expr(e1)
1463 e2_eval = self._eval_expr(e2)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001464 return e1_eval if tri_greater(e1_eval, e2_eval) else e2_eval
1465
1466 #
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001467 # Dependency tracking (for caching and invalidation)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001468 #
1469
1470 def _build_dep(self):
1471 """Populates the Symbol.dep sets, linking the symbol to the symbols
1472 that immediately depend on it in the sense that changing the value of
1473 the symbol might affect the values of those other symbols. This is used
1474 for caching/invalidation purposes. The calculated sets might be larger
1475 than necessary as we don't do any complicated analysis of the
1476 expressions."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001477
1478 # Adds 'sym' as a directly dependent symbol to all symbols that appear
1479 # in the expression 'e'
1480 def add_expr_deps(e, sym):
1481 for s in _get_expr_syms(e):
1482 s.dep.add(sym)
1483
1484 # The directly dependent symbols of a symbol are:
1485 # - Any symbols whose prompts, default values, rev_dep (select
1486 # condition), or ranges depend on the symbol
1487 # - Any symbols that belong to the same choice statement as the symbol
1488 # (these won't be included in 'dep' as that makes the dependency
1489 # graph unwieldy, but Symbol._get_dependent() will include them)
1490 # - Any symbols in a choice statement that depends on the symbol
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001491 for sym in self.syms_iter():
1492 for _, e in sym.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001493 add_expr_deps(e, sym)
1494
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001495 for v, e in sym.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001496 add_expr_deps(v, sym)
1497 add_expr_deps(e, sym)
1498
1499 add_expr_deps(sym.rev_dep, sym)
1500
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001501 for l, u, e in sym.ranges:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001502 add_expr_deps(l, sym)
1503 add_expr_deps(u, sym)
1504 add_expr_deps(e, sym)
1505
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001506 if sym.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001507 choice = sym.parent
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001508 for _, e in choice.prompts:
1509 add_expr_deps(e, sym)
1510 for _, e in choice.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001511 add_expr_deps(e, sym)
1512
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001513 def _eq_to_sym(self, eq):
1514 """_expr_depends_on() helper. For (in)equalities of the form sym = y/m
1515 or sym != n, returns sym. For other (in)equalities, returns None."""
1516 relation, left, right = eq
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001517
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001518 def transform_y_m_n(item):
1519 if item is self.y: return "y"
1520 if item is self.m: return "m"
1521 if item is self.n: return "n"
1522 return item
1523
1524 left = transform_y_m_n(left)
1525 right = transform_y_m_n(right)
1526
1527 # Make sure the symbol (if any) appears to the left
1528 if not isinstance(left, Symbol):
1529 left, right = right, left
1530 if not isinstance(left, Symbol):
1531 return None
1532 if (relation == EQUAL and (right == "y" or right == "m")) or \
1533 (relation == UNEQUAL and right == "n"):
1534 return left
1535 return None
1536
1537 def _expr_depends_on(self, expr, sym):
1538 """Reimplementation of expr_depends_symbol() from mconf.c. Used to
1539 determine if a submenu should be implicitly created, which influences
1540 what items inside choice statements are considered choice items."""
1541 if expr is None:
1542 return False
1543
1544 def rec(expr):
1545 if isinstance(expr, str):
1546 return False
1547 if isinstance(expr, Symbol):
1548 return expr is sym
1549
1550 if expr[0] in (EQUAL, UNEQUAL):
1551 return self._eq_to_sym(expr) is sym
1552 if expr[0] == AND:
1553 for and_expr in expr[1]:
1554 if rec(and_expr):
1555 return True
1556 return False
1557
1558 return rec(expr)
1559
1560 def _invalidate_all(self):
1561 for sym in self.syms_iter():
1562 sym._invalidate()
1563
1564 #
1565 # Printing and misc.
1566 #
1567
1568 def _expand_sym_refs(self, s):
1569 """Expands $-references to symbols in 's' to symbol values, or to the
1570 empty string for undefined symbols."""
1571
1572 while 1:
1573 sym_ref_match = _sym_ref_re_search(s)
1574 if sym_ref_match is None:
1575 return s
1576
1577 sym_name = sym_ref_match.group(0)[1:]
1578 sym = self.syms.get(sym_name)
1579 expansion = "" if sym is None else sym.get_value()
1580
1581 s = s[:sym_ref_match.start()] + \
1582 expansion + \
1583 s[sym_ref_match.end():]
1584
1585 def _expr_val_str(self, expr, no_value_str="(none)",
1586 get_val_instead_of_eval=False):
1587 """Printing helper. Returns a string with 'expr' and its value.
1588
1589 no_value_str: String to return when 'expr' is missing (None).
1590
1591 get_val_instead_of_eval: Assume 'expr' is a symbol or string (constant
1592 symbol) and get its value directly instead of evaluating it to a
1593 tristate value."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001594
1595 if expr is None:
1596 return no_value_str
1597
1598 if get_val_instead_of_eval:
1599 if isinstance(expr, str):
1600 return _expr_to_str(expr)
1601 val = expr.get_value()
1602 else:
1603 val = self._eval_expr(expr)
1604
1605 return "{0} (value: {1})".format(_expr_to_str(expr), _expr_to_str(val))
1606
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001607 def _get_sym_or_choice_str(self, sc):
1608 """Symbols and choices have many properties in common, so we factor out
1609 common __str__() stuff here. "sc" is short for "symbol or choice"."""
1610
1611 # As we deal a lot with string representations here, use some
1612 # convenient shorthand:
1613 s = _expr_to_str
1614
1615 #
1616 # Common symbol/choice properties
1617 #
1618
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001619 user_val_str = "(no user value)" if sc.user_val is None else \
1620 s(sc.user_val)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001621
1622 # Build prompts string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001623 if not sc.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001624 prompts_str = " (no prompts)"
1625 else:
1626 prompts_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001627 for prompt, cond_expr in sc.orig_prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001628 if cond_expr is None:
1629 prompts_str_rows.append(' "{0}"'.format(prompt))
1630 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001631 prompts_str_rows.append(
1632 ' "{0}" if {1}'.format(prompt,
1633 self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001634 prompts_str = "\n".join(prompts_str_rows)
1635
1636 # Build locations string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001637 if not sc.def_locations:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001638 locations_str = "(no locations)"
1639 else:
1640 locations_str = " ".join(["{0}:{1}".format(filename, linenr) for
1641 (filename, linenr) in sc.def_locations])
1642
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001643 # Build additional-dependencies-from-menus-and-ifs string
1644 additional_deps_str = " " + \
1645 self._expr_val_str(sc.deps_from_containing,
1646 "(no additional dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001647
1648 #
1649 # Symbol-specific stuff
1650 #
1651
1652 if isinstance(sc, Symbol):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001653 # Build ranges string
1654 if isinstance(sc, Symbol):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001655 if not sc.ranges:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001656 ranges_str = " (no ranges)"
1657 else:
1658 ranges_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001659 for l, u, cond_expr in sc.ranges:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001660 if cond_expr is None:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001661 ranges_str_rows.append(" [{0}, {1}]".format(s(l),
1662 s(u)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001663 else:
1664 ranges_str_rows.append(" [{0}, {1}] if {2}"
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001665 .format(s(l), s(u),
1666 self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001667 ranges_str = "\n".join(ranges_str_rows)
1668
1669 # Build default values string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001670 if not sc.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001671 defaults_str = " (no default values)"
1672 else:
1673 defaults_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001674 for val_expr, cond_expr in sc.orig_def_exprs:
1675 row_str = " " + self._expr_val_str(val_expr, "(none)",
1676 sc.type == STRING)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001677 defaults_str_rows.append(row_str)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001678 defaults_str_rows.append(" Condition: " +
1679 self._expr_val_str(cond_expr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001680 defaults_str = "\n".join(defaults_str_rows)
1681
1682 # Build selects string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001683 if not sc.orig_selects:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001684 selects_str = " (no selects)"
1685 else:
1686 selects_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001687 for target, cond_expr in sc.orig_selects:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001688 if cond_expr is None:
1689 selects_str_rows.append(" {0}".format(target.name))
1690 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001691 selects_str_rows.append(
1692 " {0} if {1}".format(target.name,
1693 self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001694 selects_str = "\n".join(selects_str_rows)
1695
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001696 res = _lines("Symbol " +
1697 ("(no name)" if sc.name is None else sc.name),
1698 "Type : " + TYPENAME[sc.type],
1699 "Value : " + s(sc.get_value()),
1700 "User value : " + user_val_str,
1701 "Visibility : " + s(_get_visibility(sc)),
1702 "Is choice item : " + BOOL_STR[sc.is_choice_sym],
1703 "Is defined : " + BOOL_STR[sc.is_defined_],
1704 "Is from env. : " + BOOL_STR[sc.is_from_env],
1705 "Is special : " + BOOL_STR[sc.is_special_] + "\n")
1706 if sc.ranges:
1707 res += _lines("Ranges:", ranges_str + "\n")
1708 res += _lines("Prompts:",
1709 prompts_str,
1710 "Default values:",
1711 defaults_str,
1712 "Selects:",
1713 selects_str,
1714 "Reverse (select-related) dependencies:",
1715 " (no reverse dependencies)" if sc.rev_dep == "n"
1716 else " " + self._expr_val_str(sc.rev_dep),
1717 "Additional dependencies from enclosing menus "
1718 "and ifs:",
1719 additional_deps_str,
1720 "Locations: " + locations_str)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001721
1722 return res
1723
1724 #
1725 # Choice-specific stuff
1726 #
1727
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001728 # Build selected symbol string
1729 sel = sc.get_selection()
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001730 sel_str = "(no selection)" if sel is None else sel.name
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001731
1732 # Build default values string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001733 if not sc.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001734 defaults_str = " (no default values)"
1735 else:
1736 defaults_str_rows = []
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001737 for sym, cond_expr in sc.orig_def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001738 if cond_expr is None:
1739 defaults_str_rows.append(" {0}".format(sym.name))
1740 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001741 defaults_str_rows.append(" {0} if {1}".format(sym.name,
1742 self._expr_val_str(cond_expr)))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001743 defaults_str = "\n".join(defaults_str_rows)
1744
1745 # Build contained symbols string
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001746 names = [sym.name for sym in sc.actual_symbols]
1747 syms_string = " ".join(names) if names else "(empty)"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001748
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001749 return _lines("Choice",
1750 "Name (for named choices): " +
1751 ("(no name)" if sc.name is None else sc.name),
1752 "Type : " + TYPENAME[sc.type],
1753 "Selected symbol : " + sel_str,
1754 "User value : " + user_val_str,
1755 "Mode : " + s(sc.get_mode()),
1756 "Visibility : " + s(_get_visibility(sc)),
1757 "Optional : " + BOOL_STR[sc.optional],
1758 "Prompts:",
1759 prompts_str,
1760 "Defaults:",
1761 defaults_str,
1762 "Choice symbols:",
1763 " " + syms_string,
1764 "Additional dependencies from enclosing menus and "
1765 "ifs:",
1766 additional_deps_str,
1767 "Locations: " + locations_str)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001768
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001769 def _warn(self, msg, filename=None, linenr=None):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001770 """For printing warnings to stderr."""
Simon Glass8639f692017-08-04 03:30:30 -06001771 msg = _build_msg("warning: " + msg, filename, linenr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001772 if self.print_warnings:
Simon Glass8639f692017-08-04 03:30:30 -06001773 sys.stderr.write(msg + "\n")
1774 self._warnings.append(msg)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001775
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001776class Item(object):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001777
1778 """Base class for symbols and other Kconfig constructs. Subclasses are
1779 Symbol, Choice, Menu, and Comment."""
1780
1781 def is_symbol(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001782 """Returns True if the item is a symbol. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001783 isinstance(item, kconfiglib.Symbol)."""
1784 return isinstance(self, Symbol)
1785
1786 def is_choice(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001787 """Returns True if the item is a choice. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001788 isinstance(item, kconfiglib.Choice)."""
1789 return isinstance(self, Choice)
1790
1791 def is_menu(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001792 """Returns True if the item is a menu. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001793 isinstance(item, kconfiglib.Menu)."""
1794 return isinstance(self, Menu)
1795
1796 def is_comment(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001797 """Returns True if the item is a comment. Short for
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001798 isinstance(item, kconfiglib.Comment)."""
1799 return isinstance(self, Comment)
1800
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001801class Symbol(Item):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001802
1803 """Represents a configuration symbol - e.g. FOO for
1804
1805 config FOO
1806 ..."""
1807
1808 #
1809 # Public interface
1810 #
1811
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001812 def get_config(self):
1813 """Returns the Config instance this symbol is from."""
1814 return self.config
1815
1816 def get_name(self):
1817 """Returns the name of the symbol."""
1818 return self.name
1819
1820 def get_type(self):
1821 """Returns the type of the symbol: one of UNKNOWN, BOOL, TRISTATE,
1822 STRING, HEX, or INT. These are defined at the top level of the module,
1823 so you'd do something like
1824
1825 if sym.get_type() == kconfiglib.STRING:
1826 ..."""
1827 return self.type
1828
1829 def get_prompts(self):
1830 """Returns a list of prompts defined for the symbol, in the order they
1831 appear in the configuration files. Returns the empty list for symbols
1832 with no prompt.
1833
1834 This list will have a single entry for the vast majority of symbols
1835 having prompts, but having multiple prompts for a single symbol is
1836 possible through having multiple 'config' entries for it."""
1837 return [prompt for prompt, _ in self.orig_prompts]
1838
1839 def get_help(self):
1840 """Returns the help text of the symbol, or None if the symbol has no
1841 help text."""
1842 return self.help
1843
1844 def get_parent(self):
1845 """Returns the menu or choice statement that contains the symbol, or
1846 None if the symbol is at the top level. Note that if statements are
1847 treated as syntactic and do not have an explicit class
1848 representation."""
1849 return self.parent
1850
1851 def get_def_locations(self):
1852 """Returns a list of (filename, linenr) tuples, where filename (string)
1853 and linenr (int) represent a location where the symbol is defined. For
1854 the vast majority of symbols this list will only contain one element.
1855 For the following Kconfig, FOO would get two entries: the lines marked
1856 with *.
1857
1858 config FOO *
1859 bool "foo prompt 1"
1860
1861 config FOO *
1862 bool "foo prompt 2"
1863 """
1864 return self.def_locations
1865
1866 def get_ref_locations(self):
1867 """Returns a list of (filename, linenr) tuples, where filename (string)
1868 and linenr (int) represent a location where the symbol is referenced in
1869 the configuration. For example, the lines marked by * would be included
1870 for FOO below:
1871
1872 config A
1873 bool
1874 default BAR || FOO *
1875
1876 config B
1877 tristate
1878 depends on FOO *
1879 default m if FOO *
1880
1881 if FOO *
1882 config A
1883 bool "A"
1884 endif
1885
1886 config FOO (definition not included)
1887 bool
1888 """
1889 return self.ref_locations
1890
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001891 def get_value(self):
1892 """Calculate and return the value of the symbol. See also
1893 Symbol.set_user_value()."""
1894
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001895 if self.cached_val is not None:
1896 return self.cached_val
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001897
1898 # As a quirk of Kconfig, undefined symbols get their name as their
1899 # value. This is why things like "FOO = bar" work for seeing if FOO has
1900 # the value "bar".
1901 if self.type == UNKNOWN:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001902 self.cached_val = self.name
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001903 return self.name
1904
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001905 new_val = DEFAULT_VALUE[self.type]
1906 vis = _get_visibility(self)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001907
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001908 # This is easiest to calculate together with the value
1909 self.write_to_conf = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001910
1911 if self.type == BOOL or self.type == TRISTATE:
1912 # The visibility and mode (modules-only or single-selection) of
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001913 # choice items will be taken into account in _get_visibility()
1914 if self.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001915 if vis != "n":
1916 choice = self.parent
1917 mode = choice.get_mode()
1918
1919 self.write_to_conf = (mode != "n")
1920
1921 if mode == "y":
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001922 if choice.get_selection() is self:
1923 new_val = "y"
1924 else:
1925 new_val = "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001926 elif mode == "m":
1927 if self.user_val == "m" or self.user_val == "y":
1928 new_val = "m"
1929
1930 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001931 # If the symbol is visible and has a user value, use that.
1932 # Otherwise, look at defaults.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001933 use_defaults = True
1934
1935 if vis != "n":
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001936 self.write_to_conf = True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001937 if self.user_val is not None:
1938 new_val = self.config._eval_min(self.user_val, vis)
1939 use_defaults = False
1940
1941 if use_defaults:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001942 for val_expr, cond_expr in self.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001943 cond_eval = self.config._eval_expr(cond_expr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001944 if cond_eval != "n":
1945 self.write_to_conf = True
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001946 new_val = self.config._eval_min(val_expr,
1947 cond_eval)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001948 break
1949
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001950 # Reverse (select-related) dependencies take precedence
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001951 rev_dep_val = self.config._eval_expr(self.rev_dep)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001952 if rev_dep_val != "n":
1953 self.write_to_conf = True
1954 new_val = self.config._eval_max(new_val, rev_dep_val)
1955
1956 # Promote "m" to "y" for booleans
1957 if new_val == "m" and self.type == BOOL:
1958 new_val = "y"
1959
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001960 elif self.type == INT or self.type == HEX:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001961 has_active_range = False
1962 low = None
1963 high = None
1964 use_defaults = True
1965
1966 base = 16 if self.type == HEX else 10
1967
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001968 for l, h, cond_expr in self.ranges:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001969 if self.config._eval_expr(cond_expr) != "n":
1970 has_active_range = True
1971
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001972 low_str = _str_val(l)
1973 high_str = _str_val(h)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001974 low = int(low_str, base) if \
1975 _is_base_n(low_str, base) else 0
1976 high = int(high_str, base) if \
1977 _is_base_n(high_str, base) else 0
1978
1979 break
1980
1981 if vis != "n":
1982 self.write_to_conf = True
1983
1984 if self.user_val is not None and \
1985 _is_base_n(self.user_val, base) and \
1986 (not has_active_range or
1987 low <= int(self.user_val, base) <= high):
1988
1989 # If the user value is OK, it is stored in exactly the same
1990 # form as specified in the assignment (with or without
1991 # "0x", etc).
1992
1993 use_defaults = False
1994 new_val = self.user_val
1995
1996 if use_defaults:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02001997 for val_expr, cond_expr in self.def_exprs:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09001998 if self.config._eval_expr(cond_expr) != "n":
1999 self.write_to_conf = True
2000
2001 # If the default value is OK, it is stored in exactly
2002 # the same form as specified. Otherwise, it is clamped
2003 # to the range, and the output has "0x" as appropriate
2004 # for the type.
2005
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002006 new_val = _str_val(val_expr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002007
2008 if _is_base_n(new_val, base):
2009 new_val_num = int(new_val, base)
2010 if has_active_range:
2011 clamped_val = None
2012
2013 if new_val_num < low:
2014 clamped_val = low
2015 elif new_val_num > high:
2016 clamped_val = high
2017
2018 if clamped_val is not None:
2019 new_val = (hex(clamped_val) if \
2020 self.type == HEX else str(clamped_val))
2021
2022 break
2023 else: # For the for loop
2024 # If no user value or default kicks in but the hex/int has
2025 # an active range, then the low end of the range is used,
2026 # provided it's > 0, with "0x" prepended as appropriate.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002027 if has_active_range and low > 0:
2028 new_val = (hex(low) if self.type == HEX else str(low))
2029
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002030 elif self.type == STRING:
2031 use_defaults = True
2032
2033 if vis != "n":
2034 self.write_to_conf = True
2035 if self.user_val is not None:
2036 new_val = self.user_val
2037 use_defaults = False
2038
2039 if use_defaults:
2040 for val_expr, cond_expr in self.def_exprs:
2041 if self.config._eval_expr(cond_expr) != "n":
2042 self.write_to_conf = True
2043 new_val = _str_val(val_expr)
2044 break
2045
2046 self.cached_val = new_val
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002047 return new_val
2048
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002049 def get_user_value(self):
2050 """Returns the value assigned to the symbol in a .config or via
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002051 Symbol.set_user_value() (provided the value was valid for the type of
2052 the symbol). Returns None in case of no user value."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002053 return self.user_val
2054
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002055 def get_upper_bound(self):
2056 """For string/hex/int symbols and for bool and tristate symbols that
2057 cannot be modified (see is_modifiable()), returns None.
2058
2059 Otherwise, returns the highest value the symbol can be set to with
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002060 Symbol.set_user_value() (that will not be truncated): one of "m" or
2061 "y", arranged from lowest to highest. This corresponds to the highest
2062 value the symbol could be given in e.g. the 'make menuconfig'
2063 interface.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002064
2065 See also the tri_less*() and tri_greater*() functions, which could come
2066 in handy."""
2067 if self.type != BOOL and self.type != TRISTATE:
2068 return None
2069 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002070 # A bool selected to "m" gets promoted to "y", pinning it
2071 if rev_dep == "m" and self.type == BOOL:
2072 return None
2073 vis = _get_visibility(self)
2074 if TRI_TO_INT[vis] > TRI_TO_INT[rev_dep]:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002075 return vis
2076 return None
2077
2078 def get_lower_bound(self):
2079 """For string/hex/int symbols and for bool and tristate symbols that
2080 cannot be modified (see is_modifiable()), returns None.
2081
2082 Otherwise, returns the lowest value the symbol can be set to with
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002083 Symbol.set_user_value() (that will not be truncated): one of "n" or
2084 "m", arranged from lowest to highest. This corresponds to the lowest
2085 value the symbol could be given in e.g. the 'make menuconfig'
2086 interface.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002087
2088 See also the tri_less*() and tri_greater*() functions, which could come
2089 in handy."""
2090 if self.type != BOOL and self.type != TRISTATE:
2091 return None
2092 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002093 # A bool selected to "m" gets promoted to "y", pinning it
2094 if rev_dep == "m" and self.type == BOOL:
2095 return None
2096 if TRI_TO_INT[_get_visibility(self)] > TRI_TO_INT[rev_dep]:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002097 return rev_dep
2098 return None
2099
2100 def get_assignable_values(self):
2101 """For string/hex/int symbols and for bool and tristate symbols that
2102 cannot be modified (see is_modifiable()), returns the empty list.
2103
2104 Otherwise, returns a list containing the user values that can be
2105 assigned to the symbol (that won't be truncated). Usage example:
2106
2107 if "m" in sym.get_assignable_values():
2108 sym.set_user_value("m")
2109
2110 This is basically a more convenient interface to
2111 get_lower/upper_bound() when wanting to test if a particular tristate
2112 value can be assigned."""
2113 if self.type != BOOL and self.type != TRISTATE:
2114 return []
2115 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002116 # A bool selected to "m" gets promoted to "y", pinning it
2117 if rev_dep == "m" and self.type == BOOL:
2118 return []
2119 res = ["n", "m", "y"][TRI_TO_INT[rev_dep] :
2120 TRI_TO_INT[_get_visibility(self)] + 1]
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002121 return res if len(res) > 1 else []
2122
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002123 def get_visibility(self):
2124 """Returns the visibility of the symbol: one of "n", "m" or "y". For
2125 bool and tristate symbols, this is an upper bound on the value users
2126 can set for the symbol. For other types of symbols, a visibility of "n"
2127 means the user value will be ignored. A visibility of "n" corresponds
2128 to not being visible in the 'make *config' interfaces.
2129
2130 Example (assuming we're running with modules enabled -- i.e., MODULES
2131 set to 'y'):
2132
2133 # Assume this has been assigned 'n'
2134 config N_SYM
2135 tristate "N_SYM"
2136
2137 # Assume this has been assigned 'm'
2138 config M_SYM
2139 tristate "M_SYM"
2140
2141 # Has visibility 'n'
2142 config A
2143 tristate "A"
2144 depends on N_SYM
2145
2146 # Has visibility 'm'
2147 config B
2148 tristate "B"
2149 depends on M_SYM
2150
2151 # Has visibility 'y'
2152 config C
2153 tristate "C"
2154
2155 # Has no prompt, and hence visibility 'n'
2156 config D
2157 tristate
2158
2159 Having visibility be tri-valued ensures that e.g. a symbol cannot be
2160 set to "y" by the user if it depends on a symbol with value "m", which
2161 wouldn't be safe.
2162
2163 You should probably look at get_lower/upper_bound(),
2164 get_assignable_values() and is_modifiable() before using this."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002165 return _get_visibility(self)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002166
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002167 def get_referenced_symbols(self, refs_from_enclosing=False):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002168 """Returns the set() of all symbols referenced by this symbol. For
2169 example, the symbol defined by
2170
2171 config FOO
2172 bool
2173 prompt "foo" if A && B
2174 default C if D
2175 depends on E
2176 select F if G
2177
2178 references the symbols A through G.
2179
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002180 refs_from_enclosing (default: False): If True, the symbols referenced
2181 by enclosing menus and ifs will be included in the result."""
2182 return self.all_referenced_syms if refs_from_enclosing else \
2183 self.referenced_syms
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002184
2185 def get_selected_symbols(self):
2186 """Returns the set() of all symbols X for which this symbol has a
2187 'select X' or 'select X if Y' (regardless of whether Y is satisfied or
2188 not). This is a subset of the symbols returned by
2189 get_referenced_symbols()."""
2190 return self.selected_syms
2191
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002192 def set_user_value(self, v):
2193 """Sets the user value of the symbol.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002194
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002195 Equal in effect to assigning the value to the symbol within a .config
2196 file. Use get_lower/upper_bound() or get_assignable_values() to find
2197 the range of currently assignable values for bool and tristate symbols;
2198 setting values outside this range will cause the user value to differ
2199 from the result of Symbol.get_value() (be truncated). Values that are
2200 invalid for the type (such as a_bool.set_user_value("foo")) are
2201 ignored, and a warning is emitted if an attempt is made to assign such
2202 a value.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002203
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002204 For any type of symbol, is_modifiable() can be used to check if a user
2205 value will currently have any effect on the symbol, as determined by
2206 its visibility and range of assignable values. Any value that is valid
2207 for the type (bool, tristate, etc.) will end up being reflected in
2208 get_user_value() though, and might have an effect later if conditions
2209 change. To get rid of the user value, use unset_user_value().
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002210
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002211 Any symbols dependent on the symbol are (recursively) invalidated, so
2212 things will just work with regards to dependencies.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002213
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002214 v: The user value to give to the symbol."""
2215 self._set_user_value_no_invalidate(v, False)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002216
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002217 # There might be something more efficient you could do here, but play
2218 # it safe.
2219 if self.name == "MODULES":
2220 self.config._invalidate_all()
2221 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002222
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002223 self._invalidate()
2224 self._invalidate_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002225
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002226 def unset_user_value(self):
2227 """Resets the user value of the symbol, as if the symbol had never
2228 gotten a user value via Config.load_config() or
2229 Symbol.set_user_value()."""
2230 self._unset_user_value_no_recursive_invalidate()
2231 self._invalidate_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002232
2233 def is_modifiable(self):
2234 """Returns True if the value of the symbol could be modified by calling
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002235 Symbol.set_user_value().
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002236
2237 For bools and tristates, this corresponds to the symbol being visible
2238 in the 'make menuconfig' interface and not already being pinned to a
2239 specific value (e.g. because it is selected by another symbol).
2240
2241 For strings and numbers, this corresponds to just being visible. (See
2242 Symbol.get_visibility().)"""
2243 if self.is_special_:
2244 return False
2245 if self.type == BOOL or self.type == TRISTATE:
2246 rev_dep = self.config._eval_expr(self.rev_dep)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002247 # A bool selected to "m" gets promoted to "y", pinning it
2248 if rev_dep == "m" and self.type == BOOL:
2249 return False
2250 return TRI_TO_INT[_get_visibility(self)] > TRI_TO_INT[rev_dep]
2251 return _get_visibility(self) != "n"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002252
2253 def is_defined(self):
2254 """Returns False if the symbol is referred to in the Kconfig but never
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002255 actually defined."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002256 return self.is_defined_
2257
2258 def is_special(self):
2259 """Returns True if the symbol is one of the special symbols n, m, y, or
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002260 UNAME_RELEASE, or gets its value from the environment."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002261 return self.is_special_
2262
2263 def is_from_environment(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002264 """Returns True if the symbol gets its value from the environment."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002265 return self.is_from_env
2266
2267 def has_ranges(self):
2268 """Returns True if the symbol is of type INT or HEX and has ranges that
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002269 limit what values it can take on."""
2270 return bool(self.ranges)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002271
2272 def is_choice_symbol(self):
2273 """Returns True if the symbol is in a choice statement and is an actual
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002274 choice symbol (see Choice.get_symbols())."""
2275 return self.is_choice_sym
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002276
2277 def is_choice_selection(self):
2278 """Returns True if the symbol is contained in a choice statement and is
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002279 the selected item. Equivalent to
2280
2281 sym.is_choice_symbol() and sym.get_parent().get_selection() is sym"""
2282 return self.is_choice_sym and self.parent.get_selection() is self
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002283
Masahiro Yamada9d01b782015-05-27 11:39:22 +09002284 def is_allnoconfig_y(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002285 """Returns True if the symbol has the 'allnoconfig_y' option set."""
Masahiro Yamada9d01b782015-05-27 11:39:22 +09002286 return self.allnoconfig_y
2287
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002288 def __str__(self):
2289 """Returns a string containing various information about the symbol."""
2290 return self.config._get_sym_or_choice_str(self)
2291
2292 #
2293 # Private methods
2294 #
2295
2296 def __init__(self):
2297 """Symbol constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002298 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002299
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002300 self.name = None
2301 self.type = UNKNOWN
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002302 self.prompts = []
2303 self.def_exprs = [] # 'default' properties
2304 self.ranges = [] # 'range' properties (for int and hex)
2305 self.help = None # Help text
2306 self.rev_dep = "n" # Reverse (select-related) dependencies
2307 self.config = None
2308 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002309
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002310 self.user_val = None # Value set by user
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002311
2312 # The prompt, default value and select conditions without any
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002313 # dependencies from menus and ifs propagated to them
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002314 self.orig_prompts = []
2315 self.orig_def_exprs = []
2316 self.orig_selects = []
2317
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002318 # Dependencies inherited from containing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002319 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002320 # The set of symbols referenced by this symbol (see
2321 # get_referenced_symbols())
2322 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002323 # The set of symbols selected by this symbol (see
2324 # get_selected_symbols())
2325 self.selected_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002326 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002327 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002328 self.all_referenced_syms = set()
2329
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002330 # This records only dependencies specified with 'depends on'. Needed
2331 # when determining actual choice items (hrrrr...). See also
2332 # Choice._determine_actual_symbols().
2333 self.menu_dep = None
2334
2335 # See Symbol.get_ref/def_locations().
2336 self.def_locations = []
2337 self.ref_locations = []
2338
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002339 # Populated in Config._build_dep() after parsing. Links the symbol to
2340 # the symbols that immediately depend on it (in a caching/invalidation
2341 # sense). The total set of dependent symbols for the symbol (the
2342 # transitive closure) is calculated on an as-needed basis in
2343 # _get_dependent().
2344 self.dep = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002345
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002346 # Cached values
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002347
2348 # Caches the calculated value
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002349 self.cached_val = None
2350 # Caches the visibility, which acts as an upper bound on the value
2351 self.cached_visibility = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002352 # Caches the total list of dependent symbols. Calculated in
2353 # _get_dependent().
2354 self.cached_deps = None
2355
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002356 # Flags
2357
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002358 # Does the symbol have an entry in the Kconfig file? The trailing
2359 # underscore avoids a collision with is_defined().
2360 self.is_defined_ = False
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002361 # Should the symbol get an entry in .config?
2362 self.write_to_conf = False
2363 # Set to true when _make_conf() is called on a symbol, so that symbols
2364 # defined in multiple locations only get one .config entry. We need to
2365 # reset it prior to writing out a new .config.
2366 self.already_written = False
2367 # This is set to True for "actual" choice symbols; see
2368 # Choice._determine_actual_symbols().
2369 self.is_choice_sym = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002370 # Does the symbol get its value in some special way, e.g. from the
2371 # environment or by being one of the special symbols n, m, and y? If
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002372 # so, the value is stored in self.cached_val, which is never
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002373 # invalidated. The trailing underscore avoids a collision with
2374 # is_special().
2375 self.is_special_ = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002376 # Does the symbol get its value from the environment?
2377 self.is_from_env = False
Masahiro Yamada9d01b782015-05-27 11:39:22 +09002378 # Does the symbol have the 'allnoconfig_y' option set?
2379 self.allnoconfig_y = False
2380
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002381 def _invalidate(self):
2382 if self.is_special_:
2383 return
2384
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002385 if self.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002386 self.parent._invalidate()
2387
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002388 self.cached_val = None
2389 self.cached_visibility = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002390
2391 def _invalidate_dependent(self):
2392 for sym in self._get_dependent():
2393 sym._invalidate()
2394
2395 def _set_user_value_no_invalidate(self, v, suppress_load_warnings):
2396 """Like set_user_value(), but does not invalidate any symbols.
2397
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002398 suppress_load_warnings: some warnings are annoying when loading a
2399 .config that can be helpful when manually invoking set_user_value().
2400 This flag is set to True to suppress such warnings.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002401
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002402 Perhaps this could be made optional for load_config() instead."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002403
2404 if self.is_special_:
2405 if self.is_from_env:
2406 self.config._warn('attempt to assign the value "{0}" to the '
2407 'symbol {1}, which gets its value from the '
2408 'environment. Assignment ignored.'
2409 .format(v, self.name))
2410 else:
2411 self.config._warn('attempt to assign the value "{0}" to the '
2412 'special symbol {1}. Assignment ignored.'
2413 .format(v, self.name))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002414 return
2415
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002416 if not self.is_defined_:
2417 filename, linenr = self.ref_locations[0]
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002418 if self.config.print_undef_assign:
2419 _stderr_msg('note: attempt to assign the value "{0}" to {1}, '
2420 "which is referenced at {2}:{3} but never "
2421 "defined. Assignment ignored."
2422 .format(v, self.name, filename, linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002423 return
2424
2425 # Check if the value is valid for our type
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002426 if not ((self.type == BOOL and (v == "y" or v == "n") ) or
2427 (self.type == TRISTATE and (v == "y" or v == "m" or
2428 v == "n") ) or
2429 (self.type == STRING ) or
2430 (self.type == INT and _is_base_n(v, 10) ) or
2431 (self.type == HEX and _is_base_n(v, 16) )):
2432 self.config._warn('the value "{0}" is invalid for {1}, which has '
2433 "type {2}. Assignment ignored."
2434 .format(v, self.name, TYPENAME[self.type]))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002435 return
2436
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002437 if not self.prompts and not suppress_load_warnings:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002438 self.config._warn('assigning "{0}" to the symbol {1} which '
2439 'lacks prompts and thus has visibility "n". '
2440 'The assignment will have no effect.'
2441 .format(v, self.name))
2442
2443 self.user_val = v
2444
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002445 if self.is_choice_sym and (self.type == BOOL or self.type == TRISTATE):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002446 choice = self.parent
2447 if v == "y":
2448 choice.user_val = self
2449 choice.user_mode = "y"
2450 elif v == "m":
2451 choice.user_val = None
2452 choice.user_mode = "m"
2453
2454 def _unset_user_value_no_recursive_invalidate(self):
2455 self._invalidate()
2456 self.user_val = None
2457
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002458 if self.is_choice_sym:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002459 self.parent._unset_user_value()
2460
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002461 def _make_conf(self, append_fn):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002462 if self.already_written:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002463 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002464
2465 self.already_written = True
2466
2467 # Note: write_to_conf is determined in get_value()
2468 val = self.get_value()
2469 if not self.write_to_conf:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002470 return
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002471
2472 if self.type == BOOL or self.type == TRISTATE:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002473 if val == "y" or val == "m":
2474 append_fn("CONFIG_{0}={1}".format(self.name, val))
2475 else:
2476 append_fn("# CONFIG_{0} is not set".format(self.name))
2477
2478 elif self.type == INT or self.type == HEX:
2479 append_fn("CONFIG_{0}={1}".format(self.name, val))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002480
2481 elif self.type == STRING:
2482 # Escape \ and "
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002483 append_fn('CONFIG_{0}="{1}"'
2484 .format(self.name,
2485 val.replace("\\", "\\\\").replace('"', '\\"')))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002486
2487 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002488 _internal_error("Internal error while creating .config: unknown "
2489 'type "{0}".'.format(self.type))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002490
2491 def _get_dependent(self):
2492 """Returns the set of symbols that should be invalidated if the value
2493 of the symbol changes, because they might be affected by the change.
2494 Note that this is an internal API -- it's probably of limited
2495 usefulness to clients."""
2496 if self.cached_deps is not None:
2497 return self.cached_deps
2498
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002499 res = set(self.dep)
2500 for s in self.dep:
2501 res |= s._get_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002502
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002503 if self.is_choice_sym:
2504 # Choice symbols also depend (recursively) on their siblings. The
2505 # siblings are not included in 'dep' to avoid dependency loops.
2506 for sibling in self.parent.actual_symbols:
2507 if sibling is not self:
2508 res.add(sibling)
2509 res |= sibling.dep
2510 for s in sibling.dep:
2511 res |= s._get_dependent()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002512
2513 self.cached_deps = res
2514 return res
2515
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002516 def _has_auto_menu_dep_on(self, on):
2517 """See Choice._determine_actual_symbols()."""
2518 if not isinstance(self.parent, Choice):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002519 _internal_error("Attempt to determine auto menu dependency for "
2520 "symbol ouside of choice.")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002521
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002522 if not self.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002523 # If we have no prompt, use the menu dependencies instead (what was
2524 # specified with 'depends on')
2525 return self.menu_dep is not None and \
2526 self.config._expr_depends_on(self.menu_dep, on)
2527
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002528 for _, cond_expr in self.prompts:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002529 if self.config._expr_depends_on(cond_expr, on):
2530 return True
2531
2532 return False
2533
2534class Menu(Item):
2535
2536 """Represents a menu statement."""
2537
2538 #
2539 # Public interface
2540 #
2541
2542 def get_config(self):
2543 """Return the Config instance this menu is from."""
2544 return self.config
2545
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002546 def get_title(self):
2547 """Returns the title text of the menu."""
2548 return self.title
2549
2550 def get_parent(self):
2551 """Returns the menu or choice statement that contains the menu, or
2552 None if the menu is at the top level. Note that if statements are
2553 treated as syntactic sugar and do not have an explicit class
2554 representation."""
2555 return self.parent
2556
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002557 def get_location(self):
2558 """Returns the location of the menu as a (filename, linenr) tuple,
2559 where filename is a string and linenr an int."""
2560 return (self.filename, self.linenr)
2561
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002562 def get_items(self, recursive=False):
2563 """Returns a list containing the items (symbols, menus, choice
2564 statements and comments) in in the menu, in the same order that the
2565 items appear within the menu.
2566
2567 recursive (default: False): True if items contained in items within the
2568 menu should be included recursively (preorder)."""
2569
2570 if not recursive:
2571 return self.block
2572
2573 res = []
2574 for item in self.block:
2575 res.append(item)
2576 if isinstance(item, Menu):
2577 res.extend(item.get_items(True))
2578 elif isinstance(item, Choice):
2579 res.extend(item.get_items())
2580 return res
2581
2582 def get_symbols(self, recursive=False):
2583 """Returns a list containing the symbols in the menu, in the same order
2584 that they appear within the menu.
2585
2586 recursive (default: False): True if symbols contained in items within
2587 the menu should be included recursively."""
2588
2589 return [item for item in self.get_items(recursive) if
2590 isinstance(item, Symbol)]
2591
2592 def get_visibility(self):
2593 """Returns the visibility of the menu. This also affects the visibility
2594 of subitems. See also Symbol.get_visibility()."""
2595 return self.config._eval_expr(self.dep_expr)
2596
2597 def get_visible_if_visibility(self):
2598 """Returns the visibility the menu gets from its 'visible if'
2599 condition. "y" if the menu has no 'visible if' condition."""
2600 return self.config._eval_expr(self.visible_if_expr)
2601
2602 def get_referenced_symbols(self, refs_from_enclosing=False):
2603 """See Symbol.get_referenced_symbols()."""
2604 return self.all_referenced_syms if refs_from_enclosing else \
2605 self.referenced_syms
2606
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002607 def __str__(self):
2608 """Returns a string containing various information about the menu."""
2609 depends_on_str = self.config._expr_val_str(self.orig_deps,
2610 "(no dependencies)")
2611 visible_if_str = self.config._expr_val_str(self.visible_if_expr,
2612 "(no dependencies)")
2613
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002614 additional_deps_str = " " + \
2615 self.config._expr_val_str(self.deps_from_containing,
2616 "(no additional dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002617
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002618 return _lines("Menu",
2619 "Title : " + self.title,
2620 "'depends on' dependencies : " + depends_on_str,
2621 "'visible if' dependencies : " + visible_if_str,
2622 "Additional dependencies from enclosing menus and "
2623 "ifs:",
2624 additional_deps_str,
2625 "Location: {0}:{1}".format(self.filename, self.linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002626
2627 #
2628 # Private methods
2629 #
2630
2631 def __init__(self):
2632 """Menu constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002633 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002634
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002635 self.title = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002636 self.dep_expr = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002637 self.visible_if_expr = None
2638 self.block = None
2639 self.config = None
2640 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002641
2642 # Dependency expression without dependencies from enclosing menus and
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002643 # ifs propagated
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002644 self.orig_deps = None
2645
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002646 # Dependencies inherited from containing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002647 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002648 # The set of symbols referenced by this menu (see
2649 # get_referenced_symbols())
2650 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002651 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002652 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002653 self.all_referenced_syms = None
2654
2655 self.filename = None
2656 self.linenr = None
2657
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002658 def _make_conf(self, append_fn):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002659 if self.config._eval_expr(self.dep_expr) != "n" and \
2660 self.config._eval_expr(self.visible_if_expr) != "n":
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002661 append_fn("\n#\n# {0}\n#".format(self.title))
2662 _make_block_conf(self.block, append_fn)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002663
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002664class Choice(Item):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002665
2666 """Represents a choice statement. A choice can be in one of three modes:
2667
2668 "n" - The choice is not visible and no symbols can be selected.
2669
2670 "m" - Any number of symbols can be set to "m". The rest will be "n". This
2671 is safe since potentially conflicting options don't actually get
2672 compiled into the kernel simultaneously with "m".
2673
2674 "y" - One symbol will be "y" while the rest are "n".
2675
2676 Only tristate choices can be in "m" mode, and the visibility of the choice
2677 is an upper bound on the mode, so that e.g. a choice that depends on a
2678 symbol with value "m" will be in "m" mode.
2679
2680 The mode changes automatically when a value is assigned to a symbol within
2681 the choice.
2682
2683 See Symbol.get_visibility() too."""
2684
2685 #
2686 # Public interface
2687 #
2688
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002689 def get_config(self):
2690 """Returns the Config instance this choice is from."""
2691 return self.config
2692
2693 def get_name(self):
2694 """For named choices, returns the name. Returns None for unnamed
2695 choices. No named choices appear anywhere in the kernel Kconfig files
2696 as of Linux 3.7.0-rc8."""
2697 return self.name
2698
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002699 def get_type(self):
2700 """Returns the type of the choice. See Symbol.get_type()."""
2701 return self.type
2702
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002703 def get_prompts(self):
2704 """Returns a list of prompts defined for the choice, in the order they
2705 appear in the configuration files. Returns the empty list for choices
2706 with no prompt.
2707
2708 This list will have a single entry for the vast majority of choices
2709 having prompts, but having multiple prompts for a single choice is
2710 possible through having multiple 'choice' entries for it (though I'm
2711 not sure if that ever happens in practice)."""
2712 return [prompt for prompt, _ in self.orig_prompts]
2713
2714 def get_help(self):
2715 """Returns the help text of the choice, or None if the choice has no
2716 help text."""
2717 return self.help
2718
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002719 def get_parent(self):
2720 """Returns the menu or choice statement that contains the choice, or
2721 None if the choice is at the top level. Note that if statements are
2722 treated as syntactic sugar and do not have an explicit class
2723 representation."""
2724 return self.parent
2725
2726 def get_def_locations(self):
2727 """Returns a list of (filename, linenr) tuples, where filename (string)
2728 and linenr (int) represent a location where the choice is defined. For
2729 the vast majority of choices (all of them as of Linux 3.7.0-rc8) this
2730 list will only contain one element, but its possible for named choices
2731 to be defined in multiple locations."""
2732 return self.def_locations
2733
2734 def get_selection(self):
2735 """Returns the symbol selected (either by the user or through
2736 defaults), or None if either no symbol is selected or the mode is not
2737 "y"."""
2738 if self.cached_selection is not None:
2739 if self.cached_selection == NO_SELECTION:
2740 return None
2741 return self.cached_selection
2742
2743 if self.get_mode() != "y":
2744 return self._cache_ret(None)
2745
2746 # User choice available?
2747 if self.user_val is not None and _get_visibility(self.user_val) == "y":
2748 return self._cache_ret(self.user_val)
2749
2750 if self.optional:
2751 return self._cache_ret(None)
2752
2753 return self._cache_ret(self.get_selection_from_defaults())
2754
2755 def get_selection_from_defaults(self):
2756 """Like Choice.get_selection(), but acts as if no symbol has been
2757 selected by the user and no 'optional' flag is in effect."""
2758
2759 if not self.actual_symbols:
2760 return None
2761
2762 for symbol, cond_expr in self.def_exprs:
2763 if self.config._eval_expr(cond_expr) != "n":
2764 chosen_symbol = symbol
2765 break
2766 else:
2767 chosen_symbol = self.actual_symbols[0]
2768
2769 # Is the chosen symbol visible?
2770 if _get_visibility(chosen_symbol) != "n":
2771 return chosen_symbol
2772 # Otherwise, pick the first visible symbol
2773 for sym in self.actual_symbols:
2774 if _get_visibility(sym) != "n":
2775 return sym
2776 return None
2777
2778 def get_user_selection(self):
2779 """If the choice is in "y" mode and has a user-selected symbol, returns
2780 that symbol. Otherwise, returns None."""
2781 return self.user_val
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002782
2783 def get_items(self):
2784 """Gets all items contained in the choice in the same order as within
2785 the configuration ("items" instead of "symbols" since choices and
2786 comments might appear within choices. This only happens in one place as
2787 of Linux 3.7.0-rc8, in drivers/usb/gadget/Kconfig)."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002788 return self.block
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002789
2790 def get_symbols(self):
2791 """Returns a list containing the choice's symbols.
2792
2793 A quirk (perhaps a bug) of Kconfig is that you can put items within a
2794 choice that will not be considered members of the choice insofar as
2795 selection is concerned. This happens for example if one symbol within a
2796 choice 'depends on' the symbol preceding it, or if you put non-symbol
2797 items within choices.
2798
2799 As of Linux 3.7.0-rc8, this seems to be used intentionally in one
2800 place: drivers/usb/gadget/Kconfig.
2801
2802 This function returns the "proper" symbols of the choice in the order
2803 they appear in the choice, excluding such items. If you want all items
2804 in the choice, use get_items()."""
2805 return self.actual_symbols
2806
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002807 def get_referenced_symbols(self, refs_from_enclosing=False):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002808 """See Symbol.get_referenced_symbols()."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002809 return self.all_referenced_syms if refs_from_enclosing else \
2810 self.referenced_syms
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002811
2812 def get_visibility(self):
2813 """Returns the visibility of the choice statement: one of "n", "m" or
2814 "y". This acts as an upper limit on the mode of the choice (though bool
2815 choices can only have the mode "y"). See the class documentation for an
2816 explanation of modes."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002817 return _get_visibility(self)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002818
2819 def get_mode(self):
2820 """Returns the mode of the choice. See the class documentation for
2821 an explanation of modes."""
2822 minimum_mode = "n" if self.optional else "m"
2823 mode = self.user_mode if self.user_mode is not None else minimum_mode
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002824 mode = self.config._eval_min(mode, _get_visibility(self))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002825
2826 # Promote "m" to "y" for boolean choices
2827 if mode == "m" and self.type == BOOL:
2828 return "y"
2829
2830 return mode
2831
2832 def is_optional(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002833 """Returns True if the choice has the 'optional' flag set (and so will
2834 default to "n" mode)."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002835 return self.optional
2836
2837 def __str__(self):
2838 """Returns a string containing various information about the choice
2839 statement."""
2840 return self.config._get_sym_or_choice_str(self)
2841
2842 #
2843 # Private methods
2844 #
2845
2846 def __init__(self):
2847 """Choice constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002848 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002849
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002850 self.name = None # Yes, choices can be named
2851 self.type = UNKNOWN
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002852 self.prompts = []
2853 self.def_exprs = [] # 'default' properties
2854 self.help = None # Help text
2855 self.block = None # List of contained items
2856 self.config = None
2857 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002858
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002859 self.user_val = None
2860 self.user_mode = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002861
2862 # We need to filter out symbols that appear within the choice block but
2863 # are not considered choice items (see
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002864 # Choice._determine_actual_symbols()) This list holds the "actual"
2865 # choice items.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002866 self.actual_symbols = []
2867
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002868 # The prompts and default values without any dependencies from
2869 # enclosing menus and ifs propagated
2870 self.orig_prompts = []
2871 self.orig_def_exprs = []
2872
2873 # Dependencies inherited from containing menus and ifs
2874 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002875 # The set of symbols referenced by this choice (see
2876 # get_referenced_symbols())
2877 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002878 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002879 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002880 self.all_referenced_syms = set()
2881
2882 # See Choice.get_def_locations()
2883 self.def_locations = []
2884
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002885 # Cached values
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002886 self.cached_selection = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002887 self.cached_visibility = None
2888
2889 self.optional = False
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002890
2891 def _determine_actual_symbols(self):
2892 """If a symbol's visibility depends on the preceding symbol within a
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002893 choice, it is no longer viewed as a choice item. (This is quite
2894 possibly a bug, but some things consciously use it... ugh. It stems
2895 from automatic submenu creation.) In addition, it's possible to have
2896 choices and comments within choices, and those shouldn't be considered
2897 choice items either. Only drivers/usb/gadget/Kconfig seems to depend on
2898 any of this. This method computes the "actual" items in the choice and
2899 sets the is_choice_sym flag on them (retrieved via is_choice_symbol()).
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002900
2901 Don't let this scare you: an earlier version simply checked for a
2902 sequence of symbols where all symbols after the first appeared in the
2903 'depends on' expression of the first, and that worked fine. The added
2904 complexity is to be future-proof in the event that
2905 drivers/usb/gadget/Kconfig turns even more sinister. It might very well
2906 be overkilling things (especially if that file is refactored ;)."""
2907
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002908 # Items might depend on each other in a tree structure, so we need a
2909 # stack to keep track of the current tentative parent
2910 stack = []
2911
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002912 for item in self.block:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002913 if not isinstance(item, Symbol):
2914 stack = []
2915 continue
2916
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002917 while stack:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002918 if item._has_auto_menu_dep_on(stack[-1]):
2919 # The item should not be viewed as a choice item, so don't
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002920 # set item.is_choice_sym
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002921 stack.append(item)
2922 break
2923 else:
2924 stack.pop()
2925 else:
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002926 item.is_choice_sym = True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002927 self.actual_symbols.append(item)
2928 stack.append(item)
2929
2930 def _cache_ret(self, selection):
2931 # As None is used to indicate the lack of a cached value we can't use
2932 # that to cache the fact that the choice has no selection. Instead, we
2933 # use the symbolic constant NO_SELECTION.
2934 if selection is None:
2935 self.cached_selection = NO_SELECTION
2936 else:
2937 self.cached_selection = selection
2938
2939 return selection
2940
2941 def _invalidate(self):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002942 self.cached_selection = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002943 self.cached_visibility = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002944
2945 def _unset_user_value(self):
2946 self._invalidate()
2947 self.user_val = None
2948 self.user_mode = None
2949
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002950 def _make_conf(self, append_fn):
2951 _make_block_conf(self.block, append_fn)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002952
2953class Comment(Item):
2954
2955 """Represents a comment statement."""
2956
2957 #
2958 # Public interface
2959 #
2960
2961 def get_config(self):
2962 """Returns the Config instance this comment is from."""
2963 return self.config
2964
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002965 def get_text(self):
2966 """Returns the text of the comment."""
2967 return self.text
2968
2969 def get_parent(self):
2970 """Returns the menu or choice statement that contains the comment, or
2971 None if the comment is at the top level. Note that if statements are
2972 treated as syntactic sugar and do not have an explicit class
2973 representation."""
2974 return self.parent
2975
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002976 def get_location(self):
2977 """Returns the location of the comment as a (filename, linenr) tuple,
2978 where filename is a string and linenr an int."""
2979 return (self.filename, self.linenr)
2980
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002981 def get_visibility(self):
2982 """Returns the visibility of the comment. See also
2983 Symbol.get_visibility()."""
2984 return self.config._eval_expr(self.dep_expr)
2985
2986 def get_referenced_symbols(self, refs_from_enclosing=False):
2987 """See Symbol.get_referenced_symbols()."""
2988 return self.all_referenced_syms if refs_from_enclosing else \
2989 self.referenced_syms
2990
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002991 def __str__(self):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002992 """Returns a string containing various information about the
2993 comment."""
2994 dep_str = self.config._expr_val_str(self.orig_deps,
2995 "(no dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09002996
Ulf Magnusson90c36d82015-08-13 19:55:40 +02002997 additional_deps_str = " " + \
2998 self.config._expr_val_str(self.deps_from_containing,
2999 "(no additional dependencies)")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003000
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003001 return _lines("Comment",
3002 "Text: " + str(self.text),
3003 "Dependencies: " + dep_str,
3004 "Additional dependencies from enclosing menus and "
3005 "ifs:",
3006 additional_deps_str,
3007 "Location: {0}:{1}".format(self.filename, self.linenr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003008
3009 #
3010 # Private methods
3011 #
3012
3013 def __init__(self):
3014 """Comment constructor -- not intended to be called directly by
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003015 Kconfiglib clients."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003016
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003017 self.text = None
3018 self.dep_expr = None
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003019 self.config = None
3020 self.parent = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003021
3022 # Dependency expression without dependencies from enclosing menus and
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003023 # ifs propagated
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003024 self.orig_deps = None
3025
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003026 # Dependencies inherited from containing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003027 self.deps_from_containing = None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003028 # The set of symbols referenced by this comment (see
3029 # get_referenced_symbols())
3030 self.referenced_syms = set()
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003031 # Like 'referenced_syms', but includes symbols from
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003032 # dependencies inherited from enclosing menus and ifs
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003033 self.all_referenced_syms = None
3034
3035 self.filename = None
3036 self.linenr = None
3037
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003038 def _make_conf(self, append_fn):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003039 if self.config._eval_expr(self.dep_expr) != "n":
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003040 append_fn("\n#\n# {0}\n#".format(self.text))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003041
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003042class Kconfig_Syntax_Error(Exception):
3043 """Exception raised for syntax errors."""
3044 pass
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003045
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003046class Internal_Error(Exception):
3047 """Exception raised for internal errors."""
3048 pass
3049
3050#
3051# Public functions
3052#
3053
3054def tri_less(v1, v2):
3055 """Returns True if the tristate v1 is less than the tristate v2, where "n",
3056 "m" and "y" are ordered from lowest to highest."""
3057 return TRI_TO_INT[v1] < TRI_TO_INT[v2]
3058
3059def tri_less_eq(v1, v2):
3060 """Returns True if the tristate v1 is less than or equal to the tristate
3061 v2, where "n", "m" and "y" are ordered from lowest to highest."""
3062 return TRI_TO_INT[v1] <= TRI_TO_INT[v2]
3063
3064def tri_greater(v1, v2):
3065 """Returns True if the tristate v1 is greater than the tristate v2, where
3066 "n", "m" and "y" are ordered from lowest to highest."""
3067 return TRI_TO_INT[v1] > TRI_TO_INT[v2]
3068
3069def tri_greater_eq(v1, v2):
3070 """Returns True if the tristate v1 is greater than or equal to the tristate
3071 v2, where "n", "m" and "y" are ordered from lowest to highest."""
3072 return TRI_TO_INT[v1] >= TRI_TO_INT[v2]
3073
3074#
3075# Internal classes
3076#
3077
3078class _Feed(object):
3079
3080 """Class for working with sequences in a stream-like fashion; handy for
3081 tokens."""
3082
3083 # This would be more helpful on the item classes, but would remove some
3084 # flexibility
3085 __slots__ = ['items', 'length', 'i']
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003086
3087 def __init__(self, items):
3088 self.items = items
3089 self.length = len(self.items)
3090 self.i = 0
3091
3092 def get_next(self):
3093 if self.i >= self.length:
3094 return None
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003095 item = self.items[self.i]
3096 self.i += 1
3097 return item
3098
3099 def peek_next(self):
3100 return None if self.i >= self.length else self.items[self.i]
3101
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003102 def check(self, token):
3103 """Check if the next token is 'token'. If so, remove it from the token
3104 feed and return True. Otherwise, leave it in and return False."""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003105 if self.i < self.length and self.items[self.i] == token:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003106 self.i += 1
3107 return True
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003108 return False
3109
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003110 def unget_all(self):
3111 self.i = 0
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003112
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003113class _FileFeed(object):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003114
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003115 """Feeds lines from a file. Keeps track of the filename and current line
3116 number. Joins any line ending in \\ with the following line. We need to be
3117 careful to get the line number right in the presence of continuation
3118 lines."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003119
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003120 __slots__ = ['filename', 'lines', 'length', 'linenr']
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003121
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003122 def __init__(self, filename):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003123 self.filename = _clean_up_path(filename)
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003124 with open(filename, "r") as f:
3125 # No interleaving of I/O and processing yet. Don't know if it would
3126 # help.
3127 self.lines = f.readlines()
3128 self.length = len(self.lines)
3129 self.linenr = 0
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003130
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003131 def get_next(self):
3132 if self.linenr >= self.length:
3133 return None
3134 line = self.lines[self.linenr]
3135 self.linenr += 1
3136 while line.endswith("\\\n"):
3137 line = line[:-2] + self.lines[self.linenr]
3138 self.linenr += 1
3139 return line
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003140
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003141 def peek_next(self):
3142 linenr = self.linenr
3143 if linenr >= self.length:
3144 return None
3145 line = self.lines[linenr]
3146 while line.endswith("\\\n"):
3147 linenr += 1
3148 line = line[:-2] + self.lines[linenr]
3149 return line
3150
3151 def unget(self):
3152 self.linenr -= 1
3153 while self.lines[self.linenr].endswith("\\\n"):
3154 self.linenr -= 1
3155
3156 def next_nonblank(self):
3157 """Removes lines up to and including the next non-blank (not all-space)
3158 line and returns it. Returns None if there are no more non-blank
3159 lines."""
3160 while 1:
3161 line = self.get_next()
3162 if line is None or not line.isspace():
3163 return line
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003164
3165#
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003166# Internal functions
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003167#
3168
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003169def _get_visibility(sc):
3170 """Symbols and Choices have a "visibility" that acts as an upper bound on
3171 the values a user can set for them, corresponding to the visibility in e.g.
3172 'make menuconfig'. This function calculates the visibility for the Symbol
3173 or Choice 'sc' -- the logic is nearly identical."""
3174 if sc.cached_visibility is None:
3175 vis = "n"
3176 for _, cond_expr in sc.prompts:
3177 vis = sc.config._eval_max(vis, cond_expr)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003178
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003179 if isinstance(sc, Symbol) and sc.is_choice_sym:
3180 vis = sc.config._eval_min(vis, _get_visibility(sc.parent))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003181
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003182 # Promote "m" to "y" if we're dealing with a non-tristate
3183 if vis == "m" and sc.type != TRISTATE:
3184 vis = "y"
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003185
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003186 sc.cached_visibility = vis
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003187
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003188 return sc.cached_visibility
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003189
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003190def _make_and(e1, e2):
3191 """Constructs an AND (&&) expression. Performs trivial simplification.
3192 Nones equate to 'y'.
3193
3194 Note: returns None if e1 == e2 == None."""
3195 if e1 is None or e1 == "y":
3196 return e2
3197 if e2 is None or e2 == "y":
3198 return e1
3199
3200 # Prefer to merge argument lists if possible to reduce the number of nodes
3201
3202 if isinstance(e1, tuple) and e1[0] == AND:
3203 if isinstance(e2, tuple) and e2[0] == AND:
3204 return (AND, e1[1] + e2[1])
3205 return (AND, e1[1] + [e2])
3206
3207 if isinstance(e2, tuple) and e2[0] == AND:
3208 return (AND, e2[1] + [e1])
3209
3210 return (AND, [e1, e2])
3211
3212def _make_or(e1, e2):
3213 """Constructs an OR (||) expression. Performs trivial simplification and
3214 avoids Nones. Nones equate to 'y', which is usually what we want, but needs
3215 to be kept in mind."""
3216
3217 # Perform trivial simplification and avoid None's (which
3218 # correspond to y's)
3219 if e1 is None or e2 is None or e1 == "y" or e2 == "y":
3220 return "y"
3221 if e1 == "n":
3222 return e2
3223
3224 # Prefer to merge argument lists if possible to reduce the number of nodes
3225
3226 if isinstance(e1, tuple) and e1[0] == OR:
3227 if isinstance(e2, tuple) and e2[0] == OR:
3228 return (OR, e1[1] + e2[1])
3229 return (OR, e1[1] + [e2])
3230
3231 if isinstance(e2, tuple) and e2[0] == OR:
3232 return (OR, e2[1] + [e1])
3233
3234 return (OR, [e1, e2])
3235
3236def _get_expr_syms_rec(expr, res):
3237 """_get_expr_syms() helper. Recurses through expressions."""
3238 if isinstance(expr, Symbol):
3239 res.add(expr)
3240 elif isinstance(expr, str):
3241 return
3242 elif expr[0] == AND or expr[0] == OR:
3243 for term in expr[1]:
3244 _get_expr_syms_rec(term, res)
3245 elif expr[0] == NOT:
3246 _get_expr_syms_rec(expr[1], res)
3247 elif expr[0] == EQUAL or expr[0] == UNEQUAL:
3248 if isinstance(expr[1], Symbol):
3249 res.add(expr[1])
3250 if isinstance(expr[2], Symbol):
3251 res.add(expr[2])
3252 else:
3253 _internal_error("Internal error while fetching symbols from an "
3254 "expression with token stream {0}.".format(expr))
3255
3256def _get_expr_syms(expr):
3257 """Returns the set() of symbols appearing in expr."""
3258 res = set()
3259 if expr is not None:
3260 _get_expr_syms_rec(expr, res)
3261 return res
3262
3263def _str_val(obj):
3264 """Returns the value of obj as a string. If obj is not a string (constant
3265 symbol), it must be a Symbol."""
3266 return obj if isinstance(obj, str) else obj.get_value()
3267
3268def _make_block_conf(block, append_fn):
3269 """Returns a list of .config strings for a block (list) of items."""
3270
3271 # Collect the substrings in a list and later use join() instead of += to
3272 # build the final .config contents. With older Python versions, this yields
3273 # linear instead of quadratic complexity.
3274 for item in block:
3275 item._make_conf(append_fn)
3276
3277def _sym_str_string(sym_or_str):
3278 if isinstance(sym_or_str, str):
3279 return '"' + sym_or_str + '"'
3280 return sym_or_str.name
3281
3282def _intersperse(lst, op):
3283 """_expr_to_str() helper. Gets the string representation of each expression
3284 in lst and produces a list where op has been inserted between the
3285 elements."""
3286 if not lst:
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003287 return ""
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003288
3289 res = []
3290
3291 def handle_sub_expr(expr):
3292 no_parens = isinstance(expr, (str, Symbol)) or \
3293 expr[0] in (EQUAL, UNEQUAL) or \
3294 PRECEDENCE[op] <= PRECEDENCE[expr[0]]
3295 if not no_parens:
3296 res.append("(")
3297 res.extend(_expr_to_str_rec(expr))
3298 if not no_parens:
3299 res.append(")")
3300
3301 op_str = OP_TO_STR[op]
3302
3303 handle_sub_expr(lst[0])
3304 for expr in lst[1:]:
3305 res.append(op_str)
3306 handle_sub_expr(expr)
3307
3308 return res
3309
3310def _expr_to_str_rec(expr):
3311 if expr is None:
3312 return [""]
3313
3314 if isinstance(expr, (Symbol, str)):
3315 return [_sym_str_string(expr)]
3316
3317 if expr[0] in (AND, OR):
3318 return _intersperse(expr[1], expr[0])
3319
3320 if expr[0] == NOT:
3321 need_parens = not isinstance(expr[1], (str, Symbol))
3322
3323 res = ["!"]
3324 if need_parens:
3325 res.append("(")
3326 res.extend(_expr_to_str_rec(expr[1]))
3327 if need_parens:
3328 res.append(")")
3329 return res
3330
3331 if expr[0] in (EQUAL, UNEQUAL):
3332 return [_sym_str_string(expr[1]),
3333 OP_TO_STR[expr[0]],
3334 _sym_str_string(expr[2])]
3335
3336def _expr_to_str(expr):
3337 return "".join(_expr_to_str_rec(expr))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003338
3339def _indentation(line):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003340 """Returns the length of the line's leading whitespace, treating tab stops
3341 as being spaced 8 characters apart."""
3342 line = line.expandtabs()
3343 return len(line) - len(line.lstrip())
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003344
3345def _deindent(line, indent):
3346 """Deindent 'line' by 'indent' spaces."""
3347 line = line.expandtabs()
3348 if len(line) <= indent:
3349 return line
3350 return line[indent:]
3351
3352def _is_base_n(s, n):
3353 try:
3354 int(s, n)
3355 return True
3356 except ValueError:
3357 return False
3358
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003359def _lines(*args):
3360 """Returns a string consisting of all arguments, with newlines inserted
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003361 between them."""
3362 return "\n".join(args)
3363
3364def _comment(s):
3365 """Returns a new string with "#" inserted before each line in 's'."""
3366 if not s:
3367 return "#"
3368 res = "".join(["#" + line for line in s.splitlines(True)])
3369 if s.endswith("\n"):
3370 return res + "#"
3371 return res
3372
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003373def _clean_up_path(path):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003374 """Strips an initial "./" and any trailing slashes from 'path'."""
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003375 if path.startswith("./"):
3376 path = path[2:]
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003377 return path.rstrip("/")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003378
Simon Glass8639f692017-08-04 03:30:30 -06003379def _build_msg(msg, filename, linenr):
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003380 if filename is not None:
Simon Glass8639f692017-08-04 03:30:30 -06003381 msg = "{0}:{1}: ".format(_clean_up_path(filename), linenr) + msg
3382 return msg
3383
3384def _stderr_msg(msg, filename, linenr):
3385 sys.stderr.write(_build_msg(msg, filename, linenr) + "\n")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003386
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003387def _tokenization_error(s, filename, linenr):
3388 loc = "" if filename is None else "{0}:{1}: ".format(filename, linenr)
3389 raise Kconfig_Syntax_Error("{0}Couldn't tokenize '{1}'"
3390 .format(loc, s.strip()))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003391
3392def _parse_error(s, msg, filename, linenr):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003393 loc = "" if filename is None else "{0}:{1}: ".format(filename, linenr)
3394 raise Kconfig_Syntax_Error("{0}Couldn't parse '{1}'{2}"
3395 .format(loc, s.strip(),
3396 "." if msg is None else ": " + msg))
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003397
3398def _internal_error(msg):
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003399 raise Internal_Error(msg +
3400 "\nSorry! You may want to send an email to ulfalizer a.t Google's "
3401 "email service to tell me about this. Include the message above and the "
3402 "stack trace and describe what you were doing.")
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003403
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003404#
3405# Internal global constants
3406#
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003407
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003408# Tokens
3409(T_AND, T_OR, T_NOT,
3410 T_OPEN_PAREN, T_CLOSE_PAREN,
3411 T_EQUAL, T_UNEQUAL,
3412 T_MAINMENU, T_MENU, T_ENDMENU,
3413 T_SOURCE, T_CHOICE, T_ENDCHOICE,
3414 T_COMMENT, T_CONFIG, T_MENUCONFIG,
3415 T_HELP, T_IF, T_ENDIF, T_DEPENDS, T_ON,
3416 T_OPTIONAL, T_PROMPT, T_DEFAULT,
3417 T_BOOL, T_TRISTATE, T_HEX, T_INT, T_STRING,
3418 T_DEF_BOOL, T_DEF_TRISTATE,
Tom Rinid0361072017-03-03 15:33:29 -05003419 T_SELECT, T_IMPLY, T_RANGE, T_OPTION, T_ALLNOCONFIG_Y, T_ENV,
3420 T_DEFCONFIG_LIST, T_MODULES, T_VISIBLE) = range(40)
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003421
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003422# The leading underscore before the function assignments below prevent pydoc
3423# from listing them. The constants could be hidden too, but they're fairly
3424# obviously internal anyway, so don't bother spamming the code.
Masahiro Yamadaf219e012014-09-01 19:57:37 +09003425
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003426# Keyword to token map. Note that the get() method is assigned directly as a
3427# small optimization.
3428_get_keyword = \
3429 {"mainmenu": T_MAINMENU, "menu": T_MENU, "endmenu": T_ENDMENU,
3430 "endif": T_ENDIF, "endchoice": T_ENDCHOICE, "source": T_SOURCE,
3431 "choice": T_CHOICE, "config": T_CONFIG, "comment": T_COMMENT,
3432 "menuconfig": T_MENUCONFIG, "help": T_HELP, "if": T_IF,
3433 "depends": T_DEPENDS, "on": T_ON, "optional": T_OPTIONAL,
3434 "prompt": T_PROMPT, "default": T_DEFAULT, "bool": T_BOOL, "boolean": T_BOOL,
3435 "tristate": T_TRISTATE, "int": T_INT, "hex": T_HEX, "def_bool": T_DEF_BOOL,
3436 "def_tristate": T_DEF_TRISTATE, "string": T_STRING, "select": T_SELECT,
Tom Rinid0361072017-03-03 15:33:29 -05003437 "imply": T_IMPLY, "range": T_RANGE, "option": T_OPTION,
3438 "allnoconfig_y": T_ALLNOCONFIG_Y, "env": T_ENV,
3439 "defconfig_list": T_DEFCONFIG_LIST, "modules": T_MODULES,
Ulf Magnusson90c36d82015-08-13 19:55:40 +02003440 "visible": T_VISIBLE}.get
3441
3442# Strings to use for True and False
3443BOOL_STR = {False: "false", True: "true"}
3444
3445# Tokens after which identifier-like lexemes are treated as strings. T_CHOICE
3446# is included to avoid symbols being registered for named choices.
3447STRING_LEX = frozenset((T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING, T_CHOICE,
3448 T_PROMPT, T_MENU, T_COMMENT, T_SOURCE, T_MAINMENU))
3449
3450# Matches the initial token on a line; see _tokenize(). Also eats trailing
3451# whitespace as an optimization.
3452_initial_token_re_match = re.compile(r"[^\w]*(\w+)\s*").match
3453
3454# Matches an identifier/keyword optionally preceded by whitespace. Also eats
3455# trailing whitespace as an optimization.
3456_id_keyword_re_match = re.compile(r"\s*([\w./-]+)\s*").match
3457
3458# Regular expressions for parsing .config files
3459_set_re_match = re.compile(r"CONFIG_(\w+)=(.*)").match
3460_unset_re_match = re.compile(r"# CONFIG_(\w+) is not set").match
3461
3462# Regular expression for finding $-references to symbols in strings
3463_sym_ref_re_search = re.compile(r"\$[A-Za-z0-9_]+").search
3464
3465# Integers representing symbol types
3466UNKNOWN, BOOL, TRISTATE, STRING, HEX, INT = range(6)
3467
3468# Strings to use for types
3469TYPENAME = {UNKNOWN: "unknown", BOOL: "bool", TRISTATE: "tristate",
3470 STRING: "string", HEX: "hex", INT: "int"}
3471
3472# Token to type mapping
3473TOKEN_TO_TYPE = {T_BOOL: BOOL, T_TRISTATE: TRISTATE, T_STRING: STRING,
3474 T_INT: INT, T_HEX: HEX}
3475
3476# Default values for symbols of different types (the value the symbol gets if
3477# it is not assigned a user value and none of its 'default' clauses kick in)
3478DEFAULT_VALUE = {BOOL: "n", TRISTATE: "n", STRING: "", INT: "", HEX: ""}
3479
3480# Indicates that no item is selected in a choice statement
3481NO_SELECTION = 0
3482
3483# Integers representing expression types
3484AND, OR, NOT, EQUAL, UNEQUAL = range(5)
3485
3486# Map from tristate values to integers
3487TRI_TO_INT = {"n": 0, "m": 1, "y": 2}
3488
3489# Printing-related stuff
3490
3491OP_TO_STR = {AND: " && ", OR: " || ", EQUAL: " = ", UNEQUAL: " != "}
3492PRECEDENCE = {OR: 0, AND: 1, NOT: 2}