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