1 # SPDX-License-Identifier: GPL-2.0 1 # SPDX-License-Identifier: GPL-2.0 2 # 2 # 3 # Builds a .config from a kunitconfig. 3 # Builds a .config from a kunitconfig. 4 # 4 # 5 # Copyright (C) 2019, Google LLC. 5 # Copyright (C) 2019, Google LLC. 6 # Author: Felix Guo <felixguoxiuping@gmail.com> 6 # Author: Felix Guo <felixguoxiuping@gmail.com> 7 # Author: Brendan Higgins <brendanhiggins@googl 7 # Author: Brendan Higgins <brendanhiggins@google.com> 8 8 9 from dataclasses import dataclass !! 9 import collections 10 import re 10 import re 11 from typing import Any, Dict, Iterable, List, << 12 11 13 CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_(\w+) !! 12 CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_\w+ is not set$' 14 CONFIG_PATTERN = r'^CONFIG_(\w+)=(\S+|".*")$' !! 13 CONFIG_PATTERN = r'^CONFIG_\w+=\S+$' 15 14 16 @dataclass(frozen=True) !! 15 KconfigEntryBase = collections.namedtuple('KconfigEntry', ['raw_entry']) 17 class KconfigEntry: !! 16 18 name: str !! 17 19 value: str !! 18 class KconfigEntry(KconfigEntryBase): 20 19 21 def __str__(self) -> str: 20 def __str__(self) -> str: 22 if self.value == 'n': !! 21 return self.raw_entry 23 return f'# CONFIG_{sel << 24 return f'CONFIG_{self.name}={s << 25 22 26 23 27 class KconfigParseError(Exception): 24 class KconfigParseError(Exception): 28 """Error parsing Kconfig defconfig or 25 """Error parsing Kconfig defconfig or .config.""" 29 26 30 27 31 class Kconfig: !! 28 class Kconfig(object): 32 """Represents defconfig or .config spe 29 """Represents defconfig or .config specified using the Kconfig language.""" 33 30 34 def __init__(self) -> None: !! 31 def __init__(self): 35 self._entries = {} # type: Di !! 32 self._entries = [] 36 33 37 def __eq__(self, other: Any) -> bool: !! 34 def entries(self): 38 if not isinstance(other, self. !! 35 return set(self._entries) 39 return False << 40 return self._entries == other. << 41 << 42 def __repr__(self) -> str: << 43 return ','.join(str(e) for e i << 44 << 45 def as_entries(self) -> Iterable[Kconf << 46 for name, value in self._entri << 47 yield KconfigEntry(nam << 48 36 49 def add_entry(self, name: str, value: !! 37 def add_entry(self, entry: KconfigEntry) -> None: 50 self._entries[name] = value !! 38 self._entries.append(entry) 51 39 52 def is_subset_of(self, other: 'Kconfig 40 def is_subset_of(self, other: 'Kconfig') -> bool: 53 for name, value in self._entri !! 41 return self.entries().issubset(other.entries()) 54 b = other._entries.get << 55 if b is None: << 56 if value == 'n << 57 contin << 58 return False << 59 if value != b: << 60 return False << 61 return True << 62 << 63 def conflicting_options(self, other: ' << 64 diff = [] # type: List[Tuple[ << 65 for name, value in self._entri << 66 b = other._entries.get << 67 if b and value != b: << 68 pair = (Kconfi << 69 diff.append(pa << 70 return diff << 71 << 72 def merge_in_entries(self, other: 'Kco << 73 for name, value in other._entr << 74 self._entries[name] = << 75 42 76 def write_to_file(self, path: str) -> 43 def write_to_file(self, path: str) -> None: 77 with open(path, 'a+') as f: !! 44 with open(path, 'w') as f: 78 for e in self.as_entri !! 45 for entry in self.entries(): 79 f.write(str(e) !! 46 f.write(str(entry) + '\n') 80 !! 47 81 def parse_file(path: str) -> Kconfig: !! 48 def parse_from_string(self, blob: str) -> None: 82 with open(path, 'r') as f: !! 49 """Parses a string containing KconfigEntrys and populates this Kconfig.""" 83 return parse_from_string(f.rea !! 50 self._entries = [] 84 !! 51 is_not_set_matcher = re.compile(CONFIG_IS_NOT_SET_PATTERN) 85 def parse_from_string(blob: str) -> Kconfig: !! 52 config_matcher = re.compile(CONFIG_PATTERN) 86 """Parses a string containing Kconfig !! 53 for line in blob.split('\n'): 87 kconfig = Kconfig() !! 54 line = line.strip() 88 is_not_set_matcher = re.compile(CONFIG !! 55 if not line: 89 config_matcher = re.compile(CONFIG_PAT !! 56 continue 90 for line in blob.split('\n'): !! 57 elif config_matcher.match(line) or is_not_set_matcher.match(line): 91 line = line.strip() !! 58 self._entries.append(KconfigEntry(line)) 92 if not line: !! 59 elif line[0] == '#': 93 continue !! 60 continue 94 !! 61 else: 95 match = config_matcher.match(l !! 62 raise KconfigParseError('Failed to parse: ' + line) 96 if match: !! 63 97 kconfig.add_entry(matc !! 64 def read_from_file(self, path: str) -> None: 98 continue !! 65 with open(path, 'r') as f: 99 !! 66 self.parse_from_string(f.read()) 100 empty_match = is_not_set_match << 101 if empty_match: << 102 kconfig.add_entry(empt << 103 continue << 104 << 105 if line[0] == '#': << 106 continue << 107 raise KconfigParseError('Faile << 108 return kconfig <<
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.