]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - tools/buildman/kconfiglib.py
karo: tx6ul: set VIDEO_PLL to 648MHz by default
[karo-tx-uboot.git] / tools / buildman / kconfiglib.py
1 #
2 # SPDX-License-Identifier:      ISC
3 #
4 # Author: Ulf Magnusson
5 #   https://github.com/ulfalizer/Kconfiglib
6
7 # This is Kconfiglib, a Python library for scripting, debugging, and extracting
8 # information from Kconfig-based configuration systems. To view the
9 # documentation, run
10 #
11 #  $ pydoc kconfiglib
12 #
13 # or, if you prefer HTML,
14 #
15 #  $ pydoc -w kconfiglib
16 #
17 # The examples/ subdirectory contains examples, to be run with e.g.
18 #
19 #  $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
20 #
21 # Look in testsuite.py for the test suite.
22
23 """
24 Kconfiglib is a Python library for scripting and extracting information from
25 Kconfig-based configuration systems. Features include the following:
26
27  - Symbol values and properties can be looked up and values assigned
28    programmatically.
29  - .config files can be read and written.
30  - Expressions can be evaluated in the context of a Kconfig configuration.
31  - Relations between symbols can be quickly determined, such as finding all
32    symbols that reference a particular symbol.
33  - Highly compatible with the scripts/kconfig/*conf utilities. The test suite
34    automatically compares outputs between Kconfiglib and the C implementation
35    for a large number of cases.
36
37 For the Linux kernel, scripts are run using
38
39  $ make scriptconfig [ARCH=<arch>] SCRIPT=<path to script> [SCRIPT_ARG=<arg>]
40
41 Using the 'scriptconfig' target ensures that required environment variables
42 (SRCARCH, ARCH, srctree, KERNELVERSION, etc.) are set up correctly.
43
44 Scripts receive the name of the Kconfig file to load in sys.argv[1]. As of
45 Linux 4.1.0-rc5, this is always "Kconfig" from the kernel top-level directory.
46 If an argument is provided with SCRIPT_ARG, it appears as sys.argv[2].
47
48 To get an interactive Python prompt with Kconfiglib preloaded and a Config
49 object 'c' created, run
50
51  $ make iscriptconfig [ARCH=<arch>]
52
53 Kconfiglib supports both Python 2 and Python 3. For (i)scriptconfig, the Python
54 interpreter to use can be passed in PYTHONCMD, which defaults to 'python'. PyPy
55 works well too, and might give a nice speedup for long-running jobs.
56
57 The examples/ directory contains short example scripts, which can be run with
58 e.g.
59
60  $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
61
62 or
63
64  $ make scriptconfig SCRIPT=Kconfiglib/examples/help_grep.py SCRIPT_ARG=kernel
65
66 testsuite.py contains the test suite. See the top of the script for how to run
67 it.
68
69 Credits: Written by Ulf "Ulfalizer" Magnusson
70
71 Send bug reports, suggestions and other feedback to ulfalizer a.t Google's
72 email service. Don't wrestle with internal APIs. Tell me what you need and I
73 might add it in a safe way as a client API instead."""
74
75 import os
76 import re
77 import sys
78
79 # File layout:
80 #
81 # Public classes
82 # Public functions
83 # Internal classes
84 # Internal functions
85 # Internal global constants
86
87 # Line length: 79 columns
88
89 #
90 # Public classes
91 #
92
93 class Config(object):
94
95     """Represents a Kconfig configuration, e.g. for i386 or ARM. This is the
96     set of symbols and other items appearing in the configuration together with
97     their values. Creating any number of Config objects -- including for
98     different architectures -- is safe; Kconfiglib has no global state."""
99
100     #
101     # Public interface
102     #
103
104     def __init__(self, filename="Kconfig", base_dir=None, print_warnings=True,
105                  print_undef_assign=False):
106         """Creates a new Config object, representing a Kconfig configuration.
107         Raises Kconfig_Syntax_Error on syntax errors.
108
109         filename (default: "Kconfig"): The base Kconfig file of the
110            configuration. For the Linux kernel, you'll probably want "Kconfig"
111            from the top-level directory, as environment variables will make
112            sure the right Kconfig is included from there
113            (arch/<architecture>/Kconfig). If you are using Kconfiglib via 'make
114            scriptconfig', the filename of the base base Kconfig file will be in
115            sys.argv[1].
116
117         base_dir (default: None): The base directory relative to which 'source'
118            statements within Kconfig files will work. For the Linux kernel this
119            should be the top-level directory of the kernel tree. $-references
120            to existing environment variables will be expanded.
121
122            If None (the default), the environment variable 'srctree' will be
123            used if set, and the current directory otherwise. 'srctree' is set
124            by the Linux makefiles to the top-level kernel directory. A default
125            of "." would not work with an alternative build directory.
126
127         print_warnings (default: True): Set to True if warnings related to this
128            configuration should be printed to stderr. This can be changed later
129            with Config.set_print_warnings(). It is provided as a constructor
130            argument since warnings might be generated during parsing.
131
132         print_undef_assign (default: False): Set to True if informational
133            messages related to assignments to undefined symbols should be
134            printed to stderr for this configuration. Can be changed later with
135            Config.set_print_undef_assign()."""
136
137         # The set of all symbols, indexed by name (a string)
138         self.syms = {}
139         # Python 2/3 compatibility hack. This is the only one needed.
140         if sys.version_info[0] >= 3:
141             self.syms_iter = self.syms.values
142         else:
143             self.syms_iter = self.syms.itervalues
144
145         # The set of all defined symbols in the configuration in the order they
146         # appear in the Kconfig files. This excludes the special symbols n, m,
147         # and y as well as symbols that are referenced but never defined.
148         self.kconfig_syms = []
149
150         # The set of all named choices (yes, choices can have names), indexed
151         # by name (a string)
152         self.named_choices = {}
153
154         # Lists containing all choices, menus and comments in the configuration
155         self.choices = []
156         self.menus = []
157         self.comments = []
158
159         def register_special_symbol(type_, name, val):
160             sym = Symbol()
161             sym.is_special_ = True
162             sym.is_defined_ = True
163             sym.config = self
164             sym.name = name
165             sym.type = type_
166             sym.cached_val = val
167             self.syms[name] = sym
168             return sym
169
170         # The special symbols n, m and y, used as shorthand for "n", "m" and
171         # "y"
172         self.n = register_special_symbol(TRISTATE, "n", "n")
173         self.m = register_special_symbol(TRISTATE, "m", "m")
174         self.y = register_special_symbol(TRISTATE, "y", "y")
175         # DEFCONFIG_LIST uses this
176         register_special_symbol(STRING, "UNAME_RELEASE", os.uname()[2])
177
178         # The symbol with "option defconfig_list" set, containing a list of
179         # default .config files
180         self.defconfig_sym = None
181
182         # See Symbol.get_(src)arch()
183         self.arch = os.environ.get("ARCH")
184         self.srcarch = os.environ.get("SRCARCH")
185
186         # See Config.__init__(). We need this for get_defconfig_filename().
187         self.srctree = os.environ.get("srctree")
188         if self.srctree is None:
189             self.srctree = "."
190
191         self.filename = filename
192         if base_dir is None:
193             self.base_dir = self.srctree
194         else:
195             self.base_dir = os.path.expandvars(base_dir)
196
197         # The 'mainmenu' text
198         self.mainmenu_text = None
199
200         # The filename of the most recently loaded .config file
201         self.config_filename = None
202         # The textual header of the most recently loaded .config, uncommented
203         self.config_header = None
204
205         self.print_warnings = print_warnings
206         self.print_undef_assign = print_undef_assign
207
208         # For parsing routines that stop when finding a line belonging to a
209         # different construct, these holds that line and the tokenized version
210         # of that line. The purpose is to avoid having to re-tokenize the line,
211         # which is inefficient and causes problems when recording references to
212         # symbols.
213         self.end_line = None
214         self.end_line_tokens = None
215
216         # See the comment in _parse_expr().
217         self._cur_item = None
218         self._line = None
219         self._filename = None
220         self._linenr = None
221         self._transform_m = None
222
223         # Parse the Kconfig files
224         self.top_block = self._parse_file(filename, None, None, None)
225
226         # Build Symbol.dep for all symbols
227         self._build_dep()
228
229     def get_arch(self):
230         """Returns the value the environment variable ARCH had at the time the
231         Config instance was created, or None if ARCH was not set. For the
232         kernel, this corresponds to the architecture being built for, with
233         values such as "i386" or "mips"."""
234         return self.arch
235
236     def get_srcarch(self):
237         """Returns the value the environment variable SRCARCH had at the time
238         the Config instance was created, or None if SRCARCH was not set. For
239         the kernel, this corresponds to the particular arch/ subdirectory
240         containing architecture-specific code."""
241         return self.srcarch
242
243     def get_srctree(self):
244         """Returns the value the environment variable srctree had at the time
245         the Config instance was created, or None if srctree was not defined.
246         This variable points to the source directory and is used when building
247         in a separate directory."""
248         return self.srctree
249
250     def get_base_dir(self):
251         """Returns the base directory relative to which 'source' statements
252         will work, passed as an argument to Config.__init__()."""
253         return self.base_dir
254
255     def get_kconfig_filename(self):
256         """Returns the name of the (base) kconfig file this configuration was
257         loaded from."""
258         return self.filename
259
260     def get_config_filename(self):
261         """Returns the filename of the most recently loaded configuration file,
262         or None if no configuration has been loaded."""
263         return self.config_filename
264
265     def get_config_header(self):
266         """Returns the (uncommented) textual header of the .config file most
267         recently loaded with load_config(). Returns None if no .config file has
268         been loaded or if the most recently loaded .config file has no header.
269         The header consists of all lines up to but not including the first line
270         that either
271
272         1. Does not start with "#"
273         2. Has the form "# CONFIG_FOO is not set."
274         """
275         return self.config_header
276
277     def get_mainmenu_text(self):
278         """Returns the text of the 'mainmenu' statement (with $-references to
279         symbols replaced by symbol values), or None if the configuration has no
280         'mainmenu' statement."""
281         return None if self.mainmenu_text is None else \
282           self._expand_sym_refs(self.mainmenu_text)
283
284     def get_defconfig_filename(self):
285         """Returns the name of the defconfig file, which is the first existing
286         file in the list given in a symbol having 'option defconfig_list' set.
287         $-references to symbols will be expanded ("$FOO bar" -> "foo bar" if
288         FOO has the value "foo"). Returns None in case of no defconfig file.
289         Setting 'option defconfig_list' on multiple symbols currently results
290         in undefined behavior.
291
292         If the environment variable 'srctree' was set when the Config was
293         created, get_defconfig_filename() will first look relative to that
294         directory before looking in the current directory; see
295         Config.__init__().
296
297         WARNING: A wart here is that scripts/kconfig/Makefile sometimes uses
298         the --defconfig=<defconfig> option when calling the C implementation of
299         e.g. 'make defconfig'. This option overrides the 'option
300         defconfig_list' symbol, meaning the result from
301         get_defconfig_filename() might not match what 'make defconfig' would
302         use. That probably ought to be worked around somehow, so that this
303         function always gives the "expected" result."""
304         if self.defconfig_sym is None:
305             return None
306         for filename, cond_expr in self.defconfig_sym.def_exprs:
307             if self._eval_expr(cond_expr) == "y":
308                 filename = self._expand_sym_refs(filename)
309                 # We first look in $srctree. os.path.join() won't work here as
310                 # an absolute path in filename would override $srctree.
311                 srctree_filename = os.path.normpath(self.srctree + "/" +
312                                                     filename)
313                 if os.path.exists(srctree_filename):
314                     return srctree_filename
315                 if os.path.exists(filename):
316                     return filename
317         return None
318
319     def get_symbol(self, name):
320         """Returns the symbol with name 'name', or None if no such symbol
321         appears in the configuration. An alternative shorthand is conf[name],
322         where conf is a Config instance, though that will instead raise
323         KeyError if the symbol does not exist."""
324         return self.syms.get(name)
325
326     def __getitem__(self, name):
327         """Returns the symbol with name 'name'. Raises KeyError if the symbol
328         does not appear in the configuration."""
329         return self.syms[name]
330
331     def get_symbols(self, all_symbols=True):
332         """Returns a list of symbols from the configuration. An alternative for
333         iterating over all defined symbols (in the order of definition) is
334
335         for sym in config:
336             ...
337
338         which relies on Config implementing __iter__() and is equivalent to
339
340         for sym in config.get_symbols(False):
341             ...
342
343         all_symbols (default: True): If True, all symbols -- including special
344            and undefined symbols -- will be included in the result, in an
345            undefined order. If False, only symbols actually defined and not
346            merely referred to in the configuration will be included in the
347            result, and will appear in the order that they are defined within
348            the Kconfig configuration files."""
349         return list(self.syms.values()) if all_symbols else self.kconfig_syms
350
351     def __iter__(self):
352         """Convenience function for iterating over the set of all defined
353         symbols in the configuration, used like
354
355         for sym in conf:
356             ...
357
358         The iteration happens in the order of definition within the Kconfig
359         configuration files. Symbols only referred to but not defined will not
360         be included, nor will the special symbols n, m, and y. If you want to
361         include such symbols as well, see config.get_symbols()."""
362         return iter(self.kconfig_syms)
363
364     def get_choices(self):
365         """Returns a list containing all choice statements in the
366         configuration, in the order they appear in the Kconfig files."""
367         return self.choices
368
369     def get_menus(self):
370         """Returns a list containing all menus in the configuration, in the
371         order they appear in the Kconfig files."""
372         return self.menus
373
374     def get_comments(self):
375         """Returns a list containing all comments in the configuration, in the
376         order they appear in the Kconfig files."""
377         return self.comments
378
379     def get_top_level_items(self):
380         """Returns a list containing the items (symbols, menus, choices, and
381         comments) at the top level of the configuration -- that is, all items
382         that do not appear within a menu or choice. The items appear in the
383         same order as within the configuration."""
384         return self.top_block
385
386     def load_config(self, filename, replace=True):
387         """Loads symbol values from a file in the familiar .config format.
388         Equivalent to calling Symbol.set_user_value() to set each of the
389         values.
390
391         "# CONFIG_FOO is not set" within a .config file is treated specially
392         and sets the user value of FOO to 'n'. The C implementation works the
393         same way.
394
395         filename: The .config file to load. $-references to existing
396           environment variables will be expanded. For scripts to work even when
397           an alternative build directory is used with the Linux kernel, you
398           need to refer to the top-level kernel directory with "$srctree".
399
400         replace (default: True): True if the configuration should replace the
401            old configuration; False if it should add to it."""
402
403         # Put this first so that a missing file doesn't screw up our state
404         filename = os.path.expandvars(filename)
405         line_feeder = _FileFeed(filename)
406
407         self.config_filename = filename
408
409         #
410         # Read header
411         #
412
413         def is_header_line(line):
414             return line is not None and line.startswith("#") and \
415                    not _unset_re_match(line)
416
417         self.config_header = None
418
419         line = line_feeder.peek_next()
420         if is_header_line(line):
421             self.config_header = ""
422             while is_header_line(line_feeder.peek_next()):
423                 self.config_header += line_feeder.get_next()[1:]
424             # Remove trailing newline
425             if self.config_header.endswith("\n"):
426                 self.config_header = self.config_header[:-1]
427
428         #
429         # Read assignments. Hotspot for some workloads.
430         #
431
432         def warn_override(filename, linenr, name, old_user_val, new_user_val):
433             self._warn('overriding the value of {0}. '
434                        'Old value: "{1}", new value: "{2}".'
435                        .format(name, old_user_val, new_user_val),
436                        filename, linenr)
437
438         # Invalidate everything to keep things simple. It might be possible to
439         # improve performance for the case where multiple configurations are
440         # loaded by only invalidating a symbol (and its dependent symbols) if
441         # the new user value differs from the old. One complication would be
442         # that symbols not mentioned in the .config must lose their user value
443         # when replace = True, which is the usual case.
444         if replace:
445             self.unset_user_values()
446         else:
447             self._invalidate_all()
448
449         while 1:
450             line = line_feeder.get_next()
451             if line is None:
452                 return
453
454             line = line.rstrip()
455
456             set_match = _set_re_match(line)
457             if set_match:
458                 name, val = set_match.groups()
459
460                 if val.startswith('"'):
461                     if len(val) < 2 or val[-1] != '"':
462                         _parse_error(line, "malformed string literal",
463                                      line_feeder.filename, line_feeder.linenr)
464                     # Strip quotes and remove escapings. The unescaping
465                     # procedure should be safe since " can only appear as \"
466                     # inside the string.
467                     val = val[1:-1].replace('\\"', '"').replace("\\\\", "\\")
468
469                 if name in self.syms:
470                     sym = self.syms[name]
471                     if sym.user_val is not None:
472                         warn_override(line_feeder.filename, line_feeder.linenr,
473                                       name, sym.user_val, val)
474
475                     if sym.is_choice_sym:
476                         user_mode = sym.parent.user_mode
477                         if user_mode is not None and user_mode != val:
478                             self._warn("assignment to {0} changes mode of "
479                                        'containing choice from "{1}" to "{2}".'
480                                        .format(name, val, user_mode),
481                                        line_feeder.filename,
482                                        line_feeder.linenr)
483
484                     sym._set_user_value_no_invalidate(val, True)
485                 else:
486                     if self.print_undef_assign:
487                         _stderr_msg('note: attempt to assign the value "{0}" '
488                                     "to the undefined symbol {1}."
489                                     .format(val, name),
490                                     line_feeder.filename, line_feeder.linenr)
491             else:
492                 unset_match = _unset_re_match(line)
493                 if unset_match:
494                     name = unset_match.group(1)
495                     if name in self.syms:
496                         sym = self.syms[name]
497                         if sym.user_val is not None:
498                             warn_override(line_feeder.filename,
499                                           line_feeder.linenr,
500                                           name, sym.user_val, "n")
501
502                         sym._set_user_value_no_invalidate("n", True)
503
504     def write_config(self, filename, header=None):
505         """Writes out symbol values in the familiar .config format.
506
507         Kconfiglib makes sure the format matches what the C implementation
508         would generate, down to whitespace. This eases testing.
509
510         filename: The filename under which to save the configuration.
511
512         header (default: None): A textual header that will appear at the
513            beginning of the file, with each line commented out automatically.
514            None means no header."""
515
516         for sym in self.syms_iter():
517             sym.already_written = False
518
519         with open(filename, "w") as f:
520             # Write header
521             if header is not None:
522                 f.write(_comment(header))
523                 f.write("\n")
524
525             # Build and write configuration
526             conf_strings = []
527             _make_block_conf(self.top_block, conf_strings.append)
528             f.write("\n".join(conf_strings))
529             f.write("\n")
530
531     def eval(self, s):
532         """Returns the value of the expression 's' -- where 's' is represented
533         as a string -- in the context of the configuration. Raises
534         Kconfig_Syntax_Error if syntax errors are detected in 's'.
535
536         For example, if FOO and BAR are tristate symbols at least one of which
537         has the value "y", then config.eval("y && (FOO || BAR)") => "y"
538
539         This function always yields a tristate value. To get the value of
540         non-bool, non-tristate symbols, use Symbol.get_value().
541
542         The result of this function is consistent with how evaluation works for
543         conditional expressions in the configuration as well as in the C
544         implementation. "m" and m are rewritten as '"m" && MODULES' and 'm &&
545         MODULES', respectively, and a result of "m" will get promoted to "y" if
546         we're running without modules.
547
548         Syntax checking is somewhat lax, partly to be compatible with lax
549         parsing in the C implementation."""
550         return self._eval_expr(self._parse_expr(self._tokenize(s, True), # Feed
551                                                 None, # Current symbol/choice
552                                                 s))   # line
553
554     def unset_user_values(self):
555         """Resets the values of all symbols, as if Config.load_config() or
556         Symbol.set_user_value() had never been called."""
557         for sym in self.syms_iter():
558             sym._unset_user_value_no_recursive_invalidate()
559
560     def set_print_warnings(self, print_warnings):
561         """Determines whether warnings related to this configuration (for
562         things like attempting to assign illegal values to symbols with
563         Symbol.set_user_value()) should be printed to stderr.
564
565         print_warnings: True if warnings should be printed."""
566         self.print_warnings = print_warnings
567
568     def set_print_undef_assign(self, print_undef_assign):
569         """Determines whether informational messages related to assignments to
570         undefined symbols should be printed to stderr for this configuration.
571
572         print_undef_assign: If True, such messages will be printed."""
573         self.print_undef_assign = print_undef_assign
574
575     def __str__(self):
576         """Returns a string containing various information about the Config."""
577         return _lines("Configuration",
578                       "File                                   : " +
579                         self.filename,
580                       "Base directory                         : " +
581                         self.base_dir,
582                       "Value of $ARCH at creation time        : " +
583                         ("(not set)" if self.arch is None else self.arch),
584                       "Value of $SRCARCH at creation time     : " +
585                         ("(not set)" if self.srcarch is None else
586                                         self.srcarch),
587                       "Source tree (derived from $srctree;",
588                       "defaults to '.' if $srctree isn't set) : " +
589                         self.srctree,
590                       "Most recently loaded .config           : " +
591                         ("(no .config loaded)"
592                           if self.config_filename is None else
593                              self.config_filename),
594                       "Print warnings                         : " +
595                         BOOL_STR[self.print_warnings],
596                       "Print assignments to undefined symbols : " +
597                         BOOL_STR[self.print_undef_assign])
598
599     #
600     # Private methods
601     #
602
603     #
604     # Kconfig parsing
605     #
606
607     def _parse_file(self, filename, parent, deps, visible_if_deps, res=None):
608         """Parses the Kconfig file 'filename'. Returns a list with the Items in
609         the file. See _parse_block() for the meaning of the parameters."""
610         return self._parse_block(_FileFeed(filename), None, parent, deps,
611                                  visible_if_deps, res)
612
613     def _parse_block(self, line_feeder, end_marker, parent, deps,
614                      visible_if_deps, res=None):
615         """Parses a block, which is the contents of either a file or an if,
616         menu, or choice statement. Returns a list with the Items in the block.
617
618         line_feeder: A _FileFeed instance feeding lines from a file. The
619           Kconfig language is line-based in practice.
620
621         end_marker: The token that ends the block, e.g. T_ENDIF ("endif") for
622            ifs. None for files.
623
624         parent: The enclosing menu or choice, or None if we're at the top
625            level.
626
627         deps: Dependencies from enclosing menus, choices and ifs.
628
629         visible_if_deps (default: None): 'visible if' dependencies from
630            enclosing menus.
631
632         res (default: None): The list to add items to. If None, a new list is
633            created to hold the items."""
634
635         block = [] if res is None else res
636
637         while 1:
638             # Do we already have a tokenized line that we determined wasn't
639             # part of whatever we were parsing earlier? See comment in
640             # Config.__init__().
641             if self.end_line is not None:
642                 line = self.end_line
643                 tokens = self.end_line_tokens
644                 tokens.unget_all()
645
646                 self.end_line = None
647                 self.end_line_tokens = None
648             else:
649                 line = line_feeder.get_next()
650                 if line is None:
651                     if end_marker is not None:
652                         raise Kconfig_Syntax_Error("Unexpected end of file {0}"
653                                                  .format(line_feeder.filename))
654                     return block
655
656                 tokens = self._tokenize(line, False, line_feeder.filename,
657                                         line_feeder.linenr)
658
659             t0 = tokens.get_next()
660             if t0 is None:
661                 continue
662
663             # Cases are ordered roughly by frequency, which speeds things up a
664             # bit
665
666             if t0 == T_CONFIG or t0 == T_MENUCONFIG:
667                 # The tokenizer will automatically allocate a new Symbol object
668                 # for any new names it encounters, so we don't need to worry
669                 # about that here.
670                 sym = tokens.get_next()
671
672                 # Symbols defined in multiple places get the parent of their
673                 # first definition. However, for symbols whose parents are
674                 # choice statements, the choice statement takes precedence.
675                 if not sym.is_defined_ or isinstance(parent, Choice):
676                     sym.parent = parent
677
678                 sym.is_defined_ = True
679
680                 self.kconfig_syms.append(sym)
681                 block.append(sym)
682
683                 self._parse_properties(line_feeder, sym, deps, visible_if_deps)
684
685             elif t0 == T_SOURCE:
686                 kconfig_file = tokens.get_next()
687                 exp_kconfig_file = self._expand_sym_refs(kconfig_file)
688                 f = os.path.join(self.base_dir, exp_kconfig_file)
689                 if not os.path.exists(f):
690                     raise IOError('{0}:{1}: sourced file "{2}" (expands to '
691                                   '"{3}") not found. Perhaps base_dir '
692                                   '(argument to Config.__init__(), currently '
693                                   '"{4}") is set to the wrong value.'
694                                   .format(line_feeder.filename,
695                                           line_feeder.linenr,
696                                           kconfig_file, exp_kconfig_file,
697                                           self.base_dir))
698                 # Add items to the same block
699                 self._parse_file(f, parent, deps, visible_if_deps, block)
700
701             elif t0 == end_marker:
702                 # We have reached the end of the block
703                 return block
704
705             elif t0 == T_IF:
706                 # If statements are treated as syntactic sugar for adding
707                 # dependencies to enclosed items and do not have an explicit
708                 # object representation.
709
710                 dep_expr = self._parse_expr(tokens, None, line,
711                                             line_feeder.filename,
712                                             line_feeder.linenr)
713                 # Add items to the same block
714                 self._parse_block(line_feeder, T_ENDIF, parent,
715                                   _make_and(dep_expr, deps),
716                                   visible_if_deps, block)
717
718             elif t0 == T_COMMENT:
719                 comment = Comment()
720
721                 comment.config = self
722                 comment.parent = parent
723                 comment.filename = line_feeder.filename
724                 comment.linenr = line_feeder.linenr
725                 comment.text = tokens.get_next()
726
727                 self.comments.append(comment)
728                 block.append(comment)
729
730                 self._parse_properties(line_feeder, comment, deps,
731                                        visible_if_deps)
732
733             elif t0 == T_MENU:
734                 menu = Menu()
735
736                 menu.config = self
737                 menu.parent = parent
738                 menu.filename = line_feeder.filename
739                 menu.linenr = line_feeder.linenr
740                 menu.title = tokens.get_next()
741
742                 self.menus.append(menu)
743                 block.append(menu)
744
745                 # Parse properties and contents
746                 self._parse_properties(line_feeder, menu, deps,
747                                        visible_if_deps)
748                 menu.block = self._parse_block(line_feeder, T_ENDMENU, menu,
749                                                menu.dep_expr,
750                                                _make_and(visible_if_deps,
751                                                          menu.visible_if_expr))
752
753             elif t0 == T_CHOICE:
754                 name = tokens.get_next()
755                 if name is None:
756                     choice = Choice()
757                     self.choices.append(choice)
758                 else:
759                     # Named choice
760                     choice = self.named_choices.get(name)
761                     if choice is None:
762                         choice = Choice()
763                         choice.name = name
764                         self.named_choices[name] = choice
765                         self.choices.append(choice)
766
767                 choice.config = self
768                 choice.parent = parent
769
770                 choice.def_locations.append((line_feeder.filename,
771                                              line_feeder.linenr))
772
773                 # Parse properties and contents
774                 self._parse_properties(line_feeder, choice, deps,
775                                        visible_if_deps)
776                 choice.block = self._parse_block(line_feeder, T_ENDCHOICE,
777                                                  choice, deps, visible_if_deps)
778
779                 choice._determine_actual_symbols()
780
781                 # If no type is specified for the choice, its type is that of
782                 # the first choice item with a specified type
783                 if choice.type == UNKNOWN:
784                     for item in choice.actual_symbols:
785                         if item.type != UNKNOWN:
786                             choice.type = item.type
787                             break
788
789                 # Each choice item of UNKNOWN type gets the type of the choice
790                 for item in choice.actual_symbols:
791                     if item.type == UNKNOWN:
792                         item.type = choice.type
793
794                 block.append(choice)
795
796             elif t0 == T_MAINMENU:
797                 text = tokens.get_next()
798                 if self.mainmenu_text is not None:
799                     self._warn("overriding 'mainmenu' text. "
800                                'Old value: "{0}", new value: "{1}".'
801                                .format(self.mainmenu_text, text),
802                                line_feeder.filename, line_feeder.linenr)
803                 self.mainmenu_text = text
804
805             else:
806                 _parse_error(line, "unrecognized construct",
807                              line_feeder.filename, line_feeder.linenr)
808
809     def _parse_properties(self, line_feeder, stmt, deps, visible_if_deps):
810         """Parsing of properties for symbols, menus, choices, and comments.
811         Takes care of propagating dependencies from enclosing menus and ifs."""
812
813         def parse_val_and_cond(tokens, line, filename, linenr):
814             """Parses '<expr1> if <expr2>' constructs, where the 'if' part is
815             optional. Returns a tuple containing the parsed expressions, with
816             None as the second element if the 'if' part is missing."""
817             val = self._parse_expr(tokens, stmt, line, filename, linenr, False)
818             if tokens.check(T_IF):
819                 return (val, self._parse_expr(tokens, stmt, line, filename,
820                                               linenr))
821             return (val, None)
822
823         # In case the symbol is defined in multiple locations, we need to
824         # remember what prompts, defaults, and selects are new for this
825         # definition, as "depends on" should only apply to the local
826         # definition.
827         new_prompt = None
828         new_def_exprs = []
829         new_selects = []
830
831         # Dependencies from 'depends on' statements
832         depends_on_expr = None
833
834         while 1:
835             line = line_feeder.get_next()
836             if line is None:
837                 break
838
839             filename = line_feeder.filename
840             linenr = line_feeder.linenr
841
842             tokens = self._tokenize(line, False, filename, linenr)
843
844             t0 = tokens.get_next()
845             if t0 is None:
846                 continue
847
848             # Cases are ordered roughly by frequency, which speeds things up a
849             # bit
850
851             if t0 == T_DEPENDS:
852                 if not tokens.check(T_ON):
853                     _parse_error(line, 'expected "on" after "depends"',
854                                  filename, linenr)
855
856                 parsed_deps = self._parse_expr(tokens, stmt, line, filename,
857                                                linenr)
858
859                 if isinstance(stmt, (Menu, Comment)):
860                     stmt.orig_deps = _make_and(stmt.orig_deps, parsed_deps)
861                 else:
862                     depends_on_expr = _make_and(depends_on_expr, parsed_deps)
863
864             elif t0 == T_HELP:
865                 # Find first non-blank (not all-space) line and get its
866                 # indentation
867                 line = line_feeder.next_nonblank()
868                 if line is None:
869                     stmt.help = ""
870                     break
871                 indent = _indentation(line)
872                 if indent == 0:
873                     # If the first non-empty lines has zero indent, there is no
874                     # help text
875                     stmt.help = ""
876                     line_feeder.unget()
877                     break
878
879                 # The help text goes on till the first non-empty line with less
880                 # indent
881                 help_lines = [_deindent(line, indent)]
882                 while 1:
883                     line = line_feeder.get_next()
884                     if line is None or \
885                        (not line.isspace() and _indentation(line) < indent):
886                         stmt.help = "".join(help_lines)
887                         break
888                     help_lines.append(_deindent(line, indent))
889
890                 if line is None:
891                     break
892
893                 line_feeder.unget()
894
895             elif t0 == T_SELECT:
896                 target = tokens.get_next()
897
898                 stmt.referenced_syms.add(target)
899                 stmt.selected_syms.add(target)
900
901                 if tokens.check(T_IF):
902                     new_selects.append((target,
903                                         self._parse_expr(tokens, stmt, line,
904                                                          filename, linenr)))
905                 else:
906                     new_selects.append((target, None))
907
908             elif t0 in (T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING):
909                 stmt.type = TOKEN_TO_TYPE[t0]
910                 if tokens.peek_next() is not None:
911                     new_prompt = parse_val_and_cond(tokens, line, filename,
912                                                     linenr)
913
914             elif t0 == T_DEFAULT:
915                 new_def_exprs.append(parse_val_and_cond(tokens, line, filename,
916                                                         linenr))
917
918             elif t0 == T_DEF_BOOL:
919                 stmt.type = BOOL
920                 if tokens.peek_next() is not None:
921                     new_def_exprs.append(parse_val_and_cond(tokens, line,
922                                                             filename, linenr))
923
924             elif t0 == T_PROMPT:
925                 # 'prompt' properties override each other within a single
926                 # definition of a symbol, but additional prompts can be added
927                 # by defining the symbol multiple times; hence 'new_prompt'
928                 # instead of 'prompt'.
929                 new_prompt = parse_val_and_cond(tokens, line, filename, linenr)
930
931             elif t0 == T_RANGE:
932                 low = tokens.get_next()
933                 high = tokens.get_next()
934                 stmt.referenced_syms.add(low)
935                 stmt.referenced_syms.add(high)
936
937                 if tokens.check(T_IF):
938                     stmt.ranges.append((low, high,
939                                         self._parse_expr(tokens, stmt, line,
940                                                          filename, linenr)))
941                 else:
942                     stmt.ranges.append((low, high, None))
943
944             elif t0 == T_DEF_TRISTATE:
945                 stmt.type = TRISTATE
946                 if tokens.peek_next() is not None:
947                     new_def_exprs.append(parse_val_and_cond(tokens, line,
948                                                             filename, linenr))
949
950             elif t0 == T_OPTION:
951                 if tokens.check(T_ENV) and tokens.check(T_EQUAL):
952                     env_var = tokens.get_next()
953
954                     stmt.is_special_ = True
955                     stmt.is_from_env = True
956
957                     if env_var not in os.environ:
958                         self._warn("The symbol {0} references the "
959                                    "non-existent environment variable {1} and "
960                                    "will get the empty string as its value. "
961                                    "If you're using Kconfiglib via "
962                                    "'make (i)scriptconfig', it should have "
963                                    "set up the environment correctly for you. "
964                                    "If you still got this message, that "
965                                    "might be an error, and you should email "
966                                    "ulfalizer a.t Google's email service."""
967                                    .format(stmt.name, env_var),
968                                    filename, linenr)
969
970                         stmt.cached_val = ""
971                     else:
972                         stmt.cached_val = os.environ[env_var]
973
974                 elif tokens.check(T_DEFCONFIG_LIST):
975                     self.defconfig_sym = stmt
976
977                 elif tokens.check(T_MODULES):
978                     # To reduce warning spam, only warn if 'option modules' is
979                     # set on some symbol that isn't MODULES, which should be
980                     # safe. I haven't run into any projects that make use
981                     # modules besides the kernel yet, and there it's likely to
982                     # keep being called "MODULES".
983                     if stmt.name != "MODULES":
984                         self._warn("the 'modules' option is not supported. "
985                                    "Let me know if this is a problem for you; "
986                                    "it shouldn't be that hard to implement. "
987                                    "(Note that modules are still supported -- "
988                                    "Kconfiglib just assumes the symbol name "
989                                    "MODULES, like older versions of the C "
990                                    "implementation did when 'option modules' "
991                                    "wasn't used.)",
992                                    filename, linenr)
993
994                 elif tokens.check(T_ALLNOCONFIG_Y):
995                     if not isinstance(stmt, Symbol):
996                         _parse_error(line,
997                                      "the 'allnoconfig_y' option is only "
998                                      "valid for symbols",
999                                      filename, linenr)
1000                     stmt.allnoconfig_y = True
1001
1002                 else:
1003                     _parse_error(line, "unrecognized option", filename, linenr)
1004
1005             elif t0 == T_VISIBLE:
1006                 if not tokens.check(T_IF):
1007                     _parse_error(line, 'expected "if" after "visible"',
1008                                  filename, linenr)
1009                 if not isinstance(stmt, Menu):
1010                     _parse_error(line,
1011                                  "'visible if' is only valid for menus",
1012                                  filename, linenr)
1013
1014                 parsed_deps = self._parse_expr(tokens, stmt, line, filename,
1015                                                linenr)
1016                 stmt.visible_if_expr = _make_and(stmt.visible_if_expr,
1017                                                  parsed_deps)
1018
1019             elif t0 == T_OPTIONAL:
1020                 if not isinstance(stmt, Choice):
1021                     _parse_error(line,
1022                                  '"optional" is only valid for choices',
1023                                  filename,
1024                                  linenr)
1025                 stmt.optional = True
1026
1027             else:
1028                 # See comment in Config.__init__()
1029                 self.end_line = line
1030                 self.end_line_tokens = tokens
1031                 break
1032
1033         # Done parsing properties. Now propagate 'depends on' and enclosing
1034         # menu/if dependencies to expressions.
1035
1036         # The set of symbols referenced directly by the statement plus all
1037         # symbols referenced by enclosing menus and ifs
1038         stmt.all_referenced_syms = stmt.referenced_syms | _get_expr_syms(deps)
1039
1040         # Save original dependencies from enclosing menus and ifs
1041         stmt.deps_from_containing = deps
1042
1043         if isinstance(stmt, (Menu, Comment)):
1044             stmt.dep_expr = _make_and(stmt.orig_deps, deps)
1045         else:
1046             # Symbol or Choice
1047
1048             # See comment for 'menu_dep'
1049             stmt.menu_dep = depends_on_expr
1050
1051             # Propagate dependencies to prompts
1052
1053             if new_prompt is not None:
1054                 # Propagate 'visible if' dependencies from enclosing menus
1055                 prompt, cond_expr = new_prompt
1056                 cond_expr = _make_and(cond_expr, visible_if_deps)
1057                 # Propagate 'depends on' dependencies
1058                 new_prompt = (prompt, _make_and(cond_expr, depends_on_expr))
1059                 # Save original
1060                 stmt.orig_prompts.append(new_prompt)
1061                 # Finalize with dependencies from enclosing menus and ifs
1062                 stmt.prompts.append((new_prompt[0],
1063                                      _make_and(new_prompt[1], deps)))
1064
1065             # Propagate dependencies to defaults
1066
1067             # Propagate 'depends on' dependencies
1068             new_def_exprs = [(val_expr, _make_and(cond_expr, depends_on_expr))
1069                              for val_expr, cond_expr in new_def_exprs]
1070             # Save original
1071             stmt.orig_def_exprs.extend(new_def_exprs)
1072             # Finalize with dependencies from enclosing menus and ifs
1073             stmt.def_exprs.extend([(val_expr, _make_and(cond_expr, deps))
1074                                    for val_expr, cond_expr in new_def_exprs])
1075
1076             # Propagate dependencies to selects
1077
1078             # Only symbols can select
1079             if isinstance(stmt, Symbol):
1080                 # Propagate 'depends on' dependencies
1081                 new_selects = [(target, _make_and(cond_expr, depends_on_expr))
1082                                for target, cond_expr in new_selects]
1083                 # Save original
1084                 stmt.orig_selects.extend(new_selects)
1085                 # Finalize with dependencies from enclosing menus and ifs
1086                 for target, cond in new_selects:
1087                     target.rev_dep = _make_or(target.rev_dep,
1088                                               _make_and(stmt,
1089                                                         _make_and(cond, deps)))
1090
1091     def _parse_expr(self, feed, cur_item, line, filename=None, linenr=None,
1092                     transform_m=True):
1093         """Parses an expression from the tokens in 'feed' using a simple
1094         top-down approach. The result has the form
1095         '(<operator>, [<parsed operands>])', where <operator> is e.g.
1096         kconfiglib.AND. If there is only one operand (i.e., no && or ||), then
1097         the operand is returned directly. This also goes for subexpressions.
1098
1099         feed: _Feed instance containing the tokens for the expression.
1100
1101         cur_item: The item (Symbol, Choice, Menu, or Comment) currently being
1102            parsed, or None if we're not parsing an item. Used for recording
1103            references to symbols.
1104
1105         line: The line containing the expression being parsed.
1106
1107         filename (default: None): The file containing the expression.
1108
1109         linenr (default: None): The line number containing the expression.
1110
1111         transform_m (default: False): Determines if 'm' should be rewritten to
1112            'm && MODULES' -- see parse_val_and_cond().
1113
1114         Expression grammar, in decreasing order of precedence:
1115
1116         <expr> -> <symbol>
1117                   <symbol> '=' <symbol>
1118                   <symbol> '!=' <symbol>
1119                   '(' <expr> ')'
1120                   '!' <expr>
1121                   <expr> '&&' <expr>
1122                   <expr> '||' <expr>"""
1123
1124         # Use instance variables to avoid having to pass these as arguments
1125         # through the top-down parser in _parse_expr_rec(), which is tedious
1126         # and obfuscates the code. A profiler run shows no noticeable
1127         # performance difference.
1128         self._cur_item = cur_item
1129         self._transform_m = transform_m
1130         self._line = line
1131         self._filename = filename
1132         self._linenr = linenr
1133
1134         return self._parse_expr_rec(feed)
1135
1136     def _parse_expr_rec(self, feed):
1137         or_term = self._parse_or_term(feed)
1138         if not feed.check(T_OR):
1139             # Common case -- no need for an OR node since it's just a single
1140             # operand
1141             return or_term
1142         or_terms = [or_term, self._parse_or_term(feed)]
1143         while feed.check(T_OR):
1144             or_terms.append(self._parse_or_term(feed))
1145         return (OR, or_terms)
1146
1147     def _parse_or_term(self, feed):
1148         and_term = self._parse_factor(feed)
1149         if not feed.check(T_AND):
1150             # Common case -- no need for an AND node since it's just a single
1151             # operand
1152             return and_term
1153         and_terms = [and_term, self._parse_factor(feed)]
1154         while feed.check(T_AND):
1155             and_terms.append(self._parse_factor(feed))
1156         return (AND, and_terms)
1157
1158     def _parse_factor(self, feed):
1159         token = feed.get_next()
1160
1161         if isinstance(token, (Symbol, str)):
1162             if self._cur_item is not None and isinstance(token, Symbol):
1163                 self._cur_item.referenced_syms.add(token)
1164
1165             next_token = feed.peek_next()
1166             # For conditional expressions ('depends on <expr>',
1167             # '... if <expr>', # etc.), "m" and m are rewritten to
1168             # "m" && MODULES.
1169             if next_token != T_EQUAL and next_token != T_UNEQUAL:
1170                 if self._transform_m and (token is self.m or token == "m"):
1171                     return (AND, ["m", self._sym_lookup("MODULES")])
1172                 return token
1173
1174             relation = EQUAL if (feed.get_next() == T_EQUAL) else UNEQUAL
1175             token_2 = feed.get_next()
1176             if self._cur_item is not None and isinstance(token_2, Symbol):
1177                 self._cur_item.referenced_syms.add(token_2)
1178             return (relation, token, token_2)
1179
1180         if token == T_NOT:
1181             return (NOT, self._parse_factor(feed))
1182
1183         if token == T_OPEN_PAREN:
1184             expr_parse = self._parse_expr_rec(feed)
1185             if not feed.check(T_CLOSE_PAREN):
1186                 _parse_error(self._line, "missing end parenthesis",
1187                              self._filename, self._linenr)
1188             return expr_parse
1189
1190         _parse_error(self._line, "malformed expression", self._filename,
1191                      self._linenr)
1192
1193     def _tokenize(self, s, for_eval, filename=None, linenr=None):
1194         """Returns a _Feed instance containing tokens derived from the string
1195         's'. Registers any new symbols encountered (via _sym_lookup()).
1196
1197         (I experimented with a pure regular expression implementation, but it
1198         came out slower, less readable, and wouldn't have been as flexible.)
1199
1200         for_eval: True when parsing an expression for a call to Config.eval(),
1201            in which case we should not treat the first token specially nor
1202            register new symbols."""
1203
1204         s = s.strip()
1205         if s == "" or s[0] == "#":
1206             return _Feed([])
1207
1208         if for_eval:
1209             previous = None # The previous token seen
1210             tokens = []
1211             i = 0 # The current index in the string being tokenized
1212
1213         else:
1214             # The initial word on a line is parsed specially. Let
1215             # command_chars = [A-Za-z0-9_]. Then
1216             #  - leading non-command_chars characters are ignored, and
1217             #  - the first token consists the following one or more
1218             #    command_chars characters.
1219             # This is why things like "----help--" are accepted.
1220             initial_token_match = _initial_token_re_match(s)
1221             if initial_token_match is None:
1222                 return _Feed([])
1223             keyword = _get_keyword(initial_token_match.group(1))
1224             if keyword == T_HELP:
1225                 # Avoid junk after "help", e.g. "---", being registered as a
1226                 # symbol
1227                 return _Feed([T_HELP])
1228             if keyword is None:
1229                 # We expect a keyword as the first token
1230                 _tokenization_error(s, filename, linenr)
1231
1232             previous = keyword
1233             tokens = [keyword]
1234             # The current index in the string being tokenized
1235             i = initial_token_match.end()
1236
1237         # _tokenize() is a hotspot during parsing, and this speeds things up a
1238         # bit
1239         strlen = len(s)
1240         append = tokens.append
1241
1242         # Main tokenization loop. (Handles tokens past the first one.)
1243         while i < strlen:
1244             # Test for an identifier/keyword preceded by whitespace first; this
1245             # is the most common case.
1246             id_keyword_match = _id_keyword_re_match(s, i)
1247             if id_keyword_match:
1248                 # We have an identifier or keyword. The above also stripped any
1249                 # whitespace for us.
1250                 name = id_keyword_match.group(1)
1251                 # Jump past it
1252                 i = id_keyword_match.end()
1253
1254                 keyword = _get_keyword(name)
1255                 if keyword is not None:
1256                     # It's a keyword
1257                     append(keyword)
1258                 elif previous in STRING_LEX:
1259                     # What would ordinarily be considered an identifier is
1260                     # treated as a string after certain tokens
1261                     append(name)
1262                 else:
1263                     # It's a symbol name. _sym_lookup() will take care of
1264                     # allocating a new Symbol instance if it's the first time
1265                     # we see it.
1266                     sym = self._sym_lookup(name, for_eval)
1267
1268                     if previous == T_CONFIG or previous == T_MENUCONFIG:
1269                         # If the previous token is T_(MENU)CONFIG
1270                         # ("(menu)config"), we're tokenizing the first line of
1271                         # a symbol definition, and should remember this as a
1272                         # location where the symbol is defined
1273                         sym.def_locations.append((filename, linenr))
1274                     else:
1275                         # Otherwise, it's a reference to the symbol
1276                         sym.ref_locations.append((filename, linenr))
1277
1278                     append(sym)
1279
1280             else:
1281                 # Not an identifier/keyword
1282
1283                 while i < strlen and s[i].isspace():
1284                     i += 1
1285                 if i == strlen:
1286                     break
1287                 c = s[i]
1288                 i += 1
1289
1290                 # String literal (constant symbol)
1291                 if c == '"' or c == "'":
1292                     if "\\" in s:
1293                         # Slow path: This could probably be sped up, but it's a
1294                         # very unusual case anyway.
1295                         quote = c
1296                         val = ""
1297                         while 1:
1298                             if i >= len(s):
1299                                 _tokenization_error(s, filename, linenr)
1300                             c = s[i]
1301                             if c == quote:
1302                                 break
1303                             if c == "\\":
1304                                 if i + 1 >= len(s):
1305                                     _tokenization_error(s, filename, linenr)
1306                                 val += s[i + 1]
1307                                 i += 2
1308                             else:
1309                                 val += c
1310                                 i += 1
1311                         i += 1
1312                         append(val)
1313                     else:
1314                         # Fast path: If the string contains no backslashes
1315                         # (almost always) we can simply look for the matching
1316                         # quote.
1317                         end = s.find(c, i)
1318                         if end == -1:
1319                             _tokenization_error(s, filename, linenr)
1320                         append(s[i:end])
1321                         i = end + 1
1322
1323                 elif c == "&":
1324                     # Invalid characters are ignored
1325                     if i >= len(s) or s[i] != "&": continue
1326                     append(T_AND)
1327                     i += 1
1328
1329                 elif c == "|":
1330                     # Invalid characters are ignored
1331                     if i >= len(s) or s[i] != "|": continue
1332                     append(T_OR)
1333                     i += 1
1334
1335                 elif c == "!":
1336                     if i < len(s) and s[i] == "=":
1337                         append(T_UNEQUAL)
1338                         i += 1
1339                     else:
1340                         append(T_NOT)
1341
1342                 elif c == "=": append(T_EQUAL)
1343                 elif c == "(": append(T_OPEN_PAREN)
1344                 elif c == ")": append(T_CLOSE_PAREN)
1345                 elif c == "#": break # Comment
1346
1347                 else: continue # Invalid characters are ignored
1348
1349             previous = tokens[-1]
1350
1351         return _Feed(tokens)
1352
1353     def _sym_lookup(self, name, for_eval=False):
1354         """Fetches the symbol 'name' from the symbol table, creating and
1355         registering it if it does not exist. If 'for_eval' is True, the symbol
1356         won't be added to the symbol table if it does not exist -- this is for
1357         Config.eval()."""
1358         if name in self.syms:
1359             return self.syms[name]
1360
1361         new_sym = Symbol()
1362         new_sym.config = self
1363         new_sym.name = name
1364         if for_eval:
1365             self._warn("no symbol {0} in configuration".format(name))
1366         else:
1367             self.syms[name] = new_sym
1368         return new_sym
1369
1370     #
1371     # Expression evaluation
1372     #
1373
1374     def _eval_expr(self, expr):
1375         """Evaluates an expression to "n", "m", or "y"."""
1376
1377         # Handles e.g. an "x if y" condition where the "if y" part is missing.
1378         if expr is None:
1379             return "y"
1380
1381         res = self._eval_expr_rec(expr)
1382         if res == "m":
1383             # Promote "m" to "y" if we're running without modules.
1384             #
1385             # Internally, "m" is often rewritten to "m" && MODULES by both the
1386             # C implementation and Kconfiglib, which takes care of cases where
1387             # "m" should be demoted to "n" instead.
1388             modules_sym = self.syms.get("MODULES")
1389             if modules_sym is None or modules_sym.get_value() != "y":
1390                 return "y"
1391         return res
1392
1393     def _eval_expr_rec(self, expr):
1394         if isinstance(expr, Symbol):
1395             # Non-bool/tristate symbols are always "n" in a tristate sense,
1396             # regardless of their value
1397             if expr.type != BOOL and expr.type != TRISTATE:
1398                 return "n"
1399             return expr.get_value()
1400
1401         if isinstance(expr, str):
1402             return expr if (expr == "y" or expr == "m") else "n"
1403
1404         # Ordered by frequency
1405
1406         if expr[0] == AND:
1407             res = "y"
1408             for subexpr in expr[1]:
1409                 ev = self._eval_expr_rec(subexpr)
1410                 # Return immediately upon discovering an "n" term
1411                 if ev == "n":
1412                     return "n"
1413                 if ev == "m":
1414                     res = "m"
1415             # 'res' is either "m" or "y" here; we already handled the
1416             # short-circuiting "n" case in the loop.
1417             return res
1418
1419         if expr[0] == NOT:
1420             ev = self._eval_expr_rec(expr[1])
1421             if ev == "y":
1422                 return "n"
1423             return "y" if (ev == "n") else "m"
1424
1425         if expr[0] == OR:
1426             res = "n"
1427             for subexpr in expr[1]:
1428                 ev = self._eval_expr_rec(subexpr)
1429                 # Return immediately upon discovering a "y" term
1430                 if ev == "y":
1431                     return "y"
1432                 if ev == "m":
1433                     res = "m"
1434             # 'res' is either "n" or "m" here; we already handled the
1435             # short-circuiting "y" case in the loop.
1436             return res
1437
1438         if expr[0] == EQUAL:
1439             return "y" if (_str_val(expr[1]) == _str_val(expr[2])) else "n"
1440
1441         if expr[0] == UNEQUAL:
1442             return "y" if (_str_val(expr[1]) != _str_val(expr[2])) else "n"
1443
1444         _internal_error("Internal error while evaluating expression: "
1445                         "unknown operation {0}.".format(expr[0]))
1446
1447     def _eval_min(self, e1, e2):
1448         """Returns the minimum value of the two expressions. Equates None with
1449         'y'."""
1450         e1_eval = self._eval_expr(e1)
1451         e2_eval = self._eval_expr(e2)
1452         return e1_eval if tri_less(e1_eval, e2_eval) else e2_eval
1453
1454     def _eval_max(self, e1, e2):
1455         """Returns the maximum value of the two expressions. Equates None with
1456         'y'."""
1457         e1_eval = self._eval_expr(e1)
1458         e2_eval = self._eval_expr(e2)
1459         return e1_eval if tri_greater(e1_eval, e2_eval) else e2_eval
1460
1461     #
1462     # Dependency tracking (for caching and invalidation)
1463     #
1464
1465     def _build_dep(self):
1466         """Populates the Symbol.dep sets, linking the symbol to the symbols
1467         that immediately depend on it in the sense that changing the value of
1468         the symbol might affect the values of those other symbols. This is used
1469         for caching/invalidation purposes. The calculated sets might be larger
1470         than necessary as we don't do any complicated analysis of the
1471         expressions."""
1472
1473         # Adds 'sym' as a directly dependent symbol to all symbols that appear
1474         # in the expression 'e'
1475         def add_expr_deps(e, sym):
1476             for s in _get_expr_syms(e):
1477                 s.dep.add(sym)
1478
1479         # The directly dependent symbols of a symbol are:
1480         #  - Any symbols whose prompts, default values, rev_dep (select
1481         #    condition), or ranges depend on the symbol
1482         #  - Any symbols that belong to the same choice statement as the symbol
1483         #    (these won't be included in 'dep' as that makes the dependency
1484         #    graph unwieldy, but Symbol._get_dependent() will include them)
1485         #  - Any symbols in a choice statement that depends on the symbol
1486         for sym in self.syms_iter():
1487             for _, e in sym.prompts:
1488                 add_expr_deps(e, sym)
1489
1490             for v, e in sym.def_exprs:
1491                 add_expr_deps(v, sym)
1492                 add_expr_deps(e, sym)
1493
1494             add_expr_deps(sym.rev_dep, sym)
1495
1496             for l, u, e in sym.ranges:
1497                 add_expr_deps(l, sym)
1498                 add_expr_deps(u, sym)
1499                 add_expr_deps(e, sym)
1500
1501             if sym.is_choice_sym:
1502                 choice = sym.parent
1503                 for _, e in choice.prompts:
1504                     add_expr_deps(e, sym)
1505                 for _, e in choice.def_exprs:
1506                     add_expr_deps(e, sym)
1507
1508     def _eq_to_sym(self, eq):
1509         """_expr_depends_on() helper. For (in)equalities of the form sym = y/m
1510         or sym != n, returns sym. For other (in)equalities, returns None."""
1511         relation, left, right = eq
1512
1513         def transform_y_m_n(item):
1514             if item is self.y: return "y"
1515             if item is self.m: return "m"
1516             if item is self.n: return "n"
1517             return item
1518
1519         left = transform_y_m_n(left)
1520         right = transform_y_m_n(right)
1521
1522         # Make sure the symbol (if any) appears to the left
1523         if not isinstance(left, Symbol):
1524             left, right = right, left
1525         if not isinstance(left, Symbol):
1526             return None
1527         if (relation == EQUAL and (right == "y" or right == "m")) or \
1528            (relation == UNEQUAL and right == "n"):
1529             return left
1530         return None
1531
1532     def _expr_depends_on(self, expr, sym):
1533         """Reimplementation of expr_depends_symbol() from mconf.c. Used to
1534         determine if a submenu should be implicitly created, which influences
1535         what items inside choice statements are considered choice items."""
1536         if expr is None:
1537             return False
1538
1539         def rec(expr):
1540             if isinstance(expr, str):
1541                 return False
1542             if isinstance(expr, Symbol):
1543                 return expr is sym
1544
1545             if expr[0] in (EQUAL, UNEQUAL):
1546                 return self._eq_to_sym(expr) is sym
1547             if expr[0] == AND:
1548                 for and_expr in expr[1]:
1549                     if rec(and_expr):
1550                         return True
1551             return False
1552
1553         return rec(expr)
1554
1555     def _invalidate_all(self):
1556         for sym in self.syms_iter():
1557             sym._invalidate()
1558
1559     #
1560     # Printing and misc.
1561     #
1562
1563     def _expand_sym_refs(self, s):
1564         """Expands $-references to symbols in 's' to symbol values, or to the
1565         empty string for undefined symbols."""
1566
1567         while 1:
1568             sym_ref_match = _sym_ref_re_search(s)
1569             if sym_ref_match is None:
1570                 return s
1571
1572             sym_name = sym_ref_match.group(0)[1:]
1573             sym = self.syms.get(sym_name)
1574             expansion = "" if sym is None else sym.get_value()
1575
1576             s = s[:sym_ref_match.start()] + \
1577                 expansion + \
1578                 s[sym_ref_match.end():]
1579
1580     def _expr_val_str(self, expr, no_value_str="(none)",
1581                       get_val_instead_of_eval=False):
1582         """Printing helper. Returns a string with 'expr' and its value.
1583
1584         no_value_str: String to return when 'expr' is missing (None).
1585
1586         get_val_instead_of_eval: Assume 'expr' is a symbol or string (constant
1587           symbol) and get its value directly instead of evaluating it to a
1588           tristate value."""
1589
1590         if expr is None:
1591             return no_value_str
1592
1593         if get_val_instead_of_eval:
1594             if isinstance(expr, str):
1595                 return _expr_to_str(expr)
1596             val = expr.get_value()
1597         else:
1598             val = self._eval_expr(expr)
1599
1600         return "{0} (value: {1})".format(_expr_to_str(expr), _expr_to_str(val))
1601
1602     def _get_sym_or_choice_str(self, sc):
1603         """Symbols and choices have many properties in common, so we factor out
1604         common __str__() stuff here. "sc" is short for "symbol or choice"."""
1605
1606         # As we deal a lot with string representations here, use some
1607         # convenient shorthand:
1608         s = _expr_to_str
1609
1610         #
1611         # Common symbol/choice properties
1612         #
1613
1614         user_val_str = "(no user value)" if sc.user_val is None else \
1615                        s(sc.user_val)
1616
1617         # Build prompts string
1618         if not sc.prompts:
1619             prompts_str = " (no prompts)"
1620         else:
1621             prompts_str_rows = []
1622             for prompt, cond_expr in sc.orig_prompts:
1623                 if cond_expr is None:
1624                     prompts_str_rows.append(' "{0}"'.format(prompt))
1625                 else:
1626                     prompts_str_rows.append(
1627                       ' "{0}" if {1}'.format(prompt,
1628                                              self._expr_val_str(cond_expr)))
1629             prompts_str = "\n".join(prompts_str_rows)
1630
1631         # Build locations string
1632         if not sc.def_locations:
1633             locations_str = "(no locations)"
1634         else:
1635             locations_str = " ".join(["{0}:{1}".format(filename, linenr) for
1636                                       (filename, linenr) in sc.def_locations])
1637
1638         # Build additional-dependencies-from-menus-and-ifs string
1639         additional_deps_str = " " + \
1640           self._expr_val_str(sc.deps_from_containing,
1641                              "(no additional dependencies)")
1642
1643         #
1644         # Symbol-specific stuff
1645         #
1646
1647         if isinstance(sc, Symbol):
1648             # Build ranges string
1649             if isinstance(sc, Symbol):
1650                 if not sc.ranges:
1651                     ranges_str = " (no ranges)"
1652                 else:
1653                     ranges_str_rows = []
1654                     for l, u, cond_expr in sc.ranges:
1655                         if cond_expr is None:
1656                             ranges_str_rows.append(" [{0}, {1}]".format(s(l),
1657                                                                         s(u)))
1658                         else:
1659                             ranges_str_rows.append(" [{0}, {1}] if {2}"
1660                               .format(s(l), s(u),
1661                                       self._expr_val_str(cond_expr)))
1662                     ranges_str = "\n".join(ranges_str_rows)
1663
1664             # Build default values string
1665             if not sc.def_exprs:
1666                 defaults_str = " (no default values)"
1667             else:
1668                 defaults_str_rows = []
1669                 for val_expr, cond_expr in sc.orig_def_exprs:
1670                     row_str = " " + self._expr_val_str(val_expr, "(none)",
1671                                                        sc.type == STRING)
1672                     defaults_str_rows.append(row_str)
1673                     defaults_str_rows.append("  Condition: " +
1674                                                self._expr_val_str(cond_expr))
1675                 defaults_str = "\n".join(defaults_str_rows)
1676
1677             # Build selects string
1678             if not sc.orig_selects:
1679                 selects_str = " (no selects)"
1680             else:
1681                 selects_str_rows = []
1682                 for target, cond_expr in sc.orig_selects:
1683                     if cond_expr is None:
1684                         selects_str_rows.append(" {0}".format(target.name))
1685                     else:
1686                         selects_str_rows.append(
1687                           " {0} if {1}".format(target.name,
1688                                                self._expr_val_str(cond_expr)))
1689                 selects_str = "\n".join(selects_str_rows)
1690
1691             res = _lines("Symbol " +
1692                            ("(no name)" if sc.name is None else sc.name),
1693                          "Type           : " + TYPENAME[sc.type],
1694                          "Value          : " + s(sc.get_value()),
1695                          "User value     : " + user_val_str,
1696                          "Visibility     : " + s(_get_visibility(sc)),
1697                          "Is choice item : " + BOOL_STR[sc.is_choice_sym],
1698                          "Is defined     : " + BOOL_STR[sc.is_defined_],
1699                          "Is from env.   : " + BOOL_STR[sc.is_from_env],
1700                          "Is special     : " + BOOL_STR[sc.is_special_] + "\n")
1701             if sc.ranges:
1702                 res += _lines("Ranges:", ranges_str + "\n")
1703             res += _lines("Prompts:",
1704                           prompts_str,
1705                           "Default values:",
1706                           defaults_str,
1707                           "Selects:",
1708                           selects_str,
1709                           "Reverse (select-related) dependencies:",
1710                           " (no reverse dependencies)" if sc.rev_dep == "n"
1711                             else " " + self._expr_val_str(sc.rev_dep),
1712                           "Additional dependencies from enclosing menus "
1713                             "and ifs:",
1714                           additional_deps_str,
1715                           "Locations: " + locations_str)
1716
1717             return res
1718
1719         #
1720         # Choice-specific stuff
1721         #
1722
1723         # Build selected symbol string
1724         sel = sc.get_selection()
1725         sel_str = "(no selection)" if sel is None else sel.name
1726
1727         # Build default values string
1728         if not sc.def_exprs:
1729             defaults_str = " (no default values)"
1730         else:
1731             defaults_str_rows = []
1732             for sym, cond_expr in sc.orig_def_exprs:
1733                 if cond_expr is None:
1734                     defaults_str_rows.append(" {0}".format(sym.name))
1735                 else:
1736                     defaults_str_rows.append(" {0} if {1}".format(sym.name,
1737                                                 self._expr_val_str(cond_expr)))
1738             defaults_str = "\n".join(defaults_str_rows)
1739
1740         # Build contained symbols string
1741         names = [sym.name for sym in sc.actual_symbols]
1742         syms_string = " ".join(names) if names else "(empty)"
1743
1744         return _lines("Choice",
1745                       "Name (for named choices): " +
1746                         ("(no name)" if sc.name is None else sc.name),
1747                       "Type            : " + TYPENAME[sc.type],
1748                       "Selected symbol : " + sel_str,
1749                       "User value      : " + user_val_str,
1750                       "Mode            : " + s(sc.get_mode()),
1751                       "Visibility      : " + s(_get_visibility(sc)),
1752                       "Optional        : " + BOOL_STR[sc.optional],
1753                       "Prompts:",
1754                       prompts_str,
1755                       "Defaults:",
1756                       defaults_str,
1757                       "Choice symbols:",
1758                       " " + syms_string,
1759                       "Additional dependencies from enclosing menus and "
1760                         "ifs:",
1761                       additional_deps_str,
1762                       "Locations: " + locations_str)
1763
1764     def _warn(self, msg, filename=None, linenr=None):
1765         """For printing warnings to stderr."""
1766         if self.print_warnings:
1767             _stderr_msg("warning: " + msg, filename, linenr)
1768
1769 class Item(object):
1770
1771     """Base class for symbols and other Kconfig constructs. Subclasses are
1772     Symbol, Choice, Menu, and Comment."""
1773
1774     def is_symbol(self):
1775         """Returns True if the item is a symbol. Short for
1776         isinstance(item, kconfiglib.Symbol)."""
1777         return isinstance(self, Symbol)
1778
1779     def is_choice(self):
1780         """Returns True if the item is a choice. Short for
1781         isinstance(item, kconfiglib.Choice)."""
1782         return isinstance(self, Choice)
1783
1784     def is_menu(self):
1785         """Returns True if the item is a menu. Short for
1786         isinstance(item, kconfiglib.Menu)."""
1787         return isinstance(self, Menu)
1788
1789     def is_comment(self):
1790         """Returns True if the item is a comment. Short for
1791         isinstance(item, kconfiglib.Comment)."""
1792         return isinstance(self, Comment)
1793
1794 class Symbol(Item):
1795
1796     """Represents a configuration symbol - e.g. FOO for
1797
1798     config FOO
1799         ..."""
1800
1801     #
1802     # Public interface
1803     #
1804
1805     def get_config(self):
1806         """Returns the Config instance this symbol is from."""
1807         return self.config
1808
1809     def get_name(self):
1810         """Returns the name of the symbol."""
1811         return self.name
1812
1813     def get_type(self):
1814         """Returns the type of the symbol: one of UNKNOWN, BOOL, TRISTATE,
1815         STRING, HEX, or INT. These are defined at the top level of the module,
1816         so you'd do something like
1817
1818         if sym.get_type() == kconfiglib.STRING:
1819             ..."""
1820         return self.type
1821
1822     def get_prompts(self):
1823         """Returns a list of prompts defined for the symbol, in the order they
1824         appear in the configuration files. Returns the empty list for symbols
1825         with no prompt.
1826
1827         This list will have a single entry for the vast majority of symbols
1828         having prompts, but having multiple prompts for a single symbol is
1829         possible through having multiple 'config' entries for it."""
1830         return [prompt for prompt, _ in self.orig_prompts]
1831
1832     def get_help(self):
1833         """Returns the help text of the symbol, or None if the symbol has no
1834         help text."""
1835         return self.help
1836
1837     def get_parent(self):
1838         """Returns the menu or choice statement that contains the symbol, or
1839         None if the symbol is at the top level. Note that if statements are
1840         treated as syntactic and do not have an explicit class
1841         representation."""
1842         return self.parent
1843
1844     def get_def_locations(self):
1845         """Returns a list of (filename, linenr) tuples, where filename (string)
1846         and linenr (int) represent a location where the symbol is defined. For
1847         the vast majority of symbols this list will only contain one element.
1848         For the following Kconfig, FOO would get two entries: the lines marked
1849         with *.
1850
1851         config FOO *
1852             bool "foo prompt 1"
1853
1854         config FOO *
1855             bool "foo prompt 2"
1856         """
1857         return self.def_locations
1858
1859     def get_ref_locations(self):
1860         """Returns a list of (filename, linenr) tuples, where filename (string)
1861         and linenr (int) represent a location where the symbol is referenced in
1862         the configuration. For example, the lines marked by * would be included
1863         for FOO below:
1864
1865         config A
1866             bool
1867             default BAR || FOO *
1868
1869         config B
1870             tristate
1871             depends on FOO *
1872             default m if FOO *
1873
1874         if FOO *
1875             config A
1876                 bool "A"
1877         endif
1878
1879         config FOO (definition not included)
1880             bool
1881         """
1882         return self.ref_locations
1883
1884     def get_value(self):
1885         """Calculate and return the value of the symbol. See also
1886         Symbol.set_user_value()."""
1887
1888         if self.cached_val is not None:
1889             return self.cached_val
1890
1891         # As a quirk of Kconfig, undefined symbols get their name as their
1892         # value. This is why things like "FOO = bar" work for seeing if FOO has
1893         # the value "bar".
1894         if self.type == UNKNOWN:
1895             self.cached_val = self.name
1896             return self.name
1897
1898         new_val = DEFAULT_VALUE[self.type]
1899         vis = _get_visibility(self)
1900
1901         # This is easiest to calculate together with the value
1902         self.write_to_conf = False
1903
1904         if self.type == BOOL or self.type == TRISTATE:
1905             # The visibility and mode (modules-only or single-selection) of
1906             # choice items will be taken into account in _get_visibility()
1907             if self.is_choice_sym:
1908                 if vis != "n":
1909                     choice = self.parent
1910                     mode = choice.get_mode()
1911
1912                     self.write_to_conf = (mode != "n")
1913
1914                     if mode == "y":
1915                         if choice.get_selection() is self:
1916                             new_val = "y"
1917                         else:
1918                             new_val = "n"
1919                     elif mode == "m":
1920                         if self.user_val == "m" or self.user_val == "y":
1921                             new_val = "m"
1922
1923             else:
1924                 # If the symbol is visible and has a user value, use that.
1925                 # Otherwise, look at defaults.
1926                 use_defaults = True
1927
1928                 if vis != "n":
1929                     self.write_to_conf = True
1930                     if self.user_val is not None:
1931                         new_val = self.config._eval_min(self.user_val, vis)
1932                         use_defaults = False
1933
1934                 if use_defaults:
1935                     for val_expr, cond_expr in self.def_exprs:
1936                         cond_eval = self.config._eval_expr(cond_expr)
1937                         if cond_eval != "n":
1938                             self.write_to_conf = True
1939                             new_val = self.config._eval_min(val_expr,
1940                                                             cond_eval)
1941                             break
1942
1943                 # Reverse (select-related) dependencies take precedence
1944                 rev_dep_val = self.config._eval_expr(self.rev_dep)
1945                 if rev_dep_val != "n":
1946                     self.write_to_conf = True
1947                     new_val = self.config._eval_max(new_val, rev_dep_val)
1948
1949             # Promote "m" to "y" for booleans
1950             if new_val == "m" and self.type == BOOL:
1951                 new_val = "y"
1952
1953         elif self.type == INT or self.type == HEX:
1954             has_active_range = False
1955             low = None
1956             high = None
1957             use_defaults = True
1958
1959             base = 16 if self.type == HEX else 10
1960
1961             for l, h, cond_expr in self.ranges:
1962                 if self.config._eval_expr(cond_expr) != "n":
1963                     has_active_range = True
1964
1965                     low_str = _str_val(l)
1966                     high_str = _str_val(h)
1967                     low = int(low_str, base) if \
1968                       _is_base_n(low_str, base) else 0
1969                     high = int(high_str, base) if \
1970                       _is_base_n(high_str, base) else 0
1971
1972                     break
1973
1974             if vis != "n":
1975                 self.write_to_conf = True
1976
1977                 if self.user_val is not None and \
1978                    _is_base_n(self.user_val, base) and \
1979                    (not has_active_range or
1980                     low <= int(self.user_val, base) <= high):
1981
1982                     # If the user value is OK, it is stored in exactly the same
1983                     # form as specified in the assignment (with or without
1984                     # "0x", etc).
1985
1986                     use_defaults = False
1987                     new_val = self.user_val
1988
1989             if use_defaults:
1990                 for val_expr, cond_expr in self.def_exprs:
1991                     if self.config._eval_expr(cond_expr) != "n":
1992                         self.write_to_conf = True
1993
1994                         # If the default value is OK, it is stored in exactly
1995                         # the same form as specified. Otherwise, it is clamped
1996                         # to the range, and the output has "0x" as appropriate
1997                         # for the type.
1998
1999                         new_val = _str_val(val_expr)
2000
2001                         if _is_base_n(new_val, base):
2002                             new_val_num = int(new_val, base)
2003                             if has_active_range:
2004                                 clamped_val = None
2005
2006                                 if new_val_num < low:
2007                                     clamped_val = low
2008                                 elif new_val_num > high:
2009                                     clamped_val = high
2010
2011                                 if clamped_val is not None:
2012                                     new_val = (hex(clamped_val) if \
2013                                       self.type == HEX else str(clamped_val))
2014
2015                             break
2016                 else: # For the for loop
2017                     # If no user value or default kicks in but the hex/int has
2018                     # an active range, then the low end of the range is used,
2019                     # provided it's > 0, with "0x" prepended as appropriate.
2020                     if has_active_range and low > 0:
2021                         new_val = (hex(low) if self.type == HEX else str(low))
2022
2023         elif self.type == STRING:
2024             use_defaults = True
2025
2026             if vis != "n":
2027                 self.write_to_conf = True
2028                 if self.user_val is not None:
2029                     new_val = self.user_val
2030                     use_defaults = False
2031
2032             if use_defaults:
2033                 for val_expr, cond_expr in self.def_exprs:
2034                     if self.config._eval_expr(cond_expr) != "n":
2035                         self.write_to_conf = True
2036                         new_val = _str_val(val_expr)
2037                         break
2038
2039         self.cached_val = new_val
2040         return new_val
2041
2042     def get_user_value(self):
2043         """Returns the value assigned to the symbol in a .config or via
2044         Symbol.set_user_value() (provided the value was valid for the type of
2045         the symbol). Returns None in case of no user value."""
2046         return self.user_val
2047
2048     def get_upper_bound(self):
2049         """For string/hex/int symbols and for bool and tristate symbols that
2050         cannot be modified (see is_modifiable()), returns None.
2051
2052         Otherwise, returns the highest value the symbol can be set to with
2053         Symbol.set_user_value() (that will not be truncated): one of "m" or
2054         "y", arranged from lowest to highest. This corresponds to the highest
2055         value the symbol could be given in e.g. the 'make menuconfig'
2056         interface.
2057
2058         See also the tri_less*() and tri_greater*() functions, which could come
2059         in handy."""
2060         if self.type != BOOL and self.type != TRISTATE:
2061             return None
2062         rev_dep = self.config._eval_expr(self.rev_dep)
2063         # A bool selected to "m" gets promoted to "y", pinning it
2064         if rev_dep == "m" and self.type == BOOL:
2065             return None
2066         vis = _get_visibility(self)
2067         if TRI_TO_INT[vis] > TRI_TO_INT[rev_dep]:
2068             return vis
2069         return None
2070
2071     def get_lower_bound(self):
2072         """For string/hex/int symbols and for bool and tristate symbols that
2073         cannot be modified (see is_modifiable()), returns None.
2074
2075         Otherwise, returns the lowest value the symbol can be set to with
2076         Symbol.set_user_value() (that will not be truncated): one of "n" or
2077         "m", arranged from lowest to highest. This corresponds to the lowest
2078         value the symbol could be given in e.g. the 'make menuconfig'
2079         interface.
2080
2081         See also the tri_less*() and tri_greater*() functions, which could come
2082         in handy."""
2083         if self.type != BOOL and self.type != TRISTATE:
2084             return None
2085         rev_dep = self.config._eval_expr(self.rev_dep)
2086         # A bool selected to "m" gets promoted to "y", pinning it
2087         if rev_dep == "m" and self.type == BOOL:
2088             return None
2089         if TRI_TO_INT[_get_visibility(self)] > TRI_TO_INT[rev_dep]:
2090             return rev_dep
2091         return None
2092
2093     def get_assignable_values(self):
2094         """For string/hex/int symbols and for bool and tristate symbols that
2095         cannot be modified (see is_modifiable()), returns the empty list.
2096
2097         Otherwise, returns a list containing the user values that can be
2098         assigned to the symbol (that won't be truncated). Usage example:
2099
2100         if "m" in sym.get_assignable_values():
2101             sym.set_user_value("m")
2102
2103         This is basically a more convenient interface to
2104         get_lower/upper_bound() when wanting to test if a particular tristate
2105         value can be assigned."""
2106         if self.type != BOOL and self.type != TRISTATE:
2107             return []
2108         rev_dep = self.config._eval_expr(self.rev_dep)
2109         # A bool selected to "m" gets promoted to "y", pinning it
2110         if rev_dep == "m" and self.type == BOOL:
2111             return []
2112         res = ["n", "m", "y"][TRI_TO_INT[rev_dep] :
2113                               TRI_TO_INT[_get_visibility(self)] + 1]
2114         return res if len(res) > 1 else []
2115
2116     def get_visibility(self):
2117         """Returns the visibility of the symbol: one of "n", "m" or "y". For
2118         bool and tristate symbols, this is an upper bound on the value users
2119         can set for the symbol. For other types of symbols, a visibility of "n"
2120         means the user value will be ignored. A visibility of "n" corresponds
2121         to not being visible in the 'make *config' interfaces.
2122
2123         Example (assuming we're running with modules enabled -- i.e., MODULES
2124         set to 'y'):
2125
2126         # Assume this has been assigned 'n'
2127         config N_SYM
2128             tristate "N_SYM"
2129
2130         # Assume this has been assigned 'm'
2131         config M_SYM
2132             tristate "M_SYM"
2133
2134         # Has visibility 'n'
2135         config A
2136             tristate "A"
2137             depends on N_SYM
2138
2139         # Has visibility 'm'
2140         config B
2141             tristate "B"
2142             depends on M_SYM
2143
2144         # Has visibility 'y'
2145         config C
2146             tristate "C"
2147
2148         # Has no prompt, and hence visibility 'n'
2149         config D
2150             tristate
2151
2152         Having visibility be tri-valued ensures that e.g. a symbol cannot be
2153         set to "y" by the user if it depends on a symbol with value "m", which
2154         wouldn't be safe.
2155
2156         You should probably look at get_lower/upper_bound(),
2157         get_assignable_values() and is_modifiable() before using this."""
2158         return _get_visibility(self)
2159
2160     def get_referenced_symbols(self, refs_from_enclosing=False):
2161         """Returns the set() of all symbols referenced by this symbol. For
2162         example, the symbol defined by
2163
2164         config FOO
2165             bool
2166             prompt "foo" if A && B
2167             default C if D
2168             depends on E
2169             select F if G
2170
2171         references the symbols A through G.
2172
2173         refs_from_enclosing (default: False): If True, the symbols referenced
2174            by enclosing menus and ifs will be included in the result."""
2175         return self.all_referenced_syms if refs_from_enclosing else \
2176                self.referenced_syms
2177
2178     def get_selected_symbols(self):
2179         """Returns the set() of all symbols X for which this symbol has a
2180         'select X' or 'select X if Y' (regardless of whether Y is satisfied or
2181         not). This is a subset of the symbols returned by
2182         get_referenced_symbols()."""
2183         return self.selected_syms
2184
2185     def set_user_value(self, v):
2186         """Sets the user value of the symbol.
2187
2188         Equal in effect to assigning the value to the symbol within a .config
2189         file. Use get_lower/upper_bound() or get_assignable_values() to find
2190         the range of currently assignable values for bool and tristate symbols;
2191         setting values outside this range will cause the user value to differ
2192         from the result of Symbol.get_value() (be truncated). Values that are
2193         invalid for the type (such as a_bool.set_user_value("foo")) are
2194         ignored, and a warning is emitted if an attempt is made to assign such
2195         a value.
2196
2197         For any type of symbol, is_modifiable() can be used to check if a user
2198         value will currently have any effect on the symbol, as determined by
2199         its visibility and range of assignable values. Any value that is valid
2200         for the type (bool, tristate, etc.) will end up being reflected in
2201         get_user_value() though, and might have an effect later if conditions
2202         change. To get rid of the user value, use unset_user_value().
2203
2204         Any symbols dependent on the symbol are (recursively) invalidated, so
2205         things will just work with regards to dependencies.
2206
2207         v: The user value to give to the symbol."""
2208         self._set_user_value_no_invalidate(v, False)
2209
2210         # There might be something more efficient you could do here, but play
2211         # it safe.
2212         if self.name == "MODULES":
2213             self.config._invalidate_all()
2214             return
2215
2216         self._invalidate()
2217         self._invalidate_dependent()
2218
2219     def unset_user_value(self):
2220         """Resets the user value of the symbol, as if the symbol had never
2221         gotten a user value via Config.load_config() or
2222         Symbol.set_user_value()."""
2223         self._unset_user_value_no_recursive_invalidate()
2224         self._invalidate_dependent()
2225
2226     def is_modifiable(self):
2227         """Returns True if the value of the symbol could be modified by calling
2228         Symbol.set_user_value().
2229
2230         For bools and tristates, this corresponds to the symbol being visible
2231         in the 'make menuconfig' interface and not already being pinned to a
2232         specific value (e.g. because it is selected by another symbol).
2233
2234         For strings and numbers, this corresponds to just being visible. (See
2235         Symbol.get_visibility().)"""
2236         if self.is_special_:
2237             return False
2238         if self.type == BOOL or self.type == TRISTATE:
2239             rev_dep = self.config._eval_expr(self.rev_dep)
2240             # A bool selected to "m" gets promoted to "y", pinning it
2241             if rev_dep == "m" and self.type == BOOL:
2242                 return False
2243             return TRI_TO_INT[_get_visibility(self)] > TRI_TO_INT[rev_dep]
2244         return _get_visibility(self) != "n"
2245
2246     def is_defined(self):
2247         """Returns False if the symbol is referred to in the Kconfig but never
2248         actually defined."""
2249         return self.is_defined_
2250
2251     def is_special(self):
2252         """Returns True if the symbol is one of the special symbols n, m, y, or
2253         UNAME_RELEASE, or gets its value from the environment."""
2254         return self.is_special_
2255
2256     def is_from_environment(self):
2257         """Returns True if the symbol gets its value from the environment."""
2258         return self.is_from_env
2259
2260     def has_ranges(self):
2261         """Returns True if the symbol is of type INT or HEX and has ranges that
2262         limit what values it can take on."""
2263         return bool(self.ranges)
2264
2265     def is_choice_symbol(self):
2266         """Returns True if the symbol is in a choice statement and is an actual
2267         choice symbol (see Choice.get_symbols())."""
2268         return self.is_choice_sym
2269
2270     def is_choice_selection(self):
2271         """Returns True if the symbol is contained in a choice statement and is
2272         the selected item. Equivalent to
2273
2274         sym.is_choice_symbol() and sym.get_parent().get_selection() is sym"""
2275         return self.is_choice_sym and self.parent.get_selection() is self
2276
2277     def is_allnoconfig_y(self):
2278         """Returns True if the symbol has the 'allnoconfig_y' option set."""
2279         return self.allnoconfig_y
2280
2281     def __str__(self):
2282         """Returns a string containing various information about the symbol."""
2283         return self.config._get_sym_or_choice_str(self)
2284
2285     #
2286     # Private methods
2287     #
2288
2289     def __init__(self):
2290         """Symbol constructor -- not intended to be called directly by
2291         Kconfiglib clients."""
2292
2293         self.name = None
2294         self.type = UNKNOWN
2295         self.prompts = []
2296         self.def_exprs = [] # 'default' properties
2297         self.ranges = [] # 'range' properties (for int and hex)
2298         self.help = None # Help text
2299         self.rev_dep = "n" # Reverse (select-related) dependencies
2300         self.config = None
2301         self.parent = None
2302
2303         self.user_val = None # Value set by user
2304
2305         # The prompt, default value and select conditions without any
2306         # dependencies from menus and ifs propagated to them
2307         self.orig_prompts = []
2308         self.orig_def_exprs = []
2309         self.orig_selects = []
2310
2311         # Dependencies inherited from containing menus and ifs
2312         self.deps_from_containing = None
2313         # The set of symbols referenced by this symbol (see
2314         # get_referenced_symbols())
2315         self.referenced_syms = set()
2316         # The set of symbols selected by this symbol (see
2317         # get_selected_symbols())
2318         self.selected_syms = set()
2319         # Like 'referenced_syms', but includes symbols from
2320         # dependencies inherited from enclosing menus and ifs
2321         self.all_referenced_syms = set()
2322
2323         # This records only dependencies specified with 'depends on'. Needed
2324         # when determining actual choice items (hrrrr...). See also
2325         # Choice._determine_actual_symbols().
2326         self.menu_dep = None
2327
2328         # See Symbol.get_ref/def_locations().
2329         self.def_locations = []
2330         self.ref_locations = []
2331
2332         # Populated in Config._build_dep() after parsing. Links the symbol to
2333         # the symbols that immediately depend on it (in a caching/invalidation
2334         # sense). The total set of dependent symbols for the symbol (the
2335         # transitive closure) is calculated on an as-needed basis in
2336         # _get_dependent().
2337         self.dep = set()
2338
2339         # Cached values
2340
2341         # Caches the calculated value
2342         self.cached_val = None
2343         # Caches the visibility, which acts as an upper bound on the value
2344         self.cached_visibility = None
2345         # Caches the total list of dependent symbols. Calculated in
2346         # _get_dependent().
2347         self.cached_deps = None
2348
2349         # Flags
2350
2351         # Does the symbol have an entry in the Kconfig file? The trailing
2352         # underscore avoids a collision with is_defined().
2353         self.is_defined_ = False
2354         # Should the symbol get an entry in .config?
2355         self.write_to_conf = False
2356         # Set to true when _make_conf() is called on a symbol, so that symbols
2357         # defined in multiple locations only get one .config entry. We need to
2358         # reset it prior to writing out a new .config.
2359         self.already_written = False
2360         # This is set to True for "actual" choice symbols; see
2361         # Choice._determine_actual_symbols().
2362         self.is_choice_sym = False
2363         # Does the symbol get its value in some special way, e.g. from the
2364         # environment or by being one of the special symbols n, m, and y? If
2365         # so, the value is stored in self.cached_val, which is never
2366         # invalidated. The trailing underscore avoids a collision with
2367         # is_special().
2368         self.is_special_ = False
2369         # Does the symbol get its value from the environment?
2370         self.is_from_env = False
2371         # Does the symbol have the 'allnoconfig_y' option set?
2372         self.allnoconfig_y = False
2373
2374     def _invalidate(self):
2375         if self.is_special_:
2376             return
2377
2378         if self.is_choice_sym:
2379             self.parent._invalidate()
2380
2381         self.cached_val = None
2382         self.cached_visibility = None
2383
2384     def _invalidate_dependent(self):
2385         for sym in self._get_dependent():
2386             sym._invalidate()
2387
2388     def _set_user_value_no_invalidate(self, v, suppress_load_warnings):
2389         """Like set_user_value(), but does not invalidate any symbols.
2390
2391         suppress_load_warnings: some warnings are annoying when loading a
2392            .config that can be helpful when manually invoking set_user_value().
2393            This flag is set to True to suppress such warnings.
2394
2395            Perhaps this could be made optional for load_config() instead."""
2396
2397         if self.is_special_:
2398             if self.is_from_env:
2399                 self.config._warn('attempt to assign the value "{0}" to the '
2400                                   'symbol {1}, which gets its value from the '
2401                                   'environment. Assignment ignored.'
2402                                   .format(v, self.name))
2403             else:
2404                 self.config._warn('attempt to assign the value "{0}" to the '
2405                                   'special symbol {1}. Assignment ignored.'
2406                                   .format(v, self.name))
2407             return
2408
2409         if not self.is_defined_:
2410             filename, linenr = self.ref_locations[0]
2411             if self.config.print_undef_assign:
2412                 _stderr_msg('note: attempt to assign the value "{0}" to {1}, '
2413                             "which is referenced at {2}:{3} but never "
2414                             "defined. Assignment ignored."
2415                             .format(v, self.name, filename, linenr))
2416             return
2417
2418         # Check if the value is valid for our type
2419         if not ((self.type == BOOL     and (v == "y" or v == "n")   ) or
2420                 (self.type == TRISTATE and (v == "y" or v == "m" or
2421                                             v == "n")               ) or
2422                 (self.type == STRING                                ) or
2423                 (self.type == INT      and _is_base_n(v, 10)        ) or
2424                 (self.type == HEX      and _is_base_n(v, 16)        )):
2425             self.config._warn('the value "{0}" is invalid for {1}, which has '
2426                               "type {2}. Assignment ignored."
2427                               .format(v, self.name, TYPENAME[self.type]))
2428             return
2429
2430         if not self.prompts and not suppress_load_warnings:
2431             self.config._warn('assigning "{0}" to the symbol {1} which '
2432                               'lacks prompts and thus has visibility "n". '
2433                               'The assignment will have no effect.'
2434                               .format(v, self.name))
2435
2436         self.user_val = v
2437
2438         if self.is_choice_sym and (self.type == BOOL or self.type == TRISTATE):
2439             choice = self.parent
2440             if v == "y":
2441                 choice.user_val = self
2442                 choice.user_mode = "y"
2443             elif v == "m":
2444                 choice.user_val = None
2445                 choice.user_mode = "m"
2446
2447     def _unset_user_value_no_recursive_invalidate(self):
2448         self._invalidate()
2449         self.user_val = None
2450
2451         if self.is_choice_sym:
2452             self.parent._unset_user_value()
2453
2454     def _make_conf(self, append_fn):
2455         if self.already_written:
2456             return
2457
2458         self.already_written = True
2459
2460         # Note: write_to_conf is determined in get_value()
2461         val = self.get_value()
2462         if not self.write_to_conf:
2463             return
2464
2465         if self.type == BOOL or self.type == TRISTATE:
2466             if val == "y" or val == "m":
2467                 append_fn("CONFIG_{0}={1}".format(self.name, val))
2468             else:
2469                 append_fn("# CONFIG_{0} is not set".format(self.name))
2470
2471         elif self.type == INT or self.type == HEX:
2472             append_fn("CONFIG_{0}={1}".format(self.name, val))
2473
2474         elif self.type == STRING:
2475             # Escape \ and "
2476             append_fn('CONFIG_{0}="{1}"'
2477                       .format(self.name,
2478                               val.replace("\\", "\\\\").replace('"', '\\"')))
2479
2480         else:
2481             _internal_error("Internal error while creating .config: unknown "
2482                             'type "{0}".'.format(self.type))
2483
2484     def _get_dependent(self):
2485         """Returns the set of symbols that should be invalidated if the value
2486         of the symbol changes, because they might be affected by the change.
2487         Note that this is an internal API -- it's probably of limited
2488         usefulness to clients."""
2489         if self.cached_deps is not None:
2490             return self.cached_deps
2491
2492         res = set(self.dep)
2493         for s in self.dep:
2494             res |= s._get_dependent()
2495
2496         if self.is_choice_sym:
2497             # Choice symbols also depend (recursively) on their siblings. The
2498             # siblings are not included in 'dep' to avoid dependency loops.
2499             for sibling in self.parent.actual_symbols:
2500                 if sibling is not self:
2501                     res.add(sibling)
2502                     res |= sibling.dep
2503                     for s in sibling.dep:
2504                         res |= s._get_dependent()
2505
2506         self.cached_deps = res
2507         return res
2508
2509     def _has_auto_menu_dep_on(self, on):
2510         """See Choice._determine_actual_symbols()."""
2511         if not isinstance(self.parent, Choice):
2512             _internal_error("Attempt to determine auto menu dependency for "
2513                             "symbol ouside of choice.")
2514
2515         if not self.prompts:
2516             # If we have no prompt, use the menu dependencies instead (what was
2517             # specified with 'depends on')
2518             return self.menu_dep is not None and \
2519                    self.config._expr_depends_on(self.menu_dep, on)
2520
2521         for _, cond_expr in self.prompts:
2522             if self.config._expr_depends_on(cond_expr, on):
2523                 return True
2524
2525         return False
2526
2527 class Menu(Item):
2528
2529     """Represents a menu statement."""
2530
2531     #
2532     # Public interface
2533     #
2534
2535     def get_config(self):
2536         """Return the Config instance this menu is from."""
2537         return self.config
2538
2539     def get_title(self):
2540         """Returns the title text of the menu."""
2541         return self.title
2542
2543     def get_parent(self):
2544         """Returns the menu or choice statement that contains the menu, or
2545         None if the menu is at the top level. Note that if statements are
2546         treated as syntactic sugar and do not have an explicit class
2547         representation."""
2548         return self.parent
2549
2550     def get_location(self):
2551         """Returns the location of the menu as a (filename, linenr) tuple,
2552         where filename is a string and linenr an int."""
2553         return (self.filename, self.linenr)
2554
2555     def get_items(self, recursive=False):
2556         """Returns a list containing the items (symbols, menus, choice
2557         statements and comments) in in the menu, in the same order that the
2558         items appear within the menu.
2559
2560         recursive (default: False): True if items contained in items within the
2561            menu should be included recursively (preorder)."""
2562
2563         if not recursive:
2564             return self.block
2565
2566         res = []
2567         for item in self.block:
2568             res.append(item)
2569             if isinstance(item, Menu):
2570                 res.extend(item.get_items(True))
2571             elif isinstance(item, Choice):
2572                 res.extend(item.get_items())
2573         return res
2574
2575     def get_symbols(self, recursive=False):
2576         """Returns a list containing the symbols in the menu, in the same order
2577         that they appear within the menu.
2578
2579         recursive (default: False): True if symbols contained in items within
2580            the menu should be included recursively."""
2581
2582         return [item for item in self.get_items(recursive) if
2583                 isinstance(item, Symbol)]
2584
2585     def get_visibility(self):
2586         """Returns the visibility of the menu. This also affects the visibility
2587         of subitems. See also Symbol.get_visibility()."""
2588         return self.config._eval_expr(self.dep_expr)
2589
2590     def get_visible_if_visibility(self):
2591         """Returns the visibility the menu gets from its 'visible if'
2592         condition. "y" if the menu has no 'visible if' condition."""
2593         return self.config._eval_expr(self.visible_if_expr)
2594
2595     def get_referenced_symbols(self, refs_from_enclosing=False):
2596         """See Symbol.get_referenced_symbols()."""
2597         return self.all_referenced_syms if refs_from_enclosing else \
2598                self.referenced_syms
2599
2600     def __str__(self):
2601         """Returns a string containing various information about the menu."""
2602         depends_on_str = self.config._expr_val_str(self.orig_deps,
2603                                                    "(no dependencies)")
2604         visible_if_str = self.config._expr_val_str(self.visible_if_expr,
2605                                                    "(no dependencies)")
2606
2607         additional_deps_str = " " + \
2608           self.config._expr_val_str(self.deps_from_containing,
2609                                     "(no additional dependencies)")
2610
2611         return _lines("Menu",
2612                       "Title                     : " + self.title,
2613                       "'depends on' dependencies : " + depends_on_str,
2614                       "'visible if' dependencies : " + visible_if_str,
2615                       "Additional dependencies from enclosing menus and "
2616                         "ifs:",
2617                       additional_deps_str,
2618                       "Location: {0}:{1}".format(self.filename, self.linenr))
2619
2620     #
2621     # Private methods
2622     #
2623
2624     def __init__(self):
2625         """Menu constructor -- not intended to be called directly by
2626         Kconfiglib clients."""
2627
2628         self.title = None
2629         self.dep_expr = None
2630         self.visible_if_expr = None
2631         self.block = None
2632         self.config = None
2633         self.parent = None
2634
2635         # Dependency expression without dependencies from enclosing menus and
2636         # ifs propagated
2637         self.orig_deps = None
2638
2639         # Dependencies inherited from containing menus and ifs
2640         self.deps_from_containing = None
2641         # The set of symbols referenced by this menu (see
2642         # get_referenced_symbols())
2643         self.referenced_syms = set()
2644         # Like 'referenced_syms', but includes symbols from
2645         # dependencies inherited from enclosing menus and ifs
2646         self.all_referenced_syms = None
2647
2648         self.filename = None
2649         self.linenr = None
2650
2651     def _make_conf(self, append_fn):
2652         if self.config._eval_expr(self.dep_expr) != "n" and \
2653            self.config._eval_expr(self.visible_if_expr) != "n":
2654             append_fn("\n#\n# {0}\n#".format(self.title))
2655         _make_block_conf(self.block, append_fn)
2656
2657 class Choice(Item):
2658
2659     """Represents a choice statement. A choice can be in one of three modes:
2660
2661     "n" - The choice is not visible and no symbols can be selected.
2662
2663     "m" - Any number of symbols can be set to "m". The rest will be "n". This
2664           is safe since potentially conflicting options don't actually get
2665           compiled into the kernel simultaneously with "m".
2666
2667     "y" - One symbol will be "y" while the rest are "n".
2668
2669     Only tristate choices can be in "m" mode, and the visibility of the choice
2670     is an upper bound on the mode, so that e.g. a choice that depends on a
2671     symbol with value "m" will be in "m" mode.
2672
2673     The mode changes automatically when a value is assigned to a symbol within
2674     the choice.
2675
2676     See Symbol.get_visibility() too."""
2677
2678     #
2679     # Public interface
2680     #
2681
2682     def get_config(self):
2683         """Returns the Config instance this choice is from."""
2684         return self.config
2685
2686     def get_name(self):
2687         """For named choices, returns the name. Returns None for unnamed
2688         choices. No named choices appear anywhere in the kernel Kconfig files
2689         as of Linux 3.7.0-rc8."""
2690         return self.name
2691
2692     def get_type(self):
2693         """Returns the type of the choice. See Symbol.get_type()."""
2694         return self.type
2695
2696     def get_prompts(self):
2697         """Returns a list of prompts defined for the choice, in the order they
2698         appear in the configuration files. Returns the empty list for choices
2699         with no prompt.
2700
2701         This list will have a single entry for the vast majority of choices
2702         having prompts, but having multiple prompts for a single choice is
2703         possible through having multiple 'choice' entries for it (though I'm
2704         not sure if that ever happens in practice)."""
2705         return [prompt for prompt, _ in self.orig_prompts]
2706
2707     def get_help(self):
2708         """Returns the help text of the choice, or None if the choice has no
2709         help text."""
2710         return self.help
2711
2712     def get_parent(self):
2713         """Returns the menu or choice statement that contains the choice, or
2714         None if the choice is at the top level. Note that if statements are
2715         treated as syntactic sugar and do not have an explicit class
2716         representation."""
2717         return self.parent
2718
2719     def get_def_locations(self):
2720         """Returns a list of (filename, linenr) tuples, where filename (string)
2721         and linenr (int) represent a location where the choice is defined. For
2722         the vast majority of choices (all of them as of Linux 3.7.0-rc8) this
2723         list will only contain one element, but its possible for named choices
2724         to be defined in multiple locations."""
2725         return self.def_locations
2726
2727     def get_selection(self):
2728         """Returns the symbol selected (either by the user or through
2729         defaults), or None if either no symbol is selected or the mode is not
2730         "y"."""
2731         if self.cached_selection is not None:
2732             if self.cached_selection == NO_SELECTION:
2733                 return None
2734             return self.cached_selection
2735
2736         if self.get_mode() != "y":
2737             return self._cache_ret(None)
2738
2739         # User choice available?
2740         if self.user_val is not None and _get_visibility(self.user_val) == "y":
2741             return self._cache_ret(self.user_val)
2742
2743         if self.optional:
2744             return self._cache_ret(None)
2745
2746         return self._cache_ret(self.get_selection_from_defaults())
2747
2748     def get_selection_from_defaults(self):
2749         """Like Choice.get_selection(), but acts as if no symbol has been
2750         selected by the user and no 'optional' flag is in effect."""
2751
2752         if not self.actual_symbols:
2753             return None
2754
2755         for symbol, cond_expr in self.def_exprs:
2756             if self.config._eval_expr(cond_expr) != "n":
2757                 chosen_symbol = symbol
2758                 break
2759         else:
2760             chosen_symbol = self.actual_symbols[0]
2761
2762         # Is the chosen symbol visible?
2763         if _get_visibility(chosen_symbol) != "n":
2764             return chosen_symbol
2765         # Otherwise, pick the first visible symbol
2766         for sym in self.actual_symbols:
2767             if _get_visibility(sym) != "n":
2768                 return sym
2769         return None
2770
2771     def get_user_selection(self):
2772         """If the choice is in "y" mode and has a user-selected symbol, returns
2773         that symbol. Otherwise, returns None."""
2774         return self.user_val
2775
2776     def get_items(self):
2777         """Gets all items contained in the choice in the same order as within
2778         the configuration ("items" instead of "symbols" since choices and
2779         comments might appear within choices. This only happens in one place as
2780         of Linux 3.7.0-rc8, in drivers/usb/gadget/Kconfig)."""
2781         return self.block
2782
2783     def get_symbols(self):
2784         """Returns a list containing the choice's symbols.
2785
2786         A quirk (perhaps a bug) of Kconfig is that you can put items within a
2787         choice that will not be considered members of the choice insofar as
2788         selection is concerned. This happens for example if one symbol within a
2789         choice 'depends on' the symbol preceding it, or if you put non-symbol
2790         items within choices.
2791
2792         As of Linux 3.7.0-rc8, this seems to be used intentionally in one
2793         place: drivers/usb/gadget/Kconfig.
2794
2795         This function returns the "proper" symbols of the choice in the order
2796         they appear in the choice, excluding such items. If you want all items
2797         in the choice, use get_items()."""
2798         return self.actual_symbols
2799
2800     def get_referenced_symbols(self, refs_from_enclosing=False):
2801         """See Symbol.get_referenced_symbols()."""
2802         return self.all_referenced_syms if refs_from_enclosing else \
2803                self.referenced_syms
2804
2805     def get_visibility(self):
2806         """Returns the visibility of the choice statement: one of "n", "m" or
2807         "y". This acts as an upper limit on the mode of the choice (though bool
2808         choices can only have the mode "y"). See the class documentation for an
2809         explanation of modes."""
2810         return _get_visibility(self)
2811
2812     def get_mode(self):
2813         """Returns the mode of the choice. See the class documentation for
2814         an explanation of modes."""
2815         minimum_mode = "n" if self.optional else "m"
2816         mode = self.user_mode if self.user_mode is not None else minimum_mode
2817         mode = self.config._eval_min(mode, _get_visibility(self))
2818
2819         # Promote "m" to "y" for boolean choices
2820         if mode == "m" and self.type == BOOL:
2821             return "y"
2822
2823         return mode
2824
2825     def is_optional(self):
2826         """Returns True if the choice has the 'optional' flag set (and so will
2827         default to "n" mode)."""
2828         return self.optional
2829
2830     def __str__(self):
2831         """Returns a string containing various information about the choice
2832         statement."""
2833         return self.config._get_sym_or_choice_str(self)
2834
2835     #
2836     # Private methods
2837     #
2838
2839     def __init__(self):
2840         """Choice constructor -- not intended to be called directly by
2841         Kconfiglib clients."""
2842
2843         self.name = None # Yes, choices can be named
2844         self.type = UNKNOWN
2845         self.prompts = []
2846         self.def_exprs = [] # 'default' properties
2847         self.help = None # Help text
2848         self.block = None # List of contained items
2849         self.config = None
2850         self.parent = None
2851
2852         self.user_val = None
2853         self.user_mode = None
2854
2855         # We need to filter out symbols that appear within the choice block but
2856         # are not considered choice items (see
2857         # Choice._determine_actual_symbols()) This list holds the "actual"
2858         # choice items.
2859         self.actual_symbols = []
2860
2861         # The prompts and default values without any dependencies from
2862         # enclosing menus and ifs propagated
2863         self.orig_prompts = []
2864         self.orig_def_exprs = []
2865
2866         # Dependencies inherited from containing menus and ifs
2867         self.deps_from_containing = None
2868         # The set of symbols referenced by this choice (see
2869         # get_referenced_symbols())
2870         self.referenced_syms = set()
2871         # Like 'referenced_syms', but includes symbols from
2872         # dependencies inherited from enclosing menus and ifs
2873         self.all_referenced_syms = set()
2874
2875         # See Choice.get_def_locations()
2876         self.def_locations = []
2877
2878         # Cached values
2879         self.cached_selection = None
2880         self.cached_visibility = None
2881
2882         self.optional = False
2883
2884     def _determine_actual_symbols(self):
2885         """If a symbol's visibility depends on the preceding symbol within a
2886         choice, it is no longer viewed as a choice item. (This is quite
2887         possibly a bug, but some things consciously use it... ugh. It stems
2888         from automatic submenu creation.) In addition, it's possible to have
2889         choices and comments within choices, and those shouldn't be considered
2890         choice items either. Only drivers/usb/gadget/Kconfig seems to depend on
2891         any of this. This method computes the "actual" items in the choice and
2892         sets the is_choice_sym flag on them (retrieved via is_choice_symbol()).
2893
2894         Don't let this scare you: an earlier version simply checked for a
2895         sequence of symbols where all symbols after the first appeared in the
2896         'depends on' expression of the first, and that worked fine.  The added
2897         complexity is to be future-proof in the event that
2898         drivers/usb/gadget/Kconfig turns even more sinister. It might very well
2899         be overkilling things (especially if that file is refactored ;)."""
2900
2901         # Items might depend on each other in a tree structure, so we need a
2902         # stack to keep track of the current tentative parent
2903         stack = []
2904
2905         for item in self.block:
2906             if not isinstance(item, Symbol):
2907                 stack = []
2908                 continue
2909
2910             while stack:
2911                 if item._has_auto_menu_dep_on(stack[-1]):
2912                     # The item should not be viewed as a choice item, so don't
2913                     # set item.is_choice_sym
2914                     stack.append(item)
2915                     break
2916                 else:
2917                     stack.pop()
2918             else:
2919                 item.is_choice_sym = True
2920                 self.actual_symbols.append(item)
2921                 stack.append(item)
2922
2923     def _cache_ret(self, selection):
2924         # As None is used to indicate the lack of a cached value we can't use
2925         # that to cache the fact that the choice has no selection. Instead, we
2926         # use the symbolic constant NO_SELECTION.
2927         if selection is None:
2928             self.cached_selection = NO_SELECTION
2929         else:
2930             self.cached_selection = selection
2931
2932         return selection
2933
2934     def _invalidate(self):
2935         self.cached_selection = None
2936         self.cached_visibility = None
2937
2938     def _unset_user_value(self):
2939         self._invalidate()
2940         self.user_val = None
2941         self.user_mode = None
2942
2943     def _make_conf(self, append_fn):
2944         _make_block_conf(self.block, append_fn)
2945
2946 class Comment(Item):
2947
2948     """Represents a comment statement."""
2949
2950     #
2951     # Public interface
2952     #
2953
2954     def get_config(self):
2955         """Returns the Config instance this comment is from."""
2956         return self.config
2957
2958     def get_text(self):
2959         """Returns the text of the comment."""
2960         return self.text
2961
2962     def get_parent(self):
2963         """Returns the menu or choice statement that contains the comment, or
2964         None if the comment is at the top level. Note that if statements are
2965         treated as syntactic sugar and do not have an explicit class
2966         representation."""
2967         return self.parent
2968
2969     def get_location(self):
2970         """Returns the location of the comment as a (filename, linenr) tuple,
2971         where filename is a string and linenr an int."""
2972         return (self.filename, self.linenr)
2973
2974     def get_visibility(self):
2975         """Returns the visibility of the comment. See also
2976         Symbol.get_visibility()."""
2977         return self.config._eval_expr(self.dep_expr)
2978
2979     def get_referenced_symbols(self, refs_from_enclosing=False):
2980         """See Symbol.get_referenced_symbols()."""
2981         return self.all_referenced_syms if refs_from_enclosing else \
2982                self.referenced_syms
2983
2984     def __str__(self):
2985         """Returns a string containing various information about the
2986         comment."""
2987         dep_str = self.config._expr_val_str(self.orig_deps,
2988                                             "(no dependencies)")
2989
2990         additional_deps_str = " " + \
2991           self.config._expr_val_str(self.deps_from_containing,
2992                                     "(no additional dependencies)")
2993
2994         return _lines("Comment",
2995                       "Text: "         + str(self.text),
2996                       "Dependencies: " + dep_str,
2997                       "Additional dependencies from enclosing menus and "
2998                         "ifs:",
2999                       additional_deps_str,
3000                       "Location: {0}:{1}".format(self.filename, self.linenr))
3001
3002     #
3003     # Private methods
3004     #
3005
3006     def __init__(self):
3007         """Comment constructor -- not intended to be called directly by
3008         Kconfiglib clients."""
3009
3010         self.text = None
3011         self.dep_expr = None
3012         self.config = None
3013         self.parent = None
3014
3015         # Dependency expression without dependencies from enclosing menus and
3016         # ifs propagated
3017         self.orig_deps = None
3018
3019         # Dependencies inherited from containing menus and ifs
3020         self.deps_from_containing = None
3021         # The set of symbols referenced by this comment (see
3022         # get_referenced_symbols())
3023         self.referenced_syms = set()
3024         # Like 'referenced_syms', but includes symbols from
3025         # dependencies inherited from enclosing menus and ifs
3026         self.all_referenced_syms = None
3027
3028         self.filename = None
3029         self.linenr = None
3030
3031     def _make_conf(self, append_fn):
3032         if self.config._eval_expr(self.dep_expr) != "n":
3033             append_fn("\n#\n# {0}\n#".format(self.text))
3034
3035 class Kconfig_Syntax_Error(Exception):
3036     """Exception raised for syntax errors."""
3037     pass
3038
3039 class Internal_Error(Exception):
3040     """Exception raised for internal errors."""
3041     pass
3042
3043 #
3044 # Public functions
3045 #
3046
3047 def tri_less(v1, v2):
3048     """Returns True if the tristate v1 is less than the tristate v2, where "n",
3049     "m" and "y" are ordered from lowest to highest."""
3050     return TRI_TO_INT[v1] < TRI_TO_INT[v2]
3051
3052 def tri_less_eq(v1, v2):
3053     """Returns True if the tristate v1 is less than or equal to the tristate
3054     v2, where "n", "m" and "y" are ordered from lowest to highest."""
3055     return TRI_TO_INT[v1] <= TRI_TO_INT[v2]
3056
3057 def tri_greater(v1, v2):
3058     """Returns True if the tristate v1 is greater than the tristate v2, where
3059     "n", "m" and "y" are ordered from lowest to highest."""
3060     return TRI_TO_INT[v1] > TRI_TO_INT[v2]
3061
3062 def tri_greater_eq(v1, v2):
3063     """Returns True if the tristate v1 is greater than or equal to the tristate
3064     v2, where "n", "m" and "y" are ordered from lowest to highest."""
3065     return TRI_TO_INT[v1] >= TRI_TO_INT[v2]
3066
3067 #
3068 # Internal classes
3069 #
3070
3071 class _Feed(object):
3072
3073     """Class for working with sequences in a stream-like fashion; handy for
3074     tokens."""
3075
3076     # This would be more helpful on the item classes, but would remove some
3077     # flexibility
3078     __slots__ = ['items', 'length', 'i']
3079
3080     def __init__(self, items):
3081         self.items = items
3082         self.length = len(self.items)
3083         self.i = 0
3084
3085     def get_next(self):
3086         if self.i >= self.length:
3087             return None
3088         item = self.items[self.i]
3089         self.i += 1
3090         return item
3091
3092     def peek_next(self):
3093         return None if self.i >= self.length else self.items[self.i]
3094
3095     def check(self, token):
3096         """Check if the next token is 'token'. If so, remove it from the token
3097         feed and return True. Otherwise, leave it in and return False."""
3098         if self.i < self.length and self.items[self.i] == token:
3099             self.i += 1
3100             return True
3101         return False
3102
3103     def unget_all(self):
3104         self.i = 0
3105
3106 class _FileFeed(object):
3107
3108     """Feeds lines from a file. Keeps track of the filename and current line
3109     number. Joins any line ending in \\ with the following line. We need to be
3110     careful to get the line number right in the presence of continuation
3111     lines."""
3112
3113     __slots__ = ['filename', 'lines', 'length', 'linenr']
3114
3115     def __init__(self, filename):
3116         self.filename = _clean_up_path(filename)
3117         with open(filename, "r") as f:
3118             # No interleaving of I/O and processing yet. Don't know if it would
3119             # help.
3120             self.lines = f.readlines()
3121         self.length = len(self.lines)
3122         self.linenr = 0
3123
3124     def get_next(self):
3125         if self.linenr >= self.length:
3126             return None
3127         line = self.lines[self.linenr]
3128         self.linenr += 1
3129         while line.endswith("\\\n"):
3130             line = line[:-2] + self.lines[self.linenr]
3131             self.linenr += 1
3132         return line
3133
3134     def peek_next(self):
3135         linenr = self.linenr
3136         if linenr >= self.length:
3137             return None
3138         line = self.lines[linenr]
3139         while line.endswith("\\\n"):
3140             linenr += 1
3141             line = line[:-2] + self.lines[linenr]
3142         return line
3143
3144     def unget(self):
3145         self.linenr -= 1
3146         while self.lines[self.linenr].endswith("\\\n"):
3147             self.linenr -= 1
3148
3149     def next_nonblank(self):
3150         """Removes lines up to and including the next non-blank (not all-space)
3151         line and returns it. Returns None if there are no more non-blank
3152         lines."""
3153         while 1:
3154             line = self.get_next()
3155             if line is None or not line.isspace():
3156                 return line
3157
3158 #
3159 # Internal functions
3160 #
3161
3162 def _get_visibility(sc):
3163     """Symbols and Choices have a "visibility" that acts as an upper bound on
3164     the values a user can set for them, corresponding to the visibility in e.g.
3165     'make menuconfig'. This function calculates the visibility for the Symbol
3166     or Choice 'sc' -- the logic is nearly identical."""
3167     if sc.cached_visibility is None:
3168         vis = "n"
3169         for _, cond_expr in sc.prompts:
3170             vis = sc.config._eval_max(vis, cond_expr)
3171
3172         if isinstance(sc, Symbol) and sc.is_choice_sym:
3173             vis = sc.config._eval_min(vis, _get_visibility(sc.parent))
3174
3175         # Promote "m" to "y" if we're dealing with a non-tristate
3176         if vis == "m" and sc.type != TRISTATE:
3177             vis = "y"
3178
3179         sc.cached_visibility = vis
3180
3181     return sc.cached_visibility
3182
3183 def _make_and(e1, e2):
3184     """Constructs an AND (&&) expression. Performs trivial simplification.
3185     Nones equate to 'y'.
3186
3187     Note: returns None if e1 == e2 == None."""
3188     if e1 is None or e1 == "y":
3189         return e2
3190     if e2 is None or e2 == "y":
3191         return e1
3192
3193     # Prefer to merge argument lists if possible to reduce the number of nodes
3194
3195     if isinstance(e1, tuple) and e1[0] == AND:
3196         if isinstance(e2, tuple) and e2[0] == AND:
3197             return (AND, e1[1] + e2[1])
3198         return (AND, e1[1] + [e2])
3199
3200     if isinstance(e2, tuple) and e2[0] == AND:
3201         return (AND, e2[1] + [e1])
3202
3203     return (AND, [e1, e2])
3204
3205 def _make_or(e1, e2):
3206     """Constructs an OR (||) expression. Performs trivial simplification and
3207     avoids Nones. Nones equate to 'y', which is usually what we want, but needs
3208     to be kept in mind."""
3209
3210     # Perform trivial simplification and avoid None's (which
3211     # correspond to y's)
3212     if e1 is None or e2 is None or e1 == "y" or e2 == "y":
3213         return "y"
3214     if e1 == "n":
3215         return e2
3216
3217     # Prefer to merge argument lists if possible to reduce the number of nodes
3218
3219     if isinstance(e1, tuple) and e1[0] == OR:
3220         if isinstance(e2, tuple) and e2[0] == OR:
3221             return (OR, e1[1] + e2[1])
3222         return (OR, e1[1] + [e2])
3223
3224     if isinstance(e2, tuple) and e2[0] == OR:
3225         return (OR, e2[1] + [e1])
3226
3227     return (OR, [e1, e2])
3228
3229 def _get_expr_syms_rec(expr, res):
3230     """_get_expr_syms() helper. Recurses through expressions."""
3231     if isinstance(expr, Symbol):
3232         res.add(expr)
3233     elif isinstance(expr, str):
3234         return
3235     elif expr[0] == AND or expr[0] == OR:
3236         for term in expr[1]:
3237             _get_expr_syms_rec(term, res)
3238     elif expr[0] == NOT:
3239         _get_expr_syms_rec(expr[1], res)
3240     elif expr[0] == EQUAL or expr[0] == UNEQUAL:
3241         if isinstance(expr[1], Symbol):
3242             res.add(expr[1])
3243         if isinstance(expr[2], Symbol):
3244             res.add(expr[2])
3245     else:
3246         _internal_error("Internal error while fetching symbols from an "
3247                         "expression with token stream {0}.".format(expr))
3248
3249 def _get_expr_syms(expr):
3250     """Returns the set() of symbols appearing in expr."""
3251     res = set()
3252     if expr is not None:
3253         _get_expr_syms_rec(expr, res)
3254     return res
3255
3256 def _str_val(obj):
3257     """Returns the value of obj as a string. If obj is not a string (constant
3258     symbol), it must be a Symbol."""
3259     return obj if isinstance(obj, str) else obj.get_value()
3260
3261 def _make_block_conf(block, append_fn):
3262     """Returns a list of .config strings for a block (list) of items."""
3263
3264     # Collect the substrings in a list and later use join() instead of += to
3265     # build the final .config contents. With older Python versions, this yields
3266     # linear instead of quadratic complexity.
3267     for item in block:
3268         item._make_conf(append_fn)
3269
3270 def _sym_str_string(sym_or_str):
3271     if isinstance(sym_or_str, str):
3272         return '"' + sym_or_str + '"'
3273     return sym_or_str.name
3274
3275 def _intersperse(lst, op):
3276     """_expr_to_str() helper. Gets the string representation of each expression
3277     in lst and produces a list where op has been inserted between the
3278     elements."""
3279     if not lst:
3280         return ""
3281
3282     res = []
3283
3284     def handle_sub_expr(expr):
3285         no_parens = isinstance(expr, (str, Symbol)) or \
3286                     expr[0] in (EQUAL, UNEQUAL) or \
3287                     PRECEDENCE[op] <= PRECEDENCE[expr[0]]
3288         if not no_parens:
3289             res.append("(")
3290         res.extend(_expr_to_str_rec(expr))
3291         if not no_parens:
3292             res.append(")")
3293
3294     op_str = OP_TO_STR[op]
3295
3296     handle_sub_expr(lst[0])
3297     for expr in lst[1:]:
3298         res.append(op_str)
3299         handle_sub_expr(expr)
3300
3301     return res
3302
3303 def _expr_to_str_rec(expr):
3304     if expr is None:
3305         return [""]
3306
3307     if isinstance(expr, (Symbol, str)):
3308         return [_sym_str_string(expr)]
3309
3310     if expr[0] in (AND, OR):
3311         return _intersperse(expr[1], expr[0])
3312
3313     if expr[0] == NOT:
3314         need_parens = not isinstance(expr[1], (str, Symbol))
3315
3316         res = ["!"]
3317         if need_parens:
3318             res.append("(")
3319         res.extend(_expr_to_str_rec(expr[1]))
3320         if need_parens:
3321             res.append(")")
3322         return res
3323
3324     if expr[0] in (EQUAL, UNEQUAL):
3325         return [_sym_str_string(expr[1]),
3326                 OP_TO_STR[expr[0]],
3327                 _sym_str_string(expr[2])]
3328
3329 def _expr_to_str(expr):
3330     return "".join(_expr_to_str_rec(expr))
3331
3332 def _indentation(line):
3333     """Returns the length of the line's leading whitespace, treating tab stops
3334     as being spaced 8 characters apart."""
3335     line = line.expandtabs()
3336     return len(line) - len(line.lstrip())
3337
3338 def _deindent(line, indent):
3339     """Deindent 'line' by 'indent' spaces."""
3340     line = line.expandtabs()
3341     if len(line) <= indent:
3342         return line
3343     return line[indent:]
3344
3345 def _is_base_n(s, n):
3346     try:
3347         int(s, n)
3348         return True
3349     except ValueError:
3350         return False
3351
3352 def _lines(*args):
3353     """Returns a string consisting of all arguments, with newlines inserted
3354     between them."""
3355     return "\n".join(args)
3356
3357 def _comment(s):
3358     """Returns a new string with "#" inserted before each line in 's'."""
3359     if not s:
3360         return "#"
3361     res = "".join(["#" + line for line in s.splitlines(True)])
3362     if s.endswith("\n"):
3363         return res + "#"
3364     return res
3365
3366 def _clean_up_path(path):
3367     """Strips an initial "./" and any trailing slashes from 'path'."""
3368     if path.startswith("./"):
3369         path = path[2:]
3370     return path.rstrip("/")
3371
3372 def _stderr_msg(msg, filename, linenr):
3373     if filename is not None:
3374         sys.stderr.write("{0}:{1}: ".format(_clean_up_path(filename), linenr))
3375     sys.stderr.write(msg + "\n")
3376
3377 def _tokenization_error(s, filename, linenr):
3378     loc = "" if filename is None else "{0}:{1}: ".format(filename, linenr)
3379     raise Kconfig_Syntax_Error("{0}Couldn't tokenize '{1}'"
3380                                .format(loc, s.strip()))
3381
3382 def _parse_error(s, msg, filename, linenr):
3383     loc = "" if filename is None else "{0}:{1}: ".format(filename, linenr)
3384     raise Kconfig_Syntax_Error("{0}Couldn't parse '{1}'{2}"
3385                                .format(loc, s.strip(),
3386                                        "." if msg is None else ": " + msg))
3387
3388 def _internal_error(msg):
3389     raise Internal_Error(msg +
3390       "\nSorry! You may want to send an email to ulfalizer a.t Google's "
3391       "email service to tell me about this. Include the message above and the "
3392       "stack trace and describe what you were doing.")
3393
3394 #
3395 # Internal global constants
3396 #
3397
3398 # Tokens
3399 (T_AND, T_OR, T_NOT,
3400  T_OPEN_PAREN, T_CLOSE_PAREN,
3401  T_EQUAL, T_UNEQUAL,
3402  T_MAINMENU, T_MENU, T_ENDMENU,
3403  T_SOURCE, T_CHOICE, T_ENDCHOICE,
3404  T_COMMENT, T_CONFIG, T_MENUCONFIG,
3405  T_HELP, T_IF, T_ENDIF, T_DEPENDS, T_ON,
3406  T_OPTIONAL, T_PROMPT, T_DEFAULT,
3407  T_BOOL, T_TRISTATE, T_HEX, T_INT, T_STRING,
3408  T_DEF_BOOL, T_DEF_TRISTATE,
3409  T_SELECT, T_RANGE, T_OPTION, T_ALLNOCONFIG_Y, T_ENV,
3410  T_DEFCONFIG_LIST, T_MODULES, T_VISIBLE) = range(39)
3411
3412 # The leading underscore before the function assignments below prevent pydoc
3413 # from listing them. The constants could be hidden too, but they're fairly
3414 # obviously internal anyway, so don't bother spamming the code.
3415
3416 # Keyword to token map. Note that the get() method is assigned directly as a
3417 # small optimization.
3418 _get_keyword = \
3419   {"mainmenu": T_MAINMENU, "menu": T_MENU, "endmenu": T_ENDMENU,
3420    "endif": T_ENDIF, "endchoice": T_ENDCHOICE, "source": T_SOURCE,
3421    "choice": T_CHOICE, "config": T_CONFIG, "comment": T_COMMENT,
3422    "menuconfig": T_MENUCONFIG, "help": T_HELP, "if": T_IF,
3423    "depends": T_DEPENDS, "on": T_ON, "optional": T_OPTIONAL,
3424    "prompt": T_PROMPT, "default": T_DEFAULT, "bool": T_BOOL, "boolean": T_BOOL,
3425    "tristate": T_TRISTATE, "int": T_INT, "hex": T_HEX, "def_bool": T_DEF_BOOL,
3426    "def_tristate": T_DEF_TRISTATE, "string": T_STRING, "select": T_SELECT,
3427    "range": T_RANGE, "option": T_OPTION, "allnoconfig_y": T_ALLNOCONFIG_Y,
3428    "env": T_ENV, "defconfig_list": T_DEFCONFIG_LIST, "modules": T_MODULES,
3429    "visible": T_VISIBLE}.get
3430
3431 # Strings to use for True and False
3432 BOOL_STR = {False: "false", True: "true"}
3433
3434 # Tokens after which identifier-like lexemes are treated as strings. T_CHOICE
3435 # is included to avoid symbols being registered for named choices.
3436 STRING_LEX = frozenset((T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING, T_CHOICE,
3437                         T_PROMPT, T_MENU, T_COMMENT, T_SOURCE, T_MAINMENU))
3438
3439 # Matches the initial token on a line; see _tokenize(). Also eats trailing
3440 # whitespace as an optimization.
3441 _initial_token_re_match = re.compile(r"[^\w]*(\w+)\s*").match
3442
3443 # Matches an identifier/keyword optionally preceded by whitespace. Also eats
3444 # trailing whitespace as an optimization.
3445 _id_keyword_re_match = re.compile(r"\s*([\w./-]+)\s*").match
3446
3447 # Regular expressions for parsing .config files
3448 _set_re_match = re.compile(r"CONFIG_(\w+)=(.*)").match
3449 _unset_re_match = re.compile(r"# CONFIG_(\w+) is not set").match
3450
3451 # Regular expression for finding $-references to symbols in strings
3452 _sym_ref_re_search = re.compile(r"\$[A-Za-z0-9_]+").search
3453
3454 # Integers representing symbol types
3455 UNKNOWN, BOOL, TRISTATE, STRING, HEX, INT = range(6)
3456
3457 # Strings to use for types
3458 TYPENAME = {UNKNOWN: "unknown", BOOL: "bool", TRISTATE: "tristate",
3459             STRING: "string", HEX: "hex", INT: "int"}
3460
3461 # Token to type mapping
3462 TOKEN_TO_TYPE = {T_BOOL: BOOL, T_TRISTATE: TRISTATE, T_STRING: STRING,
3463                  T_INT: INT, T_HEX: HEX}
3464
3465 # Default values for symbols of different types (the value the symbol gets if
3466 # it is not assigned a user value and none of its 'default' clauses kick in)
3467 DEFAULT_VALUE = {BOOL: "n", TRISTATE: "n", STRING: "", INT: "", HEX: ""}
3468
3469 # Indicates that no item is selected in a choice statement
3470 NO_SELECTION = 0
3471
3472 # Integers representing expression types
3473 AND, OR, NOT, EQUAL, UNEQUAL = range(5)
3474
3475 # Map from tristate values to integers
3476 TRI_TO_INT = {"n": 0, "m": 1, "y": 2}
3477
3478 # Printing-related stuff
3479
3480 OP_TO_STR = {AND: " && ", OR: " || ", EQUAL: " = ", UNEQUAL: " != "}
3481 PRECEDENCE = {OR: 0, AND: 1, NOT: 2}