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