1 # This is Kconfiglib, a Python library for scripting, debugging, and extracting
2 # information from Kconfig-based configuration systems. To view the
7 # or, if you prefer HTML,
9 # $ pydoc -w kconfiglib
11 # The examples/ subdirectory contains examples, to be run with e.g.
13 # $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
15 # Look in testsuite.py for the test suite.
18 Kconfiglib is a Python library for scripting and extracting information from
19 Kconfig-based configuration systems. Features include the following:
21 - Symbol values and properties can be looked up and values assigned
23 - .config files can be read and written.
24 - Expressions can be evaluated in the context of a Kconfig configuration.
25 - Relations between symbols can be quickly determined, such as finding all
26 symbols that reference a particular symbol.
27 - Highly compatible with the scripts/kconfig/*conf utilities. The test suite
28 automatically compares outputs between Kconfiglib and the C implementation
29 for a large number of cases.
31 For the Linux kernel, scripts are run using
33 $ make scriptconfig [ARCH=<arch>] SCRIPT=<path to script> [SCRIPT_ARG=<arg>]
35 Using the 'scriptconfig' target ensures that required environment variables
36 (SRCARCH, ARCH, srctree, KERNELVERSION, etc.) are set up correctly.
38 Scripts receive the name of the Kconfig file to load in sys.argv[1]. As of
39 Linux 4.1.0-rc5, this is always "Kconfig" from the kernel top-level directory.
40 If an argument is provided with SCRIPT_ARG, it appears as sys.argv[2].
42 To get an interactive Python prompt with Kconfiglib preloaded and a Config
43 object 'c' created, run
45 $ make iscriptconfig [ARCH=<arch>]
47 Kconfiglib supports both Python 2 and Python 3. For (i)scriptconfig, the Python
48 interpreter to use can be passed in PYTHONCMD, which defaults to 'python'. PyPy
49 works well too, and might give a nice speedup for long-running jobs.
51 The examples/ directory contains short example scripts, which can be run with
54 $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
58 $ make scriptconfig SCRIPT=Kconfiglib/examples/help_grep.py SCRIPT_ARG=kernel
60 testsuite.py contains the test suite. See the top of the script for how to run
63 Credits: Written by Ulf "Ulfalizer" Magnusson
65 Send bug reports, suggestions and other feedback to ulfalizer a.t Google's
66 email service. Don't wrestle with internal APIs. Tell me what you need and I
67 might add it in a safe way as a client API instead."""
80 # Internal global constants
82 # Line length: 79 columns
90 """Represents a Kconfig configuration, e.g. for i386 or ARM. This is the
91 set of symbols and other items appearing in the configuration together with
92 their values. Creating any number of Config objects -- including for
93 different architectures -- is safe; Kconfiglib has no global state."""
99 def __init__(self, filename="Kconfig", base_dir=None, print_warnings=True,
100 print_undef_assign=False):
101 """Creates a new Config object, representing a Kconfig configuration.
102 Raises Kconfig_Syntax_Error on syntax errors.
104 filename (default: "Kconfig"): The base Kconfig file of the
105 configuration. For the Linux kernel, you'll probably want "Kconfig"
106 from the top-level directory, as environment variables will make
107 sure the right Kconfig is included from there
108 (arch/<architecture>/Kconfig). If you are using Kconfiglib via 'make
109 scriptconfig', the filename of the base base Kconfig file will be in
112 base_dir (default: None): The base directory relative to which 'source'
113 statements within Kconfig files will work. For the Linux kernel this
114 should be the top-level directory of the kernel tree. $-references
115 to existing environment variables will be expanded.
117 If None (the default), the environment variable 'srctree' will be
118 used if set, and the current directory otherwise. 'srctree' is set
119 by the Linux makefiles to the top-level kernel directory. A default
120 of "." would not work with an alternative build directory.
122 print_warnings (default: True): Set to True if warnings related to this
123 configuration should be printed to stderr. This can be changed later
124 with Config.set_print_warnings(). It is provided as a constructor
125 argument since warnings might be generated during parsing.
127 print_undef_assign (default: False): Set to True if informational
128 messages related to assignments to undefined symbols should be
129 printed to stderr for this configuration. Can be changed later with
130 Config.set_print_undef_assign()."""
132 # The set of all symbols, indexed by name (a string)
134 # Python 2/3 compatibility hack. This is the only one needed.
135 self.syms_iter = self.syms.values if sys.version_info[0] >= 3 else \
138 # The set of all defined symbols in the configuration in the order they
139 # appear in the Kconfig files. This excludes the special symbols n, m,
140 # and y as well as symbols that are referenced but never defined.
141 self.kconfig_syms = []
143 # The set of all named choices (yes, choices can have names), indexed
145 self.named_choices = {}
147 # Lists containing all choices, menus and comments in the configuration
152 def register_special_symbol(type_, name, val):
154 sym.is_special_ = True
155 sym.is_defined_ = True
160 self.syms[name] = sym
163 # The special symbols n, m and y, used as shorthand for "n", "m" and
165 self.n = register_special_symbol(TRISTATE, "n", "n")
166 self.m = register_special_symbol(TRISTATE, "m", "m")
167 self.y = register_special_symbol(TRISTATE, "y", "y")
168 # DEFCONFIG_LIST uses this
169 # changed os.uname to platform.uname for compatibility with Windows
170 register_special_symbol(STRING, "UNAME_RELEASE", platform.uname()[2])
172 # The symbol with "option defconfig_list" set, containing a list of
173 # default .config files
174 self.defconfig_sym = None
176 # See Symbol.get_(src)arch()
177 self.arch = os.environ.get("ARCH")
178 self.srcarch = os.environ.get("SRCARCH")
180 # If you set CONFIG_ in the environment, Kconfig will prefix all symbols
181 # with its value when saving the configuration, instead of using the default, "CONFIG_".
182 self.config_prefix = os.environ.get("CONFIG_")
183 if self.config_prefix is None:
184 self.config_prefix = "CONFIG_"
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
192 self.base_dir = self.srctree if base_dir is None else \
193 os.path.expandvars(base_dir)
195 # The 'mainmenu' text
196 self.mainmenu_text = None
198 # The filename of the most recently loaded .config file
199 self.config_filename = None
200 # The textual header of the most recently loaded .config, uncommented
201 self.config_header = None
203 self.print_warnings = print_warnings
204 self.print_undef_assign = print_undef_assign
206 # For parsing routines that stop when finding a line belonging to a
207 # different construct, these holds that line and the tokenized version
208 # of that line. The purpose is to avoid having to re-tokenize the line,
209 # which is inefficient and causes problems when recording references to
212 self.end_line_tokens = None
214 # See the comment in _parse_expr().
215 self._cur_item = None
217 self._filename = None
219 self._transform_m = None
221 # Parse the Kconfig files
222 self.top_block = self._parse_file(filename, None, None, None)
224 # Build Symbol.dep for all symbols
228 """Returns the value the environment variable ARCH had at the time the
229 Config instance was created, or None if ARCH was not set. For the
230 kernel, this corresponds to the architecture being built for, with
231 values such as "i386" or "mips"."""
234 def get_srcarch(self):
235 """Returns the value the environment variable SRCARCH had at the time
236 the Config instance was created, or None if SRCARCH was not set. For
237 the kernel, this corresponds to the particular arch/ subdirectory
238 containing architecture-specific code."""
241 def get_srctree(self):
242 """Returns the value the environment variable srctree had at the time
243 the Config instance was created, or None if srctree was not defined.
244 This variable points to the source directory and is used when building
245 in a separate directory."""
248 def get_base_dir(self):
249 """Returns the base directory relative to which 'source' statements
250 will work, passed as an argument to Config.__init__()."""
253 def get_kconfig_filename(self):
254 """Returns the name of the (base) kconfig file this configuration was
258 def get_config_filename(self):
259 """Returns the filename of the most recently loaded configuration file,
260 or None if no configuration has been loaded."""
261 return self.config_filename
263 def get_config_header(self):
264 """Returns the (uncommented) textual header of the .config file most
265 recently loaded with load_config(). Returns None if no .config file has
266 been loaded or if the most recently loaded .config file has no header.
267 The header consists of all lines up to but not including the first line
270 1. Does not start with "#"
271 2. Has the form "# CONFIG_FOO is not set."
273 return self.config_header
275 def get_mainmenu_text(self):
276 """Returns the text of the 'mainmenu' statement (with $-references to
277 symbols replaced by symbol values), or None if the configuration has no
278 'mainmenu' statement."""
279 return None if self.mainmenu_text is None else \
280 self._expand_sym_refs(self.mainmenu_text)
282 def get_defconfig_filename(self):
283 """Returns the name of the defconfig file, which is the first existing
284 file in the list given in a symbol having 'option defconfig_list' set.
285 $-references to symbols will be expanded ("$FOO bar" -> "foo bar" if
286 FOO has the value "foo"). Returns None in case of no defconfig file.
287 Setting 'option defconfig_list' on multiple symbols currently results
288 in undefined behavior.
290 If the environment variable 'srctree' was set when the Config was
291 created, get_defconfig_filename() will first look relative to that
292 directory before looking in the current directory; see
295 WARNING: A wart here is that scripts/kconfig/Makefile sometimes uses
296 the --defconfig=<defconfig> option when calling the C implementation of
297 e.g. 'make defconfig'. This option overrides the 'option
298 defconfig_list' symbol, meaning the result from
299 get_defconfig_filename() might not match what 'make defconfig' would
300 use. That probably ought to be worked around somehow, so that this
301 function always gives the "expected" result."""
302 if self.defconfig_sym is None:
304 for filename, cond_expr in self.defconfig_sym.def_exprs:
305 if self._eval_expr(cond_expr) == "y":
306 filename = self._expand_sym_refs(filename)
307 # We first look in $srctree. os.path.join() won't work here as
308 # an absolute path in filename would override $srctree.
309 srctree_filename = os.path.normpath(self.srctree + "/" +
311 if os.path.exists(srctree_filename):
312 return srctree_filename
313 if os.path.exists(filename):
317 def get_symbol(self, name):
318 """Returns the symbol with name 'name', or None if no such symbol
319 appears in the configuration. An alternative shorthand is conf[name],
320 where conf is a Config instance, though that will instead raise
321 KeyError if the symbol does not exist."""
322 return self.syms.get(name)
324 def __getitem__(self, name):
325 """Returns the symbol with name 'name'. Raises KeyError if the symbol
326 does not appear in the configuration."""
327 return self.syms[name]
329 def get_symbols(self, all_symbols=True):
330 """Returns a list of symbols from the configuration. An alternative for
331 iterating over all defined symbols (in the order of definition) is
336 which relies on Config implementing __iter__() and is equivalent to
338 for sym in config.get_symbols(False):
341 all_symbols (default: True): If True, all symbols -- including special
342 and undefined symbols -- will be included in the result, in an
343 undefined order. If False, only symbols actually defined and not
344 merely referred to in the configuration will be included in the
345 result, and will appear in the order that they are defined within
346 the Kconfig configuration files."""
347 return list(self.syms.values()) if all_symbols else self.kconfig_syms
350 """Convenience function for iterating over the set of all defined
351 symbols in the configuration, used like
356 The iteration happens in the order of definition within the Kconfig
357 configuration files. Symbols only referred to but not defined will not
358 be included, nor will the special symbols n, m, and y. If you want to
359 include such symbols as well, see config.get_symbols()."""
360 return iter(self.kconfig_syms)
362 def get_choices(self):
363 """Returns a list containing all choice statements in the
364 configuration, in the order they appear in the Kconfig files."""
368 """Returns a list containing all menus in the configuration, in the
369 order they appear in the Kconfig files."""
372 def get_comments(self):
373 """Returns a list containing all comments in the configuration, in the
374 order they appear in the Kconfig files."""
377 def get_top_level_items(self):
378 """Returns a list containing the items (symbols, menus, choices, and
379 comments) at the top level of the configuration -- that is, all items
380 that do not appear within a menu or choice. The items appear in the
381 same order as within the configuration."""
382 return self.top_block
384 def load_config(self, filename, replace=True):
385 """Loads symbol values from a file in the familiar .config format.
386 Equivalent to calling Symbol.set_user_value() to set each of the
389 "# CONFIG_FOO is not set" within a .config file is treated specially
390 and sets the user value of FOO to 'n'. The C implementation works the
393 filename: The .config file to load. $-references to existing
394 environment variables will be expanded. For scripts to work even when
395 an alternative build directory is used with the Linux kernel, you
396 need to refer to the top-level kernel directory with "$srctree".
398 replace (default: True): True if the configuration should replace the
399 old configuration; False if it should add to it."""
401 # Regular expressions for parsing .config files
402 _set_re_match = re.compile(r"{}(\w+)=(.*)".format(self.config_prefix)).match
403 _unset_re_match = re.compile(r"# {}(\w+) is not set".format(self.config_prefix)).match
405 # Put this first so that a missing file doesn't screw up our state
406 filename = os.path.expandvars(filename)
407 line_feeder = _FileFeed(filename)
409 self.config_filename = filename
415 def is_header_line(line):
416 return line is not None and line.startswith("#") and \
417 not _unset_re_match(line)
419 self.config_header = None
421 line = line_feeder.peek_next()
422 if is_header_line(line):
423 self.config_header = ""
424 while is_header_line(line_feeder.peek_next()):
425 self.config_header += line_feeder.get_next()[1:]
426 # Remove trailing newline
427 if self.config_header.endswith("\n"):
428 self.config_header = self.config_header[:-1]
431 # Read assignments. Hotspot for some workloads.
434 def warn_override(filename, linenr, name, old_user_val, new_user_val):
435 self._warn('overriding the value of {0}. '
436 'Old value: "{1}", new value: "{2}".'
437 .format(name, old_user_val, new_user_val),
440 # Invalidate everything to keep things simple. It might be possible to
441 # improve performance for the case where multiple configurations are
442 # loaded by only invalidating a symbol (and its dependent symbols) if
443 # the new user value differs from the old. One complication would be
444 # that symbols not mentioned in the .config must lose their user value
445 # when replace = True, which is the usual case.
447 self.unset_user_values()
449 self._invalidate_all()
452 line = line_feeder.get_next()
458 set_match = _set_re_match(line)
460 name, val = set_match.groups()
462 if val.startswith('"'):
463 if len(val) < 2 or val[-1] != '"':
464 _parse_error(line, "malformed string literal",
465 line_feeder.filename, line_feeder.linenr)
466 # Strip quotes and remove escapings. The unescaping
467 # procedure should be safe since " can only appear as \"
469 val = val[1:-1].replace('\\"', '"').replace("\\\\", "\\")
471 if name in self.syms:
472 sym = self.syms[name]
473 if sym.user_val is not None:
474 warn_override(line_feeder.filename, line_feeder.linenr,
475 name, sym.user_val, val)
477 if sym.is_choice_sym:
478 user_mode = sym.parent.user_mode
479 if user_mode is not None and user_mode != val:
480 self._warn("assignment to {0} changes mode of "
481 'containing choice from "{1}" to "{2}".'
482 .format(name, val, user_mode),
483 line_feeder.filename,
486 sym._set_user_value_no_invalidate(val, True)
488 if self.print_undef_assign:
489 _stderr_msg('note: attempt to assign the value "{0}" '
490 "to the undefined symbol {1}."
492 line_feeder.filename, line_feeder.linenr)
494 unset_match = _unset_re_match(line)
496 name = unset_match.group(1)
497 if name in self.syms:
498 sym = self.syms[name]
499 if sym.user_val is not None:
500 warn_override(line_feeder.filename,
502 name, sym.user_val, "n")
504 sym._set_user_value_no_invalidate("n", True)
506 def write_config(self, filename, header=None):
507 """Writes out symbol values in the familiar .config format.
509 Kconfiglib makes sure the format matches what the C implementation
510 would generate, down to whitespace. This eases testing.
512 filename: The filename under which to save the configuration.
514 header (default: None): A textual header that will appear at the
515 beginning of the file, with each line commented out automatically.
516 None means no header."""
518 for sym in self.syms_iter():
519 sym.already_written = False
521 with open(filename, "w") as f:
523 if header is not None:
524 f.write(_comment(header))
527 # Build and write configuration
529 _make_block_conf(self.top_block, conf_strings.append)
530 f.write("\n".join(conf_strings))
534 """Returns the value of the expression 's' -- where 's' is represented
535 as a string -- in the context of the configuration. Raises
536 Kconfig_Syntax_Error if syntax errors are detected in 's'.
538 For example, if FOO and BAR are tristate symbols at least one of which
539 has the value "y", then config.eval("y && (FOO || BAR)") => "y"
541 This function always yields a tristate value. To get the value of
542 non-bool, non-tristate symbols, use Symbol.get_value().
544 The result of this function is consistent with how evaluation works for
545 conditional expressions in the configuration as well as in the C
546 implementation. "m" and m are rewritten as '"m" && MODULES' and 'm &&
547 MODULES', respectively, and a result of "m" will get promoted to "y" if
548 we're running without modules.
550 Syntax checking is somewhat lax, partly to be compatible with lax
551 parsing in the C implementation."""
552 return self._eval_expr(self._parse_expr(self._tokenize(s, True), # Feed
553 None, # Current symbol/choice
556 def unset_user_values(self):
557 """Resets the values of all symbols, as if Config.load_config() or
558 Symbol.set_user_value() had never been called."""
559 for sym in self.syms_iter():
560 sym._unset_user_value_no_recursive_invalidate()
562 def set_print_warnings(self, print_warnings):
563 """Determines whether warnings related to this configuration (for
564 things like attempting to assign illegal values to symbols with
565 Symbol.set_user_value()) should be printed to stderr.
567 print_warnings: True if warnings should be printed."""
568 self.print_warnings = print_warnings
570 def set_print_undef_assign(self, print_undef_assign):
571 """Determines whether informational messages related to assignments to
572 undefined symbols should be printed to stderr for this configuration.
574 print_undef_assign: If True, such messages will be printed."""
575 self.print_undef_assign = print_undef_assign
578 """Returns a string containing various information about the Config."""
579 return _lines("Configuration",
582 "Base directory : " +
584 "Value of $ARCH at creation time : " +
585 ("(not set)" if self.arch is None else self.arch),
586 "Value of $SRCARCH at creation time : " +
587 ("(not set)" if self.srcarch is None else
589 "Source tree (derived from $srctree;",
590 "defaults to '.' if $srctree isn't set) : " +
592 "Most recently loaded .config : " +
593 ("(no .config loaded)"
594 if self.config_filename is None else
595 self.config_filename),
596 "Print warnings : " +
597 BOOL_STR[self.print_warnings],
598 "Print assignments to undefined symbols : " +
599 BOOL_STR[self.print_undef_assign])
609 def _parse_file(self, filename, parent, deps, visible_if_deps, res=None):
610 """Parses the Kconfig file 'filename'. Returns a list with the Items in
611 the file. See _parse_block() for the meaning of the parameters."""
612 return self._parse_block(_FileFeed(filename), None, parent, deps,
613 visible_if_deps, res)
615 def _parse_block(self, line_feeder, end_marker, parent, deps,
616 visible_if_deps, res=None):
617 """Parses a block, which is the contents of either a file or an if,
618 menu, or choice statement. Returns a list with the Items in the block.
620 line_feeder: A _FileFeed instance feeding lines from a file. The
621 Kconfig language is line-based in practice.
623 end_marker: The token that ends the block, e.g. T_ENDIF ("endif") for
626 parent: The enclosing menu or choice, or None if we're at the top
629 deps: Dependencies from enclosing menus, choices and ifs.
631 visible_if_deps (default: None): 'visible if' dependencies from
634 res (default: None): The list to add items to. If None, a new list is
635 created to hold the items."""
637 block = [] if res is None else res
640 # Do we already have a tokenized line that we determined wasn't
641 # part of whatever we were parsing earlier? See comment in
643 if self.end_line is not None:
645 tokens = self.end_line_tokens
649 self.end_line_tokens = None
651 line = line_feeder.get_next()
653 if end_marker is not None:
654 raise Kconfig_Syntax_Error("Unexpected end of file {0}"
655 .format(line_feeder.filename))
658 tokens = self._tokenize(line, False, line_feeder.filename,
661 t0 = tokens.get_next()
665 # Cases are ordered roughly by frequency, which speeds things up a
668 if t0 == T_CONFIG or t0 == T_MENUCONFIG:
669 # The tokenizer will automatically allocate a new Symbol object
670 # for any new names it encounters, so we don't need to worry
672 sym = tokens.get_next()
674 # Symbols defined in multiple places get the parent of their
675 # first definition. However, for symbols whose parents are
676 # choice statements, the choice statement takes precedence.
677 if not sym.is_defined_ or isinstance(parent, Choice):
680 sym.is_defined_ = True
682 self.kconfig_syms.append(sym)
685 self._parse_properties(line_feeder, sym, deps, visible_if_deps)
688 kconfig_file = tokens.get_next()
689 exp_kconfig_file = self._expand_sym_refs(kconfig_file)
690 f = os.path.join(self.base_dir, exp_kconfig_file)
691 if not os.path.exists(f):
692 raise IOError('{0}:{1}: sourced file "{2}" (expands to '
693 '"{3}") not found. Perhaps base_dir '
694 '(argument to Config.__init__(), currently '
695 '"{4}") is set to the wrong value.'
696 .format(line_feeder.filename,
698 kconfig_file, exp_kconfig_file,
700 # Add items to the same block
701 self._parse_file(f, parent, deps, visible_if_deps, block)
703 elif t0 == end_marker:
704 # We have reached the end of the block
708 # If statements are treated as syntactic sugar for adding
709 # dependencies to enclosed items and do not have an explicit
710 # object representation.
712 dep_expr = self._parse_expr(tokens, None, line,
713 line_feeder.filename,
715 # Add items to the same block
716 self._parse_block(line_feeder, T_ENDIF, parent,
717 _make_and(dep_expr, deps),
718 visible_if_deps, block)
720 elif t0 == T_COMMENT:
723 comment.config = self
724 comment.parent = parent
725 comment.filename = line_feeder.filename
726 comment.linenr = line_feeder.linenr
727 comment.text = tokens.get_next()
729 self.comments.append(comment)
730 block.append(comment)
732 self._parse_properties(line_feeder, comment, deps,
740 menu.filename = line_feeder.filename
741 menu.linenr = line_feeder.linenr
742 menu.title = tokens.get_next()
744 self.menus.append(menu)
747 # Parse properties and contents
748 self._parse_properties(line_feeder, menu, deps,
750 menu.block = self._parse_block(line_feeder, T_ENDMENU, menu,
752 _make_and(visible_if_deps,
753 menu.visible_if_expr))
756 name = tokens.get_next()
759 self.choices.append(choice)
762 choice = self.named_choices.get(name)
766 self.named_choices[name] = choice
767 self.choices.append(choice)
770 choice.parent = parent
772 choice.def_locations.append((line_feeder.filename,
775 # Parse properties and contents
776 self._parse_properties(line_feeder, choice, deps,
778 choice.block = self._parse_block(line_feeder, T_ENDCHOICE,
779 choice, deps, visible_if_deps)
781 choice._determine_actual_symbols()
783 # If no type is specified for the choice, its type is that of
784 # the first choice item with a specified type
785 if choice.type == UNKNOWN:
786 for item in choice.actual_symbols:
787 if item.type != UNKNOWN:
788 choice.type = item.type
791 # Each choice item of UNKNOWN type gets the type of the choice
792 for item in choice.actual_symbols:
793 if item.type == UNKNOWN:
794 item.type = choice.type
798 elif t0 == T_MAINMENU:
799 text = tokens.get_next()
800 if self.mainmenu_text is not None:
801 self._warn("overriding 'mainmenu' text. "
802 'Old value: "{0}", new value: "{1}".'
803 .format(self.mainmenu_text, text),
804 line_feeder.filename, line_feeder.linenr)
805 self.mainmenu_text = text
808 _parse_error(line, "unrecognized construct",
809 line_feeder.filename, line_feeder.linenr)
811 def _parse_properties(self, line_feeder, stmt, deps, visible_if_deps):
812 """Parsing of properties for symbols, menus, choices, and comments.
813 Takes care of propagating dependencies from enclosing menus and ifs."""
815 def parse_val_and_cond(tokens, line, filename, linenr):
816 """Parses '<expr1> if <expr2>' constructs, where the 'if' part is
817 optional. Returns a tuple containing the parsed expressions, with
818 None as the second element if the 'if' part is missing."""
819 return (self._parse_expr(tokens, stmt, line, filename, linenr,
821 self._parse_expr(tokens, stmt, line, filename, linenr)
822 if tokens.check(T_IF) else None)
824 # In case the symbol is defined in multiple locations, we need to
825 # remember what prompts, defaults, and selects are new for this
826 # definition, as "depends on" should only apply to the local
832 # Dependencies from 'depends on' statements
833 depends_on_expr = None
836 line = line_feeder.get_next()
840 filename = line_feeder.filename
841 linenr = line_feeder.linenr
843 tokens = self._tokenize(line, False, filename, linenr)
845 t0 = tokens.get_next()
849 # Cases are ordered roughly by frequency, which speeds things up a
853 if not tokens.check(T_ON):
854 _parse_error(line, 'expected "on" after "depends"',
857 parsed_deps = self._parse_expr(tokens, stmt, line, filename,
860 if isinstance(stmt, (Menu, Comment)):
861 stmt.orig_deps = _make_and(stmt.orig_deps, parsed_deps)
863 depends_on_expr = _make_and(depends_on_expr, parsed_deps)
866 # Find first non-blank (not all-space) line and get its
868 line = line_feeder.next_nonblank()
872 indent = _indentation(line)
874 # If the first non-empty lines has zero indent, there is no
880 # The help text goes on till the first non-empty line with less
882 help_lines = [_deindent(line, indent)]
884 line = line_feeder.get_next()
886 (not line.isspace() and _indentation(line) < indent):
887 stmt.help = "".join(help_lines)
889 help_lines.append(_deindent(line, indent))
897 target = tokens.get_next()
899 stmt.referenced_syms.add(target)
900 stmt.selected_syms.add(target)
904 self._parse_expr(tokens, stmt, line, filename, linenr)
905 if tokens.check(T_IF) else None))
907 elif t0 in (T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING):
908 stmt.type = TOKEN_TO_TYPE[t0]
909 if tokens.peek_next() is not None:
910 new_prompt = parse_val_and_cond(tokens, line, filename,
913 elif t0 == T_DEFAULT:
914 new_def_exprs.append(parse_val_and_cond(tokens, line, filename,
917 elif t0 == T_DEF_BOOL:
919 if tokens.peek_next() is not None:
920 new_def_exprs.append(parse_val_and_cond(tokens, line,
924 # 'prompt' properties override each other within a single
925 # definition of a symbol, but additional prompts can be added
926 # by defining the symbol multiple times; hence 'new_prompt'
927 # instead of 'prompt'.
928 new_prompt = parse_val_and_cond(tokens, line, filename, linenr)
931 low = tokens.get_next()
932 high = tokens.get_next()
933 stmt.referenced_syms.add(low)
934 stmt.referenced_syms.add(high)
938 self._parse_expr(tokens, stmt, line, filename, linenr)
939 if tokens.check(T_IF) else None))
941 elif t0 == T_DEF_TRISTATE:
943 if tokens.peek_next() is not None:
944 new_def_exprs.append(parse_val_and_cond(tokens, line,
948 if tokens.check(T_ENV) and tokens.check(T_EQUAL):
949 env_var = tokens.get_next()
951 stmt.is_special_ = True
952 stmt.is_from_env = True
954 if env_var not in os.environ:
955 self._warn("The symbol {0} references the "
956 "non-existent environment variable {1} and "
957 "will get the empty string as its value. "
958 "If you're using Kconfiglib via "
959 "'make (i)scriptconfig', it should have "
960 "set up the environment correctly for you. "
961 "If you still got this message, that "
962 "might be an error, and you should email "
963 "ulfalizer a.t Google's email service."""
964 .format(stmt.name, env_var),
969 stmt.cached_val = os.environ[env_var]
971 elif tokens.check(T_DEFCONFIG_LIST):
972 self.defconfig_sym = stmt
974 elif tokens.check(T_MODULES):
975 # To reduce warning spam, only warn if 'option modules' is
976 # set on some symbol that isn't MODULES, which should be
977 # safe. I haven't run into any projects that make use
978 # modules besides the kernel yet, and there it's likely to
979 # keep being called "MODULES".
980 if stmt.name != "MODULES":
981 self._warn("the 'modules' option is not supported. "
982 "Let me know if this is a problem for you; "
983 "it shouldn't be that hard to implement. "
984 "(Note that modules are still supported -- "
985 "Kconfiglib just assumes the symbol name "
986 "MODULES, like older versions of the C "
987 "implementation did when 'option modules' "
991 elif tokens.check(T_ALLNOCONFIG_Y):
992 if not isinstance(stmt, Symbol):
994 "the 'allnoconfig_y' option is only "
997 stmt.allnoconfig_y = True
1000 _parse_error(line, "unrecognized option", filename, linenr)
1002 elif t0 == T_VISIBLE:
1003 if not tokens.check(T_IF):
1004 _parse_error(line, 'expected "if" after "visible"',
1006 if not isinstance(stmt, Menu):
1008 "'visible if' is only valid for menus",
1011 parsed_deps = self._parse_expr(tokens, stmt, line, filename,
1013 stmt.visible_if_expr = _make_and(stmt.visible_if_expr,
1016 elif t0 == T_OPTIONAL:
1017 if not isinstance(stmt, Choice):
1019 '"optional" is only valid for choices',
1022 stmt.optional = True
1025 # See comment in Config.__init__()
1026 self.end_line = line
1027 self.end_line_tokens = tokens
1030 # Done parsing properties. Now propagate 'depends on' and enclosing
1031 # menu/if dependencies to expressions.
1033 # The set of symbols referenced directly by the statement plus all
1034 # symbols referenced by enclosing menus and ifs
1035 stmt.all_referenced_syms = stmt.referenced_syms | _get_expr_syms(deps)
1037 # Save original dependencies from enclosing menus and ifs
1038 stmt.deps_from_containing = deps
1040 if isinstance(stmt, (Menu, Comment)):
1041 stmt.dep_expr = _make_and(stmt.orig_deps, deps)
1045 # See comment for 'menu_dep'
1046 stmt.menu_dep = depends_on_expr
1048 # Propagate dependencies to prompts
1050 if new_prompt is not None:
1051 # Propagate 'visible if' dependencies from enclosing menus
1052 prompt, cond_expr = new_prompt
1053 cond_expr = _make_and(cond_expr, visible_if_deps)
1054 # Propagate 'depends on' dependencies
1055 new_prompt = (prompt, _make_and(cond_expr, depends_on_expr))
1057 stmt.orig_prompts.append(new_prompt)
1058 # Finalize with dependencies from enclosing menus and ifs
1059 stmt.prompts.append((new_prompt[0],
1060 _make_and(new_prompt[1], deps)))
1062 # Propagate dependencies to defaults
1064 # Propagate 'depends on' dependencies
1065 new_def_exprs = [(val_expr, _make_and(cond_expr, depends_on_expr))
1066 for val_expr, cond_expr in new_def_exprs]
1068 stmt.orig_def_exprs.extend(new_def_exprs)
1069 # Finalize with dependencies from enclosing menus and ifs
1070 stmt.def_exprs.extend([(val_expr, _make_and(cond_expr, deps))
1071 for val_expr, cond_expr in new_def_exprs])
1073 # Propagate dependencies to selects
1075 # Only symbols can select
1076 if isinstance(stmt, Symbol):
1077 # Propagate 'depends on' dependencies
1078 new_selects = [(target, _make_and(cond_expr, depends_on_expr))
1079 for target, cond_expr in new_selects]
1081 stmt.orig_selects.extend(new_selects)
1082 # Finalize with dependencies from enclosing menus and ifs
1083 for target, cond in new_selects:
1084 target.rev_dep = _make_or(target.rev_dep,
1086 _make_and(cond, deps)))
1088 def _parse_expr(self, feed, cur_item, line, filename=None, linenr=None,
1090 """Parses an expression from the tokens in 'feed' using a simple
1091 top-down approach. The result has the form
1092 '(<operator>, [<parsed operands>])', where <operator> is e.g.
1093 kconfiglib.AND. If there is only one operand (i.e., no && or ||), then
1094 the operand is returned directly. This also goes for subexpressions.
1096 feed: _Feed instance containing the tokens for the expression.
1098 cur_item: The item (Symbol, Choice, Menu, or Comment) currently being
1099 parsed, or None if we're not parsing an item. Used for recording
1100 references to symbols.
1102 line: The line containing the expression being parsed.
1104 filename (default: None): The file containing the expression.
1106 linenr (default: None): The line number containing the expression.
1108 transform_m (default: False): Determines if 'm' should be rewritten to
1109 'm && MODULES' -- see parse_val_and_cond().
1111 Expression grammar, in decreasing order of precedence:
1114 <symbol> '=' <symbol>
1115 <symbol> '!=' <symbol>
1119 <expr> '||' <expr>"""
1121 # Use instance variables to avoid having to pass these as arguments
1122 # through the top-down parser in _parse_expr_rec(), which is tedious
1123 # and obfuscates the code. A profiler run shows no noticeable
1124 # performance difference.
1125 self._cur_item = cur_item
1126 self._transform_m = transform_m
1128 self._filename = filename
1129 self._linenr = linenr
1131 return self._parse_expr_rec(feed)
1133 def _parse_expr_rec(self, feed):
1134 or_term = self._parse_or_term(feed)
1135 if not feed.check(T_OR):
1136 # Common case -- no need for an OR node since it's just a single
1139 or_terms = [or_term, self._parse_or_term(feed)]
1140 while feed.check(T_OR):
1141 or_terms.append(self._parse_or_term(feed))
1142 return (OR, or_terms)
1144 def _parse_or_term(self, feed):
1145 and_term = self._parse_factor(feed)
1146 if not feed.check(T_AND):
1147 # Common case -- no need for an AND node since it's just a single
1150 and_terms = [and_term, self._parse_factor(feed)]
1151 while feed.check(T_AND):
1152 and_terms.append(self._parse_factor(feed))
1153 return (AND, and_terms)
1155 def _parse_factor(self, feed):
1156 token = feed.get_next()
1158 if isinstance(token, (Symbol, str)):
1159 if self._cur_item is not None and isinstance(token, Symbol):
1160 self._cur_item.referenced_syms.add(token)
1162 next_token = feed.peek_next()
1163 # For conditional expressions ('depends on <expr>',
1164 # '... if <expr>', # etc.), "m" and m are rewritten to
1166 if next_token != T_EQUAL and next_token != T_UNEQUAL:
1167 if self._transform_m and (token is self.m or token == "m"):
1168 return (AND, ["m", self._sym_lookup("MODULES")])
1171 relation = EQUAL if (feed.get_next() == T_EQUAL) else UNEQUAL
1172 token_2 = feed.get_next()
1173 if self._cur_item is not None and isinstance(token_2, Symbol):
1174 self._cur_item.referenced_syms.add(token_2)
1175 return (relation, token, token_2)
1178 return (NOT, self._parse_factor(feed))
1180 if token == T_OPEN_PAREN:
1181 expr_parse = self._parse_expr_rec(feed)
1182 if not feed.check(T_CLOSE_PAREN):
1183 _parse_error(self._line, "missing end parenthesis",
1184 self._filename, self._linenr)
1187 _parse_error(self._line, "malformed expression", self._filename,
1190 def _tokenize(self, s, for_eval, filename=None, linenr=None):
1191 """Returns a _Feed instance containing tokens derived from the string
1192 's'. Registers any new symbols encountered (via _sym_lookup()).
1194 (I experimented with a pure regular expression implementation, but it
1195 came out slower, less readable, and wouldn't have been as flexible.)
1197 for_eval: True when parsing an expression for a call to Config.eval(),
1198 in which case we should not treat the first token specially nor
1199 register new symbols."""
1202 if s == "" or s[0] == "#":
1206 previous = None # The previous token seen
1208 i = 0 # The current index in the string being tokenized
1211 # The initial word on a line is parsed specially. Let
1212 # command_chars = [A-Za-z0-9_]. Then
1213 # - leading non-command_chars characters are ignored, and
1214 # - the first token consists the following one or more
1215 # command_chars characters.
1216 # This is why things like "----help--" are accepted.
1217 initial_token_match = _initial_token_re_match(s)
1218 if initial_token_match is None:
1220 keyword = _get_keyword(initial_token_match.group(1))
1221 if keyword == T_HELP:
1222 # Avoid junk after "help", e.g. "---", being registered as a
1224 return _Feed([T_HELP])
1226 # We expect a keyword as the first token
1227 _tokenization_error(s, filename, linenr)
1231 # The current index in the string being tokenized
1232 i = initial_token_match.end()
1234 # _tokenize() is a hotspot during parsing, and this speeds things up a
1237 append = tokens.append
1239 # Main tokenization loop. (Handles tokens past the first one.)
1241 # Test for an identifier/keyword preceded by whitespace first; this
1242 # is the most common case.
1243 id_keyword_match = _id_keyword_re_match(s, i)
1244 if id_keyword_match:
1245 # We have an identifier or keyword. The above also stripped any
1246 # whitespace for us.
1247 name = id_keyword_match.group(1)
1249 i = id_keyword_match.end()
1251 keyword = _get_keyword(name)
1252 if keyword is not None:
1255 elif previous in STRING_LEX:
1256 # What would ordinarily be considered an identifier is
1257 # treated as a string after certain tokens
1260 # It's a symbol name. _sym_lookup() will take care of
1261 # allocating a new Symbol instance if it's the first time
1263 sym = self._sym_lookup(name, for_eval)
1265 if previous == T_CONFIG or previous == T_MENUCONFIG:
1266 # If the previous token is T_(MENU)CONFIG
1267 # ("(menu)config"), we're tokenizing the first line of
1268 # a symbol definition, and should remember this as a
1269 # location where the symbol is defined
1270 sym.def_locations.append((filename, linenr))
1272 # Otherwise, it's a reference to the symbol
1273 sym.ref_locations.append((filename, linenr))
1278 # Not an identifier/keyword
1280 while i < strlen and s[i].isspace():
1287 # String literal (constant symbol)
1288 if c == '"' or c == "'":
1290 # Slow path: This could probably be sped up, but it's a
1291 # very unusual case anyway.
1296 _tokenization_error(s, filename, linenr)
1302 _tokenization_error(s, filename, linenr)
1311 # Fast path: If the string contains no backslashes
1312 # (almost always) we can simply look for the matching
1316 _tokenization_error(s, filename, linenr)
1321 # Invalid characters are ignored
1322 if i >= len(s) or s[i] != "&": continue
1327 # Invalid characters are ignored
1328 if i >= len(s) or s[i] != "|": continue
1333 if i < len(s) and s[i] == "=":
1339 elif c == "=": append(T_EQUAL)
1340 elif c == "(": append(T_OPEN_PAREN)
1341 elif c == ")": append(T_CLOSE_PAREN)
1342 elif c == "#": break # Comment
1344 else: continue # Invalid characters are ignored
1346 previous = tokens[-1]
1348 return _Feed(tokens)
1350 def _sym_lookup(self, name, for_eval=False):
1351 """Fetches the symbol 'name' from the symbol table, creating and
1352 registering it if it does not exist. If 'for_eval' is True, the symbol
1353 won't be added to the symbol table if it does not exist -- this is for
1355 if name in self.syms:
1356 return self.syms[name]
1359 new_sym.config = self
1362 self._warn("no symbol {0} in configuration".format(name))
1364 self.syms[name] = new_sym
1368 # Expression evaluation
1371 def _eval_expr(self, expr):
1372 """Evaluates an expression to "n", "m", or "y"."""
1374 # Handles e.g. an "x if y" condition where the "if y" part is missing.
1378 res = self._eval_expr_rec(expr)
1380 # Promote "m" to "y" if we're running without modules.
1382 # Internally, "m" is often rewritten to "m" && MODULES by both the
1383 # C implementation and Kconfiglib, which takes care of cases where
1384 # "m" should be demoted to "n" instead.
1385 modules_sym = self.syms.get("MODULES")
1386 if modules_sym is None or modules_sym.get_value() != "y":
1390 def _eval_expr_rec(self, expr):
1391 if isinstance(expr, Symbol):
1392 # Non-bool/tristate symbols are always "n" in a tristate sense,
1393 # regardless of their value
1394 if expr.type != BOOL and expr.type != TRISTATE:
1396 return expr.get_value()
1398 if isinstance(expr, str):
1399 return expr if (expr == "y" or expr == "m") else "n"
1401 # Ordered by frequency
1405 for subexpr in expr[1]:
1406 ev = self._eval_expr_rec(subexpr)
1407 # Return immediately upon discovering an "n" term
1412 # 'res' is either "m" or "y" here; we already handled the
1413 # short-circuiting "n" case in the loop.
1417 ev = self._eval_expr_rec(expr[1])
1420 return "y" if (ev == "n") else "m"
1424 for subexpr in expr[1]:
1425 ev = self._eval_expr_rec(subexpr)
1426 # Return immediately upon discovering a "y" term
1431 # 'res' is either "n" or "m" here; we already handled the
1432 # short-circuiting "y" case in the loop.
1435 if expr[0] == EQUAL:
1436 return "y" if (_str_val(expr[1]) == _str_val(expr[2])) else "n"
1438 if expr[0] == UNEQUAL:
1439 return "y" if (_str_val(expr[1]) != _str_val(expr[2])) else "n"
1441 _internal_error("Internal error while evaluating expression: "
1442 "unknown operation {0}.".format(expr[0]))
1444 def _eval_min(self, e1, e2):
1445 """Returns the minimum value of the two expressions. Equates None with
1447 e1_eval = self._eval_expr(e1)
1448 e2_eval = self._eval_expr(e2)
1449 return e1_eval if tri_less(e1_eval, e2_eval) else e2_eval
1451 def _eval_max(self, e1, e2):
1452 """Returns the maximum value of the two expressions. Equates None with
1454 e1_eval = self._eval_expr(e1)
1455 e2_eval = self._eval_expr(e2)
1456 return e1_eval if tri_greater(e1_eval, e2_eval) else e2_eval
1459 # Dependency tracking (for caching and invalidation)
1462 def _build_dep(self):
1463 """Populates the Symbol.dep sets, linking the symbol to the symbols
1464 that immediately depend on it in the sense that changing the value of
1465 the symbol might affect the values of those other symbols. This is used
1466 for caching/invalidation purposes. The calculated sets might be larger
1467 than necessary as we don't do any complicated analysis of the
1470 # Adds 'sym' as a directly dependent symbol to all symbols that appear
1471 # in the expression 'e'
1472 def add_expr_deps(e, sym):
1473 for s in _get_expr_syms(e):
1476 # The directly dependent symbols of a symbol are:
1477 # - Any symbols whose prompts, default values, rev_dep (select
1478 # condition), or ranges depend on the symbol
1479 # - Any symbols that belong to the same choice statement as the symbol
1480 # (these won't be included in 'dep' as that makes the dependency
1481 # graph unwieldy, but Symbol._get_dependent() will include them)
1482 # - Any symbols in a choice statement that depends on the symbol
1483 for sym in self.syms_iter():
1484 for _, e in sym.prompts:
1485 add_expr_deps(e, sym)
1487 for v, e in sym.def_exprs:
1488 add_expr_deps(v, sym)
1489 add_expr_deps(e, sym)
1491 add_expr_deps(sym.rev_dep, sym)
1493 for l, u, e in sym.ranges:
1494 add_expr_deps(l, sym)
1495 add_expr_deps(u, sym)
1496 add_expr_deps(e, sym)
1498 if sym.is_choice_sym:
1500 for _, e in choice.prompts:
1501 add_expr_deps(e, sym)
1502 for _, e in choice.def_exprs:
1503 add_expr_deps(e, sym)
1505 def _eq_to_sym(self, eq):
1506 """_expr_depends_on() helper. For (in)equalities of the form sym = y/m
1507 or sym != n, returns sym. For other (in)equalities, returns None."""
1508 relation, left, right = eq
1510 def transform_y_m_n(item):
1511 if item is self.y: return "y"
1512 if item is self.m: return "m"
1513 if item is self.n: return "n"
1516 left = transform_y_m_n(left)
1517 right = transform_y_m_n(right)
1519 # Make sure the symbol (if any) appears to the left
1520 if not isinstance(left, Symbol):
1521 left, right = right, left
1522 if not isinstance(left, Symbol):
1524 if (relation == EQUAL and (right == "y" or right == "m")) or \
1525 (relation == UNEQUAL and right == "n"):
1529 def _expr_depends_on(self, expr, sym):
1530 """Reimplementation of expr_depends_symbol() from mconf.c. Used to
1531 determine if a submenu should be implicitly created, which influences
1532 what items inside choice statements are considered choice items."""
1537 if isinstance(expr, str):
1539 if isinstance(expr, Symbol):
1542 if expr[0] in (EQUAL, UNEQUAL):
1543 return self._eq_to_sym(expr) is sym
1545 for and_expr in expr[1]:
1552 def _invalidate_all(self):
1553 for sym in self.syms_iter():
1557 # Printing and misc.
1560 def _expand_sym_refs(self, s):
1561 """Expands $-references to symbols in 's' to symbol values, or to the
1562 empty string for undefined symbols."""
1565 sym_ref_match = _sym_ref_re_search(s)
1566 if sym_ref_match is None:
1569 sym_name = sym_ref_match.group(0)[1:]
1570 sym = self.syms.get(sym_name)
1571 expansion = "" if sym is None else sym.get_value()
1573 s = s[:sym_ref_match.start()] + \
1575 s[sym_ref_match.end():]
1577 def _expr_val_str(self, expr, no_value_str="(none)",
1578 get_val_instead_of_eval=False):
1579 """Printing helper. Returns a string with 'expr' and its value.
1581 no_value_str: String to return when 'expr' is missing (None).
1583 get_val_instead_of_eval: Assume 'expr' is a symbol or string (constant
1584 symbol) and get its value directly instead of evaluating it to a
1590 if get_val_instead_of_eval:
1591 if isinstance(expr, str):
1592 return _expr_to_str(expr)
1593 val = expr.get_value()
1595 val = self._eval_expr(expr)
1597 return "{0} (value: {1})".format(_expr_to_str(expr), _expr_to_str(val))
1599 def _get_sym_or_choice_str(self, sc):
1600 """Symbols and choices have many properties in common, so we factor out
1601 common __str__() stuff here. "sc" is short for "symbol or choice"."""
1603 # As we deal a lot with string representations here, use some
1604 # convenient shorthand:
1608 # Common symbol/choice properties
1611 user_val_str = "(no user value)" if sc.user_val is None else \
1614 # Build prompts string
1616 prompts_str = " (no prompts)"
1618 prompts_str_rows = []
1619 for prompt, cond_expr in sc.orig_prompts:
1620 prompts_str_rows.append(
1621 ' "{0}"'.format(prompt) if cond_expr is None else
1622 ' "{0}" if {1}'.format(prompt,
1623 self._expr_val_str(cond_expr)))
1624 prompts_str = "\n".join(prompts_str_rows)
1626 # Build locations string
1627 locations_str = "(no locations)" if not sc.def_locations else \
1628 " ".join(["{0}:{1}".format(filename, linenr) for
1629 filename, linenr in sc.def_locations])
1631 # Build additional-dependencies-from-menus-and-ifs string
1632 additional_deps_str = " " + \
1633 self._expr_val_str(sc.deps_from_containing,
1634 "(no additional dependencies)")
1637 # Symbol-specific stuff
1640 if isinstance(sc, Symbol):
1641 # Build ranges string
1642 if isinstance(sc, Symbol):
1644 ranges_str = " (no ranges)"
1646 ranges_str_rows = []
1647 for l, u, cond_expr in sc.ranges:
1648 ranges_str_rows.append(
1649 " [{0}, {1}]".format(s(l), s(u))
1650 if cond_expr is None else
1651 " [{0}, {1}] if {2}"
1652 .format(s(l), s(u), self._expr_val_str(cond_expr)))
1653 ranges_str = "\n".join(ranges_str_rows)
1655 # Build default values string
1656 if not sc.def_exprs:
1657 defaults_str = " (no default values)"
1659 defaults_str_rows = []
1660 for val_expr, cond_expr in sc.orig_def_exprs:
1661 row_str = " " + self._expr_val_str(val_expr, "(none)",
1663 defaults_str_rows.append(row_str)
1664 defaults_str_rows.append(" Condition: " +
1665 self._expr_val_str(cond_expr))
1666 defaults_str = "\n".join(defaults_str_rows)
1668 # Build selects string
1669 if not sc.orig_selects:
1670 selects_str = " (no selects)"
1672 selects_str_rows = []
1673 for target, cond_expr in sc.orig_selects:
1674 selects_str_rows.append(
1675 " {0}".format(target.name) if cond_expr is None else
1676 " {0} if {1}".format(target.name,
1677 self._expr_val_str(cond_expr)))
1678 selects_str = "\n".join(selects_str_rows)
1680 res = _lines("Symbol " +
1681 ("(no name)" if sc.name is None else sc.name),
1682 "Type : " + TYPENAME[sc.type],
1683 "Value : " + s(sc.get_value()),
1684 "User value : " + user_val_str,
1685 "Visibility : " + s(_get_visibility(sc)),
1686 "Is choice item : " + BOOL_STR[sc.is_choice_sym],
1687 "Is defined : " + BOOL_STR[sc.is_defined_],
1688 "Is from env. : " + BOOL_STR[sc.is_from_env],
1689 "Is special : " + BOOL_STR[sc.is_special_] + "\n")
1691 res += _lines("Ranges:", ranges_str + "\n")
1692 res += _lines("Prompts:",
1698 "Reverse (select-related) dependencies:",
1699 " (no reverse dependencies)" if sc.rev_dep == "n"
1700 else " " + self._expr_val_str(sc.rev_dep),
1701 "Additional dependencies from enclosing menus "
1703 additional_deps_str,
1704 "Locations: " + locations_str)
1709 # Choice-specific stuff
1712 # Build selected symbol string
1713 sel = sc.get_selection()
1714 sel_str = "(no selection)" if sel is None else sel.name
1716 # Build default values string
1717 if not sc.def_exprs:
1718 defaults_str = " (no default values)"
1720 defaults_str_rows = []
1721 for sym, cond_expr in sc.orig_def_exprs:
1722 defaults_str_rows.append(
1723 " {0}".format(sym.name) if cond_expr is None else
1724 " {0} if {1}".format(sym.name,
1725 self._expr_val_str(cond_expr)))
1726 defaults_str = "\n".join(defaults_str_rows)
1728 # Build contained symbols string
1729 names = [sym.name for sym in sc.actual_symbols]
1730 syms_string = " ".join(names) if names else "(empty)"
1732 return _lines("Choice",
1733 "Name (for named choices): " +
1734 ("(no name)" if sc.name is None else sc.name),
1735 "Type : " + TYPENAME[sc.type],
1736 "Selected symbol : " + sel_str,
1737 "User value : " + user_val_str,
1738 "Mode : " + s(sc.get_mode()),
1739 "Visibility : " + s(_get_visibility(sc)),
1740 "Optional : " + BOOL_STR[sc.optional],
1747 "Additional dependencies from enclosing menus and "
1749 additional_deps_str,
1750 "Locations: " + locations_str)
1752 def _warn(self, msg, filename=None, linenr=None):
1753 """For printing warnings to stderr."""
1754 if self.print_warnings:
1755 _stderr_msg("warning: " + msg, filename, linenr)
1759 """Base class for symbols and other Kconfig constructs. Subclasses are
1760 Symbol, Choice, Menu, and Comment."""
1762 def is_symbol(self):
1763 """Returns True if the item is a symbol. Short for
1764 isinstance(item, kconfiglib.Symbol)."""
1765 return isinstance(self, Symbol)
1767 def is_choice(self):
1768 """Returns True if the item is a choice. Short for
1769 isinstance(item, kconfiglib.Choice)."""
1770 return isinstance(self, Choice)
1773 """Returns True if the item is a menu. Short for
1774 isinstance(item, kconfiglib.Menu)."""
1775 return isinstance(self, Menu)
1777 def is_comment(self):
1778 """Returns True if the item is a comment. Short for
1779 isinstance(item, kconfiglib.Comment)."""
1780 return isinstance(self, Comment)
1784 """Represents a configuration symbol - e.g. FOO for
1793 def get_config(self):
1794 """Returns the Config instance this symbol is from."""
1798 """Returns the name of the symbol."""
1802 """Returns the type of the symbol: one of UNKNOWN, BOOL, TRISTATE,
1803 STRING, HEX, or INT. These are defined at the top level of the module,
1804 so you'd do something like
1806 if sym.get_type() == kconfiglib.STRING:
1810 def get_prompts(self):
1811 """Returns a list of prompts defined for the symbol, in the order they
1812 appear in the configuration files. Returns the empty list for symbols
1815 This list will have a single entry for the vast majority of symbols
1816 having prompts, but having multiple prompts for a single symbol is
1817 possible through having multiple 'config' entries for it."""
1818 return [prompt for prompt, _ in self.orig_prompts]
1821 """Returns the help text of the symbol, or None if the symbol has no
1825 def get_parent(self):
1826 """Returns the menu or choice statement that contains the symbol, or
1827 None if the symbol is at the top level. Note that if statements are
1828 treated as syntactic and do not have an explicit class
1832 def get_def_locations(self):
1833 """Returns a list of (filename, linenr) tuples, where filename (string)
1834 and linenr (int) represent a location where the symbol is defined. For
1835 the vast majority of symbols this list will only contain one element.
1836 For the following Kconfig, FOO would get two entries: the lines marked
1845 return self.def_locations
1847 def get_ref_locations(self):
1848 """Returns a list of (filename, linenr) tuples, where filename (string)
1849 and linenr (int) represent a location where the symbol is referenced in
1850 the configuration. For example, the lines marked by * would be included
1855 default BAR || FOO *
1867 config FOO (definition not included)
1870 return self.ref_locations
1872 def get_value(self):
1873 """Calculate and return the value of the symbol. See also
1874 Symbol.set_user_value()."""
1876 if self.cached_val is not None:
1877 return self.cached_val
1879 # As a quirk of Kconfig, undefined symbols get their name as their
1880 # value. This is why things like "FOO = bar" work for seeing if FOO has
1882 if self.type == UNKNOWN:
1883 self.cached_val = self.name
1886 new_val = DEFAULT_VALUE[self.type]
1887 vis = _get_visibility(self)
1889 # This is easiest to calculate together with the value
1890 self.write_to_conf = False
1892 if self.type == BOOL or self.type == TRISTATE:
1893 # The visibility and mode (modules-only or single-selection) of
1894 # choice items will be taken into account in _get_visibility()
1895 if self.is_choice_sym:
1897 choice = self.parent
1898 mode = choice.get_mode()
1900 self.write_to_conf = (mode != "n")
1903 new_val = "y" if choice.get_selection() is self \
1906 if self.user_val == "m" or self.user_val == "y":
1910 # If the symbol is visible and has a user value, use that.
1911 # Otherwise, look at defaults.
1915 self.write_to_conf = True
1916 if self.user_val is not None:
1917 new_val = self.config._eval_min(self.user_val, vis)
1918 use_defaults = False
1921 for val_expr, cond_expr in self.def_exprs:
1922 cond_eval = self.config._eval_expr(cond_expr)
1923 if cond_eval != "n":
1924 self.write_to_conf = True
1925 new_val = self.config._eval_min(val_expr,
1929 # Reverse (select-related) dependencies take precedence
1930 rev_dep_val = self.config._eval_expr(self.rev_dep)
1931 if rev_dep_val != "n":
1932 self.write_to_conf = True
1933 new_val = self.config._eval_max(new_val, rev_dep_val)
1935 # Promote "m" to "y" for booleans
1936 if new_val == "m" and self.type == BOOL:
1939 elif self.type == INT or self.type == HEX:
1940 has_active_range = False
1945 base = 16 if self.type == HEX else 10
1947 for l, h, cond_expr in self.ranges:
1948 if self.config._eval_expr(cond_expr) != "n":
1949 has_active_range = True
1951 low_str = _str_val(l)
1952 high_str = _str_val(h)
1953 low = int(low_str, base) if \
1954 _is_base_n(low_str, base) else 0
1955 high = int(high_str, base) if \
1956 _is_base_n(high_str, base) else 0
1961 self.write_to_conf = True
1963 if self.user_val is not None and \
1964 _is_base_n(self.user_val, base) and \
1965 (not has_active_range or
1966 low <= int(self.user_val, base) <= high):
1968 # If the user value is OK, it is stored in exactly the same
1969 # form as specified in the assignment (with or without
1972 use_defaults = False
1973 new_val = self.user_val
1976 for val_expr, cond_expr in self.def_exprs:
1977 if self.config._eval_expr(cond_expr) != "n":
1978 self.write_to_conf = True
1980 # If the default value is OK, it is stored in exactly
1981 # the same form as specified. Otherwise, it is clamped
1982 # to the range, and the output has "0x" as appropriate
1985 new_val = _str_val(val_expr)
1987 if _is_base_n(new_val, base):
1988 new_val_num = int(new_val, base)
1989 if has_active_range:
1992 if new_val_num < low:
1994 elif new_val_num > high:
1997 if clamped_val is not None:
1998 new_val = (hex(clamped_val) if \
1999 self.type == HEX else str(clamped_val))
2002 else: # For the for loop
2003 # If no user value or default kicks in but the hex/int has
2004 # an active range, then the low end of the range is used,
2005 # provided it's > 0, with "0x" prepended as appropriate.
2006 if has_active_range and low > 0:
2007 new_val = (hex(low) if self.type == HEX else str(low))
2009 elif self.type == STRING:
2013 self.write_to_conf = True
2014 if self.user_val is not None:
2015 new_val = self.user_val
2016 use_defaults = False
2019 for val_expr, cond_expr in self.def_exprs:
2020 if self.config._eval_expr(cond_expr) != "n":
2021 self.write_to_conf = True
2022 new_val = _str_val(val_expr)
2025 self.cached_val = new_val
2028 def get_user_value(self):
2029 """Returns the value assigned to the symbol in a .config or via
2030 Symbol.set_user_value() (provided the value was valid for the type of
2031 the symbol). Returns None in case of no user value."""
2032 return self.user_val
2034 def get_upper_bound(self):
2035 """For string/hex/int symbols and for bool and tristate symbols that
2036 cannot be modified (see is_modifiable()), returns None.
2038 Otherwise, returns the highest value the symbol can be set to with
2039 Symbol.set_user_value() (that will not be truncated): one of "m" or
2040 "y", arranged from lowest to highest. This corresponds to the highest
2041 value the symbol could be given in e.g. the 'make menuconfig'
2044 See also the tri_less*() and tri_greater*() functions, which could come
2046 if self.type != BOOL and self.type != TRISTATE:
2048 rev_dep = self.config._eval_expr(self.rev_dep)
2049 # A bool selected to "m" gets promoted to "y", pinning it
2050 if rev_dep == "m" and self.type == BOOL:
2052 vis = _get_visibility(self)
2053 if TRI_TO_INT[vis] > TRI_TO_INT[rev_dep]:
2057 def get_lower_bound(self):
2058 """For string/hex/int symbols and for bool and tristate symbols that
2059 cannot be modified (see is_modifiable()), returns None.
2061 Otherwise, returns the lowest value the symbol can be set to with
2062 Symbol.set_user_value() (that will not be truncated): one of "n" or
2063 "m", arranged from lowest to highest. This corresponds to the lowest
2064 value the symbol could be given in e.g. the 'make menuconfig'
2067 See also the tri_less*() and tri_greater*() functions, which could come
2069 if self.type != BOOL and self.type != TRISTATE:
2071 rev_dep = self.config._eval_expr(self.rev_dep)
2072 # A bool selected to "m" gets promoted to "y", pinning it
2073 if rev_dep == "m" and self.type == BOOL:
2075 if TRI_TO_INT[_get_visibility(self)] > TRI_TO_INT[rev_dep]:
2079 def get_assignable_values(self):
2080 """For string/hex/int symbols and for bool and tristate symbols that
2081 cannot be modified (see is_modifiable()), returns the empty list.
2083 Otherwise, returns a list containing the user values that can be
2084 assigned to the symbol (that won't be truncated). Usage example:
2086 if "m" in sym.get_assignable_values():
2087 sym.set_user_value("m")
2089 This is basically a more convenient interface to
2090 get_lower/upper_bound() when wanting to test if a particular tristate
2091 value can be assigned."""
2092 if self.type != BOOL and self.type != TRISTATE:
2094 rev_dep = self.config._eval_expr(self.rev_dep)
2095 # A bool selected to "m" gets promoted to "y", pinning it
2096 if rev_dep == "m" and self.type == BOOL:
2098 res = ["n", "m", "y"][TRI_TO_INT[rev_dep] :
2099 TRI_TO_INT[_get_visibility(self)] + 1]
2100 return res if len(res) > 1 else []
2102 def get_visibility(self):
2103 """Returns the visibility of the symbol: one of "n", "m" or "y". For
2104 bool and tristate symbols, this is an upper bound on the value users
2105 can set for the symbol. For other types of symbols, a visibility of "n"
2106 means the user value will be ignored. A visibility of "n" corresponds
2107 to not being visible in the 'make *config' interfaces.
2109 Example (assuming we're running with modules enabled -- i.e., MODULES
2112 # Assume this has been assigned 'n'
2116 # Assume this has been assigned 'm'
2120 # Has visibility 'n'
2125 # Has visibility 'm'
2130 # Has visibility 'y'
2134 # Has no prompt, and hence visibility 'n'
2138 Having visibility be tri-valued ensures that e.g. a symbol cannot be
2139 set to "y" by the user if it depends on a symbol with value "m", which
2142 You should probably look at get_lower/upper_bound(),
2143 get_assignable_values() and is_modifiable() before using this."""
2144 return _get_visibility(self)
2146 def get_referenced_symbols(self, refs_from_enclosing=False):
2147 """Returns the set() of all symbols referenced by this symbol. For
2148 example, the symbol defined by
2152 prompt "foo" if A && B
2157 references the symbols A through G.
2159 refs_from_enclosing (default: False): If True, the symbols referenced
2160 by enclosing menus and ifs will be included in the result."""
2161 return self.all_referenced_syms if refs_from_enclosing else \
2162 self.referenced_syms
2164 def get_selected_symbols(self):
2165 """Returns the set() of all symbols X for which this symbol has a
2166 'select X' or 'select X if Y' (regardless of whether Y is satisfied or
2167 not). This is a subset of the symbols returned by
2168 get_referenced_symbols()."""
2169 return self.selected_syms
2171 def set_user_value(self, v):
2172 """Sets the user value of the symbol.
2174 Equal in effect to assigning the value to the symbol within a .config
2175 file. Use get_lower/upper_bound() or get_assignable_values() to find
2176 the range of currently assignable values for bool and tristate symbols;
2177 setting values outside this range will cause the user value to differ
2178 from the result of Symbol.get_value() (be truncated). Values that are
2179 invalid for the type (such as a_bool.set_user_value("foo")) are
2180 ignored, and a warning is emitted if an attempt is made to assign such
2183 For any type of symbol, is_modifiable() can be used to check if a user
2184 value will currently have any effect on the symbol, as determined by
2185 its visibility and range of assignable values. Any value that is valid
2186 for the type (bool, tristate, etc.) will end up being reflected in
2187 get_user_value() though, and might have an effect later if conditions
2188 change. To get rid of the user value, use unset_user_value().
2190 Any symbols dependent on the symbol are (recursively) invalidated, so
2191 things will just work with regards to dependencies.
2193 v: The user value to give to the symbol."""
2194 self._set_user_value_no_invalidate(v, False)
2196 # There might be something more efficient you could do here, but play
2198 if self.name == "MODULES":
2199 self.config._invalidate_all()
2203 self._invalidate_dependent()
2205 def unset_user_value(self):
2206 """Resets the user value of the symbol, as if the symbol had never
2207 gotten a user value via Config.load_config() or
2208 Symbol.set_user_value()."""
2209 self._unset_user_value_no_recursive_invalidate()
2210 self._invalidate_dependent()
2212 def is_modifiable(self):
2213 """Returns True if the value of the symbol could be modified by calling
2214 Symbol.set_user_value().
2216 For bools and tristates, this corresponds to the symbol being visible
2217 in the 'make menuconfig' interface and not already being pinned to a
2218 specific value (e.g. because it is selected by another symbol).
2220 For strings and numbers, this corresponds to just being visible. (See
2221 Symbol.get_visibility().)"""
2222 if self.is_special_:
2224 if self.type == BOOL or self.type == TRISTATE:
2225 rev_dep = self.config._eval_expr(self.rev_dep)
2226 # A bool selected to "m" gets promoted to "y", pinning it
2227 if rev_dep == "m" and self.type == BOOL:
2229 return TRI_TO_INT[_get_visibility(self)] > TRI_TO_INT[rev_dep]
2230 return _get_visibility(self) != "n"
2232 def is_defined(self):
2233 """Returns False if the symbol is referred to in the Kconfig but never
2234 actually defined."""
2235 return self.is_defined_
2237 def is_special(self):
2238 """Returns True if the symbol is one of the special symbols n, m, y, or
2239 UNAME_RELEASE, or gets its value from the environment."""
2240 return self.is_special_
2242 def is_from_environment(self):
2243 """Returns True if the symbol gets its value from the environment."""
2244 return self.is_from_env
2246 def has_ranges(self):
2247 """Returns True if the symbol is of type INT or HEX and has ranges that
2248 limit what values it can take on."""
2249 return bool(self.ranges)
2251 def is_choice_symbol(self):
2252 """Returns True if the symbol is in a choice statement and is an actual
2253 choice symbol (see Choice.get_symbols())."""
2254 return self.is_choice_sym
2256 def is_choice_selection(self):
2257 """Returns True if the symbol is contained in a choice statement and is
2258 the selected item. Equivalent to
2260 sym.is_choice_symbol() and sym.get_parent().get_selection() is sym"""
2261 return self.is_choice_sym and self.parent.get_selection() is self
2263 def is_allnoconfig_y(self):
2264 """Returns True if the symbol has the 'allnoconfig_y' option set."""
2265 return self.allnoconfig_y
2268 """Returns a string containing various information about the symbol."""
2269 return self.config._get_sym_or_choice_str(self)
2276 """Symbol constructor -- not intended to be called directly by
2277 Kconfiglib clients."""
2282 self.def_exprs = [] # 'default' properties
2283 self.ranges = [] # 'range' properties (for int and hex)
2284 self.help = None # Help text
2285 self.rev_dep = "n" # Reverse (select-related) dependencies
2289 self.user_val = None # Value set by user
2291 # The prompt, default value and select conditions without any
2292 # dependencies from menus and ifs propagated to them
2293 self.orig_prompts = []
2294 self.orig_def_exprs = []
2295 self.orig_selects = []
2297 # Dependencies inherited from containing menus and ifs
2298 self.deps_from_containing = None
2299 # The set of symbols referenced by this symbol (see
2300 # get_referenced_symbols())
2301 self.referenced_syms = set()
2302 # The set of symbols selected by this symbol (see
2303 # get_selected_symbols())
2304 self.selected_syms = set()
2305 # Like 'referenced_syms', but includes symbols from
2306 # dependencies inherited from enclosing menus and ifs
2307 self.all_referenced_syms = set()
2309 # This records only dependencies specified with 'depends on'. Needed
2310 # when determining actual choice items (hrrrr...). See also
2311 # Choice._determine_actual_symbols().
2312 self.menu_dep = None
2314 # See Symbol.get_ref/def_locations().
2315 self.def_locations = []
2316 self.ref_locations = []
2318 # Populated in Config._build_dep() after parsing. Links the symbol to
2319 # the symbols that immediately depend on it (in a caching/invalidation
2320 # sense). The total set of dependent symbols for the symbol (the
2321 # transitive closure) is calculated on an as-needed basis in
2327 # Caches the calculated value
2328 self.cached_val = None
2329 # Caches the visibility, which acts as an upper bound on the value
2330 self.cached_visibility = None
2331 # Caches the total list of dependent symbols. Calculated in
2333 self.cached_deps = None
2337 # Does the symbol have an entry in the Kconfig file? The trailing
2338 # underscore avoids a collision with is_defined().
2339 self.is_defined_ = False
2340 # Should the symbol get an entry in .config?
2341 self.write_to_conf = False
2342 # Set to true when _make_conf() is called on a symbol, so that symbols
2343 # defined in multiple locations only get one .config entry. We need to
2344 # reset it prior to writing out a new .config.
2345 self.already_written = False
2346 # This is set to True for "actual" choice symbols; see
2347 # Choice._determine_actual_symbols().
2348 self.is_choice_sym = False
2349 # Does the symbol get its value in some special way, e.g. from the
2350 # environment or by being one of the special symbols n, m, and y? If
2351 # so, the value is stored in self.cached_val, which is never
2352 # invalidated. The trailing underscore avoids a collision with
2354 self.is_special_ = False
2355 # Does the symbol get its value from the environment?
2356 self.is_from_env = False
2357 # Does the symbol have the 'allnoconfig_y' option set?
2358 self.allnoconfig_y = False
2360 def _invalidate(self):
2361 if self.is_special_:
2364 if self.is_choice_sym:
2365 self.parent._invalidate()
2367 self.cached_val = None
2368 self.cached_visibility = None
2370 def _invalidate_dependent(self):
2371 for sym in self._get_dependent():
2374 def _set_user_value_no_invalidate(self, v, suppress_load_warnings):
2375 """Like set_user_value(), but does not invalidate any symbols.
2377 suppress_load_warnings: some warnings are annoying when loading a
2378 .config that can be helpful when manually invoking set_user_value().
2379 This flag is set to True to suppress such warnings.
2381 Perhaps this could be made optional for load_config() instead."""
2383 if self.is_special_:
2384 if self.is_from_env:
2385 self.config._warn('attempt to assign the value "{0}" to the '
2386 'symbol {1}, which gets its value from the '
2387 'environment. Assignment ignored.'
2388 .format(v, self.name))
2390 self.config._warn('attempt to assign the value "{0}" to the '
2391 'special symbol {1}. Assignment ignored.'
2392 .format(v, self.name))
2395 if not self.is_defined_:
2396 filename, linenr = self.ref_locations[0]
2397 if self.config.print_undef_assign:
2398 _stderr_msg('note: attempt to assign the value "{0}" to {1}, '
2399 "which is referenced at {2}:{3} but never "
2400 "defined. Assignment ignored."
2401 .format(v, self.name, filename, linenr))
2404 # Check if the value is valid for our type
2405 if not ((self.type == BOOL and (v == "y" or v == "n") ) or
2406 (self.type == TRISTATE and (v == "y" or v == "m" or
2408 (self.type == STRING ) or
2409 (self.type == INT and _is_base_n(v, 10) ) or
2410 (self.type == HEX and _is_base_n(v, 16) )):
2411 self.config._warn('the value "{0}" is invalid for {1}, which has '
2412 "type {2}. Assignment ignored."
2413 .format(v, self.name, TYPENAME[self.type]))
2416 if not self.prompts and not suppress_load_warnings:
2417 self.config._warn('assigning "{0}" to the symbol {1} which '
2418 'lacks prompts and thus has visibility "n". '
2419 'The assignment will have no effect.'
2420 .format(v, self.name))
2424 if self.is_choice_sym and (self.type == BOOL or self.type == TRISTATE):
2425 choice = self.parent
2427 choice.user_val = self
2428 choice.user_mode = "y"
2430 choice.user_val = None
2431 choice.user_mode = "m"
2433 def _unset_user_value_no_recursive_invalidate(self):
2435 self.user_val = None
2437 if self.is_choice_sym:
2438 self.parent._unset_user_value()
2440 def _make_conf(self, append_fn):
2441 if self.already_written:
2444 self.already_written = True
2446 # Note: write_to_conf is determined in get_value()
2447 val = self.get_value()
2448 if not self.write_to_conf:
2451 if self.type == BOOL or self.type == TRISTATE:
2452 append_fn("{0}{1}={2}".format(self.config.config_prefix, self.name, val)
2453 if val == "y" or val == "m" else
2454 "# {0}{1} is not set".format(self.config.config_prefix, self.name))
2456 elif self.type == INT or self.type == HEX:
2457 append_fn("{0}{1}={2}".format(self.config.config_prefix, self.name, val))
2459 elif self.type == STRING:
2461 append_fn('{0}{1}="{2}"'
2462 .format(self.config.config_prefix, self.name,
2463 val.replace("\\", "\\\\").replace('"', '\\"')))
2466 _internal_error("Internal error while creating .config: unknown "
2467 'type "{0}".'.format(self.type))
2469 def _get_dependent(self):
2470 """Returns the set of symbols that should be invalidated if the value
2471 of the symbol changes, because they might be affected by the change.
2472 Note that this is an internal API -- it's probably of limited
2473 usefulness to clients."""
2474 if self.cached_deps is not None:
2475 return self.cached_deps
2479 res |= s._get_dependent()
2481 if self.is_choice_sym:
2482 # Choice symbols also depend (recursively) on their siblings. The
2483 # siblings are not included in 'dep' to avoid dependency loops.
2484 for sibling in self.parent.actual_symbols:
2485 if sibling is not self:
2488 for s in sibling.dep:
2489 res |= s._get_dependent()
2491 self.cached_deps = res
2494 def _has_auto_menu_dep_on(self, on):
2495 """See Choice._determine_actual_symbols()."""
2496 if not isinstance(self.parent, Choice):
2497 _internal_error("Attempt to determine auto menu dependency for "
2498 "symbol ouside of choice.")
2500 if not self.prompts:
2501 # If we have no prompt, use the menu dependencies instead (what was
2502 # specified with 'depends on')
2503 return self.menu_dep is not None and \
2504 self.config._expr_depends_on(self.menu_dep, on)
2506 for _, cond_expr in self.prompts:
2507 if self.config._expr_depends_on(cond_expr, on):
2514 """Represents a menu statement."""
2520 def get_config(self):
2521 """Return the Config instance this menu is from."""
2524 def get_title(self):
2525 """Returns the title text of the menu."""
2528 def get_parent(self):
2529 """Returns the menu or choice statement that contains the menu, or
2530 None if the menu is at the top level. Note that if statements are
2531 treated as syntactic sugar and do not have an explicit class
2535 def get_location(self):
2536 """Returns the location of the menu as a (filename, linenr) tuple,
2537 where filename is a string and linenr an int."""
2538 return (self.filename, self.linenr)
2540 def get_items(self, recursive=False):
2541 """Returns a list containing the items (symbols, menus, choice
2542 statements and comments) in in the menu, in the same order that the
2543 items appear within the menu.
2545 recursive (default: False): True if items contained in items within the
2546 menu should be included recursively (preorder)."""
2552 for item in self.block:
2554 if isinstance(item, Menu):
2555 res.extend(item.get_items(True))
2556 elif isinstance(item, Choice):
2557 res.extend(item.get_items())
2560 def get_symbols(self, recursive=False):
2561 """Returns a list containing the symbols in the menu, in the same order
2562 that they appear within the menu.
2564 recursive (default: False): True if symbols contained in items within
2565 the menu should be included recursively."""
2567 return [item for item in self.get_items(recursive) if
2568 isinstance(item, Symbol)]
2570 def get_visibility(self):
2571 """Returns the visibility of the menu. This also affects the visibility
2572 of subitems. See also Symbol.get_visibility()."""
2573 return self.config._eval_expr(self.dep_expr)
2575 def get_visible_if_visibility(self):
2576 """Returns the visibility the menu gets from its 'visible if'
2577 condition. "y" if the menu has no 'visible if' condition."""
2578 return self.config._eval_expr(self.visible_if_expr)
2580 def get_referenced_symbols(self, refs_from_enclosing=False):
2581 """See Symbol.get_referenced_symbols()."""
2582 return self.all_referenced_syms if refs_from_enclosing else \
2583 self.referenced_syms
2586 """Returns a string containing various information about the menu."""
2587 depends_on_str = self.config._expr_val_str(self.orig_deps,
2588 "(no dependencies)")
2589 visible_if_str = self.config._expr_val_str(self.visible_if_expr,
2590 "(no dependencies)")
2592 additional_deps_str = " " + \
2593 self.config._expr_val_str(self.deps_from_containing,
2594 "(no additional dependencies)")
2596 return _lines("Menu",
2597 "Title : " + self.title,
2598 "'depends on' dependencies : " + depends_on_str,
2599 "'visible if' dependencies : " + visible_if_str,
2600 "Additional dependencies from enclosing menus and "
2602 additional_deps_str,
2603 "Location: {0}:{1}".format(self.filename, self.linenr))
2610 """Menu constructor -- not intended to be called directly by
2611 Kconfiglib clients."""
2614 self.dep_expr = None
2615 self.visible_if_expr = None
2620 # Dependency expression without dependencies from enclosing menus and
2622 self.orig_deps = None
2624 # Dependencies inherited from containing menus and ifs
2625 self.deps_from_containing = None
2626 # The set of symbols referenced by this menu (see
2627 # get_referenced_symbols())
2628 self.referenced_syms = set()
2629 # Like 'referenced_syms', but includes symbols from
2630 # dependencies inherited from enclosing menus and ifs
2631 self.all_referenced_syms = None
2633 self.filename = None
2636 def _make_conf(self, append_fn):
2637 if self.config._eval_expr(self.dep_expr) != "n" and \
2638 self.config._eval_expr(self.visible_if_expr) != "n":
2639 append_fn("\n#\n# {0}\n#".format(self.title))
2640 _make_block_conf(self.block, append_fn)
2644 """Represents a choice statement. A choice can be in one of three modes:
2646 "n" - The choice is not visible and no symbols can be selected.
2648 "m" - Any number of symbols can be set to "m". The rest will be "n". This
2649 is safe since potentially conflicting options don't actually get
2650 compiled into the kernel simultaneously with "m".
2652 "y" - One symbol will be "y" while the rest are "n".
2654 Only tristate choices can be in "m" mode, and the visibility of the choice
2655 is an upper bound on the mode, so that e.g. a choice that depends on a
2656 symbol with value "m" will be in "m" mode.
2658 The mode changes automatically when a value is assigned to a symbol within
2661 See Symbol.get_visibility() too."""
2667 def get_config(self):
2668 """Returns the Config instance this choice is from."""
2672 """For named choices, returns the name. Returns None for unnamed
2673 choices. No named choices appear anywhere in the kernel Kconfig files
2674 as of Linux 3.7.0-rc8."""
2678 """Returns the type of the choice. See Symbol.get_type()."""
2681 def get_prompts(self):
2682 """Returns a list of prompts defined for the choice, in the order they
2683 appear in the configuration files. Returns the empty list for choices
2686 This list will have a single entry for the vast majority of choices
2687 having prompts, but having multiple prompts for a single choice is
2688 possible through having multiple 'choice' entries for it (though I'm
2689 not sure if that ever happens in practice)."""
2690 return [prompt for prompt, _ in self.orig_prompts]
2693 """Returns the help text of the choice, or None if the choice has no
2697 def get_parent(self):
2698 """Returns the menu or choice statement that contains the choice, or
2699 None if the choice is at the top level. Note that if statements are
2700 treated as syntactic sugar and do not have an explicit class
2704 def get_def_locations(self):
2705 """Returns a list of (filename, linenr) tuples, where filename (string)
2706 and linenr (int) represent a location where the choice is defined. For
2707 the vast majority of choices (all of them as of Linux 3.7.0-rc8) this
2708 list will only contain one element, but its possible for named choices
2709 to be defined in multiple locations."""
2710 return self.def_locations
2712 def get_selection(self):
2713 """Returns the symbol selected (either by the user or through
2714 defaults), or None if either no symbol is selected or the mode is not
2716 if self.cached_selection is not None:
2717 if self.cached_selection == NO_SELECTION:
2719 return self.cached_selection
2721 if self.get_mode() != "y":
2722 return self._cache_ret(None)
2724 # User choice available?
2725 if self.user_val is not None and _get_visibility(self.user_val) == "y":
2726 return self._cache_ret(self.user_val)
2729 return self._cache_ret(None)
2731 return self._cache_ret(self.get_selection_from_defaults())
2733 def get_selection_from_defaults(self):
2734 """Like Choice.get_selection(), but acts as if no symbol has been
2735 selected by the user and no 'optional' flag is in effect."""
2737 if not self.actual_symbols:
2740 for symbol, cond_expr in self.def_exprs:
2741 if self.config._eval_expr(cond_expr) != "n":
2742 chosen_symbol = symbol
2745 chosen_symbol = self.actual_symbols[0]
2747 # Is the chosen symbol visible?
2748 if _get_visibility(chosen_symbol) != "n":
2749 return chosen_symbol
2750 # Otherwise, pick the first visible symbol
2751 for sym in self.actual_symbols:
2752 if _get_visibility(sym) != "n":
2756 def get_user_selection(self):
2757 """If the choice is in "y" mode and has a user-selected symbol, returns
2758 that symbol. Otherwise, returns None."""
2759 return self.user_val
2761 def get_items(self):
2762 """Gets all items contained in the choice in the same order as within
2763 the configuration ("items" instead of "symbols" since choices and
2764 comments might appear within choices. This only happens in one place as
2765 of Linux 3.7.0-rc8, in drivers/usb/gadget/Kconfig)."""
2768 def get_symbols(self):
2769 """Returns a list containing the choice's symbols.
2771 A quirk (perhaps a bug) of Kconfig is that you can put items within a
2772 choice that will not be considered members of the choice insofar as
2773 selection is concerned. This happens for example if one symbol within a
2774 choice 'depends on' the symbol preceding it, or if you put non-symbol
2775 items within choices.
2777 As of Linux 3.7.0-rc8, this seems to be used intentionally in one
2778 place: drivers/usb/gadget/Kconfig.
2780 This function returns the "proper" symbols of the choice in the order
2781 they appear in the choice, excluding such items. If you want all items
2782 in the choice, use get_items()."""
2783 return self.actual_symbols
2785 def get_referenced_symbols(self, refs_from_enclosing=False):
2786 """See Symbol.get_referenced_symbols()."""
2787 return self.all_referenced_syms if refs_from_enclosing else \
2788 self.referenced_syms
2790 def get_visibility(self):
2791 """Returns the visibility of the choice statement: one of "n", "m" or
2792 "y". This acts as an upper limit on the mode of the choice (though bool
2793 choices can only have the mode "y"). See the class documentation for an
2794 explanation of modes."""
2795 return _get_visibility(self)
2798 """Returns the mode of the choice. See the class documentation for
2799 an explanation of modes."""
2800 minimum_mode = "n" if self.optional else "m"
2801 mode = self.user_mode if self.user_mode is not None else minimum_mode
2802 mode = self.config._eval_min(mode, _get_visibility(self))
2804 # Promote "m" to "y" for boolean choices
2805 if mode == "m" and self.type == BOOL:
2810 def is_optional(self):
2811 """Returns True if the choice has the 'optional' flag set (and so will
2812 default to "n" mode)."""
2813 return self.optional
2816 """Returns a string containing various information about the choice
2818 return self.config._get_sym_or_choice_str(self)
2825 """Choice constructor -- not intended to be called directly by
2826 Kconfiglib clients."""
2828 self.name = None # Yes, choices can be named
2831 self.def_exprs = [] # 'default' properties
2832 self.help = None # Help text
2833 self.block = None # List of contained items
2837 self.user_val = None
2838 self.user_mode = None
2840 # We need to filter out symbols that appear within the choice block but
2841 # are not considered choice items (see
2842 # Choice._determine_actual_symbols()) This list holds the "actual"
2844 self.actual_symbols = []
2846 # The prompts and default values without any dependencies from
2847 # enclosing menus and ifs propagated
2848 self.orig_prompts = []
2849 self.orig_def_exprs = []
2851 # Dependencies inherited from containing menus and ifs
2852 self.deps_from_containing = None
2853 # The set of symbols referenced by this choice (see
2854 # get_referenced_symbols())
2855 self.referenced_syms = set()
2856 # Like 'referenced_syms', but includes symbols from
2857 # dependencies inherited from enclosing menus and ifs
2858 self.all_referenced_syms = set()
2860 # See Choice.get_def_locations()
2861 self.def_locations = []
2864 self.cached_selection = None
2865 self.cached_visibility = None
2867 self.optional = False
2869 def _determine_actual_symbols(self):
2870 """If a symbol's visibility depends on the preceding symbol within a
2871 choice, it is no longer viewed as a choice item. (This is quite
2872 possibly a bug, but some things consciously use it... ugh. It stems
2873 from automatic submenu creation.) In addition, it's possible to have
2874 choices and comments within choices, and those shouldn't be considered
2875 choice items either. Only drivers/usb/gadget/Kconfig seems to depend on
2876 any of this. This method computes the "actual" items in the choice and
2877 sets the is_choice_sym flag on them (retrieved via is_choice_symbol()).
2879 Don't let this scare you: an earlier version simply checked for a
2880 sequence of symbols where all symbols after the first appeared in the
2881 'depends on' expression of the first, and that worked fine. The added
2882 complexity is to be future-proof in the event that
2883 drivers/usb/gadget/Kconfig turns even more sinister. It might very well
2884 be overkilling things (especially if that file is refactored ;)."""
2886 # Items might depend on each other in a tree structure, so we need a
2887 # stack to keep track of the current tentative parent
2890 for item in self.block:
2891 if not isinstance(item, Symbol):
2896 if item._has_auto_menu_dep_on(stack[-1]):
2897 # The item should not be viewed as a choice item, so don't
2898 # set item.is_choice_sym
2904 item.is_choice_sym = True
2905 self.actual_symbols.append(item)
2908 def _cache_ret(self, selection):
2909 # As None is used to indicate the lack of a cached value we can't use
2910 # that to cache the fact that the choice has no selection. Instead, we
2911 # use the symbolic constant NO_SELECTION.
2912 if selection is None:
2913 self.cached_selection = NO_SELECTION
2915 self.cached_selection = selection
2919 def _invalidate(self):
2920 self.cached_selection = None
2921 self.cached_visibility = None
2923 def _unset_user_value(self):
2925 self.user_val = None
2926 self.user_mode = None
2928 def _make_conf(self, append_fn):
2929 _make_block_conf(self.block, append_fn)
2931 class Comment(Item):
2933 """Represents a comment statement."""
2939 def get_config(self):
2940 """Returns the Config instance this comment is from."""
2944 """Returns the text of the comment."""
2947 def get_parent(self):
2948 """Returns the menu or choice statement that contains the comment, or
2949 None if the comment is at the top level. Note that if statements are
2950 treated as syntactic sugar and do not have an explicit class
2954 def get_location(self):
2955 """Returns the location of the comment as a (filename, linenr) tuple,
2956 where filename is a string and linenr an int."""
2957 return (self.filename, self.linenr)
2959 def get_visibility(self):
2960 """Returns the visibility of the comment. See also
2961 Symbol.get_visibility()."""
2962 return self.config._eval_expr(self.dep_expr)
2964 def get_referenced_symbols(self, refs_from_enclosing=False):
2965 """See Symbol.get_referenced_symbols()."""
2966 return self.all_referenced_syms if refs_from_enclosing else \
2967 self.referenced_syms
2970 """Returns a string containing various information about the
2972 dep_str = self.config._expr_val_str(self.orig_deps,
2973 "(no dependencies)")
2975 additional_deps_str = " " + \
2976 self.config._expr_val_str(self.deps_from_containing,
2977 "(no additional dependencies)")
2979 return _lines("Comment",
2980 "Text: " + str(self.text),
2981 "Dependencies: " + dep_str,
2982 "Additional dependencies from enclosing menus and "
2984 additional_deps_str,
2985 "Location: {0}:{1}".format(self.filename, self.linenr))
2992 """Comment constructor -- not intended to be called directly by
2993 Kconfiglib clients."""
2996 self.dep_expr = None
3000 # Dependency expression without dependencies from enclosing menus and
3002 self.orig_deps = None
3004 # Dependencies inherited from containing menus and ifs
3005 self.deps_from_containing = None
3006 # The set of symbols referenced by this comment (see
3007 # get_referenced_symbols())
3008 self.referenced_syms = set()
3009 # Like 'referenced_syms', but includes symbols from
3010 # dependencies inherited from enclosing menus and ifs
3011 self.all_referenced_syms = None
3013 self.filename = None
3016 def _make_conf(self, append_fn):
3017 if self.config._eval_expr(self.dep_expr) != "n":
3018 append_fn("\n#\n# {0}\n#".format(self.text))
3020 class Kconfig_Syntax_Error(Exception):
3021 """Exception raised for syntax errors."""
3024 class Internal_Error(Exception):
3025 """Exception raised for internal errors."""
3032 def tri_less(v1, v2):
3033 """Returns True if the tristate v1 is less than the tristate v2, where "n",
3034 "m" and "y" are ordered from lowest to highest."""
3035 return TRI_TO_INT[v1] < TRI_TO_INT[v2]
3037 def tri_less_eq(v1, v2):
3038 """Returns True if the tristate v1 is less than or equal to the tristate
3039 v2, where "n", "m" and "y" are ordered from lowest to highest."""
3040 return TRI_TO_INT[v1] <= TRI_TO_INT[v2]
3042 def tri_greater(v1, v2):
3043 """Returns True if the tristate v1 is greater than the tristate v2, where
3044 "n", "m" and "y" are ordered from lowest to highest."""
3045 return TRI_TO_INT[v1] > TRI_TO_INT[v2]
3047 def tri_greater_eq(v1, v2):
3048 """Returns True if the tristate v1 is greater than or equal to the tristate
3049 v2, where "n", "m" and "y" are ordered from lowest to highest."""
3050 return TRI_TO_INT[v1] >= TRI_TO_INT[v2]
3056 class _Feed(object):
3058 """Class for working with sequences in a stream-like fashion; handy for
3061 # This would be more helpful on the item classes, but would remove some
3063 __slots__ = ['items', 'length', 'i']
3065 def __init__(self, items):
3067 self.length = len(self.items)
3071 if self.i >= self.length:
3073 item = self.items[self.i]
3077 def peek_next(self):
3078 return None if self.i >= self.length else self.items[self.i]
3080 def check(self, token):
3081 """Check if the next token is 'token'. If so, remove it from the token
3082 feed and return True. Otherwise, leave it in and return False."""
3083 if self.i < self.length and self.items[self.i] == token:
3088 def unget_all(self):
3091 class _FileFeed(object):
3093 """Feeds lines from a file. Keeps track of the filename and current line
3094 number. Joins any line ending in \\ with the following line. We need to be
3095 careful to get the line number right in the presence of continuation
3098 __slots__ = ['filename', 'lines', 'length', 'linenr']
3100 def __init__(self, filename):
3101 self.filename = _clean_up_path(filename)
3102 with open(filename, "r") as f:
3103 # No interleaving of I/O and processing yet. Don't know if it would
3105 self.lines = f.readlines()
3106 self.length = len(self.lines)
3110 if self.linenr >= self.length:
3112 line = self.lines[self.linenr]
3114 while line.endswith("\\\n"):
3115 line = line[:-2] + self.lines[self.linenr]
3119 def peek_next(self):
3120 linenr = self.linenr
3121 if linenr >= self.length:
3123 line = self.lines[linenr]
3124 while line.endswith("\\\n"):
3126 line = line[:-2] + self.lines[linenr]
3131 while self.lines[self.linenr].endswith("\\\n"):
3134 def next_nonblank(self):
3135 """Removes lines up to and including the next non-blank (not all-space)
3136 line and returns it. Returns None if there are no more non-blank
3139 line = self.get_next()
3140 if line is None or not line.isspace():
3144 # Internal functions
3147 def _get_visibility(sc):
3148 """Symbols and Choices have a "visibility" that acts as an upper bound on
3149 the values a user can set for them, corresponding to the visibility in e.g.
3150 'make menuconfig'. This function calculates the visibility for the Symbol
3151 or Choice 'sc' -- the logic is nearly identical."""
3152 if sc.cached_visibility is None:
3154 for _, cond_expr in sc.prompts:
3155 vis = sc.config._eval_max(vis, cond_expr)
3157 if isinstance(sc, Symbol) and sc.is_choice_sym:
3158 vis = sc.config._eval_min(vis, _get_visibility(sc.parent))
3160 # Promote "m" to "y" if we're dealing with a non-tristate
3161 if vis == "m" and sc.type != TRISTATE:
3164 sc.cached_visibility = vis
3166 return sc.cached_visibility
3168 def _make_and(e1, e2):
3169 """Constructs an AND (&&) expression. Performs trivial simplification.
3170 Nones equate to 'y'.
3172 Note: returns None if e1 == e2 == None."""
3173 if e1 is None or e1 == "y":
3175 if e2 is None or e2 == "y":
3178 # Prefer to merge argument lists if possible to reduce the number of nodes
3180 if isinstance(e1, tuple) and e1[0] == AND:
3181 if isinstance(e2, tuple) and e2[0] == AND:
3182 return (AND, e1[1] + e2[1])
3183 return (AND, e1[1] + [e2])
3185 if isinstance(e2, tuple) and e2[0] == AND:
3186 return (AND, e2[1] + [e1])
3188 return (AND, [e1, e2])
3190 def _make_or(e1, e2):
3191 """Constructs an OR (||) expression. Performs trivial simplification and
3192 avoids Nones. Nones equate to 'y', which is usually what we want, but needs
3193 to be kept in mind."""
3195 # Perform trivial simplification and avoid None's (which
3196 # correspond to y's)
3197 if e1 is None or e2 is None or e1 == "y" or e2 == "y":
3202 # Prefer to merge argument lists if possible to reduce the number of nodes
3204 if isinstance(e1, tuple) and e1[0] == OR:
3205 if isinstance(e2, tuple) and e2[0] == OR:
3206 return (OR, e1[1] + e2[1])
3207 return (OR, e1[1] + [e2])
3209 if isinstance(e2, tuple) and e2[0] == OR:
3210 return (OR, e2[1] + [e1])
3212 return (OR, [e1, e2])
3214 def _get_expr_syms_rec(expr, res):
3215 """_get_expr_syms() helper. Recurses through expressions."""
3216 if isinstance(expr, Symbol):
3218 elif isinstance(expr, str):
3220 elif expr[0] == AND or expr[0] == OR:
3221 for term in expr[1]:
3222 _get_expr_syms_rec(term, res)
3223 elif expr[0] == NOT:
3224 _get_expr_syms_rec(expr[1], res)
3225 elif expr[0] == EQUAL or expr[0] == UNEQUAL:
3226 if isinstance(expr[1], Symbol):
3228 if isinstance(expr[2], Symbol):
3231 _internal_error("Internal error while fetching symbols from an "
3232 "expression with token stream {0}.".format(expr))
3234 def _get_expr_syms(expr):
3235 """Returns the set() of symbols appearing in expr."""
3237 if expr is not None:
3238 _get_expr_syms_rec(expr, res)
3242 """Returns the value of obj as a string. If obj is not a string (constant
3243 symbol), it must be a Symbol."""
3244 return obj if isinstance(obj, str) else obj.get_value()
3246 def _make_block_conf(block, append_fn):
3247 """Returns a list of .config strings for a block (list) of items."""
3249 # Collect the substrings in a list and later use join() instead of += to
3250 # build the final .config contents. With older Python versions, this yields
3251 # linear instead of quadratic complexity.
3253 item._make_conf(append_fn)
3255 def _sym_str_string(sym_or_str):
3256 if isinstance(sym_or_str, str):
3257 return '"' + sym_or_str + '"'
3258 return sym_or_str.name
3260 def _intersperse(lst, op):
3261 """_expr_to_str() helper. Gets the string representation of each expression
3262 in lst and produces a list where op has been inserted between the
3269 def handle_sub_expr(expr):
3270 no_parens = isinstance(expr, (str, Symbol)) or \
3271 expr[0] in (EQUAL, UNEQUAL) or \
3272 PRECEDENCE[op] <= PRECEDENCE[expr[0]]
3275 res.extend(_expr_to_str_rec(expr))
3279 op_str = OP_TO_STR[op]
3281 handle_sub_expr(lst[0])
3282 for expr in lst[1:]:
3284 handle_sub_expr(expr)
3288 def _expr_to_str_rec(expr):
3292 if isinstance(expr, (Symbol, str)):
3293 return [_sym_str_string(expr)]
3295 if expr[0] in (AND, OR):
3296 return _intersperse(expr[1], expr[0])
3299 need_parens = not isinstance(expr[1], (str, Symbol))
3304 res.extend(_expr_to_str_rec(expr[1]))
3309 if expr[0] in (EQUAL, UNEQUAL):
3310 return [_sym_str_string(expr[1]),
3312 _sym_str_string(expr[2])]
3314 def _expr_to_str(expr):
3315 return "".join(_expr_to_str_rec(expr))
3317 def _indentation(line):
3318 """Returns the length of the line's leading whitespace, treating tab stops
3319 as being spaced 8 characters apart."""
3320 line = line.expandtabs()
3321 return len(line) - len(line.lstrip())
3323 def _deindent(line, indent):
3324 """Deindent 'line' by 'indent' spaces."""
3325 line = line.expandtabs()
3326 if len(line) <= indent:
3328 return line[indent:]
3330 def _is_base_n(s, n):
3338 """Returns a string consisting of all arguments, with newlines inserted
3340 return "\n".join(args)
3343 """Returns a new string with "#" inserted before each line in 's'."""
3346 res = "".join(["#" + line for line in s.splitlines(True)])
3347 if s.endswith("\n"):
3351 def _clean_up_path(path):
3352 """Strips an initial "./" and any trailing slashes from 'path'."""
3353 if path.startswith("./"):
3355 return path.rstrip("/")
3357 def _stderr_msg(msg, filename, linenr):
3358 if filename is not None:
3359 sys.stderr.write("{0}:{1}: ".format(_clean_up_path(filename), linenr))
3360 sys.stderr.write(msg + "\n")
3362 def _tokenization_error(s, filename, linenr):
3363 loc = "" if filename is None else "{0}:{1}: ".format(filename, linenr)
3364 raise Kconfig_Syntax_Error("{0}Couldn't tokenize '{1}'"
3365 .format(loc, s.strip()))
3367 def _parse_error(s, msg, filename, linenr):
3368 loc = "" if filename is None else "{0}:{1}: ".format(filename, linenr)
3369 raise Kconfig_Syntax_Error("{0}Couldn't parse '{1}'{2}"
3370 .format(loc, s.strip(),
3371 "." if msg is None else ": " + msg))
3373 def _internal_error(msg):
3374 raise Internal_Error(msg +
3375 "\nSorry! You may want to send an email to ulfalizer a.t Google's "
3376 "email service to tell me about this. Include the message above and the "
3377 "stack trace and describe what you were doing.")
3380 # Internal global constants
3384 (T_AND, T_OR, T_NOT,
3385 T_OPEN_PAREN, T_CLOSE_PAREN,
3387 T_MAINMENU, T_MENU, T_ENDMENU,
3388 T_SOURCE, T_CHOICE, T_ENDCHOICE,
3389 T_COMMENT, T_CONFIG, T_MENUCONFIG,
3390 T_HELP, T_IF, T_ENDIF, T_DEPENDS, T_ON,
3391 T_OPTIONAL, T_PROMPT, T_DEFAULT,
3392 T_BOOL, T_TRISTATE, T_HEX, T_INT, T_STRING,
3393 T_DEF_BOOL, T_DEF_TRISTATE,
3394 T_SELECT, T_RANGE, T_OPTION, T_ALLNOCONFIG_Y, T_ENV,
3395 T_DEFCONFIG_LIST, T_MODULES, T_VISIBLE) = range(39)
3397 # The leading underscore before the function assignments below prevent pydoc
3398 # from listing them. The constants could be hidden too, but they're fairly
3399 # obviously internal anyway, so don't bother spamming the code.
3401 # Keyword to token map. Note that the get() method is assigned directly as a
3402 # small optimization.
3404 {"mainmenu": T_MAINMENU, "menu": T_MENU, "endmenu": T_ENDMENU,
3405 "endif": T_ENDIF, "endchoice": T_ENDCHOICE, "source": T_SOURCE,
3406 "choice": T_CHOICE, "config": T_CONFIG, "comment": T_COMMENT,
3407 "menuconfig": T_MENUCONFIG, "help": T_HELP, "if": T_IF,
3408 "depends": T_DEPENDS, "on": T_ON, "optional": T_OPTIONAL,
3409 "prompt": T_PROMPT, "default": T_DEFAULT, "bool": T_BOOL, "boolean": T_BOOL,
3410 "tristate": T_TRISTATE, "int": T_INT, "hex": T_HEX, "def_bool": T_DEF_BOOL,
3411 "def_tristate": T_DEF_TRISTATE, "string": T_STRING, "select": T_SELECT,
3412 "range": T_RANGE, "option": T_OPTION, "allnoconfig_y": T_ALLNOCONFIG_Y,
3413 "env": T_ENV, "defconfig_list": T_DEFCONFIG_LIST, "modules": T_MODULES,
3414 "visible": T_VISIBLE}.get
3416 # Strings to use for True and False
3417 BOOL_STR = {False: "false", True: "true"}
3419 # Tokens after which identifier-like lexemes are treated as strings. T_CHOICE
3420 # is included to avoid symbols being registered for named choices.
3421 STRING_LEX = frozenset((T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING, T_CHOICE,
3422 T_PROMPT, T_MENU, T_COMMENT, T_SOURCE, T_MAINMENU))
3424 # Matches the initial token on a line; see _tokenize(). Also eats trailing
3425 # whitespace as an optimization.
3426 _initial_token_re_match = re.compile(r"[^\w]*(\w+)\s*").match
3428 # Matches an identifier/keyword optionally preceded by whitespace. Also eats
3429 # trailing whitespace as an optimization.
3430 _id_keyword_re_match = re.compile(r"\s*([\w./-]+)\s*").match
3432 # Regular expression for finding $-references to symbols in strings
3433 _sym_ref_re_search = re.compile(r"\$[A-Za-z0-9_]+").search
3435 # Integers representing symbol types
3436 UNKNOWN, BOOL, TRISTATE, STRING, HEX, INT = range(6)
3438 # Strings to use for types
3439 TYPENAME = {UNKNOWN: "unknown", BOOL: "bool", TRISTATE: "tristate",
3440 STRING: "string", HEX: "hex", INT: "int"}
3442 # Token to type mapping
3443 TOKEN_TO_TYPE = {T_BOOL: BOOL, T_TRISTATE: TRISTATE, T_STRING: STRING,
3444 T_INT: INT, T_HEX: HEX}
3446 # Default values for symbols of different types (the value the symbol gets if
3447 # it is not assigned a user value and none of its 'default' clauses kick in)
3448 DEFAULT_VALUE = {BOOL: "n", TRISTATE: "n", STRING: "", INT: "", HEX: ""}
3450 # Indicates that no item is selected in a choice statement
3453 # Integers representing expression types
3454 AND, OR, NOT, EQUAL, UNEQUAL = range(5)
3456 # Map from tristate values to integers
3457 TRI_TO_INT = {"n": 0, "m": 1, "y": 2}
3459 # Printing-related stuff
3461 OP_TO_STR = {AND: " && ", OR: " || ", EQUAL: " = ", UNEQUAL: " != "}
3462 PRECEDENCE = {OR: 0, AND: 1, NOT: 2}