xref: /aosp_15_r20/external/libxkbcommon/scripts/makekeys (revision 2b949d0487e80d67f1fda82db69e101e761f8064)
1*2b949d04SAndroid Build Coastguard Worker#!/usr/bin/env python
2*2b949d04SAndroid Build Coastguard Worker
3*2b949d04SAndroid Build Coastguard Workerimport re, sys, itertools
4*2b949d04SAndroid Build Coastguard Worker
5*2b949d04SAndroid Build Coastguard Workerimport perfect_hash
6*2b949d04SAndroid Build Coastguard Worker
7*2b949d04SAndroid Build Coastguard Workerpattern = re.compile(r'^#define\s+XKB_KEY_(?P<name>\w+)\s+(?P<value>0x[0-9a-fA-F]+)\s')
8*2b949d04SAndroid Build Coastguard Workermatches = [pattern.match(line) for line in open(sys.argv[1])]
9*2b949d04SAndroid Build Coastguard Workerentries = [(m.group("name"), int(m.group("value"), 16)) for m in matches if m]
10*2b949d04SAndroid Build Coastguard Worker
11*2b949d04SAndroid Build Coastguard Workerentries_isorted = sorted(entries, key=lambda e: e[0].lower())
12*2b949d04SAndroid Build Coastguard Workerentries_kssorted = sorted(entries, key=lambda e: e[1])
13*2b949d04SAndroid Build Coastguard Worker
14*2b949d04SAndroid Build Coastguard Workerprint('''
15*2b949d04SAndroid Build Coastguard Worker/**
16*2b949d04SAndroid Build Coastguard Worker * This file comes from libxkbcommon and was generated by makekeys.py
17*2b949d04SAndroid Build Coastguard Worker * You can always fetch the latest version from:
18*2b949d04SAndroid Build Coastguard Worker * https://raw.github.com/xkbcommon/libxkbcommon/master/src/ks_tables.h
19*2b949d04SAndroid Build Coastguard Worker */
20*2b949d04SAndroid Build Coastguard Worker''')
21*2b949d04SAndroid Build Coastguard Worker
22*2b949d04SAndroid Build Coastguard Workerentry_offsets = {}
23*2b949d04SAndroid Build Coastguard Worker
24*2b949d04SAndroid Build Coastguard Workerprint('''
25*2b949d04SAndroid Build Coastguard Worker#ifdef __GNUC__
26*2b949d04SAndroid Build Coastguard Worker#pragma GCC diagnostic push
27*2b949d04SAndroid Build Coastguard Worker#pragma GCC diagnostic ignored "-Woverlength-strings"
28*2b949d04SAndroid Build Coastguard Worker#endif
29*2b949d04SAndroid Build Coastguard Workerstatic const char *keysym_names =
30*2b949d04SAndroid Build Coastguard Worker'''.strip())
31*2b949d04SAndroid Build Coastguard Workeroffs = 0
32*2b949d04SAndroid Build Coastguard Workerfor (name, _) in entries_isorted:
33*2b949d04SAndroid Build Coastguard Worker    entry_offsets[name] = offs
34*2b949d04SAndroid Build Coastguard Worker    print('    "{name}\\0"'.format(name=name))
35*2b949d04SAndroid Build Coastguard Worker    offs += len(name) + 1
36*2b949d04SAndroid Build Coastguard Workerprint('''
37*2b949d04SAndroid Build Coastguard Worker;
38*2b949d04SAndroid Build Coastguard Worker#ifdef __GNUC__
39*2b949d04SAndroid Build Coastguard Worker#pragma GCC diagnostic pop
40*2b949d04SAndroid Build Coastguard Worker#endif
41*2b949d04SAndroid Build Coastguard Worker'''.strip())
42*2b949d04SAndroid Build Coastguard Worker
43*2b949d04SAndroid Build Coastguard Worker
44*2b949d04SAndroid Build Coastguard Workertemplate = r'''
45*2b949d04SAndroid Build Coastguard Workerstatic const uint16_t keysym_name_G[] = {
46*2b949d04SAndroid Build Coastguard Worker    $G
47*2b949d04SAndroid Build Coastguard Worker};
48*2b949d04SAndroid Build Coastguard Worker
49*2b949d04SAndroid Build Coastguard Workerstatic size_t
50*2b949d04SAndroid Build Coastguard Workerkeysym_name_hash_f(const char *key, const char *T)
51*2b949d04SAndroid Build Coastguard Worker{
52*2b949d04SAndroid Build Coastguard Worker    size_t sum = 0;
53*2b949d04SAndroid Build Coastguard Worker    for (size_t i = 0; key[i] != '\0'; i++)
54*2b949d04SAndroid Build Coastguard Worker        sum += T[i % $NS] * key[i];
55*2b949d04SAndroid Build Coastguard Worker    return sum % $NG;
56*2b949d04SAndroid Build Coastguard Worker}
57*2b949d04SAndroid Build Coastguard Worker
58*2b949d04SAndroid Build Coastguard Workerstatic size_t
59*2b949d04SAndroid Build Coastguard Workerkeysym_name_perfect_hash(const char *key)
60*2b949d04SAndroid Build Coastguard Worker{
61*2b949d04SAndroid Build Coastguard Worker    return (
62*2b949d04SAndroid Build Coastguard Worker        keysym_name_G[keysym_name_hash_f(key, "$S1")] +
63*2b949d04SAndroid Build Coastguard Worker        keysym_name_G[keysym_name_hash_f(key, "$S2")]
64*2b949d04SAndroid Build Coastguard Worker    ) % $NG;
65*2b949d04SAndroid Build Coastguard Worker}
66*2b949d04SAndroid Build Coastguard Worker'''
67*2b949d04SAndroid Build Coastguard Workerprint(perfect_hash.generate_code(
68*2b949d04SAndroid Build Coastguard Worker    keys=[name for name, value in entries_isorted],
69*2b949d04SAndroid Build Coastguard Worker    template=template,
70*2b949d04SAndroid Build Coastguard Worker))
71*2b949d04SAndroid Build Coastguard Worker
72*2b949d04SAndroid Build Coastguard Workerprint('''
73*2b949d04SAndroid Build Coastguard Workerstruct name_keysym {
74*2b949d04SAndroid Build Coastguard Worker    xkb_keysym_t keysym;
75*2b949d04SAndroid Build Coastguard Worker    uint32_t offset;
76*2b949d04SAndroid Build Coastguard Worker};\n''')
77*2b949d04SAndroid Build Coastguard Worker
78*2b949d04SAndroid Build Coastguard Workerdef print_entries(x):
79*2b949d04SAndroid Build Coastguard Worker    for (name, value) in x:
80*2b949d04SAndroid Build Coastguard Worker        print('    {{ 0x{value:08x}, {offs} }}, /* {name} */'.format(offs=entry_offsets[name], value=value, name=name))
81*2b949d04SAndroid Build Coastguard Worker
82*2b949d04SAndroid Build Coastguard Workerprint('static const struct name_keysym name_to_keysym[] = {')
83*2b949d04SAndroid Build Coastguard Workerprint_entries(entries_isorted)
84*2b949d04SAndroid Build Coastguard Workerprint('};\n')
85*2b949d04SAndroid Build Coastguard Worker
86*2b949d04SAndroid Build Coastguard Worker# *.sort() is stable so we always get the first keysym for duplicate
87*2b949d04SAndroid Build Coastguard Workerprint('static const struct name_keysym keysym_to_name[] = {')
88*2b949d04SAndroid Build Coastguard Workerprint_entries(next(g[1]) for g in itertools.groupby(entries_kssorted, key=lambda e: e[1]))
89*2b949d04SAndroid Build Coastguard Workerprint('};')
90