mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-09 20:27:41 +08:00
chore(gdb): refactor generators into shared enum_parser and unified generate_all entry
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
*.egg-info/
|
||||
dist/
|
||||
build/
|
||||
__pycache__/
|
||||
.idea/
|
||||
.DS_Store
|
||||
@@ -1,8 +1,8 @@
|
||||
"""
|
||||
Auto-generated indev constants from LVGL headers.
|
||||
|
||||
Do not edit manually. Regenerate with:
|
||||
python3 scripts/gen_indev_consts.py
|
||||
Do not edit manually. Regenerate from the GDB script root with:
|
||||
python3 scripts/generate_all.py
|
||||
"""
|
||||
|
||||
INDEV_TYPE_NAMES = {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"""
|
||||
Auto-generated observer constants from LVGL headers.
|
||||
|
||||
Do not edit manually. Regenerate with:
|
||||
python3 scripts/gen_subject_consts.py
|
||||
Do not edit manually. Regenerate from the GDB script root with:
|
||||
python3 scripts/generate_all.py
|
||||
"""
|
||||
|
||||
SUBJECT_TYPE_NAMES = {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"""
|
||||
Auto-generated draw constants from LVGL headers.
|
||||
|
||||
Do not edit manually. Regenerate with:
|
||||
python3 scripts/gen_draw_consts.py
|
||||
Do not edit manually. Regenerate from the GDB script root with:
|
||||
python3 scripts/generate_all.py
|
||||
"""
|
||||
|
||||
DRAW_TASK_TYPE_NAMES = {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"""
|
||||
Auto-generated event constants from LVGL headers.
|
||||
|
||||
Do not edit manually. Regenerate with:
|
||||
python3 scripts/gen_event_consts.py
|
||||
Do not edit manually. Regenerate from the GDB script root with:
|
||||
python3 scripts/generate_all.py
|
||||
"""
|
||||
|
||||
EVENT_CODE_NAMES = {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"""
|
||||
Auto-generated style constants from LVGL headers.
|
||||
|
||||
Do not edit manually. Regenerate with:
|
||||
python3 scripts/gen_style_consts.py
|
||||
Do not edit manually. Regenerate from the GDB script root with:
|
||||
python3 scripts/generate_all.py
|
||||
"""
|
||||
|
||||
STYLE_PROP_NAMES = {
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Shared utilities for LVGL constant generators.
|
||||
|
||||
Provides:
|
||||
- parse_enum(): Parse a C typedef enum from a header file.
|
||||
- generate_dict_module(): Generate a Python module with dict constants.
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def parse_enum(path: Path, enum_type: str, prefix: str,
|
||||
skip: set[str] | None = None) -> dict[int, str]:
|
||||
"""Parse a C typedef enum from a header file.
|
||||
|
||||
Args:
|
||||
path: Path to the C header file.
|
||||
enum_type: The typedef name (e.g. "lv_indev_type_t").
|
||||
prefix: Enum member prefix to strip (e.g. "LV_INDEV_TYPE_").
|
||||
skip: Optional set of full enum member names to skip.
|
||||
|
||||
Returns:
|
||||
Dict mapping int value -> short name string.
|
||||
"""
|
||||
text = path.read_text()
|
||||
skip = skip or set()
|
||||
|
||||
pattern = rf"\}}\s*{re.escape(enum_type)}\s*;"
|
||||
m = re.search(rf"typedef\s+enum\s*\{{(.*?){pattern}", text, re.DOTALL)
|
||||
if not m:
|
||||
raise RuntimeError(f"Cannot find {enum_type} enum in {path}")
|
||||
|
||||
entries = {}
|
||||
current_val = 0
|
||||
for line in m.group(1).splitlines():
|
||||
line = line.strip().rstrip(",")
|
||||
if (
|
||||
not line
|
||||
or line.startswith("/*")
|
||||
or line.startswith("//")
|
||||
or line.startswith("*")
|
||||
or line.startswith("#")
|
||||
):
|
||||
continue
|
||||
|
||||
match = re.match(
|
||||
rf"({re.escape(prefix)}\w+)\s*=\s*(0x[\da-fA-F]+|\d+)", line
|
||||
)
|
||||
if match:
|
||||
name = match.group(1)
|
||||
current_val = int(match.group(2), 0)
|
||||
else:
|
||||
match = re.match(rf"({re.escape(prefix)}\w+)", line)
|
||||
if not match:
|
||||
continue
|
||||
name = match.group(1)
|
||||
|
||||
if name in skip:
|
||||
current_val += 1
|
||||
continue
|
||||
|
||||
short = name.removeprefix(prefix)
|
||||
entries[current_val] = short
|
||||
current_val += 1
|
||||
|
||||
return entries
|
||||
|
||||
|
||||
def generate_dict_module(
|
||||
description: str,
|
||||
dicts: dict[str, dict],
|
||||
) -> str:
|
||||
"""Generate a Python module containing one or more dict constants.
|
||||
|
||||
Args:
|
||||
description: Short description for the module docstring.
|
||||
dicts: Mapping of variable_name -> dict to emit.
|
||||
|
||||
Returns:
|
||||
Python source code string.
|
||||
"""
|
||||
lines = [
|
||||
'"""',
|
||||
f"Auto-generated {description}.",
|
||||
"",
|
||||
"Do not edit manually. Regenerate from the GDB script root with:",
|
||||
" python3 scripts/generate_all.py",
|
||||
'"""',
|
||||
"",
|
||||
]
|
||||
|
||||
for var_name, data in dicts.items():
|
||||
lines.append(f"{var_name} = {{")
|
||||
for k in sorted(data):
|
||||
v = data[k]
|
||||
if isinstance(k, int):
|
||||
lines.append(f' {k}: "{v}",')
|
||||
else:
|
||||
lines.append(f' "{k}": "{v}",')
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
return "\n".join(lines)
|
||||
@@ -1,141 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate draw constant tables from LVGL header and source files.
|
||||
|
||||
Parses lv_draw.h for task type/state enums, and scans draw unit source
|
||||
files for name-to-struct-type mappings.
|
||||
|
||||
Usage:
|
||||
python3 scripts/gen_draw_consts.py
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
SCRIPT_DIR = Path(__file__).parent
|
||||
GDB_ROOT = SCRIPT_DIR.parent
|
||||
LVGL_SRC = GDB_ROOT.parent.parent / "src"
|
||||
OUTPUT = GDB_ROOT / "lvglgdb" / "lvgl" / "draw" / "lv_draw_consts.py"
|
||||
|
||||
DRAW_H = LVGL_SRC / "draw" / "lv_draw.h"
|
||||
DRAW_DIR = LVGL_SRC / "draw"
|
||||
|
||||
sys.path.insert(0, str(SCRIPT_DIR))
|
||||
|
||||
|
||||
def parse_enum(path: Path, enum_type: str, prefix: str) -> dict[int, str]:
|
||||
"""Parse a C enum from a header file."""
|
||||
text = path.read_text()
|
||||
|
||||
pattern = rf"\}}\s*{re.escape(enum_type)}\s*;"
|
||||
m = re.search(rf"typedef\s+enum\s*\{{(.*?){pattern}", text, re.DOTALL)
|
||||
if not m:
|
||||
raise RuntimeError(f"Cannot find {enum_type} enum in {path}")
|
||||
|
||||
entries = {}
|
||||
current_val = 0
|
||||
for line in m.group(1).splitlines():
|
||||
line = line.strip().rstrip(",")
|
||||
if (
|
||||
not line
|
||||
or line.startswith("/*")
|
||||
or line.startswith("//")
|
||||
or line.startswith("*")
|
||||
or line.startswith("#")
|
||||
):
|
||||
continue
|
||||
|
||||
match = re.match(rf"({re.escape(prefix)}\w+)\s*=\s*(0x[\da-fA-F]+|\d+)", line)
|
||||
if match:
|
||||
name = match.group(1)
|
||||
current_val = int(match.group(2), 0)
|
||||
else:
|
||||
match = re.match(rf"({re.escape(prefix)}\w+)", line)
|
||||
if not match:
|
||||
continue
|
||||
name = match.group(1)
|
||||
|
||||
short = name.removeprefix(prefix)
|
||||
entries[current_val] = short
|
||||
current_val += 1
|
||||
|
||||
return entries
|
||||
|
||||
|
||||
def parse_draw_unit_types(draw_dir: Path) -> dict[str, str]:
|
||||
"""Scan draw unit .c files for name-to-struct-type mappings.
|
||||
|
||||
Looks for patterns like: unit->base_unit.name = "SW";
|
||||
Then finds the corresponding struct type from the variable declaration.
|
||||
"""
|
||||
mappings = {}
|
||||
|
||||
for c_file in draw_dir.rglob("*.c"):
|
||||
text = c_file.read_text()
|
||||
|
||||
for m in re.finditer(r'(\w+)->base_unit\.name\s*=\s*"(\w+)"', text):
|
||||
var_name = m.group(1)
|
||||
unit_name = m.group(2)
|
||||
|
||||
decl = re.search(
|
||||
rf"(lv_draw_\w+_unit_t)\s*\*\s*{re.escape(var_name)}\b", text
|
||||
)
|
||||
if decl:
|
||||
mappings[unit_name] = decl.group(1)
|
||||
|
||||
return mappings
|
||||
|
||||
|
||||
def generate(
|
||||
task_types: dict[int, str],
|
||||
task_states: dict[int, str],
|
||||
unit_types: dict[str, str],
|
||||
) -> str:
|
||||
"""Generate Python source for the draw constants module."""
|
||||
lines = [
|
||||
'"""',
|
||||
"Auto-generated draw constants from LVGL headers.",
|
||||
"",
|
||||
"Do not edit manually. Regenerate with:",
|
||||
" python3 scripts/gen_draw_consts.py",
|
||||
'"""',
|
||||
"",
|
||||
]
|
||||
|
||||
lines.append("DRAW_TASK_TYPE_NAMES = {")
|
||||
for k in sorted(task_types):
|
||||
lines.append(f' {k}: "{task_types[k]}",')
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
lines.append("DRAW_TASK_STATE_NAMES = {")
|
||||
for k in sorted(task_states):
|
||||
lines.append(f' {k}: "{task_states[k]}",')
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
lines.append("DRAW_UNIT_TYPE_NAMES = {")
|
||||
for name in sorted(unit_types):
|
||||
lines.append(f' "{name}": "{unit_types[name]}",')
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
task_types = parse_enum(DRAW_H, "lv_draw_task_type_t", "LV_DRAW_TASK_TYPE_")
|
||||
task_states = parse_enum(DRAW_H, "lv_draw_task_state_t", "LV_DRAW_TASK_STATE_")
|
||||
unit_types = parse_draw_unit_types(DRAW_DIR)
|
||||
|
||||
src = generate(task_types, task_states, unit_types)
|
||||
OUTPUT.write_text(src)
|
||||
print(
|
||||
f"Generated {OUTPUT} ({len(task_types)} task types, "
|
||||
f"{len(task_states)} task states, {len(unit_types)} unit types)"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,95 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate event constant tables from LVGL header files.
|
||||
|
||||
Parses lv_event.h for the lv_event_code_t enum.
|
||||
|
||||
Usage:
|
||||
python3 scripts/gen_event_consts.py
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
SCRIPT_DIR = Path(__file__).parent
|
||||
GDB_ROOT = SCRIPT_DIR.parent
|
||||
LVGL_SRC = GDB_ROOT.parent.parent / "src"
|
||||
OUTPUT = GDB_ROOT / "lvglgdb" / "lvgl" / "misc" / "lv_event_consts.py"
|
||||
|
||||
EVENT_H = LVGL_SRC / "misc" / "lv_event.h"
|
||||
|
||||
|
||||
def parse_event_codes(path: Path) -> dict[int, str]:
|
||||
"""Parse lv_event_code_t enum from lv_event.h."""
|
||||
text = path.read_text()
|
||||
|
||||
m = re.search(r"typedef\s+enum\s*\{(.*?)\}\s*lv_event_code_t", text, re.DOTALL)
|
||||
if not m:
|
||||
raise RuntimeError("Cannot find lv_event_code_t enum")
|
||||
|
||||
codes = {}
|
||||
current_val = 0
|
||||
for line in m.group(1).splitlines():
|
||||
line = line.strip().rstrip(",")
|
||||
if (
|
||||
not line
|
||||
or line.startswith("/*")
|
||||
or line.startswith("//")
|
||||
or line.startswith("*")
|
||||
or line.startswith("#")
|
||||
):
|
||||
continue
|
||||
|
||||
# Match: LV_EVENT_XXX = value
|
||||
match = re.match(r"(LV_EVENT_\w+)\s*=\s*(0x[\da-fA-F]+|\d+)", line)
|
||||
if match:
|
||||
name = match.group(1)
|
||||
current_val = int(match.group(2), 0)
|
||||
else:
|
||||
match = re.match(r"(LV_EVENT_\w+)", line)
|
||||
if not match:
|
||||
continue
|
||||
name = match.group(1)
|
||||
|
||||
# Skip meta entries
|
||||
if name in ("LV_EVENT_LAST", "LV_EVENT_PREPROCESS", "LV_EVENT_MARKED_DELETING"):
|
||||
current_val += 1
|
||||
continue
|
||||
|
||||
short = name.removeprefix("LV_EVENT_")
|
||||
codes[current_val] = short
|
||||
current_val += 1
|
||||
|
||||
return codes
|
||||
|
||||
|
||||
def generate(codes: dict[int, str]) -> str:
|
||||
"""Generate Python source for the event constants module."""
|
||||
lines = [
|
||||
'"""',
|
||||
"Auto-generated event constants from LVGL headers.",
|
||||
"",
|
||||
"Do not edit manually. Regenerate with:",
|
||||
" python3 scripts/gen_event_consts.py",
|
||||
'"""',
|
||||
"",
|
||||
]
|
||||
|
||||
lines.append("EVENT_CODE_NAMES = {")
|
||||
for k in sorted(codes):
|
||||
lines.append(f' {k}: "{codes[k]}",')
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
codes = parse_event_codes(EVENT_H)
|
||||
src = generate(codes)
|
||||
OUTPUT.write_text(src)
|
||||
print(f"Generated {OUTPUT} ({len(codes)} event codes)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,89 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate indev constant tables from LVGL header files.
|
||||
|
||||
Parses lv_indev.h for indev type enum.
|
||||
|
||||
Usage:
|
||||
python3 scripts/gen_indev_consts.py
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
SCRIPT_DIR = Path(__file__).parent
|
||||
GDB_ROOT = SCRIPT_DIR.parent
|
||||
LVGL_SRC = GDB_ROOT.parent.parent / "src"
|
||||
OUTPUT = GDB_ROOT / "lvglgdb" / "lvgl" / "core" / "lv_indev_consts.py"
|
||||
|
||||
INDEV_H = LVGL_SRC / "indev" / "lv_indev.h"
|
||||
|
||||
|
||||
def parse_enum(path: Path, enum_type: str, prefix: str) -> dict[int, str]:
|
||||
"""Parse a C enum from a header file."""
|
||||
text = path.read_text()
|
||||
|
||||
pattern = rf"\}}\s*{re.escape(enum_type)}\s*;"
|
||||
m = re.search(rf"typedef\s+enum\s*\{{(.*?){pattern}", text, re.DOTALL)
|
||||
if not m:
|
||||
raise RuntimeError(f"Cannot find {enum_type} enum in {path}")
|
||||
|
||||
entries = {}
|
||||
current_val = 0
|
||||
for line in m.group(1).splitlines():
|
||||
line = line.strip().rstrip(",")
|
||||
if (
|
||||
not line
|
||||
or line.startswith("/*")
|
||||
or line.startswith("//")
|
||||
or line.startswith("*")
|
||||
or line.startswith("#")
|
||||
):
|
||||
continue
|
||||
|
||||
match = re.match(rf"({re.escape(prefix)}\w+)\s*=\s*(0x[\da-fA-F]+|\d+)", line)
|
||||
if match:
|
||||
name = match.group(1)
|
||||
current_val = int(match.group(2), 0)
|
||||
else:
|
||||
match = re.match(rf"({re.escape(prefix)}\w+)", line)
|
||||
if not match:
|
||||
continue
|
||||
name = match.group(1)
|
||||
|
||||
short = name.removeprefix(prefix)
|
||||
entries[current_val] = short
|
||||
current_val += 1
|
||||
|
||||
return entries
|
||||
|
||||
|
||||
def generate(indev_types: dict[int, str]) -> str:
|
||||
"""Generate Python source for the indev constants module."""
|
||||
lines = [
|
||||
'"""',
|
||||
"Auto-generated indev constants from LVGL headers.",
|
||||
"",
|
||||
"Do not edit manually. Regenerate with:",
|
||||
" python3 scripts/gen_indev_consts.py",
|
||||
'"""',
|
||||
"",
|
||||
"INDEV_TYPE_NAMES = {",
|
||||
]
|
||||
for k in sorted(indev_types):
|
||||
lines.append(f' {k}: "{indev_types[k]}",')
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
indev_types = parse_enum(INDEV_H, "lv_indev_type_t", "LV_INDEV_TYPE_")
|
||||
src = generate(indev_types)
|
||||
OUTPUT.write_text(src)
|
||||
print(f"Generated {OUTPUT} ({len(indev_types)} indev types)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,53 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate subject type constant table from LVGL header files.
|
||||
|
||||
Parses lv_observer.h for subject type enum.
|
||||
|
||||
Usage:
|
||||
python3 scripts/gen_subject_consts.py
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
SCRIPT_DIR = Path(__file__).parent
|
||||
GDB_ROOT = SCRIPT_DIR.parent
|
||||
LVGL_SRC = GDB_ROOT.parent.parent / "src"
|
||||
OUTPUT = GDB_ROOT / "lvglgdb" / "lvgl" / "core" / "lv_observer_consts.py"
|
||||
|
||||
OBSERVER_H = LVGL_SRC / "core" / "lv_observer.h"
|
||||
|
||||
sys.path.insert(0, str(SCRIPT_DIR))
|
||||
from gen_indev_consts import parse_enum
|
||||
|
||||
|
||||
def generate(subject_types: dict[int, str]) -> str:
|
||||
"""Generate Python source for the observer constants module."""
|
||||
lines = [
|
||||
'"""',
|
||||
"Auto-generated observer constants from LVGL headers.",
|
||||
"",
|
||||
"Do not edit manually. Regenerate with:",
|
||||
" python3 scripts/gen_subject_consts.py",
|
||||
'"""',
|
||||
"",
|
||||
"SUBJECT_TYPE_NAMES = {",
|
||||
]
|
||||
for k in sorted(subject_types):
|
||||
lines.append(f' {k}: "{subject_types[k]}",')
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
subject_types = parse_enum(OBSERVER_H, "lv_subject_type_t", "LV_SUBJECT_TYPE_")
|
||||
src = generate(subject_types)
|
||||
OUTPUT.write_text(src)
|
||||
print(f"Generated {OUTPUT} ({len(subject_types)} subject types)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Unified entry point for all LVGL GDB constant generators.
|
||||
|
||||
Scans the generators/ subdirectory for gen_*.py modules and calls
|
||||
each module's main() function.
|
||||
|
||||
Usage (from the GDB script root):
|
||||
python3 scripts/generate_all.py
|
||||
"""
|
||||
|
||||
import importlib
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
SCRIPT_DIR = Path(__file__).parent
|
||||
GENERATORS_DIR = SCRIPT_DIR / "generators"
|
||||
|
||||
# Make enum_parser importable from generators
|
||||
sys.path.insert(0, str(SCRIPT_DIR))
|
||||
|
||||
|
||||
def main():
|
||||
gen_files = sorted(GENERATORS_DIR.glob("gen_*.py"))
|
||||
if not gen_files:
|
||||
print("No generators found.")
|
||||
return
|
||||
|
||||
print(f"Running {len(gen_files)} generator(s)...\n")
|
||||
|
||||
for gen_file in gen_files:
|
||||
module_name = gen_file.stem
|
||||
print(f" [{module_name}]")
|
||||
spec = importlib.util.spec_from_file_location(module_name, gen_file)
|
||||
mod = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(mod)
|
||||
mod.main()
|
||||
print()
|
||||
|
||||
print("All generators completed.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1 @@
|
||||
# generators package
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate draw constant tables from LVGL headers and source files."""
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||
from enum_parser import parse_enum, generate_dict_module
|
||||
|
||||
LVGL_SRC = Path(__file__).parent.parent.parent.parent.parent / "src"
|
||||
OUTPUT = Path(__file__).parent.parent.parent / "lvglgdb" / "lvgl" / "draw" / "lv_draw_consts.py"
|
||||
|
||||
DRAW_H = LVGL_SRC / "draw" / "lv_draw.h"
|
||||
DRAW_DIR = LVGL_SRC / "draw"
|
||||
|
||||
|
||||
def parse_draw_unit_types(draw_dir: Path) -> dict[str, str]:
|
||||
"""Scan draw unit .c files for name-to-struct-type mappings.
|
||||
|
||||
Looks for patterns like: unit->base_unit.name = "SW";
|
||||
Then finds the corresponding struct type from the variable declaration.
|
||||
"""
|
||||
mappings = {}
|
||||
for c_file in draw_dir.rglob("*.c"):
|
||||
text = c_file.read_text()
|
||||
for m in re.finditer(r'(\w+)->base_unit\.name\s*=\s*"(\w+)"', text):
|
||||
var_name = m.group(1)
|
||||
unit_name = m.group(2)
|
||||
decl = re.search(
|
||||
rf"(lv_draw_\w+_unit_t)\s*\*\s*{re.escape(var_name)}\b", text
|
||||
)
|
||||
if decl:
|
||||
mappings[unit_name] = decl.group(1)
|
||||
return mappings
|
||||
|
||||
|
||||
def main():
|
||||
task_types = parse_enum(DRAW_H, "lv_draw_task_type_t", "LV_DRAW_TASK_TYPE_")
|
||||
task_states = parse_enum(DRAW_H, "lv_draw_task_state_t", "LV_DRAW_TASK_STATE_")
|
||||
unit_types = parse_draw_unit_types(DRAW_DIR)
|
||||
|
||||
src = generate_dict_module(
|
||||
"draw constants from LVGL headers",
|
||||
{
|
||||
"DRAW_TASK_TYPE_NAMES": task_types,
|
||||
"DRAW_TASK_STATE_NAMES": task_states,
|
||||
"DRAW_UNIT_TYPE_NAMES": unit_types,
|
||||
},
|
||||
)
|
||||
OUTPUT.write_text(src)
|
||||
print(
|
||||
f"Generated {OUTPUT.name} ({len(task_types)} task types, "
|
||||
f"{len(task_states)} task states, {len(unit_types)} unit types)"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate event constant tables from LVGL headers."""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||
from enum_parser import parse_enum, generate_dict_module
|
||||
|
||||
LVGL_SRC = Path(__file__).parent.parent.parent.parent.parent / "src"
|
||||
OUTPUT = Path(__file__).parent.parent.parent / "lvglgdb" / "lvgl" / "misc" / "lv_event_consts.py"
|
||||
|
||||
SKIP_EVENTS = {"LV_EVENT_LAST", "LV_EVENT_PREPROCESS", "LV_EVENT_MARKED_DELETING"}
|
||||
|
||||
|
||||
def main():
|
||||
event_codes = parse_enum(
|
||||
LVGL_SRC / "misc" / "lv_event.h",
|
||||
"lv_event_code_t",
|
||||
"LV_EVENT_",
|
||||
skip=SKIP_EVENTS,
|
||||
)
|
||||
src = generate_dict_module(
|
||||
"event constants from LVGL headers",
|
||||
{"EVENT_CODE_NAMES": event_codes},
|
||||
)
|
||||
OUTPUT.write_text(src)
|
||||
print(f"Generated {OUTPUT.name} ({len(event_codes)} event codes)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate indev constant tables from LVGL headers."""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||
from enum_parser import parse_enum, generate_dict_module
|
||||
|
||||
LVGL_SRC = Path(__file__).parent.parent.parent.parent.parent / "src"
|
||||
OUTPUT = Path(__file__).parent.parent.parent / "lvglgdb" / "lvgl" / "core" / "lv_indev_consts.py"
|
||||
|
||||
|
||||
def main():
|
||||
indev_types = parse_enum(
|
||||
LVGL_SRC / "indev" / "lv_indev.h",
|
||||
"lv_indev_type_t",
|
||||
"LV_INDEV_TYPE_",
|
||||
)
|
||||
src = generate_dict_module(
|
||||
"indev constants from LVGL headers",
|
||||
{"INDEV_TYPE_NAMES": indev_types},
|
||||
)
|
||||
OUTPUT.write_text(src)
|
||||
print(f"Generated {OUTPUT.name} ({len(indev_types)} indev types)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+24
-76
@@ -1,32 +1,29 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate style constant tables from LVGL header files.
|
||||
|
||||
Parses lv_style.h, lv_obj_style.h, and lv_style_gen.h to produce
|
||||
lv_style_consts.py used by the lvglgdb GDB plugin.
|
||||
|
||||
Usage:
|
||||
python3 scripts/gen_style_consts.py
|
||||
"""
|
||||
"""Generate style constant tables from LVGL headers."""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
SCRIPT_DIR = Path(__file__).parent
|
||||
GDB_ROOT = SCRIPT_DIR.parent
|
||||
LVGL_SRC = GDB_ROOT.parent.parent / "src"
|
||||
LVGL_SRC = Path(__file__).parent.parent.parent.parent.parent / "src"
|
||||
GDB_ROOT = Path(__file__).parent.parent.parent
|
||||
OUTPUT = GDB_ROOT / "lvglgdb" / "lvgl" / "misc" / "lv_style_consts.py"
|
||||
|
||||
STYLE_H = LVGL_SRC / "misc" / "lv_style.h"
|
||||
OBJ_STYLE_H = LVGL_SRC / "core" / "lv_obj_style.h"
|
||||
STYLE_GEN_H = LVGL_SRC / "misc" / "lv_style_gen.h"
|
||||
|
||||
SKIP_PROPS = {
|
||||
"LV_STYLE_PROP_INV",
|
||||
"LV_STYLE_PROP_ANY",
|
||||
"LV_STYLE_PROP_CONST",
|
||||
"LV_STYLE_LAST_BUILT_IN_PROP",
|
||||
"LV_STYLE_NUM_BUILT_IN_PROPS",
|
||||
}
|
||||
|
||||
|
||||
def parse_style_props(path: Path) -> dict[int, str]:
|
||||
"""Parse _lv_style_id_t enum from lv_style.h."""
|
||||
text = path.read_text()
|
||||
|
||||
# Extract enum block
|
||||
m = re.search(r"enum\s+_lv_style_id_t\s*\{(.*?)\}", text, re.DOTALL)
|
||||
if not m:
|
||||
raise RuntimeError("Cannot find _lv_style_id_t enum")
|
||||
@@ -35,41 +32,21 @@ def parse_style_props(path: Path) -> dict[int, str]:
|
||||
current_val = 0
|
||||
for line in m.group(1).splitlines():
|
||||
line = line.strip().rstrip(",")
|
||||
if (
|
||||
not line
|
||||
or line.startswith("/*")
|
||||
or line.startswith("//")
|
||||
or line.startswith("*")
|
||||
):
|
||||
if not line or line.startswith(("/*", "//", "*")):
|
||||
continue
|
||||
|
||||
# Match: LV_STYLE_XXX = value or LV_STYLE_XXX (auto-increment)
|
||||
match = re.match(r"(LV_STYLE_\w+)\s*=\s*(0x[\da-fA-F]+|\d+)", line)
|
||||
if match:
|
||||
name = match.group(1)
|
||||
val_str = match.group(2)
|
||||
current_val = int(val_str, 0)
|
||||
name, current_val = match.group(1), int(match.group(2), 0)
|
||||
else:
|
||||
match = re.match(r"(LV_STYLE_\w+)", line)
|
||||
if not match:
|
||||
continue
|
||||
name = match.group(1)
|
||||
|
||||
# Skip meta entries
|
||||
if name in (
|
||||
"LV_STYLE_PROP_INV",
|
||||
"LV_STYLE_PROP_ANY",
|
||||
"LV_STYLE_PROP_CONST",
|
||||
"LV_STYLE_LAST_BUILT_IN_PROP",
|
||||
"LV_STYLE_NUM_BUILT_IN_PROPS",
|
||||
):
|
||||
if name in SKIP_PROPS:
|
||||
current_val += 1
|
||||
continue
|
||||
|
||||
short = name.removeprefix("LV_STYLE_")
|
||||
props[current_val] = short
|
||||
props[current_val] = name.removeprefix("LV_STYLE_")
|
||||
current_val += 1
|
||||
|
||||
return props
|
||||
|
||||
|
||||
@@ -79,18 +56,13 @@ def parse_parts(path: Path) -> dict[int, str]:
|
||||
m = re.search(r"typedef\s+enum\s*\{(.*?)\}\s*lv_part_t", text, re.DOTALL)
|
||||
if not m:
|
||||
raise RuntimeError("Cannot find lv_part_t enum")
|
||||
|
||||
parts = {}
|
||||
for line in m.group(1).splitlines():
|
||||
match = re.match(r"\s*(LV_PART_\w+)\s*=\s*(0x[\da-fA-F]+|\d+)", line)
|
||||
if not match:
|
||||
continue
|
||||
name = match.group(1)
|
||||
val = int(match.group(2), 0)
|
||||
short = name.removeprefix("LV_PART_")
|
||||
# Selector uses bits [23:16], shift down to get the key
|
||||
parts[val >> 16] = short
|
||||
|
||||
parts[val >> 16] = match.group(1).removeprefix("LV_PART_")
|
||||
return parts
|
||||
|
||||
|
||||
@@ -112,25 +84,17 @@ def parse_states(path: Path) -> dict[int, str]:
|
||||
m = re.search(r"typedef\s+enum\s*\{(.*?)\}\s*lv_state_t", text, re.DOTALL)
|
||||
if not m:
|
||||
raise RuntimeError("Cannot find lv_state_t enum")
|
||||
|
||||
states = {}
|
||||
for line in m.group(1).splitlines():
|
||||
match = re.match(r"\s*(LV_STATE_\w+)\s*=\s*(.+?)(?:,|/)", line)
|
||||
if not match:
|
||||
continue
|
||||
name = match.group(1)
|
||||
expr = match.group(2).strip()
|
||||
|
||||
# Skip DEFAULT (0) and ANY (0xFFFF)
|
||||
if name in ("LV_STATE_DEFAULT", "LV_STATE_ANY"):
|
||||
continue
|
||||
|
||||
val = _parse_int_expr(expr)
|
||||
if val is None:
|
||||
continue
|
||||
short = name.removeprefix("LV_STATE_")
|
||||
states[val] = short
|
||||
|
||||
val = _parse_int_expr(match.group(2))
|
||||
if val is not None:
|
||||
states[val] = name.removeprefix("LV_STATE_")
|
||||
return states
|
||||
|
||||
|
||||
@@ -138,7 +102,6 @@ def parse_color_props(style_gen_h: Path, prop_map: dict[int, str]) -> set[int]:
|
||||
"""Identify color properties from lv_style_gen.h setter signatures."""
|
||||
text = style_gen_h.read_text()
|
||||
name_to_id = {v: k for k, v in prop_map.items()}
|
||||
|
||||
color_ids = set()
|
||||
for match in re.finditer(
|
||||
r"void\s+lv_style_set_(\w+)\s*\([^,]+,\s*lv_color_t", text
|
||||
@@ -146,7 +109,6 @@ def parse_color_props(style_gen_h: Path, prop_map: dict[int, str]) -> set[int]:
|
||||
prop_name = match.group(1).upper()
|
||||
if prop_name in name_to_id:
|
||||
color_ids.add(name_to_id[prop_name])
|
||||
|
||||
return color_ids
|
||||
|
||||
|
||||
@@ -154,7 +116,6 @@ def parse_pointer_props(style_gen_h: Path, prop_map: dict[int, str]) -> set[int]
|
||||
"""Identify pointer properties from lv_style_gen.h setter signatures."""
|
||||
text = style_gen_h.read_text()
|
||||
name_to_id = {v: k for k, v in prop_map.items()}
|
||||
|
||||
ptr_ids = set()
|
||||
for match in re.finditer(
|
||||
r"void\s+lv_style_set_(\w+)\s*\([^,]+,\s*(?:const\s+)?(?:void|lv_\w+)\s*\*",
|
||||
@@ -163,50 +124,38 @@ def parse_pointer_props(style_gen_h: Path, prop_map: dict[int, str]) -> set[int]
|
||||
prop_name = match.group(1).upper()
|
||||
if prop_name in name_to_id:
|
||||
ptr_ids.add(name_to_id[prop_name])
|
||||
|
||||
return ptr_ids
|
||||
|
||||
|
||||
def generate(
|
||||
props: dict[int, str],
|
||||
parts: dict[int, str],
|
||||
states: dict[int, str],
|
||||
color_ids: set[int],
|
||||
pointer_ids: set[int],
|
||||
) -> str:
|
||||
"""Generate Python source for the constants module."""
|
||||
def generate(props, parts, states, color_ids, pointer_ids) -> str:
|
||||
"""Generate Python source for the style constants module."""
|
||||
lines = [
|
||||
'"""',
|
||||
"Auto-generated style constants from LVGL headers.",
|
||||
"",
|
||||
"Do not edit manually. Regenerate with:",
|
||||
" python3 scripts/gen_style_consts.py",
|
||||
"Do not edit manually. Regenerate from the GDB script root with:",
|
||||
" python3 scripts/generate_all.py",
|
||||
'"""',
|
||||
"",
|
||||
]
|
||||
|
||||
# STYLE_PROP_NAMES
|
||||
lines.append("STYLE_PROP_NAMES = {")
|
||||
for k in sorted(props):
|
||||
lines.append(f' {k}: "{props[k]}",')
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
# PART_NAMES
|
||||
lines.append("PART_NAMES = {")
|
||||
for k in sorted(parts):
|
||||
lines.append(f' 0x{k:02X}: "{parts[k]}",')
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
# STATE_FLAGS
|
||||
lines.append("STATE_FLAGS = {")
|
||||
for k in sorted(states):
|
||||
lines.append(f' 0x{k:04X}: "{states[k]}",')
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
# COLOR_PROPS
|
||||
if color_ids:
|
||||
lines.append("COLOR_PROPS = {")
|
||||
for v in sorted(color_ids):
|
||||
@@ -216,7 +165,6 @@ def generate(
|
||||
lines.append("COLOR_PROPS = set()")
|
||||
lines.append("")
|
||||
|
||||
# POINTER_PROPS
|
||||
if pointer_ids:
|
||||
lines.append("POINTER_PROPS = {")
|
||||
for v in sorted(pointer_ids):
|
||||
@@ -239,7 +187,7 @@ def main():
|
||||
src = generate(props, parts, states, color_ids, pointer_ids)
|
||||
OUTPUT.write_text(src)
|
||||
print(
|
||||
f"Generated {OUTPUT} ({len(props)} props, {len(parts)} parts, "
|
||||
f"Generated {OUTPUT.name} ({len(props)} props, {len(parts)} parts, "
|
||||
f"{len(states)} states, {len(color_ids)} color, {len(pointer_ids)} pointer)"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate subject type constant table from LVGL headers."""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||
from enum_parser import parse_enum, generate_dict_module
|
||||
|
||||
LVGL_SRC = Path(__file__).parent.parent.parent.parent.parent / "src"
|
||||
OUTPUT = Path(__file__).parent.parent.parent / "lvglgdb" / "lvgl" / "core" / "lv_observer_consts.py"
|
||||
|
||||
|
||||
def main():
|
||||
subject_types = parse_enum(
|
||||
LVGL_SRC / "core" / "lv_observer.h",
|
||||
"lv_subject_type_t",
|
||||
"LV_SUBJECT_TYPE_",
|
||||
)
|
||||
src = generate_dict_module(
|
||||
"observer constants from LVGL headers",
|
||||
{"SUBJECT_TYPE_NAMES": subject_types},
|
||||
)
|
||||
OUTPUT.write_text(src)
|
||||
print(f"Generated {OUTPUT.name} ({len(subject_types)} subject types)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user