1 # This is Kconfiglib, a Python library for scripting, debugging, and extracting
2 # information from Kconfig-based configuration systems. To view the
7 # or, if you prefer HTML,
9 # $ pydoc -w kconfiglib
11 # The examples/ subdirectory contains examples, to be run with e.g.
13 # $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
15 # Look in testsuite.py for the test suite.
18 Kconfiglib is a Python library for scripting and extracting information from
19 Kconfig-based configuration systems. Features include the following:
21 - Symbol values and properties can be looked up and values assigned
23 - .config files can be read and written.
24 - Expressions can be evaluated in the context of a Kconfig configuration.
25 - Relations between symbols can be quickly determined, such as finding all
26 symbols that reference a particular symbol.
27 - Highly compatible with the scripts/kconfig/*conf utilities. The test suite
28 automatically compares outputs between Kconfiglib and the C implementation
29 for a large number of cases.
31 For the Linux kernel, scripts are run using
33 $ make scriptconfig [ARCH=<architecture>] SCRIPT=<path to script> [SCRIPT_ARG=<arg>]
35 Using the 'scriptconfig' target ensures that required environment variables
36 (SRCARCH, ARCH, srctree, KERNELVERSION, etc.) are set up correctly.
38 Scripts receive the name of the Kconfig file to load in sys.argv[1]. As of
39 Linux 4.1.0-rc5, this is always "Kconfig" from the kernel top-level directory.
40 If an argument is provided with SCRIPT_ARG, it appears as sys.argv[2].
42 To get an interactive Python prompt with Kconfiglib preloaded and a Config
43 object 'c' created, run
45 $ make iscriptconfig [ARCH=<architecture>]
47 Kconfiglib currently uses Python 2. For (i)scriptconfig, the Python interpreter
48 to use can be passed in PYTHONCMD. It defaults to 'python', but PyPy works too
49 and might be faster for long-running jobs.
51 The examples/ directory contains short example scripts, which can be run with
54 $ make scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
58 $ make scriptconfig SCRIPT=Kconfiglib/examples/help_grep.py SCRIPT_ARG=kernel
60 testsuite.py contains the test suite. See the top of the script for how to run
63 Credits: Written by Ulf "Ulfalizer" Magnusson
65 Send bug reports, suggestions and other feedback to ulfalizer a.t Google's
66 email service. Don't wrestle with internal APIs. Tell me what you need and I
67 might add it in a safe way as a client API instead."""
79 # Internal global constants
87 """Represents a Kconfig configuration, e.g. for i386 or ARM. This is the
88 set of symbols and other items appearing in the configuration together with
89 their values. Creating any number of Config objects -- including for
90 different architectures -- is safe; Kconfiglib has no global state."""
96 def __init__(self
, filename
= "Kconfig", base_dir
= None,
97 print_warnings
= True, print_undef_assign
= False):
98 """Creates a new Config object, representing a Kconfig configuration.
99 Raises Kconfig_Syntax_Error on syntax errors.
101 filename (default: "Kconfig") -- The base Kconfig file of the
102 configuration. For the Linux kernel, you'll probably want
103 "Kconfig" from the top-level directory, as environment
104 variables will make sure the right Kconfig is included from
105 there (arch/<architecture>/Kconfig). If you are using
106 kconfiglib via 'make scriptconfig', the filename of the base
107 base Kconfig file will be in sys.argv[1].
109 base_dir (default: None) -- The base directory relative to which
110 'source' statements within Kconfig files will work. For the
111 Linux kernel this should be the top-level directory of the
112 kernel tree. $-references to existing environment variables
115 If None (the default), the environment variable 'srctree' will
116 be used if set, and the current directory otherwise. 'srctree'
117 is set by the Linux makefiles to the top-level kernel
118 directory. A default of "." would not work with an alternative
121 print_warnings (default: True) -- Set to True if warnings related to
122 this configuration should be printed to stderr. This can
123 be changed later with Config.set_print_warnings(). It is
124 provided as a constructor argument since warnings might
125 be generated during parsing.
127 print_undef_assign (default: False) -- Set to True if informational
128 messages related to assignments to undefined symbols
129 should be printed to stderr for this configuration.
130 Can be changed later with
131 Config.set_print_undef_assign()."""
133 # The set of all symbols, indexed by name (a string)
136 # Python 2/3 compatibility hack. This is the only one needed.
137 if sys
.version_info
[0] >= 3:
138 self
.syms_iter
= self
.syms
.values
140 self
.syms_iter
= self
.syms
.itervalues
142 # The set of all defined symbols in the configuration in the order they
143 # appear in the Kconfig files. This excludes the special symbols n, m,
144 # and y as well as symbols that are referenced but never defined.
145 self
.kconfig_syms
= []
147 # The set of all named choices (yes, choices can have names), indexed
149 self
.named_choices
= {}
151 def register_special_symbol(type_
, name
, val
):
153 sym
.is_special_
= True
154 sym
.is_defined_
= True
159 self
.syms
[name
] = sym
162 # The special symbols n, m and y, used as shorthand for "n", "m" and
164 self
.n
= register_special_symbol(TRISTATE
, "n", "n")
165 self
.m
= register_special_symbol(TRISTATE
, "m", "m")
166 self
.y
= register_special_symbol(TRISTATE
, "y", "y")
168 # DEFCONFIG_LIST uses this
169 register_special_symbol(STRING
, "UNAME_RELEASE", os
.uname()[2])
171 # The symbol with "option defconfig_list" set, containing a list of
172 # default .config files
173 self
.defconfig_sym
= None
175 # See Symbol.get_(src)arch()
176 self
.arch
= os
.environ
.get("ARCH")
177 self
.srcarch
= os
.environ
.get("SRCARCH")
179 # See Config.__init__(). We need this for get_defconfig_filename().
180 self
.srctree
= os
.environ
.get("srctree")
181 if self
.srctree
is None:
184 self
.filename
= filename
186 self
.base_dir
= self
.srctree
188 self
.base_dir
= os
.path
.expandvars(base_dir
)
190 # The 'mainmenu' text
191 self
.mainmenu_text
= None
193 # The filename of the most recently loaded .config file
194 self
.config_filename
= None
196 # The textual header of the most recently loaded .config, uncommented
197 self
.config_header
= None
199 self
.print_warnings
= print_warnings
200 self
.print_undef_assign
= print_undef_assign
202 # Lists containing all choices, menus and comments in the configuration
208 # For parsing routines that stop when finding a line belonging to a
209 # different construct, these holds that line and the tokenized version
210 # of that line. The purpose is to avoid having to re-tokenize the line,
211 # which is inefficient and causes problems when recording references to
214 self
.end_line_tokens
= None
216 # See the comment in _parse_expr().
217 self
.parse_expr_cur_sym_or_choice
= None
218 self
.parse_expr_line
= None
219 self
.parse_expr_filename
= None
220 self
.parse_expr_linenr
= None
221 self
.parse_expr_transform_m
= None
223 # Parse the Kconfig files
224 self
.top_block
= self
._parse
_file
(filename
, None, None, None)
226 # Build Symbol.dep for all symbols
229 def load_config(self
, filename
, replace
= True):
230 """Loads symbol values from a file in the familiar .config format.
231 Equivalent to calling Symbol.set_user_value() to set each of the
234 "# CONFIG_FOO is not set" within a .config file is treated specially
235 and sets the user value of FOO to 'n'. The C implementation works
238 filename -- The .config file to load. $-references to environment
239 variables will be expanded. For scripts to work even
240 when an alternative build directory is used with the
241 Linux kernel, you need to refer to the top-level kernel
242 directory with "$srctree".
244 replace (default: True) -- True if the configuration should replace
245 the old configuration; False if it should add to it."""
247 # Put this first so that a missing file doesn't screw up our state
248 filename
= os
.path
.expandvars(filename
)
249 line_feeder
= _FileFeed(filename
)
251 self
.config_filename
= filename
257 def is_header_line(line
):
258 return line
is not None and line
.startswith("#") and \
259 not _unset_re_match(line
)
261 self
.config_header
= None
263 line
= line_feeder
.peek_next()
264 if is_header_line(line
):
265 self
.config_header
= ""
266 while is_header_line(line_feeder
.peek_next()):
267 self
.config_header
+= line_feeder
.get_next()[1:]
268 # Remove trailing newline
269 if self
.config_header
.endswith("\n"):
270 self
.config_header
= self
.config_header
[:-1]
273 # Read assignments. Hotspot for some workloads.
276 def warn_override(filename
, linenr
, name
, old_user_val
, new_user_val
):
277 self
._warn
('overriding the value of {0}. '
278 'Old value: "{1}", new value: "{2}".'
279 .format(name
, old_user_val
, new_user_val
),
282 # Invalidate everything to keep things simple. It might be possible to
283 # improve performance for the case where multiple configurations are
284 # loaded by only invalidating a symbol (and its dependent symbols) if
285 # the new user value differs from the old. One complication would be
286 # that symbols not mentioned in the .config must lose their user value
287 # when replace = True, which is the usual case.
289 self
.unset_user_values()
291 self
._invalidate
_all
()
294 line
= line_feeder
.get_next()
300 set_match
= _set_re_match(line
)
302 name
, val
= set_match
.groups()
304 if val
.startswith(('"', "'")):
305 if len(val
) < 2 or val
[-1] != val
[0]:
306 _parse_error(line
, "malformed string literal",
307 line_feeder
.get_filename(),
308 line_feeder
.get_linenr())
309 # Strip quotes and remove escapings. The unescaping
310 # producedure should be safe since " can only appear as \"
312 val
= val
[1:-1].replace('\\"', '"').replace("\\\\", "\\")
314 if name
in self
.syms
:
315 sym
= self
.syms
[name
]
316 if sym
.user_val
is not None:
317 warn_override(line_feeder
.get_filename(),
318 line_feeder
.get_linenr(),
319 name
, sym
.user_val
, val
)
321 if sym
.is_choice_symbol_
:
322 user_mode
= sym
.parent
.user_mode
323 if user_mode
is not None and user_mode
!= val
:
324 self
._warn
("assignment to {0} changes mode of containing "
325 'choice from "{1}" to "{2}".'
326 .format(name
, val
, user_mode
),
327 line_feeder
.get_filename(),
328 line_feeder
.get_linenr())
330 sym
._set
_user
_value
_no
_invalidate
(val
, True)
332 if self
.print_undef_assign
:
333 _stderr_msg('note: attempt to assign the value "{0}" to the '
334 "undefined symbol {1}.".format(val
, name
),
335 line_feeder
.get_filename(),
336 line_feeder
.get_linenr())
338 unset_match
= _unset_re_match(line
)
340 name
= unset_match
.group(1)
341 if name
in self
.syms
:
342 sym
= self
.syms
[name
]
343 if sym
.user_val
is not None:
344 warn_override(line_feeder
.get_filename(),
345 line_feeder
.get_linenr(),
346 name
, sym
.user_val
, "n")
348 sym
._set
_user
_value
_no
_invalidate
("n", True)
350 def write_config(self
, filename
, header
= None):
351 """Writes out symbol values in the familiar .config format.
353 Kconfiglib makes sure the format matches what the C implementation
354 would generate, down to whitespace. This eases testing.
356 filename -- The filename under which to save the configuration.
358 header (default: None) -- A textual header that will appear at the
359 beginning of the file, with each line commented out
360 automatically. None means no header."""
362 # already_written is set when _make_conf() is called on a symbol, so
363 # that symbols defined in multiple locations only get one entry in the
364 # .config. We need to reset it prior to writing out a new .config.
365 for sym
in self
.syms_iter():
366 sym
.already_written
= False
368 with
open(filename
, "w") as f
:
370 if header
is not None:
371 f
.write(_comment(header
))
374 # Write configuration.
376 # Passing a list around to all the nodes and appending to it to
377 # avoid copying was surprisingly a lot slower with PyPy, and about
378 # as fast with Python. Passing the file around was slower too. Been
379 # a while since I last measured though.
381 f
.write("\n".join(_make_block_conf(self
.top_block
)))
384 def get_kconfig_filename(self
):
385 """Returns the name of the (base) kconfig file this configuration was
390 """Returns the value the environment variable ARCH had at the time the
391 Config instance was created, or None if ARCH was not set. For the
392 kernel, this corresponds to the architecture being built for, with
393 values such as "i386" or "mips"."""
396 def get_srcarch(self
):
397 """Returns the value the environment variable SRCARCH had at the time
398 the Config instance was created, or None if SRCARCH was not set. For
399 the kernel, this corresponds to the particular arch/ subdirectory
400 containing architecture-specific code."""
403 def get_srctree(self
):
404 """Returns the value the environment variable srctree had at the time
405 the Config instance was created, or None if srctree was not defined.
406 This variable points to the source directory and is used when building
407 in a separate directory."""
410 def get_config_filename(self
):
411 """Returns the filename of the most recently loaded configuration file,
412 or None if no configuration has been loaded."""
413 return self
.config_filename
415 def get_mainmenu_text(self
):
416 """Returns the text of the 'mainmenu' statement (with $-references to
417 symbols replaced by symbol values), or None if the configuration has no
418 'mainmenu' statement."""
419 return None if self
.mainmenu_text
is None else \
420 self
._expand
_sym
_refs
(self
.mainmenu_text
)
422 def get_defconfig_filename(self
):
423 """Returns the name of the defconfig file, which is the first existing
424 file in the list given in a symbol having 'option defconfig_list' set.
425 $-references to symbols will be expanded ("$FOO bar" -> "foo bar" if
426 FOO has the value "foo"). Returns None in case of no defconfig file.
427 Setting 'option defconfig_list' on multiple symbols currently results
428 in undefined behavior.
430 If the environment variable 'srctree' was set when the Config was
431 created, get_defconfig_filename() will first look relative to that
432 directory before looking in the current directory; see
435 WARNING: A wart here is that scripts/kconfig/Makefile sometimes uses the
436 --defconfig=<defconfig> option when calling the C implementation of e.g.
437 'make defconfig'. This option overrides the 'option defconfig_list'
438 symbol, meaning the result from get_defconfig_filename() might not
439 match what 'make defconfig' would use. That probably ought to be worked
440 around somehow, so that this function always gives the "expected"
442 if self
.defconfig_sym
is None:
444 for filename
, cond_expr
in self
.defconfig_sym
.def_exprs
:
445 if self
._eval
_expr
(cond_expr
) == "y":
446 filename
= self
._expand
_sym
_refs
(filename
)
447 # We first look in $srctree. os.path.join() won't work here as
448 # an absolute path in filename would override $srctree.
449 srctree_filename
= os
.path
.normpath(self
.srctree
+ "/" + filename
)
450 if os
.path
.exists(srctree_filename
):
451 return srctree_filename
452 if os
.path
.exists(filename
):
456 def get_symbol(self
, name
):
457 """Returns the symbol with name 'name', or None if no such symbol
458 appears in the configuration. An alternative shorthand is conf[name],
459 where conf is a Config instance, though that will instead raise
460 KeyError if the symbol does not exist."""
461 return self
.syms
.get(name
)
463 def get_top_level_items(self
):
464 """Returns a list containing the items (symbols, menus, choice
465 statements and comments) at the top level of the configuration -- that
466 is, all items that do not appear within a menu or choice. The items
467 appear in the same order as within the configuration."""
468 return self
.top_block
470 def get_symbols(self
, all_symbols
= True):
471 """Returns a list of symbols from the configuration. An alternative for
472 iterating over all defined symbols (in the order of definition) is
477 which relies on Config implementing __iter__() and is equivalent to
479 for sym in config.get_symbols(False):
482 all_symbols (default: True) -- If True, all symbols -- including special
483 and undefined symbols -- will be included in the result, in
484 an undefined order. If False, only symbols actually defined
485 and not merely referred to in the configuration will be
486 included in the result, and will appear in the order that
487 they are defined within the Kconfig configuration files."""
488 return self
.syms
.values() if all_symbols
else self
.kconfig_syms
490 def get_choices(self
):
491 """Returns a list containing all choice statements in the
492 configuration, in the order they appear in the Kconfig files."""
496 """Returns a list containing all menus in the configuration, in the
497 order they appear in the Kconfig files."""
500 def get_comments(self
):
501 """Returns a list containing all comments in the configuration, in the
502 order they appear in the Kconfig files."""
506 """Returns the value of the expression 's' -- where 's' is represented
507 as a string -- in the context of the configuration. Raises
508 Kconfig_Syntax_Error if syntax errors are detected in 's'.
510 For example, if FOO and BAR are tristate symbols at least one of which
511 has the value "y", then config.eval("y && (FOO || BAR)") => "y"
513 This function always yields a tristate value. To get the value of
514 non-bool, non-tristate symbols, use Symbol.get_value().
516 The result of this function is consistent with how evaluation works for
517 conditional expressions in the configuration as well as in the C
518 implementation. "m" and m are rewritten as '"m" && MODULES' and 'm &&
519 MODULES', respectively, and a result of "m" will get promoted to "y" if
520 we're running without modules.
522 Syntax checking is somewhat lax, partly to be compatible with lax
523 parsing in the C implementation."""
524 return self
._eval
_expr
(self
._parse
_expr
(self
._tokenize
(s
, True), # Feed
525 None, # Current symbol or choice
528 def get_config_header(self
):
529 """Returns the (uncommented) textual header of the .config file most
530 recently loaded with load_config(). Returns None if no .config file has
531 been loaded or if the most recently loaded .config file has no header.
532 The header comprises all lines up to but not including the first line
535 1. Does not start with "#"
536 2. Has the form "# CONFIG_FOO is not set."
538 return self
.config_header
540 def get_base_dir(self
):
541 """Returns the base directory relative to which 'source' statements
542 will work, passed as an argument to Config.__init__()."""
545 def set_print_warnings(self
, print_warnings
):
546 """Determines whether warnings related to this configuration (for
547 things like attempting to assign illegal values to symbols with
548 Symbol.set_user_value()) should be printed to stderr.
550 print_warnings -- True if warnings should be printed."""
551 self
.print_warnings
= print_warnings
553 def set_print_undef_assign(self
, print_undef_assign
):
554 """Determines whether informational messages related to assignments to
555 undefined symbols should be printed to stderr for this configuration.
557 print_undef_assign -- If True, such messages will be printed."""
558 self
.print_undef_assign
= print_undef_assign
560 def __getitem__(self
, key
):
561 """Returns the symbol with name 'name'. Raises KeyError if the symbol
562 does not appear in the configuration."""
563 return self
.syms
[key
]
566 """Convenience function for iterating over the set of all defined
567 symbols in the configuration, used like
572 The iteration happens in the order of definition within the Kconfig
573 configuration files. Symbols only referred to but not defined will not
574 be included, nor will the special symbols n, m, and y. If you want to
575 include such symbols as well, see config.get_symbols()."""
576 return iter(self
.kconfig_syms
)
578 def unset_user_values(self
):
579 """Resets the values of all symbols, as if Config.load_config() or
580 Symbol.set_user_value() had never been called."""
581 for sym
in self
.syms_iter():
582 sym
._unset
_user
_value
_no
_recursive
_invalidate
()
585 """Returns a string containing various information about the Config."""
586 return _sep_lines("Configuration",
587 "File : " + self
.filename
,
588 "Base directory : " + self
.base_dir
,
589 "Value of $ARCH at creation time : " +
590 ("(not set)" if self
.arch
is None else self
.arch
),
591 "Value of $SRCARCH at creation time : " +
592 ("(not set)" if self
.srcarch
is None else self
.srcarch
),
593 "Source tree (derived from $srctree;",
594 "defaults to '.' if $srctree isn't set) : " + self
.srctree
,
595 "Most recently loaded .config : " +
596 ("(no .config loaded)" if self
.config_filename
is None else
597 self
.config_filename
),
598 "Print warnings : " +
599 bool_str
[self
.print_warnings
],
600 "Print assignments to undefined symbols : " +
601 bool_str
[self
.print_undef_assign
])
607 def _invalidate_all(self
):
608 for sym
in self
.syms_iter():
611 def _tokenize(self
, s
, for_eval
= False, filename
= None, linenr
= None):
612 """Returns a _Feed instance containing tokens derived from the string
613 's'. Registers any new symbols encountered (via _sym_lookup()).
615 (I experimented with a pure regular expression implementation, but it
616 came out slower, less readable, and wouldn't have been as flexible.)
618 for_eval -- True when parsing an expression for a call to
619 Config.eval(), in which case we should not treat the first
620 token specially nor register new symbols."""
622 # lstrip() would work here too, but removing the '\n' at the end leads
623 # to earlier termination in the 'while' loop below, saving lots of
626 if s
== "" or s
[0] == "#":
630 i
= 0 # The current index in the string being tokenized
631 previous
= None # The previous token seen
634 # The initial word on a line is parsed specially. Let
635 # command_chars = [A-Za-z0-9_]. Then
636 # - leading non-command_chars characters on the line are ignored, and
637 # - the first token consists the following one or more command_chars
639 # This is why things like "----help--" are accepted.
641 initial_token_match
= _initial_token_re_match(s
)
642 if initial_token_match
is None:
644 # The current index in the string being tokenized
645 i
= initial_token_match
.end()
647 keyword
= _get_keyword(initial_token_match
.group(1))
649 # We expect a keyword as the first token
650 _tokenization_error(s
, filename
, linenr
)
651 if keyword
== T_HELP
:
652 # Avoid junk after "help", e.g. "---", being registered as a
654 return _Feed([T_HELP
])
658 # _tokenize() is a hotspot during parsing, and this speeds things up a
661 append
= tokens
.append
663 # Main tokenization loop. (Handles tokens past the first one.)
665 # Test for an identifier/keyword preceded by whitespace first; this
666 # is the most common case.
667 id_keyword_match
= _id_keyword_re_match(s
, i
)
669 # We have an identifier or keyword. The above also stripped any
671 name
= id_keyword_match
.group(1)
673 i
= id_keyword_match
.end()
676 keyword
= _get_keyword(name
)
677 if keyword
is not None:
679 # What would ordinarily be considered a name is treated as a
680 # string after certain tokens.
681 elif previous
in string_lex
:
684 # We're dealing with a symbol. _sym_lookup() will take care
685 # of allocating a new Symbol instance if it's the first
687 sym
= self
._sym
_lookup
(name
, not for_eval
)
689 if previous
== T_CONFIG
or previous
== T_MENUCONFIG
:
690 # If the previous token is T_(MENU)CONFIG
691 # ("(menu)config"), we're tokenizing the first line of
692 # a symbol definition, and should remember this as a
693 # location where the symbol is defined.
694 sym
.def_locations
.append((filename
, linenr
))
696 # Otherwise, it's a reference to the symbol
697 sym
.ref_locations
.append((filename
, linenr
))
702 # This restrips whitespace that could have been stripped in the
703 # regex above, but it's worth it since identifiers/keywords are
711 # String literal (constant symbol)
712 if c
== '"' or c
== "'":
714 # Slow path: This could probably be sped up, but it's a
715 # very unusual case anyway.
720 _tokenization_error(s
, filename
, linenr
)
726 _tokenization_error(s
, filename
, linenr
)
735 # Fast path: If the string contains no backslashes (almost
736 # always) we can simply look for the matching quote.
739 _tokenization_error(s
, filename
, linenr
)
744 # Invalid characters are ignored
745 if i
>= len(s
) or s
[i
] != "&": continue
750 # Invalid characters are ignored
751 if i
>= len(s
) or s
[i
] != "|": continue
756 if i
< len(s
) and s
[i
] == "=":
762 elif c
== "=": append(T_EQUAL
)
763 elif c
== "(": append(T_OPEN_PAREN
)
764 elif c
== ")": append(T_CLOSE_PAREN
)
765 elif c
== "#": break # Comment
767 else: continue # Invalid characters are ignored
769 previous
= tokens
[-1]
777 # Expression grammar:
780 # <symbol> '=' <symbol>
781 # <symbol> '!=' <symbol>
787 def _parse_expr(self
, feed
, cur_sym_or_choice
, line
, filename
= None,
788 linenr
= None, transform_m
= True):
789 """Parse an expression from the tokens in 'feed' using a simple
790 top-down approach. The result has the form (<operator>, <list
791 containing parsed operands>).
793 feed -- _Feed instance containing the tokens for the expression.
795 cur_sym_or_choice -- The symbol or choice currently being parsed, or
796 None if we're not parsing a symbol or choice.
797 Used for recording references to symbols.
799 line -- The line containing the expression being parsed.
801 filename (default: None) -- The file containing the expression.
803 linenr (default: None) -- The line number containing the expression.
805 transform_m (default: False) -- Determines if 'm' should be rewritten to
806 'm && MODULES' -- see
807 parse_val_and_cond()."""
809 # Use instance variables to avoid having to pass these as arguments
810 # through the top-down parser in _parse_expr_2(), which is tedious and
811 # obfuscates the code. A profiler run shows no noticeable performance
813 self
.parse_expr_cur_sym_or_choice
= cur_sym_or_choice
814 self
.parse_expr_line
= line
815 self
.parse_expr_filename
= filename
816 self
.parse_expr_linenr
= linenr
817 self
.parse_expr_transform_m
= transform_m
819 return self
._parse
_expr
_2(feed
)
821 def _parse_expr_2(self
, feed
):
822 or_terms
= [self
._parse
_or
_term
(feed
)]
823 # Keep parsing additional terms while the lookahead is '||'
824 while feed
.check(T_OR
):
825 or_terms
.append(self
._parse
_or
_term
(feed
))
826 return or_terms
[0] if len(or_terms
) == 1 else (OR
, or_terms
)
828 def _parse_or_term(self
, feed
):
829 and_terms
= [self
._parse
_factor
(feed
)]
830 # Keep parsing additional terms while the lookahead is '&&'
831 while feed
.check(T_AND
):
832 and_terms
.append(self
._parse
_factor
(feed
))
833 return and_terms
[0] if len(and_terms
) == 1 else (AND
, and_terms
)
835 def _parse_factor(self
, feed
):
836 if feed
.check(T_OPEN_PAREN
):
837 expr_parse
= self
._parse
_expr
_2(feed
)
839 if not feed
.check(T_CLOSE_PAREN
):
840 _parse_error(self
.parse_expr_line
,
841 "missing end parenthesis.",
842 self
.parse_expr_filename
,
843 self
.parse_expr_linenr
)
847 if feed
.check(T_NOT
):
848 return (NOT
, self
._parse
_factor
(feed
))
850 sym_or_string
= feed
.get_next()
852 if not isinstance(sym_or_string
, (Symbol
, str)):
853 _parse_error(self
.parse_expr_line
,
854 "malformed expression.",
855 self
.parse_expr_filename
,
856 self
.parse_expr_linenr
)
858 if self
.parse_expr_cur_sym_or_choice
is not None and \
859 isinstance(sym_or_string
, Symbol
):
860 self
.parse_expr_cur_sym_or_choice
.referenced_syms
.add(sym_or_string
)
862 next_token
= feed
.peek_next()
864 # For conditional expressions ('depends on <expr>', '... if <expr>',
865 # etc.), "m" and m are rewritten to "m" && MODULES.
866 if next_token
!= T_EQUAL
and next_token
!= T_UNEQUAL
:
867 if self
.parse_expr_transform_m
and (sym_or_string
is self
.m
or
868 sym_or_string
== "m"):
869 return (AND
, ["m", self
._sym
_lookup
("MODULES")])
872 relation
= EQUAL
if (feed
.get_next() == T_EQUAL
) else UNEQUAL
873 sym_or_string_2
= feed
.get_next()
875 if self
.parse_expr_cur_sym_or_choice
is not None and \
876 isinstance(sym_or_string_2
, Symbol
):
877 self
.parse_expr_cur_sym_or_choice
.referenced_syms
.add(sym_or_string_2
)
879 if sym_or_string
is self
.m
:
881 if sym_or_string_2
is self
.m
:
882 sym_or_string_2
= "m"
884 return (relation
, sym_or_string
, sym_or_string_2
)
886 def _parse_file(self
, filename
, parent
, deps
, visible_if_deps
, res
= None):
887 """Parses the Kconfig file 'filename'. Returns a list with the Items in
888 the file. See _parse_block() for the meaning of the parameters."""
889 return self
._parse
_block
(_FileFeed(filename
), None, parent
, deps
,
890 visible_if_deps
, res
)
892 def _parse_block(self
, line_feeder
, end_marker
, parent
, deps
,
893 visible_if_deps
= None, res
= None):
894 """Parses a block, which is the contents of either a file or an if,
895 menu, or choice statement. Returns a list with the Items in the block.
897 end_marker -- The token that ends the block, e.g. T_ENDIF ("endif") for
898 if's. None for files.
900 parent -- The enclosing menu, choice or if, or None if we're at the top
903 deps -- Dependencies from enclosing menus, choices and if's.
905 visible_if_deps (default: None) -- 'visible if' dependencies from
908 res (default: None) -- The list to add items to. If None, a new list is
909 created to hold the items."""
911 block
= [] if res
is None else res
914 # Do we already have a tokenized line that we determined wasn't
915 # part of whatever we were parsing earlier? See comment in
917 if self
.end_line
is not None:
919 tokens
= self
.end_line_tokens
923 self
.end_line_tokens
= None
925 line
= line_feeder
.get_next()
927 if end_marker
is not None:
928 raise Kconfig_Syntax_Error(
929 "Unexpected end of file {0}."
930 .format(line_feeder
.get_filename()))
933 tokens
= self
._tokenize
(line
, False,
934 line_feeder
.get_filename(),
935 line_feeder
.get_linenr())
937 t0
= tokens
.get_next()
941 # Cases are ordered roughly by frequency, which speeds things up a
944 if t0
== T_CONFIG
or t0
== T_MENUCONFIG
:
945 # The tokenizer will automatically allocate a new Symbol object
946 # for any new names it encounters, so we don't need to worry
948 sym
= tokens
.get_next()
950 # Symbols defined in multiple places get the parent of their
951 # first definition. However, for symbols whose parents are choice
952 # statements, the choice statement takes precedence.
953 if not sym
.is_defined_
or isinstance(parent
, Choice
):
956 sym
.is_defined_
= True
958 self
.kconfig_syms
.append(sym
)
961 self
._parse
_properties
(line_feeder
, sym
, deps
, visible_if_deps
)
964 kconfig_file
= tokens
.get_next()
965 exp_kconfig_file
= self
._expand
_sym
_refs
(kconfig_file
)
966 f
= os
.path
.join(self
.base_dir
, exp_kconfig_file
)
968 if not os
.path
.exists(f
):
969 raise IOError('{0}:{1}: sourced file "{2}" (expands to '
970 '"{3}") not found. Perhaps base_dir '
971 '(argument to Config.__init__(), currently '
972 '"{4}") is set to the wrong value.'
973 .format(line_feeder
.get_filename(),
974 line_feeder
.get_linenr(),
975 kconfig_file
, exp_kconfig_file
,
978 # Add items to the same block
979 self
._parse
_file
(f
, parent
, deps
, visible_if_deps
, block
)
981 elif t0
== end_marker
:
982 # We have reached the end of the block
986 # If statements are treated as syntactic sugar for adding
987 # dependencies to enclosed items and do not have an explicit
988 # object representation.
990 dep_expr
= self
._parse
_expr
(tokens
, None, line
,
991 line_feeder
.get_filename(),
992 line_feeder
.get_linenr())
993 self
._parse
_block
(line_feeder
,
996 _make_and(dep_expr
, deps
),
998 block
) # Add items to the same block
1000 elif t0
== T_COMMENT
:
1003 comment
.config
= self
1004 comment
.parent
= parent
1005 comment
.filename
= line_feeder
.get_filename()
1006 comment
.linenr
= line_feeder
.get_linenr()
1007 comment
.text
= tokens
.get_next()
1009 self
.comments
.append(comment
)
1010 block
.append(comment
)
1012 self
._parse
_properties
(line_feeder
, comment
, deps
, visible_if_deps
)
1018 menu
.parent
= parent
1019 menu
.filename
= line_feeder
.get_filename()
1020 menu
.linenr
= line_feeder
.get_linenr()
1021 menu
.title
= tokens
.get_next()
1023 self
.menus
.append(menu
)
1026 # Parse properties and contents
1027 self
._parse
_properties
(line_feeder
, menu
, deps
, visible_if_deps
)
1028 menu
.block
= self
._parse
_block
(line_feeder
,
1032 _make_and(visible_if_deps
,
1033 menu
.visible_if_expr
))
1035 elif t0
== T_CHOICE
:
1036 name
= tokens
.get_next()
1039 self
.choices
.append(choice
)
1042 choice
= self
.named_choices
.get(name
)
1046 self
.named_choices
[name
] = choice
1047 self
.choices
.append(choice
)
1049 choice
.config
= self
1050 choice
.parent
= parent
1052 choice
.def_locations
.append((line_feeder
.get_filename(),
1053 line_feeder
.get_linenr()))
1055 # Parse properties and contents
1056 self
._parse
_properties
(line_feeder
, choice
, deps
, visible_if_deps
)
1057 choice
.block
= self
._parse
_block
(line_feeder
,
1063 choice
._determine
_actual
_symbols
()
1065 # If no type is set for the choice, its type is that of the first
1067 if choice
.type == UNKNOWN
:
1068 for item
in choice
.get_symbols():
1069 if item
.type != UNKNOWN
:
1070 choice
.type = item
.type
1073 # Each choice item of UNKNOWN type gets the type of the choice
1074 for item
in choice
.get_symbols():
1075 if item
.type == UNKNOWN
:
1076 item
.type = choice
.type
1078 block
.append(choice
)
1080 elif t0
== T_MAINMENU
:
1081 text
= tokens
.get_next()
1083 if self
.mainmenu_text
is not None:
1084 self
._warn
("overriding 'mainmenu' text. "
1085 'Old value: "{0}", new value: "{1}".'
1086 .format(self
.mainmenu_text
, text
),
1087 line_feeder
.get_filename(),
1088 line_feeder
.get_linenr())
1090 self
.mainmenu_text
= text
1093 _parse_error(line
, "unrecognized construct.",
1094 line_feeder
.get_filename(),
1095 line_feeder
.get_linenr())
1097 def _parse_properties(self
, line_feeder
, stmt
, deps
, visible_if_deps
):
1098 """Parsing of properties for symbols, menus, choices, and comments."""
1100 def parse_val_and_cond(tokens
, line
, filename
, linenr
):
1101 """Parses '<expr1> if <expr2>' constructs, where the 'if' part is
1102 optional. Returns a tuple containing the parsed expressions, with
1103 None as the second element if the 'if' part is missing."""
1104 val
= self
._parse
_expr
(tokens
, stmt
, line
, filename
, linenr
, False)
1105 if tokens
.check(T_IF
):
1106 return (val
, self
._parse
_expr
(tokens
, stmt
, line
, filename
, linenr
))
1109 # In case the symbol is defined in multiple locations, we need to
1110 # remember what prompts, defaults, and selects are new for this
1111 # definition, as "depends on" should only apply to the local
1117 # Dependencies from 'depends on' statements
1118 depends_on_expr
= None
1121 line
= line_feeder
.get_next()
1125 filename
= line_feeder
.get_filename()
1126 linenr
= line_feeder
.get_linenr()
1128 tokens
= self
._tokenize
(line
, False, filename
, linenr
)
1130 t0
= tokens
.get_next()
1134 # Cases are ordered roughly by frequency, which speeds things up a
1138 if not tokens
.check(T_ON
):
1139 _parse_error(line
, 'expected "on" after "depends".', filename
, linenr
)
1141 parsed_deps
= self
._parse
_expr
(tokens
, stmt
, line
, filename
, linenr
)
1143 if isinstance(stmt
, (Menu
, Comment
)):
1144 stmt
.dep_expr
= _make_and(stmt
.dep_expr
, parsed_deps
)
1146 depends_on_expr
= _make_and(depends_on_expr
, parsed_deps
)
1149 # Find first non-blank (not all-space) line and get its
1152 line_feeder
.remove_blank()
1153 line
= line_feeder
.get_next()
1158 indent
= _indentation(line
)
1160 # If the first non-empty lines has zero indent, there is no
1163 line_feeder
.go_back()
1166 # The help text goes on till the first non-empty line with less
1168 help_lines
= [_deindent(line
, indent
)]
1170 line
= line_feeder
.get_next()
1171 if line
is None or \
1172 (not line
.isspace() and _indentation(line
) < indent
):
1173 stmt
.help = "".join(help_lines
)
1175 help_lines
.append(_deindent(line
, indent
))
1180 line_feeder
.go_back()
1182 elif t0
== T_SELECT
:
1183 target
= tokens
.get_next()
1185 stmt
.referenced_syms
.add(target
)
1186 stmt
.selected_syms
.add(target
)
1188 if tokens
.check(T_IF
):
1189 new_selects
.append((target
,
1190 self
._parse
_expr
(tokens
, stmt
, line
, filename
, linenr
)))
1192 new_selects
.append((target
, None))
1194 elif t0
in (T_BOOL
, T_TRISTATE
, T_INT
, T_HEX
, T_STRING
):
1195 stmt
.type = token_to_type
[t0
]
1197 new_prompt
= parse_val_and_cond(tokens
, line
, filename
, linenr
)
1199 elif t0
== T_DEFAULT
:
1200 new_def_exprs
.append(parse_val_and_cond(tokens
, line
, filename
, linenr
))
1202 elif t0
== T_DEF_BOOL
:
1205 new_def_exprs
.append(parse_val_and_cond(tokens
, line
, filename
, linenr
))
1207 elif t0
== T_PROMPT
:
1208 # 'prompt' properties override each other within a single
1209 # definition of a symbol, but additional prompts can be added
1210 # by defining the symbol multiple times; hence 'new_prompt'
1211 # instead of 'prompt'.
1212 new_prompt
= parse_val_and_cond(tokens
, line
, filename
, linenr
)
1215 lower
= tokens
.get_next()
1216 upper
= tokens
.get_next()
1217 stmt
.referenced_syms
.add(lower
)
1218 stmt
.referenced_syms
.add(upper
)
1220 if tokens
.check(T_IF
):
1221 stmt
.ranges
.append((lower
, upper
,
1222 self
._parse
_expr
(tokens
, stmt
, line
, filename
, linenr
)))
1224 stmt
.ranges
.append((lower
, upper
, None))
1226 elif t0
== T_DEF_TRISTATE
:
1227 stmt
.type = TRISTATE
1229 new_def_exprs
.append(parse_val_and_cond(tokens
, line
, filename
, linenr
))
1231 elif t0
== T_OPTION
:
1232 if tokens
.check(T_ENV
) and tokens
.check(T_EQUAL
):
1233 env_var
= tokens
.get_next()
1235 stmt
.is_special_
= True
1236 stmt
.is_from_env
= True
1238 if env_var
not in os
.environ
:
1239 self
._warn
("The symbol {0} references the "
1240 "non-existent environment variable {1} and "
1241 "will get the empty string as its value. "
1242 "If you're using kconfiglib via "
1243 "'make (i)scriptconfig', it should have "
1244 "set up the environment correctly for you. "
1245 "If you still got this message, that "
1246 "might be an error, and you should email "
1247 "ulfalizer a.t Google's email service."""
1248 .format(stmt.name, env_var),
1251 stmt.cached_val = ""
1253 stmt.cached_val = os.environ[env_var]
1255 elif tokens.check(T_DEFCONFIG_LIST):
1256 self.defconfig_sym = stmt
1258 elif tokens.check(T_MODULES):
1259 # To reduce warning spam, only warn if 'option modules' is
1260 # set on some symbol that isn't MODULES, which should be
1261 # safe. I haven't run into any projects that make use
1262 # modules besides the kernel yet, and there it's likely to
1263 # keep being called "MODULES
".
1264 if stmt.name != "MODULES
":
1265 self._warn("the
'modules' option
is not supported
. "
1266 "Let me know
if this
is a problem
for you
; "
1267 "it shouldn
't be that hard to implement. "
1268 "(Note that modules are still supported -- "
1269 "Kconfiglib just assumes the symbol name "
1270 "MODULES, like older versions of the C "
1271 "implementation did when 'option modules
' "
1275 elif tokens.check(T_ALLNOCONFIG_Y):
1276 if not isinstance(stmt, Symbol):
1278 "the
'allnoconfig_y' option
is only valid
for symbols
.",
1281 stmt.allnoconfig_y = True
1284 _parse_error(line, "unrecognized option
.", filename, linenr)
1286 elif t0 == T_VISIBLE:
1287 if not tokens.check(T_IF):
1288 _parse_error(line, 'expected "if" after "visible
".', filename, linenr)
1289 if not isinstance(stmt, Menu):
1291 "'visible if' is only valid
for menus
.",
1295 parsed_deps = self._parse_expr(tokens, stmt, line, filename, linenr)
1296 stmt.visible_if_expr = _make_and(stmt.visible_if_expr, parsed_deps)
1298 elif t0 == T_OPTIONAL:
1299 if not isinstance(stmt, Choice):
1301 '"optional
" is only valid for choices.',
1304 stmt.optional = True
1307 # See comment in Config.__init__()
1308 self.end_line = line
1309 self.end_line_tokens = tokens
1312 # Propagate dependencies from enclosing menus and if's.
1314 # For menus and comments..
1315 if isinstance(stmt, (Menu, Comment)):
1316 stmt.orig_deps = stmt.dep_expr
1317 stmt.deps_from_containing = deps
1318 stmt.dep_expr = _make_and(stmt.dep_expr, deps)
1320 stmt.all_referenced_syms = \
1321 stmt.referenced_syms | _get_expr_syms(deps)
1323 # For symbols and choices..
1326 # See comment for 'menu_dep'
1327 stmt.menu_dep = depends_on_expr
1329 # Propagate dependencies specified with 'depends on' to any new
1330 # default expressions, prompts, and selections. ("New
" since a
1331 # symbol might be defined in multiple places and the dependencies
1332 # should only apply to the local definition.)
1334 new_def_exprs = [(val_expr, _make_and(cond_expr, depends_on_expr))
1335 for val_expr, cond_expr in new_def_exprs]
1337 new_selects = [(target, _make_and(cond_expr, depends_on_expr))
1338 for target, cond_expr in new_selects]
1340 if new_prompt is not None:
1341 prompt, cond_expr = new_prompt
1343 # 'visible if' dependencies from enclosing menus get propagated
1345 if visible_if_deps is not None:
1346 cond_expr = _make_and(cond_expr, visible_if_deps)
1348 new_prompt = (prompt, _make_and(cond_expr, depends_on_expr))
1350 # We save the original expressions -- before any menu and if
1351 # conditions have been propagated -- so these can be retrieved
1354 stmt.orig_def_exprs.extend(new_def_exprs)
1355 if new_prompt is not None:
1356 stmt.orig_prompts.append(new_prompt)
1358 # Only symbols can select
1359 if isinstance(stmt, Symbol):
1360 stmt.orig_selects.extend(new_selects)
1362 # Save dependencies from enclosing menus and if's
1363 stmt.deps_from_containing = deps
1365 # The set of symbols referenced directly by the symbol/choice plus
1366 # all symbols referenced by enclosing menus and if's.
1367 stmt.all_referenced_syms = \
1368 stmt.referenced_syms | _get_expr_syms(deps)
1370 # Propagate dependencies from enclosing menus and if's
1372 stmt.def_exprs.extend([(val_expr, _make_and(cond_expr, deps))
1373 for val_expr, cond_expr in new_def_exprs])
1375 for target, cond in new_selects:
1376 target.rev_dep = _make_or(target.rev_dep,
1378 _make_and(cond, deps)))
1380 if new_prompt is not None:
1381 prompt, cond_expr = new_prompt
1382 stmt.prompts.append((prompt, _make_and(cond_expr, deps)))
1385 # Symbol table manipulation
1388 def _sym_lookup(self, name, add_sym_if_not_exists = True):
1389 """Fetches the symbol 'name' from the symbol table, optionally adding
1390 it if it does not exist (this is usually what we want)."""
1391 if name in self.syms:
1392 return self.syms[name]
1395 new_sym.config = self
1398 if add_sym_if_not_exists:
1399 self.syms[name] = new_sym
1401 # This warning is generated while evaluating an expression
1402 # containing undefined symbols using Config.eval()
1403 self._warn("no symbol {0}
in configuration
".format(name))
1408 # Evaluation of symbols and expressions
1411 def _eval_expr(self, expr):
1412 """Evaluates an expression and returns one of the tristate values "n
",
1414 res = self._eval_expr_2(expr)
1416 # Promote "m
" to "y
" if we're running without modules. Internally, "m
"
1417 # is often rewritten to "m
" && MODULES by both the C implementation and
1418 # kconfiglib, which takes care of cases where "m
" should be false if
1419 # we're running without modules.
1420 if res == "m
" and not self._has_modules():
1425 def _eval_expr_2(self, expr):
1429 if isinstance(expr, Symbol):
1430 # Non-bool/tristate symbols are always "n
" in a tristate sense,
1431 # regardless of their value
1432 if expr.type != BOOL and expr.type != TRISTATE:
1434 return expr.get_value()
1436 if isinstance(expr, str):
1437 return expr if (expr == "y
" or expr == "m
") else "n
"
1439 first_expr = expr[0]
1441 if first_expr == AND:
1443 for subexpr in expr[1]:
1444 ev = self._eval_expr_2(subexpr)
1445 # Return immediately upon discovering an "n
" term
1450 # 'res' is either "m
" or "y
" here; we already handled the
1451 # short-circuiting "n
" case in the loop.
1454 if first_expr == OR:
1456 for subexpr in expr[1]:
1457 ev = self._eval_expr_2(subexpr)
1458 # Return immediately upon discovering a "y
" term
1463 # 'res' is either "n
" or "m
" here; we already handled the
1464 # short-circuiting "y
" case in the loop.
1467 if first_expr == NOT:
1468 ev = self._eval_expr_2(expr[1])
1471 return "y
" if (ev == "n
") else "m
"
1473 if first_expr == EQUAL:
1474 return "y
" if (_str_val(expr[1]) == _str_val(expr[2])) else "n
"
1476 if first_expr == UNEQUAL:
1477 return "y
" if (_str_val(expr[1]) != _str_val(expr[2])) else "n
"
1479 _internal_error("Internal error
while evaluating expression
: "
1480 "unknown operation {0}
.".format(first_expr))
1482 def _eval_min(self, e1, e2):
1483 """Returns the minimum value of the two expressions. Equates None with
1485 e1_eval = self._eval_expr(e1)
1486 e2_eval = self._eval_expr(e2)
1487 return e1_eval if tri_less(e1_eval, e2_eval) else e2_eval
1489 def _eval_max(self, e1, e2):
1490 """Returns the maximum value of the two expressions. Equates None with
1492 e1_eval = self._eval_expr(e1)
1493 e2_eval = self._eval_expr(e2)
1494 return e1_eval if tri_greater(e1_eval, e2_eval) else e2_eval
1497 # Methods related to the MODULES symbol
1500 def _has_modules(self):
1501 modules_sym = self.syms.get("MODULES
")
1502 return (modules_sym is not None) and (modules_sym.get_value() == "y
")
1505 # Dependency tracking
1508 def _build_dep(self):
1509 """Populates the Symbol.dep sets, linking the symbol to the symbols
1510 that immediately depend on it in the sense that changing the value of
1511 the symbol might affect the values of those other symbols. This is used
1512 for caching/invalidation purposes. The calculated sets might be larger
1513 than necessary as we don't do any complicated analysis of the
1516 # Adds 'sym' as a directly dependent symbol to all symbols that appear
1517 # in the expression 'e'
1518 def add_expr_deps(e, sym):
1519 for s in _get_expr_syms(e):
1522 # The directly dependent symbols of a symbol are:
1523 # - Any symbols whose prompts, default values, rev_dep (select
1524 # condition), or ranges depend on the symbol
1525 # - Any symbols that belong to the same choice statement as the symbol
1526 # (these won't be included in 'dep' as that makes the dependency
1527 # graph unwieldy, but Symbol._get_dependent() will include them)
1528 # - Any symbols in a choice statement that depends on the symbol
1529 for sym in self.syms_iter():
1530 for _, e in sym.prompts:
1531 add_expr_deps(e, sym)
1533 for v, e in sym.def_exprs:
1534 add_expr_deps(v, sym)
1535 add_expr_deps(e, sym)
1537 add_expr_deps(sym.rev_dep, sym)
1539 for l, u, e in sym.ranges:
1540 add_expr_deps(l, sym)
1541 add_expr_deps(u, sym)
1542 add_expr_deps(e, sym)
1544 if sym.is_choice_symbol_:
1546 for _, e in choice.prompts:
1547 add_expr_deps(e, sym)
1548 for _, e in choice.def_exprs:
1549 add_expr_deps(e, sym)
1551 def _expr_val_str(self, expr, no_value_str = "(none
)", get_val_instead_of_eval = False):
1552 # Since values are valid expressions, _expr_to_str() will get a nice
1553 # string representation for those as well.
1558 if get_val_instead_of_eval:
1559 if isinstance(expr, str):
1560 return _expr_to_str(expr)
1561 val = expr.get_value()
1563 val = self._eval_expr(expr)
1565 return "{0}
(value
: {1}
)".format(_expr_to_str(expr), _expr_to_str(val))
1567 def _expand_sym_refs(self, s):
1568 """Expands $-references to symbols in 's' to symbol values, or to the
1569 empty string for undefined symbols."""
1572 sym_ref_match = _sym_ref_re_search(s)
1573 if sym_ref_match is None:
1576 sym_name = sym_ref_match.group(0)[1:]
1577 sym = self.syms.get(sym_name)
1578 expansion = "" if sym is None else sym.get_value()
1580 s = s[:sym_ref_match.start()] + \
1582 s[sym_ref_match.end():]
1584 def _get_sym_or_choice_str(self, sc):
1585 """Symbols and choices have many properties in common, so we factor out
1586 common __str__() stuff here. "sc
" is short for "symbol
or choice
"."""
1588 # As we deal a lot with string representations here, use some
1589 # convenient shorthand:
1593 # Common symbol/choice properties
1596 user_val_str = "(no user value
)" if sc.user_val is None else s(sc.user_val)
1598 # Build prompts string
1599 if sc.prompts == []:
1600 prompts_str = " (no prompts
)"
1602 prompts_str_rows = []
1603 for prompt, cond_expr in sc.orig_prompts:
1604 if cond_expr is None:
1605 prompts_str_rows.append(' "{0}
"'.format(prompt))
1607 prompts_str_rows.append(' "{0}
" if {1}'
1608 .format(prompt, self._expr_val_str(cond_expr)))
1609 prompts_str = "\n".join(prompts_str_rows)
1611 # Build locations string
1612 if sc.def_locations == []:
1613 locations_str = "(no locations
)"
1615 locations_str = " ".join(["{0}
:{1}
".format(filename, linenr) for
1616 (filename, linenr) in sc.def_locations])
1618 # Build additional-dependencies-from-menus-and-if's string
1619 additional_deps_str = " " + self._expr_val_str(sc.deps_from_containing,
1620 "(no additional dependencies
)")
1623 # Symbol-specific stuff
1626 if isinstance(sc, Symbol):
1627 # Build ranges string
1628 if isinstance(sc, Symbol):
1630 ranges_str = " (no ranges
)"
1632 ranges_str_rows = []
1633 for l, u, cond_expr in sc.ranges:
1634 if cond_expr is None:
1635 ranges_str_rows.append(" [{0}
, {1}
]".format(s(l), s(u)))
1637 ranges_str_rows.append(" [{0}
, {1}
] if {2}
"
1638 .format(s(l), s(u), self._expr_val_str(cond_expr)))
1639 ranges_str = "\n".join(ranges_str_rows)
1641 # Build default values string
1642 if sc.def_exprs == []:
1643 defaults_str = " (no default values
)"
1645 defaults_str_rows = []
1646 for val_expr, cond_expr in sc.orig_def_exprs:
1647 row_str = " " + self._expr_val_str(val_expr, "(none
)", sc.type == STRING)
1648 defaults_str_rows.append(row_str)
1649 defaults_str_rows.append(" Condition
: " + self._expr_val_str(cond_expr))
1650 defaults_str = "\n".join(defaults_str_rows)
1652 # Build selects string
1653 if sc.orig_selects == []:
1654 selects_str = " (no selects
)"
1656 selects_str_rows = []
1657 for target, cond_expr in sc.orig_selects:
1658 if cond_expr is None:
1659 selects_str_rows.append(" {0}
".format(target.name))
1661 selects_str_rows.append(" {0}
if ".format(target.name) +
1662 self._expr_val_str(cond_expr))
1663 selects_str = "\n".join(selects_str_rows)
1665 res = _sep_lines("Symbol
" +
1666 ("(no name
)" if sc.name is None else sc.name),
1667 "Type
: " + typename[sc.type],
1668 "Value
: " + s(sc.get_value()),
1669 "User value
: " + user_val_str,
1670 "Visibility
: " + s(sc.get_visibility()),
1671 "Is choice item
: " + bool_str[sc.is_choice_symbol_],
1672 "Is defined
: " + bool_str[sc.is_defined_],
1673 "Is
from env
. : " + bool_str[sc.is_from_env],
1674 "Is special
: " + bool_str[sc.is_special_] + "\n")
1676 res += _sep_lines("Ranges
:",
1678 res += _sep_lines("Prompts
:",
1684 "Reverse (select
-related
) dependencies
:",
1685 " (no reverse dependencies
)" if sc.rev_dep == "n
"
1686 else " " + self._expr_val_str(sc.rev_dep),
1687 "Additional dependencies
from enclosing menus
and if's:",
1688 additional_deps_str,
1689 "Locations: " + locations_str)
1694 # Choice-specific stuff
1697 # Build selected symbol string
1698 sel = sc.get_selection()
1699 sel_str = "(no selection)" if sel is None else sel.name
1701 # Build default values string
1702 if sc.def_exprs == []:
1703 defaults_str = " (no default values)"
1705 defaults_str_rows = []
1706 for sym, cond_expr in sc.orig_def_exprs:
1707 if cond_expr is None:
1708 defaults_str_rows.append(" {0}".format(sym.name))
1710 defaults_str_rows.append(" {0} if ".format(sym.name) +
1711 self._expr_val_str(cond_expr))
1712 defaults_str = "\n".join(defaults_str_rows)
1714 # Build contained symbols string
1715 names = [sym.name for sym in sc.get_symbols()]
1716 syms_string = "(empty)" if names == [] else " ".join(names)
1718 return _sep_lines("Choice",
1719 "Name (for named choices): " +
1720 ("(no name)" if sc.name is None else sc.name),
1721 "Type : " + typename[sc.type],
1722 "Selected symbol : " + sel_str,
1723 "User value : " + user_val_str,
1724 "Mode : " + s(sc.get_mode()),
1725 "Visibility : " + s(sc.get_visibility()),
1726 "Optional : " + bool_str[sc.optional],
1733 "Additional dependencies from enclosing menus and if's
:",
1734 additional_deps_str,
1735 "Locations
: " + locations_str)
1737 def _expr_depends_on(self, expr, sym):
1738 """Reimplementation of expr_depends_symbol() from mconf.c. Used to
1739 determine if a submenu should be implicitly created, which influences what
1740 items inside choice statements are considered choice items."""
1745 if isinstance(expr, str):
1747 if isinstance(expr, Symbol):
1751 if e0 == EQUAL or e0 == UNEQUAL:
1752 return self._eq_to_sym(expr) is sym
1754 for and_expr in expr[1]:
1761 def _eq_to_sym(self, eq):
1762 """_expr_depends_on() helper. For (in)equalities of the form sym = y/m
1763 or sym != n, returns sym. For other (in)equalities, returns None."""
1764 relation, left, right = eq
1765 left = self._transform_n_m_y(left)
1766 right = self._transform_n_m_y(right)
1768 # Make sure the symbol (if any) appears to the left
1769 if not isinstance(left, Symbol):
1770 left, right = right, left
1771 if not isinstance(left, Symbol):
1773 if (relation == EQUAL and (right == "y
" or right == "m
")) or \
1774 (relation == UNEQUAL and right == "n
"):
1778 def _transform_n_m_y(self, item):
1779 """_eq_to_sym() helper. Translates the symbols n, m, and y to their
1780 string equivalents."""
1789 def _warn(self, msg, filename = None, linenr = None):
1790 """For printing warnings to stderr."""
1791 if self.print_warnings:
1792 _stderr_msg("warning
: " + msg, filename, linenr)
1796 """Base class for symbols and other Kconfig constructs. Subclasses are
1797 Symbol, Choice, Menu, and Comment."""
1799 def is_symbol(self):
1800 """Returns True if the item is a symbol. Short for
1801 isinstance(item, kconfiglib.Symbol)."""
1802 return isinstance(self, Symbol)
1804 def is_choice(self):
1805 """Returns True if the item is a choice. Short for
1806 isinstance(item, kconfiglib.Choice)."""
1807 return isinstance(self, Choice)
1810 """Returns True if the item is a menu. Short for
1811 isinstance(item, kconfiglib.Menu)."""
1812 return isinstance(self, Menu)
1814 def is_comment(self):
1815 """Returns True if the item is a comment. Short for
1816 isinstance(item, kconfiglib.Comment)."""
1817 return isinstance(self, Comment)
1821 """Represents a configuration symbol - e.g. FOO for
1830 def get_value(self):
1831 """Calculate and return the value of the symbol. See also
1832 Symbol.set_user_value()."""
1834 if self.cached_val is not None:
1835 return self.cached_val
1837 self.write_to_conf = False
1839 # As a quirk of Kconfig, undefined symbols get their name as their
1840 # value. This is why things like "FOO
= bar
" work for seeing if FOO has
1842 if self.type == UNKNOWN:
1843 self.cached_val = self.name
1846 new_val = default_value[self.type]
1848 vis = _get_visibility(self)
1850 if self.type == BOOL or self.type == TRISTATE:
1851 # The visibility and mode (modules-only or single-selection) of
1852 # choice items will be taken into account in _get_visibility()
1853 if self.is_choice_symbol_:
1855 choice = self.parent
1856 mode = choice.get_mode()
1858 self.write_to_conf = (mode != "n
")
1861 new_val = "y
" if (choice.get_selection() is self) else "n
"
1863 if self.user_val == "m
" or self.user_val == "y
":
1867 # If the symbol is visible and has a user value, use that.
1868 # Otherwise, look at defaults.
1872 self.write_to_conf = True
1873 if self.user_val is not None:
1874 new_val = self.config._eval_min(self.user_val, vis)
1875 use_defaults = False
1878 for val_expr, cond_expr in self.def_exprs:
1879 cond_eval = self.config._eval_expr(cond_expr)
1880 if cond_eval != "n
":
1881 self.write_to_conf = True
1882 new_val = self.config._eval_min(val_expr, cond_eval)
1885 # Reverse (select-related) dependencies take precedence
1886 rev_dep_val = self.config._eval_expr(self.rev_dep)
1887 if rev_dep_val != "n
":
1888 self.write_to_conf = True
1889 new_val = self.config._eval_max(new_val, rev_dep_val)
1891 # Promote "m
" to "y
" for booleans
1892 if new_val == "m
" and self.type == BOOL:
1895 elif self.type == STRING:
1899 self.write_to_conf = True
1900 if self.user_val is not None:
1901 new_val = self.user_val
1902 use_defaults = False
1905 for val_expr, cond_expr in self.def_exprs:
1906 if self.config._eval_expr(cond_expr) != "n
":
1907 self.write_to_conf = True
1908 new_val = _str_val(val_expr)
1911 elif self.type == HEX or self.type == INT:
1912 has_active_range = False
1917 base = 16 if self.type == HEX else 10
1919 for(l, h, cond_expr) in self.ranges:
1920 if self.config._eval_expr(cond_expr) != "n
":
1921 has_active_range = True
1923 low_str = _str_val(l)
1924 high_str = _str_val(h)
1925 low = int(low_str, base) if \
1926 _is_base_n(low_str, base) else 0
1927 high = int(high_str, base) if \
1928 _is_base_n(high_str, base) else 0
1933 self.write_to_conf = True
1935 if self.user_val is not None and \
1936 _is_base_n(self.user_val, base) and \
1937 (not has_active_range or
1938 low <= int(self.user_val, base) <= high):
1940 # If the user value is OK, it is stored in exactly the same
1941 # form as specified in the assignment (with or without
1944 use_defaults = False
1945 new_val = self.user_val
1948 for val_expr, cond_expr in self.def_exprs:
1949 if self.config._eval_expr(cond_expr) != "n
":
1950 self.write_to_conf = True
1952 # If the default value is OK, it is stored in exactly
1953 # the same form as specified. Otherwise, it is clamped
1954 # to the range, and the output has "0x
" as appropriate
1957 new_val = _str_val(val_expr)
1959 if _is_base_n(new_val, base):
1960 new_val_num = int(new_val, base)
1961 if has_active_range:
1964 if new_val_num < low:
1966 elif new_val_num > high:
1969 if clamped_val is not None:
1970 new_val = (hex(clamped_val) if \
1971 self.type == HEX else str(clamped_val))
1974 else: # For the for loop
1975 # If no user value or default kicks in but the hex/int has
1976 # an active range, then the low end of the range is used,
1977 # provided it's > 0, with "0x
" prepended as appropriate.
1978 if has_active_range and low > 0:
1979 new_val = (hex(low) if self.type == HEX else str(low))
1981 self.cached_val = new_val
1984 def set_user_value(self, v):
1985 """Sets the user value of the symbol.
1987 Equal in effect to assigning the value to the symbol within a .config
1988 file. Use get_lower/upper_bound() or get_assignable_values() to find
1989 the range of currently assignable values for bool and tristate symbols;
1990 setting values outside this range will cause the user value to differ
1991 from the result of Symbol.get_value() (be truncated). Values that are
1992 invalid for the type (such as a_bool.set_user_value("foo
")) are
1993 ignored, and a warning is emitted if an attempt is made to assign such
1996 For any type of symbol, is_modifiable() can be used to check if a user
1997 value will currently have any effect on the symbol, as determined by
1998 its visibility and range of assignable values. Any value that is valid
1999 for the type (bool, tristate, etc.) will end up being reflected in
2000 get_user_value() though, and might have an effect later if conditions
2001 change. To get rid of the user value, use unset_user_value().
2003 Any symbols dependent on the symbol are (recursively) invalidated, so
2004 things will just work with regards to dependencies.
2006 v -- The user value to give to the symbol."""
2007 self._set_user_value_no_invalidate(v, False)
2009 # There might be something more efficient you could do here, but play
2011 if self.name == "MODULES
":
2012 self.config._invalidate_all()
2016 self._invalidate_dependent()
2018 def unset_user_value(self):
2019 """Resets the user value of the symbol, as if the symbol had never
2020 gotten a user value via Config.load_config() or
2021 Symbol.set_user_value()."""
2022 self._unset_user_value_no_recursive_invalidate()
2023 self._invalidate_dependent()
2025 def get_user_value(self):
2026 """Returns the value assigned to the symbol in a .config or via
2027 Symbol.set_user_value() (provided the value was valid for the type of the
2028 symbol). Returns None in case of no user value."""
2029 return self.user_val
2032 """Returns the name of the symbol."""
2035 def get_prompts(self):
2036 """Returns a list of prompts defined for the symbol, in the order they
2037 appear in the configuration files. Returns the empty list for symbols
2040 This list will have a single entry for the vast majority of symbols
2041 having prompts, but having multiple prompts for a single symbol is
2042 possible through having multiple 'config' entries for it."""
2043 return [prompt for prompt, _ in self.orig_prompts]
2045 def get_upper_bound(self):
2046 """For string/hex/int symbols and for bool and tristate symbols that
2047 cannot be modified (see is_modifiable()), returns None.
2049 Otherwise, returns the highest value the symbol can be set to with
2050 Symbol.set_user_value() (that will not be truncated): one of "m
" or "y
",
2051 arranged from lowest to highest. This corresponds to the highest value
2052 the symbol could be given in e.g. the 'make menuconfig' interface.
2054 See also the tri_less*() and tri_greater*() functions, which could come
2056 if self.type != BOOL and self.type != TRISTATE:
2058 rev_dep = self.config._eval_expr(self.rev_dep)
2059 # A bool selected to "m
" gets promoted to "y
"
2060 if self.type == BOOL and rev_dep == "m
":
2062 vis = _get_visibility(self)
2063 if (tri_to_int[vis] - tri_to_int[rev_dep]) > 0:
2067 def get_lower_bound(self):
2068 """For string/hex/int symbols and for bool and tristate symbols that
2069 cannot be modified (see is_modifiable()), returns None.
2071 Otherwise, returns the lowest value the symbol can be set to with
2072 Symbol.set_user_value() (that will not be truncated): one of "n
" or "m
",
2073 arranged from lowest to highest. This corresponds to the lowest value
2074 the symbol could be given in e.g. the 'make menuconfig' interface.
2076 See also the tri_less*() and tri_greater*() functions, which could come
2078 if self.type != BOOL and self.type != TRISTATE:
2080 rev_dep = self.config._eval_expr(self.rev_dep)
2081 # A bool selected to "m
" gets promoted to "y
"
2082 if self.type == BOOL and rev_dep == "m
":
2084 if (tri_to_int[_get_visibility(self)] - tri_to_int[rev_dep]) > 0:
2088 def get_assignable_values(self):
2089 """For string/hex/int symbols and for bool and tristate symbols that
2090 cannot be modified (see is_modifiable()), returns the empty list.
2092 Otherwise, returns a list containing the user values that can be
2093 assigned to the symbol (that won't be truncated). Usage example:
2095 if "m
" in sym.get_assignable_values():
2096 sym.set_user_value("m
")
2098 This is basically a more convenient interface to
2099 get_lower/upper_bound() when wanting to test if a particular tristate
2100 value can be assigned."""
2101 if self.type != BOOL and self.type != TRISTATE:
2103 rev_dep = self.config._eval_expr(self.rev_dep)
2104 # A bool selected to "m
" gets promoted to "y
"
2105 if self.type == BOOL and rev_dep == "m
":
2107 res = ["n
", "m
", "y
"][tri_to_int[rev_dep] :
2108 tri_to_int[_get_visibility(self)] + 1]
2109 return res if len(res) > 1 else []
2112 """Returns the type of the symbol: one of UNKNOWN, BOOL, TRISTATE,
2113 STRING, HEX, or INT. These are defined at the top level of the module,
2114 so you'd do something like
2116 if sym.get_type() == kconfiglib.STRING:
2120 def get_visibility(self):
2121 """Returns the visibility of the symbol: one of "n
", "m
" or "y
". For
2122 bool and tristate symbols, this is an upper bound on the value users
2123 can set for the symbol. For other types of symbols, a visibility of "n
"
2124 means the user value will be ignored. A visibility of "n
" corresponds
2125 to not being visible in the 'make *config' interfaces.
2127 Example (assuming we're running with modules enabled -- i.e., MODULES
2130 # Assume this has been assigned 'n'
2134 # Assume this has been assigned 'm'
2138 # Has visibility 'n'
2143 # Has visibility 'm'
2148 # Has visibility 'y'
2152 # Has no prompt, and hence visibility 'n'
2156 Having visibility be tri-valued ensures that e.g. a symbol cannot be
2157 set to "y
" by the user if it depends on a symbol with value "m
", which
2160 You should probably look at get_lower/upper_bound(),
2161 get_assignable_values() and is_modifiable() before using this."""
2162 return _get_visibility(self)
2164 def get_parent(self):
2165 """Returns the menu or choice statement that contains the symbol, or
2166 None if the symbol is at the top level. Note that if statements are
2167 treated as syntactic and do not have an explicit class
2171 def get_referenced_symbols(self, refs_from_enclosing = False):
2172 """Returns the set() of all symbols referenced by this symbol. For
2173 example, the symbol defined by
2177 prompt "foo
" if A && B
2182 references the symbols A through G.
2184 refs_from_enclosing (default: False) -- If True, the symbols
2185 referenced by enclosing menus and if's will be
2186 included in the result."""
2187 return self.all_referenced_syms if refs_from_enclosing else self.referenced_syms
2189 def get_selected_symbols(self):
2190 """Returns the set() of all symbols X for which this symbol has a
2191 'select X' or 'select X if Y' (regardless of whether Y is satisfied or
2192 not). This is a subset of the symbols returned by
2193 get_referenced_symbols()."""
2194 return self.selected_syms
2197 """Returns the help text of the symbol, or None if the symbol has no
2201 def get_config(self):
2202 """Returns the Config instance this symbol is from."""
2205 def get_def_locations(self):
2206 """Returns a list of (filename, linenr) tuples, where filename (string)
2207 and linenr (int) represent a location where the symbol is defined. For
2208 the vast majority of symbols this list will only contain one element.
2209 For the following Kconfig, FOO would get two entries: the lines marked
2218 return self.def_locations
2220 def get_ref_locations(self):
2221 """Returns a list of (filename, linenr) tuples, where filename (string)
2222 and linenr (int) represent a location where the symbol is referenced in
2223 the configuration. For example, the lines marked by * would be included
2228 default BAR || FOO *
2240 config FOO (definition not included)
2243 return self.ref_locations
2245 def is_modifiable(self):
2246 """Returns True if the value of the symbol could be modified by calling
2247 Symbol.set_user_value().
2249 For bools and tristates, this corresponds to the symbol being visible
2250 in the 'make menuconfig' interface and not already being pinned to a
2251 specific value (e.g. because it is selected by another symbol).
2253 For strings and numbers, this corresponds to just being visible. (See
2254 Symbol.get_visibility().)"""
2255 if self.is_special_:
2257 if self.type == BOOL or self.type == TRISTATE:
2258 rev_dep = self.config._eval_expr(self.rev_dep)
2259 # A bool selected to "m
" gets promoted to "y
"
2260 if self.type == BOOL and rev_dep == "m
":
2262 return (tri_to_int[_get_visibility(self)] -
2263 tri_to_int[rev_dep]) > 0
2264 return _get_visibility(self) != "n
"
2266 def is_defined(self):
2267 """Returns False if the symbol is referred to in the Kconfig but never
2268 actually defined."""
2269 return self.is_defined_
2271 def is_special(self):
2272 """Returns True if the symbol is one of the special symbols n, m, y, or
2273 UNAME_RELEASE, or gets its value from the environment."""
2274 return self.is_special_
2276 def is_from_environment(self):
2277 """Returns True if the symbol gets its value from the environment."""
2278 return self.is_from_env
2280 def has_ranges(self):
2281 """Returns True if the symbol is of type INT or HEX and has ranges that
2282 limit what values it can take on."""
2283 return self.ranges != []
2285 def is_choice_symbol(self):
2286 """Returns True if the symbol is in a choice statement and is an actual
2287 choice symbol (see Choice.get_symbols())."""
2288 return self.is_choice_symbol_
2290 def is_choice_selection(self):
2291 """Returns True if the symbol is contained in a choice statement and is
2292 the selected item. Equivalent to
2293 'sym.is_choice_symbol() and sym.get_parent().get_selection() is sym'."""
2294 return self.is_choice_symbol_ and self.parent.get_selection() is self
2296 def is_allnoconfig_y(self):
2297 """Returns True if the symbol has the 'allnoconfig_y' option set."""
2298 return self.allnoconfig_y
2301 """Returns a string containing various information about the symbol."""
2302 return self.config._get_sym_or_choice_str(self)
2309 """Symbol constructor -- not intended to be called directly by
2310 kconfiglib clients."""
2313 self.cached_visibility = None
2325 # The prompt, default value and select conditions without any
2326 # dependencies from menus or if's propagated to them
2328 self.orig_prompts = []
2329 self.orig_def_exprs = []
2330 self.orig_selects = []
2332 # Dependencies inherited from containing menus and if's
2333 self.deps_from_containing = None
2337 # The set of symbols referenced by this symbol (see
2338 # get_referenced_symbols())
2339 self.referenced_syms = set()
2341 # The set of symbols selected by this symbol (see
2342 # get_selected_symbols())
2343 self.selected_syms = set()
2345 # Like 'referenced_syms', but includes symbols from
2346 # dependencies inherited from enclosing menus and if's
2347 self.all_referenced_syms = set()
2349 # This is set to True for "actual
" choice symbols. See
2350 # Choice._determine_actual_symbols(). The trailing underscore avoids a
2351 # collision with is_choice_symbol().
2352 self.is_choice_symbol_ = False
2354 # This records only dependencies specified with 'depends on'. Needed
2355 # when determining actual choice items (hrrrr...). See also
2356 # Choice._determine_actual_symbols().
2357 self.menu_dep = None
2359 # See Symbol.get_ref/def_locations().
2360 self.def_locations = []
2361 self.ref_locations = []
2363 self.user_val = None
2367 # Should the symbol get an entry in .config?
2368 self.write_to_conf = False
2370 # Caches the calculated value
2371 self.cached_val = None
2373 # Populated in Config._build_dep() after parsing. Links the symbol to
2374 # the symbols that immediately depend on it (in a caching/invalidation
2375 # sense). The total set of dependent symbols for the symbol (the
2376 # transitive closure) is calculated on an as-needed basis in
2380 # Caches the total list of dependent symbols. Calculated in
2382 self.cached_deps = None
2384 # Does the symbol have an entry in the Kconfig file? The trailing
2385 # underscore avoids a collision with is_defined().
2386 self.is_defined_ = False
2388 # Does the symbol get its value in some special way, e.g. from the
2389 # environment or by being one of the special symbols n, m, and y? If
2390 # so, the value is stored in self.cached_val, which is never
2391 # invalidated. The trailing underscore avoids a collision with
2393 self.is_special_ = False
2395 # Does the symbol get its value from the environment?
2396 self.is_from_env = False
2398 # Does the symbol have the 'allnoconfig_y' option set?
2399 self.allnoconfig_y = False
2401 def _invalidate(self):
2402 if self.is_special_:
2405 if self.is_choice_symbol_:
2406 self.parent._invalidate()
2408 self.cached_val = None
2409 self.cached_visibility = None
2410 self.write_to_conf = False
2412 def _invalidate_dependent(self):
2413 for sym in self._get_dependent():
2416 def _set_user_value_no_invalidate(self, v, suppress_load_warnings):
2417 """Like set_user_value(), but does not invalidate any symbols.
2419 suppress_load_warnings --
2420 some warnings are annoying when loading a .config that can be helpful
2421 when manually invoking set_user_value(). This flag is set to True to
2422 suppress such warnings.
2424 Perhaps this could be made optional for load_config() instead."""
2426 if self.is_special_:
2427 if self.is_from_env:
2428 self.config._warn('attempt to assign the value "{0}
" to the '
2429 'symbol {1}, which gets its value from the '
2430 'environment. Assignment ignored.'
2431 .format(v, self.name))
2433 self.config._warn('attempt to assign the value "{0}
" to the '
2434 'special symbol {1}. Assignment ignored.'
2435 .format(v, self.name))
2438 if not self.is_defined_:
2439 filename, linenr = self.ref_locations[0]
2440 if self.config.print_undef_assign:
2441 _stderr_msg('note: attempt to assign the value "{0}
" to {1}, '
2442 "which
is referenced at {2}
:{3} but never
"
2443 "defined
. Assignment ignored
."
2444 .format(v, self.name, filename, linenr))
2447 # Check if the value is valid for our type
2448 if not ((self.type == BOOL and (v == "y
" or v == "n
") ) or
2449 (self.type == TRISTATE and (v == "y
" or v == "m
" or
2451 (self.type == STRING ) or
2452 (self.type == INT and _is_base_n(v, 10) ) or
2453 (self.type == HEX and _is_base_n(v, 16) )):
2454 self.config._warn('the value "{0}
" is invalid for {1}, which has type {2}. '
2455 "Assignment ignored
."
2456 .format(v, self.name, typename[self.type]))
2459 if self.prompts == [] and not suppress_load_warnings:
2460 self.config._warn('assigning "{0}
" to the symbol {1} which '
2461 'lacks prompts and thus has visibility "n
". '
2462 'The assignment will have no effect.'
2463 .format(v, self.name))
2467 if self.is_choice_symbol_ and (self.type == BOOL or
2468 self.type == TRISTATE):
2469 choice = self.parent
2471 choice.user_val = self
2472 choice.user_mode = "y
"
2474 choice.user_val = None
2475 choice.user_mode = "m
"
2477 def _unset_user_value_no_recursive_invalidate(self):
2479 self.user_val = None
2481 if self.is_choice_symbol_:
2482 self.parent._unset_user_value()
2484 def _make_conf(self):
2485 if self.already_written:
2488 self.already_written = True
2490 # Note: write_to_conf is determined in get_value()
2491 val = self.get_value()
2492 if not self.write_to_conf:
2495 if self.type == BOOL or self.type == TRISTATE:
2496 if val == "m
" or val == "y
":
2497 return ["CONFIG_{0}
={1}
".format(self.name, val)]
2498 return ["# CONFIG_{0} is not set".format(self.name)]
2500 elif self
.type == STRING
:
2502 return ['CONFIG_{0}="{1}"'
2504 val
.replace("\\", "\\\\").replace('"', '\\"'))]
2506 elif self
.type == INT
or self
.type == HEX
:
2507 return ["CONFIG_{0}={1}".format(self
.name
, val
)]
2510 _internal_error('Internal error while creating .config: unknown type "{0}".'
2513 def _get_dependent(self
):
2514 """Returns the set of symbols that should be invalidated if the value
2515 of the symbol changes, because they might be affected by the change.
2516 Note that this is an internal API -- it's probably of limited
2517 usefulness to clients."""
2518 if self
.cached_deps
is not None:
2519 return self
.cached_deps
2523 self
._add
_dependent
_ignore
_siblings
(res
)
2524 if self
.is_choice_symbol_
:
2525 for s
in self
.parent
.get_symbols():
2528 s
._add
_dependent
_ignore
_siblings
(res
)
2530 self
.cached_deps
= res
2533 def _add_dependent_ignore_siblings(self
, to
):
2534 """Calculating dependencies gets a bit tricky for choice items as they
2535 all depend on each other, potentially leading to infinite recursion.
2536 This helper function calculates dependencies ignoring the other symbols
2537 in the choice. It also works fine for symbols that are not choice
2541 to |
= s
._get
_dependent
()
2543 def _has_auto_menu_dep_on(self
, on
):
2544 """See Choice._determine_actual_symbols()."""
2545 if not isinstance(self
.parent
, Choice
):
2546 _internal_error("Attempt to determine auto menu dependency for symbol ouside of choice.")
2548 if self
.prompts
== []:
2549 # If we have no prompt, use the menu dependencies instead (what was
2550 # specified with 'depends on')
2551 return self
.menu_dep
is not None and \
2552 self
.config
._expr
_depends
_on
(self
.menu_dep
, on
)
2554 for _
, cond_expr
in self
.prompts
:
2555 if self
.config
._expr
_depends
_on
(cond_expr
, on
):
2562 """Represents a menu statement."""
2568 def get_config(self
):
2569 """Return the Config instance this menu is from."""
2572 def get_visibility(self
):
2573 """Returns the visibility of the menu. This also affects the visibility
2574 of subitems. See also Symbol.get_visibility()."""
2575 return self
.config
._eval
_expr
(self
.dep_expr
)
2577 def get_visible_if_visibility(self
):
2578 """Returns the visibility the menu gets from its 'visible if'
2579 condition. "y" if the menu has no 'visible if' condition."""
2580 return self
.config
._eval
_expr
(self
.visible_if_expr
)
2582 def get_items(self
, recursive
= False):
2583 """Returns a list containing the items (symbols, menus, choice
2584 statements and comments) in in the menu, in the same order that the
2585 items appear within the menu.
2587 recursive (default: False) -- True if items contained in items within
2588 the menu should be included
2589 recursively (preorder)."""
2595 for item
in self
.block
:
2597 if isinstance(item
, Menu
):
2598 res
.extend(item
.get_items(True))
2599 elif isinstance(item
, Choice
):
2600 res
.extend(item
.get_items())
2603 def get_symbols(self
, recursive
= False):
2604 """Returns a list containing the symbols in the menu, in the same order
2605 that they appear within the menu.
2607 recursive (default: False) -- True if symbols contained in items within
2608 the menu should be included
2611 return [item
for item
in self
.get_items(recursive
) if isinstance(item
, Symbol
)]
2613 def get_title(self
):
2614 """Returns the title text of the menu."""
2617 def get_parent(self
):
2618 """Returns the menu or choice statement that contains the menu, or
2619 None if the menu is at the top level. Note that if statements are
2620 treated as syntactic sugar and do not have an explicit class
2624 def get_referenced_symbols(self
, refs_from_enclosing
= False):
2625 """See Symbol.get_referenced_symbols()."""
2626 return self
.all_referenced_syms
if refs_from_enclosing
else self
.referenced_syms
2628 def get_location(self
):
2629 """Returns the location of the menu as a (filename, linenr) tuple,
2630 where filename is a string and linenr an int."""
2631 return (self
.filename
, self
.linenr
)
2634 """Returns a string containing various information about the menu."""
2635 depends_on_str
= self
.config
._expr
_val
_str
(self
.orig_deps
,
2636 "(no dependencies)")
2637 visible_if_str
= self
.config
._expr
_val
_str
(self
.visible_if_expr
,
2638 "(no dependencies)")
2640 additional_deps_str
= " " + self
.config
._expr
_val
_str
(self
.deps_from_containing
,
2641 "(no additional dependencies)")
2643 return _sep_lines("Menu",
2644 "Title : " + self
.title
,
2645 "'depends on' dependencies : " + depends_on_str
,
2646 "'visible if' dependencies : " + visible_if_str
,
2647 "Additional dependencies from enclosing menus and if's:",
2648 additional_deps_str
,
2649 "Location: {0}:{1}".format(self
.filename
, self
.linenr
))
2656 """Menu constructor -- not intended to be called directly by
2657 kconfiglib clients."""
2664 self
.dep_expr
= None
2666 # Dependency expression without dependencies from enclosing menus and
2668 self
.orig_deps
= None
2670 # Dependencies inherited from containing menus and if's
2671 self
.deps_from_containing
= None
2673 # The 'visible if' expression
2674 self
.visible_if_expr
= None
2676 # The set of symbols referenced by this menu (see
2677 # get_referenced_symbols())
2678 self
.referenced_syms
= set()
2680 # Like 'referenced_syms', but includes symbols from
2681 # dependencies inherited from enclosing menus and if's
2682 self
.all_referenced_syms
= None
2684 self
.filename
= None
2687 def _make_conf(self
):
2688 item_conf
= _make_block_conf(self
.block
)
2690 if self
.config
._eval
_expr
(self
.dep_expr
) != "n" and \
2691 self
.config
._eval
_expr
(self
.visible_if_expr
) != "n":
2692 return ["\n#\n# {0}\n#".format(self
.title
)] + item_conf
2697 """Represents a choice statement. A choice can be in one of three modes:
2699 "n" - The choice is not visible and no symbols can be selected.
2701 "m" - Any number of symbols can be set to "m". The rest will be "n". This
2702 is safe since potentially conflicting options don't actually get
2703 compiled into the kernel simultaneously with "m".
2705 "y" - One symbol will be "y" while the rest are "n".
2707 Only tristate choices can be in "m" mode, and the visibility of the choice
2708 is an upper bound on the mode, so that e.g. a choice that depends on a
2709 symbol with value "m" will be in "m" mode.
2711 The mode changes automatically when a value is assigned to a symbol within
2714 See Symbol.get_visibility() too."""
2720 def get_selection(self
):
2721 """Returns the symbol selected (either by the user or through
2722 defaults), or None if either no symbol is selected or the mode is not
2724 if self
.cached_selection
is not None:
2725 if self
.cached_selection
== NO_SELECTION
:
2727 return self
.cached_selection
2729 if self
.get_mode() != "y":
2730 return self
._cache
_ret
(None)
2732 # User choice available?
2733 if self
.user_val
is not None and _get_visibility(self
.user_val
) == "y":
2734 return self
._cache
_ret
(self
.user_val
)
2737 return self
._cache
_ret
(None)
2739 return self
._cache
_ret
(self
.get_selection_from_defaults())
2741 def get_selection_from_defaults(self
):
2742 """Like Choice.get_selection(), but acts as if no symbol has been
2743 selected by the user and no 'optional' flag is in effect."""
2745 if self
.actual_symbols
== []:
2748 for symbol
, cond_expr
in self
.def_exprs
:
2749 if self
.config
._eval
_expr
(cond_expr
) != "n":
2750 chosen_symbol
= symbol
2753 chosen_symbol
= self
.actual_symbols
[0]
2755 # Is the chosen symbol visible?
2756 if _get_visibility(chosen_symbol
) != "n":
2757 return chosen_symbol
2758 # Otherwise, pick the first visible symbol
2759 for sym
in self
.actual_symbols
:
2760 if _get_visibility(sym
) != "n":
2764 def get_user_selection(self
):
2765 """If the choice is in "y" mode and has a user-selected symbol, returns
2766 that symbol. Otherwise, returns None."""
2767 return self
.user_val
2769 def get_config(self
):
2770 """Returns the Config instance this choice is from."""
2774 """For named choices, returns the name. Returns None for unnamed
2775 choices. No named choices appear anywhere in the kernel Kconfig files
2776 as of Linux 3.7.0-rc8."""
2779 def get_prompts(self
):
2780 """Returns a list of prompts defined for the choice, in the order they
2781 appear in the configuration files. Returns the empty list for choices
2784 This list will have a single entry for the vast majority of choices
2785 having prompts, but having multiple prompts for a single choice is
2786 possible through having multiple 'choice' entries for it (though I'm
2787 not sure if that ever happens in practice)."""
2788 return [prompt
for prompt
, _
in self
.orig_prompts
]
2791 """Returns the help text of the choice, or None if the choice has no
2796 """Returns the type of the choice. See Symbol.get_type()."""
2799 def get_items(self
):
2800 """Gets all items contained in the choice in the same order as within
2801 the configuration ("items" instead of "symbols" since choices and
2802 comments might appear within choices. This only happens in one place as
2803 of Linux 3.7.0-rc8, in drivers/usb/gadget/Kconfig)."""
2806 def get_symbols(self
):
2807 """Returns a list containing the choice's symbols.
2809 A quirk (perhaps a bug) of Kconfig is that you can put items within a
2810 choice that will not be considered members of the choice insofar as
2811 selection is concerned. This happens for example if one symbol within a
2812 choice 'depends on' the symbol preceding it, or if you put non-symbol
2813 items within choices.
2815 As of Linux 3.7.0-rc8, this seems to be used intentionally in one
2816 place: drivers/usb/gadget/Kconfig.
2818 This function returns the "proper" symbols of the choice in the order
2819 they appear in the choice, excluding such items. If you want all items
2820 in the choice, use get_items()."""
2821 return self
.actual_symbols
2823 def get_parent(self
):
2824 """Returns the menu or choice statement that contains the choice, or
2825 None if the choice is at the top level. Note that if statements are
2826 treated as syntactic sugar and do not have an explicit class
2830 def get_referenced_symbols(self
, refs_from_enclosing
= False):
2831 """See Symbol.get_referenced_symbols()."""
2832 return self
.all_referenced_syms
if refs_from_enclosing
else self
.referenced_syms
2834 def get_def_locations(self
):
2835 """Returns a list of (filename, linenr) tuples, where filename (string)
2836 and linenr (int) represent a location where the choice is defined. For
2837 the vast majority of choices (all of them as of Linux 3.7.0-rc8) this
2838 list will only contain one element, but its possible for named choices
2839 to be defined in multiple locations."""
2840 return self
.def_locations
2842 def get_visibility(self
):
2843 """Returns the visibility of the choice statement: one of "n", "m" or
2844 "y". This acts as an upper limit on the mode of the choice (though bool
2845 choices can only have the mode "y"). See the class documentation for an
2846 explanation of modes."""
2847 return _get_visibility(self
)
2850 """Returns the mode of the choice. See the class documentation for
2851 an explanation of modes."""
2852 minimum_mode
= "n" if self
.optional
else "m"
2853 mode
= self
.user_mode
if self
.user_mode
is not None else minimum_mode
2854 mode
= self
.config
._eval
_min
(mode
, _get_visibility(self
))
2856 # Promote "m" to "y" for boolean choices
2857 if mode
== "m" and self
.type == BOOL
:
2862 def is_optional(self
):
2863 """Returns True if the choice has the 'optional' flag set (and so will
2864 default to "n" mode)."""
2865 return self
.optional
2868 """Returns a string containing various information about the choice
2870 return self
.config
._get
_sym
_or
_choice
_str
(self
)
2877 """Choice constructor -- not intended to be called directly by
2878 kconfiglib clients."""
2881 self
.cached_visibility
= None
2886 self
.name
= None # Yes, choices can be named
2890 self
.optional
= False
2893 # The prompts and default values without any dependencies from
2894 # enclosing menus or if's propagated
2896 self
.orig_prompts
= []
2897 self
.orig_def_exprs
= []
2899 # Dependencies inherited from containing menus and if's
2900 self
.deps_from_containing
= None
2902 # We need to filter out symbols that appear within the choice block but
2903 # are not considered choice items (see
2904 # Choice._determine_actual_symbols()) This list holds the "actual" choice
2906 self
.actual_symbols
= []
2908 # The set of symbols referenced by this choice (see
2909 # get_referenced_symbols())
2910 self
.referenced_syms
= set()
2912 # Like 'referenced_syms', but includes symbols from
2913 # dependencies inherited from enclosing menus and if's
2914 self
.all_referenced_syms
= set()
2916 # See Choice.get_def_locations()
2917 self
.def_locations
= []
2919 self
.user_val
= None
2920 self
.user_mode
= None
2922 self
.cached_selection
= None
2924 def _determine_actual_symbols(self
):
2925 """If a symbol's visibility depends on the preceding symbol within a
2926 choice, it is no longer viewed as a choice item. (This is quite
2927 possibly a bug, but some things consciously use it... ugh. It stems
2928 from automatic submenu creation.) In addition, it's possible to have
2929 choices and comments within choices, and those shouldn't be considered
2930 choice items either. Only drivers/usb/gadget/Kconfig seems to depend on
2931 any of this. This method computes the "actual" items in the choice and
2932 sets the is_choice_symbol_ flag on them (retrieved via
2933 is_choice_symbol()).
2935 Don't let this scare you: an earlier version simply checked for a
2936 sequence of symbols where all symbols after the first appeared in the
2937 'depends on' expression of the first, and that worked fine. The added
2938 complexity is to be future-proof in the event that
2939 drivers/usb/gadget/Kconfig turns even more sinister. It might very well
2940 be overkilling things (especially if that file is refactored ;)."""
2942 # Items might depend on each other in a tree structure, so we need a
2943 # stack to keep track of the current tentative parent
2946 for item
in self
.block
:
2947 if not isinstance(item
, Symbol
):
2952 if item
._has
_auto
_menu
_dep
_on
(stack
[-1]):
2953 # The item should not be viewed as a choice item, so don't
2954 # set item.is_choice_symbol_.
2960 item
.is_choice_symbol_
= True
2961 self
.actual_symbols
.append(item
)
2964 def _cache_ret(self
, selection
):
2965 # As None is used to indicate the lack of a cached value we can't use
2966 # that to cache the fact that the choice has no selection. Instead, we
2967 # use the symbolic constant NO_SELECTION.
2968 if selection
is None:
2969 self
.cached_selection
= NO_SELECTION
2971 self
.cached_selection
= selection
2975 def _invalidate(self
):
2976 self
.cached_selection
= None
2977 self
.cached_visibility
= None
2979 def _unset_user_value(self
):
2981 self
.user_val
= None
2982 self
.user_mode
= None
2984 def _make_conf(self
):
2985 return _make_block_conf(self
.block
)
2987 class Comment(Item
):
2989 """Represents a comment statement."""
2995 def get_config(self
):
2996 """Returns the Config instance this comment is from."""
2999 def get_visibility(self
):
3000 """Returns the visibility of the comment. See also
3001 Symbol.get_visibility()."""
3002 return self
.config
._eval
_expr
(self
.dep_expr
)
3005 """Returns the text of the comment."""
3008 def get_parent(self
):
3009 """Returns the menu or choice statement that contains the comment, or
3010 None if the comment is at the top level. Note that if statements are
3011 treated as syntactic sugar and do not have an explicit class
3015 def get_referenced_symbols(self
, refs_from_enclosing
= False):
3016 """See Symbol.get_referenced_symbols()."""
3017 return self
.all_referenced_syms
if refs_from_enclosing
else self
.referenced_syms
3019 def get_location(self
):
3020 """Returns the location of the comment as a (filename, linenr) tuple,
3021 where filename is a string and linenr an int."""
3022 return (self
.filename
, self
.linenr
)
3025 """Returns a string containing various information about the comment."""
3026 dep_str
= self
.config
._expr
_val
_str
(self
.orig_deps
, "(no dependencies)")
3028 additional_deps_str
= " " + self
.config
._expr
_val
_str
(self
.deps_from_containing
,
3029 "(no additional dependencies)")
3031 return _sep_lines("Comment",
3032 "Text: " + str(self
.text
),
3033 "Dependencies: " + dep_str
,
3034 "Additional dependencies from enclosing menus and if's:",
3035 additional_deps_str
,
3036 "Location: {0}:{1}".format(self
.filename
, self
.linenr
))
3043 """Comment constructor -- not intended to be called directly by
3044 kconfiglib clients."""
3050 self
.dep_expr
= None
3052 # Dependency expression without dependencies from enclosing menus and
3054 self
.orig_deps
= None
3056 # Dependencies inherited from containing menus and if's
3057 self
.deps_from_containing
= None
3059 # The set of symbols referenced by this comment (see
3060 # get_referenced_symbols())
3061 self
.referenced_syms
= set()
3063 # Like 'referenced_syms', but includes symbols from
3064 # dependencies inherited from enclosing menus and if's
3065 self
.all_referenced_syms
= None
3067 self
.filename
= None
3070 def _make_conf(self
):
3071 if self
.config
._eval
_expr
(self
.dep_expr
) != "n":
3072 return ["\n#\n# {0}\n#".format(self
.text
)]
3075 class Kconfig_Syntax_Error(Exception):
3076 """Exception raised for syntax errors."""
3079 class Internal_Error(Exception):
3080 """Exception raised for internal errors."""
3087 def tri_less(v1
, v2
):
3088 """Returns True if the tristate v1 is less than the tristate v2, where "n",
3089 "m" and "y" are ordered from lowest to highest."""
3090 return tri_to_int
[v1
] < tri_to_int
[v2
]
3092 def tri_less_eq(v1
, v2
):
3093 """Returns True if the tristate v1 is less than or equal to the tristate
3094 v2, where "n", "m" and "y" are ordered from lowest to highest."""
3095 return tri_to_int
[v1
] <= tri_to_int
[v2
]
3097 def tri_greater(v1
, v2
):
3098 """Returns True if the tristate v1 is greater than the tristate v2, where
3099 "n", "m" and "y" are ordered from lowest to highest."""
3100 return tri_to_int
[v1
] > tri_to_int
[v2
]
3102 def tri_greater_eq(v1
, v2
):
3103 """Returns True if the tristate v1 is greater than or equal to the tristate
3104 v2, where "n", "m" and "y" are ordered from lowest to highest."""
3105 return tri_to_int
[v1
] >= tri_to_int
[v2
]
3111 class _Feed(object):
3113 """Class for working with sequences in a stream-like fashion; handy for tokens."""
3115 def __init__(self
, items
):
3117 self
.length
= len(self
.items
)
3121 if self
.i
>= self
.length
:
3124 item
= self
.items
[self
.i
]
3128 def peek_next(self
):
3129 return None if self
.i
>= self
.length
else self
.items
[self
.i
]
3131 def check(self
, token
):
3132 """Check if the next token is 'token'. If so, remove it from the token
3133 feed and return True. Otherwise, leave it in and return False."""
3134 if self
.i
< self
.length
and self
.items
[self
.i
] == token
:
3141 _internal_error("Attempt to move back in Feed while already at the beginning.")
3144 def go_to_start(self
):
3150 class _FileFeed(_Feed
):
3152 """_Feed subclass that feeds lines from a file. Joins any line ending in
3153 \\ with the following line. Keeps track of the filename and current line
3156 def __init__(self
, filename
):
3157 self
.filename
= _clean_up_path(filename
)
3158 _Feed
.__init
__(self
, _get_lines(filename
))
3160 def remove_blank(self
):
3161 """Removes lines until the first non-blank (not all-space) line."""
3162 while self
.i
< self
.length
and self
.items
[self
.i
].isspace():
3165 def get_filename(self
):
3166 return self
.filename
3168 def get_linenr(self
):
3172 # Internal functions
3175 def _get_visibility(sc
):
3176 """Symbols and Choices have a "visibility" that acts as an upper bound on
3177 the values a user can set for them, corresponding to the visibility in e.g.
3178 'make menuconfig'. This function calculates the visibility for the Symbol
3179 or Choice 'sc' -- the logic is nearly identical."""
3180 if sc
.cached_visibility
is None:
3182 for _
, cond_expr
in sc
.prompts
:
3183 vis
= sc
.config
._eval
_max
(vis
, cond_expr
)
3185 if isinstance(sc
, Symbol
) and sc
.is_choice_symbol_
:
3186 vis
= sc
.config
._eval
_min
(vis
, _get_visibility(sc
.parent
))
3188 # Promote "m" to "y" if we're dealing with a non-tristate
3189 if vis
== "m" and sc
.type != TRISTATE
:
3192 sc
.cached_visibility
= vis
3194 return sc
.cached_visibility
3196 def _make_and(e1
, e2
):
3197 """Constructs an AND (&&) expression. Performs trivial simplification.
3198 Nones equate to 'y'.
3200 Note: returns None if e1 == e2 == None."""
3201 if e1
== "n" or e2
== "n":
3203 if e1
is None or e1
== "y":
3205 if e2
is None or e2
== "y":
3208 # Prefer to merge/update argument list if possible instead of creating
3211 if isinstance(e1
, tuple) and e1
[0] == AND
:
3212 if isinstance(e2
, tuple) and e2
[0] == AND
:
3213 return (AND
, e1
[1] + e2
[1])
3214 return (AND
, e1
[1] + [e2
])
3216 if isinstance(e2
, tuple) and e2
[0] == AND
:
3217 return (AND
, e2
[1] + [e1
])
3219 return (AND
, [e1
, e2
])
3221 def _make_or(e1
, e2
):
3222 """Constructs an OR (||) expression. Performs trivial simplification and
3223 avoids Nones. Nones equate to 'y', which is usually what we want, but needs
3224 to be kept in mind."""
3226 # Perform trivial simplification and avoid None's (which
3227 # correspond to y's)
3228 if e1
is None or e2
is None or e1
== "y" or e2
== "y":
3235 # Prefer to merge/update argument list if possible instead of creating
3238 if isinstance(e1
, tuple) and e1
[0] == OR
:
3239 if isinstance(e2
, tuple) and e2
[0] == OR
:
3240 return (OR
, e1
[1] + e2
[1])
3241 return (OR
, e1
[1] + [e2
])
3243 if isinstance(e2
, tuple) and e2
[0] == OR
:
3244 return (OR
, e2
[1] + [e1
])
3246 return (OR
, [e1
, e2
])
3248 def _get_expr_syms(expr
):
3249 """Returns the set() of symbols appearing in expr."""
3255 if isinstance(expr
, Symbol
):
3258 if isinstance(expr
, str):
3262 if e0
== AND
or e0
== OR
:
3263 for term
in expr
[1]:
3267 elif e0
== EQUAL
or e0
== UNEQUAL
:
3269 if isinstance(v1
, Symbol
):
3271 if isinstance(v2
, Symbol
):
3274 _internal_error("Internal error while fetching symbols from an "
3275 "expression with token stream {0}.".format(expr
))
3281 """Returns the value of obj as a string. If obj is not a string (constant
3282 symbol), it must be a Symbol."""
3283 return obj
if isinstance(obj
, str) else obj
.get_value()
3285 def _make_block_conf(block
):
3286 """Returns a list of .config strings for a block (list) of items."""
3288 # Collect the substrings in a list and later use join() instead of += to
3289 # build the final .config contents. With older Python versions, this yields
3290 # linear instead of quadratic complexity.
3293 strings
.extend(item
._make
_conf
())
3296 def _sym_str_string(sym_or_str
):
3297 if isinstance(sym_or_str
, str):
3298 return '"' + sym_or_str
+ '"'
3299 return sym_or_str
.name
3301 def _intersperse(lst
, op
):
3302 """_expr_to_str() helper. Gets the string representation of each expression in lst
3303 and produces a list where op has been inserted between the elements."""
3309 def handle_sub_expr(expr
):
3310 no_parens
= isinstance(expr
, (str, Symbol
)) or \
3311 expr
[0] in (EQUAL
, UNEQUAL
) or \
3312 precedence
[op
] <= precedence
[expr
[0]]
3315 res
.extend(_expr_to_str_rec(expr
))
3319 op_str
= op_to_str
[op
]
3321 handle_sub_expr(lst
[0])
3322 for expr
in lst
[1:]:
3324 handle_sub_expr(expr
)
3328 def _expr_to_str_rec(expr
):
3332 if isinstance(expr
, (Symbol
, str)):
3333 return [_sym_str_string(expr
)]
3337 if e0
== AND
or e0
== OR
:
3338 return _intersperse(expr
[1], expr
[0])
3341 need_parens
= not isinstance(expr
[1], (str, Symbol
))
3346 res
.extend(_expr_to_str_rec(expr
[1]))
3351 if e0
== EQUAL
or e0
== UNEQUAL
:
3352 return [_sym_str_string(expr
[1]),
3354 _sym_str_string(expr
[2])]
3356 def _expr_to_str(expr
):
3357 return "".join(_expr_to_str_rec(expr
))
3359 def _indentation(line
):
3360 """Returns the length of the line's leading whitespace, treating tab stops
3361 as being spaced 8 characters apart."""
3362 line
= line
.expandtabs()
3363 return len(line
) - len(line
.lstrip())
3365 def _deindent(line
, indent
):
3366 """Deindent 'line' by 'indent' spaces."""
3367 line
= line
.expandtabs()
3368 if len(line
) <= indent
:
3370 return line
[indent
:]
3372 def _is_base_n(s
, n
):
3379 def _sep_lines(*args
):
3380 """Returns a string comprised of all arguments, with newlines inserted
3382 return "\n".join(args
)
3385 """Returns a new string with "#" inserted before each line in 's'."""
3388 res
= "".join(["#" + line
for line
in s
.splitlines(True)])
3389 if s
.endswith("\n"):
3393 def _get_lines(filename
):
3394 """Returns a list of lines from 'filename', joining any line ending in \\
3395 with the following line."""
3396 with
open(filename
, "r") as f
:
3400 if line
.endswith("\\\n"):
3403 lines
.append(accum
+ line
)
3407 def _clean_up_path(path
):
3408 """Strips an initial "./" and any trailing slashes from 'path'."""
3409 if path
.startswith("./"):
3411 return path
.rstrip("/")
3413 def _stderr_msg(msg
, filename
, linenr
):
3414 if filename
is not None:
3415 sys
.stderr
.write("{0}:{1}: ".format(_clean_up_path(filename
), linenr
))
3416 sys
.stderr
.write(msg
+ "\n")
3418 def _tokenization_error(s
, filename
, linenr
):
3419 loc
= "" if filename
is None else "{0}:{1}: ".format(filename
, linenr
)
3420 raise Kconfig_Syntax_Error("{0}Couldn't tokenize '{1}'"
3421 .format(loc
, s
.strip()))
3423 def _parse_error(s
, msg
, filename
, linenr
):
3424 loc
= "" if filename
is None else "{0}:{1}: ".format(filename
, linenr
)
3425 raise Kconfig_Syntax_Error("{0}Couldn't parse '{1}'{2}"
3426 .format(loc
, s
.strip(),
3427 "." if msg
is None else ": " + msg
))
3429 def _internal_error(msg
):
3430 raise Internal_Error(msg
+
3431 "\nSorry! You may want to send an email to ulfalizer a.t Google's " \
3432 "email service to tell me about this. Include the message above " \
3433 "and the stack trace and describe what you were doing.")
3436 # Internal global constants
3440 (T_AND
, T_OR
, T_NOT
,
3441 T_OPEN_PAREN
, T_CLOSE_PAREN
,
3443 T_MAINMENU
, T_MENU
, T_ENDMENU
,
3444 T_SOURCE
, T_CHOICE
, T_ENDCHOICE
,
3445 T_COMMENT
, T_CONFIG
, T_MENUCONFIG
,
3446 T_HELP
, T_IF
, T_ENDIF
, T_DEPENDS
, T_ON
,
3447 T_OPTIONAL
, T_PROMPT
, T_DEFAULT
,
3448 T_BOOL
, T_TRISTATE
, T_HEX
, T_INT
, T_STRING
,
3449 T_DEF_BOOL
, T_DEF_TRISTATE
,
3450 T_SELECT
, T_RANGE
, T_OPTION
, T_ALLNOCONFIG_Y
, T_ENV
,
3451 T_DEFCONFIG_LIST
, T_MODULES
, T_VISIBLE
) = range(39)
3453 # The leading underscore before the function assignments below prevent pydoc
3454 # from listing them. The constants could be hidden too, but they're fairly
3455 # obviously internal anyway, so don't bother spamming the code.
3457 # Keyword to token map. Note that the get() method is assigned directly as a
3458 # small optimization.
3459 _get_keyword
= { "mainmenu" : T_MAINMENU
,
3461 "endmenu" : T_ENDMENU
,
3463 "endchoice" : T_ENDCHOICE
,
3464 "source" : T_SOURCE
,
3465 "choice" : T_CHOICE
,
3466 "config" : T_CONFIG
,
3467 "comment" : T_COMMENT
,
3468 "menuconfig" : T_MENUCONFIG
,
3471 "depends" : T_DEPENDS
,
3473 "optional" : T_OPTIONAL
,
3474 "prompt" : T_PROMPT
,
3475 "default" : T_DEFAULT
,
3478 "tristate" : T_TRISTATE
,
3481 "def_bool" : T_DEF_BOOL
,
3482 "def_tristate" : T_DEF_TRISTATE
,
3483 "string" : T_STRING
,
3484 "select" : T_SELECT
,
3486 "option" : T_OPTION
,
3487 "allnoconfig_y" : T_ALLNOCONFIG_Y
,
3489 "defconfig_list" : T_DEFCONFIG_LIST
,
3490 "modules" : T_MODULES
,
3491 "visible" : T_VISIBLE
}.get
3493 # Strings to use for True and False
3494 bool_str
= { False : "false", True : "true" }
3496 # Tokens after which identifier-like lexemes are treated as strings. T_CHOICE
3497 # is included to avoid symbols being registered for named choices.
3498 string_lex
= frozenset((T_BOOL
, T_TRISTATE
, T_INT
, T_HEX
, T_STRING
, T_CHOICE
,
3499 T_PROMPT
, T_MENU
, T_COMMENT
, T_SOURCE
, T_MAINMENU
))
3501 # Matches the initial token on a line; see _tokenize().
3502 _initial_token_re_match
= re
.compile(r
"[^\w]*(\w+)").match
3504 # Matches an identifier/keyword optionally preceded by whitespace
3505 _id_keyword_re_match
= re
.compile(r
"\s*([\w./-]+)").match
3507 # Regular expressions for parsing .config files
3508 _set_re_match
= re
.compile(r
"CONFIG_(\w+)=(.*)").match
3509 _unset_re_match
= re
.compile(r
"# CONFIG_(\w+) is not set").match
3511 # Regular expression for finding $-references to symbols in strings
3512 _sym_ref_re_search
= re
.compile(r
"\$[A-Za-z0-9_]+").search
3514 # Integers representing symbol types
3515 UNKNOWN
, BOOL
, TRISTATE
, STRING
, HEX
, INT
= range(6)
3517 # Strings to use for types
3518 typename
= { UNKNOWN
: "unknown", BOOL
: "bool", TRISTATE
: "tristate",
3519 STRING
: "string", HEX
: "hex", INT
: "int" }
3521 # Token to type mapping
3522 token_to_type
= { T_BOOL
: BOOL
, T_TRISTATE
: TRISTATE
, T_STRING
: STRING
,
3523 T_INT
: INT
, T_HEX
: HEX
}
3525 # Default values for symbols of different types (the value the symbol gets if
3526 # it is not assigned a user value and none of its 'default' clauses kick in)
3527 default_value
= { BOOL
: "n", TRISTATE
: "n", STRING
: "", INT
: "", HEX
: "" }
3529 # Indicates that no item is selected in a choice statement
3532 # Integers representing expression types
3533 AND
, OR
, NOT
, EQUAL
, UNEQUAL
= range(5)
3535 # Map from tristate values to integers
3536 tri_to_int
= { "n" : 0, "m" : 1, "y" : 2 }
3538 # Printing-related stuff
3540 op_to_str
= { AND
: " && ", OR
: " || ", EQUAL
: " = ", UNEQUAL
: " != " }
3541 precedence
= { OR
: 0, AND
: 1, NOT
: 2 }