Hash :
238d1324
Author :
Date :
2023-09-29T11:33:28
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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
#!/usr/bin/env python3
from __future__ import print_function
import re
import os
from pathlib import Path
# Expected format:
# #define XF86XK_FooBar 0x1234 /* some optional comment */
# or:
# #define XF86XK_FooBar _EVDEVK(0x123) /* some optional comment */
# We also need to match commented evdev entries:
# /* Use: XF86XK_FooBar _EVDEVK(0x123) some optional comment */
keysym_entry_pattern = re.compile(
r"""^
(?P<define>\#define|/\*\s+Use:)\s+
(?P<prefix>\w*)XK_(?P<name>\w+)(?P<spacing>\s+)
(?P<evdev>_EVDEVK\()?(?P<value>0x[0-9A-Fa-f]+)(?(evdev)\))
""",
re.VERBOSE,
)
# Match keysym guarded by #ifndef
keysym_ifndef_pattern = re.compile(r"^#ifndef\s+(?P<prefix>\w*)XK_(?P<name>\w+)\s*$")
# Match remaining XK_ references in the comments, e.g we will replace:
# XF86XK_CamelCaseKernelName _EVDEVK(kernel value)
# #define XKB_KEY_SunCompose 0x0000FF20 /* Same as XK_Multi_key */
# with:
# XKB_KEY_XF86CamelCaseKernelName _EVDEVK(kernel value)
# #define XKB_KEY_SunCompose 0x0000FF20 /* Same as XKB_KEY_Multi_key */
xorgproto_keysym_prefix_pattern = re.compile(r"\b(?P<prefix>\w*)XK_(?!KOREAN\b)")
def make_keysym_name(m: re.Match[str]) -> str:
return m.group("prefix") + m.group("name")
def make_keysym_entry(m: re.Match[str]) -> str:
"""
Perform the substitutions
"""
if m.group("evdev"):
if m.group("define").startswith("#"):
# Replace the xorgproto _EVDEVK macro with the actual value:
# 0x10081000 is the base, the evdev hex code is added to that.
# We replace to make parsing of the keys later easier.
value = 0x10081000 + int(m.group("value"), 16)
value_str = f"{value:#x} "
else:
value_str = f"""_EVDEVK({m.group('value')})"""
else:
value_str = m.group("value")
define = m.group("define")
prefix = m.group("prefix") or ""
name = m.group("name")
spacing = m.group("spacing")
return f"""{define} XKB_KEY_{prefix}{name}{spacing}{value_str}"""
prefix = Path(os.environ.get("X11_HEADERS_PREFIX", "/usr"))
HEADERS = (
prefix / "include/X11/keysymdef.h",
prefix / "include/X11/XF86keysym.h",
prefix / "include/X11/Sunkeysym.h",
prefix / "include/X11/DECkeysym.h",
prefix / "include/X11/HPkeysym.h",
)
print(
"""#ifndef _XKBCOMMON_KEYSYMS_H
#define _XKBCOMMON_KEYSYMS_H
/* This file is autogenerated; please do not commit directly. */
/**
* @file
* Key symbols (keysyms) definitions.
*/
#define XKB_KEY_NoSymbol 0x000000 /* Special KeySym */
"""
)
keysyms: set[str] = set()
for path in HEADERS:
pending_guarded_keysym: str | None = None
with path.open("rt", encoding="utf-8") as header:
for line in header:
# Duplicate keysym name guard
if m := keysym_ifndef_pattern.match(line):
if pending_guarded_keysym:
raise ValueError(f"Nested #ifndef {pending_guarded_keysym}")
pending_guarded_keysym = make_keysym_name(m)
continue
# Ignore C macro #ifdef/#ifndef
elif line.startswith("#ifdef") or line.startswith("#ifndef"):
if pending_guarded_keysym:
raise ValueError(f"Nested C macro {pending_guarded_keysym}")
continue
# Ignore C macro #endif and check end of keysym name guard
elif line.startswith("#endif"):
if pending_guarded_keysym:
pending_guarded_keysym = None
continue
# Remove #define _OSF_Keysyms and such.
elif line.startswith("#define _"):
continue
# Keysym entry: proceed various tests
if line.startswith("#") and (m := keysym_entry_pattern.match(line)):
name = make_keysym_name(m)
# Check expected guarded keysym, if relevant
if pending_guarded_keysym and name != pending_guarded_keysym:
raise ValueError(f"{path}: Malformed keysym name guard: {line}")
# Check if name already defined
elif name in keysyms:
if pending_guarded_keysym:
# Ignore guarded keysym
continue
else:
raise ValueError(f"{path}: Unguarded redefinition: {line}")
else:
keysyms.add(name)
# Perform _EVDEV and XK_ substitutions
line = keysym_entry_pattern.sub(make_keysym_entry, line)
line = xorgproto_keysym_prefix_pattern.sub(r"XKB_KEY_\1", line)
print(line, end="")
print("\n\n#endif")