1# SPDX-License-Identifier: GPL-2.0 2# 3# Builds a .config from a kunitconfig. 4# 5# Copyright (C) 2019, Google LLC. 6# Author: Felix Guo <felixguoxiuping@gmail.com> 7# Author: Brendan Higgins <brendanhiggins@google.com> 8 9import collections 10import re 11 12CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_\w+ is not set$' 13CONFIG_PATTERN = r'^CONFIG_\w+=\S+$' 14 15KconfigEntryBase = collections.namedtuple('KconfigEntry', ['raw_entry']) 16 17 18class KconfigEntry(KconfigEntryBase): 19 20 def __str__(self) -> str: 21 return self.raw_entry 22 23 24class KconfigParseError(Exception): 25 """Error parsing Kconfig defconfig or .config.""" 26 27 28class Kconfig(object): 29 """Represents defconfig or .config specified using the Kconfig language.""" 30 31 def __init__(self): 32 self._entries = [] 33 34 def entries(self): 35 return set(self._entries) 36 37 def add_entry(self, entry: KconfigEntry) -> None: 38 self._entries.append(entry) 39 40 def is_subset_of(self, other: 'Kconfig') -> bool: 41 return self.entries().issubset(other.entries()) 42 43 def write_to_file(self, path: str) -> None: 44 with open(path, 'w') as f: 45 for entry in self.entries(): 46 f.write(str(entry) + '\n') 47 48 def parse_from_string(self, blob: str) -> None: 49 """Parses a string containing KconfigEntrys and populates this Kconfig.""" 50 self._entries = [] 51 is_not_set_matcher = re.compile(CONFIG_IS_NOT_SET_PATTERN) 52 config_matcher = re.compile(CONFIG_PATTERN) 53 for line in blob.split('\n'): 54 line = line.strip() 55 if not line: 56 continue 57 elif config_matcher.match(line) or is_not_set_matcher.match(line): 58 self._entries.append(KconfigEntry(line)) 59 elif line[0] == '#': 60 continue 61 else: 62 raise KconfigParseError('Failed to parse: ' + line) 63 64 def read_from_file(self, path: str) -> None: 65 with open(path, 'r') as f: 66 self.parse_from_string(f.read()) 67