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', ['name', 'value']) 17 class KconfigEntry: !! 16 18 name: str !! 17 class KconfigEntry(KconfigEntryBase): 19 value: str << 20 18 21 def __str__(self) -> str: 19 def __str__(self) -> str: 22 if self.value == 'n': 20 if self.value == 'n': 23 return f'# CONFIG_{sel !! 21 return r'# CONFIG_%s is not set' % (self.name) 24 return f'CONFIG_{self.name}={s !! 22 else: >> 23 return r'CONFIG_%s=%s' % (self.name, self.value) 25 24 26 25 27 class KconfigParseError(Exception): 26 class KconfigParseError(Exception): 28 """Error parsing Kconfig defconfig or 27 """Error parsing Kconfig defconfig or .config.""" 29 28 30 29 31 class Kconfig: !! 30 class Kconfig(object): 32 """Represents defconfig or .config spe 31 """Represents defconfig or .config specified using the Kconfig language.""" 33 32 34 def __init__(self) -> None: !! 33 def __init__(self): 35 self._entries = {} # type: Di !! 34 self._entries = [] 36 35 37 def __eq__(self, other: Any) -> bool: !! 36 def entries(self): 38 if not isinstance(other, self. !! 37 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 38 49 def add_entry(self, name: str, value: !! 39 def add_entry(self, entry: KconfigEntry) -> None: 50 self._entries[name] = value !! 40 self._entries.append(entry) 51 41 52 def is_subset_of(self, other: 'Kconfig 42 def is_subset_of(self, other: 'Kconfig') -> bool: 53 for name, value in self._entri !! 43 for a in self.entries(): 54 b = other._entries.get !! 44 found = False 55 if b is None: !! 45 for b in other.entries(): 56 if value == 'n !! 46 if a.name != b.name: 57 contin 47 continue 58 return False !! 48 if a.value != b.value: 59 if value != b: !! 49 return False >> 50 found = True >> 51 if a.value != 'n' and found == False: 60 return False 52 return False 61 return True 53 return True 62 54 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 << 76 def write_to_file(self, path: str) -> 55 def write_to_file(self, path: str) -> None: 77 with open(path, 'a+') as f: !! 56 with open(path, 'w') as f: 78 for e in self.as_entri !! 57 for entry in self.entries(): 79 f.write(str(e) !! 58 f.write(str(entry) + '\n') 80 !! 59 81 def parse_file(path: str) -> Kconfig: !! 60 def parse_from_string(self, blob: str) -> None: 82 with open(path, 'r') as f: !! 61 """Parses a string containing KconfigEntrys and populates this Kconfig.""" 83 return parse_from_string(f.rea !! 62 self._entries = [] 84 !! 63 is_not_set_matcher = re.compile(CONFIG_IS_NOT_SET_PATTERN) 85 def parse_from_string(blob: str) -> Kconfig: !! 64 config_matcher = re.compile(CONFIG_PATTERN) 86 """Parses a string containing Kconfig !! 65 for line in blob.split('\n'): 87 kconfig = Kconfig() !! 66 line = line.strip() 88 is_not_set_matcher = re.compile(CONFIG !! 67 if not line: 89 config_matcher = re.compile(CONFIG_PAT !! 68 continue 90 for line in blob.split('\n'): !! 69 91 line = line.strip() !! 70 match = config_matcher.match(line) 92 if not line: !! 71 if match: 93 continue !! 72 entry = KconfigEntry(match.group(1), match.group(2)) 94 !! 73 self.add_entry(entry) 95 match = config_matcher.match(l !! 74 continue 96 if match: !! 75 97 kconfig.add_entry(matc !! 76 empty_match = is_not_set_matcher.match(line) 98 continue !! 77 if empty_match: 99 !! 78 entry = KconfigEntry(empty_match.group(1), 'n') 100 empty_match = is_not_set_match !! 79 self.add_entry(entry) 101 if empty_match: !! 80 continue 102 kconfig.add_entry(empt !! 81 103 continue !! 82 if line[0] == '#': 104 !! 83 continue 105 if line[0] == '#': !! 84 else: 106 continue !! 85 raise KconfigParseError('Failed to parse: ' + line) 107 raise KconfigParseError('Faile !! 86 108 return kconfig !! 87 def read_from_file(self, path: str) -> None: >> 88 with open(path, 'r') as f: >> 89 self.parse_from_string(f.read())
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.