- else:
- selects_str_rows = []
-
- for (target, cond_expr) in sc.orig_selects:
- if cond_expr is None:
- selects_str_rows.append(" {0}".format(target.name))
- else:
- selects_str_rows.append(" {0} if ".format(target.name) +
- self._expr_val_str(cond_expr))
-
- selects_str = "\n".join(selects_str_rows)
-
- # Build reverse dependencies string
- if sc.rev_dep == "n":
- rev_dep_str = " (no reverse dependencies)"
- else:
- rev_dep_str = " " + self._expr_val_str(sc.rev_dep)
-
- res = _sep_lines("Symbol " + (sc.name if sc.name is not None else "(no name)"),
- "Type : " + typename[sc.type],
- "Value : " + value_str,
- "User value : " + user_value_str,
- "Visibility : " + visibility_str,
- "Is choice item : " + bool_str[sc.is_choice_symbol_],
- "Is defined : " + bool_str[sc.is_defined_],
- "Is from env. : " + bool_str[sc.is_from_env],
- "Is special : " + bool_str[sc.is_special_] + "\n")
-
- if sc.ranges != []:
- res += _sep_lines("Ranges:",
- ranges_str + "\n")
-
- res += _sep_lines("Prompts:",
- prompts_str,
- "Default values:",
- defaults_str,
- "Selects:",
- selects_str,
- "Reverse dependencies:",
- rev_dep_str,
- "Additional dependencies from enclosing menus and if's:",
- additional_deps_str,
- "Locations: " + locations_str)
-
- return res
-
- #
- # Choice-specific stuff
- #
-
- # Build name string (for named choices)
- if sc.name is None:
- name_str = "(no name)"
- else:
- name_str = sc.name
-
- # Build selected symbol string
- sel = sc.get_selection()
- if sel is None:
- sel_str = "(no selection)"
- else:
- sel_str = sel.name
-
- # Build mode string
- mode_str = s(sc.get_mode())
-
- # Build default values string
- if sc.def_exprs == []:
- defaults_str = " (no default values)"
- else:
- defaults_str_rows = []
-
- for (sym, cond_expr) in sc.orig_def_exprs:
- if cond_expr is None:
- defaults_str_rows.append(" {0}".format(sym.name))
- else:
- defaults_str_rows.append(" {0} if ".format(sym.name) +
- self._expr_val_str(cond_expr))
-
- defaults_str = "\n".join(defaults_str_rows)
-
- # Build contained symbols string
- names = [sym.name for sym in sc.get_symbols()]
-
- if names == []:
- syms_string = "(empty)"
- else:
- syms_string = " ".join(names)
-
- return _sep_lines("Choice",
- "Name (for named choices): " + name_str,
- "Type : " + typename[sc.type],
- "Selected symbol : " + sel_str,
- "User value : " + user_value_str,
- "Mode : " + mode_str,
- "Visibility : " + visibility_str,
- "Optional : " + bool_str[sc.optional],
- "Prompts:",
- prompts_str,
- "Defaults:",
- defaults_str,
- "Choice symbols:",
- " " + syms_string,
- "Additional dependencies from enclosing menus and if's:",
- additional_deps_str,
- "Locations: " + locations_str)
-
- def _expr_depends_on(self, expr, sym):
- """Reimplementation of expr_depends_symbol() from mconf.c. Used to
- determine if a submenu should be implicitly created, which influences what
- items inside choice statements are considered choice items."""
- if expr is None:
- return False
-
- def rec(expr):
- if isinstance(expr, str):
- return False
-
- if isinstance(expr, Symbol):
- return expr is sym
-
- e0 = expr[0]
-
- if e0 == EQUAL or e0 == UNEQUAL:
- return self._eq_to_sym(expr) is sym
-
- if e0 == AND:
- for and_expr in expr[1]:
- if rec(and_expr):
- return True
-
- return False
-
- return rec(expr)
-
- def _eq_to_sym(self, eq):
- """_expr_depends_on() helper. For (in)equalities of the form sym = y/m
- or sym != n, returns sym. For other (in)equalities, returns None."""
- relation, left, right = eq
-
- left = self._transform_n_m_y(left)
- right = self._transform_n_m_y(right)
-
- # Make sure the symbol (if any) appears to the left
- if not isinstance(left, Symbol):
- left, right = right, left
-
- if not isinstance(left, Symbol):
- return None
-
- if (relation == EQUAL and (right == "m" or right == "y")) or \
- (relation == UNEQUAL and right == "n"):
- return left
-
- return None
-
- def _transform_n_m_y(self, item):
- """_eq_to_sym() helper. Translates the symbols n, m, and y to their
- string equivalents."""
- if item is self.n:
- return "n"
- if item is self.m:
- return "m"
- if item is self.y:
- return "y"
- return item
-
- def _warn(self, msg, filename = None, linenr = None):
- """For printing warnings to stderr."""
- if self.print_warnings:
- self._warn_or_undef_assign(msg, WARNING, filename, linenr)
-
- def _undef_assign(self, msg, filename = None, linenr = None):
- """For printing informational messages related to assignments
- to undefined variables to stderr."""
- if self.print_undef_assign:
- self._warn_or_undef_assign(msg, UNDEF_ASSIGN, filename, linenr)
-
- def _warn_or_undef_assign(self, msg, msg_type, filename, linenr):
- if filename is not None:
- sys.stderr.write("{0}:".format(_clean_up_path(filename)))
- if linenr is not None:
- sys.stderr.write("{0}:".format(linenr))
-
- if msg_type == WARNING:
- sys.stderr.write("warning: ")
- elif msg_type == UNDEF_ASSIGN:
- sys.stderr.write("info: ")
- else:
- _internal_error('Internal error while printing warning: unknown warning type "{0}".'
- .format(msg_type))
-
- sys.stderr.write(msg + "\n")
-
-def _get_expr_syms(expr):
- """Returns the set() of symbols appearing in expr."""
- res = set()
- if expr is None:
- return res
-
- def rec(expr):
- if isinstance(expr, Symbol):
- res.add(expr)
- return
-
- if isinstance(expr, str):
- return
-
- e0 = expr[0]
-
- if e0 == OR or e0 == AND:
- for term in expr[1]:
- rec(term)
-
- elif e0 == NOT:
- rec(expr[1])
-
- elif e0 == EQUAL or e0 == UNEQUAL:
- _, v1, v2 = expr
-
- if isinstance(v1, Symbol):
- res.add(v1)
-
- if isinstance(v2, Symbol):
- res.add(v2)
-
- else:
- _internal_error("Internal error while fetching symbols from an "
- "expression with token stream {0}.".format(expr))
-
- rec(expr)
- return res
-
-
-#
-# Construction of expressions
-#
-
-# These functions as well as the _eval_min/max() functions above equate
-# None with "y", which is usually what we want, but needs to be kept in
-# mind.
-
-def _make_or(e1, e2):
- # Perform trivial simplification and avoid None's (which
- # correspond to y's)
- if e1 is None or e2 is None or \
- e1 == "y" or e2 == "y":
- return "y"
-
- if e1 == "n":
- return e2
-
- if e2 == "n":
- return e1
-
- # Prefer to merge/update argument list if possible instead of creating
- # a new OR node
-
- if isinstance(e1, tuple) and e1[0] == OR:
- if isinstance(e2, tuple) and e2[0] == OR:
- return (OR, e1[1] + e2[1])
- return (OR, e1[1] + [e2])
-
- if isinstance(e2, tuple) and e2[0] == OR:
- return (OR, e2[1] + [e1])
-
- return (OR, [e1, e2])
-
-# Note: returns None if e1 == e2 == None
-
-def _make_and(e1, e2):
- if e1 == "n" or e2 == "n":
- return "n"
-
- if e1 is None or e1 == "y":
- return e2
-
- if e2 is None or e2 == "y":
- return e1
-
- # Prefer to merge/update argument list if possible instead of creating
- # a new AND node
-
- if isinstance(e1, tuple) and e1[0] == AND:
- if isinstance(e2, tuple) and e2[0] == AND:
- return (AND, e1[1] + e2[1])
- return (AND, e1[1] + [e2])
-
- if isinstance(e2, tuple) and e2[0] == AND:
- return (AND, e2[1] + [e1])
-
- return (AND, [e1, e2])
-
-#
-# Constants and functions related to types, parsing, evaluation and printing,
-# put globally to unclutter the Config class a bit.
-#
-
-# Tokens
-(T_OR, T_AND, T_NOT,
- T_OPEN_PAREN, T_CLOSE_PAREN,
- T_EQUAL, T_UNEQUAL,
- T_MAINMENU, T_MENU, T_ENDMENU,
- T_SOURCE, T_CHOICE, T_ENDCHOICE,
- T_COMMENT, T_CONFIG, T_MENUCONFIG,
- T_HELP, T_IF, T_ENDIF, T_DEPENDS, T_ON,
- T_OPTIONAL, T_PROMPT, T_DEFAULT,
- T_BOOL, T_TRISTATE, T_HEX, T_INT, T_STRING,
- T_DEF_BOOL, T_DEF_TRISTATE,
- T_SELECT, T_RANGE, T_OPTION, T_ALLNOCONFIG_Y, T_ENV,
- T_DEFCONFIG_LIST, T_MODULES, T_VISIBLE) = range(0, 39)
-
-# Keyword to token map
-keywords = {
- "mainmenu" : T_MAINMENU,
- "menu" : T_MENU,
- "endmenu" : T_ENDMENU,
- "endif" : T_ENDIF,
- "endchoice" : T_ENDCHOICE,
- "source" : T_SOURCE,
- "choice" : T_CHOICE,
- "config" : T_CONFIG,
- "comment" : T_COMMENT,
- "menuconfig" : T_MENUCONFIG,
- "help" : T_HELP,
- "if" : T_IF,
- "depends" : T_DEPENDS,
- "on" : T_ON,
- "optional" : T_OPTIONAL,
- "prompt" : T_PROMPT,
- "default" : T_DEFAULT,
- "bool" : T_BOOL,
- "boolean" : T_BOOL,
- "tristate" : T_TRISTATE,
- "int" : T_INT,
- "hex" : T_HEX,
- "def_bool" : T_DEF_BOOL,
- "def_tristate" : T_DEF_TRISTATE,
- "string" : T_STRING,
- "select" : T_SELECT,
- "range" : T_RANGE,
- "option" : T_OPTION,
- "allnoconfig_y" : T_ALLNOCONFIG_Y,
- "env" : T_ENV,
- "defconfig_list" : T_DEFCONFIG_LIST,
- "modules" : T_MODULES,
- "visible" : T_VISIBLE }
-
-# Strings to use for True and False
-bool_str = { False : "false", True : "true" }
-
-# Tokens after which identifier-like lexemes are treated as strings. T_CHOICE
-# is included to avoid symbols being registered for named choices.
-string_lex = frozenset((T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING, T_CHOICE,
- T_PROMPT, T_MENU, T_COMMENT, T_SOURCE, T_MAINMENU))
-
-# Matches the initial token on a line; see _tokenize().
-initial_token_re = re.compile(r"[^\w]*(\w+)")
-
-# Matches an identifier/keyword optionally preceded by whitespace
-id_keyword_re = re.compile(r"\s*([\w./-]+)")
-
-# Regular expressions for parsing .config files
-set_re = re.compile(r"CONFIG_(\w+)=(.*)")
-unset_re = re.compile(r"# CONFIG_(\w+) is not set")
-
-# Regular expression for finding $-references to symbols in strings
-sym_ref_re = re.compile(r"\$[A-Za-z0-9_]+")
-
-# Integers representing symbol types
-UNKNOWN, BOOL, TRISTATE, STRING, HEX, INT = range(0, 6)
-
-# Strings to use for types
-typename = {
- UNKNOWN : "unknown",
- BOOL : "bool",
- TRISTATE : "tristate",
- STRING : "string",
- HEX : "hex",
- INT : "int" }
-
-# Token to type mapping
-token_to_type = { T_BOOL : BOOL,
- T_TRISTATE : TRISTATE,
- T_STRING : STRING,
- T_INT : INT,
- T_HEX : HEX }
-
-# Default values for symbols of different types (the value the symbol gets if
-# it is not assigned a user value and none of its 'default' clauses kick in)
-default_value = { BOOL : "n",
- TRISTATE : "n",
- STRING : "",
- INT : "",
- HEX : "" }
-
-# Indicates that no item is selected in a choice statement
-NO_SELECTION = 0
-
-# Integers representing expression types
-OR, AND, NOT, EQUAL, UNEQUAL = range(0, 5)
-
-# Map from tristate values to integers
-tri_to_int = { "n" : 0, "m" : 1, "y" : 2 }
-
-# Printing-related stuff
-
-op_to_str = { AND : " && ",
- OR : " || ",
- EQUAL : " = ",
- UNEQUAL : " != " }
-
-precedence = { OR : 0, AND : 1, NOT : 2 }
-
-# Types of informational messages
-WARNING = 0
-UNDEF_ASSIGN = 1
-
-def _intersperse(lst, op):
- """_expr_to_str() helper. Gets the string representation of each expression in lst
- and produces a list where op has been inserted between the elements."""
- if lst == []:
- return ""
-
- res = []
-
- def handle_sub_expr(expr):
- no_parens = isinstance(expr, (str, Symbol)) or \
- expr[0] in (EQUAL, UNEQUAL) or \
- precedence[op] <= precedence[expr[0]]
- if not no_parens:
- res.append("(")
- res.extend(_expr_to_str_rec(expr))
- if not no_parens:
- res.append(")")
-
- op_str = op_to_str[op]
-
- handle_sub_expr(lst[0])
- for expr in lst[1:]:
- res.append(op_str)
- handle_sub_expr(expr)
-
- return res
-
-def _expr_to_str(expr):
- s = "".join(_expr_to_str_rec(expr))
- return s
-
-def _sym_str_string(sym_or_str):
- if isinstance(sym_or_str, str):
- return '"{0}"'.format(sym_or_str)
- return sym_or_str.name
-
-def _expr_to_str_rec(expr):
- if expr is None:
- return [""]
-
- if isinstance(expr, (Symbol, str)):
- return [_sym_str_string(expr)]
-
- e0 = expr[0]
-
- if e0 == OR or e0 == AND:
- return _intersperse(expr[1], expr[0])
-
- if e0 == NOT:
- need_parens = not isinstance(expr[1], (str, Symbol))
-
- res = ["!"]
- if need_parens:
- res.append("(")
- res.extend(_expr_to_str_rec(expr[1]))
- if need_parens:
- res.append(")")
- return res
-
- if e0 == EQUAL or e0 == UNEQUAL:
- return [_sym_str_string(expr[1]),
- op_to_str[expr[0]],
- _sym_str_string(expr[2])]
-
-class _Block:
-
- """Represents a list of items (symbols, menus, choice statements and
- comments) appearing at the top-level of a file or witin a menu, choice or
- if statement."""