2 # SPDX-License-Identifier: ISC
4 # Author: Ulf Magnusson
5 # https://github.com/ulfalizer/Kconfiglib
7 # This is Kconfiglib, a Python library for scripting, debugging, and extracting
8 # information from Kconfig-based configuration systems. To view the
13 # or, if you prefer HTML,
15 # $ pydoc -w kconfiglib
17 # The examples/ subdirectory contains examples, to be run with e.g.
19 # $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
21 # Look in testsuite.py for the test suite.
24 Kconfiglib is a Python library for scripting and extracting information from
25 Kconfig-based configuration systems. Features include the following:
27 - Symbol values and properties can be looked up and values assigned
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.
37 For the Linux kernel, scripts are run using
39 $ make scriptconfig [ARCH=<arch>] SCRIPT=<path to script> [SCRIPT_ARG=<arg>]
41 Using the 'scriptconfig' target ensures that required environment variables
42 (SRCARCH, ARCH, srctree, KERNELVERSION, etc.) are set up correctly.
44 Scripts receive the name of the Kconfig file to load in sys.argv[1]. As of
45 Linux 4.1.0-rc5, this is always "Kconfig" from the kernel top-level directory.
46 If an argument is provided with SCRIPT_ARG, it appears as sys.argv[2].
48 To get an interactive Python prompt with Kconfiglib preloaded and a Config
49 object 'c' created, run
51 $ make iscriptconfig [ARCH=<arch>]
53 Kconfiglib supports both Python 2 and Python 3. For (i)scriptconfig, the Python
54 interpreter to use can be passed in PYTHONCMD, which defaults to 'python'. PyPy
55 works well too, and might give a nice speedup for long-running jobs.
57 The examples/ directory contains short example scripts, which can be run with
60 $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
64 $ make scriptconfig SCRIPT=Kconfiglib/examples/help_grep.py SCRIPT_ARG=kernel
66 testsuite.py contains the test suite. See the top of the script for how to run
69 Credits: Written by Ulf "Ulfalizer" Magnusson
71 Send bug reports, suggestions and other feedback to ulfalizer a.t Google's
72 email service. Don't wrestle with internal APIs. Tell me what you need and I
73 might add it in a safe way as a client API instead."""
85 # Internal global constants
87 # Line length: 79 columns
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."""
104 def __init__(self, filename="Kconfig", base_dir=None, print_warnings=True,
105 print_undef_assign=False):
106 """Creates a new Config object, representing a Kconfig configuration.
107 Raises Kconfig_Syntax_Error on syntax errors.
109 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
117 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.
122 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.
127 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.
132 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()."""
137 # The set of all symbols, indexed by name (a string)
139 # 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
143 self.syms_iter = self.syms.itervalues
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 = []
150 # The set of all named choices (yes, choices can have names), indexed
152 self.named_choices = {}
154 # Lists containing all choices, menus and comments in the configuration
159 def register_special_symbol(type_, name, val):
161 sym.is_special_ = True
162 sym.is_defined_ = True
167 self.syms[name] = sym
170 # The special symbols n, m and y, used as shorthand for "n", "m" and
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")
175 # DEFCONFIG_LIST uses this
176 register_special_symbol(STRING, "UNAME_RELEASE", os.uname()[2])
178 # The symbol with "option defconfig_list" set, containing a list of
179 # default .config files
180 self.defconfig_sym = None
182 # See Symbol.get_(src)arch()
183 self.arch = os.environ.get("ARCH")
184 self.srcarch = os.environ.get("SRCARCH")
186 # See Config.__init__(). We need this for get_defconfig_filename().
187 self.srctree = os.environ.get("srctree")
188 if self.srctree is None:
191 self.filename = filename
193 self.base_dir = self.srctree
195 self.base_dir = os.path.expandvars(base_dir)
197 # The 'mainmenu' text
198 self.mainmenu_text = None
200 # The filename of the most recently loaded .config file
201 self.config_filename = None
202 # The textual header of the most recently loaded .config, uncommented
203 self.config_header = None
205 self.print_warnings = print_warnings
206 self.print_undef_assign = print_undef_assign
208 # For parsing routines that stop when finding a line belonging to a
209 # different construct, these holds that line and the tokenized version
210 # of that line. The purpose is to avoid having to re-tokenize the line,
211 # which is inefficient and causes problems when recording references to
214 self.end_line_tokens = None
216 # See the comment in _parse_expr().
217 self._cur_item = None
219 self._filename = None
221 self._transform_m = None
223 # Parse the Kconfig files
224 self.top_block = self._parse_file(filename, None, None, None)
226 # Build Symbol.dep for all symbols
230 """Returns the value the environment variable ARCH had at the time the
231 Config instance was created, or None if ARCH was not set. For the
232 kernel, this corresponds to the architecture being built for, with
233 values such as "i386" or "mips"."""
236 def get_srcarch(self):
237 """Returns the value the environment variable SRCARCH had at the time
238 the Config instance was created, or None if SRCARCH was not set. For
239 the kernel, this corresponds to the particular arch/ subdirectory
240 containing architecture-specific code."""
243 def get_srctree(self):
244 """Returns the value the environment variable srctree had at the time
245 the Config instance was created, or None if srctree was not defined.
246 This variable points to the source directory and is used when building
247 in a separate directory."""
250 def get_base_dir(self):
251 """Returns the base directory relative to which 'source' statements
252 will work, passed as an argument to Config.__init__()."""
255 def get_kconfig_filename(self):
256 """Returns the name of the (base) kconfig file this configuration was
260 def get_config_filename(self):
261 """Returns the filename of the most recently loaded configuration file,
262 or None if no configuration has been loaded."""
263 return self.config_filename
265 def get_config_header(self):
266 """Returns the (uncommented) textual header of the .config file most
267 recently loaded with load_config(). Returns None if no .config file has
268 been loaded or if the most recently loaded .config file has no header.
269 The header consists of all lines up to but not including the first line
272 1. Does not start with "#"
273 2. Has the form "# CONFIG_FOO is not set."
275 return self.config_header
277 def get_mainmenu_text(self):
278 """Returns the text of the 'mainmenu' statement (with $-references to
279 symbols replaced by symbol values), or None if the configuration has no
280 'mainmenu' statement."""
281 return None if self.mainmenu_text is None else \
282 self._expand_sym_refs(self.mainmenu_text)
284 def get_defconfig_filename(self):
285 """Returns the name of the defconfig file, which is the first existing
286 file in the list given in a symbol having 'option defconfig_list' set.
287 $-references to symbols will be expanded ("$FOO bar" -> "foo bar" if
288 FOO has the value "foo"). Returns None in case of no defconfig file.
289 Setting 'option defconfig_list' on multiple symbols currently results
290 in undefined behavior.
292 If the environment variable 'srctree' was set when the Config was
293 created, get_defconfig_filename() will first look relative to that
294 directory before looking in the current directory; see
297 WARNING: A wart here is that scripts/kconfig/Makefile sometimes uses
298 the --defconfig=<defconfig> option when calling the C implementation of
299 e.g. 'make defconfig'. This option overrides the 'option
300 defconfig_list' symbol, meaning the result from
301 get_defconfig_filename() might not match what 'make defconfig' would
302 use. That probably ought to be worked around somehow, so that this
303 function always gives the "expected" result."""
304 if self.defconfig_sym is None:
306 for filename, cond_expr in self.defconfig_sym.def_exprs:
307 if self._eval_expr(cond_expr) == "y":
308 filename = self._expand_sym_refs(filename)
309 # We first look in $srctree. os.path.join() won't work here as
310 # an absolute path in filename would override $srctree.
311 srctree_filename = os.path.normpath(self.srctree + "/" +
313 if os.path.exists(srctree_filename):
314 return srctree_filename
315 if os.path.exists(filename):
319 def get_symbol(self, name):
320 """Returns the symbol with name 'name', or None if no such symbol
321 appears in the configuration. An alternative shorthand is conf[name],
322 where conf is a Config instance, though that will instead raise
323 KeyError if the symbol does not exist."""
324 return self.syms.get(name)
326 def __getitem__(self, name):
327 """Returns the symbol with name 'name'. Raises KeyError if the symbol
328 does not appear in the configuration."""
329 return self.syms[name]
331 def get_symbols(self, all_symbols=True):
332 """Returns a list of symbols from the configuration. An alternative for
333 iterating over all defined symbols (in the order of definition) is
338 which relies on Config implementing __iter__() and is equivalent to
340 for sym in config.get_symbols(False):
343 all_symbols (default: True): If True, all symbols -- including special
344 and undefined symbols -- will be included in the result, in an
345 undefined order. If False, only symbols actually defined and not
346 merely referred to in the configuration will be included in the
347 result, and will appear in the order that they are defined within
348 the Kconfig configuration files."""
349 return list(self.syms.values()) if all_symbols else self.kconfig_syms
352 """Convenience function for iterating over the set of all defined
353 symbols in the configuration, used like
358 The iteration happens in the order of definition within the Kconfig
359 configuration files. Symbols only referred to but not defined will not
360 be included, nor will the special symbols n, m, and y. If you want to
361 include such symbols as well, see config.get_symbols()."""
362 return iter(self.kconfig_syms)
364 def get_choices(self):
365 """Returns a list containing all choice statements in the
366 configuration, in the order they appear in the Kconfig files."""
370 """Returns a list containing all menus in the configuration, in the
371 order they appear in the Kconfig files."""
374 def get_comments(self):
375 """Returns a list containing all comments in the configuration, in the
376 order they appear in the Kconfig files."""
379 def get_top_level_items(self):
380 """Returns a list containing the items (symbols, menus, choices, and
381 comments) at the top level of the configuration -- that is, all items
382 that do not appear within a menu or choice. The items appear in the
383 same order as within the configuration."""
384 return self.top_block
386 def load_config(self, filename, replace=True):
387 """Loads symbol values from a file in the familiar .config format.
388 Equivalent to calling Symbol.set_user_value() to set each of the
391 "# CONFIG_FOO is not set" within a .config file is treated specially
392 and sets the user value of FOO to 'n'. The C implementation works the
395 filename: The .config file to load. $-references to existing
396 environment variables will be expanded. For scripts to work even when
397 an alternative build directory is used with the Linux kernel, you
398 need to refer to the top-level kernel directory with "$srctree".
400 replace (default: True): True if the configuration should replace the
401 old configuration; False if it should add to it."""
403 # Put this first so that a missing file doesn't screw up our state
404 filename = os.path.expandvars(filename)
405 line_feeder = _FileFeed(filename)
407 self.config_filename = filename
413 def is_header_line(line):
414 return line is not None and line.startswith("#") and \
415 not _unset_re_match(line)
417 self.config_header = None
419 line = line_feeder.peek_next()
420 if is_header_line(line):
421 self.config_header = ""
422 while is_header_line(line_feeder.peek_next()):
423 self.config_header += line_feeder.get_next()[1:]
424 # Remove trailing newline
425 if self.config_header.endswith("\n"):
426 self.config_header = self.config_header[:-1]
429 # Read assignments. Hotspot for some workloads.
432 def warn_override(filename, linenr, name, old_user_val, new_user_val):
433 self._warn('overriding the value of {0}. '
434 'Old value: "{1}", new value: "{2}".'
435 .format(name, old_user_val, new_user_val),
438 # Invalidate everything to keep things simple. It might be possible to
439 # improve performance for the case where multiple configurations are
440 # loaded by only invalidating a symbol (and its dependent symbols) if
441 # the new user value differs from the old. One complication would be
442 # that symbols not mentioned in the .config must lose their user value
443 # when replace = True, which is the usual case.
445 self.unset_user_values()
447 self._invalidate_all()
450 line = line_feeder.get_next()
456 set_match = _set_re_match(line)
458 name, val = set_match.groups()
460 if val.startswith('"'):
461 if len(val) < 2 or val[-1] != '"':
462 _parse_error(line, "malformed string literal",
463 line_feeder.filename, line_feeder.linenr)
464 # Strip quotes and remove escapings. The unescaping
465 # procedure should be safe since " can only appear as \"
467 val = val[1:-1].replace('\\"', '"').replace("\\\\", "\\")
469 if name in self.syms:
470 sym = self.syms[name]
471 if sym.user_val is not None:
472 warn_override(line_feeder.filename, line_feeder.linenr,
473 name, sym.user_val, val)
475 if sym.is_choice_sym:
476 user_mode = sym.parent.user_mode
477 if user_mode is not None and user_mode != val:
478 self._warn("assignment to {0} changes mode of "
479 'containing choice from "{1}" to "{2}".'
480 .format(name, val, user_mode),
481 line_feeder.filename,
484 sym._set_user_value_no_invalidate(val, True)
486 if self.print_undef_assign:
487 _stderr_msg('note: attempt to assign the value "{0}" '
488 "to the undefined symbol {1}."
490 line_feeder.filename, line_feeder.linenr)
492 unset_match = _unset_re_match(line)
494 name = unset_match.group(1)
495 if name in self.syms:
496 sym = self.syms[name]
497 if sym.user_val is not None:
498 warn_override(line_feeder.filename,
500 name, sym.user_val, "n")
502 sym._set_user_value_no_invalidate("n", True)
504 def write_config(self, filename, header=None):
505 """Writes out symbol values in the familiar .config format.
507 Kconfiglib makes sure the format matches what the C implementation
508 would generate, down to whitespace. This eases testing.
510 filename: The filename under which to save the configuration.
512 header (default: None): A textual header that will appear at the
513 beginning of the file, with each line commented out automatically.
514 None means no header."""
516 for sym in self.syms_iter():
517 sym.already_written = False
519 with open(filename, "w") as f:
521 if header is not None:
522 f.write(_comment(header))
525 # Build and write configuration
527 _make_block_conf(self.top_block, conf_strings.append)
528 f.write("\n".join(conf_strings))
532 """Returns the value of the expression 's' -- where 's' is represented
533 as a string -- in the context of the configuration. Raises
534 Kconfig_Syntax_Error if syntax errors are detected in 's'.
536 For example, if FOO and BAR are tristate symbols at least one of which
537 has the value "y", then config.eval("y && (FOO || BAR)") => "y"
539 This function always yields a tristate value. To get the value of
540 non-bool, non-tristate symbols, use Symbol.get_value().
542 The result of this function is consistent with how evaluation works for
543 conditional expressions in the configuration as well as in the C
544 implementation. "m" and m are rewritten as '"m" && MODULES' and 'm &&
545 MODULES', respectively, and a result of "m" will get promoted to "y" if
546 we're running without modules.
548 Syntax checking is somewhat lax, partly to be compatible with lax
549 parsing in the C implementation."""
550 return self._eval_expr(self._parse_expr(self._tokenize(s, True), # Feed
551 None, # Current symbol/choice
554 def unset_user_values(self):
555 """Resets the values of all symbols, as if Config.load_config() or
556 Symbol.set_user_value() had never been called."""
557 for sym in self.syms_iter():
558 sym._unset_user_value_no_recursive_invalidate()
560 def set_print_warnings(self, print_warnings):
561 """Determines whether warnings related to this configuration (for
562 things like attempting to assign illegal values to symbols with
563 Symbol.set_user_value()) should be printed to stderr.
565 print_warnings: True if warnings should be printed."""
566 self.print_warnings = print_warnings
568 def set_print_undef_assign(self, print_undef_assign):
569 """Determines whether informational messages related to assignments to
570 undefined symbols should be printed to stderr for this configuration.
572 print_undef_assign: If True, such messages will be printed."""
573 self.print_undef_assign = print_undef_assign
576 """Returns a string containing various information about the Config."""
577 return _lines("Configuration",
580 "Base directory : " +
582 "Value of $ARCH at creation time : " +
583 ("(not set)" if self.arch is None else self.arch),
584 "Value of $SRCARCH at creation time : " +
585 ("(not set)" if self.srcarch is None else
587 "Source tree (derived from $srctree;",
588 "defaults to '.' if $srctree isn't set) : " +
590 "Most recently loaded .config : " +
591 ("(no .config loaded)"
592 if self.config_filename is None else
593 self.config_filename),
594 "Print warnings : " +
595 BOOL_STR[self.print_warnings],
596 "Print assignments to undefined symbols : " +
597 BOOL_STR[self.print_undef_assign])
607 def _parse_file(self, filename, parent, deps, visible_if_deps, res=None):
608 """Parses the Kconfig file 'filename'. Returns a list with the Items in
609 the file. See _parse_block() for the meaning of the parameters."""
610 return self._parse_block(_FileFeed(filename), None, parent, deps,
611 visible_if_deps, res)
613 def _parse_block(self, line_feeder, end_marker, parent, deps,
614 visible_if_deps, res=None):
615 """Parses a block, which is the contents of either a file or an if,
616 menu, or choice statement. Returns a list with the Items in the block.
618 line_feeder: A _FileFeed instance feeding lines from a file. The
619 Kconfig language is line-based in practice.
621 end_marker: The token that ends the block, e.g. T_ENDIF ("endif") for
624 parent: The enclosing menu or choice, or None if we're at the top
627 deps: Dependencies from enclosing menus, choices and ifs.
629 visible_if_deps (default: None): 'visible if' dependencies from
632 res (default: None): The list to add items to. If None, a new list is
633 created to hold the items."""
635 block = [] if res is None else res
638 # Do we already have a tokenized line that we determined wasn't
639 # part of whatever we were parsing earlier? See comment in
641 if self.end_line is not None:
643 tokens = self.end_line_tokens
647 self.end_line_tokens = None
649 line = line_feeder.get_next()
651 if end_marker is not None:
652 raise Kconfig_Syntax_Error("Unexpected end of file {0}"
653 .format(line_feeder.filename))
656 tokens = self._tokenize(line, False, line_feeder.filename,
659 t0 = tokens.get_next()
663 # Cases are ordered roughly by frequency, which speeds things up a
666 if t0 == T_CONFIG or t0 == T_MENUCONFIG:
667 # The tokenizer will automatically allocate a new Symbol object
668 # for any new names it encounters, so we don't need to worry
670 sym = tokens.get_next()
672 # Symbols defined in multiple places get the parent of their
673 # first definition. However, for symbols whose parents are
674 # choice statements, the choice statement takes precedence.
675 if not sym.is_defined_ or isinstance(parent, Choice):
678 sym.is_defined_ = True
680 self.kconfig_syms.append(sym)
683 self._parse_properties(line_feeder, sym, deps, visible_if_deps)
686 kconfig_file = tokens.get_next()
687 exp_kconfig_file = self._expand_sym_refs(kconfig_file)
688 f = os.path.join(self.base_dir, exp_kconfig_file)
689 if not os.path.exists(f):
690 raise IOError('{0}:{1}: sourced file "{2}" (expands to '
691 '"{3}") not found. Perhaps base_dir '
692 '(argument to Config.__init__(), currently '
693 '"{4}") is set to the wrong value.'
694 .format(line_feeder.filename,
696 kconfig_file, exp_kconfig_file,
698 # Add items to the same block
699 self._parse_file(f, parent, deps, visible_if_deps, block)
701 elif t0 == end_marker:
702 # We have reached the end of the block
706 # If statements are treated as syntactic sugar for adding
707 # dependencies to enclosed items and do not have an explicit
708 # object representation.
710 dep_expr = self._parse_expr(tokens, None, line,
711 line_feeder.filename,
713 # Add items to the same block
714 self._parse_block(line_feeder, T_ENDIF, parent,
715 _make_and(dep_expr, deps),
716 visible_if_deps, block)
718 elif t0 == T_COMMENT:
721 comment.config = self
722 comment.parent = parent
723 comment.filename = line_feeder.filename
724 comment.linenr = line_feeder.linenr
725 comment.text = tokens.get_next()
727 self.comments.append(comment)
728 block.append(comment)
730 self._parse_properties(line_feeder, comment, deps,
738 menu.filename = line_feeder.filename
739 menu.linenr = line_feeder.linenr
740 menu.title = tokens.get_next()
742 self.menus.append(menu)
745 # Parse properties and contents
746 self._parse_properties(line_feeder, menu, deps,
748 menu.block = self._parse_block(line_feeder, T_ENDMENU, menu,
750 _make_and(visible_if_deps,
751 menu.visible_if_expr))
754 name = tokens.get_next()
757 self.choices.append(choice)
760 choice = self.named_choices.get(name)
764 self.named_choices[name] = choice
765 self.choices.append(choice)
768 choice.parent = parent
770 choice.def_locations.append((line_feeder.filename,
773 # Parse properties and contents
774 self._parse_properties(line_feeder, choice, deps,
776 choice.block = self._parse_block(line_feeder, T_ENDCHOICE,
777 choice, deps, visible_if_deps)
779 choice._determine_actual_symbols()
781 # If no type is specified for the choice, its type is that of
782 # the first choice item with a specified type
783 if choice.type == UNKNOWN:
784 for item in choice.actual_symbols:
785 if item.type != UNKNOWN:
786 choice.type = item.type
789 # Each choice item of UNKNOWN type gets the type of the choice
790 for item in choice.actual_symbols:
791 if item.type == UNKNOWN:
792 item.type = choice.type
796 elif t0 == T_MAINMENU:
797 text = tokens.get_next()
798 if self.mainmenu_text is not None:
799 self._warn("overriding 'mainmenu' text. "
800 'Old value: "{0}", new value: "{1}".'
801 .format(self.mainmenu_text, text),
802 line_feeder.filename, line_feeder.linenr)
803 self.mainmenu_text = text
806 _parse_error(line, "unrecognized construct",
807 line_feeder.filename, line_feeder.linenr)
809 def _parse_properties(self, line_feeder, stmt, deps, visible_if_deps):
810 """Parsing of properties for symbols, menus, choices, and comments.
811 Takes care of propagating dependencies from enclosing menus and ifs."""
813 def parse_val_and_cond(tokens, line, filename, linenr):
814 """Parses '<expr1> if <expr2>' constructs, where the 'if' part is
815 optional. Returns a tuple containing the parsed expressions, with
816 None as the second element if the 'if' part is missing."""
817 val = self._parse_expr(tokens, stmt, line, filename, linenr, False)
818 if tokens.check(T_IF):
819 return (val, self._parse_expr(tokens, stmt, line, filename,
823 # In case the symbol is defined in multiple locations, we need to
824 # remember what prompts, defaults, and selects are new for this
825 # definition, as "depends on" should only apply to the local
831 # Dependencies from 'depends on' statements
832 depends_on_expr = None
835 line = line_feeder.get_next()
839 filename = line_feeder.filename
840 linenr = line_feeder.linenr
842 tokens = self._tokenize(line, False, filename, linenr)
844 t0 = tokens.get_next()
848 # Cases are ordered roughly by frequency, which speeds things up a
852 if not tokens.check(T_ON):
853 _parse_error(line, 'expected "on" after "depends"',
856 parsed_deps = self._parse_expr(tokens, stmt, line, filename,
859 if isinstance(stmt, (Menu, Comment)):
860 stmt.orig_deps = _make_and(stmt.orig_deps, parsed_deps)
862 depends_on_expr = _make_and(depends_on_expr, parsed_deps)
865 # Find first non-blank (not all-space) line and get its
867 line = line_feeder.next_nonblank()
871 indent = _indentation(line)
873 # If the first non-empty lines has zero indent, there is no
879 # The help text goes on till the first non-empty line with less
881 help_lines = [_deindent(line, indent)]
883 line = line_feeder.get_next()
885 (not line.isspace() and _indentation(line) < indent):
886 stmt.help = "".join(help_lines)
888 help_lines.append(_deindent(line, indent))
895 elif t0 == T_SELECT or t0 == T_IMPLY:
896 target = tokens.get_next()
898 stmt.referenced_syms.add(target)
899 stmt.selected_syms.add(target)
901 if tokens.check(T_IF):
902 new_selects.append((target,
903 self._parse_expr(tokens, stmt, line,
906 new_selects.append((target, None))
908 elif t0 in (T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING):
909 stmt.type = TOKEN_TO_TYPE[t0]
910 if tokens.peek_next() is not None:
911 new_prompt = parse_val_and_cond(tokens, line, filename,
914 elif t0 == T_DEFAULT:
915 new_def_exprs.append(parse_val_and_cond(tokens, line, filename,
918 elif t0 == T_DEF_BOOL:
920 if tokens.peek_next() is not None:
921 new_def_exprs.append(parse_val_and_cond(tokens, line,
925 # 'prompt' properties override each other within a single
926 # definition of a symbol, but additional prompts can be added
927 # by defining the symbol multiple times; hence 'new_prompt'
928 # instead of 'prompt'.
929 new_prompt = parse_val_and_cond(tokens, line, filename, linenr)
932 low = tokens.get_next()
933 high = tokens.get_next()
934 stmt.referenced_syms.add(low)
935 stmt.referenced_syms.add(high)
937 if tokens.check(T_IF):
938 stmt.ranges.append((low, high,
939 self._parse_expr(tokens, stmt, line,
942 stmt.ranges.append((low, high, None))
944 elif t0 == T_DEF_TRISTATE:
946 if tokens.peek_next() is not None:
947 new_def_exprs.append(parse_val_and_cond(tokens, line,
951 if tokens.check(T_ENV) and tokens.check(T_EQUAL):
952 env_var = tokens.get_next()
954 stmt.is_special_ = True
955 stmt.is_from_env = True
957 if env_var not in os.environ:
958 self._warn("The symbol {0} references the "
959 "non-existent environment variable {1} and "
960 "will get the empty string as its value. "
961 "If you're using Kconfiglib via "
962 "'make (i)scriptconfig', it should have "
963 "set up the environment correctly for you. "
964 "If you still got this message, that "
965 "might be an error, and you should email "
966 "ulfalizer a.t Google's email service."""
967 .format(stmt.name, env_var),
972 stmt.cached_val = os.environ[env_var]
974 elif tokens.check(T_DEFCONFIG_LIST):
975 self.defconfig_sym = stmt
977 elif tokens.check(T_MODULES):
978 # To reduce warning spam, only warn if 'option modules' is
979 # set on some symbol that isn't MODULES, which should be
980 # safe. I haven't run into any projects that make use
981 # modules besides the kernel yet, and there it's likely to
982 # keep being called "MODULES".
983 if stmt.name != "MODULES":
984 self._warn("the 'modules' option is not supported. "
985 "Let me know if this is a problem for you; "
986 "it shouldn't be that hard to implement. "
987 "(Note that modules are still supported -- "
988 "Kconfiglib just assumes the symbol name "
989 "MODULES, like older versions of the C "
990 "implementation did when 'option modules' "
994 elif tokens.check(T_ALLNOCONFIG_Y):
995 if not isinstance(stmt, Symbol):
997 "the 'allnoconfig_y' option is only "
1000 stmt.allnoconfig_y = True
1003 _parse_error(line, "unrecognized option", filename, linenr)
1005 elif t0 == T_VISIBLE:
1006 if not tokens.check(T_IF):
1007 _parse_error(line, 'expected "if" after "visible"',
1009 if not isinstance(stmt, Menu):
1011 "'visible if' is only valid for menus",
1014 parsed_deps = self._parse_expr(tokens, stmt, line, filename,
1016 stmt.visible_if_expr = _make_and(stmt.visible_if_expr,
1019 elif t0 == T_OPTIONAL:
1020 if not isinstance(stmt, Choice):
1022 '"optional" is only valid for choices',
1025 stmt.optional = True
1028 # See comment in Config.__init__()
1029 self.end_line = line
1030 self.end_line_tokens = tokens
1033 # Done parsing properties. Now propagate 'depends on' and enclosing
1034 # menu/if dependencies to expressions.
1036 # The set of symbols referenced directly by the statement plus all
1037 # symbols referenced by enclosing menus and ifs
1038 stmt.all_referenced_syms = stmt.referenced_syms | _get_expr_syms(deps)
1040 # Save original dependencies from enclosing menus and ifs
1041 stmt.deps_from_containing = deps
1043 if isinstance(stmt, (Menu, Comment)):
1044 stmt.dep_expr = _make_and(stmt.orig_deps, deps)
1048 # See comment for 'menu_dep'
1049 stmt.menu_dep = depends_on_expr
1051 # Propagate dependencies to prompts
1053 if new_prompt is not None:
1054 # Propagate 'visible if' dependencies from enclosing menus
1055 prompt, cond_expr = new_prompt
1056 cond_expr = _make_and(cond_expr, visible_if_deps)
1057 # Propagate 'depends on' dependencies
1058 new_prompt = (prompt, _make_and(cond_expr, depends_on_expr))
1060 stmt.orig_prompts.append(new_prompt)
1061 # Finalize with dependencies from enclosing menus and ifs
1062 stmt.prompts.append((new_prompt[0],
1063 _make_and(new_prompt[1], deps)))
1065 # Propagate dependencies to defaults
1067 # Propagate 'depends on' dependencies
1068 new_def_exprs = [(val_expr, _make_and(cond_expr, depends_on_expr))
1069 for val_expr, cond_expr in new_def_exprs]
1071 stmt.orig_def_exprs.extend(new_def_exprs)
1072 # Finalize with dependencies from enclosing menus and ifs
1073 stmt.def_exprs.extend([(val_expr, _make_and(cond_expr, deps))
1074 for val_expr, cond_expr in new_def_exprs])
1076 # Propagate dependencies to selects
1078 # Only symbols can select
1079 if isinstance(stmt, Symbol):
1080 # Propagate 'depends on' dependencies
1081 new_selects = [(target, _make_and(cond_expr, depends_on_expr))
1082 for target, cond_expr in new_selects]
1084 stmt.orig_selects.extend(new_selects)
1085 # Finalize with dependencies from enclosing menus and ifs
1086 for target, cond in new_selects:
1087 target.rev_dep = _make_or(target.rev_dep,
1089 _make_and(cond, deps)))
1091 def _parse_expr(self, feed, cur_item, line, filename=None, linenr=None,
1093 """Parses an expression from the tokens in 'feed' using a simple
1094 top-down approach. The result has the form
1095 '(<operator>, [<parsed operands>])', where <operator> is e.g.
1096 kconfiglib.AND. If there is only one operand (i.e., no && or ||), then
1097 the operand is returned directly. This also goes for subexpressions.
1099 feed: _Feed instance containing the tokens for the expression.
1101 cur_item: The item (Symbol, Choice, Menu, or Comment) currently being
1102 parsed, or None if we're not parsing an item. Used for recording
1103 references to symbols.
1105 line: The line containing the expression being parsed.
1107 filename (default: None): The file containing the expression.
1109 linenr (default: None): The line number containing the expression.
1111 transform_m (default: False): Determines if 'm' should be rewritten to
1112 'm && MODULES' -- see parse_val_and_cond().
1114 Expression grammar, in decreasing order of precedence:
1117 <symbol> '=' <symbol>
1118 <symbol> '!=' <symbol>
1122 <expr> '||' <expr>"""
1124 # Use instance variables to avoid having to pass these as arguments
1125 # through the top-down parser in _parse_expr_rec(), which is tedious
1126 # and obfuscates the code. A profiler run shows no noticeable
1127 # performance difference.
1128 self._cur_item = cur_item
1129 self._transform_m = transform_m
1131 self._filename = filename
1132 self._linenr = linenr
1134 return self._parse_expr_rec(feed)
1136 def _parse_expr_rec(self, feed):
1137 or_term = self._parse_or_term(feed)
1138 if not feed.check(T_OR):
1139 # Common case -- no need for an OR node since it's just a single
1142 or_terms = [or_term, self._parse_or_term(feed)]
1143 while feed.check(T_OR):
1144 or_terms.append(self._parse_or_term(feed))
1145 return (OR, or_terms)
1147 def _parse_or_term(self, feed):
1148 and_term = self._parse_factor(feed)
1149 if not feed.check(T_AND):
1150 # Common case -- no need for an AND node since it's just a single
1153 and_terms = [and_term, self._parse_factor(feed)]
1154 while feed.check(T_AND):
1155 and_terms.append(self._parse_factor(feed))
1156 return (AND, and_terms)
1158 def _parse_factor(self, feed):
1159 token = feed.get_next()
1161 if isinstance(token, (Symbol, str)):
1162 if self._cur_item is not None and isinstance(token, Symbol):
1163 self._cur_item.referenced_syms.add(token)
1165 next_token = feed.peek_next()
1166 # For conditional expressions ('depends on <expr>',
1167 # '... if <expr>', # etc.), "m" and m are rewritten to
1169 if next_token != T_EQUAL and next_token != T_UNEQUAL:
1170 if self._transform_m and (token is self.m or token == "m"):
1171 return (AND, ["m", self._sym_lookup("MODULES")])
1174 relation = EQUAL if (feed.get_next() == T_EQUAL) else UNEQUAL
1175 token_2 = feed.get_next()
1176 if self._cur_item is not None and isinstance(token_2, Symbol):
1177 self._cur_item.referenced_syms.add(token_2)
1178 return (relation, token, token_2)
1181 return (NOT, self._parse_factor(feed))
1183 if token == T_OPEN_PAREN:
1184 expr_parse = self._parse_expr_rec(feed)
1185 if not feed.check(T_CLOSE_PAREN):
1186 _parse_error(self._line, "missing end parenthesis",
1187 self._filename, self._linenr)
1190 _parse_error(self._line, "malformed expression", self._filename,
1193 def _tokenize(self, s, for_eval, filename=None, linenr=None):
1194 """Returns a _Feed instance containing tokens derived from the string
1195 's'. Registers any new symbols encountered (via _sym_lookup()).
1197 (I experimented with a pure regular expression implementation, but it
1198 came out slower, less readable, and wouldn't have been as flexible.)
1200 for_eval: True when parsing an expression for a call to Config.eval(),
1201 in which case we should not treat the first token specially nor
1202 register new symbols."""
1205 if s == "" or s[0] == "#":
1209 previous = None # The previous token seen
1211 i = 0 # The current index in the string being tokenized
1214 # The initial word on a line is parsed specially. Let
1215 # command_chars = [A-Za-z0-9_]. Then
1216 # - leading non-command_chars characters are ignored, and
1217 # - the first token consists the following one or more
1218 # command_chars characters.
1219 # This is why things like "----help--" are accepted.
1220 initial_token_match = _initial_token_re_match(s)
1221 if initial_token_match is None:
1223 keyword = _get_keyword(initial_token_match.group(1))
1224 if keyword == T_HELP:
1225 # Avoid junk after "help", e.g. "---", being registered as a
1227 return _Feed([T_HELP])
1229 # We expect a keyword as the first token
1230 _tokenization_error(s, filename, linenr)
1234 # The current index in the string being tokenized
1235 i = initial_token_match.end()
1237 # _tokenize() is a hotspot during parsing, and this speeds things up a
1240 append = tokens.append
1242 # Main tokenization loop. (Handles tokens past the first one.)
1244 # Test for an identifier/keyword preceded by whitespace first; this
1245 # is the most common case.
1246 id_keyword_match = _id_keyword_re_match(s, i)
1247 if id_keyword_match:
1248 # We have an identifier or keyword. The above also stripped any
1249 # whitespace for us.
1250 name = id_keyword_match.group(1)
1252 i = id_keyword_match.end()
1254 keyword = _get_keyword(name)
1255 if keyword is not None:
1258 elif previous in STRING_LEX:
1259 # What would ordinarily be considered an identifier is
1260 # treated as a string after certain tokens
1263 # It's a symbol name. _sym_lookup() will take care of
1264 # allocating a new Symbol instance if it's the first time
1266 sym = self._sym_lookup(name, for_eval)
1268 if previous == T_CONFIG or previous == T_MENUCONFIG:
1269 # If the previous token is T_(MENU)CONFIG
1270 # ("(menu)config"), we're tokenizing the first line of
1271 # a symbol definition, and should remember this as a
1272 # location where the symbol is defined
1273 sym.def_locations.append((filename, linenr))
1275 # Otherwise, it's a reference to the symbol
1276 sym.ref_locations.append((filename, linenr))
1281 # Not an identifier/keyword
1283 while i < strlen and s[i].isspace():
1290 # String literal (constant symbol)
1291 if c == '"' or c == "'":
1293 # Slow path: This could probably be sped up, but it's a
1294 # very unusual case anyway.
1299 _tokenization_error(s, filename, linenr)
1305 _tokenization_error(s, filename, linenr)
1314 # Fast path: If the string contains no backslashes
1315 # (almost always) we can simply look for the matching
1319 _tokenization_error(s, filename, linenr)
1324 # Invalid characters are ignored
1325 if i >= len(s) or s[i] != "&": continue
1330 # Invalid characters are ignored
1331 if i >= len(s) or s[i] != "|": continue
1336 if i < len(s) and s[i] == "=":
1342 elif c == "=": append(T_EQUAL)
1343 elif c == "(": append(T_OPEN_PAREN)
1344 elif c == ")": append(T_CLOSE_PAREN)
1345 elif c == "#": break # Comment
1347 else: continue # Invalid characters are ignored
1349 previous = tokens[-1]
1351 return _Feed(tokens)
1353 def _sym_lookup(self, name, for_eval=False):
1354 """Fetches the symbol 'name' from the symbol table, creating and
1355 registering it if it does not exist. If 'for_eval' is True, the symbol
1356 won't be added to the symbol table if it does not exist -- this is for
1358 if name in self.syms:
1359 return self.syms[name]
1362 new_sym.config = self
1365 self._warn("no symbol {0} in configuration".format(name))
1367 self.syms[name] = new_sym
1371 # Expression evaluation
1374 def _eval_expr(self, expr):
1375 """Evaluates an expression to "n", "m", or "y"."""
1377 # Handles e.g. an "x if y" condition where the "if y" part is missing.
1381 res = self._eval_expr_rec(expr)
1383 # Promote "m" to "y" if we're running without modules.
1385 # Internally, "m" is often rewritten to "m" && MODULES by both the
1386 # C implementation and Kconfiglib, which takes care of cases where
1387 # "m" should be demoted to "n" instead.
1388 modules_sym = self.syms.get("MODULES")
1389 if modules_sym is None or modules_sym.get_value() != "y":
1393 def _eval_expr_rec(self, expr):
1394 if isinstance(expr, Symbol):
1395 # Non-bool/tristate symbols are always "n" in a tristate sense,
1396 # regardless of their value
1397 if expr.type != BOOL and expr.type != TRISTATE:
1399 return expr.get_value()
1401 if isinstance(expr, str):
1402 return expr if (expr == "y" or expr == "m") else "n"
1404 # Ordered by frequency
1408 for subexpr in expr[1]:
1409 ev = self._eval_expr_rec(subexpr)
1410 # Return immediately upon discovering an "n" term
1415 # 'res' is either "m" or "y" here; we already handled the
1416 # short-circuiting "n" case in the loop.
1420 ev = self._eval_expr_rec(expr[1])
1423 return "y" if (ev == "n") else "m"
1427 for subexpr in expr[1]:
1428 ev = self._eval_expr_rec(subexpr)
1429 # Return immediately upon discovering a "y" term
1434 # 'res' is either "n" or "m" here; we already handled the
1435 # short-circuiting "y" case in the loop.
1438 if expr[0] == EQUAL:
1439 return "y" if (_str_val(expr[1]) == _str_val(expr[2])) else "n"
1441 if expr[0] == UNEQUAL:
1442 return "y" if (_str_val(expr[1]) != _str_val(expr[2])) else "n"
1444 _internal_error("Internal error while evaluating expression: "
1445 "unknown operation {0}.".format(expr[0]))
1447 def _eval_min(self, e1, e2):
1448 """Returns the minimum value of the two expressions. Equates None with
1450 e1_eval = self._eval_expr(e1)
1451 e2_eval = self._eval_expr(e2)
1452 return e1_eval if tri_less(e1_eval, e2_eval) else e2_eval
1454 def _eval_max(self, e1, e2):
1455 """Returns the maximum value of the two expressions. Equates None with
1457 e1_eval = self._eval_expr(e1)
1458 e2_eval = self._eval_expr(e2)
1459 return e1_eval if tri_greater(e1_eval, e2_eval) else e2_eval
1462 # Dependency tracking (for caching and invalidation)
1465 def _build_dep(self):
1466 """Populates the Symbol.dep sets, linking the symbol to the symbols
1467 that immediately depend on it in the sense that changing the value of
1468 the symbol might affect the values of those other symbols. This is used
1469 for caching/invalidation purposes. The calculated sets might be larger
1470 than necessary as we don't do any complicated analysis of the
1473 # Adds 'sym' as a directly dependent symbol to all symbols that appear
1474 # in the expression 'e'
1475 def add_expr_deps(e, sym):
1476 for s in _get_expr_syms(e):
1479 # The directly dependent symbols of a symbol are:
1480 # - Any symbols whose prompts, default values, rev_dep (select
1481 # condition), or ranges depend on the symbol
1482 # - Any symbols that belong to the same choice statement as the symbol
1483 # (these won't be included in 'dep' as that makes the dependency
1484 # graph unwieldy, but Symbol._get_dependent() will include them)
1485 # - Any symbols in a choice statement that depends on the symbol
1486 for sym in self.syms_iter():
1487 for _, e in sym.prompts:
1488 add_expr_deps(e, sym)
1490 for v, e in sym.def_exprs:
1491 add_expr_deps(v, sym)
1492 add_expr_deps(e, sym)
1494 add_expr_deps(sym.rev_dep, sym)
1496 for l, u, e in sym.ranges:
1497 add_expr_deps(l, sym)
1498 add_expr_deps(u, sym)
1499 add_expr_deps(e, sym)
1501 if sym.is_choice_sym:
1503 for _, e in choice.prompts:
1504 add_expr_deps(e, sym)
1505 for _, e in choice.def_exprs:
1506 add_expr_deps(e, sym)
1508 def _eq_to_sym(self, eq):
1509 """_expr_depends_on() helper. For (in)equalities of the form sym = y/m
1510 or sym != n, returns sym. For other (in)equalities, returns None."""
1511 relation, left, right = eq
1513 def transform_y_m_n(item):
1514 if item is self.y: return "y"
1515 if item is self.m: return "m"
1516 if item is self.n: return "n"
1519 left = transform_y_m_n(left)
1520 right = transform_y_m_n(right)
1522 # Make sure the symbol (if any) appears to the left
1523 if not isinstance(left, Symbol):
1524 left, right = right, left
1525 if not isinstance(left, Symbol):
1527 if (relation == EQUAL and (right == "y" or right == "m")) or \
1528 (relation == UNEQUAL and right == "n"):
1532 def _expr_depends_on(self, expr, sym):
1533 """Reimplementation of expr_depends_symbol() from mconf.c. Used to
1534 determine if a submenu should be implicitly created, which influences
1535 what items inside choice statements are considered choice items."""
1540 if isinstance(expr, str):
1542 if isinstance(expr, Symbol):
1545 if expr[0] in (EQUAL, UNEQUAL):
1546 return self._eq_to_sym(expr) is sym
1548 for and_expr in expr[1]:
1555 def _invalidate_all(self):
1556 for sym in self.syms_iter():
1560 # Printing and misc.
1563 def _expand_sym_refs(self, s):
1564 """Expands $-references to symbols in 's' to symbol values, or to the
1565 empty string for undefined symbols."""
1568 sym_ref_match = _sym_ref_re_search(s)
1569 if sym_ref_match is None:
1572 sym_name = sym_ref_match.group(0)[1:]
1573 sym = self.syms.get(sym_name)
1574 expansion = "" if sym is None else sym.get_value()
1576 s = s[:sym_ref_match.start()] + \
1578 s[sym_ref_match.end():]
1580 def _expr_val_str(self, expr, no_value_str="(none)",
1581 get_val_instead_of_eval=False):
1582 """Printing helper. Returns a string with 'expr' and its value.
1584 no_value_str: String to return when 'expr' is missing (None).
1586 get_val_instead_of_eval: Assume 'expr' is a symbol or string (constant
1587 symbol) and get its value directly instead of evaluating it to a
1593 if get_val_instead_of_eval:
1594 if isinstance(expr, str):
1595 return _expr_to_str(expr)
1596 val = expr.get_value()
1598 val = self._eval_expr(expr)
1600 return "{0} (value: {1})".format(_expr_to_str(expr), _expr_to_str(val))
1602 def _get_sym_or_choice_str(self, sc):
1603 """Symbols and choices have many properties in common, so we factor out
1604 common __str__() stuff here. "sc" is short for "symbol or choice"."""
1606 # As we deal a lot with string representations here, use some
1607 # convenient shorthand:
1611 # Common symbol/choice properties
1614 user_val_str = "(no user value)" if sc.user_val is None else \
1617 # Build prompts string
1619 prompts_str = " (no prompts)"
1621 prompts_str_rows = []
1622 for prompt, cond_expr in sc.orig_prompts:
1623 if cond_expr is None:
1624 prompts_str_rows.append(' "{0}"'.format(prompt))
1626 prompts_str_rows.append(
1627 ' "{0}" if {1}'.format(prompt,
1628 self._expr_val_str(cond_expr)))
1629 prompts_str = "\n".join(prompts_str_rows)
1631 # Build locations string
1632 if not sc.def_locations:
1633 locations_str = "(no locations)"
1635 locations_str = " ".join(["{0}:{1}".format(filename, linenr) for
1636 (filename, linenr) in sc.def_locations])
1638 # Build additional-dependencies-from-menus-and-ifs string
1639 additional_deps_str = " " + \
1640 self._expr_val_str(sc.deps_from_containing,
1641 "(no additional dependencies)")
1644 # Symbol-specific stuff
1647 if isinstance(sc, Symbol):
1648 # Build ranges string
1649 if isinstance(sc, Symbol):
1651 ranges_str = " (no ranges)"
1653 ranges_str_rows = []
1654 for l, u, cond_expr in sc.ranges:
1655 if cond_expr is None:
1656 ranges_str_rows.append(" [{0}, {1}]".format(s(l),
1659 ranges_str_rows.append(" [{0}, {1}] if {2}"
1661 self._expr_val_str(cond_expr)))
1662 ranges_str = "\n".join(ranges_str_rows)
1664 # Build default values string
1665 if not sc.def_exprs:
1666 defaults_str = " (no default values)"
1668 defaults_str_rows = []
1669 for val_expr, cond_expr in sc.orig_def_exprs:
1670 row_str = " " + self._expr_val_str(val_expr, "(none)",
1672 defaults_str_rows.append(row_str)
1673 defaults_str_rows.append(" Condition: " +
1674 self._expr_val_str(cond_expr))
1675 defaults_str = "\n".join(defaults_str_rows)
1677 # Build selects string
1678 if not sc.orig_selects:
1679 selects_str = " (no selects)"
1681 selects_str_rows = []
1682 for target, cond_expr in sc.orig_selects:
1683 if cond_expr is None:
1684 selects_str_rows.append(" {0}".format(target.name))
1686 selects_str_rows.append(
1687 " {0} if {1}".format(target.name,
1688 self._expr_val_str(cond_expr)))
1689 selects_str = "\n".join(selects_str_rows)
1691 res = _lines("Symbol " +
1692 ("(no name)" if sc.name is None else sc.name),
1693 "Type : " + TYPENAME[sc.type],
1694 "Value : " + s(sc.get_value()),
1695 "User value : " + user_val_str,
1696 "Visibility : " + s(_get_visibility(sc)),
1697 "Is choice item : " + BOOL_STR[sc.is_choice_sym],
1698 "Is defined : " + BOOL_STR[sc.is_defined_],
1699 "Is from env. : " + BOOL_STR[sc.is_from_env],
1700 "Is special : " + BOOL_STR[sc.is_special_] + "\n")
1702 res += _lines("Ranges:", ranges_str + "\n")
1703 res += _lines("Prompts:",
1709 "Reverse (select-related) dependencies:",
1710 " (no reverse dependencies)" if sc.rev_dep == "n"
1711 else " " + self._expr_val_str(sc.rev_dep),
1712 "Additional dependencies from enclosing menus "
1714 additional_deps_str,
1715 "Locations: " + locations_str)
1720 # Choice-specific stuff
1723 # Build selected symbol string
1724 sel = sc.get_selection()
1725 sel_str = "(no selection)" if sel is None else sel.name
1727 # Build default values string
1728 if not sc.def_exprs:
1729 defaults_str = " (no default values)"
1731 defaults_str_rows = []
1732 for sym, cond_expr in sc.orig_def_exprs:
1733 if cond_expr is None:
1734 defaults_str_rows.append(" {0}".format(sym.name))
1736 defaults_str_rows.append(" {0} if {1}".format(sym.name,
1737 self._expr_val_str(cond_expr)))
1738 defaults_str = "\n".join(defaults_str_rows)
1740 # Build contained symbols string
1741 names = [sym.name for sym in sc.actual_symbols]
1742 syms_string = " ".join(names) if names else "(empty)"
1744 return _lines("Choice",
1745 "Name (for named choices): " +
1746 ("(no name)" if sc.name is None else sc.name),
1747 "Type : " + TYPENAME[sc.type],
1748 "Selected symbol : " + sel_str,
1749 "User value : " + user_val_str,
1750 "Mode : " + s(sc.get_mode()),
1751 "Visibility : " + s(_get_visibility(sc)),
1752 "Optional : " + BOOL_STR[sc.optional],
1759 "Additional dependencies from enclosing menus and "
1761 additional_deps_str,
1762 "Locations: " + locations_str)
1764 def _warn(self, msg, filename=None, linenr=None):
1765 """For printing warnings to stderr."""
1766 if self.print_warnings:
1767 _stderr_msg("warning: " + msg, filename, linenr)
1771 """Base class for symbols and other Kconfig constructs. Subclasses are
1772 Symbol, Choice, Menu, and Comment."""
1774 def is_symbol(self):
1775 """Returns True if the item is a symbol. Short for
1776 isinstance(item, kconfiglib.Symbol)."""
1777 return isinstance(self, Symbol)
1779 def is_choice(self):
1780 """Returns True if the item is a choice. Short for
1781 isinstance(item, kconfiglib.Choice)."""
1782 return isinstance(self, Choice)
1785 """Returns True if the item is a menu. Short for
1786 isinstance(item, kconfiglib.Menu)."""
1787 return isinstance(self, Menu)
1789 def is_comment(self):
1790 """Returns True if the item is a comment. Short for
1791 isinstance(item, kconfiglib.Comment)."""
1792 return isinstance(self, Comment)
1796 """Represents a configuration symbol - e.g. FOO for
1805 def get_config(self):
1806 """Returns the Config instance this symbol is from."""
1810 """Returns the name of the symbol."""
1814 """Returns the type of the symbol: one of UNKNOWN, BOOL, TRISTATE,
1815 STRING, HEX, or INT. These are defined at the top level of the module,
1816 so you'd do something like
1818 if sym.get_type() == kconfiglib.STRING:
1822 def get_prompts(self):
1823 """Returns a list of prompts defined for the symbol, in the order they
1824 appear in the configuration files. Returns the empty list for symbols
1827 This list will have a single entry for the vast majority of symbols
1828 having prompts, but having multiple prompts for a single symbol is
1829 possible through having multiple 'config' entries for it."""
1830 return [prompt for prompt, _ in self.orig_prompts]
1833 """Returns the help text of the symbol, or None if the symbol has no
1837 def get_parent(self):
1838 """Returns the menu or choice statement that contains the symbol, or
1839 None if the symbol is at the top level. Note that if statements are
1840 treated as syntactic and do not have an explicit class
1844 def get_def_locations(self):
1845 """Returns a list of (filename, linenr) tuples, where filename (string)
1846 and linenr (int) represent a location where the symbol is defined. For
1847 the vast majority of symbols this list will only contain one element.
1848 For the following Kconfig, FOO would get two entries: the lines marked
1857 return self.def_locations
1859 def get_ref_locations(self):
1860 """Returns a list of (filename, linenr) tuples, where filename (string)
1861 and linenr (int) represent a location where the symbol is referenced in
1862 the configuration. For example, the lines marked by * would be included
1867 default BAR || FOO *
1879 config FOO (definition not included)
1882 return self.ref_locations
1884 def get_value(self):
1885 """Calculate and return the value of the symbol. See also
1886 Symbol.set_user_value()."""
1888 if self.cached_val is not None:
1889 return self.cached_val
1891 # As a quirk of Kconfig, undefined symbols get their name as their
1892 # value. This is why things like "FOO = bar" work for seeing if FOO has
1894 if self.type == UNKNOWN:
1895 self.cached_val = self.name
1898 new_val = DEFAULT_VALUE[self.type]
1899 vis = _get_visibility(self)
1901 # This is easiest to calculate together with the value
1902 self.write_to_conf = False
1904 if self.type == BOOL or self.type == TRISTATE:
1905 # The visibility and mode (modules-only or single-selection) of
1906 # choice items will be taken into account in _get_visibility()
1907 if self.is_choice_sym:
1909 choice = self.parent
1910 mode = choice.get_mode()
1912 self.write_to_conf = (mode != "n")
1915 if choice.get_selection() is self:
1920 if self.user_val == "m" or self.user_val == "y":
1924 # If the symbol is visible and has a user value, use that.
1925 # Otherwise, look at defaults.
1929 self.write_to_conf = True
1930 if self.user_val is not None:
1931 new_val = self.config._eval_min(self.user_val, vis)
1932 use_defaults = False
1935 for val_expr, cond_expr in self.def_exprs:
1936 cond_eval = self.config._eval_expr(cond_expr)
1937 if cond_eval != "n":
1938 self.write_to_conf = True
1939 new_val = self.config._eval_min(val_expr,
1943 # Reverse (select-related) dependencies take precedence
1944 rev_dep_val = self.config._eval_expr(self.rev_dep)
1945 if rev_dep_val != "n":
1946 self.write_to_conf = True
1947 new_val = self.config._eval_max(new_val, rev_dep_val)
1949 # Promote "m" to "y" for booleans
1950 if new_val == "m" and self.type == BOOL:
1953 elif self.type == INT or self.type == HEX:
1954 has_active_range = False
1959 base = 16 if self.type == HEX else 10
1961 for l, h, cond_expr in self.ranges:
1962 if self.config._eval_expr(cond_expr) != "n":
1963 has_active_range = True
1965 low_str = _str_val(l)
1966 high_str = _str_val(h)
1967 low = int(low_str, base) if \
1968 _is_base_n(low_str, base) else 0
1969 high = int(high_str, base) if \
1970 _is_base_n(high_str, base) else 0
1975 self.write_to_conf = True
1977 if self.user_val is not None and \
1978 _is_base_n(self.user_val, base) and \
1979 (not has_active_range or
1980 low <= int(self.user_val, base) <= high):
1982 # If the user value is OK, it is stored in exactly the same
1983 # form as specified in the assignment (with or without
1986 use_defaults = False
1987 new_val = self.user_val
1990 for val_expr, cond_expr in self.def_exprs:
1991 if self.config._eval_expr(cond_expr) != "n":
1992 self.write_to_conf = True
1994 # If the default value is OK, it is stored in exactly
1995 # the same form as specified. Otherwise, it is clamped
1996 # to the range, and the output has "0x" as appropriate
1999 new_val = _str_val(val_expr)
2001 if _is_base_n(new_val, base):
2002 new_val_num = int(new_val, base)
2003 if has_active_range:
2006 if new_val_num < low:
2008 elif new_val_num > high:
2011 if clamped_val is not None:
2012 new_val = (hex(clamped_val) if \
2013 self.type == HEX else str(clamped_val))
2016 else: # For the for loop
2017 # If no user value or default kicks in but the hex/int has
2018 # an active range, then the low end of the range is used,
2019 # provided it's > 0, with "0x" prepended as appropriate.
2020 if has_active_range and low > 0:
2021 new_val = (hex(low) if self.type == HEX else str(low))
2023 elif self.type == STRING:
2027 self.write_to_conf = True
2028 if self.user_val is not None:
2029 new_val = self.user_val
2030 use_defaults = False
2033 for val_expr, cond_expr in self.def_exprs:
2034 if self.config._eval_expr(cond_expr) != "n":
2035 self.write_to_conf = True
2036 new_val = _str_val(val_expr)
2039 self.cached_val = new_val
2042 def get_user_value(self):
2043 """Returns the value assigned to the symbol in a .config or via
2044 Symbol.set_user_value() (provided the value was valid for the type of
2045 the symbol). Returns None in case of no user value."""
2046 return self.user_val
2048 def get_upper_bound(self):
2049 """For string/hex/int symbols and for bool and tristate symbols that
2050 cannot be modified (see is_modifiable()), returns None.
2052 Otherwise, returns the highest value the symbol can be set to with
2053 Symbol.set_user_value() (that will not be truncated): one of "m" or
2054 "y", arranged from lowest to highest. This corresponds to the highest
2055 value the symbol could be given in e.g. the 'make menuconfig'
2058 See also the tri_less*() and tri_greater*() functions, which could come
2060 if self.type != BOOL and self.type != TRISTATE:
2062 rev_dep = self.config._eval_expr(self.rev_dep)
2063 # A bool selected to "m" gets promoted to "y", pinning it
2064 if rev_dep == "m" and self.type == BOOL:
2066 vis = _get_visibility(self)
2067 if TRI_TO_INT[vis] > TRI_TO_INT[rev_dep]:
2071 def get_lower_bound(self):
2072 """For string/hex/int symbols and for bool and tristate symbols that
2073 cannot be modified (see is_modifiable()), returns None.
2075 Otherwise, returns the lowest value the symbol can be set to with
2076 Symbol.set_user_value() (that will not be truncated): one of "n" or
2077 "m", arranged from lowest to highest. This corresponds to the lowest
2078 value the symbol could be given in e.g. the 'make menuconfig'
2081 See also the tri_less*() and tri_greater*() functions, which could come
2083 if self.type != BOOL and self.type != TRISTATE:
2085 rev_dep = self.config._eval_expr(self.rev_dep)
2086 # A bool selected to "m" gets promoted to "y", pinning it
2087 if rev_dep == "m" and self.type == BOOL:
2089 if TRI_TO_INT[_get_visibility(self)] > TRI_TO_INT[rev_dep]:
2093 def get_assignable_values(self):
2094 """For string/hex/int symbols and for bool and tristate symbols that
2095 cannot be modified (see is_modifiable()), returns the empty list.
2097 Otherwise, returns a list containing the user values that can be
2098 assigned to the symbol (that won't be truncated). Usage example:
2100 if "m" in sym.get_assignable_values():
2101 sym.set_user_value("m")
2103 This is basically a more convenient interface to
2104 get_lower/upper_bound() when wanting to test if a particular tristate
2105 value can be assigned."""
2106 if self.type != BOOL and self.type != TRISTATE:
2108 rev_dep = self.config._eval_expr(self.rev_dep)
2109 # A bool selected to "m" gets promoted to "y", pinning it
2110 if rev_dep == "m" and self.type == BOOL:
2112 res = ["n", "m", "y"][TRI_TO_INT[rev_dep] :
2113 TRI_TO_INT[_get_visibility(self)] + 1]
2114 return res if len(res) > 1 else []
2116 def get_visibility(self):
2117 """Returns the visibility of the symbol: one of "n", "m" or "y". For
2118 bool and tristate symbols, this is an upper bound on the value users
2119 can set for the symbol. For other types of symbols, a visibility of "n"
2120 means the user value will be ignored. A visibility of "n" corresponds
2121 to not being visible in the 'make *config' interfaces.
2123 Example (assuming we're running with modules enabled -- i.e., MODULES
2126 # Assume this has been assigned 'n'
2130 # Assume this has been assigned 'm'
2134 # Has visibility 'n'
2139 # Has visibility 'm'
2144 # Has visibility 'y'
2148 # Has no prompt, and hence visibility 'n'
2152 Having visibility be tri-valued ensures that e.g. a symbol cannot be
2153 set to "y" by the user if it depends on a symbol with value "m", which
2156 You should probably look at get_lower/upper_bound(),
2157 get_assignable_values() and is_modifiable() before using this."""
2158 return _get_visibility(self)
2160 def get_referenced_symbols(self, refs_from_enclosing=False):
2161 """Returns the set() of all symbols referenced by this symbol. For
2162 example, the symbol defined by
2166 prompt "foo" if A && B
2171 references the symbols A through G.
2173 refs_from_enclosing (default: False): If True, the symbols referenced
2174 by enclosing menus and ifs will be included in the result."""
2175 return self.all_referenced_syms if refs_from_enclosing else \
2176 self.referenced_syms
2178 def get_selected_symbols(self):
2179 """Returns the set() of all symbols X for which this symbol has a
2180 'select X' or 'select X if Y' (regardless of whether Y is satisfied or
2181 not). This is a subset of the symbols returned by
2182 get_referenced_symbols()."""
2183 return self.selected_syms
2185 def set_user_value(self, v):
2186 """Sets the user value of the symbol.
2188 Equal in effect to assigning the value to the symbol within a .config
2189 file. Use get_lower/upper_bound() or get_assignable_values() to find
2190 the range of currently assignable values for bool and tristate symbols;
2191 setting values outside this range will cause the user value to differ
2192 from the result of Symbol.get_value() (be truncated). Values that are
2193 invalid for the type (such as a_bool.set_user_value("foo")) are
2194 ignored, and a warning is emitted if an attempt is made to assign such
2197 For any type of symbol, is_modifiable() can be used to check if a user
2198 value will currently have any effect on the symbol, as determined by
2199 its visibility and range of assignable values. Any value that is valid
2200 for the type (bool, tristate, etc.) will end up being reflected in
2201 get_user_value() though, and might have an effect later if conditions
2202 change. To get rid of the user value, use unset_user_value().
2204 Any symbols dependent on the symbol are (recursively) invalidated, so
2205 things will just work with regards to dependencies.
2207 v: The user value to give to the symbol."""
2208 self._set_user_value_no_invalidate(v, False)
2210 # There might be something more efficient you could do here, but play
2212 if self.name == "MODULES":
2213 self.config._invalidate_all()
2217 self._invalidate_dependent()
2219 def unset_user_value(self):
2220 """Resets the user value of the symbol, as if the symbol had never
2221 gotten a user value via Config.load_config() or
2222 Symbol.set_user_value()."""
2223 self._unset_user_value_no_recursive_invalidate()
2224 self._invalidate_dependent()
2226 def is_modifiable(self):
2227 """Returns True if the value of the symbol could be modified by calling
2228 Symbol.set_user_value().
2230 For bools and tristates, this corresponds to the symbol being visible
2231 in the 'make menuconfig' interface and not already being pinned to a
2232 specific value (e.g. because it is selected by another symbol).
2234 For strings and numbers, this corresponds to just being visible. (See
2235 Symbol.get_visibility().)"""
2236 if self.is_special_:
2238 if self.type == BOOL or self.type == TRISTATE:
2239 rev_dep = self.config._eval_expr(self.rev_dep)
2240 # A bool selected to "m" gets promoted to "y", pinning it
2241 if rev_dep == "m" and self.type == BOOL:
2243 return TRI_TO_INT[_get_visibility(self)] > TRI_TO_INT[rev_dep]
2244 return _get_visibility(self) != "n"
2246 def is_defined(self):
2247 """Returns False if the symbol is referred to in the Kconfig but never
2248 actually defined."""
2249 return self.is_defined_
2251 def is_special(self):
2252 """Returns True if the symbol is one of the special symbols n, m, y, or
2253 UNAME_RELEASE, or gets its value from the environment."""
2254 return self.is_special_
2256 def is_from_environment(self):
2257 """Returns True if the symbol gets its value from the environment."""
2258 return self.is_from_env
2260 def has_ranges(self):
2261 """Returns True if the symbol is of type INT or HEX and has ranges that
2262 limit what values it can take on."""
2263 return bool(self.ranges)
2265 def is_choice_symbol(self):
2266 """Returns True if the symbol is in a choice statement and is an actual
2267 choice symbol (see Choice.get_symbols())."""
2268 return self.is_choice_sym
2270 def is_choice_selection(self):
2271 """Returns True if the symbol is contained in a choice statement and is
2272 the selected item. Equivalent to
2274 sym.is_choice_symbol() and sym.get_parent().get_selection() is sym"""
2275 return self.is_choice_sym and self.parent.get_selection() is self
2277 def is_allnoconfig_y(self):
2278 """Returns True if the symbol has the 'allnoconfig_y' option set."""
2279 return self.allnoconfig_y
2282 """Returns a string containing various information about the symbol."""
2283 return self.config._get_sym_or_choice_str(self)
2290 """Symbol constructor -- not intended to be called directly by
2291 Kconfiglib clients."""
2296 self.def_exprs = [] # 'default' properties
2297 self.ranges = [] # 'range' properties (for int and hex)
2298 self.help = None # Help text
2299 self.rev_dep = "n" # Reverse (select-related) dependencies
2303 self.user_val = None # Value set by user
2305 # The prompt, default value and select conditions without any
2306 # dependencies from menus and ifs propagated to them
2307 self.orig_prompts = []
2308 self.orig_def_exprs = []
2309 self.orig_selects = []
2311 # Dependencies inherited from containing menus and ifs
2312 self.deps_from_containing = None
2313 # The set of symbols referenced by this symbol (see
2314 # get_referenced_symbols())
2315 self.referenced_syms = set()
2316 # The set of symbols selected by this symbol (see
2317 # get_selected_symbols())
2318 self.selected_syms = set()
2319 # Like 'referenced_syms', but includes symbols from
2320 # dependencies inherited from enclosing menus and ifs
2321 self.all_referenced_syms = set()
2323 # This records only dependencies specified with 'depends on'. Needed
2324 # when determining actual choice items (hrrrr...). See also
2325 # Choice._determine_actual_symbols().
2326 self.menu_dep = None
2328 # See Symbol.get_ref/def_locations().
2329 self.def_locations = []
2330 self.ref_locations = []
2332 # Populated in Config._build_dep() after parsing. Links the symbol to
2333 # the symbols that immediately depend on it (in a caching/invalidation
2334 # sense). The total set of dependent symbols for the symbol (the
2335 # transitive closure) is calculated on an as-needed basis in
2341 # Caches the calculated value
2342 self.cached_val = None
2343 # Caches the visibility, which acts as an upper bound on the value
2344 self.cached_visibility = None
2345 # Caches the total list of dependent symbols. Calculated in
2347 self.cached_deps = None
2351 # Does the symbol have an entry in the Kconfig file? The trailing
2352 # underscore avoids a collision with is_defined().
2353 self.is_defined_ = False
2354 # Should the symbol get an entry in .config?
2355 self.write_to_conf = False
2356 # Set to true when _make_conf() is called on a symbol, so that symbols
2357 # defined in multiple locations only get one .config entry. We need to
2358 # reset it prior to writing out a new .config.
2359 self.already_written = False
2360 # This is set to True for "actual" choice symbols; see
2361 # Choice._determine_actual_symbols().
2362 self.is_choice_sym = False
2363 # Does the symbol get its value in some special way, e.g. from the
2364 # environment or by being one of the special symbols n, m, and y? If
2365 # so, the value is stored in self.cached_val, which is never
2366 # invalidated. The trailing underscore avoids a collision with
2368 self.is_special_ = False
2369 # Does the symbol get its value from the environment?
2370 self.is_from_env = False
2371 # Does the symbol have the 'allnoconfig_y' option set?
2372 self.allnoconfig_y = False
2374 def _invalidate(self):
2375 if self.is_special_:
2378 if self.is_choice_sym:
2379 self.parent._invalidate()
2381 self.cached_val = None
2382 self.cached_visibility = None
2384 def _invalidate_dependent(self):
2385 for sym in self._get_dependent():
2388 def _set_user_value_no_invalidate(self, v, suppress_load_warnings):
2389 """Like set_user_value(), but does not invalidate any symbols.
2391 suppress_load_warnings: some warnings are annoying when loading a
2392 .config that can be helpful when manually invoking set_user_value().
2393 This flag is set to True to suppress such warnings.
2395 Perhaps this could be made optional for load_config() instead."""
2397 if self.is_special_:
2398 if self.is_from_env:
2399 self.config._warn('attempt to assign the value "{0}" to the '
2400 'symbol {1}, which gets its value from the '
2401 'environment. Assignment ignored.'
2402 .format(v, self.name))
2404 self.config._warn('attempt to assign the value "{0}" to the '
2405 'special symbol {1}. Assignment ignored.'
2406 .format(v, self.name))
2409 if not self.is_defined_:
2410 filename, linenr = self.ref_locations[0]
2411 if self.config.print_undef_assign:
2412 _stderr_msg('note: attempt to assign the value "{0}" to {1}, '
2413 "which is referenced at {2}:{3} but never "
2414 "defined. Assignment ignored."
2415 .format(v, self.name, filename, linenr))
2418 # Check if the value is valid for our type
2419 if not ((self.type == BOOL and (v == "y" or v == "n") ) or
2420 (self.type == TRISTATE and (v == "y" or v == "m" or
2422 (self.type == STRING ) or
2423 (self.type == INT and _is_base_n(v, 10) ) or
2424 (self.type == HEX and _is_base_n(v, 16) )):
2425 self.config._warn('the value "{0}" is invalid for {1}, which has '
2426 "type {2}. Assignment ignored."
2427 .format(v, self.name, TYPENAME[self.type]))
2430 if not self.prompts and not suppress_load_warnings:
2431 self.config._warn('assigning "{0}" to the symbol {1} which '
2432 'lacks prompts and thus has visibility "n". '
2433 'The assignment will have no effect.'
2434 .format(v, self.name))
2438 if self.is_choice_sym and (self.type == BOOL or self.type == TRISTATE):
2439 choice = self.parent
2441 choice.user_val = self
2442 choice.user_mode = "y"
2444 choice.user_val = None
2445 choice.user_mode = "m"
2447 def _unset_user_value_no_recursive_invalidate(self):
2449 self.user_val = None
2451 if self.is_choice_sym:
2452 self.parent._unset_user_value()
2454 def _make_conf(self, append_fn):
2455 if self.already_written:
2458 self.already_written = True
2460 # Note: write_to_conf is determined in get_value()
2461 val = self.get_value()
2462 if not self.write_to_conf:
2465 if self.type == BOOL or self.type == TRISTATE:
2466 if val == "y" or val == "m":
2467 append_fn("CONFIG_{0}={1}".format(self.name, val))
2469 append_fn("# CONFIG_{0} is not set".format(self.name))
2471 elif self.type == INT or self.type == HEX:
2472 append_fn("CONFIG_{0}={1}".format(self.name, val))
2474 elif self.type == STRING:
2476 append_fn('CONFIG_{0}="{1}"'
2478 val.replace("\\", "\\\\").replace('"', '\\"')))
2481 _internal_error("Internal error while creating .config: unknown "
2482 'type "{0}".'.format(self.type))
2484 def _get_dependent(self):
2485 """Returns the set of symbols that should be invalidated if the value
2486 of the symbol changes, because they might be affected by the change.
2487 Note that this is an internal API -- it's probably of limited
2488 usefulness to clients."""
2489 if self.cached_deps is not None:
2490 return self.cached_deps
2494 res |= s._get_dependent()
2496 if self.is_choice_sym:
2497 # Choice symbols also depend (recursively) on their siblings. The
2498 # siblings are not included in 'dep' to avoid dependency loops.
2499 for sibling in self.parent.actual_symbols:
2500 if sibling is not self:
2503 for s in sibling.dep:
2504 res |= s._get_dependent()
2506 self.cached_deps = res
2509 def _has_auto_menu_dep_on(self, on):
2510 """See Choice._determine_actual_symbols()."""
2511 if not isinstance(self.parent, Choice):
2512 _internal_error("Attempt to determine auto menu dependency for "
2513 "symbol ouside of choice.")
2515 if not self.prompts:
2516 # If we have no prompt, use the menu dependencies instead (what was
2517 # specified with 'depends on')
2518 return self.menu_dep is not None and \
2519 self.config._expr_depends_on(self.menu_dep, on)
2521 for _, cond_expr in self.prompts:
2522 if self.config._expr_depends_on(cond_expr, on):
2529 """Represents a menu statement."""
2535 def get_config(self):
2536 """Return the Config instance this menu is from."""
2539 def get_title(self):
2540 """Returns the title text of the menu."""
2543 def get_parent(self):
2544 """Returns the menu or choice statement that contains the menu, or
2545 None if the menu is at the top level. Note that if statements are
2546 treated as syntactic sugar and do not have an explicit class
2550 def get_location(self):
2551 """Returns the location of the menu as a (filename, linenr) tuple,
2552 where filename is a string and linenr an int."""
2553 return (self.filename, self.linenr)
2555 def get_items(self, recursive=False):
2556 """Returns a list containing the items (symbols, menus, choice
2557 statements and comments) in in the menu, in the same order that the
2558 items appear within the menu.
2560 recursive (default: False): True if items contained in items within the
2561 menu should be included recursively (preorder)."""
2567 for item in self.block:
2569 if isinstance(item, Menu):
2570 res.extend(item.get_items(True))
2571 elif isinstance(item, Choice):
2572 res.extend(item.get_items())
2575 def get_symbols(self, recursive=False):
2576 """Returns a list containing the symbols in the menu, in the same order
2577 that they appear within the menu.
2579 recursive (default: False): True if symbols contained in items within
2580 the menu should be included recursively."""
2582 return [item for item in self.get_items(recursive) if
2583 isinstance(item, Symbol)]
2585 def get_visibility(self):
2586 """Returns the visibility of the menu. This also affects the visibility
2587 of subitems. See also Symbol.get_visibility()."""
2588 return self.config._eval_expr(self.dep_expr)
2590 def get_visible_if_visibility(self):
2591 """Returns the visibility the menu gets from its 'visible if'
2592 condition. "y" if the menu has no 'visible if' condition."""
2593 return self.config._eval_expr(self.visible_if_expr)
2595 def get_referenced_symbols(self, refs_from_enclosing=False):
2596 """See Symbol.get_referenced_symbols()."""
2597 return self.all_referenced_syms if refs_from_enclosing else \
2598 self.referenced_syms
2601 """Returns a string containing various information about the menu."""
2602 depends_on_str = self.config._expr_val_str(self.orig_deps,
2603 "(no dependencies)")
2604 visible_if_str = self.config._expr_val_str(self.visible_if_expr,
2605 "(no dependencies)")
2607 additional_deps_str = " " + \
2608 self.config._expr_val_str(self.deps_from_containing,
2609 "(no additional dependencies)")
2611 return _lines("Menu",
2612 "Title : " + self.title,
2613 "'depends on' dependencies : " + depends_on_str,
2614 "'visible if' dependencies : " + visible_if_str,
2615 "Additional dependencies from enclosing menus and "
2617 additional_deps_str,
2618 "Location: {0}:{1}".format(self.filename, self.linenr))
2625 """Menu constructor -- not intended to be called directly by
2626 Kconfiglib clients."""
2629 self.dep_expr = None
2630 self.visible_if_expr = None
2635 # Dependency expression without dependencies from enclosing menus and
2637 self.orig_deps = None
2639 # Dependencies inherited from containing menus and ifs
2640 self.deps_from_containing = None
2641 # The set of symbols referenced by this menu (see
2642 # get_referenced_symbols())
2643 self.referenced_syms = set()
2644 # Like 'referenced_syms', but includes symbols from
2645 # dependencies inherited from enclosing menus and ifs
2646 self.all_referenced_syms = None
2648 self.filename = None
2651 def _make_conf(self, append_fn):
2652 if self.config._eval_expr(self.dep_expr) != "n" and \
2653 self.config._eval_expr(self.visible_if_expr) != "n":
2654 append_fn("\n#\n# {0}\n#".format(self.title))
2655 _make_block_conf(self.block, append_fn)
2659 """Represents a choice statement. A choice can be in one of three modes:
2661 "n" - The choice is not visible and no symbols can be selected.
2663 "m" - Any number of symbols can be set to "m". The rest will be "n". This
2664 is safe since potentially conflicting options don't actually get
2665 compiled into the kernel simultaneously with "m".
2667 "y" - One symbol will be "y" while the rest are "n".
2669 Only tristate choices can be in "m" mode, and the visibility of the choice
2670 is an upper bound on the mode, so that e.g. a choice that depends on a
2671 symbol with value "m" will be in "m" mode.
2673 The mode changes automatically when a value is assigned to a symbol within
2676 See Symbol.get_visibility() too."""
2682 def get_config(self):
2683 """Returns the Config instance this choice is from."""
2687 """For named choices, returns the name. Returns None for unnamed
2688 choices. No named choices appear anywhere in the kernel Kconfig files
2689 as of Linux 3.7.0-rc8."""
2693 """Returns the type of the choice. See Symbol.get_type()."""
2696 def get_prompts(self):
2697 """Returns a list of prompts defined for the choice, in the order they
2698 appear in the configuration files. Returns the empty list for choices
2701 This list will have a single entry for the vast majority of choices
2702 having prompts, but having multiple prompts for a single choice is
2703 possible through having multiple 'choice' entries for it (though I'm
2704 not sure if that ever happens in practice)."""
2705 return [prompt for prompt, _ in self.orig_prompts]
2708 """Returns the help text of the choice, or None if the choice has no
2712 def get_parent(self):
2713 """Returns the menu or choice statement that contains the choice, or
2714 None if the choice is at the top level. Note that if statements are
2715 treated as syntactic sugar and do not have an explicit class
2719 def get_def_locations(self):
2720 """Returns a list of (filename, linenr) tuples, where filename (string)
2721 and linenr (int) represent a location where the choice is defined. For
2722 the vast majority of choices (all of them as of Linux 3.7.0-rc8) this
2723 list will only contain one element, but its possible for named choices
2724 to be defined in multiple locations."""
2725 return self.def_locations
2727 def get_selection(self):
2728 """Returns the symbol selected (either by the user or through
2729 defaults), or None if either no symbol is selected or the mode is not
2731 if self.cached_selection is not None:
2732 if self.cached_selection == NO_SELECTION:
2734 return self.cached_selection
2736 if self.get_mode() != "y":
2737 return self._cache_ret(None)
2739 # User choice available?
2740 if self.user_val is not None and _get_visibility(self.user_val) == "y":
2741 return self._cache_ret(self.user_val)
2744 return self._cache_ret(None)
2746 return self._cache_ret(self.get_selection_from_defaults())
2748 def get_selection_from_defaults(self):
2749 """Like Choice.get_selection(), but acts as if no symbol has been
2750 selected by the user and no 'optional' flag is in effect."""
2752 if not self.actual_symbols:
2755 for symbol, cond_expr in self.def_exprs:
2756 if self.config._eval_expr(cond_expr) != "n":
2757 chosen_symbol = symbol
2760 chosen_symbol = self.actual_symbols[0]
2762 # Is the chosen symbol visible?
2763 if _get_visibility(chosen_symbol) != "n":
2764 return chosen_symbol
2765 # Otherwise, pick the first visible symbol
2766 for sym in self.actual_symbols:
2767 if _get_visibility(sym) != "n":
2771 def get_user_selection(self):
2772 """If the choice is in "y" mode and has a user-selected symbol, returns
2773 that symbol. Otherwise, returns None."""
2774 return self.user_val
2776 def get_items(self):
2777 """Gets all items contained in the choice in the same order as within
2778 the configuration ("items" instead of "symbols" since choices and
2779 comments might appear within choices. This only happens in one place as
2780 of Linux 3.7.0-rc8, in drivers/usb/gadget/Kconfig)."""
2783 def get_symbols(self):
2784 """Returns a list containing the choice's symbols.
2786 A quirk (perhaps a bug) of Kconfig is that you can put items within a
2787 choice that will not be considered members of the choice insofar as
2788 selection is concerned. This happens for example if one symbol within a
2789 choice 'depends on' the symbol preceding it, or if you put non-symbol
2790 items within choices.
2792 As of Linux 3.7.0-rc8, this seems to be used intentionally in one
2793 place: drivers/usb/gadget/Kconfig.
2795 This function returns the "proper" symbols of the choice in the order
2796 they appear in the choice, excluding such items. If you want all items
2797 in the choice, use get_items()."""
2798 return self.actual_symbols
2800 def get_referenced_symbols(self, refs_from_enclosing=False):
2801 """See Symbol.get_referenced_symbols()."""
2802 return self.all_referenced_syms if refs_from_enclosing else \
2803 self.referenced_syms
2805 def get_visibility(self):
2806 """Returns the visibility of the choice statement: one of "n", "m" or
2807 "y". This acts as an upper limit on the mode of the choice (though bool
2808 choices can only have the mode "y"). See the class documentation for an
2809 explanation of modes."""
2810 return _get_visibility(self)
2813 """Returns the mode of the choice. See the class documentation for
2814 an explanation of modes."""
2815 minimum_mode = "n" if self.optional else "m"
2816 mode = self.user_mode if self.user_mode is not None else minimum_mode
2817 mode = self.config._eval_min(mode, _get_visibility(self))
2819 # Promote "m" to "y" for boolean choices
2820 if mode == "m" and self.type == BOOL:
2825 def is_optional(self):
2826 """Returns True if the choice has the 'optional' flag set (and so will
2827 default to "n" mode)."""
2828 return self.optional
2831 """Returns a string containing various information about the choice
2833 return self.config._get_sym_or_choice_str(self)
2840 """Choice constructor -- not intended to be called directly by
2841 Kconfiglib clients."""
2843 self.name = None # Yes, choices can be named
2846 self.def_exprs = [] # 'default' properties
2847 self.help = None # Help text
2848 self.block = None # List of contained items
2852 self.user_val = None
2853 self.user_mode = None
2855 # We need to filter out symbols that appear within the choice block but
2856 # are not considered choice items (see
2857 # Choice._determine_actual_symbols()) This list holds the "actual"
2859 self.actual_symbols = []
2861 # The prompts and default values without any dependencies from
2862 # enclosing menus and ifs propagated
2863 self.orig_prompts = []
2864 self.orig_def_exprs = []
2866 # Dependencies inherited from containing menus and ifs
2867 self.deps_from_containing = None
2868 # The set of symbols referenced by this choice (see
2869 # get_referenced_symbols())
2870 self.referenced_syms = set()
2871 # Like 'referenced_syms', but includes symbols from
2872 # dependencies inherited from enclosing menus and ifs
2873 self.all_referenced_syms = set()
2875 # See Choice.get_def_locations()
2876 self.def_locations = []
2879 self.cached_selection = None
2880 self.cached_visibility = None
2882 self.optional = False
2884 def _determine_actual_symbols(self):
2885 """If a symbol's visibility depends on the preceding symbol within a
2886 choice, it is no longer viewed as a choice item. (This is quite
2887 possibly a bug, but some things consciously use it... ugh. It stems
2888 from automatic submenu creation.) In addition, it's possible to have
2889 choices and comments within choices, and those shouldn't be considered
2890 choice items either. Only drivers/usb/gadget/Kconfig seems to depend on
2891 any of this. This method computes the "actual" items in the choice and
2892 sets the is_choice_sym flag on them (retrieved via is_choice_symbol()).
2894 Don't let this scare you: an earlier version simply checked for a
2895 sequence of symbols where all symbols after the first appeared in the
2896 'depends on' expression of the first, and that worked fine. The added
2897 complexity is to be future-proof in the event that
2898 drivers/usb/gadget/Kconfig turns even more sinister. It might very well
2899 be overkilling things (especially if that file is refactored ;)."""
2901 # Items might depend on each other in a tree structure, so we need a
2902 # stack to keep track of the current tentative parent
2905 for item in self.block:
2906 if not isinstance(item, Symbol):
2911 if item._has_auto_menu_dep_on(stack[-1]):
2912 # The item should not be viewed as a choice item, so don't
2913 # set item.is_choice_sym
2919 item.is_choice_sym = True
2920 self.actual_symbols.append(item)
2923 def _cache_ret(self, selection):
2924 # As None is used to indicate the lack of a cached value we can't use
2925 # that to cache the fact that the choice has no selection. Instead, we
2926 # use the symbolic constant NO_SELECTION.
2927 if selection is None:
2928 self.cached_selection = NO_SELECTION
2930 self.cached_selection = selection
2934 def _invalidate(self):
2935 self.cached_selection = None
2936 self.cached_visibility = None
2938 def _unset_user_value(self):
2940 self.user_val = None
2941 self.user_mode = None
2943 def _make_conf(self, append_fn):
2944 _make_block_conf(self.block, append_fn)
2946 class Comment(Item):
2948 """Represents a comment statement."""
2954 def get_config(self):
2955 """Returns the Config instance this comment is from."""
2959 """Returns the text of the comment."""
2962 def get_parent(self):
2963 """Returns the menu or choice statement that contains the comment, or
2964 None if the comment is at the top level. Note that if statements are
2965 treated as syntactic sugar and do not have an explicit class
2969 def get_location(self):
2970 """Returns the location of the comment as a (filename, linenr) tuple,
2971 where filename is a string and linenr an int."""
2972 return (self.filename, self.linenr)
2974 def get_visibility(self):
2975 """Returns the visibility of the comment. See also
2976 Symbol.get_visibility()."""
2977 return self.config._eval_expr(self.dep_expr)
2979 def get_referenced_symbols(self, refs_from_enclosing=False):
2980 """See Symbol.get_referenced_symbols()."""
2981 return self.all_referenced_syms if refs_from_enclosing else \
2982 self.referenced_syms
2985 """Returns a string containing various information about the
2987 dep_str = self.config._expr_val_str(self.orig_deps,
2988 "(no dependencies)")
2990 additional_deps_str = " " + \
2991 self.config._expr_val_str(self.deps_from_containing,
2992 "(no additional dependencies)")
2994 return _lines("Comment",
2995 "Text: " + str(self.text),
2996 "Dependencies: " + dep_str,
2997 "Additional dependencies from enclosing menus and "
2999 additional_deps_str,
3000 "Location: {0}:{1}".format(self.filename, self.linenr))
3007 """Comment constructor -- not intended to be called directly by
3008 Kconfiglib clients."""
3011 self.dep_expr = None
3015 # Dependency expression without dependencies from enclosing menus and
3017 self.orig_deps = None
3019 # Dependencies inherited from containing menus and ifs
3020 self.deps_from_containing = None
3021 # The set of symbols referenced by this comment (see
3022 # get_referenced_symbols())
3023 self.referenced_syms = set()
3024 # Like 'referenced_syms', but includes symbols from
3025 # dependencies inherited from enclosing menus and ifs
3026 self.all_referenced_syms = None
3028 self.filename = None
3031 def _make_conf(self, append_fn):
3032 if self.config._eval_expr(self.dep_expr) != "n":
3033 append_fn("\n#\n# {0}\n#".format(self.text))
3035 class Kconfig_Syntax_Error(Exception):
3036 """Exception raised for syntax errors."""
3039 class Internal_Error(Exception):
3040 """Exception raised for internal errors."""
3047 def tri_less(v1, v2):
3048 """Returns True if the tristate v1 is less than the tristate v2, where "n",
3049 "m" and "y" are ordered from lowest to highest."""
3050 return TRI_TO_INT[v1] < TRI_TO_INT[v2]
3052 def tri_less_eq(v1, v2):
3053 """Returns True if the tristate v1 is less than or equal to the tristate
3054 v2, where "n", "m" and "y" are ordered from lowest to highest."""
3055 return TRI_TO_INT[v1] <= TRI_TO_INT[v2]
3057 def tri_greater(v1, v2):
3058 """Returns True if the tristate v1 is greater than the tristate v2, where
3059 "n", "m" and "y" are ordered from lowest to highest."""
3060 return TRI_TO_INT[v1] > TRI_TO_INT[v2]
3062 def tri_greater_eq(v1, v2):
3063 """Returns True if the tristate v1 is greater than or equal to the tristate
3064 v2, where "n", "m" and "y" are ordered from lowest to highest."""
3065 return TRI_TO_INT[v1] >= TRI_TO_INT[v2]
3071 class _Feed(object):
3073 """Class for working with sequences in a stream-like fashion; handy for
3076 # This would be more helpful on the item classes, but would remove some
3078 __slots__ = ['items', 'length', 'i']
3080 def __init__(self, items):
3082 self.length = len(self.items)
3086 if self.i >= self.length:
3088 item = self.items[self.i]
3092 def peek_next(self):
3093 return None if self.i >= self.length else self.items[self.i]
3095 def check(self, token):
3096 """Check if the next token is 'token'. If so, remove it from the token
3097 feed and return True. Otherwise, leave it in and return False."""
3098 if self.i < self.length and self.items[self.i] == token:
3103 def unget_all(self):
3106 class _FileFeed(object):
3108 """Feeds lines from a file. Keeps track of the filename and current line
3109 number. Joins any line ending in \\ with the following line. We need to be
3110 careful to get the line number right in the presence of continuation
3113 __slots__ = ['filename', 'lines', 'length', 'linenr']
3115 def __init__(self, filename):
3116 self.filename = _clean_up_path(filename)
3117 with open(filename, "r") as f:
3118 # No interleaving of I/O and processing yet. Don't know if it would
3120 self.lines = f.readlines()
3121 self.length = len(self.lines)
3125 if self.linenr >= self.length:
3127 line = self.lines[self.linenr]
3129 while line.endswith("\\\n"):
3130 line = line[:-2] + self.lines[self.linenr]
3134 def peek_next(self):
3135 linenr = self.linenr
3136 if linenr >= self.length:
3138 line = self.lines[linenr]
3139 while line.endswith("\\\n"):
3141 line = line[:-2] + self.lines[linenr]
3146 while self.lines[self.linenr].endswith("\\\n"):
3149 def next_nonblank(self):
3150 """Removes lines up to and including the next non-blank (not all-space)
3151 line and returns it. Returns None if there are no more non-blank
3154 line = self.get_next()
3155 if line is None or not line.isspace():
3159 # Internal functions
3162 def _get_visibility(sc):
3163 """Symbols and Choices have a "visibility" that acts as an upper bound on
3164 the values a user can set for them, corresponding to the visibility in e.g.
3165 'make menuconfig'. This function calculates the visibility for the Symbol
3166 or Choice 'sc' -- the logic is nearly identical."""
3167 if sc.cached_visibility is None:
3169 for _, cond_expr in sc.prompts:
3170 vis = sc.config._eval_max(vis, cond_expr)
3172 if isinstance(sc, Symbol) and sc.is_choice_sym:
3173 vis = sc.config._eval_min(vis, _get_visibility(sc.parent))
3175 # Promote "m" to "y" if we're dealing with a non-tristate
3176 if vis == "m" and sc.type != TRISTATE:
3179 sc.cached_visibility = vis
3181 return sc.cached_visibility
3183 def _make_and(e1, e2):
3184 """Constructs an AND (&&) expression. Performs trivial simplification.
3185 Nones equate to 'y'.
3187 Note: returns None if e1 == e2 == None."""
3188 if e1 is None or e1 == "y":
3190 if e2 is None or e2 == "y":
3193 # Prefer to merge argument lists if possible to reduce the number of nodes
3195 if isinstance(e1, tuple) and e1[0] == AND:
3196 if isinstance(e2, tuple) and e2[0] == AND:
3197 return (AND, e1[1] + e2[1])
3198 return (AND, e1[1] + [e2])
3200 if isinstance(e2, tuple) and e2[0] == AND:
3201 return (AND, e2[1] + [e1])
3203 return (AND, [e1, e2])
3205 def _make_or(e1, e2):
3206 """Constructs an OR (||) expression. Performs trivial simplification and
3207 avoids Nones. Nones equate to 'y', which is usually what we want, but needs
3208 to be kept in mind."""
3210 # Perform trivial simplification and avoid None's (which
3211 # correspond to y's)
3212 if e1 is None or e2 is None or e1 == "y" or e2 == "y":
3217 # Prefer to merge argument lists if possible to reduce the number of nodes
3219 if isinstance(e1, tuple) and e1[0] == OR:
3220 if isinstance(e2, tuple) and e2[0] == OR:
3221 return (OR, e1[1] + e2[1])
3222 return (OR, e1[1] + [e2])
3224 if isinstance(e2, tuple) and e2[0] == OR:
3225 return (OR, e2[1] + [e1])
3227 return (OR, [e1, e2])
3229 def _get_expr_syms_rec(expr, res):
3230 """_get_expr_syms() helper. Recurses through expressions."""
3231 if isinstance(expr, Symbol):
3233 elif isinstance(expr, str):
3235 elif expr[0] == AND or expr[0] == OR:
3236 for term in expr[1]:
3237 _get_expr_syms_rec(term, res)
3238 elif expr[0] == NOT:
3239 _get_expr_syms_rec(expr[1], res)
3240 elif expr[0] == EQUAL or expr[0] == UNEQUAL:
3241 if isinstance(expr[1], Symbol):
3243 if isinstance(expr[2], Symbol):
3246 _internal_error("Internal error while fetching symbols from an "
3247 "expression with token stream {0}.".format(expr))
3249 def _get_expr_syms(expr):
3250 """Returns the set() of symbols appearing in expr."""
3252 if expr is not None:
3253 _get_expr_syms_rec(expr, res)
3257 """Returns the value of obj as a string. If obj is not a string (constant
3258 symbol), it must be a Symbol."""
3259 return obj if isinstance(obj, str) else obj.get_value()
3261 def _make_block_conf(block, append_fn):
3262 """Returns a list of .config strings for a block (list) of items."""
3264 # Collect the substrings in a list and later use join() instead of += to
3265 # build the final .config contents. With older Python versions, this yields
3266 # linear instead of quadratic complexity.
3268 item._make_conf(append_fn)
3270 def _sym_str_string(sym_or_str):
3271 if isinstance(sym_or_str, str):
3272 return '"' + sym_or_str + '"'
3273 return sym_or_str.name
3275 def _intersperse(lst, op):
3276 """_expr_to_str() helper. Gets the string representation of each expression
3277 in lst and produces a list where op has been inserted between the
3284 def handle_sub_expr(expr):
3285 no_parens = isinstance(expr, (str, Symbol)) or \
3286 expr[0] in (EQUAL, UNEQUAL) or \
3287 PRECEDENCE[op] <= PRECEDENCE[expr[0]]
3290 res.extend(_expr_to_str_rec(expr))
3294 op_str = OP_TO_STR[op]
3296 handle_sub_expr(lst[0])
3297 for expr in lst[1:]:
3299 handle_sub_expr(expr)
3303 def _expr_to_str_rec(expr):
3307 if isinstance(expr, (Symbol, str)):
3308 return [_sym_str_string(expr)]
3310 if expr[0] in (AND, OR):
3311 return _intersperse(expr[1], expr[0])
3314 need_parens = not isinstance(expr[1], (str, Symbol))
3319 res.extend(_expr_to_str_rec(expr[1]))
3324 if expr[0] in (EQUAL, UNEQUAL):
3325 return [_sym_str_string(expr[1]),
3327 _sym_str_string(expr[2])]
3329 def _expr_to_str(expr):
3330 return "".join(_expr_to_str_rec(expr))
3332 def _indentation(line):
3333 """Returns the length of the line's leading whitespace, treating tab stops
3334 as being spaced 8 characters apart."""
3335 line = line.expandtabs()
3336 return len(line) - len(line.lstrip())
3338 def _deindent(line, indent):
3339 """Deindent 'line' by 'indent' spaces."""
3340 line = line.expandtabs()
3341 if len(line) <= indent:
3343 return line[indent:]
3345 def _is_base_n(s, n):
3353 """Returns a string consisting of all arguments, with newlines inserted
3355 return "\n".join(args)
3358 """Returns a new string with "#" inserted before each line in 's'."""
3361 res = "".join(["#" + line for line in s.splitlines(True)])
3362 if s.endswith("\n"):
3366 def _clean_up_path(path):
3367 """Strips an initial "./" and any trailing slashes from 'path'."""
3368 if path.startswith("./"):
3370 return path.rstrip("/")
3372 def _stderr_msg(msg, filename, linenr):
3373 if filename is not None:
3374 sys.stderr.write("{0}:{1}: ".format(_clean_up_path(filename), linenr))
3375 sys.stderr.write(msg + "\n")
3377 def _tokenization_error(s, filename, linenr):
3378 loc = "" if filename is None else "{0}:{1}: ".format(filename, linenr)
3379 raise Kconfig_Syntax_Error("{0}Couldn't tokenize '{1}'"
3380 .format(loc, s.strip()))
3382 def _parse_error(s, msg, filename, linenr):
3383 loc = "" if filename is None else "{0}:{1}: ".format(filename, linenr)
3384 raise Kconfig_Syntax_Error("{0}Couldn't parse '{1}'{2}"
3385 .format(loc, s.strip(),
3386 "." if msg is None else ": " + msg))
3388 def _internal_error(msg):
3389 raise Internal_Error(msg +
3390 "\nSorry! You may want to send an email to ulfalizer a.t Google's "
3391 "email service to tell me about this. Include the message above and the "
3392 "stack trace and describe what you were doing.")
3395 # Internal global constants
3399 (T_AND, T_OR, T_NOT,
3400 T_OPEN_PAREN, T_CLOSE_PAREN,
3402 T_MAINMENU, T_MENU, T_ENDMENU,
3403 T_SOURCE, T_CHOICE, T_ENDCHOICE,
3404 T_COMMENT, T_CONFIG, T_MENUCONFIG,
3405 T_HELP, T_IF, T_ENDIF, T_DEPENDS, T_ON,
3406 T_OPTIONAL, T_PROMPT, T_DEFAULT,
3407 T_BOOL, T_TRISTATE, T_HEX, T_INT, T_STRING,
3408 T_DEF_BOOL, T_DEF_TRISTATE,
3409 T_SELECT, T_IMPLY, T_RANGE, T_OPTION, T_ALLNOCONFIG_Y, T_ENV,
3410 T_DEFCONFIG_LIST, T_MODULES, T_VISIBLE) = range(40)
3412 # The leading underscore before the function assignments below prevent pydoc
3413 # from listing them. The constants could be hidden too, but they're fairly
3414 # obviously internal anyway, so don't bother spamming the code.
3416 # Keyword to token map. Note that the get() method is assigned directly as a
3417 # small optimization.
3419 {"mainmenu": T_MAINMENU, "menu": T_MENU, "endmenu": T_ENDMENU,
3420 "endif": T_ENDIF, "endchoice": T_ENDCHOICE, "source": T_SOURCE,
3421 "choice": T_CHOICE, "config": T_CONFIG, "comment": T_COMMENT,
3422 "menuconfig": T_MENUCONFIG, "help": T_HELP, "if": T_IF,
3423 "depends": T_DEPENDS, "on": T_ON, "optional": T_OPTIONAL,
3424 "prompt": T_PROMPT, "default": T_DEFAULT, "bool": T_BOOL, "boolean": T_BOOL,
3425 "tristate": T_TRISTATE, "int": T_INT, "hex": T_HEX, "def_bool": T_DEF_BOOL,
3426 "def_tristate": T_DEF_TRISTATE, "string": T_STRING, "select": T_SELECT,
3427 "imply": T_IMPLY, "range": T_RANGE, "option": T_OPTION,
3428 "allnoconfig_y": T_ALLNOCONFIG_Y, "env": T_ENV,
3429 "defconfig_list": T_DEFCONFIG_LIST, "modules": T_MODULES,
3430 "visible": T_VISIBLE}.get
3432 # Strings to use for True and False
3433 BOOL_STR = {False: "false", True: "true"}
3435 # Tokens after which identifier-like lexemes are treated as strings. T_CHOICE
3436 # is included to avoid symbols being registered for named choices.
3437 STRING_LEX = frozenset((T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING, T_CHOICE,
3438 T_PROMPT, T_MENU, T_COMMENT, T_SOURCE, T_MAINMENU))
3440 # Matches the initial token on a line; see _tokenize(). Also eats trailing
3441 # whitespace as an optimization.
3442 _initial_token_re_match = re.compile(r"[^\w]*(\w+)\s*").match
3444 # Matches an identifier/keyword optionally preceded by whitespace. Also eats
3445 # trailing whitespace as an optimization.
3446 _id_keyword_re_match = re.compile(r"\s*([\w./-]+)\s*").match
3448 # Regular expressions for parsing .config files
3449 _set_re_match = re.compile(r"CONFIG_(\w+)=(.*)").match
3450 _unset_re_match = re.compile(r"# CONFIG_(\w+) is not set").match
3452 # Regular expression for finding $-references to symbols in strings
3453 _sym_ref_re_search = re.compile(r"\$[A-Za-z0-9_]+").search
3455 # Integers representing symbol types
3456 UNKNOWN, BOOL, TRISTATE, STRING, HEX, INT = range(6)
3458 # Strings to use for types
3459 TYPENAME = {UNKNOWN: "unknown", BOOL: "bool", TRISTATE: "tristate",
3460 STRING: "string", HEX: "hex", INT: "int"}
3462 # Token to type mapping
3463 TOKEN_TO_TYPE = {T_BOOL: BOOL, T_TRISTATE: TRISTATE, T_STRING: STRING,
3464 T_INT: INT, T_HEX: HEX}
3466 # Default values for symbols of different types (the value the symbol gets if
3467 # it is not assigned a user value and none of its 'default' clauses kick in)
3468 DEFAULT_VALUE = {BOOL: "n", TRISTATE: "n", STRING: "", INT: "", HEX: ""}
3470 # Indicates that no item is selected in a choice statement
3473 # Integers representing expression types
3474 AND, OR, NOT, EQUAL, UNEQUAL = range(5)
3476 # Map from tristate values to integers
3477 TRI_TO_INT = {"n": 0, "m": 1, "y": 2}
3479 # Printing-related stuff
3481 OP_TO_STR = {AND: " && ", OR: " || ", EQUAL: " = ", UNEQUAL: " != "}
3482 PRECEDENCE = {OR: 0, AND: 1, NOT: 2}