]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - tools/buildman/kconfiglib.py
c662b64dadab8251086be1fdf042080f9319ad2e
[karo-tx-uboot.git] / tools / buildman / kconfiglib.py
1 #
2 # SPDX-License-Identifier:      ISC
3 #
4 # Author: Ulf Magnusson
5 #   https://github.com/ulfalizer/Kconfiglib
6
7 # This is Kconfiglib, a Python library for scripting, debugging, and extracting
8 # information from Kconfig-based configuration systems. To view the
9 # documentation, run
10 #
11 #  $ pydoc kconfiglib
12 #
13 # or, if you prefer HTML,
14 #
15 #  $ pydoc -w kconfiglib
16 #
17 # The examples/ subdirectory contains examples, to be run with e.g.
18 #
19 #  $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
20 #
21 # Look in testsuite.py for the test suite.
22
23 """
24 Kconfiglib is a Python library for scripting and extracting information from
25 Kconfig-based configuration systems. Features include the following:
26
27  - Symbol values and properties can be looked up and values assigned
28    programmatically.
29  - .config files can be read and written.
30  - Expressions can be evaluated in the context of a Kconfig configuration.
31  - Relations between symbols can be quickly determined, such as finding all
32    symbols that reference a particular symbol.
33  - Highly compatible with the scripts/kconfig/*conf utilities. The test suite
34    automatically compares outputs between Kconfiglib and the C implementation
35    for a large number of cases.
36
37 For the Linux kernel, scripts are run using
38
39  $ make scriptconfig SCRIPT=<path to script> [SCRIPT_ARG=<arg>]
40
41 Running scripts via the 'scriptconfig' target ensures that required environment
42 variables (SRCARCH, ARCH, srctree, KERNELVERSION, etc.) are set up correctly.
43 Alternative architectures can be specified like for other 'make *config'
44 targets:
45
46  $ make scriptconfig ARCH=mips SCRIPT=<path to script> [SCRIPT_ARG=<arg>]
47
48 The 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
50 directory.) If an argument is provided with SCRIPT_ARG, it will appear in
51 sys.argv[2].
52
53 To get an interactive Python prompt with Kconfiglib preloaded and a Config
54 object 'c' created, use
55
56  $ make iscriptconfig [ARCH=<architecture>]
57
58 Kconfiglib requires Python 2. For (i)scriptconfig the command to run the Python
59 interpreter can be passed in the environment variable PYTHONCMD (defaults to
60 'python'; PyPy works too and is a bit faster).
61
62 Look in the examples/ subdirectory for examples, which can be run with e.g.
63
64  $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
65
66 or
67
68  $ make scriptconfig SCRIPT=Kconfiglib/examples/help_grep.py SCRIPT_ARG="kernel"
69
70 Look in testsuite.py for the test suite.
71
72 Credits: Written by Ulf "Ulfalizer" Magnusson
73
74 Send bug reports, suggestions and other feedback to kconfiglib@gmail.com .
75 Don't wrestle with internal APIs. Tell me what you need and I might add it in a
76 safe 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.)
82 use_psyco = False
83
84 import os
85 import re
86 import string
87 import sys
88
89 class 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("""
1317 The symbol {0} references the non-existent environment variable {1} and will
1318 get the empty string as its value.
1319
1320 If you're using kconfiglib via 'make (i)scriptconfig' it should have set up the
1321 environment correctly for you. If you still got this message, that might be an
1322 error, 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
1930 def _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
1978 def _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
2006 def _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
2049 keywords = {
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
2085 bool_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.
2089 string_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().
2093 initial_token_re = re.compile(r"[^\w]*(\w+)")
2094
2095 # Matches an identifier/keyword optionally preceded by whitespace
2096 id_keyword_re = re.compile(r"\s*([\w./-]+)")
2097
2098 # Regular expressions for parsing .config files
2099 set_re   = re.compile(r"CONFIG_(\w+)=(.*)")
2100 unset_re = re.compile(r"# CONFIG_(\w+) is not set")
2101
2102 # Regular expression for finding $-references to symbols in strings
2103 sym_ref_re = re.compile(r"\$[A-Za-z0-9_]+")
2104
2105 # Integers representing symbol types
2106 UNKNOWN, BOOL, TRISTATE, STRING, HEX, INT = range(0, 6)
2107
2108 # Strings to use for types
2109 typename = {
2110         UNKNOWN  : "unknown",
2111         BOOL     : "bool",
2112         TRISTATE : "tristate",
2113         STRING   : "string",
2114         HEX      : "hex",
2115         INT      : "int" }
2116
2117 # Token to type mapping
2118 token_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)
2126 default_value = { BOOL     : "n",
2127                   TRISTATE : "n",
2128                   STRING   : "",
2129                   INT      : "",
2130                   HEX      : "" }
2131
2132 # Indicates that no item is selected in a choice statement
2133 NO_SELECTION = 0
2134
2135 # Integers representing expression types
2136 OR, AND, NOT, EQUAL, UNEQUAL = range(0, 5)
2137
2138 # Map from tristate values to integers
2139 tri_to_int = { "n" : 0, "m" : 1, "y" : 2 }
2140
2141 # Printing-related stuff
2142
2143 op_to_str = { AND     : " && ",
2144               OR      : " || ",
2145               EQUAL   : " = ",
2146               UNEQUAL : " != " }
2147
2148 precedence = { OR : 0, AND : 1, NOT : 2 }
2149
2150 # Types of informational messages
2151 WARNING = 0
2152 UNDEF_ASSIGN = 1
2153
2154 def _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
2181 def _expr_to_str(expr):
2182     s = "".join(_expr_to_str_rec(expr))
2183     return s
2184
2185 def _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
2190 def _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
2218 class _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
2247 class 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
2272 class _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
2302 class 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
3057 class 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
3192 class 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
3485 class 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
3573 class _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
3626 class _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
3645 def 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
3651 def 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
3657 def 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
3663 def 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
3673 def _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
3688 def _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
3703 def _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
3710 def _is_base_n(s, n):
3711     try:
3712         int(s, n)
3713         return True
3714     except ValueError:
3715         return False
3716
3717 def _sep_lines(*args):
3718     """Returns a string comprised of all arguments, with newlines inserted
3719     between them."""
3720     return "\n".join(args)
3721
3722 def _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
3731 def _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
3750 def _strip_trailing_slash(path):
3751     """Removes any trailing slash from 'path'."""
3752     return path[:-1] if path.endswith("/") else path
3753
3754 def _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
3764 class Kconfig_Syntax_Error(Exception):
3765     """Exception raised for syntax errors."""
3766     pass
3767
3768 class Internal_Error(Exception):
3769     """Exception raised for internal errors."""
3770     pass
3771
3772 def _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
3798 def _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
3813 def _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
3820 if 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)