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