blob: ca22fb093ea5c502aa8b21f14412460eabe3f4bc [file] [log] [blame]
#!/usr/bin/env python3
# Copyright (c) 2025 Arduino SA
# SPDX-License-Identifier: Apache-2.0
import argparse
import os
import pickle
from tabulate import tabulate
KIND_TO_COL = {
"unset": "not set",
"default": "default",
"assign": "assigned",
"select": "selected",
"imply": "implied",
}
def source_link(refpath, fn, ln):
if refpath:
fn = os.path.relpath(fn, refpath)
link_fn = fn
disp_fn = os.path.normpath(fn).replace("../", "").replace("_", "\\_")
return f"[{disp_fn}:{ln}](<{link_fn}#L{ln}>)"
def write_markdown(trace_data, output):
sections = {"user": [], "hidden": [], "unset": []}
if os.name == "nt":
# relative paths on Windows can't span drives, so don't use them
# generated links will be absolute
refpath = None
else:
refpath = os.path.dirname(os.path.abspath(output))
for sym in trace_data:
sym_name, sym_vis, sym_type, sym_value, sym_src, sym_loc = sym
if sym_vis == "n":
section = "hidden"
elif sym_src == "unset":
section = "unset"
else:
section = "user"
if section == "user":
sym_name = f"`{sym_name}`"
elif section == "hidden":
sym_name = f"`{sym_name}` (h)"
if sym_type == "string" and sym_value is not None:
sym_value = f'"{sym_value}"'.replace("_", "\\_")
if isinstance(sym_loc, tuple):
sym_loc = source_link(refpath, *sym_loc)
elif isinstance(sym_loc, list):
sym_loc = " || <br> ".join(f"`{loc}`" for loc in sym_loc)
sym_loc = sym_loc.replace("|", "\\|")
elif sym_loc is None and sym_src == "default":
sym_loc = "_(implicit)_"
sym_src = KIND_TO_COL[sym_src]
sections[section].append((sym_type, sym_name, sym_value, sym_src, sym_loc))
lines = []
add = lines.append
headers = ["Type", "Name", "Value", "Source", "Location"]
colaligns = ["right", "left", "right", "center", "left"]
add("\n## Visible symbols\n\n")
add(
tabulate(
sorted(sections["user"], key=lambda x: x[1]),
headers=headers,
tablefmt='pipe',
colalign=colaligns,
)
)
add("\n\n## Invisible symbols\n\n")
add(
tabulate(
sorted(sections["hidden"], key=lambda x: x[1]),
headers=headers,
tablefmt='pipe',
colalign=colaligns,
)
)
add("\n\n## Unset symbols\n\n")
for sym_name in sorted(x[1] for x in sections["unset"]):
add(f" # {sym_name} is not set\n")
with open(output, "w") as f:
f.writelines(lines)
def main():
parser = argparse.ArgumentParser(allow_abbrev=False)
parser.add_argument("dotconfig_file", help="Input merged .config file")
parser.add_argument("output_file", help="Output Markdown file")
parser.add_argument("kconfig_file", help="Top-level Kconfig file", nargs="?")
args = parser.parse_args()
with open(args.dotconfig_file + '-trace.pickle', 'rb') as f:
trace_data = pickle.load(f)
write_markdown(trace_data, args.output_file)
if __name__ == '__main__':
main()