""" Generate a Python extension module with the constants defined in linux/input.h. """ import getopt import os import re import sys # ----------------------------------------------------------------------------- # The default header file locations to try. headers = [ "/usr/include/linux/input.h", "/usr/include/linux/input-event-codes.h", "/usr/include/linux/uinput.h", ] opts, args = getopt.getopt(sys.argv[1:], "", ["ecodes", "stubs", "reproducible"]) if not opts: print("usage: genecodes.py [--ecodes|--stubs] [--reproducible] ") exit(2) if args: headers = args reproducible = ("--reproducible", "") in opts # ----------------------------------------------------------------------------- macro_regex = r"#define\s+((?:KEY|ABS|REL|SW|MSC|LED|BTN|REP|SND|ID|EV|BUS|SYN|FF|UI_FF|INPUT_PROP)_\w+)" macro_regex = re.compile(macro_regex) if reproducible: uname = "hidden for reproducibility" else: # Uname without hostname. uname = list(os.uname()) uname = " ".join((uname[0], *uname[2:])) # ----------------------------------------------------------------------------- template_ecodes = r""" #include #ifdef __FreeBSD__ #include #include #else #include #include #endif /* Automatically generated by evdev.genecodes */ /* Generated on %s */ /* Generated from %s */ #define MODULE_NAME "_ecodes" #define MODULE_HELP "linux/input.h macros" static PyMethodDef MethodTable[] = { { NULL, NULL, 0, NULL} }; static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, MODULE_NAME, MODULE_HELP, -1, /* m_size */ MethodTable, /* m_methods */ NULL, /* m_reload */ NULL, /* m_traverse */ NULL, /* m_clear */ NULL, /* m_free */ }; PyMODINIT_FUNC PyInit__ecodes(void) { PyObject* m = PyModule_Create(&moduledef); if (m == NULL) return NULL; %s return m; } """ template_stubs = r""" # Automatically generated by evdev.genecodes # Generated on %s # Generated from %s # pylint: skip-file ecodes: dict[str, int] keys: dict[int, str|list[str]] bytype: dict[int, dict[int, str|list[str]]] KEY: dict[int, str|list[str]] ABS: dict[int, str|list[str]] REL: dict[int, str|list[str]] SW: dict[int, str|list[str]] MSC: dict[int, str|list[str]] LED: dict[int, str|list[str]] BTN: dict[int, str|list[str]] REP: dict[int, str|list[str]] SND: dict[int, str|list[str]] ID: dict[int, str|list[str]] EV: dict[int, str|list[str]] BUS: dict[int, str|list[str]] SYN: dict[int, str|list[str]] FF_STATUS: dict[int, str|list[str]] FF_INPUT_PROP: dict[int, str|list[str]] %s """ def parse_headers(headers=headers): for header in headers: try: fh = open(header) except (IOError, OSError): continue for line in fh: macro = macro_regex.search(line) if macro: yield macro.group(1) all_macros = list(parse_headers()) if not all_macros: print("no input macros found in: %s" % " ".join(headers), file=sys.stderr) sys.exit(1) # pylint: disable=possibly-used-before-assignment, used-before-assignment if ("--ecodes", "") in opts: body = (" PyModule_AddIntMacro(m, %s);" % macro for macro in all_macros) template = template_ecodes elif ("--stubs", "") in opts: body = ("%s: int" % macro for macro in all_macros) template = template_stubs body = os.linesep.join(body) text = template % (uname, headers if not reproducible else ["hidden for reproducibility"], body) print(text.strip())