1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
#!/usr/bin/env python3
import kconfiglib
from frozendict import frozendict
import json
import os
import subprocess
class KConfigAttributes:
def __init__(self, kconfig_path, datadir):
experiments = list()
failed_experiments = list()
for direntry in os.listdir(datadir):
config_path = f"{datadir}/{direntry}/.config"
attr_path = f"{datadir}/{direntry}/attributes.json"
metadata_path = f"{datadir}/{direntry}/metadata"
if os.path.exists(attr_path):
experiments.append((config_path, attr_path))
elif os.path.exists(config_path):
failed_experiments.append(config_path)
kconf = kconfiglib.Kconfig(kconfig_path)
self.kconf = kconf
self.kconfig_hash = self.file_hash(kconfig_path)
self.kconfig_dir = "unknown"
if "/" in kconfig_path:
self.kconfig_dir = kconfig_path.split("/")[-2]
self.symbol_names = sorted(
map(
lambda sym: sym.name,
filter(
lambda sym: kconfiglib.TYPE_TO_STR[sym.type]
in ("bool", "tristate", "int", "string", "hex"),
kconf.syms.values(),
),
)
)
self.choice_names = sorted(
map(lambda choice: choice.name or choice.name_and_loc, kconf.choices)
)
self.choice = dict()
self.choice_symbol_names = list()
for choice in kconf.choices:
self.choice[choice.name or choice.name_and_loc] = choice
self.choice_symbol_names.extend(map(lambda sym: sym.name, choice.syms))
self.symbol = dict()
for symbol_name in self.symbol_names:
self.symbol[symbol_name] = kconf.syms[symbol_name]
if int(os.getenv("DFATOOL_KCONF_WITH_CHOICE_NODES", 1)):
for sym_name in self.choice_symbol_names:
self.symbol_names.remove(sym_name)
self.param_names = self.symbol_names + self.choice_names
else:
self.param_names = self.symbol_names
self.data = list()
self.configs = list()
self.failures = list()
for config_path, attr_path in experiments:
self.configs.append(config_path)
kconf.load_config(config_path)
with open(attr_path, "r") as f:
attr = json.load(f)
param = self._conf_to_param()
self.data.append((frozendict(param), attr))
for config_path in failed_experiments:
kconf.load_config(config_path)
param = self._conf_to_param()
self.failures.append(frozendict(param))
def _conf_to_param(self):
param = dict()
for sym_name in self.symbol_names:
sym = self.kconf.syms[sym_name]
if not sym.visibility and sym.str_value == "":
param[sym_name] = None
elif kconfiglib.TYPE_TO_STR[sym.type] in ("int", "hex"):
try:
param[sym_name] = int(sym.str_value, base=0)
except ValueError:
print(
f"Warning: Illegal value for {sym.__repr__()}, defaulting to None"
)
param[sym_name] = None
else:
param[sym_name] = sym.str_value
for choice in self.choice_names:
if self.choice[choice].selection is None:
param[choice] = None
else:
param[choice] = self.choice[choice].selection.name
return param
def file_hash(self, config_file):
status = subprocess.run(
["sha256sum", config_file],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
)
sha256sum = status.stdout.split()[0]
return sha256sum
|